/*
Copyright 2006 by Daniel Kuebrich
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.app.lightcycles;
import sim.util.*;
import sim.engine.*;
// The cycle itself... A steppable which either proceeds while being manipulated by
// user input or directed by a very minimal AI.
public class Cycle implements Steppable
{
private static final long serialVersionUID = 1;
// Properties
public int dir, my_id;
boolean alive;
boolean cpu;
// Stop stepping the cycle when it dies
Stoppable stopper;
// accessors for inspectors - direction
public int getdir() { return dir; }
public void setdir(int ndir) { dir = ndir; }
// accessors for inspectors - id
public int getmy_id() { return my_id; }
public void setmy_id(int nid) { my_id = nid; }
// accessors for inspectors - alive?
public boolean getalive() { return alive; }
public void setalive(boolean nalive) { alive = nalive; }
// accessors for inspectors - player control - cpu
public boolean getcpu() { return cpu; }
public void setcpu(boolean ncpu) { cpu = ncpu; }
public Cycle(int id, int ndir)
{
my_id = id;
dir = ndir;
alive = true;
cpu = true;
}
public void step( final SimState state )
{
// if this cycle has crashed,
// stop rescheduling this cycle's step function
if(!alive)
{
if(stopper!=null) stopper.stop();
return;
}
LightCycles lc = (LightCycles)state;
int dirs[] = new int[5];
int i=0, n=0;
Int2D location = lc.cycleGrid.getObjectLocation(this); // find x and y
int x = location.x;
int y = location.y;
// if cpu controlled, use ai for direction change action
if(cpu)
{
// cycle through directions and find direction with longest open path in any one direction -- (simplistic, no?)
for(i = 1; i<5; i++)
{
// make sure direction is even vaguely viable (eg not on edge of grid)
if( (i == 1 && y == 0) ||
(i == 2 && y == lc.gridHeight-1) ||
(i == 3 && x == 0) ||
(i == 4 && x == lc.gridWidth-1) )
continue;
n=1;
switch(i)
{
case 1:
while(lc.grid.field[x][y-n] == 0 && y-(n+1) > 0)
n++;
break;
case 2:
while(lc.grid.field[x][y+n] == 0 && y+(n+1) < lc.gridHeight)
n++;
break;
case 3:
while(lc.grid.field[x-n][y] == 0 && x-(n+1) > 0)
n++;
break;
case 4:
while(lc.grid.field[x+n][y] == 0 && x+(n+1) < lc.gridWidth)
n++;
break;
}
dirs[i] = n;
}
int bestDir = 0;
int maxN = 0;
// pick best direction (longest path)
for(i = 1; i<5; i++)
{
if(dirs[i] > maxN || (dirs[i]==maxN && state.random.nextBoolean()))
{
maxN = dirs[i];
bestDir = i;
}
}
if(maxN == 1)
alive = false;
dir = bestDir;
}
// if player or cpu, no matter, still moves
if(dir == 1) // up
y -= 1;
if(dir == 2) // down
y += 1;
if(dir == 3) // left
x -= 1;
if(dir == 4) // right
x += 1;
// see if going off edge
if(x < 0 || x >= lc.gridWidth || y < 0 || y >= lc.gridHeight)
alive = false;
else
{
// see if crashing
if(lc.grid.field[x][y] != 0)
alive = false;
else // else you're good
{
lc.cycleGrid.setObjectLocation(this,x,y);
lc.grid.field[x][y] = my_id;
}
}
} // end Step
} // end class Cycle