import java.awt.*;
import java.util.Random;
/**
@author Heinze, Pausch, Robl
@version 1.0
*/
public class Microbe
{
/** current energy value of this microbe */
private int energy;
/** energyloss per step */
private int energyloss;
/** local reference to the playfield where this microbe "lives" */
private PlayField playfield;
/** old movement direction of this microbe */
private int olddir;
/** x- and y-position of the microbe */
private int xp, yp;
/** current movement direction for this microbe */
private int dx, dy;
/** the microbe's brain: the food-energy-storage */
private int colorscore[]=new int[16];
/** random generator for all random calculations needed for the microbe */
private Random rnd=new Random();
/**
* calculates a positive random value in the rango of 0 to n-1
* @param n upper limit for calculation
*/
private int random(int n)
{
if (n<=0)
return 0;
int r=rnd.nextInt();
if (r<0) r*=-1;
return r%n;
}
/**
* helpermethod - calculates dx and dy from dir
* @param dir direction number
*/
private void direction(int dir)
{
int x, y;
for(y=-1; y<2; y++)
{
for(x=-1; x<2; x++)
{
if (x!=0 || y!=0)
{
if (dir==0)
{
dx=x;
dy=y;
return;
}
dir--;
}
}
}
}
/**
* creates a new microbe
* @param pf playfield where this microbe "lives"
* @param x x startposition
* @param y y startposition
* @param start_energy startenergy
* @param start_energyloss energy loss per step
*/
public Microbe(PlayField pf, int x, int y, int start_energy, int start_energyloss)
{
rnd.setSeed(rnd.nextInt()+(y*1234)+(x*9876)+(x*y)); // init the random generator (seed) by the current time and the microbes position
playfield=pf;
olddir=random(8);
direction(olddir);
for(int i=0; i<16; i++)
colorscore[i]=0;
Food f=new Food(Food.TYPE_BORDER);
colorscore[f.gettype()]=f.getenergy(); // microbe *must* know: border is *immediate* death!!
energy=start_energy;
energyloss=start_energyloss;
xp=x;
yp=y;
}
/**
* returns the current energy level of this microbe
* @return energy level
*/
public int getenergy()
{
return energy;
}
/**
* sets the energy level to a new value
* @param new_energy new energy level
*/
public void setenergy(int new_energy)
{
energy=new_energy;
}
/**
* returns the energy loss per step
* @return energy loss per step
*/
public int getenergyloss()
{
return energyloss;
}
/**
* sets the energy loss per step to a new value
* @param new_energyloss energyloss per step
*/
public void setenergyloss(int new_energyloss)
{
energyloss=new_energyloss;
}
/**
* returns the current x position of the microbe
* @return x position
*/
public int getx()
{
return xp;
}
/**
* returns the current y position of the microbe
* @return y position
*/
public int gety()
{
return yp;
}
/**
* calculates one microbe-step
* the microbe analyzes the surrounding food and runs into the direction which has the
* best energy value; the microbe learns new energy values and divides into two microbes
* if it reaches the energy limit of 1000 (each microbe gets the half of the old microbe energy)
* @return true: microbe is alive / false: microbe is dead
*/
boolean step()
{
int i, x, y;
int m=colorscore[playfield.getfoodtype(xp+dx, yp+dy)];
int wa[]=new int[9], wz=0;
boolean ex=false;
// evaluate the surrounding pixels, search for the best energy value and store it to m
for(y=-1; y<2; y++)
for(x=-1; x<2; x++)
if (x!=0 || y!=0)
{
i=colorscore[playfield.playfield[xp+x][yp+y].gettype()];
if (i>m) m=i;
}
// store all direction with the same value as m in the direction-storage wa
for(i=0, y=-1; y<2; y++)
for(x=-1; x<2; x++)
if (x!=0 || y!=0)
{
if (colorscore[playfield.playfield[xp+x][yp+y].gettype()]==m)
wa[wz++]=i;
i++;
}
// If the food in the direction of the old movement direction has also the best energy value,
// the microbe shall go on in the old direction; now and then, a new movement direction
// will be selected by random
if (colorscore[playfield.playfield[xp+dx][yp+dy].gettype()]==m && wz>1)
{
for(i=0; i0 && !ex)
direction(wa[random(wz)]);
xp+=dx; yp+=dy; // apply the movement direction to the microbe's position
i=playfield.playfield[xp][yp].gettype(); // get the food type on the new position
colorscore[i]=playfield.playfield[xp][yp].getenergy(); // and store in the "brain" the energy value
energy+=colorscore[i]-energyloss; // the food energy value influences the microbe's energy value (+ energy loss per step!)
playfield.playfield[xp][yp].clear(); // the food gets "eaten"
if (energy>=1000)
{ // the microbe divides into two microbes if it reaches the energy limit of 1000
energy/=2;
playfield.new_microbe(xp, yp, energy, energyloss);
return true; // microbe is still alive
}
else if (energy>0)
{
return true; // microbe is still alive
}
return false; // microbe is dead
}
/**
* returns the "color" of this microbe, the "color" depends on its current energy level
* @return "color" value in the range from 0 to 255
*/
public int getcolor()
{
int col=(energy*255)/1000;
if (col<0) col=0;
if (col>255) col=255;
return col;
}
}