--- /dev/null
+/**
+ ** A path finder implementation that uses the AStar heuristic based algorithm
+ ** to determine a path.
+ ** New changes for our purposes
+ **/
+public class AStarPathFinder {
+
+ /** The set of nodes that have been searched through */
+ private Vector closed;
+
+ /** The set of nodes that we do not yet consider fully searched */
+ private SortedList open;
+
+ /** The map being searched */
+ global GameMap[][] land;
+
+ /** The maximum depth of search we're willing to accept before giving up */
+ private int maxSearchDistance;
+
+ /** The complete set of nodes across the map */
+ private Node[][] nodes;
+
+ /** True if we allow diagonal movement */
+ private boolean allowDiagMovement;
+
+ /** Map size where we are searching */
+ private int rows, columns;
+
+ /**
+ ** Create a path finder with the default heuristic - closest to target.
+ **
+ ** @param land The map to be searched
+ ** @param maxSearchDistance The maximum depth we'll search before giving up
+ ** @param allowDiagMovement True if the search should try diagonal movement
+ **/
+ public AStarPathFinder(GameMap[][] land, int maxSearchDistance, boolean allowDiagMovement, int rows, int columns) {
+ this.land = land;
+ this.maxSearchDistance = maxSearchDistance;
+ this.allowDiagMovement = allowDiagMovement;
+ closed = new Vector();
+ open = new SortedList();
+
+ nodes = new Node[rows][columns];
+ for (int x=0;x<rows;x++) {
+ for (int y=0;y<columns;y++) {
+ nodes[x][y] = new Node(x,y);
+ }
+ }
+ this.rows = rows;
+ this.columns = columns;
+ }
+
+ /**
+ ** A description of an implementation that can find a path from one
+ ** location on a tile map to another based on information provided
+ ** by that tile map.
+ **
+ ** Find a path from the starting location to the target
+ ** location avoiding blockages and attempting to honour costs
+ ** provided by the land.
+ **
+ ** @return The path found from start to end, or null if no path can be found.
+ **/
+
+ public Path findPath(Player gamer) {
+ int tx = gamer.getGoalX();
+ int ty = gamer.getGoalY();
+ int sx = gamer.getX();
+ int sy = gamer.getY();
+
+ int type = gamer.kind();
+
+ // easy first check, if the destination is blocked, we can't get there
+
+ if(type == 1) { //1 => PLANTER
+ if(land[tx][ty].hasTree() || land[tx][ty].hasRock()) {
+ return null;
+ }
+ } else { //LUMBERJACK
+ if((!land[tx][ty].hasTree()) || land[tx][ty].hasRock()) {
+ return null;
+ }
+ }
+
+ // initial state for A*. The closed group is empty. Only the starting
+ // tile is in the open list
+ nodes[sx][sy].cost = 0;
+ nodes[sx][sy].depth = 0;
+ closed.clear();
+ open.clear();
+ open.add(nodes[sx][sy]);
+
+ nodes[tx][ty].parent = null;
+
+ // while we haven't exceeded our max search depth
+ int maxDepth = 0;
+ while ((maxDepth < maxSearchDistance) && (open.size() != 0)) {
+ // pull out the first node in our open list, this is determined to
+ // be the most likely to be the next step based on our heuristic
+
+ Node current = getFirstInOpen();
+
+ if (current == nodes[tx][ty]) {
+ break;
+ }
+
+ removeFromOpen(current);
+ addToClosed(current);
+
+ // search through all the neighbours of the current node evaluating
+ // them as next steps
+
+ for (int x=-1;x<2;x++) {
+ for (int y=-1;y<2;y++) {
+ // not a neighbour, its the current tile
+
+ if ((x == 0) && (y == 0)) {
+ continue;
+ }
+
+ // if we're not allowing diagonal movement then only
+ // one of x or y can be set
+
+ if (!allowDiagMovement) {
+ if ((x != 0) && (y != 0)) {
+ continue;
+ }
+ }
+
+ // determine the location of the neighbour and evaluate it
+
+ int xp = x + current.x;
+ int yp = y + current.y;
+
+ if (isValidLocation(gamer,sx,sy,xp,yp)) {
+ // the cost to get to this node is cost the current plus the movement
+ // cost to reach this node. Note that the heursitic value is only used
+ // in the sorted open list
+
+ int nextStepCost = current.cost + getMovementCost(current.x, current.y, xp, yp);
+ Node neighbour = nodes[xp][yp];
+
+ // if the new cost we've determined for this node is lower than
+ // it has been previously makes sure the node has
+ // determined that there might have been a better path to get to
+ // this node so it needs to be re-evaluated
+
+ if (nextStepCost < neighbour.cost) {
+ if (inOpenList(neighbour)) {
+ removeFromOpen(neighbour);
+ }
+ if (inClosedList(neighbour)) {
+ removeFromClosed(neighbour);
+ }
+ }
+
+ // if the node hasn't already been processed and discarded then
+ // reset it's cost to our current cost and add it as a next possible
+ // step (i.e. to the open list)
+ if (!inOpenList(neighbour) && !(inClosedList(neighbour))) {
+ neighbour.cost = nextStepCost;
+ neighbour.heuristic = getHeuristicCost(xp, yp, tx, ty);
+ maxDepth = Math.max(maxDepth, neighbour.setParent(current));
+ addToOpen(neighbour);
+ }
+ }
+ }
+ }
+ }
+
+ // since we'e've run out of search
+ // there was no path. Just return null
+ if (nodes[tx][ty].parent == null) {
+ return null;
+ }
+
+ // At this point we've definitely found a path so we can uses the parent
+ // references of the nodes to find out way from the target location back
+ // to the start recording the nodes on the way.
+
+ Path path = new Path();
+ Node target = nodes[tx][ty];
+ while (target != nodes[sx][sy]) {
+ path.prependStep(target.x, target.y);
+ target = target.parent;
+ }
+
+ // thats it, we have our path
+ return path;
+ }
+
+ /**
+ ** Check if a given location is valid for the supplied gamer
+ **
+ ** @param gamer The Player moving in the map
+ ** @param sx The starting x coordinate
+ ** @param sy The starting y coordinate
+ ** @param xp The x coordinate of the location to check
+ ** @param yp The y coordinate of the location to check
+ ** @return True if the location is valid for the given gamer
+ **/
+
+
+ public boolean isValidLocation(Player gamer, int sx, int sy, int xp, int yp) {
+ boolean invalid = (xp <= 0) || (yp <= 0) || (xp >= rows-1) || (yp >= columns-1);
+
+ if ((!invalid) && ((sx != xp) || (sy != yp))) {
+ if(gamer.kind() == 1) { //1=> PLANTER
+ if (land[xp][yp].hasTree() || land[xp][yp].hasRock()) {
+ invalid = true;
+ }
+ } else { //LUMBERJACK
+ if (land[xp][yp].hasRock()) {
+ invalid = true;
+ }
+ }
+ }
+ return !invalid;
+ }
+
+ /**
+ ** Get the first element from the open list. This is the next
+ ** one to be searched.
+ **
+ ** @return The first element in the open list
+ **/
+ protected Node getFirstInOpen() {
+ Node n = (Node) open.first();
+ return n;
+ }
+
+ /**
+ ** Remove a node from the open list
+ **
+ ** @param node The node to remove from the open list
+ **/
+ protected void removeFromOpen(Node node) {
+ open.remove(node);
+ }
+
+ /**
+ ** Add a node to the closed list
+ **
+ ** @param node The node to add to the closed list
+ **/
+ protected void addToClosed(Node node) {
+ closed.addElement(node);
+ }
+
+ /**
+ ** Remove a node from the closed list
+ **
+ ** @param node The node to remove from the closed list
+ **/
+ protected void removeFromClosed(Node node) {
+ closed.remove(node);
+ }
+
+ /**
+ ** Check if the node supplied is in the closed list
+ **
+ ** @param node The node to search for
+ ** @return True if the node specified is in the closed list
+ **/
+ protected boolean inClosedList(Node node) {
+ return closed.contains(node);
+ }
+
+ /**
+ ** Check if a node is in the open list
+ **
+ ** @param node The node to check for
+ ** @return True if the node given is in the open list
+ **/
+ protected boolean inOpenList(Node node) {
+ return open.contains(node);
+ }
+
+ /**
+ ** Add a node to the open list
+ **
+ ** @param node The node to be added to the open list
+ **/
+ protected void addToOpen(Node node) {
+ open.add(node);
+ }
+
+ /**
+ ** Get the cost to move through a given location
+ **
+ ** @param x The x coordinate of the tile whose cost is being determined
+ ** @param y The y coordiante of the tile whose cost is being determined
+ ** @param xp The x coordinate of the neighbor target location
+ ** @param yp The y coordinate of the neighbor target location
+ ** @return The cost of movement through the given tile
+ **/
+ public int getMovementCost(int x, int y, int xp, int yp) {
+ if (Math.abs(xp - x) == 1 && Math.abs(yp - y) == 1) {
+ return 14;
+ }
+ return 10;
+ }
+
+ /**
+ *
+ * Get the cost of moving through the given tile. This can be used to
+ ** make certain areas more desirable.
+ **
+ ** @param xp The x coordinate of the tile we're moving from
+ ** @param yp The y coordinate of the tile we're moving from
+ ** @param tx The x coordinate of the tile we're moving to
+ ** @param ty The y coordinate of the tile we're moving to
+ ** @return The relative cost of moving across the given tile
+ **/
+ public int getHeuristicCost(int xp, int yp, int tx, int ty) {
+ int heur = (Math.abs(tx - xp) + Math.abs(ty - yp)) * 10;
+ return heur;
+ }
+
+ /**
+ * Used only for debugging by printing the list element's
+ * x and y coordinates
+ **/
+
+ public void debugClosedList() {
+ for(int i=0; i<closed.size(); i++) {
+ Node n = (Node) closed.elementAt(i);
+ System.print("Element "+i+": n.getX()= "+n.getX()+" n.getY()= "+n.getY()+ "\n");
+ }
+ System.printString("\n");
+ }
+}
--- /dev/null
+public class BarrierServer extends Thread {
+ int numthreads;
+ boolean done;
+
+ public BarrierServer(int n) {
+ numthreads=n;
+ done=false;
+ }
+
+ public void run() {
+ int n;
+ ServerSocket ss=new ServerSocket(2000);
+ n=numthreads;
+ done=true;
+ Socket ar[]=new Socket[n];
+ for(int i=0; i<n; i++) {
+ ar[i]=ss.accept();
+ }
+
+ while(true) {
+ for(int j=0; j<n; j++) {
+ Socket s=ar[j];
+ byte b[]=new byte[1];
+ while(s.read(b)!=1) {
+ ;
+ }
+ }
+ byte b[]=new byte[1];
+ b[0]= (byte) 'A';
+ for(int j=0; j<n; j++)
+ ar[j].write(b);
+ }
+ }
+}
+
+public class Barrier {
+ Socket s;
+ public Barrier(String name) {
+ s=new Socket(name, 2000);
+ }
+
+ public static void enterBarrier(Barrier barr) {
+ byte b[]=new byte[1];
+ b[0]=(byte)'A';
+ barr.s.write(b);
+ while(barr.s.read(b)!=1) {
+ ;
+ }
+ }
+}
--- /dev/null
+/**
+ ** The main Map that is shared across machines
+ ** The description for the data we're pathfinding over. This provides the contract
+ ** between the data being searched (i.e. the in game map) and the path finding
+ ** generic tools
+ **/
+
+public class GameMap {
+ private TreeType tree;
+ private RockType rock;
+
+ public GameMap() {
+ tree = null;
+ rock = null;
+ }
+
+ public boolean hasTree() {
+ if (tree != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasRock() {
+ if (rock != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public void putTree(TreeType t) {
+ tree = t;
+ }
+
+ public void putRock(RockType r) {
+ rock = r;
+ }
+
+ public void cutTree() {
+ tree = null;
+ }
+
+ public boolean isEmpty() {
+ if (tree == null && rock == null) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ ** Only for Debugging by printing the map
+ ** Called after every round
+ **/
+ public void print() {
+ if (tree != null) {
+ System.print("T ");
+ return;
+ }
+ if (rock != null) {
+ System.print("o ");
+ return;
+ }
+ System.print(". ");
+ }
+}
--- /dev/null
+/**
+ ** Saves the X and Y coordinates of a single tile in a Map
+ **/
+
+public class Goal {
+ private int locX;
+ private int locY;
+
+ public Goal() {
+ locX = 0;
+ locY = 0;
+ }
+
+ public Goal(int x, int y) {
+ locX = x;
+ locY = y;
+ }
+
+ public void setXY(int x, int y) {
+ locX = x;
+ locY = y;
+ }
+
+ public int getX() {
+ return locX;
+ }
+
+ public int getY() {
+ return locY;
+ }
+}
--- /dev/null
+/**
+ ** A single node in the search graph
+ ** Has same dimensions as the Map where we are searching
+ **/
+private class Node {
+ /** The x coordinate of the node */
+ private int x;
+ /** The y coordinate of the node */
+ private int y;
+ /** The path cost for this node */
+ private int cost;
+ /** The parent of this node, how we reached it in the search */
+ private Node parent;
+ /** The heuristic cost of this node */
+ private int heuristic;
+ /** The search depth of this node */
+ private int depth;
+
+ /**
+ **Create a new node
+ **
+ ** @param x The x coordinate of the node
+ ** @param y The y coordinate of the node
+ **/
+ public Node(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ ** Set the parent of this node
+ **
+ ** @param parent The parent node which lead us to this node
+ ** @return The depth we have no reached in searching
+ **/
+ public int setParent(Node parent) {
+ depth = parent.depth + 1;
+ this.parent = parent;
+
+ return depth;
+ }
+
+ /**
+ ** compareTo(Object)
+ **/
+ public int compareTo(Object other) {
+ Node o = (Node) other;
+
+ int f = heuristic + cost;
+ int of = o.heuristic + o.cost;
+
+ if (f < of) {
+ return -1;
+ } else if (f > of) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ ** @return The cost of the heuristic
+ **/
+ public int getHeuristic() {
+ return heuristic;
+ }
+
+
+ /**
+ ** @return The actual cost of traversal
+ **/
+ public int getCost() {
+ return cost;
+ }
+
+ /**
+ ** Only for Debugging by printing contents of Node
+ **/
+ public void debugNode() {
+ System.println("x= "+ x + " y= "+ y + " cost= " + cost + " heuristic= "+ heuristic + " depth= " + depth);
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+}
+
+/**
+ ** A simple sorted list
+ **
+ **/
+class SortedList {
+ /** The list of elements */
+ private Vector list;
+
+ public SortedList() {
+ list = new Vector();
+ }
+ /**
+ ** Retrieve the first element from the list
+ **
+ ** @return The first element from the list
+ **/
+ public Object first() {
+ Object o = list.elementAt(0);
+ return o;
+ }
+
+ /**
+ ** Empty the list
+ **/
+ public void clear() {
+ list.clear();
+ }
+
+ /**
+ **Add an element to the list - causes sorting
+ **
+ ** @param o The element to add
+ **/
+ public void add(Object o) {
+ list.addElement(o);
+ Node tmp = (Node) o;
+ int min = tmp.heuristic + tmp.cost;
+ int i;
+ int index = 0;
+ /* Move the Node with minimum cost to the first position */
+ for(i = 0; i < list.size(); i++) {
+ if(min > totalCost(list.elementAt(i))) {
+ min = totalCost(list.elementAt(i));
+ index = i;
+ }
+ }
+
+ if(index < 0 || index >=list.size()) {
+ System.printString("Illegal SortedList.add\n");
+ System.exit(-1);
+ return;
+ }
+
+ Object temp = list.elementAt(0);
+ list.setElementAt(list.elementAt(index),0);
+ list.setElementAt(temp, index);
+ }
+
+ /**
+ **@return fixed cost + heuristic cost
+ **/
+ public int totalCost(Object o) {
+ Node tmp = (Node) o;
+ int cost = tmp.getHeuristic() + tmp.getCost();
+ return cost;
+ }
+
+
+ /**
+ ** Remove an element from the list
+ **
+ ** @param o The element to remove
+ **/
+ public void remove(Object o) {
+ list.remove(o);
+ }
+
+ /**
+ ** Get the number of elements in the list
+ **
+ ** @return The number of element in the list
+ **/
+ public int size() {
+ return list.size();
+ }
+
+ /**
+ ** Check if an element is in the list
+ **
+ ** @param o The element to search for
+ ** @return True if the element is in the list
+ **/
+ public boolean contains(Object o) {
+ return list.contains(o);
+ }
+
+ /**
+ ** Only for Debugging by printing contents of openlist
+ **/
+ public void debugOpenList() {
+ for(int i=0; i<list.size(); i++) {
+ Node n = (Node) list.elementAt(i);
+ System.print("Element "+i+": n.getX()= "+n.getX()+" n.getY()= "+n.getY()+ "\n");
+ }
+ System.printString("\n");
+ }
+}
--- /dev/null
+/**
+ ** A path determined by some path finding algorithm. A series of steps from
+ ** the starting location to the target location. This includes a step for the
+ ** initial location.
+ **
+ **/
+public class Path {
+ /** The list of steps building up this path */
+ private Vector steps;
+
+ /**
+ ** Create an empty path
+ **/
+ public Path() {
+ steps = new Vector();
+ }
+
+ /**
+ ** Get the length of the path, i.e. the number of steps
+ **
+ ** @return The number of steps in this path
+ **/
+ public int getLength() {
+ return steps.size();
+ }
+
+ /**
+ ** Get the step at a given index in the path
+ **
+ ** @param index The index of the step to retrieve. Note this should
+ ** be >= 0 and < getLength();
+ ** @return The step information, the position on the map.
+ **/
+ public Step getStep(int index) {
+ return (Step) steps.elementAt(index);
+ }
+
+ /**
+ ** Get the x coordinate for the step at the given index
+ **
+ ** @param index The index of the step whose x coordinate should be retrieved
+ ** @return The x coordinate at the step
+ **/
+ public int getX(int index) {
+ return getStep(index).x;
+ }
+
+ /**
+ ** Get the y coordinate for the step at the given index
+ **
+ ** @param index The index of the step whose y coordinate should be retrieved
+ ** @return The y coordinate at the step
+ **/
+ public int getY(int index) {
+ return getStep(index).y;
+ }
+
+ /**
+ ** Append a step to the path.
+ **
+ ** @param x The x coordinate of the new step
+ ** @param y The y coordinate of the new step
+ **/
+ public void appendStep(int x, int y) {
+ steps.addElement(new Step(x,y));
+ }
+
+ /**
+ ** Prepend a step to the path.
+ **
+ ** @param x The x coordinate of the new step
+ ** @param y The y coordinate of the new step
+ **/
+ public void prependStep(int x, int y) {
+ steps.insertElementAt(new Step(x, y), 0);
+ }
+
+ /**
+ ** Check if this path contains the given step
+ **
+ ** @param x The x coordinate of the step to check for
+ ** @param y The y coordinate of the step to check for
+ ** @return True if the path contains the given step
+ **/
+ public boolean contains(int x, int y) {
+ return steps.contains(new Step(x,y));
+ }
+
+}
+
+/**
+ ** A single step within the path
+ **/
+class Step {
+ /** The x coordinate at the given step */
+ private int x;
+ /** The y coordinate at the given step */
+ private int y;
+
+ /**
+ ** Create a new step
+ **
+ ** @param x The x coordinate of the new step
+ ** @param y The y coordinate of the new step
+ **/
+ public Step(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ ** Get the x coordinate of the new step
+ **
+ ** @return The x coodindate of the new step
+ **/
+ public int getX() {
+ return x;
+ }
+
+ /**
+ ** Get the y coordinate of the new step
+ **
+ ** @return The y coodindate of the new step
+ **/
+ public int getY() {
+ return y;
+ }
+
+ /**
+ ** Same as Object#hashCode()
+ **/
+ public int hashCode() {
+ return x*y;
+ }
+
+ /**
+ ** Same as Object#equals(Object)
+ **
+ **/
+ public boolean equals(Object other) {
+ if (other instanceof Step) {
+ Step o = (Step) other;
+ if((o.x == x) && (o.y == y)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
--- /dev/null
+/**
+ ** An object representing the entity in the game that
+ ** is going to move along the path. This allows us to pass around entity/state
+ ** information to determine whether a particular tile is blocked, or how much
+ ** cost to apply on a particular tile.
+ **
+ ** a) Saves the current X and Y coordinates for a Player
+ ** b) Saves the destination goalX and goalY
+ ** c) Determines the boundary using high/low X and Y coordinates for
+ ** the current position
+ ** d) Keeps track of the STATE of the player
+ **/
+public class Player {
+ private int type;
+ private int x;
+ private int y;
+ private int lowx, highx;
+ private int lowy, highy;
+ private int state;
+ private int goalx, goaly;
+ private int rows, cols;
+ private Random rand;
+ private char action;
+
+ public Player(int type, int x, int y) {
+ this.type = type;
+ this.x = x;
+ this.y = y;
+ }
+
+ public Player(int type, int x, int y, int rows, int cols, int bounds) {
+ this.type = type;
+ this.x = x;
+ this.y = y;
+ this.rows = rows;
+ this.cols = cols;
+ lowx = x - bounds;
+ highx = x + bounds;
+ lowy = y - bounds;
+ highy = y + bounds;
+ // define new boundaries
+ if (lowx <= 0)
+ lowx = 1;
+ if (lowy <= 0)
+ lowy = 1;
+ if (highx >= rows)
+ highx = rows-2;
+ if (highy >= cols)
+ highy = cols-2;
+ this.state = 0; //0 => INIT state
+ this.goalx = 0;
+ this.goaly = 0;
+ rand = new Random(30); //seed to generate random numbers
+ this.action = 'M'; //initalized to moving
+ }
+
+ public void reset(GameMap[][] land, int row, int col, int bounds) {
+ //Teleport to new location
+ if(type == 1) { //PLANTER
+ x = (rand.nextInt(Math.abs(row - 2) + 1)) + 1;
+ y = (rand.nextInt(Math.abs(col - 2) + 1)) + 1;
+ goalx = -1;
+ goaly = -1;
+ setBoundary(bounds, row, col);
+ }
+
+ if(type == 0) { //LUMBERJACK
+ int trycount = 5; //try a few more times before teleporting
+ int i = 0;
+ while(i<trycount) {
+ int locx = (rand.nextInt(Math.abs(row - 2) + 1)) + 1;
+ int locy = (rand.nextInt(Math.abs(col - 2) + 1)) + 1;
+ if(!land[locx][locy].hasRock() && land[locx][locy].hasTree()) {
+ goalx = locx;
+ goaly = locy;
+ state = 1; //1=> MOVING state
+ return;
+ }
+ i++;
+ }
+ x = (rand.nextInt(Math.abs(row - 2) + 1)) + 1;
+ y = (rand.nextInt(Math.abs(col - 2) + 1)) + 1;
+ goalx = -1;
+ goaly = -1;
+ setBoundary(bounds, row, col);
+ }
+ }
+
+ public void setBoundary(int bounds, int rows, int cols) {
+ lowx = x - bounds;
+ highx = x + bounds;
+ lowy = y - bounds;
+ highy = y + bounds;
+ // define new boundaries
+ if (lowx <= 0)
+ lowx = 1;
+ if (lowy <= 0)
+ lowy = 1;
+ if (highx >= rows-1)
+ highx = rows-2;
+ if (highy >= cols-1)
+ highy = cols-2;
+ return;
+ }
+
+ /**
+ ** @return if Player is lumberjack or a planter
+ **/
+ public int kind() {
+ return type;
+ }
+
+ /**
+ ** Sets the X and Y coordinate of the Player
+ **/
+ public void setPosition(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ //public void setNewPosition(int x, int y, int row, int col, int bounds) {
+ public void setNewPosition(int row, int col, int bounds) {
+ //setPosition(x, y);
+ setBoundary(bounds, row, col);
+ goalx = -1;
+ goaly = -1;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ /** Sets state of the Player **/
+
+ public void setState(int state) {
+ this.state = state;
+ return;
+ }
+
+ public int getState() {
+ return this.state;
+ }
+
+ /** Randomly finds a goal in a given boundary for player
+ ** @return 0 on success and -1 when you cannot find any new goal
+ **/
+ public int findGoal(GameMap[][] land) {
+ /* Try setting the goal for try count times
+ * if not possible, then select a completely new goal
+ */
+ int trycount = (highx - lowx) + (highy - lowy);
+ int i;
+
+ Random rand = new Random(0);
+ for (i = 0; i < trycount; i++) {
+ int row = (rand.nextInt(Math.abs(highx - lowx)) + 1) + lowx;
+ int col = (rand.nextInt(Math.abs(highy - lowy)) + 1) + lowy;
+ if (type == 1 && (land[row][col].hasTree() == false) && (land[row][col].hasRock() == false)) {
+ goalx = row;
+ goaly = col;
+ return 0;
+ }
+ if (type == 0 && (land[row][col].hasTree() == true) && (land[row][col].hasRock() == false)) {
+ goalx = row;
+ goaly = col;
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ public void setGoal(int x, int y) {
+ goalx = x;
+ goaly = y;
+ }
+
+ public int getGoalX() {
+ return goalx;
+ }
+
+ public int getGoalY() {
+ return goaly;
+ }
+
+ /**
+ ** Only for debugging
+ **/
+ public debugPlayer() {
+ System.println("State= "+ state+ " Curr X= "+ x + " Curr Y= " + y + " Goal X= "+ goalx + " Goal Y= "+ goaly + " Type = " + type);
+ }
+
+ /**
+ ** @return true if reached the goal else return false
+ **/
+ public boolean atDest() {
+ if (x == goalx && y == goaly) {
+ return true;
+ }
+ return false;
+ }
+}
--- /dev/null
+#define ROW 100 /* columns in the map */
+#define COLUMN 100 /* rows of in the map */
+#define ROUNDS 200 /* Number of moves by each player */
+#define PLAYERS 20 /* Number of Players when num Players != num of client machines */
+#define RATI0 0.5 /* Number of lumberjacks to number of planters */
+#define BLOCK 3 /* Area around the gamer to consider */
+#define TREE_ZONE 0.4 /* Max percentage of trees in a zone */
+
+#define LUMBERJACK 0 /* If lumberjack */
+#define PLANTER 1 /* If a tree planter */
+#define SHIFT 2 /* Shift to new location */
+
+#define INIT 0 /* Initial state */
+#define MOVING 1 /* When moving along the map */
+
+public class RainForestClient {
+
+ public RainForestClient() {
+
+ }
+
+ public static void main(String[] args) {
+ int seed;
+ if(args.length>0) {
+ seed = Integer.parseInt(args[0]);
+ }
+
+ Random rand = new Random(seed);
+ RainForestClient rfc = new RainForestClient();
+ Socket sock = new Socket("dw-8.eecs.uci.edu",9002);
+
+ /* Read player type from Server */
+ byte b[] = new byte[1]; //read planter or lumber jack
+ int numbytes;
+ while((numbytes = sock.read(b)) < 1) {
+ ;
+ }
+ String str = (new String(b)).subString(0, numbytes);
+ int person;
+ if(str.equalsIgnoreCase("L")) {
+ person = LUMBERJACK;
+ }
+ if(str.equalsIgnoreCase("P")) {
+ person = PLANTER;
+ }
+
+ //Generate a random x and y coordinate to start with
+ int maxValue = ROW - 1;
+ int minValue = 1;
+ int row = (rand.nextInt(Math.abs(maxValue - minValue) + 1)) + minValue;
+ maxValue = COLUMN -1;
+ int col = (rand.nextInt(Math.abs(maxValue - minValue) + 1)) + minValue;
+ Player gamer = new Player(person, row, col, ROW, COLUMN, BLOCK);
+
+ //
+ //Debug
+ //
+ /* System.println("Person= "+person+" LocX= "+row+" LocY= "+col); */
+
+ GameMap[][] land = new GameMap[ROW][COLUMN];
+ for(int i = 0; i<ROW; i++) {
+ for(int j = 0; j<COLUMN; j++) {
+ land[i][j] = new GameMap();
+ }
+ }
+ byte buf[] = new byte[9];
+ String temp;
+ Barrier barr;
+ barr = new Barrier("128.195.175.79");
+ for(int i = 0; i<ROUNDS; i++) {
+ //
+ // Send the continue to read
+ //
+ sock.write(rfc.fillBytes("U",i));
+
+ //
+ //Read information of land object from Server
+ //
+ while(true) {
+ numbytes = sock.read(buf);
+ temp = (new String(buf)).subString(0, numbytes);
+ if(temp.startsWith("sentLand"))
+ break;
+ rfc.extractCoordinates(buf, land);
+ }
+
+ //Debug
+ //rfc.printLand(land, ROW, COLUMN);
+
+ //
+ //Do rounds
+ //do one move per round and write to server
+ //
+ rfc.doOneMove(land, gamer, sock);
+
+ //Receive ACK from server and do player updates
+ while((numbytes = sock.read(b)) < 1) {
+ ;
+ }
+ if((b[0] == (byte)'S') && ((gamer.action == 'C') || gamer.action == 'P')) {
+ //Update position and boundaries
+ gamer.setNewPosition(ROW, COLUMN, BLOCK);
+ gamer.setState(INIT);
+ }
+
+ //Retry if failure
+ if(b[0] == (byte)'F'){
+ i--;
+ }
+
+ //Synchronize threads
+ Barrier.enterBarrier(barr);
+ }
+
+ //
+ //Special character "T" to terminate computation
+ //
+ sock.write(rfc.fillBytes("T", 0));
+ sock.close();
+ }
+
+ public void extractCoordinates(byte[] b, GameMap[][] land) {
+ int posX = getX(b);
+ int posY = getY(b);
+
+ if(b[0] == (byte) 'T') {
+ land[posX][posY].putTree(new TreeType());
+ }
+ if(b[0] == (byte) 'R') {
+ land[posX][posY].putRock(new RockType());
+ }
+ }
+
+ int getX(byte[] b) {
+ int val;
+ val = ((b[1] & 0xFF) << 24) + ((b[2] & 0xFF) << 16) + ((b[3] & 0xFF) << 8) + (b[4] & 0xFF);
+ return val;
+ }
+
+ int getY(byte[] b) {
+ int val;
+ val = ((b[5] & 0xFF) << 24) + ((b[6] & 0xFF) << 16) + ((b[7] & 0xFF) << 8) + (b[8] & 0xFF);
+ return val;
+ }
+
+ /**
+ ** Only for Debugging
+ **/
+ public void printLand(GameMap[][] land, int row, int col) {
+ for (int i = 0; i < row; i++) {
+ for (int j = 0; j < col; j++) {
+ land[i][j].print();
+ }
+ System.println("");
+ }
+ }
+
+ /**
+ ** One move by the gamer
+ ** @param land The map to be searched
+ ** @param gamer The player making the move
+ ** @return 0 is success , -1 otherwise
+ **/
+ public int doOneMove(GameMap[][] land, Player gamer, Socket sock) {
+ // 1. Get start(x, y) position of the player
+ int currx = gamer.getX();
+ int curry = gamer.getY();
+
+ //
+ //Debug
+ //
+ /* printLand(land, ROW, COLUMN); */
+
+ // 2. Get type of player (lumberjack or planter)
+ int type = gamer.kind();
+
+ //3. Change states
+ if (gamer.getState() == INIT) {
+
+ //gamer.debugPlayer();
+
+ if (gamer.findGoal(land) < 0) {
+ gamer.reset(land, ROW, COLUMN, BLOCK);
+ gamer.action = 'M';
+ sock.write(fillBytes(SHIFT, 0, 0));
+ return 0;
+ }
+
+ //gamer.debugPlayer();
+
+ gamer.setState(MOVING);
+ }
+
+ if (gamer.getState() == MOVING) {
+ Goal nextmove = new Goal();
+ int maxSearchDistance = 10;
+ boolean allowDiagMovement = true;
+
+ /* Find shortest path using AStar algo from start to goal */
+ AStarPathFinder apath = new AStarPathFinder(land, maxSearchDistance, allowDiagMovement, ROW, COLUMN);
+ Path newpath = apath.findPath(gamer);
+
+ /* Reset state if there in no path from start to goal */
+ if(newpath == null) {
+ //
+ //Debug
+ //
+ /* System.println("Path from ("+currx+","+curry+") to ("+gamer.getGoalX()+","+gamer.getGoalY()+") is null"); */
+
+ gamer.reset(land, ROW, COLUMN, BLOCK);
+ gamer.setState(INIT);
+ gamer.action = 'M';
+ sock.write(fillBytes(SHIFT, 0, 0));
+ return 0;
+ }
+
+ nextmove.setXY(newpath.getX(0), newpath.getY(0));
+ gamer.setPosition(nextmove.getX(), nextmove.getY());
+ //
+ //Debug
+ //gamer.debugPlayer();
+ //
+ currx = gamer.getX();
+ curry = gamer.getY();
+ if (gamer.atDest()) {
+ if (gamer.kind() == LUMBERJACK) {
+ if (land[currx][curry].hasTree()) {
+ //Send next move to server
+ gamer.action = 'C';
+ sock.write(fillBytes(LUMBERJACK, currx, curry));
+ return 0;
+ }
+ sock.write(fillBytes(SHIFT, 0, 0));
+ return 0;
+ } else { // PLANTER
+ if (land[currx][curry].hasTree() == false) {
+ if(hasMoreTrees(land, currx, curry) == false) {
+ //Send next move to server
+ gamer.action = 'P';
+ sock.write(fillBytes(PLANTER, currx, curry));
+ return 0;
+ }
+ sock.write(fillBytes(SHIFT, 0, 0));
+ return 0;
+ }
+ sock.write(fillBytes(SHIFT, 0, 0));
+ return 0;
+ }
+ } else {
+ if(land[currx][curry].hasTree() && gamer.kind() == LUMBERJACK) { //Cut trees along the way
+ //
+ //Send next move to server
+ //
+ gamer.action = 'C';
+ sock.write(fillBytes(LUMBERJACK, currx, curry));
+ return 0;
+ }
+ // Not at destination - do nothing
+ gamer.action = 'M';
+ sock.write(fillBytes(SHIFT, 0, 0));
+ }
+
+ return 0;
+ }
+ }
+
+ /**
+ ** Check the number of trees in a given area
+ **
+ ** @param land The map to be searched
+ ** @param x The x coordinate to plant a tree
+ ** @param y The y coordinate to plant a tree
+ **
+ ** @return true if area covered more than the zone for trees
+ **/
+ public boolean hasMoreTrees(GameMap[][] land, int x, int y) {
+ int lowx = x - BLOCK;
+ int highx = x + BLOCK;
+ int lowy = y - BLOCK;
+ int highy = y + BLOCK;
+ // define new boundaries
+ if (lowx <= 0)
+ lowx = 1;
+ if (lowy <= 0)
+ lowy = 1;
+ if (highx >= ROW-1)
+ highx = ROW-2;
+ if (highy >= COLUMN-1)
+ highy = COLUMN-2;
+ int treeCount = 0;
+ int areaCount = 0;
+ for(int i = lowx; i < highx; i++) {
+ for(int j = lowy; j < highy; j++) {
+ if(land[i][j].hasTree())
+ treeCount++;
+ areaCount++;
+ }
+ }
+ if(treeCount >= (TREE_ZONE * areaCount)) {
+ return true;
+ }
+ return false;
+ }
+
+ /** Fill byte array
+ ** @param type The player kind 1 => Planter 0=> Lumberjack 2=> Shift to new location
+ ** @param x The x coordinate of player
+ ** @param y The y coordinate of player
+ **/
+ byte[] fillBytes(int type, int x, int y) {
+ byte[] b = new byte[9]; //1 byte for the move + 8 bytes for x and y
+ if(type == PLANTER)
+ b[0] = (byte)'P'; //planting
+ if(type == LUMBERJACK)
+ b[0] = (byte)'C'; // cutting
+ if(type == SHIFT)
+ b[0] = (byte)'M'; //moving
+ for(int i = 1; i<5; i++) {
+ int offset = (3-(i-1)) * 8;
+ b[i] = (byte) ((x >> offset) & 0xFF);
+ }
+ for(int i = 5; i<9; i++) {
+ int offset = (3-(i-5)) * 8;
+ b[i] = (byte) ((y >> offset) & 0xFF);
+ }
+ return b;
+ }
+
+ /** Fill byte array for round index and termination
+ ** @param x The x coordinate of player
+ ** @param y The y coordinate of player
+ **/
+ byte[] fillBytes(String str, int index) {
+ byte[] b = new byte[5]; //1 byte for the control msg + 4 bytes for roundIndex
+ if(str.equalsIgnoreCase("U")) {
+ b[0] = (byte)'U';
+ }
+
+ if(str.equalsIgnoreCase("T")) {
+ b[0] = (byte)'T';
+ }
+
+ for(int i = 1; i<5; i++) {
+ int offset = (3-(i-1)) * 8;
+ b[i] = (byte) ((index >> offset) & 0xFF);
+ }
+
+ return b;
+ }
+}
--- /dev/null
+#define ROW 100 /* columns in the map */
+#define COLUMN 100 /* rows of in the map */
+
+public class RainForestServerExample {
+ private int numThreads;
+
+ public RainForestServerExample() {
+
+ }
+
+ public static int main(String args[]) {
+ int numThreads;
+ if(args.length>0) {
+ numThreads = Integer.parseInt(args[0]);
+ }
+
+ /**
+ * Create shared Map
+ **/
+ // Init land and place rocks in boundaries
+ GameMap[][] world;
+ world = new GameMap[ROW][COLUMN];
+ for (int i = 0; i < ROW; i++) {
+ for (int j = 0; j < COLUMN; j++) {
+ world[i][j] = new GameMap();
+ if (j == 0 || j == COLUMN-1) {
+ RockType r = new RockType();
+ world[i][j].putRock(r);
+ }
+ if (i == 0 || i == ROW-1) {
+ RockType r = new RockType();
+ world[i][j].putRock(r);
+ }
+ }
+ }
+
+ ServerSocket ss = new ServerSocket(9002);
+ acceptConnection(ss, world, numThreads);
+ }
+
+ public static void acceptConnection(ServerSocket ss, GameMap[][] world, int numThreads) {
+ //
+ //Start Barrier server
+ //
+ BarrierServer mybarr = new BarrierServer(numThreads);
+ mybarr.start();
+
+ /* Set up threads */
+ RainForestServerThread[] rft = new RainForestServerThread[numThreads];
+ for(int i=0; i<numThreads; i++) {
+ Socket s = ss.accept();
+ rft[i] = new RainForestServerThread(world, s, ROW, COLUMN, i);
+ }
+
+ /* Wait for messages */
+ boolean waitforthreaddone = true;
+ while(waitforthreaddone) {
+ if(mybarr.done)
+ waitforthreaddone = false;
+ }
+
+ /* Start threads */
+ for(int i = 0; i<numThreads; i++) {
+ rft[i].start();
+ }
+
+ /* Join threads */
+ for(int i = 0; i<numThreads; i++) {
+ rft[i].join();
+ }
+
+ System.printString("Finished\n");
+ }
+
+ /**
+ * Parse the command line options.
+ **/
+ public static void parseCmdLine(String args[], RainForestServerExample rf) {
+ int i = 0;
+ String arg;
+ while(i < args.length && args[i].startsWith("-")) {
+ arg = args[i++];
+ //check options
+ if(arg.equals("-N")) {
+ if(i < args.length) {
+ rf.numThreads = new Integer(args[i++]).intValue();
+ }
+ } else if(arg.equals("-h")) {
+ rf.usage();
+ }
+ }
+
+ if(rf.numThreads == 0)
+ rf.usage();
+ }
+
+ /**
+ * The usage routine which describes the program options.
+ **/
+ public void usage() {
+ System.println("usage: ./RainForestN.bin master -N <threads>\n");
+ System.printString(" -N the number of threads\n");
+ System.printString(" -h help with usage\n");
+ }
+}
--- /dev/null
+#define PLAYERS 20 /* Number of Players when num Players != num of client machines */
+#define RATI0 0.5 /* Number of lumberjacks to number of planters */
+#define BLOCK 3 /* Area around the gamer to consider */
+#define TREE_ZONE 0.4 /* Max percentage of trees in a zone */
+#define AGEUPDATETHRESHOLD 10 /* How frequently/how many rounds to increment age of tree */
+#define MAXAGE 100 /* Max age of a tree */
+
+public class RainForestServerThread extends Thread {
+ GameMap[][] land;
+ Socket sock;
+ int rows;
+ int cols;
+ int id;
+
+ public RainForestServerThread(GameMap[][] land, Socket sock, int rows, int cols, int id) {
+ this.land = land;
+ this.sock = sock;
+ this.rows = rows;
+ this.cols = cols;
+ this.id = id;
+ }
+
+ public void run() {
+ /* Assign a player to be a lumberjack or planter */
+ byte b[] = new byte[1]; //1 byte control to determine if lumberjack/planter
+ if((id&1) != 0)
+ b[0] = (byte)'L';
+ else
+ b[0] = (byte)'P';
+ sock.write(b);
+
+ //
+ //Debugging
+ //
+ /* printLand(land, rows, cols); */
+
+ byte[] buf = new byte[5]; //1 byte to decide if terminate or continue + 4 bytes for getting the round index
+ int numbytes;
+ byte[] buffer = new byte[9]; //1 byte presence of tree/rocks + 8 bytes for their x and y coordinates
+
+ while(true) {
+
+ /* Check for termination character */
+ while((numbytes = sock.read(buf)) < 5) {
+ //System.println("Looping in 2");
+ ;
+ }
+
+ String str1 = (new String(buf)).subString(0, 1);
+
+ /* terminate if opcode sent is "t" */
+ if(str1.equalsIgnoreCase("T")) {
+ break;
+ } else if(str1.equalsIgnoreCase("U")) {
+ int roundIndex = getX(buf); //Get the index from client
+ System.println("round id = " + roundIndex);
+ if((roundIndex % AGEUPDATETHRESHOLD) == 0 && (id == 0)) {
+ /* Update age of all trees in a Map */
+ updateAge(land, MAXAGE, rows, cols);
+ }
+
+ /* Data representing presence/absence of trees */
+ for(int i=0 ; i<rows; i++) {
+ for(int j=0; j<cols; j++) {
+ sock.write(fillBytes(land, i, j, buffer));
+ }
+ }
+
+ StringBuffer header = new StringBuffer("sentLand");
+ String temp_str = new String(header);
+ sock.write(temp_str.getBytes());
+ header = null;
+ temp_str = null;
+
+ /* Read client's move */
+ while((numbytes = sock.read(buffer)) < 9) {
+ ;
+ }
+ str1 = (new String(buffer)).subString(0, 1);
+
+ /* Take actions such as cutting or planting or moving */
+ if(str1.equalsIgnoreCase("C")) {
+ int val;
+ if((val = doTreeCutting(land, buffer)) == 0) {
+ System.println("Cutting\n");
+ b[0] = (byte)'S';
+ } else {
+ System.println("Retrying to cut\n");
+ b[0] = (byte)'F';
+ }
+ sock.write(b);
+ }
+
+ if(str1.equalsIgnoreCase("P")) {
+ int val;
+ if((val = doTreePlanting(land, buffer)) == 0) {
+ System.println("Planting\n");
+ b[0] = (byte)'S';
+ } else {
+ System.println("Retrying to plant\n");
+ b[0] = (byte)'F';
+ }
+ sock.write(b);
+ }
+
+ if(str1.equalsIgnoreCase("M")) {
+ System.println("Moving to goal\n");
+ b[0] = (byte)'S';
+ sock.write(b);
+ }
+ }
+ } //end while
+
+ //
+ //Debugging
+ //printLand(land, rows, cols);
+ //
+ sock.close();
+
+ }//end run()
+
+ /**
+ ** fill byte array
+ **/
+ byte[] fillBytes(GameMap[][] land, int x, int y, byte[] b) {
+ if(land[x][y].hasTree())
+ b[0] = (byte)'T';
+ if(land[x][y].hasRock())
+ b[0] = (byte)'R';
+ if(!land[x][y].hasRock() && !land[x][y].hasTree())
+ b[0] = (byte)'N';
+ for(int i = 1; i<5; i++) {
+ int offset = (3-(i-1)) * 8;
+ b[i] = (byte) ((x >> offset) & 0xFF);
+ }
+ for(int i = 5; i<9; i++) {
+ int offset = (3-(i-5)) * 8;
+ b[i] = (byte) ((y >> offset) & 0xFF);
+ }
+ return b;
+ }
+
+ /**
+ ** Only for Debugging
+ **/
+ public void printLand(GameMap[][] land, int row, int col) {
+ for (int i = 0; i < row; i++) {
+ for (int j = 0; j < col; j++) {
+ land[i][j].print();
+ }
+ System.println("");
+ }
+ }
+
+ /**
+ * Synchronize threads that are cutting trees
+ **/
+ synchronized int doTreeCutting(GameMap[][] land, byte[] b) {
+ int posX = getX(b);
+ int posY = getY(b);
+
+ /* Cut, if tree present */
+ if(land[posX][posY].hasTree()) {
+ land[posX][posY].cutTree();
+ return 0;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Synchronize threads that are planting trees
+ **/
+ synchronized int doTreePlanting(GameMap[][] land, byte[] b) {
+ int posX = getX(b);
+ int posY = getY(b);
+
+ /* Plant if no tree */
+ if(!land[posX][posY].hasTree()) {
+ TreeType t = new TreeType();
+ land[posX][posY].putTree(t);
+ return 0;
+ }
+
+ return -1;
+ }
+
+ /**
+ ** Get X coordinate
+ **/
+ int getX(byte[] b) {
+ int val;
+ val = ((b[1] & 0xFF) << 24) + ((b[2] & 0xFF) << 16) + ((b[3] & 0xFF) << 8) + (b[4] & 0xFF);
+ return val;
+ }
+
+ /**
+ ** Get Y coordinate
+ **/
+ int getY(byte[] b) {
+ int val;
+ val = ((b[5] & 0xFF) << 24) + ((b[6] & 0xFF) << 16) + ((b[7] & 0xFF) << 8) + (b[8] & 0xFF);
+ return val;
+ }
+
+ /**
+ ** Update age of trees in a map
+ ** @param land: The map
+ ** @param maxage: The max age of a tree
+ ** @param rows: Rows in the map
+ ** @param cols: Cols in the map
+ **/
+
+ /**
+ * Synchronize threads that are cutting trees
+ **/
+ synchronized void updateAge(GameMap[][] land, int maxage, int rows, int cols) {
+ int countTrees = 0;
+ for(int i = 0; i<rows; i++) {
+ for(int j = 0; j<cols; j++) {
+ if(land[i][j].hasTree()) {
+ if(land[i][j].tree.getage() > maxage) {
+ land[i][j].tree = null;
+ } else {
+ land[i][j].tree.incrementage();
+ }
+ countTrees++;
+ }
+ }
+ }
+ //
+ //Debug
+ //System.println("Tree count= "+countTrees);
+ //
+ }
+}
--- /dev/null
+/**
+ ** Rock and its properties
+ **/
+public class RockType {
+ public RockType() {
+
+ }
+}
--- /dev/null
+/**
+ ** Tree and its properties
+ **/
+public class TreeType {
+ private int age;
+
+ public TreeType() {
+ age = 0;
+ }
+
+ public int getage() {
+ return age;
+ }
+
+ public void incrementage() {
+ age++;
+ }
+
+ public void incrementTenYrs() {
+ age = age + 10;
+ }
+
+ public void incrementFiveYrs() {
+ age = age + 5;
+ }
+
+ public int hashCode() {
+ return age;
+ }
+
+ public String toString() {
+ return String.valueOf(age);
+ }
+}
--- /dev/null
+#!/bin/sh
+lines=$(grep -n "#" tmp1RainForestClient.java | cut -d: -f1 | sed '1q')
+sed '/^#/d' tmp1RainForestClient.java > tmpRainForestClient.java
+lines=$(grep -n "#" tmp1RainForestServerExample.java | cut -d: -f1 | sed '1q')
+sed '/^#/d' tmp1RainForestServerExample.java > tmpRainForestServerExample.java
+lines=$(grep -n "#" tmp1RainForestServerThread.java | cut -d: -f1 | sed '1q')
+sed '/^#/d' tmp1RainForestServerThread.java > tmpRainForestServerThread.java
--- /dev/null
+MAINCLASS1=RainForestServerExample
+MAINCLASS2=RainForestClient
+SRC=tmp${MAINCLASS1}.java \
+ tmpRainForestServerThread.java \
+ TreeType.java \
+ GameMap.java \
+ RockType.java \
+ Player.java \
+ BarrierNonDSM.java
+
+SRC1 =tmp${MAINCLASS2}.java \
+ GameMap.java \
+ TreeType.java \
+ RockType.java \
+ Goal.java \
+ Path.java \
+ Node.java \
+ Player.java \
+ AStarPathFinder.java \
+ BarrierNonDSM.java
+
+
+FLAGS1= -thread -nooptimize -debug -mainclass ${MAINCLASS1}
+FLAGS2= -thread -nooptimize -debug -mainclass ${MAINCLASS2}
+
+default:
+ cpp RainForestServerExample.java > tmp1RainForestServerExample.java
+ cpp RainForestServerThread.java > tmp1RainForestServerThread.java
+ cpp RainForestClient.java > tmp1RainForestClient.java
+ ./extractLines
+ ../../../../buildscript ${FLAGS1} -o Server ${SRC}
+ ../../../../buildscript ${FLAGS2} -o Client ${SRC1}
+
+clean:
+ rm -rf tmpbuilddirectory
+ rm *.bin
+ rm tmp1RainForestServerExample.java
+ rm tmp1RainForestServerThread.java
+ rm tmp1RainForestClient.java
+ rm tmpRainForestServerExample.java
+ rm tmpRainForestServerThread.java
+ rm tmpRainForestClient.java