public class Ghost {\r
- public int x;\r
- public int y;\r
- public int index;\r
- public int target;\r
- public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
- int dx;\r
- int dy;\r
- int destinationX;\r
- int destinationY;\r
- Map map;\r
\r
- public Ghost(int x, int y, Map map) {\r
- this.x = x;\r
- this.y = y;\r
- this.dx = this.dy = 0;\r
- this.index = -1;\r
- this.target = -1;\r
- this.direction = 0;\r
- this.destinationX = -1;\r
- this.destinationY = -1;\r
- this.map = map;\r
- }\r
+ public int m_locX;\r
+ public int m_locY;\r
+ public int m_index;\r
+ public int m_target;\r
+ public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
+ int m_dx;\r
+ int m_dy;\r
+ Map m_map;\r
\r
- public void setTarget(int pacman) {\r
- this.target = pacman;\r
+ public Ghost(int x, int y, Map map) {\r
+ this.m_locX = x;\r
+ this.m_locY = y;\r
+ this.m_dx = this.m_dy = 0;\r
+ this.m_index = -1;\r
+ this.m_target = -1;\r
+ this.m_direction = 0;\r
+ this.m_map = map;\r
}\r
\r
// 0:still, 1:up, 2:down, 3:left, 4:right\r
public void tryMove() {\r
- //System.printString("step 1\n");\r
- //System.printString("target: " + this.target + "\n");\r
- \r
- // Don't let the ghost go back the way it came.\r
- int prevDirection = 0;\r
+ // System.printString("step 1\n");\r
+ int i = 0;\r
\r
- // If there is a destination, then check if the destination has been reached.\r
- if (destinationX >= 0 && destinationY >= 0) {\r
- // Check if the destination has been reached, if so, then\r
- // get new destination.\r
- if (destinationX == x && destinationY == y) {\r
- destinationX = -1;\r
- destinationY = -1;\r
- prevDirection = direction;\r
- } else {\r
- // Otherwise, we haven't reached the destionation so\r
- // continue in same direction.\r
- return;\r
+ // check the nearest pacman and set it as current target\r
+ this.m_target = -1;\r
+ int deltaX = this.m_map.m_nrofblocks;\r
+ int deltaY = this.m_map.m_nrofblocks;\r
+ int distance = deltaX * deltaX + deltaY * deltaY;\r
+ for(i = 0; i < this.m_map.m_nrofpacs; i++) {\r
+ if(this.m_map.m_pacMenX[i] != -1) {\r
+ int dx = this.m_locX - this.m_map.m_pacMenX[i];\r
+ int dy = this.m_locY - this.m_map.m_pacMenY[i];\r
+ int dd = dx*dx+dy*dy;\r
+ if(distance > dd) {\r
+ this.m_target = i;\r
+ distance = dd;\r
+ deltaX = dx;\r
+ deltaY = dy;\r
+ }\r
}\r
}\r
- setNextDirection (prevDirection);\r
+ // System.printString("target: " + this.m_target + "\n");\r
+ \r
+ if(this.m_target == -1) {\r
+ // no more pacmen to chase, stay still\r
+ this.m_dx = 0;\r
+ this.m_dy = 0;\r
+ this.m_direction = this.m_map.m_ghostdirections[this.m_index] = 0;\r
+ return;\r
+ }\r
+ \r
+ // find the shortest way to the chosen target\r
+ setNextDirection();\r
}\r
\r
- private void setNextDirection(int prevDirection) {\r
+ private void setNextDirection() {\r
+ // current position of the ghost\r
+ Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];\r
+ \r
// get target's position\r
- int targetx = this.map.pacMenX[this.target];\r
- //System.printString("aaa\n");\r
- int targety = this.map.pacMenY[this.target];\r
+ int targetx = this.m_map.m_pacMenX[this.m_target];\r
+ int targety = this.m_map.m_pacMenY[this.m_target];\r
int[] nextLocation = new int[2];\r
nextLocation[0] = nextLocation[1] = -1;\r
- \r
- //System.printString("bbb\n");\r
- if(targetx == -1) {\r
- //System.printString("a\n");\r
- // already kicked off, choose another target\r
- int i = 0;\r
- boolean found = false;\r
- while((!found) && (i < map.pacMenX.length)) {\r
- if(this.map.pacMenX[i] != -1) {\r
- this.target = i;\r
- targetx = this.map.pacMenX[i];\r
- targety = this.map.pacMenY[i];\r
- this.map.targets[i] = this.target;\r
- found = true;\r
- }\r
- i++;\r
- }\r
- //System.printString("b\n");\r
- if(i == this.map.pacMenX.length) {\r
- //System.printString("c\n");\r
- // no more pacmen to chase\r
- this.dx = 0;\r
- this.dy = 0;\r
- this.direction = 0;\r
- return;\r
- }\r
- //System.printString("d\n");\r
- }\r
- getDestination (this.map.pacmen[this.target].direction, targetx, targety, nextLocation);\r
+ // check the target pacman's possible destination\r
+ getDestination (this.m_map.m_directions[this.m_target], targetx, targety, nextLocation);\r
targetx = nextLocation[0];\r
targety = nextLocation[1];\r
+ // target's position\r
+ Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];\r
+ // reset the target as index of the end node\r
+ this.m_target = this.m_map.m_targets[this.m_index] = end.getIndex();\r
\r
- //System.printString("step 2\n");\r
- // check the distance\r
- int deltax = this.x - targetx; // <0: move right; >0: move left\r
- int deltay = this.y - targety; // <0: move down; >0: move up\r
- // decide the priority of four moving directions\r
- int[] bestDirection = new int[4];\r
- //System.printString("dx: " + deltax + "; dy: " + deltay + "\n");\r
- if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) {\r
- // go first along y\r
- if(deltay > 0) {\r
- bestDirection[0] = 1;\r
- bestDirection[3] = 2;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
+ // breadth-first traverse the graph view of the maze\r
+ // check the shortest path for the start node to the end node\r
+ boolean set = false;\r
+ Vector cuts = new Vector();\r
+ int tmpdx = 0;\r
+ int tmpdy = 0;\r
+ int tmpdirection = 0;\r
+ boolean first = true;\r
+ while(!set) {\r
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks];\r
+ for(int i = 0; i < parents.length; i++) {\r
+ parents[i] = -1;\r
+ }\r
+ if(!BFS(start, end, parents, cuts)) {\r
+ this.m_dx = tmpdx;\r
+ this.m_dy = tmpdy;\r
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;\r
+ set = true;\r
+ //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");\r
} else {\r
- bestDirection[0] = 2;\r
- bestDirection[3] = 1;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
+ // Reversely go over the parents array to find the next node to reach\r
+ boolean found = false;\r
+ int index = end.getIndex();\r
+ while(!found) {\r
+ int parent = parents[index];\r
+ if(parent == start.getIndex()) {\r
+ found = true;\r
+ } else {\r
+ index = parent;\r
+ }\r
}\r
- }\r
- } else {\r
- if(deltax > 0) {\r
- bestDirection[0] = 3;\r
- bestDirection[3] = 4;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+\r
+ // set the chase direction\r
+ int nx = this.m_map.m_mapNodes[index].getXLoc();\r
+ int ny = this.m_map.m_mapNodes[index].getYLoc();\r
+ this.m_dx = nx - this.m_locX;\r
+ this.m_dy = ny - this.m_locY;\r
+ if(this.m_dx > 0) {\r
+ // right\r
+ this.m_direction = 4;\r
+ } else if(this.m_dx < 0) {\r
+ // left\r
+ this.m_direction = 3;\r
+ } else if(this.m_dy > 0) {\r
+ // down\r
+ this.m_direction = 2;\r
+ } else if(this.m_dy < 0) {\r
+ // up\r
+ this.m_direction = 1;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ // still\r
+ this.m_direction = 0;\r
}\r
- } else {\r
- bestDirection[0] = 4;\r
- bestDirection[3] = 3;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+ if(first) {\r
+ tmpdx = this.m_dx;\r
+ tmpdy = this.m_dy;\r
+ tmpdirection = this.m_direction;\r
+ first = false;\r
+ //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");\r
+ }\r
+\r
+ // check if this choice follows some other ghosts' path\r
+ if(!isFollowing()) {\r
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction;\r
+ set = true;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ cuts.addElement(new Integer(index));\r
+ /*for( int h = 0; h < cuts.size(); h++) {\r
+ System.printString(cuts.elementAt(h) + ", ");\r
+ }\r
+ System.printString("\n");*/\r
}\r
}\r
}\r
- /*for(int i = 0; i < 4; i++) {\r
- System.printString(bestDirection[i] + ",");\r
- }\r
- System.printString("\n");*/\r
- \r
- // There's a 50% chance that the ghost will try the sub-optimal direction first.\r
- // This will keep the ghosts from following each other and to trap Pacman.\r
- if (this.map.r.nextDouble() < .50) { \r
- int temp = bestDirection[0];\r
- bestDirection[0] = bestDirection[1];\r
- bestDirection[1] = temp;\r
- }\r
- \r
- //System.printString("step 3\n");\r
- // try to move one by one\r
- int i = 0;\r
- boolean set = false;\r
- this.dx = 0;\r
- this.dy = 0;\r
- while((!set) && (i < 4)) {\r
- if(bestDirection[i] == 1) {\r
- // try to move up\r
- if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) {\r
- //System.printString("a\n");\r
- if (getDestination (1, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = -1;\r
- set = true;\r
+ }\r
+ \r
+ // This methos do BFS from start node to end node\r
+ // If there is a path from start to end, return true; otherwise, return false\r
+ // Array parents records parent for a node in the BFS search\r
+ // Vector cuts specifies which nodes can not be the first one to access in this BFS\r
+ private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {\r
+ Vector toaccess = new Vector();\r
+ toaccess.addElement(start);\r
+ while(toaccess.size() > 0) {\r
+ // pull out the first one to access\r
+ Node access = (Node)toaccess.elementAt(0);\r
+ toaccess.removeElementAt(0);\r
+ if(access.getIndex() == end.getIndex()) {\r
+ // hit the end node\r
+ return true;\r
+ }\r
+ Vector neighbours = access.getNeighbours();\r
+ for(int i = 0; i < neighbours.size(); i++) {\r
+ Node neighbour = (Node)neighbours.elementAt(i);\r
+ if(parents[neighbour.getIndex()] == -1) {\r
+ // not accessed\r
+ boolean ignore = false;\r
+ if(access.getIndex() == start.getIndex()) {\r
+ // start node, check if the neighbour node is in cuts\r
+ int j = 0;\r
+ while((!ignore) && (j < cuts.size())) {\r
+ int tmp = ((Integer)cuts.elementAt(j)).intValue();\r
+ if(tmp == neighbour.getIndex()) {\r
+ ignore = true;\r
+ }\r
+ j++;\r
+ }\r
}\r
- }\r
- } else if (bestDirection[i] == 2) {\r
- // try to move down\r
- if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) {\r
- //System.printString("b\n");\r
- if (getDestination (2, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = 1;\r
- set = true;\r
+ if(!ignore) {\r
+ parents[neighbour.getIndex()] = access.getIndex();\r
+ toaccess.addElement(neighbour);\r
}\r
}\r
- } else if (bestDirection[i] == 3) {\r
- // try to move left\r
- if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) {\r
- //System.printString("c\n");\r
- if (getDestination (3, this.x, this.y, nextLocation)) {\r
- this.dx = -1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ // This method returns true if this ghost is traveling to the same\r
+ // destination with the same direction as another ghost.\r
+ private boolean isFollowing () {\r
+ boolean bFollowing = false;\r
+ double dRandom;\r
+\r
+ // If the ghost is in the same location as another ghost\r
+ // and moving in the same direction, then they are on\r
+ // top of each other and should not follow.\r
+ for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {\r
+ // Ignore myself\r
+ if (this.m_index != i) {\r
+ if (this.m_map.m_ghostsX[i] == this.m_locX &&\r
+ this.m_map.m_ghostsY[i] == this.m_locY &&\r
+ this.m_map.m_ghostdirections[i] == this.m_direction) {\r
+ return true;\r
}\r
- } else if (bestDirection[i] == 4) {\r
- // try to move right\r
- if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) {\r
- //System.printString("d\n");\r
- if (getDestination (4, this.x, this.y, nextLocation)) {\r
- this.dx = 1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
+ }\r
+ }\r
+\r
+ // This will allow ghosts to often\r
+ // clump together for easier eating\r
+ dRandom = this.m_map.m_r.nextDouble();\r
+ if (dRandom < .90) { \r
+ //if (m_bInsaneAI && dRandom < .25)\r
+ // return false;\r
+ //else\r
+ return false;\r
+ }\r
+\r
+ // If ghost is moving to the same location and using the\r
+ // same direction, then it is following another ghost. \r
+ for (int i = 0; i < this.m_map.m_ghostsX.length; i++) { \r
+ // Ignore myself \r
+ if (this.m_index != i) {\r
+ if (this.m_map.m_targets[i] == this.m_target &&\r
+ this.m_map.m_ghostdirections[i] == this.m_direction) {\r
+ return true;\r
}\r
}\r
- i++;\r
}\r
- //System.printString("step 4\n");\r
+\r
+ return bFollowing;\r
}\r
\r
// This method will take the specified location and direction and determine\r
// for the given location if the thing moved in that direction, what the\r
// next possible turning location would be.\r
- boolean getDestination (int direction, int locX, int locY, int[] point) {\r
+ private boolean getDestination (int direction, int locX, int locY, int[] point) {\r
// If the request direction is blocked by a wall, then just return the current location\r
- if ((direction == 1 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up\r
- (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left\r
- (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down\r
- (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right \r
+ if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up\r
+ ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left\r
+ ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down\r
+ ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right \r
point[0] = locX;\r
point[1] = locY;\r
return false;\r
// then return false.\r
if (locY < 0 ||\r
locX < 0 ||\r
- locY == this.map.nrofblocks ||\r
- locX == this.map.nrofblocks) {\r
+ locY == this.m_map.m_nrofblocks ||\r
+ locX == this.m_map.m_nrofblocks) {\r
return false;\r
}\r
\r
boolean set = false;\r
- // Determine next turning location..\r
+ // Determine next turning location.\r
while (!set) {\r
if (direction == 1 || direction == 2) { \r
// up or down\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // down\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down\r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
// Check for Top Warp\r
if (locY == 0) {\r
point[0] = locX;\r
- point[1] = this.map.nrofblocks - 1;\r
+ point[1] = this.m_map.m_nrofblocks - 1;\r
set = true;\r
} else {\r
locY--;\r
}\r
} else {\r
// Check for Bottom Warp\r
- if (locY == this.map.nrofblocks - 1) {\r
+ if (locY == this.m_map.m_nrofblocks - 1) {\r
point[0] = locX;\r
point[1] = 0;\r
set = true;\r
}\r
} else {\r
// left or right\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left \r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left \r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
if (direction == 3) {\r
// Check for Left Warp\r
if (locX == 0) {\r
- point[0] = this.map.nrofblocks - 1;\r
+ point[0] = this.m_map.m_nrofblocks - 1;\r
point[1] = locY;\r
set = true;\r
} else {\r
}\r
} else {\r
// Check for Right Warp\r
- if (locX == this.map.nrofblocks - 1) {\r
+ if (locX == this.m_map.m_nrofblocks - 1) {\r
point[0] = 0;\r
point[1] = locY;\r
set = true;\r
}\r
\r
public void doMove() {\r
- this.x += this.dx;\r
- this.y += this.dy;\r
- //this.dx = 0;\r
- //this.dy = 0;\r
+ this.m_locX += this.m_dx;\r
+ this.m_locY += this.m_dy;\r
+ this.m_dx = 0;\r
+ this.m_dy = 0;\r
+ //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");\r
}\r
}
\ No newline at end of file
\r
// Initiate the map\r
map.init();\r
- \r
+ //System.printString("Init finish\n");\r
int i = 0;\r
// create ghosts\r
- for(i = 0; i < map.nrofghosts; i++) {\r
+ for(i = 0; i < map.m_nrofghosts; i++) {\r
Ghost ghost = new Ghost(7, 7, map);\r
- ghost.setTarget(i%map.nrofpacs);\r
- ghost.index = i;\r
+ ghost.m_index = i;\r
map.placeGhost(ghost);\r
- map.targets[i] = ghost.target;\r
- map.ghosts[i] = ghost;\r
+ map.m_ghosts[i] = ghost;\r
}\r
// create pacmen\r
int tx = 14;\r
int ty = 14;\r
- for(i = 0; i < map.nrofpacs; i++) {\r
+ for(i = 0; i < map.m_nrofpacs; i++) {\r
Pacman pacman = new Pacman(5, 7, map);\r
pacman.setTarget(tx*(i/2), ty*(i%2));\r
- pacman.index = i;\r
+ pacman.m_index = i;\r
map.placePacman(pacman);\r
- map.desX[i] = tx*(i/2);\r
- map.desY[i] = ty*(i%2);\r
- map.pacmen[i] = pacman;\r
+ map.m_desX[i] = tx*(i/2);\r
+ map.m_desY[i] = ty*(i%2);\r
+ map.m_pacmen[i] = pacman;\r
//System.printString("destination: " + map.desX[i] + "," + map.desY[i] + "\n");\r
}\r
\r
- map.ghostcount = 0;\r
- map.paccount = 0;\r
+ map.m_ghostcount = 0;\r
+ map.m_paccount = 0;\r
\r
- while(map.nrofpacs > 0) {\r
+ while(map.m_nrofpacs > 0) {\r
// try to move ghost\r
- for(i = 0; i < map.nrofghosts; i++) {\r
- map.ghosts[i].tryMove();\r
+ for(i = 0; i < nrofghosts; i++) {\r
+ map.m_ghosts[i].tryMove();\r
}\r
// try to move pacmen\r
- for(i = 0; i < map.nrofpacs; i++) {\r
- map.pacmen[i].tryMove();\r
+ for(i = 0; i < nrofpacs; i++) {\r
+ if(map.m_pacMenX[i] != -1) {\r
+ map.m_pacmen[i].tryMove();\r
+ }\r
}\r
\r
// update ghosts\r
- for(i = 0; i < map.nrofghosts; i++) {\r
- map.ghosts[i].doMove();\r
- map.placeGhost(map.ghosts[i]);\r
+ for(i = 0; i < nrofghosts; i++) {\r
+ map.m_ghosts[i].doMove();\r
+ map.placeGhost(map.m_ghosts[i]);\r
}\r
- /*for(i = 0; i < map.nrofghosts; i++) {\r
- System.printString("(" + map.ghostsX[i] + "," + map.ghostsY[i] + ") ");\r
+ /*for(i = 0; i < nrofghosts; i++) {\r
+ System.printString("(" + map.m_ghostsX[i] + "," + map.m_ghostsY[i] + ") ");\r
}\r
System.printString("\n");*/\r
// update pacmen\r
- for(i = 0; i < map.nrofpacs; i++) {\r
- map.pacmen[i].doMove();\r
- map.placePacman(map.pacmen[i]);\r
- //System.printString("Pacman " + map.pacmen[i].index + ": (" + map.pacMenX[map.pacmen[i].index] + "," + map.pacMenY[map.pacmen[i].index] + ")\n");\r
- boolean death = map.check(map.pacmen[i]);\r
- /*if(death) {\r
- System.printString("Pacman " + map.pacmen[i].index + " caught!\n");\r
- }*/\r
+ for(i = 0; i < nrofpacs; i++) {\r
+ if(map.m_pacMenX[i] != -1) {\r
+ map.m_pacmen[i].doMove();\r
+ map.placePacman(map.m_pacmen[i]);\r
+ //System.printString("Pacman " + map.m_pacmen[i].m_index + ": (" + map.m_pacMenX[map.m_pacmen[i].m_index] + "," + map.m_pacMenY[map.m_pacmen[i].m_index] + ")\n");\r
+ boolean death = map.check(map.m_pacmen[i]);\r
+ /*if(death) {\r
+ System.printString("Pacman " + map.m_pacmen[i].m_index + " caught!\n");\r
+ }*/\r
+ }\r
}\r
- map.nrofpacs -= map.deathcount;\r
- //System.printString(map.nrofpacs + " pacmen left. \n");\r
+ map.m_nrofpacs -= map.m_deathcount;\r
+ //System.printString(map.m_nrofpacs + " pacmen left. \n");\r
\r
// reset for next run\r
- map.paccount = 0;\r
- map.deathcount = 0;\r
+ map.m_paccount = 0;\r
+ map.m_deathcount = 0;\r
}\r
\r
System.printString("Finish\n");\r
-public class Map { \r
- public int[] map;\r
- public int[] pacMenX;\r
- public int[] pacMenY;\r
- public int[] ghostsX;\r
- public int[] ghostsY;\r
- public int[] targets;\r
- public int[] desX;\r
- public int[] desY;\r
- public Ghost[] ghosts;\r
- public Pacman[] pacmen;\r
+public class Map {\r
+ // maze\r
+ private int m_nrofblocks;\r
+ public int[] m_map;\r
+ public Node[] m_mapNodes;\r
+ public Ghost[] m_ghosts;\r
+ public Pacman[] m_pacmen;\r
\r
- public int nrofghosts;\r
- public int nrofpacs;\r
- private int nrofblocks;\r
- //public boolean toupdate;\r
- public int ghostcount;\r
- public int paccount;\r
- public int deathcount;\r
+ // pacmen information\r
+ public int m_nrofpacs;\r
+ public int[] m_pacMenX;\r
+ public int[] m_pacMenY;\r
+ public int[] m_directions;\r
+ public int[] m_desX;\r
+ public int[] m_desY;\r
+ public int m_paccount;\r
+ public int m_deathcount;\r
\r
- public Random r;\r
+ // ghosts information\r
+ public int m_nrofghosts;\r
+ public int[] m_ghostsX;\r
+ public int[] m_ghostsY;\r
+ public int[] m_ghostdirections;\r
+ public int[] m_targets;\r
+ public int m_ghostcount;\r
+ \r
+ // helper member\r
+ public Random m_r;\r
\r
public Map(int nrofpacs, int nrofghosts) {\r
//System.printString("step 1\n");\r
- this.nrofblocks = 15;\r
- this.map = new int[this.nrofblocks*this.nrofblocks];\r
- this.nrofpacs = nrofpacs;\r
- this.nrofghosts = nrofghosts;\r
- this.pacMenX = new int[this.nrofpacs];\r
- this.pacMenY = new int[this.nrofpacs];\r
- this.ghostsX = new int[this.nrofghosts];\r
- this.ghostsY = new int[this.nrofghosts];\r
- this.targets = new int[this.nrofghosts];\r
- this.desX = new int[this.nrofpacs];\r
- this.desY = new int[this.nrofpacs];\r
- this.ghosts = new Ghost[this.nrofghosts];\r
- this.pacmen = new Pacman[this.nrofpacs];\r
- //this.toupdate = false;\r
- this.ghostcount = 0;\r
- this.paccount = 0;\r
- this.deathcount = 0;\r
- this.r = new Random();\r
+ this.m_nrofblocks = 15;\r
+ this.m_map = new int[this.m_nrofblocks*this.m_nrofblocks];\r
+ this.m_mapNodes = new Node[this.m_nrofblocks*this.m_nrofblocks];\r
+ \r
+ this.m_nrofpacs = nrofpacs;\r
+ this.m_pacMenX = new int[this.m_nrofpacs];\r
+ this.m_pacMenY = new int[this.m_nrofpacs];\r
+ this.m_directions = new int[this.m_nrofpacs];\r
+ this.m_desX = new int[this.m_nrofpacs];\r
+ this.m_desY = new int[this.m_nrofpacs];\r
+ this.m_paccount = 0;\r
+ this.m_deathcount = 0;\r
+ \r
+ this.m_nrofghosts = nrofghosts;\r
+ this.m_ghostsX = new int[this.m_nrofghosts];\r
+ this.m_ghostsY = new int[this.m_nrofghosts];\r
+ this.m_ghostdirections = new int[this.m_nrofghosts];\r
+ this.m_targets = new int[this.m_nrofghosts];\r
+ this.m_ghostcount = 0;\r
+ \r
+ this.m_ghosts = new Ghost[this.m_nrofghosts];\r
+ this.m_pacmen = new Pacman[this.m_nrofpacs];\r
+ \r
+ this.m_r = new Random();\r
+ \r
+ for(int i = 0; i < this.m_nrofblocks*this.m_nrofblocks; i++) {\r
+ this.m_map[i] = -1;\r
+ this.m_mapNodes[i] = new Node(i%this.m_nrofblocks, i/this.m_nrofblocks, i);\r
+ }\r
\r
//System.printString("step 2\n");\r
- for(int i = 0; i < this.nrofpacs; i++) {\r
- this.pacMenX[i] = this.pacMenY[i] = -1;\r
- this.desX[i] = this.desY[i] = -1;\r
- this.pacmen[i] = null;\r
+ for(int i = 0; i < this.m_nrofpacs; i++) {\r
+ this.m_pacMenX[i] = this.m_pacMenY[i] = -1;\r
+ this.m_desX[i] = this.m_desY[i] = -1;\r
+ this.m_pacmen[i] = null;\r
}\r
//System.printString("step 3\n");\r
- for(int i = 0; i < this.nrofghosts; i++) {\r
- this.ghostsX[i] = this.ghostsY[i] = -1;\r
- this.targets[i] = -1;\r
- this.ghosts[i] = null;\r
+ for(int i = 0; i < this.m_nrofghosts; i++) {\r
+ this.m_ghostsX[i] = this.m_ghostsY[i] = -1;\r
+ this.m_targets[i] = -1;\r
+ this.m_ghosts[i] = null;\r
}\r
//System.printString("step 4\n");\r
}\r
\r
public void init() {\r
+ // initilize the maze\r
int i = 0;\r
- this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;this.map[i++]=9;this.map[i++]=12;this.map[i++]=3;this.map[i++]=10;this.map[i++]=6;this.map[i++]=9;this.map[i++]=12;this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;\r
- this.map[i++]=5;this.map[i++]=11;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=15;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=14;this.map[i++]=5;\r
- this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=6;this.map[i++]=1;this.map[i++]=10;this.map[i++]=4;this.map[i++]=3;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;\r
- this.map[i++]=5;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=6;this.map[i++]=5;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=5;this.map[i++]=3;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=5;\r
- this.map[i++]=5;this.map[i++]=9;this.map[i++]=8;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=8;this.map[i++]=12;this.map[i++]=5;\r
- this.map[i++]=9;this.map[i++]=2;this.map[i++]=10;this.map[i++]=2;this.map[i++]=8;this.map[i++]=2;this.map[i++]=12;this.map[i++]=5;this.map[i++]=9;this.map[i++]=2;this.map[i++]=8;this.map[i++]=2;this.map[i++]=10;this.map[i++]=2;this.map[i++]=12;\r
- this.map[i++]=6;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=11;this.map[i++]=8;this.map[i++]=14;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=3;\r
- this.map[i++]=4;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=10;this.map[i++]=10;this.map[i++]=10;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=1;\r
- this.map[i++]=12;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=10;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=9;\r
- this.map[i++]=3;this.map[i++]=8;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=0;this.map[i++]=10;this.map[i++]=2;this.map[i++]=10;this.map[i++]=0;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=8;this.map[i++]=6;\r
- this.map[i++]=5;this.map[i++]=3;this.map[i++]=2;this.map[i++]=2;this.map[i++]=6;this.map[i++]=5;this.map[i++]=15;this.map[i++]=5;this.map[i++]=15;this.map[i++]=5;this.map[i++]=3;this.map[i++]=2;this.map[i++]=2;this.map[i++]=6;this.map[i++]=5;\r
- this.map[i++]=5;this.map[i++]=9;this.map[i++]=8;this.map[i++]=8;this.map[i++]=4;this.map[i++]=1;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=4;this.map[i++]=1;this.map[i++]=8;this.map[i++]=8;this.map[i++]=12;this.map[i++]=5;\r
- this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=2;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;\r
- this.map[i++]=5;this.map[i++]=11;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=8;this.map[i++]=6;this.map[i++]=13;this.map[i++]=3;this.map[i++]=8;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=14;this.map[i++]=5;\r
- this.map[i++]=9;this.map[i++]=10;this.map[i++]=10;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=10;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=10;this.map[i++]=10;this.map[i++]=12; // 15*15 \r
+ this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;\r
+ this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=15;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=5;\r
+ this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=6;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=3;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;\r
+ this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=5;\r
+ this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=8;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=8;this.m_map[i++]=12;this.m_map[i++]=5;\r
+ this.m_map[i++]=9;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=8;this.m_map[i++]=2;this.m_map[i++]=12;this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=2;this.m_map[i++]=8;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=12;\r
+ this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=8;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=3;\r
+ this.m_map[i++]=4;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=1;\r
+ this.m_map[i++]=12;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=10;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=9;\r
+ this.m_map[i++]=3;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=0;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=0;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=6;\r
+ this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=2;this.m_map[i++]=2;this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=15;this.m_map[i++]=5;this.m_map[i++]=15;this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=2;this.m_map[i++]=2;this.m_map[i++]=6;this.m_map[i++]=5;\r
+ this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=8;this.m_map[i++]=8;this.m_map[i++]=4;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=1;this.m_map[i++]=8;this.m_map[i++]=8;this.m_map[i++]=12;this.m_map[i++]=5;\r
+ this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=2;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;\r
+ this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=6;this.m_map[i++]=13;this.m_map[i++]=3;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=5;\r
+ this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=12; // 15*15\r
+ \r
+ // initilize the graph of the maze\r
+ for(i = 0; i < this.m_nrofblocks*this.m_nrofblocks; i++) {\r
+ int tmp = this.m_map[i];\r
+ Node tmpNode = this.m_mapNodes[i];\r
+ int locX = tmpNode.getXLoc();\r
+ int locY = tmpNode.getYLoc();\r
+ if((int)(tmp & 1) == 0) {\r
+ // can go left\r
+ if(locX == 0) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[locY * this.m_nrofblocks + this.m_nrofblocks - 1]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[i - 1]);\r
+ }\r
+ } \r
+ if((int)(tmp & 2) == 0) {\r
+ // can go up\r
+ if(locY == 0) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[(this.m_nrofblocks - 1) * this.m_nrofblocks + locX]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[(locY - 1) * this.m_nrofblocks + locX]);\r
+ }\r
+ }\r
+ if((int)(tmp & 4) == 0) {\r
+ // can go right\r
+ if(locX == this.m_nrofblocks - 1) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[locY * this.m_nrofblocks]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[i + 1]);\r
+ }\r
+ }\r
+ if((int)(tmp & 8) == 0) {\r
+ // can go down\r
+ if(locY == this.m_nrofblocks - 1) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[locX]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[(locY + 1) * this.m_nrofblocks + locX]);\r
+ }\r
+ }\r
+ }\r
} \r
\r
public void placePacman(Pacman t) {\r
- this.pacMenX[t.index] = t.x;\r
- this.pacMenY[t.index] = t.y;\r
- //this.map[t.y * this.nrofblocks + t.x - 1] |= 16;\r
- this.paccount++;\r
+ this.m_pacMenX[t.m_index] = t.m_locX;\r
+ this.m_pacMenY[t.m_index] = t.m_locY;\r
+ this.m_paccount++;\r
}\r
\r
public void placeGhost(Ghost t) {\r
- this.ghostsX[t.index] = t.x;\r
- this.ghostsY[t.index] = t.y;\r
- //this.map[t.y * this.nrofblocks + t.x - 1] |= 32;\r
- this.ghostcount++;\r
+ this.m_ghostsX[t.m_index] = t.m_locX;\r
+ this.m_ghostsY[t.m_index] = t.m_locY;\r
+ this.m_ghostcount++;\r
}\r
\r
public boolean check(Pacman t) {\r
boolean death = false;\r
int i = 0;\r
- while((!death) && (i < this.nrofghosts)) {\r
- if((t.x == this.ghostsX[i]) && (t.y == this.ghostsY[i])) {\r
+ while((!death) && (i < this.m_ghostsX.length)) {\r
+ if((t.m_locX == this.m_ghostsX[i]) && (t.m_locY == this.m_ghostsY[i])) {\r
death = true;\r
}\r
i++;\r
}\r
- if((!death) && (t.x == t.tx) && (t.y == t.ty)) {\r
+ if((!death) && (t.m_locX == t.m_tx) && (t.m_locY == t.m_ty)) {\r
// reach the destination\r
//System.printString("Hit destination!\n");\r
death = true;\r
if(death) {\r
// pacman caught by ghost\r
// set pacman as death\r
- t.death = true;\r
+ t.m_death = true;\r
// kick it out\r
- //this.map[t.y * this.nrofblocks + t.x - 1] -= 16;\r
- this.deathcount++;\r
- this.pacMenX[t.index] = -1;\r
- this.pacMenY[t.index] = -1;\r
+ //this.m_map[t.y * this.m_nrofblocks + t.x - 1] -= 16;\r
+ this.m_deathcount++;\r
+ this.m_pacMenX[t.m_index] = -1;\r
+ this.m_pacMenY[t.m_index] = -1;\r
}\r
return death;\r
}\r
\r
public boolean isfinish() {\r
- return nrofpacs == 0;\r
+ return this.m_nrofpacs == 0;\r
}\r
}
\ No newline at end of file
--- /dev/null
+public class Node {
+
+ int m_locX;
+ int m_locY;
+ int m_index;
+ Vector m_neighbours;
+
+ public Node(int locX, int locY, int index) {
+ this.m_locX = locX;
+ this.m_locY = locY;
+ this.m_index = index;
+ this.m_neighbours = new Vector();
+ }
+
+ public void addNeighbour(Node n) {
+ this.m_neighbours.addElement(n);
+ }
+
+ public Vector getNeighbours() {
+ return this.m_neighbours;
+ }
+
+ public int getXLoc() {
+ return this.m_locX;
+ }
+
+ public int getYLoc() {
+ return this.m_locY;
+ }
+
+ public int getIndex() {
+ return this.m_index;
+ }
+}
\ No newline at end of file
public class Pacman {\r
- public int x;\r
- public int y;\r
- public boolean death;\r
- public int index;\r
- public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
- int dx;\r
- int dy;\r
- public int tx;\r
- public int ty;\r
- int destinationX;\r
- int destinationY;\r
- Map map;\r
+ public int m_locX;\r
+ public int m_locY;\r
+ public boolean m_death;\r
+ public int m_index;\r
+ public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
+ int m_dx;\r
+ int m_dy;\r
+ public int m_tx;\r
+ public int m_ty;\r
+ Map m_map;\r
\r
public Pacman(int x, int y, Map map) {\r
- this.x = x;\r
- this.y = y;\r
- this.dx = this.dy = 0;\r
- this.death = false;\r
- this.index = -1;\r
- this.tx = this.ty = -1;\r
- this.direction = 0;\r
- this.destinationX = -1;\r
- this.destinationY = -1;\r
- this.map = map;\r
+ this.m_locX = x;\r
+ this.m_locY = y;\r
+ this.m_dx = this.m_dy = 0;\r
+ this.m_death = false;\r
+ this.m_index = -1;\r
+ this.m_tx = this.m_ty = -1;\r
+ this.m_direction = 0;\r
+ this.m_map = map;\r
}\r
\r
public void setTarget(int x, int y) {\r
- this.tx = x;\r
- this.ty = y;\r
+ this.m_tx = x;\r
+ this.m_ty = y;\r
}\r
\r
public void tryMove() {\r
// decide dx & dy\r
\r
- // Don't let the pacman go back the way it came.\r
- int prevDirection = 0;\r
-\r
- // If there is a destination, then check if the destination has been reached.\r
- if (destinationX >= 0 && destinationY >= 0) {\r
- // Check if the destination has been reached, if so, then\r
- // get new destination.\r
- if (destinationX == x && destinationY == y) {\r
- destinationX = -1;\r
- destinationY = -1;\r
- prevDirection = direction;\r
- } else {\r
- // Otherwise, we haven't reached the destionation so\r
- // continue in same direction.\r
- return;\r
- }\r
- }\r
- setNextDirection (prevDirection);\r
+ // find the shortest possible way to the chosen target\r
+ setNextDirection();\r
}\r
\r
- private void setNextDirection(int prevDirection) {\r
+ private void setNextDirection() {\r
+ // current position of the ghost\r
+ Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];\r
+ \r
// get target's position\r
- int targetx = this.tx;\r
- //System.printString("aaa\n");\r
- int targety = this.ty;\r
+ int targetx = this.m_tx;\r
+ int targety = this.m_ty;\r
int[] nextLocation = new int[2];\r
nextLocation[0] = nextLocation[1] = -1;\r
\r
- //System.printString("bbb\n");\r
- getDestination (this.direction, targetx, targety, nextLocation);\r
- targetx = nextLocation[0];\r
- targety = nextLocation[1];\r
+ // target's position\r
+ Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];\r
\r
- //System.printString("step 2\n");\r
- // check the distance\r
- int deltax = this.x - targetx; // <0: move right; >0: move left\r
- int deltay = this.y - targety; // <0: move down; >0: move up\r
- // decide the priority of four moving directions\r
- int[] bestDirection = new int[4];\r
- //System.printString("dx: " + deltax + "; dy: " + deltay + "\n");\r
- if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) {\r
- // go first along y\r
- if(deltay > 0) {\r
- bestDirection[0] = 1;\r
- bestDirection[3] = 2;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
+ // breadth-first traverse the graph view of the maze\r
+ // check the shortest path for the start node to the end node\r
+ boolean set = false;\r
+ Vector cuts = new Vector();\r
+ int tmpdx = 0;\r
+ int tmpdy = 0;\r
+ int tmpdirection = 0;\r
+ boolean first = true;\r
+ while(!set) {\r
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];\r
+ for(int i = 0; i < parents.length; i++) {\r
+ parents[i] = -1;\r
+ }\r
+ if(!BFS(start, end, parents, cuts)) {\r
+ this.m_dx = tmpdx;\r
+ this.m_dy = tmpdy;\r
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;\r
+ set = true;\r
+ //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");\r
} else {\r
- bestDirection[0] = 2;\r
- bestDirection[3] = 1;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
+ // Reversely go over the parents array to find the next node to reach\r
+ boolean found = false;\r
+ int index = end.getIndex();\r
+ while(!found) {\r
+ int parent = parents[index];\r
+ if(parent == start.getIndex()) {\r
+ found = true;\r
+ } else {\r
+ index = parent;\r
+ }\r
}\r
- }\r
- } else {\r
- if(deltax > 0) {\r
- bestDirection[0] = 3;\r
- bestDirection[3] = 4;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+\r
+ // set the chase direction\r
+ int nx = this.m_map.m_mapNodes[index].getXLoc();\r
+ int ny = this.m_map.m_mapNodes[index].getYLoc();\r
+ this.m_dx = nx - this.m_locX;\r
+ this.m_dy = ny - this.m_locY;\r
+ if(this.m_dx > 0) {\r
+ // right\r
+ this.m_direction = 4;\r
+ } else if(this.m_dx < 0) {\r
+ // left\r
+ this.m_direction = 3;\r
+ } else if(this.m_dy > 0) {\r
+ // down\r
+ this.m_direction = 2;\r
+ } else if(this.m_dy < 0) {\r
+ // up\r
+ this.m_direction = 1;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ // still\r
+ this.m_direction = 0;\r
}\r
- } else {\r
- bestDirection[0] = 4;\r
- bestDirection[3] = 3;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+ if(first) {\r
+ tmpdx = this.m_dx;\r
+ tmpdy = this.m_dy;\r
+ tmpdirection = this.m_direction;\r
+ first = false;\r
+ //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");\r
+ }\r
+\r
+ // check if this choice follows some other ghosts' path\r
+ if(canFlee()) {\r
+ this.m_map.m_directions[this.m_index] = this.m_direction;\r
+ set = true;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ cuts.addElement(new Integer(index));\r
+ /*for( int h = 0; h < cuts.size(); h++) {\r
+ System.printString(cuts.elementAt(h) + ", ");\r
+ }\r
+ System.printString("\n");*/\r
}\r
}\r
}\r
- /*for(int i = 0; i < 4; i++) {\r
- System.printString(bestDirection[i] + ",");\r
+ }\r
+ \r
+ // This methos do BFS from start node to end node\r
+ // If there is a path from start to end, return true; otherwise, return false\r
+ // Array parents records parent for a node in the BFS search, \r
+ // the last item of parents records the least steps to reach end node from start node\r
+ // Vector cuts specifies which nodes can not be the first one to access in this BFS\r
+ private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {\r
+ int steps = 0;\r
+ Vector toaccess = new Vector();\r
+ toaccess.addElement(start);\r
+ while(toaccess.size() > 0) {\r
+ // pull out the first one to access\r
+ Node access = (Node)toaccess.elementAt(0);\r
+ toaccess.removeElementAt(0);\r
+ if(access.getIndex() == end.getIndex()) {\r
+ // hit the end node\r
+ parents[parents.length - 1] = steps;\r
+ return true;\r
+ }\r
+ steps++;\r
+ Vector neighbours = access.getNeighbours();\r
+ for(int i = 0; i < neighbours.size(); i++) {\r
+ Node neighbour = (Node)neighbours.elementAt(i);\r
+ if(parents[neighbour.getIndex()] == -1) {\r
+ // not accessed\r
+ boolean ignore = false;\r
+ if(access.getIndex() == start.getIndex()) {\r
+ // start node, check if the neighbour node is in cuts\r
+ int j = 0;\r
+ while((!ignore) && (j < cuts.size())) {\r
+ int tmp = ((Integer)cuts.elementAt(j)).intValue();\r
+ if(tmp == neighbour.getIndex()) {\r
+ ignore = true;\r
+ }\r
+ j++;\r
+ }\r
+ }\r
+ if(!ignore) {\r
+ parents[neighbour.getIndex()] = access.getIndex();\r
+ toaccess.addElement(neighbour);\r
+ }\r
+ }\r
+ }\r
}\r
- System.printString("\n");*/\r
+ parents[parents.length - 1] = -1;\r
+ return false;\r
+ }\r
+ \r
+ // This method returns true if this pacmen can flee in this direction.\r
+ private boolean canFlee () {\r
+ int steps = 0;\r
+ int locX = this.m_locX;\r
+ int locY = this.m_locY;\r
+ int[] point = new int[2];\r
+ point[0] = point[1] = -1;\r
\r
- // There's a 50% chance that the ghost will try the sub-optimal direction first.\r
- // This will keep the ghosts from following each other and to trap Pacman.\r
- if (this.map.r.nextDouble() < .50) { \r
- int temp = bestDirection[0];\r
- bestDirection[0] = bestDirection[1];\r
- bestDirection[1] = temp;\r
+ // Start off by advancing one in direction for specified location\r
+ if (this.m_direction == 1) {\r
+ // up\r
+ locY--;\r
+ } else if (this.m_direction == 2) {\r
+ // down\r
+ locY++;\r
+ } else if (this.m_direction == 3) {\r
+ // left\r
+ locX--;\r
+ } else if (this.m_direction == 4) {\r
+ // right\r
+ locX++;\r
}\r
- \r
- //System.printString("step 3\n");\r
- // try to move one by one\r
- int i = 0;\r
+ steps++; \r
+ \r
boolean set = false;\r
- this.dx = 0;\r
- this.dy = 0;\r
- while((!set) && (i < 4)) {\r
- if(bestDirection[i] == 1) {\r
- // try to move up\r
- if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) {\r
- //System.printString("a\n");\r
- if (getDestination (1, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = -1;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 2) {\r
- // try to move down\r
- if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) {\r
- //System.printString("b\n");\r
- if (getDestination (2, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = 1;\r
- set = true;\r
+ // Determine next turning location.\r
+ while (!set) {\r
+ if (this.m_direction == 1 || this.m_direction == 2) { \r
+ // up or down\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down\r
+ point[0] = locX;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ if (this.m_direction == 1) {\r
+ // Check for Top Warp\r
+ if (locY == 0) {\r
+ point[0] = locX;\r
+ point[1] = this.m_map.m_nrofblocks - 1;\r
+ set = true;\r
+ } else {\r
+ locY--;\r
+ steps++;\r
+ }\r
+ } else {\r
+ // Check for Bottom Warp\r
+ if (locY == this.m_map.m_nrofblocks - 1) {\r
+ point[0] = locX;\r
+ point[1] = 0;\r
+ set = true;\r
+ } else {\r
+ locY++;\r
+ steps++;\r
+ }\r
}\r
}\r
- } else if (bestDirection[i] == 3) {\r
- // try to move left\r
- if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) {\r
- //System.printString("c\n");\r
- if (getDestination (3, this.x, this.y, nextLocation)) {\r
- this.dx = -1;\r
- this.dy = 0;\r
- set = true;\r
+ } else {\r
+ // left or right\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left \r
+ point[0] = locX;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ if (this.m_direction == 3) {\r
+ // Check for Left Warp\r
+ if (locX == 0) {\r
+ point[0] = this.m_map.m_nrofblocks - 1;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ locX--;\r
+ steps++;\r
+ }\r
+ } else {\r
+ // Check for Right Warp\r
+ if (locX == this.m_map.m_nrofblocks - 1) {\r
+ point[0] = 0;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ locX++;\r
+ steps++;\r
+ }\r
}\r
}\r
- } else if (bestDirection[i] == 4) {\r
- // try to move right\r
- if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) {\r
- //System.printString("d\n");\r
- if (getDestination (4, this.x, this.y, nextLocation)) {\r
- this.dx = 1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
+ }\r
+ }\r
+ \r
+ // check the least steps for the ghosts to reach point location\r
+ int chasesteps = -1;\r
+ Node end = this.m_map.m_mapNodes[point[1] * this.m_map.m_nrofblocks + point[0]];\r
+ for(int i = 0; i < this.m_map.m_ghostsX.length; i++) {\r
+ Node start = this.m_map.m_mapNodes[this.m_map.m_ghostsY[i] * this.m_map.m_nrofblocks + this.m_map.m_ghostsX[i]];\r
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];\r
+ for(int j = 0; j < parents.length; j++) {\r
+ parents[j] = -1;\r
+ }\r
+ if(BFS(start, end, parents, new Vector())) {\r
+ if((chasesteps == -1) ||\r
+ (chasesteps > parents[parents.length - 1])) {\r
+ chasesteps = parents[parents.length - 1];\r
}\r
}\r
- i++;\r
}\r
- //System.printString("step 4\n");\r
+\r
+ return ((chasesteps == -1) || (steps < chasesteps));\r
}\r
\r
// This method will take the specified location and direction and determine\r
// for the given location if the thing moved in that direction, what the\r
// next possible turning location would be.\r
- boolean getDestination (int direction, int locX, int locY, int[] point) {\r
+ private boolean getDestination (int direction, int locX, int locY, int[] point) {\r
// If the request direction is blocked by a wall, then just return the current location\r
- if ((direction == 1 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up\r
- (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left\r
- (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down\r
- (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right \r
+ if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up\r
+ ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left\r
+ ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down\r
+ ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right \r
point[0] = locX;\r
point[1] = locY;\r
return false;\r
// then return false.\r
if (locY < 0 ||\r
locX < 0 ||\r
- locY == this.map.nrofblocks ||\r
- locX == this.map.nrofblocks) {\r
+ locY == this.m_map.m_nrofblocks ||\r
+ locX == this.m_map.m_nrofblocks) {\r
return false;\r
}\r
\r
boolean set = false;\r
- // Determine next turning location..\r
+ // Determine next turning location.\r
while (!set) {\r
if (direction == 1 || direction == 2) { \r
// up or down\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // down\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down\r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
// Check for Top Warp\r
if (locY == 0) {\r
point[0] = locX;\r
- point[1] = this.map.nrofblocks - 1;\r
+ point[1] = this.m_map.m_nrofblocks - 1;\r
set = true;\r
} else {\r
locY--;\r
}\r
} else {\r
// Check for Bottom Warp\r
- if (locY == this.map.nrofblocks - 1) {\r
+ if (locY == this.m_map.m_nrofblocks - 1) {\r
point[0] = locX;\r
point[1] = 0;\r
set = true;\r
}\r
} else {\r
// left or right\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left \r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left \r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
if (direction == 3) {\r
// Check for Left Warp\r
if (locX == 0) {\r
- point[0] = this.map.nrofblocks - 1;\r
+ point[0] = this.m_map.m_nrofblocks - 1;\r
point[1] = locY;\r
set = true;\r
} else {\r
}\r
} else {\r
// Check for Right Warp\r
- if (locX == this.map.nrofblocks - 1) {\r
+ if (locX == this.m_map.m_nrofblocks - 1) {\r
point[0] = 0;\r
point[1] = locY;\r
set = true;\r
}\r
\r
public void doMove() {\r
- //System.printString("dx: " + this.dx + ", dy: " + this.dy + "\n");\r
- this.x += this.dx;\r
- this.y += this.dy;\r
- //this.dx = 0;\r
- //this.dy = 0;\r
+ this.m_locX += this.m_dx;\r
+ this.m_locY += this.m_dy;\r
+ this.m_dx = 0;\r
+ this.m_dy = 0;\r
+ //System.printString("Pacmen " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");\r
}\r
}
\ No newline at end of file
-public class Ghost {\r
- flag move;\r
- flag update;\r
-\r
- public int x;\r
- public int y;\r
- public int index;\r
- public int target;\r
- public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
- int dx;\r
- int dy;\r
- int destinationX;\r
- int destinationY;\r
- Map map;\r
- \r
- public Ghost(int x, int y, Map map) {\r
- this.x = x;\r
- this.y = y;\r
- this.dx = this.dy = 0;\r
- this.index = -1;\r
- this.target = -1;\r
- this.direction = 0;\r
- this.destinationX = -1;\r
- this.destinationY = -1;\r
- this.map = map;\r
- }\r
- \r
- public void setTarget(int pacman) {\r
- this.target = pacman;\r
- }\r
- \r
- // 0:still, 1:up, 2:down, 3:left, 4:right\r
- public void tryMove() {\r
- //System.printString("step 1\n");\r
- //System.printString("target: " + this.target + "\n");\r
- \r
- // Don't let the ghost go back the way it came.\r
- int prevDirection = 0;\r
-\r
- // If there is a destination, then check if the destination has been reached.\r
- if (destinationX >= 0 && destinationY >= 0) {\r
- // Check if the destination has been reached, if so, then\r
- // get new destination.\r
- if (destinationX == x && destinationY == y) {\r
- destinationX = -1;\r
- destinationY = -1;\r
- prevDirection = direction;\r
- } else {\r
- // Otherwise, we haven't reached the destionation so\r
- // continue in same direction.\r
- return;\r
- }\r
- }\r
- setNextDirection (prevDirection);\r
- }\r
- \r
- private void setNextDirection(int prevDirection) {\r
- // get target's position\r
- int targetx = this.map.pacMenX[this.target];\r
- //System.printString("aaa\n");\r
- int targety = this.map.pacMenY[this.target];\r
- int[] nextLocation = new int[2];\r
- nextLocation[0] = nextLocation[1] = -1;\r
- \r
- //System.printString("bbb\n");\r
- if(targetx == -1) {\r
- //System.printString("a\n");\r
- // already kicked off, choose another target\r
- int i = 0;\r
- boolean found = false;\r
- while((!found) && (i < map.pacMenX.length)) {\r
- if(this.map.pacMenX[i] != -1) {\r
- this.target = i;\r
- targetx = this.map.pacMenX[i];\r
- targety = this.map.pacMenY[i];\r
- this.map.targets[i] = this.target;\r
- found = true;\r
- }\r
- i++;\r
- }\r
- //System.printString("b\n");\r
- if(i == this.map.pacMenX.length) {\r
- //System.printString("c\n");\r
- // no more pacmen to chase\r
- this.dx = 0;\r
- this.dy = 0;\r
- this.direction = 0;\r
- return;\r
- }\r
- //System.printString("d\n");\r
- }\r
- getDestination (this.map.directions[this.target], targetx, targety, nextLocation);\r
- targetx = nextLocation[0];\r
- targety = nextLocation[1];\r
- \r
- //System.printString("step 2\n");\r
- // check the distance\r
- int deltax = this.x - targetx; // <0: move right; >0: move left\r
- int deltay = this.y - targety; // <0: move down; >0: move up\r
- // decide the priority of four moving directions\r
- int[] bestDirection = new int[4];\r
- //System.printString("dx: " + deltax + "; dy: " + deltay + "\n");\r
- if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) {\r
- // go first along y\r
- if(deltay > 0) {\r
- bestDirection[0] = 1;\r
- bestDirection[3] = 2;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
- } else {\r
- bestDirection[0] = 2;\r
- bestDirection[3] = 1;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
- }\r
- } else {\r
- if(deltax > 0) {\r
- bestDirection[0] = 3;\r
- bestDirection[3] = 4;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
- } else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
- }\r
- } else {\r
- bestDirection[0] = 4;\r
- bestDirection[3] = 3;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
- } else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
- }\r
- }\r
- }\r
- /*for(int i = 0; i < 4; i++) {\r
- System.printString(bestDirection[i] + ",");\r
- }\r
- System.printString("\n");*/\r
- \r
- // There's a 50% chance that the ghost will try the sub-optimal direction first.\r
- // This will keep the ghosts from following each other and to trap Pacman.\r
- if (this.map.r.nextDouble() < .50) { \r
- int temp = bestDirection[0];\r
- bestDirection[0] = bestDirection[1];\r
- bestDirection[1] = temp;\r
- }\r
- \r
- //System.printString("step 3\n");\r
- // try to move one by one\r
- int i = 0;\r
- boolean set = false;\r
- this.dx = 0;\r
- this.dy = 0;\r
- while((!set) && (i < 4)) {\r
- if(bestDirection[i] == 1) {\r
- // try to move up\r
- if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) {\r
- //System.printString("a\n");\r
- if (getDestination (1, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = -1;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 2) {\r
- // try to move down\r
- if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) {\r
- //System.printString("b\n");\r
- if (getDestination (2, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = 1;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 3) {\r
- // try to move left\r
- if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) {\r
- //System.printString("c\n");\r
- if (getDestination (3, this.x, this.y, nextLocation)) {\r
- this.dx = -1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 4) {\r
- // try to move right\r
- if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) {\r
- //System.printString("d\n");\r
- if (getDestination (4, this.x, this.y, nextLocation)) {\r
- this.dx = 1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
- }\r
- }\r
- i++;\r
- }\r
- //System.printString("step 4\n");\r
- }\r
- \r
- // This method will take the specified location and direction and determine\r
- // for the given location if the thing moved in that direction, what the\r
- // next possible turning location would be.\r
- boolean getDestination (int direction, int locX, int locY, int[] point) {\r
- // If the request direction is blocked by a wall, then just return the current location\r
- if ((direction == 1 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up\r
- (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left\r
- (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down\r
- (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right \r
- point[0] = locX;\r
- point[1] = locY;\r
- return false;\r
- }\r
- \r
- // Start off by advancing one in direction for specified location\r
- if (direction == 1) {\r
- // up\r
- locY--;\r
- } else if (direction == 2) {\r
- // down\r
- locY++;\r
- } else if (direction == 3) {\r
- // left\r
- locX--;\r
- } else if (direction == 4) {\r
- // right\r
- locX++;\r
- }\r
- \r
- // If we violate the grid boundary,\r
- // then return false.\r
- if (locY < 0 ||\r
- locX < 0 ||\r
- locY == this.map.nrofblocks ||\r
- locX == this.map.nrofblocks) {\r
- return false;\r
- }\r
- \r
- boolean set = false;\r
- // Determine next turning location..\r
- while (!set) {\r
- if (direction == 1 || direction == 2) { \r
- // up or down\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // down\r
- point[0] = locX;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- if (direction == 1) {\r
- // Check for Top Warp\r
- if (locY == 0) {\r
- point[0] = locX;\r
- point[1] = this.map.nrofblocks - 1;\r
- set = true;\r
- } else {\r
- locY--;\r
- }\r
- } else {\r
- // Check for Bottom Warp\r
- if (locY == this.map.nrofblocks - 1) {\r
- point[0] = locX;\r
- point[1] = 0;\r
- set = true;\r
- } else {\r
- locY++;\r
- }\r
- }\r
- }\r
- } else {\r
- // left or right\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left \r
- point[0] = locX;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- if (direction == 3) {\r
- // Check for Left Warp\r
- if (locX == 0) {\r
- point[0] = this.map.nrofblocks - 1;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- locX--;\r
- }\r
- } else {\r
- // Check for Right Warp\r
- if (locX == this.map.nrofblocks - 1) {\r
- point[0] = 0;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- locX++;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
- \r
- public void doMove() {\r
- this.x += this.dx;\r
- this.y += this.dy;\r
- //this.dx = 0;\r
- //this.dy = 0;\r
- }\r
-}\r
+public class Ghost {
+ flag move;
+ flag update;
+
+ public int m_locX;
+ public int m_locY;
+ public int m_index;
+ public int m_target;
+ public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
+ int m_dx;
+ int m_dy;
+ Map m_map;
+
+ public Ghost(int x, int y, Map map) {
+ this.m_locX = x;
+ this.m_locY = y;
+ this.m_dx = this.m_dy = 0;
+ this.m_index = -1;
+ this.m_target = -1;
+ this.m_direction = 0;
+ this.m_map = map;
+ }
+
+ // 0:still, 1:up, 2:down, 3:left, 4:right
+ public void tryMove() {
+ //System.printString("step 1\n");
+ int i = 0;
+
+ // check the nearest pacman and set it as current target
+ this.m_target = -1;
+ int deltaX = this.m_map.m_nrofblocks;
+ int deltaY = this.m_map.m_nrofblocks;
+ int distance = deltaX * deltaX + deltaY * deltaY;
+ for(i = 0; i < this.m_map.m_nrofpacs; i++) {
+ if(this.m_map.m_pacMenX[i] != -1) {
+ int dx = this.m_locX - this.m_map.m_pacMenX[i];
+ int dy = this.m_locY - this.m_map.m_pacMenY[i];
+ int dd = dx*dx+dy*dy;
+ if(distance > dd) {
+ this.m_target = i;
+ distance = dd;
+ deltaX = dx;
+ deltaY = dy;
+ }
+ }
+ }
+ // System.printString("target: " + this.m_target + "\n");
+
+ if(this.m_target == -1) {
+ // no more pacmen to chase, stay still
+ this.m_dx = 0;
+ this.m_dy = 0;
+ this.m_direction = this.m_map.m_ghostdirections[this.m_index] = 0;
+ return;
+ }
+
+ // find the shortest way to the chosen target
+ setNextDirection();
+ }
+
+ private void setNextDirection() {
+ // current position of the ghost
+ Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];
+
+ // get target's position
+ int targetx = this.m_map.m_pacMenX[this.m_target];
+ int targety = this.m_map.m_pacMenY[this.m_target];
+ int[] nextLocation = new int[2];
+ nextLocation[0] = nextLocation[1] = -1;
+ // check the target pacman's possible destination
+ getDestination (this.m_map.m_directions[this.m_target], targetx, targety, nextLocation);
+ targetx = nextLocation[0];
+ targety = nextLocation[1];
+ // target's position
+ Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];
+ // reset the target as index of the end node
+ this.m_target = this.m_map.m_targets[this.m_index] = end.getIndex();
+
+ // breadth-first traverse the graph view of the maze
+ // check the shortest path for the start node to the end node
+ boolean set = false;
+ Vector cuts = new Vector();
+ int tmpdx = 0;
+ int tmpdy = 0;
+ int tmpdirection = 0;
+ boolean first = true;
+ while(!set) {
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks];
+ for(int i = 0; i < parents.length; i++) {
+ parents[i] = -1;
+ }
+ if(!BFS(start, end, parents, cuts)) {
+ this.m_dx = tmpdx;
+ this.m_dy = tmpdy;
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
+ set = true;
+ //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
+ } else {
+ // Reversely go over the parents array to find the next node to reach
+ boolean found = false;
+ int index = end.getIndex();
+ while(!found) {
+ int parent = parents[index];
+ if(parent == start.getIndex()) {
+ found = true;
+ } else {
+ index = parent;
+ }
+ }
+
+ // set the chase direction
+ int nx = this.m_map.m_mapNodes[index].getXLoc();
+ int ny = this.m_map.m_mapNodes[index].getYLoc();
+ this.m_dx = nx - this.m_locX;
+ this.m_dy = ny - this.m_locY;
+ if(this.m_dx > 0) {
+ // right
+ this.m_direction = 4;
+ } else if(this.m_dx < 0) {
+ // left
+ this.m_direction = 3;
+ } else if(this.m_dy > 0) {
+ // down
+ this.m_direction = 2;
+ } else if(this.m_dy < 0) {
+ // up
+ this.m_direction = 1;
+ } else {
+ // still
+ this.m_direction = 0;
+ }
+ if(first) {
+ tmpdx = this.m_dx;
+ tmpdy = this.m_dy;
+ tmpdirection = this.m_direction;
+ first = false;
+ //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
+ }
+
+ // check if this choice follows some other ghosts' path
+ if(!isFollowing()) {
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction;
+ set = true;
+ } else {
+ cuts.addElement(new Integer(index));
+ /*for( int h = 0; h < cuts.size(); h++) {
+ System.printString(cuts.elementAt(h) + ", ");
+ }
+ System.printString("\n");*/
+ }
+ }
+ }
+ }
+
+ // This methos do BFS from start node to end node
+ // If there is a path from start to end, return true; otherwise, return false
+ // Array parents records parent for a node in the BFS search
+ // Vector cuts specifies which nodes can not be the first one to access in this BFS
+ private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {
+ Vector toaccess = new Vector();
+ toaccess.addElement(start);
+ while(toaccess.size() > 0) {
+ // pull out the first one to access
+ Node access = (Node)toaccess.elementAt(0);
+ toaccess.removeElementAt(0);
+ if(access.getIndex() == end.getIndex()) {
+ // hit the end node
+ return true;
+ }
+ Vector neighbours = access.getNeighbours();
+ for(int i = 0; i < neighbours.size(); i++) {
+ Node neighbour = (Node)neighbours.elementAt(i);
+ if(parents[neighbour.getIndex()] == -1) {
+ // not accessed
+ boolean ignore = false;
+ if(access.getIndex() == start.getIndex()) {
+ // start node, check if the neighbour node is in cuts
+ int j = 0;
+ while((!ignore) && (j < cuts.size())) {
+ int tmp = ((Integer)cuts.elementAt(j)).intValue();
+ if(tmp == neighbour.getIndex()) {
+ ignore = true;
+ }
+ j++;
+ }
+ }
+ if(!ignore) {
+ parents[neighbour.getIndex()] = access.getIndex();
+ toaccess.addElement(neighbour);
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ // This method returns true if this ghost is traveling to the same
+ // destination with the same direction as another ghost.
+ private boolean isFollowing () {
+ boolean bFollowing = false;
+ double dRandom;
+
+ // If the ghost is in the same location as another ghost
+ // and moving in the same direction, then they are on
+ // top of each other and should not follow.
+ for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
+ // Ignore myself
+ if (this.m_index != i) {
+ if (this.m_map.m_ghostsX[i] == this.m_locX &&
+ this.m_map.m_ghostsY[i] == this.m_locY &&
+ this.m_map.m_ghostdirections[i] == this.m_direction) {
+ return true;
+ }
+ }
+ }
+
+ // This will allow ghosts to often
+ // clump together for easier eating
+ dRandom = this.m_map.m_r.nextDouble();
+ if (dRandom < .90) {
+ //if (m_bInsaneAI && dRandom < .25)
+ // return false;
+ //else
+ return false;
+ }
+
+ // If ghost is moving to the same location and using the
+ // same direction, then it is following another ghost.
+ for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
+ // Ignore myself
+ if (this.m_index != i) {
+ if (this.m_map.m_targets[i] == this.m_target &&
+ this.m_map.m_ghostdirections[i] == this.m_direction) {
+ return true;
+ }
+ }
+ }
+
+ return bFollowing;
+ }
+
+ // This method will take the specified location and direction and determine
+ // for the given location if the thing moved in that direction, what the
+ // next possible turning location would be.
+ private boolean getDestination (int direction, int locX, int locY, int[] point) {
+ // If the request direction is blocked by a wall, then just return the current location
+ if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
+ ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
+ ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
+ ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
+ point[0] = locX;
+ point[1] = locY;
+ return false;
+ }
+
+ // Start off by advancing one in direction for specified location
+ if (direction == 1) {
+ // up
+ locY--;
+ } else if (direction == 2) {
+ // down
+ locY++;
+ } else if (direction == 3) {
+ // left
+ locX--;
+ } else if (direction == 4) {
+ // right
+ locX++;
+ }
+
+ // If we violate the grid boundary,
+ // then return false.
+ if (locY < 0 ||
+ locX < 0 ||
+ locY == this.m_map.m_nrofblocks ||
+ locX == this.m_map.m_nrofblocks) {
+ return false;
+ }
+
+ boolean set = false;
+ // Determine next turning location.
+ while (!set) {
+ if (direction == 1 || direction == 2) {
+ // up or down
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
+ point[0] = locX;
+ point[1] = locY;
+ set = true;
+ } else {
+ if (direction == 1) {
+ // Check for Top Warp
+ if (locY == 0) {
+ point[0] = locX;
+ point[1] = this.m_map.m_nrofblocks - 1;
+ set = true;
+ } else {
+ locY--;
+ }
+ } else {
+ // Check for Bottom Warp
+ if (locY == this.m_map.m_nrofblocks - 1) {
+ point[0] = locX;
+ point[1] = 0;
+ set = true;
+ } else {
+ locY++;
+ }
+ }
+ }
+ } else {
+ // left or right
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
+ point[0] = locX;
+ point[1] = locY;
+ set = true;
+ } else {
+ if (direction == 3) {
+ // Check for Left Warp
+ if (locX == 0) {
+ point[0] = this.m_map.m_nrofblocks - 1;
+ point[1] = locY;
+ set = true;
+ } else {
+ locX--;
+ }
+ } else {
+ // Check for Right Warp
+ if (locX == this.m_map.m_nrofblocks - 1) {
+ point[0] = 0;
+ point[1] = locY;
+ set = true;
+ } else {
+ locX++;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ public void doMove() {
+ this.m_locX += this.m_dx;
+ this.m_locY += this.m_dy;
+ this.m_dx = 0;
+ this.m_dy = 0;
+ //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");
+ }
+}
\ No newline at end of file
-task startup(StartupObject s{initialstate}) {\r
- //System.printString("Task startup\n");\r
- \r
- int nrofpacs = 4;\r
- int nrofghosts = 8;\r
- Map map = new Map(nrofpacs, nrofghosts){init};\r
- taskexit(s{!initialstate});\r
-}\r
-\r
-task initMap(Map map{init}) {\r
- //System.printString("Task initMap\n");\r
- \r
- map.init();\r
- \r
- int i = 0;\r
- // create ghosts\r
- for(i = 0; i < map.nrofghosts; i++) {\r
- Ghost ghost = new Ghost(7, 7, map){move};\r
- ghost.setTarget(i%map.nrofpacs);\r
- ghost.index = i;\r
- map.placeGhost(ghost);\r
- map.targets[i] = ghost.target;\r
- }\r
- // create pacmen\r
- int tx = 14;\r
- int ty = 14;\r
- for(i = 0; i < map.nrofpacs; i++) {\r
- Pacman pacman = new Pacman(5, 7, map){move};\r
- pacman.setTarget(tx*(i/2), ty*(i%2));\r
- pacman.index = i;\r
- map.placePacman(pacman);\r
- map.desX[i] = tx*(i/2);\r
- map.desY[i] = ty*(i%2);\r
- }\r
- \r
- map.ghostcount = 0;\r
- map.paccount = 0;\r
- \r
- taskexit(map{!init, updateGhost});\r
-}\r
-\r
-task moveGhost(Ghost g{move}) {\r
- //System.printString("Task moveGhost\n");\r
- \r
- g.tryMove();\r
- \r
- taskexit(g{!move, update});\r
-}\r
-\r
-task movePacman(Pacman p{move}) {\r
- //System.printString("Task movePacman\n");\r
- \r
- p.tryMove();\r
- \r
- taskexit(p{!move, update});\r
-}\r
-\r
-task updateGhost(Map map{updateGhost}, /*optional*/ Ghost g{update}) {\r
- //System.printString("Task updateGhost\n");\r
- \r
- //if(isavailable(g)) {\r
- g.doMove();\r
- map.placeGhost(g);\r
- map.ghostdirections[g.index] = g.direction;\r
- /*} else {\r
- System.printString("FAILURE ghost!!!\n");\r
- //map.failghostcount++;\r
- map.ghostcount++;\r
- }*/\r
- \r
- if(map.ghostcount == map.nrofghosts) {\r
- //map.nrofghosts -= map.failghostcount;\r
- map.ghostcount = 0;\r
- map.failghostcount = 0;\r
- /*for(int i = 0; i < map.ghostsX.length; i++) {\r
- System.printString("(" + map.ghostsX[i] + "," + map.ghostsY[i] + ") ");\r
- }\r
- System.printString("\n");*/\r
- taskexit(map{updatePac, !updateGhost}, g{!update});\r
- }\r
- taskexit(g{!update});\r
-}\r
-\r
-task updatePac(Map map{updatePac}, /*optional*/ Pacman p{update}) {\r
- //System.printString("Task updatePac\n");\r
- \r
- //if(isavailable(p)) {\r
- p.doMove();\r
- map.placePacman(p);\r
- map.directions[p.index] = p.direction;\r
- //System.printString("Pacman " + p.index + ": (" + map.pacMenX[p.index] + "," + map.pacMenY[p.index] + ")\n");\r
- boolean death = map.check(p);\r
- /*if(death) {\r
- System.printString("Pacman " + p.index + " caught!\n");\r
- }*/\r
- /*} else {\r
- System.printString("FAILURE pacman!!!\n");\r
- map.deathcount++;\r
- map.paccount++;\r
- }*/\r
- \r
- boolean finish = map.paccount == map.nrofpacs;\r
- \r
- if(finish) {\r
- map.nrofpacs -= map.deathcount;\r
- //System.printString(map.nrofpacs + " pacmen left. \n");\r
- if(map.isfinish()) {\r
- taskexit(map{finish, !updatePac}, p{!update, !move});\r
- } else {\r
- taskexit(map{next, !updatePac}, p{!update, !move});\r
- }\r
- } else {\r
- taskexit(p{!move, !update});\r
- }\r
-}\r
-\r
-task next(Map map{next}) {\r
- //System.printString("Task next\n");\r
- \r
- int i = 0;\r
- for(i = 0; i < map.nrofghosts; i++) {\r
- Ghost ghost = new Ghost(map.ghostsX[i], map.ghostsY[i], map){move};\r
- ghost.setTarget(map.targets[i]);\r
- ghost.index = i;\r
- ghost.direction = map.ghostdirections[i];\r
- }\r
- for(i = 0; i < map.pacMenX.length; i++) {\r
- if(map.pacMenX[i] != -1) {\r
- // still in the map\r
- //System.printString("new Pacman\n");\r
- Pacman pacman = new Pacman(map.pacMenX[i], map.pacMenY[i], map){move};\r
- pacman.setTarget(map.desX[i], map.desY[i]);\r
- pacman.index = i;\r
- pacman.direction = map.directions[i];\r
- }\r
- }\r
- \r
- map.paccount = 0;\r
- map.deathcount = 0;\r
- \r
- taskexit(map{!next, updateGhost});\r
-}\r
-\r
-task finish(Map map{finish}) {\r
- System.printString("Task Finish\n");\r
- taskexit(map{!finish});\r
-}\r
+task startup(StartupObject s{initialstate}) {
+ //System.printString("Task startup\n");
+
+ int nrofpacs = 4;
+ int nrofghosts = 8;
+ Map map = new Map(nrofpacs, nrofghosts){init};
+ taskexit(s{!initialstate});
+}
+
+task initMap(Map map{init}) {
+ //System.printString("Task initMap\n");
+
+ map.init();
+
+ int i = 0;
+ // create ghosts
+ for(i = 0; i < map.m_nrofghosts; i++) {
+ Ghost ghost = new Ghost(7, 7, map){move};
+ ghost.m_index = i;
+ map.placeGhost(ghost);
+ }
+ // create pacmen
+ int tx = 14;
+ int ty = 14;
+ for(i = 0; i < map.m_nrofpacs; i++) {
+ Pacman pacman = new Pacman(5, 7, map){move};
+ pacman.setTarget(tx*(i/2), ty*(i%2));
+ pacman.m_index = i;
+ map.placePacman(pacman);
+ map.m_desX[i] = tx*(i/2);
+ map.m_desY[i] = ty*(i%2);
+ }
+
+ map.m_ghostcount = 0;
+ map.m_paccount = 0;
+
+ taskexit(map{!init, updateGhost});
+}
+
+task moveGhost(Ghost g{move}) {
+ //System.printString("Task moveGhost\n");
+
+ g.tryMove();
+
+ taskexit(g{!move, update});
+}
+
+task movePacman(Pacman p{move}) {
+ //System.printString("Task movePacman\n");
+
+ p.tryMove();
+
+ taskexit(p{!move, update});
+}
+
+task updateGhost(Map map{updateGhost}, /*optional*/ Ghost g{update}) {
+ //System.printString("Task updateGhost\n");
+
+ //if(isavailable(g)) {
+ g.doMove();
+ map.placeGhost(g);
+ /*} else {
+ map.m_ghostcount++;
+ }*/
+
+ if(map.m_ghostcount == map.m_nrofghosts) {
+ //map.m_nrofghosts -= map.m_failghostcount;
+ map.m_ghostcount = 0;
+ map.m_failghostcount = 0;
+ /*for(int i = 0; i < map.m_ghostsX.length; i++) {
+ System.printString("(" + map.m_ghostsX[i] + "," + map.m_ghostsY[i] + ") ");
+ }
+ System.printString("\n");*/
+ taskexit(map{updatePac, !updateGhost}, g{!update});
+ }
+ taskexit(g{!update});
+}
+
+task updatePac(Map map{updatePac}, /*optional*/ Pacman p{update}) {
+ //System.printString("Task updatePac\n");
+
+ //if(isavailable(p)) {
+ p.doMove();
+ map.placePacman(p);
+ //System.printString("Pacman " + p.m_index + ": (" + map.m_pacMenX[p.m_index] + "," + map.m_pacMenY[p.m_index] + ")\n");
+ boolean death = map.check(p);
+ /*if(death) {
+ System.printString("Pacman " + p.m_index + " caught!\n");
+ }*/
+ /*} else {
+ map.m_deathcount++;
+ map.m_paccount++;
+ }*/
+
+ boolean finish = map.m_paccount == map.m_nrofpacs;
+
+ if(finish) {
+ map.m_nrofpacs -= map.m_deathcount;
+ //System.printString(map.m_nrofpacs + " pacmen left. \n");
+ if(map.isfinish()) {
+ taskexit(map{finish, !updatePac}, p{!update, !move});
+ } else {
+ taskexit(map{next, !updatePac}, p{!update, !move});
+ }
+ } else {
+ taskexit(p{!move, !update});
+ }
+}
+
+task next(Map map{next}) {
+ //System.printString("Task next\n");
+
+ int i = 0;
+ for(i = 0; i < map.m_nrofghosts; i++) {
+ Ghost ghost = new Ghost(map.m_ghostsX[i], map.m_ghostsY[i], map){move};
+ ghost.m_index = i;
+ ghost.m_direction = map.m_ghostdirections[i];
+ }
+ for(i = 0; i < map.m_pacMenX.length; i++) {
+ if(map.m_pacMenX[i] != -1) {
+ // still in the map
+ //System.printString("new Pacman\n");
+ Pacman pacman = new Pacman(map.m_pacMenX[i], map.m_pacMenY[i], map){move};
+ pacman.setTarget(map.m_desX[i], map.m_desY[i]);
+ pacman.m_index = i;
+ pacman.m_direction = map.m_directions[i];
+ }
+ }
+
+ map.m_paccount = 0;
+ map.m_deathcount = 0;
+
+ taskexit(map{!next, updateGhost});
+}
+
+task finish(Map map{finish}) {
+ System.printString("Task Finish\n");
+ taskexit(map{!finish});
+}
\ No newline at end of file
-public class Map {\r
- flag init;\r
- flag updateGhost;\r
- flag updatePac;\r
- flag next;\r
- flag finish;\r
- \r
- public int[] map;\r
- public int[] pacMenX;\r
- public int[] pacMenY;\r
- public int[] directions;\r
- public int[] ghostsX;\r
- public int[] ghostsY;\r
- public int[] ghostdirections;\r
- public int[] targets;\r
- public int[] desX;\r
- public int[] desY;\r
- \r
- public int nrofghosts;\r
- public int nrofpacs;\r
- private int nrofblocks;\r
- //public boolean toupdate;\r
- public int ghostcount;\r
- public int paccount;\r
- public int deathcount;\r
- public int failghostcount;\r
- \r
- public Random r;\r
- \r
- public Map(int nrofpacs, int nrofghosts) {\r
- //System.printString("step 1\n");\r
- this.nrofblocks = 15;\r
- this.map = new int[this.nrofblocks*this.nrofblocks];\r
- this.nrofpacs = nrofpacs;\r
- this.nrofghosts = nrofghosts;\r
- this.pacMenX = new int[this.nrofpacs];\r
- this.pacMenY = new int[this.nrofpacs];\r
- this.directions = new int[this.nrofpacs];\r
- this.ghostsX = new int[this.nrofghosts];\r
- this.ghostsY = new int[this.nrofghosts];\r
- this.ghostdirections = new int[this.nrofghosts];\r
- this.targets = new int[this.nrofghosts];\r
- this.desX = new int[this.nrofpacs];\r
- this.desY = new int[this.nrofpacs];\r
- //this.toupdate = false;\r
- this.ghostcount = 0;\r
- this.paccount = 0;\r
- this.deathcount = 0;\r
- this.failghostcount = 0;\r
- \r
- this.r = new Random();\r
- \r
- //System.printString("step 2\n");\r
- for(int i = 0; i < this.nrofpacs; i++) {\r
- this.pacMenX[i] = this.pacMenY[i] = -1;\r
- this.desX[i] = this.desY[i] = -1;\r
- }\r
- //System.printString("step 3\n");\r
- for(int i = 0; i < this.nrofghosts; i++) {\r
- this.ghostsX[i] = this.ghostsY[i] = -1;\r
- this.targets[i] = -1;\r
- }\r
- //System.printString("step 4\n");\r
- }\r
- \r
- public void init() {\r
- int i = 0;\r
- this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;this.map[i++]=9;this.map[i++]=12;this.map[i++]=3;this.map[i++]=10;this.map[i++]=6;this.map[i++]=9;this.map[i++]=12;this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;\r
- this.map[i++]=5;this.map[i++]=11;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=15;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=14;this.map[i++]=5;\r
- this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=6;this.map[i++]=1;this.map[i++]=10;this.map[i++]=4;this.map[i++]=3;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;\r
- this.map[i++]=5;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=6;this.map[i++]=5;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=5;this.map[i++]=3;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=5;\r
- this.map[i++]=5;this.map[i++]=9;this.map[i++]=8;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=8;this.map[i++]=12;this.map[i++]=5;\r
- this.map[i++]=9;this.map[i++]=2;this.map[i++]=10;this.map[i++]=2;this.map[i++]=8;this.map[i++]=2;this.map[i++]=12;this.map[i++]=5;this.map[i++]=9;this.map[i++]=2;this.map[i++]=8;this.map[i++]=2;this.map[i++]=10;this.map[i++]=2;this.map[i++]=12;\r
- this.map[i++]=6;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=11;this.map[i++]=8;this.map[i++]=14;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=3;\r
- this.map[i++]=4;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=10;this.map[i++]=10;this.map[i++]=10;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=1;\r
- this.map[i++]=12;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=10;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=9;\r
- this.map[i++]=3;this.map[i++]=8;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=0;this.map[i++]=10;this.map[i++]=2;this.map[i++]=10;this.map[i++]=0;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=8;this.map[i++]=6;\r
- this.map[i++]=5;this.map[i++]=3;this.map[i++]=2;this.map[i++]=2;this.map[i++]=6;this.map[i++]=5;this.map[i++]=15;this.map[i++]=5;this.map[i++]=15;this.map[i++]=5;this.map[i++]=3;this.map[i++]=2;this.map[i++]=2;this.map[i++]=6;this.map[i++]=5;\r
- this.map[i++]=5;this.map[i++]=9;this.map[i++]=8;this.map[i++]=8;this.map[i++]=4;this.map[i++]=1;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=4;this.map[i++]=1;this.map[i++]=8;this.map[i++]=8;this.map[i++]=12;this.map[i++]=5;\r
- this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=2;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;\r
- this.map[i++]=5;this.map[i++]=11;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=8;this.map[i++]=6;this.map[i++]=13;this.map[i++]=3;this.map[i++]=8;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=14;this.map[i++]=5;\r
- this.map[i++]=9;this.map[i++]=10;this.map[i++]=10;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=10;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=10;this.map[i++]=10;this.map[i++]=12; // 15*15 \r
- } \r
-\r
- public void placePacman(Pacman t) {\r
- this.pacMenX[t.index] = t.x;\r
- this.pacMenY[t.index] = t.y;\r
- //this.map[t.y * this.nrofblocks + t.x - 1] |= 16;\r
- this.paccount++;\r
- }\r
- \r
- public void placeGhost(Ghost t) {\r
- this.ghostsX[t.index] = t.x;\r
- this.ghostsY[t.index] = t.y;\r
- //this.map[t.y * this.nrofblocks + t.x - 1] |= 32;\r
- this.ghostcount++;\r
- }\r
- \r
- public boolean check(Pacman t) {\r
- boolean death = false;\r
- int i = 0;\r
- while((!death) && (i < this.nrofghosts)) {\r
- if((t.x == this.ghostsX[i]) && (t.y == this.ghostsY[i])) {\r
- death = true;\r
- }\r
- i++;\r
- }\r
- if((!death) && (t.x == t.tx) && (t.y == t.ty)) {\r
- // reach the destination\r
- //System.printString("Hit destination!\n");\r
- death = true;\r
- }\r
- if(death) {\r
- // pacman caught by ghost\r
- // set pacman as death\r
- t.death = true;\r
- // kick it out\r
- //this.map[t.y * this.nrofblocks + t.x - 1] -= 16;\r
- this.deathcount++;\r
- this.pacMenX[t.index] = -1;\r
- this.pacMenY[t.index] = -1;\r
- }\r
- return death;\r
- }\r
- \r
- public boolean isfinish() {\r
- return nrofpacs == 0;\r
- }\r
-}\r
+public class Map {
+ flag init;
+ flag updateGhost;
+ flag updatePac;
+ flag next;
+ flag finish;
+
+ // maze
+ private int m_nrofblocks;
+ public int[] m_map;
+ public Node[] m_mapNodes;
+
+ // pacmen information
+ public int m_nrofpacs;
+ public int[] m_pacMenX;
+ public int[] m_pacMenY;
+ public int[] m_directions;
+ public int[] m_desX;
+ public int[] m_desY;
+ public int m_paccount;
+ public int m_deathcount;
+
+ // ghosts information
+ public int m_nrofghosts;
+ public int[] m_ghostsX;
+ public int[] m_ghostsY;
+ public int[] m_ghostdirections;
+ public int[] m_targets;
+ public int m_ghostcount;
+ public int m_failghostcount;
+
+ // helper member
+ public Random m_r;
+
+ public Map(int nrofpacs, int nrofghosts) {
+ //System.printString("step 1\n");
+ this.m_nrofblocks = 15;
+ this.m_map = new int[this.m_nrofblocks*this.m_nrofblocks];
+ this.m_mapNodes = new Node[this.m_nrofblocks*this.m_nrofblocks];
+
+ this.m_nrofpacs = nrofpacs;
+ this.m_pacMenX = new int[this.m_nrofpacs];
+ this.m_pacMenY = new int[this.m_nrofpacs];
+ this.m_directions = new int[this.m_nrofpacs];
+ this.m_desX = new int[this.m_nrofpacs];
+ this.m_desY = new int[this.m_nrofpacs];
+ this.m_paccount = 0;
+ this.m_deathcount = 0;
+
+ this.m_nrofghosts = nrofghosts;
+ this.m_ghostsX = new int[this.m_nrofghosts];
+ this.m_ghostsY = new int[this.m_nrofghosts];
+ this.m_ghostdirections = new int[this.m_nrofghosts];
+ this.m_targets = new int[this.m_nrofghosts];
+ this.m_ghostcount = 0;
+ this.m_failghostcount = 0;
+
+ this.m_r = new Random();
+
+ for(int i = 0; i < this.m_nrofblocks*this.m_nrofblocks; i++) {
+ this.m_map[i] = -1;
+ this.m_mapNodes[i] = new Node(i%this.m_nrofblocks, i/this.m_nrofblocks, i);
+ }
+
+ //System.printString("step 2\n");
+ for(int i = 0; i < this.m_nrofpacs; i++) {
+ this.m_pacMenX[i] = this.m_pacMenY[i] = -1;
+ this.m_desX[i] = this.m_desY[i] = -1;
+ }
+ //System.printString("step 3\n");
+ for(int i = 0; i < this.m_nrofghosts; i++) {
+ this.m_ghostsX[i] = this.m_ghostsY[i] = -1;
+ this.m_targets[i] = -1;
+ }
+ //System.printString("step 4\n");
+ }
+
+ public void init() {
+ // initilize the maze
+ int i = 0;
+ this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;
+ this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=15;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=5;
+ this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=6;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=3;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;
+ this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=5;
+ this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=8;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=8;this.m_map[i++]=12;this.m_map[i++]=5;
+ this.m_map[i++]=9;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=8;this.m_map[i++]=2;this.m_map[i++]=12;this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=2;this.m_map[i++]=8;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=12;
+ this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=8;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=3;
+ this.m_map[i++]=4;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=1;
+ this.m_map[i++]=12;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=10;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=9;
+ this.m_map[i++]=3;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=0;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=0;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=6;
+ this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=2;this.m_map[i++]=2;this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=15;this.m_map[i++]=5;this.m_map[i++]=15;this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=2;this.m_map[i++]=2;this.m_map[i++]=6;this.m_map[i++]=5;
+ this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=8;this.m_map[i++]=8;this.m_map[i++]=4;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=1;this.m_map[i++]=8;this.m_map[i++]=8;this.m_map[i++]=12;this.m_map[i++]=5;
+ this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=2;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;
+ this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=6;this.m_map[i++]=13;this.m_map[i++]=3;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=5;
+ this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=12; // 15*15
+
+ // initilize the graph of the maze
+ for(i = 0; i < this.m_nrofblocks*this.m_nrofblocks; i++) {
+ int tmp = this.m_map[i];
+ Node tmpNode = this.m_mapNodes[i];
+ int locX = tmpNode.getXLoc();
+ int locY = tmpNode.getYLoc();
+ if((int)(tmp & 1) == 0) {
+ // can go left
+ if(locX == 0) {
+ tmpNode.addNeighbour(this.m_mapNodes[locY * this.m_nrofblocks + this.m_nrofblocks - 1]);
+ } else {
+ tmpNode.addNeighbour(this.m_mapNodes[i - 1]);
+ }
+ }
+ if((int)(tmp & 2) == 0) {
+ // can go up
+ if(locY == 0) {
+ tmpNode.addNeighbour(this.m_mapNodes[(this.m_nrofblocks - 1) * this.m_nrofblocks + locX]);
+ } else {
+ tmpNode.addNeighbour(this.m_mapNodes[(locY - 1) * this.m_nrofblocks + locX]);
+ }
+ }
+ if((int)(tmp & 4) == 0) {
+ // can go right
+ if(locX == this.m_nrofblocks - 1) {
+ tmpNode.addNeighbour(this.m_mapNodes[locY * this.m_nrofblocks]);
+ } else {
+ tmpNode.addNeighbour(this.m_mapNodes[i + 1]);
+ }
+ }
+ if((int)(tmp & 8) == 0) {
+ // can go down
+ if(locY == this.m_nrofblocks - 1) {
+ tmpNode.addNeighbour(this.m_mapNodes[locX]);
+ } else {
+ tmpNode.addNeighbour(this.m_mapNodes[(locY + 1) * this.m_nrofblocks + locX]);
+ }
+ }
+ }
+ }
+
+ public void placePacman(Pacman t) {
+ this.m_pacMenX[t.m_index] = t.m_locX;
+ this.m_pacMenY[t.m_index] = t.m_locY;
+ this.m_paccount++;
+ }
+
+ public void placeGhost(Ghost t) {
+ this.m_ghostsX[t.m_index] = t.m_locX;
+ this.m_ghostsY[t.m_index] = t.m_locY;
+ this.m_ghostcount++;
+ }
+
+ public boolean check(Pacman t) {
+ boolean death = false;
+ int i = 0;
+ while((!death) && (i < this.m_ghostsX.length)) {
+ if((t.m_locX == this.m_ghostsX[i]) && (t.m_locY == this.m_ghostsY[i])) {
+ death = true;
+ }
+ i++;
+ }
+ if((!death) && (t.m_locX == t.m_tx) && (t.m_locY == t.m_ty)) {
+ // reach the destination
+ //System.printString("Hit destination!\n");
+ death = true;
+ }
+ if(death) {
+ // pacman caught by ghost
+ // set pacman as death
+ t.m_death = true;
+ // kick it out
+ //this.m_map[t.y * this.m_nrofblocks + t.x - 1] -= 16;
+ this.m_deathcount++;
+ this.m_pacMenX[t.m_index] = -1;
+ this.m_pacMenY[t.m_index] = -1;
+ }
+ return death;
+ }
+
+ public boolean isfinish() {
+ return this.m_nrofpacs == 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+public class Node {
+
+ int m_locX;
+ int m_locY;
+ int m_index;
+ Vector m_neighbours;
+
+ public Node(int locX, int locY, int index) {
+ this.m_locX = locX;
+ this.m_locY = locY;
+ this.m_index = index;
+ this.m_neighbours = new Vector();
+ }
+
+ public void addNeighbour(Node n) {
+ this.m_neighbours.addElement(n);
+ }
+
+ public Vector getNeighbours() {
+ return this.m_neighbours;
+ }
+
+ public int getXLoc() {
+ return this.m_locX;
+ }
+
+ public int getYLoc() {
+ return this.m_locY;
+ }
+
+ public int getIndex() {
+ return this.m_index;
+ }
+}
\ No newline at end of file
-public class Pacman {\r
- flag move;\r
- flag update;\r
-\r
- public int x;\r
- public int y;\r
- public boolean death;\r
- public int index;\r
- public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
- int dx;\r
- int dy;\r
- public int tx;\r
- public int ty;\r
- int destinationX;\r
- int destinationY;\r
- Map map;\r
- \r
- public Pacman(int x, int y, Map map) {\r
- this.x = x;\r
- this.y = y;\r
- this.dx = this.dy = 0;\r
- this.death = false;\r
- this.index = -1;\r
- this.tx = this.ty = -1;\r
- this.direction = 0;\r
- this.destinationX = -1;\r
- this.destinationY = -1;\r
- this.map = map;\r
- }\r
- \r
- public void setTarget(int x, int y) {\r
- this.tx = x;\r
- this.ty = y;\r
- }\r
- \r
- public void tryMove() {\r
- // decide dx & dy\r
-\r
- // Don't let the pacman go back the way it came.\r
- int prevDirection = 0;\r
-\r
- // If there is a destination, then check if the destination has been reached.\r
- if (destinationX >= 0 && destinationY >= 0) {\r
- // Check if the destination has been reached, if so, then\r
- // get new destination.\r
- if (destinationX == x && destinationY == y) {\r
- destinationX = -1;\r
- destinationY = -1;\r
- prevDirection = direction;\r
- } else {\r
- // Otherwise, we haven't reached the destionation so\r
- // continue in same direction.\r
- return;\r
- }\r
- }\r
- setNextDirection (prevDirection);\r
- }\r
- \r
- private void setNextDirection(int prevDirection) {\r
- // get target's position\r
- int targetx = this.tx;\r
- //System.printString("aaa\n");\r
- int targety = this.ty;\r
- int[] nextLocation = new int[2];\r
- nextLocation[0] = nextLocation[1] = -1;\r
- \r
- //System.printString("bbb\n");\r
- getDestination (this.direction, targetx, targety, nextLocation);\r
- targetx = nextLocation[0];\r
- targety = nextLocation[1];\r
- \r
- //System.printString("step 2\n");\r
- // check the distance\r
- int deltax = this.x - targetx; // <0: move right; >0: move left\r
- int deltay = this.y - targety; // <0: move down; >0: move up\r
- // decide the priority of four moving directions\r
- int[] bestDirection = new int[4];\r
- //System.printString("dx: " + deltax + "; dy: " + deltay + "\n");\r
- if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) {\r
- // go first along y\r
- if(deltay > 0) {\r
- bestDirection[0] = 1;\r
- bestDirection[3] = 2;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
- } else {\r
- bestDirection[0] = 2;\r
- bestDirection[3] = 1;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
- }\r
- } else {\r
- if(deltax > 0) {\r
- bestDirection[0] = 3;\r
- bestDirection[3] = 4;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
- } else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
- }\r
- } else {\r
- bestDirection[0] = 4;\r
- bestDirection[3] = 3;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
- } else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
- }\r
- }\r
- }\r
- /*for(int i = 0; i < 4; i++) {\r
- System.printString(bestDirection[i] + ",");\r
- }\r
- System.printString("\n");*/\r
- \r
- // There's a 50% chance that the ghost will try the sub-optimal direction first.\r
- // This will keep the ghosts from following each other and to trap Pacman.\r
- if (this.map.r.nextDouble() < .50) { \r
- int temp = bestDirection[0];\r
- bestDirection[0] = bestDirection[1];\r
- bestDirection[1] = temp;\r
- }\r
- \r
- //System.printString("step 3\n");\r
- // try to move one by one\r
- int i = 0;\r
- boolean set = false;\r
- this.dx = 0;\r
- this.dy = 0;\r
- while((!set) && (i < 4)) {\r
- if(bestDirection[i] == 1) {\r
- // try to move up\r
- if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) {\r
- //System.printString("a\n");\r
- if (getDestination (1, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = -1;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 2) {\r
- // try to move down\r
- if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) {\r
- //System.printString("b\n");\r
- if (getDestination (2, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = 1;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 3) {\r
- // try to move left\r
- if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) {\r
- //System.printString("c\n");\r
- if (getDestination (3, this.x, this.y, nextLocation)) {\r
- this.dx = -1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 4) {\r
- // try to move right\r
- if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) {\r
- //System.printString("d\n");\r
- if (getDestination (4, this.x, this.y, nextLocation)) {\r
- this.dx = 1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
- }\r
- }\r
- i++;\r
- }\r
- //System.printString("step 4\n");\r
- }\r
- \r
- // This method will take the specified location and direction and determine\r
- // for the given location if the thing moved in that direction, what the\r
- // next possible turning location would be.\r
- boolean getDestination (int direction, int locX, int locY, int[] point) {\r
- // If the request direction is blocked by a wall, then just return the current location\r
- if ((direction == 1 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up\r
- (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left\r
- (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down\r
- (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right \r
- point[0] = locX;\r
- point[1] = locY;\r
- return false;\r
- }\r
- \r
- // Start off by advancing one in direction for specified location\r
- if (direction == 1) {\r
- // up\r
- locY--;\r
- } else if (direction == 2) {\r
- // down\r
- locY++;\r
- } else if (direction == 3) {\r
- // left\r
- locX--;\r
- } else if (direction == 4) {\r
- // right\r
- locX++;\r
- }\r
- \r
- // If we violate the grid boundary,\r
- // then return false.\r
- if (locY < 0 ||\r
- locX < 0 ||\r
- locY == this.map.nrofblocks ||\r
- locX == this.map.nrofblocks) {\r
- return false;\r
- }\r
- \r
- boolean set = false;\r
- // Determine next turning location..\r
- while (!set) {\r
- if (direction == 1 || direction == 2) { \r
- // up or down\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // down\r
- point[0] = locX;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- if (direction == 1) {\r
- // Check for Top Warp\r
- if (locY == 0) {\r
- point[0] = locX;\r
- point[1] = this.map.nrofblocks - 1;\r
- set = true;\r
- } else {\r
- locY--;\r
- }\r
- } else {\r
- // Check for Bottom Warp\r
- if (locY == this.map.nrofblocks - 1) {\r
- point[0] = locX;\r
- point[1] = 0;\r
- set = true;\r
- } else {\r
- locY++;\r
- }\r
- }\r
- }\r
- } else {\r
- // left or right\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left \r
- point[0] = locX;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- if (direction == 3) {\r
- // Check for Left Warp\r
- if (locX == 0) {\r
- point[0] = this.map.nrofblocks - 1;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- locX--;\r
- }\r
- } else {\r
- // Check for Right Warp\r
- if (locX == this.map.nrofblocks - 1) {\r
- point[0] = 0;\r
- point[1] = locY;\r
- set = true;\r
- } else {\r
- locX++;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
- \r
- public void doMove() {\r
- // System.printString("dx: " + this.dx + ", dy: " + this.dy + "\n");\r
- this.x += this.dx;\r
- this.y += this.dy;\r
- //this.dx = 0;\r
- //this.dy = 0;\r
- }\r
-}\r
+public class Pacman {
+ flag move;
+ flag update;
+
+ public int m_locX;
+ public int m_locY;
+ public boolean m_death;
+ public int m_index;
+ public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
+ int m_dx;
+ int m_dy;
+ public int m_tx;
+ public int m_ty;
+ Map m_map;
+
+ public Pacman(int x, int y, Map map) {
+ this.m_locX = x;
+ this.m_locY = y;
+ this.m_dx = this.m_dy = 0;
+ this.m_death = false;
+ this.m_index = -1;
+ this.m_tx = this.m_ty = -1;
+ this.m_direction = 0;
+ this.m_map = map;
+ }
+
+ public void setTarget(int x, int y) {
+ this.m_tx = x;
+ this.m_ty = y;
+ }
+
+ public void tryMove() {
+ // decide dx & dy
+
+ // find the shortest possible way to the chosen target
+ setNextDirection();
+ }
+
+ private void setNextDirection() {
+ // current position of the ghost
+ Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];
+
+ // get target's position
+ int targetx = this.m_tx;
+ int targety = this.m_ty;
+ int[] nextLocation = new int[2];
+ nextLocation[0] = nextLocation[1] = -1;
+
+ // target's position
+ Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];
+
+ // breadth-first traverse the graph view of the maze
+ // check the shortest path for the start node to the end node
+ boolean set = false;
+ Vector cuts = new Vector();
+ int tmpdx = 0;
+ int tmpdy = 0;
+ int tmpdirection = 0;
+ boolean first = true;
+ while(!set) {
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
+ for(int i = 0; i < parents.length; i++) {
+ parents[i] = -1;
+ }
+ if(!BFS(start, end, parents, cuts)) {
+ this.m_dx = tmpdx;
+ this.m_dy = tmpdy;
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
+ set = true;
+ //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
+ } else {
+ // Reversely go over the parents array to find the next node to reach
+ boolean found = false;
+ int index = end.getIndex();
+ while(!found) {
+ int parent = parents[index];
+ if(parent == start.getIndex()) {
+ found = true;
+ } else {
+ index = parent;
+ }
+ }
+
+ // set the chase direction
+ int nx = this.m_map.m_mapNodes[index].getXLoc();
+ int ny = this.m_map.m_mapNodes[index].getYLoc();
+ this.m_dx = nx - this.m_locX;
+ this.m_dy = ny - this.m_locY;
+ if(this.m_dx > 0) {
+ // right
+ this.m_direction = 4;
+ } else if(this.m_dx < 0) {
+ // left
+ this.m_direction = 3;
+ } else if(this.m_dy > 0) {
+ // down
+ this.m_direction = 2;
+ } else if(this.m_dy < 0) {
+ // up
+ this.m_direction = 1;
+ } else {
+ // still
+ this.m_direction = 0;
+ }
+ if(first) {
+ tmpdx = this.m_dx;
+ tmpdy = this.m_dy;
+ tmpdirection = this.m_direction;
+ first = false;
+ //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
+ }
+
+ // check if this choice follows some other ghosts' path
+ if(canFlee()) {
+ this.m_map.m_directions[this.m_index] = this.m_direction;
+ set = true;
+ } else {
+ cuts.addElement(new Integer(index));
+ /*for( int h = 0; h < cuts.size(); h++) {
+ System.printString(cuts.elementAt(h) + ", ");
+ }
+ System.printString("\n");*/
+ }
+ }
+ }
+ }
+
+ // This methos do BFS from start node to end node
+ // If there is a path from start to end, return true; otherwise, return false
+ // Array parents records parent for a node in the BFS search,
+ // the last item of parents records the least steps to reach end node from start node
+ // Vector cuts specifies which nodes can not be the first one to access in this BFS
+ private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {
+ int steps = 0;
+ Vector toaccess = new Vector();
+ toaccess.addElement(start);
+ while(toaccess.size() > 0) {
+ // pull out the first one to access
+ Node access = (Node)toaccess.elementAt(0);
+ toaccess.removeElementAt(0);
+ if(access.getIndex() == end.getIndex()) {
+ // hit the end node
+ parents[parents.length - 1] = steps;
+ return true;
+ }
+ steps++;
+ Vector neighbours = access.getNeighbours();
+ for(int i = 0; i < neighbours.size(); i++) {
+ Node neighbour = (Node)neighbours.elementAt(i);
+ if(parents[neighbour.getIndex()] == -1) {
+ // not accessed
+ boolean ignore = false;
+ if(access.getIndex() == start.getIndex()) {
+ // start node, check if the neighbour node is in cuts
+ int j = 0;
+ while((!ignore) && (j < cuts.size())) {
+ int tmp = ((Integer)cuts.elementAt(j)).intValue();
+ if(tmp == neighbour.getIndex()) {
+ ignore = true;
+ }
+ j++;
+ }
+ }
+ if(!ignore) {
+ parents[neighbour.getIndex()] = access.getIndex();
+ toaccess.addElement(neighbour);
+ }
+ }
+ }
+ }
+ parents[parents.length - 1] = -1;
+ return false;
+ }
+
+ // This method returns true if this pacmen can flee in this direction.
+ private boolean canFlee () {
+ int steps = 0;
+ int locX = this.m_locX;
+ int locY = this.m_locY;
+ int[] point = new int[2];
+ point[0] = point[1] = -1;
+
+ // Start off by advancing one in direction for specified location
+ if (this.m_direction == 1) {
+ // up
+ locY--;
+ } else if (this.m_direction == 2) {
+ // down
+ locY++;
+ } else if (this.m_direction == 3) {
+ // left
+ locX--;
+ } else if (this.m_direction == 4) {
+ // right
+ locX++;
+ }
+ steps++;
+
+ boolean set = false;
+ // Determine next turning location.
+ while (!set) {
+ if (this.m_direction == 1 || this.m_direction == 2) {
+ // up or down
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
+ point[0] = locX;
+ point[1] = locY;
+ set = true;
+ } else {
+ if (this.m_direction == 1) {
+ // Check for Top Warp
+ if (locY == 0) {
+ point[0] = locX;
+ point[1] = this.m_map.m_nrofblocks - 1;
+ set = true;
+ } else {
+ locY--;
+ steps++;
+ }
+ } else {
+ // Check for Bottom Warp
+ if (locY == this.m_map.m_nrofblocks - 1) {
+ point[0] = locX;
+ point[1] = 0;
+ set = true;
+ } else {
+ locY++;
+ steps++;
+ }
+ }
+ }
+ } else {
+ // left or right
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
+ point[0] = locX;
+ point[1] = locY;
+ set = true;
+ } else {
+ if (this.m_direction == 3) {
+ // Check for Left Warp
+ if (locX == 0) {
+ point[0] = this.m_map.m_nrofblocks - 1;
+ point[1] = locY;
+ set = true;
+ } else {
+ locX--;
+ steps++;
+ }
+ } else {
+ // Check for Right Warp
+ if (locX == this.m_map.m_nrofblocks - 1) {
+ point[0] = 0;
+ point[1] = locY;
+ set = true;
+ } else {
+ locX++;
+ steps++;
+ }
+ }
+ }
+ }
+ }
+
+ // check the least steps for the ghosts to reach point location
+ int chasesteps = -1;
+ Node end = this.m_map.m_mapNodes[point[1] * this.m_map.m_nrofblocks + point[0]];
+ for(int i = 0; i < this.m_map.m_ghostsX.length; i++) {
+ Node start = this.m_map.m_mapNodes[this.m_map.m_ghostsY[i] * this.m_map.m_nrofblocks + this.m_map.m_ghostsX[i]];
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
+ for(int j = 0; j < parents.length; j++) {
+ parents[j] = -1;
+ }
+ if(BFS(start, end, parents, new Vector())) {
+ if((chasesteps == -1) ||
+ (chasesteps > parents[parents.length - 1])) {
+ chasesteps = parents[parents.length - 1];
+ }
+ }
+ }
+
+ return ((chasesteps == -1) || (steps < chasesteps));
+ }
+
+ // This method will take the specified location and direction and determine
+ // for the given location if the thing moved in that direction, what the
+ // next possible turning location would be.
+ private boolean getDestination (int direction, int locX, int locY, int[] point) {
+ // If the request direction is blocked by a wall, then just return the current location
+ if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
+ ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
+ ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
+ ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
+ point[0] = locX;
+ point[1] = locY;
+ return false;
+ }
+
+ // Start off by advancing one in direction for specified location
+ if (direction == 1) {
+ // up
+ locY--;
+ } else if (direction == 2) {
+ // down
+ locY++;
+ } else if (direction == 3) {
+ // left
+ locX--;
+ } else if (direction == 4) {
+ // right
+ locX++;
+ }
+
+ // If we violate the grid boundary,
+ // then return false.
+ if (locY < 0 ||
+ locX < 0 ||
+ locY == this.m_map.m_nrofblocks ||
+ locX == this.m_map.m_nrofblocks) {
+ return false;
+ }
+
+ boolean set = false;
+ // Determine next turning location.
+ while (!set) {
+ if (direction == 1 || direction == 2) {
+ // up or down
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
+ point[0] = locX;
+ point[1] = locY;
+ set = true;
+ } else {
+ if (direction == 1) {
+ // Check for Top Warp
+ if (locY == 0) {
+ point[0] = locX;
+ point[1] = this.m_map.m_nrofblocks - 1;
+ set = true;
+ } else {
+ locY--;
+ }
+ } else {
+ // Check for Bottom Warp
+ if (locY == this.m_map.m_nrofblocks - 1) {
+ point[0] = locX;
+ point[1] = 0;
+ set = true;
+ } else {
+ locY++;
+ }
+ }
+ }
+ } else {
+ // left or right
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
+ point[0] = locX;
+ point[1] = locY;
+ set = true;
+ } else {
+ if (direction == 3) {
+ // Check for Left Warp
+ if (locX == 0) {
+ point[0] = this.m_map.m_nrofblocks - 1;
+ point[1] = locY;
+ set = true;
+ } else {
+ locX--;
+ }
+ } else {
+ // Check for Right Warp
+ if (locX == this.m_map.m_nrofblocks - 1) {
+ point[0] = 0;
+ point[1] = locY;
+ set = true;
+ } else {
+ locX++;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ public void doMove() {
+ this.m_locX += this.m_dx;
+ this.m_locY += this.m_dy;
+ this.m_dx = 0;
+ this.m_dy = 0;
+ //System.printString("Pacmen " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");
+ }
+}
\ No newline at end of file
flag move;\r
flag update;\r
\r
- public int x;\r
- public int y;\r
- public int index;\r
- public int target;\r
- public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
- int dx;\r
- int dy;\r
- int destinationX;\r
- int destinationY;\r
- Map map;\r
+ public int m_locX;\r
+ public int m_locY;\r
+ public int m_index;\r
+ public int m_target;\r
+ public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
+ int m_dx;\r
+ int m_dy;\r
+ Map m_map;\r
\r
public Ghost(int x, int y, Map map) {\r
- this.x = x;\r
- this.y = y;\r
- this.dx = this.dy = 0;\r
- this.index = -1;\r
- this.target = -1;\r
- this.direction = 0;\r
- this.destinationX = -1;\r
- this.destinationY = -1;\r
- this.map = map;\r
- }\r
- \r
- public void setTarget(int pacman) {\r
- this.target = pacman;\r
+ this.m_locX = x;\r
+ this.m_locY = y;\r
+ this.m_dx = this.m_dy = 0;\r
+ this.m_index = -1;\r
+ this.m_target = -1;\r
+ this.m_direction = 0;\r
+ this.m_map = map;\r
}\r
\r
// 0:still, 1:up, 2:down, 3:left, 4:right\r
public void tryMove() {\r
//System.printString("step 1\n");\r
- //System.printString("target: " + this.target + "\n");\r
- \r
- // Don't let the ghost go back the way it came.\r
- int prevDirection = 0;\r
+ int i = 0;\r
\r
- // If there is a destination, then check if the destination has been reached.\r
- if (destinationX >= 0 && destinationY >= 0) {\r
- // Check if the destination has been reached, if so, then\r
- // get new destination.\r
- if (destinationX == x && destinationY == y) {\r
- destinationX = -1;\r
- destinationY = -1;\r
- prevDirection = direction;\r
- } else {\r
- // Otherwise, we haven't reached the destionation so\r
- // continue in same direction.\r
- return;\r
+ // check the nearest pacman and set it as current target\r
+ this.m_target = -1;\r
+ int deltaX = this.m_map.m_nrofblocks;\r
+ int deltaY = this.m_map.m_nrofblocks;\r
+ int distance = deltaX * deltaX + deltaY * deltaY;\r
+ for(i = 0; i < this.m_map.m_nrofpacs; i++) {\r
+ if(this.m_map.m_pacMenX[i] != -1) {\r
+ int dx = this.m_locX - this.m_map.m_pacMenX[i];\r
+ int dy = this.m_locY - this.m_map.m_pacMenY[i];\r
+ int dd = dx*dx+dy*dy;\r
+ if(distance > dd) {\r
+ this.m_target = i;\r
+ distance = dd;\r
+ deltaX = dx;\r
+ deltaY = dy;\r
+ }\r
}\r
}\r
- setNextDirection (prevDirection);\r
+ // System.printString("target: " + this.m_target + "\n");\r
+ \r
+ if(this.m_target == -1) {\r
+ // no more pacmen to chase, stay still\r
+ this.m_dx = 0;\r
+ this.m_dy = 0;\r
+ this.m_direction = this.m_map.m_ghostdirections[this.m_index] = 0;\r
+ return;\r
+ }\r
+ \r
+ // find the shortest possible way to the chosen target\r
+ setNextDirection();\r
}\r
\r
- private void setNextDirection(int prevDirection) {\r
+ private void setNextDirection() {\r
+ // current position of the ghost\r
+ Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];\r
+ \r
// get target's position\r
- int targetx = this.map.pacMenX[this.target];\r
- //System.printString("aaa\n");\r
- int targety = this.map.pacMenY[this.target];\r
+ int targetx = this.m_map.m_pacMenX[this.m_target];\r
+ int targety = this.m_map.m_pacMenY[this.m_target];\r
int[] nextLocation = new int[2];\r
nextLocation[0] = nextLocation[1] = -1;\r
- \r
- //System.printString("bbb\n");\r
- if(targetx == -1) {\r
- //System.printString("a\n");\r
- // already kicked off, choose another target\r
- int i = 0;\r
- boolean found = false;\r
- while((!found) && (i < map.pacMenX.length)) {\r
- if(this.map.pacMenX[i] != -1) {\r
- this.target = i;\r
- targetx = this.map.pacMenX[i];\r
- targety = this.map.pacMenY[i];\r
- this.map.targets[i] = this.target;\r
- found = true;\r
- }\r
- i++;\r
- }\r
- //System.printString("b\n");\r
- if(i == this.map.pacMenX.length) {\r
- //System.printString("c\n");\r
- // no more pacmen to chase\r
- this.dx = 0;\r
- this.dy = 0;\r
- this.direction = 0;\r
- return;\r
- }\r
- //System.printString("d\n");\r
- }\r
- getDestination (this.map.directions[this.target], targetx, targety, nextLocation);\r
+ // check the target pacman's possible destination\r
+ getDestination (this.m_map.m_directions[this.m_target], targetx, targety, nextLocation);\r
targetx = nextLocation[0];\r
targety = nextLocation[1];\r
+ // target's position\r
+ Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];\r
+ // reset the target as index of the end node\r
+ this.m_target = this.m_map.m_targets[this.m_index] = end.getIndex();\r
\r
- //System.printString("step 2\n");\r
- // check the distance\r
- int deltax = this.x - targetx; // <0: move right; >0: move left\r
- int deltay = this.y - targety; // <0: move down; >0: move up\r
- // decide the priority of four moving directions\r
- int[] bestDirection = new int[4];\r
- //System.printString("dx: " + deltax + "; dy: " + deltay + "\n");\r
- if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) {\r
- // go first along y\r
- if(deltay > 0) {\r
- bestDirection[0] = 1;\r
- bestDirection[3] = 2;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
+ // breadth-first traverse the graph view of the maze\r
+ // check the shortest path for the start node to the end node\r
+ boolean set = false;\r
+ Vector cuts = new Vector();\r
+ int tmpdx = 0;\r
+ int tmpdy = 0;\r
+ int tmpdirection = 0;\r
+ boolean first = true;\r
+ while(!set) {\r
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];\r
+ for(int i = 0; i < parents.length; i++) {\r
+ parents[i] = -1;\r
+ }\r
+ if(!BFS(start, end, parents, cuts)) {\r
+ this.m_dx = tmpdx;\r
+ this.m_dy = tmpdy;\r
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;\r
+ set = true;\r
+ //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");\r
} else {\r
- bestDirection[0] = 2;\r
- bestDirection[3] = 1;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
+ // Reversely go over the parents array to find the next node to reach\r
+ boolean found = false;\r
+ int index = end.getIndex();\r
+ while(!found) {\r
+ int parent = parents[index];\r
+ if(parent == start.getIndex()) {\r
+ found = true;\r
+ } else {\r
+ index = parent;\r
+ }\r
}\r
- }\r
- } else {\r
- if(deltax > 0) {\r
- bestDirection[0] = 3;\r
- bestDirection[3] = 4;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+\r
+ // set the chase direction\r
+ int nx = this.m_map.m_mapNodes[index].getXLoc();\r
+ int ny = this.m_map.m_mapNodes[index].getYLoc();\r
+ this.m_dx = nx - this.m_locX;\r
+ this.m_dy = ny - this.m_locY;\r
+ if(this.m_dx > 0) {\r
+ // right\r
+ this.m_direction = 4;\r
+ } else if(this.m_dx < 0) {\r
+ // left\r
+ this.m_direction = 3;\r
+ } else if(this.m_dy > 0) {\r
+ // down\r
+ this.m_direction = 2;\r
+ } else if(this.m_dy < 0) {\r
+ // up\r
+ this.m_direction = 1;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ // still\r
+ this.m_direction = 0;\r
}\r
- } else {\r
- bestDirection[0] = 4;\r
- bestDirection[3] = 3;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+ if(first) {\r
+ tmpdx = this.m_dx;\r
+ tmpdy = this.m_dy;\r
+ tmpdirection = this.m_direction;\r
+ first = false;\r
+ //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");\r
+ }\r
+\r
+ // check if this choice follows some other ghosts' path\r
+ if(!isFollowing()) {\r
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction;\r
+ set = true;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ cuts.addElement(new Integer(index));\r
+ /*for( int h = 0; h < cuts.size(); h++) {\r
+ System.printString(cuts.elementAt(h) + ", ");\r
+ }\r
+ System.printString("\n");*/\r
}\r
}\r
}\r
- /*for(int i = 0; i < 4; i++) {\r
- System.printString(bestDirection[i] + ",");\r
- }\r
- System.printString("\n");*/\r
- \r
- // There's a 50% chance that the ghost will try the sub-optimal direction first.\r
- // This will keep the ghosts from following each other and to trap Pacman.\r
- if (this.map.r.nextDouble() < .50) { \r
- int temp = bestDirection[0];\r
- bestDirection[0] = bestDirection[1];\r
- bestDirection[1] = temp;\r
- }\r
- \r
- //System.printString("step 3\n");\r
- // try to move one by one\r
- int i = 0;\r
- boolean set = false;\r
- this.dx = 0;\r
- this.dy = 0;\r
- while((!set) && (i < 4)) {\r
- if(bestDirection[i] == 1) {\r
- // try to move up\r
- if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) {\r
- //System.printString("a\n");\r
- if (getDestination (1, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = -1;\r
- set = true;\r
+ }\r
+ \r
+ // This methos do BFS from start node to end node\r
+ // If there is a path from start to end, return true; otherwise, return false\r
+ // Array parents records parent for a node in the BFS search,\r
+// the last item of parents records the least steps to reach end node from start node\r
+ // Vector cuts specifies which nodes can not be the first one to access in this BFS\r
+ private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {\r
+ int steps = 0;\r
+ Vector toaccess = new Vector();\r
+ toaccess.addElement(start);\r
+ while(toaccess.size() > 0) {\r
+ // pull out the first one to access\r
+ Node access = (Node)toaccess.elementAt(0);\r
+ toaccess.removeElementAt(0);\r
+ if(access.getIndex() == end.getIndex()) {\r
+ // hit the end node\r
+ parents[parents.length - 1] = steps;\r
+ return true;\r
+ }\r
+ steps++;\r
+ Vector neighbours = access.getNeighbours();\r
+ for(int i = 0; i < neighbours.size(); i++) {\r
+ Node neighbour = (Node)neighbours.elementAt(i);\r
+ if(parents[neighbour.getIndex()] == -1) {\r
+ // not accessed\r
+ boolean ignore = false;\r
+ if(access.getIndex() == start.getIndex()) {\r
+ // start node, check if the neighbour node is in cuts\r
+ int j = 0;\r
+ while((!ignore) && (j < cuts.size())) {\r
+ int tmp = ((Integer)cuts.elementAt(j)).intValue();\r
+ if(tmp == neighbour.getIndex()) {\r
+ ignore = true;\r
+ }\r
+ j++;\r
+ }\r
}\r
- }\r
- } else if (bestDirection[i] == 2) {\r
- // try to move down\r
- if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) {\r
- //System.printString("b\n");\r
- if (getDestination (2, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = 1;\r
- set = true;\r
+ if(!ignore) {\r
+ parents[neighbour.getIndex()] = access.getIndex();\r
+ toaccess.addElement(neighbour);\r
}\r
}\r
- } else if (bestDirection[i] == 3) {\r
- // try to move left\r
- if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) {\r
- //System.printString("c\n");\r
- if (getDestination (3, this.x, this.y, nextLocation)) {\r
- this.dx = -1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
+ }\r
+ }\r
+ parents[parents.length - 1] = -1;\r
+ return false;\r
+ }\r
+ \r
+ // This method returns true if this ghost is traveling to the same\r
+ // destination with the same direction as another ghost.\r
+ private boolean isFollowing () {\r
+ boolean bFollowing = false;\r
+ double dRandom;\r
+\r
+ // If the ghost is in the same location as another ghost\r
+ // and moving in the same direction, then they are on\r
+ // top of each other and should not follow.\r
+ for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {\r
+ // Ignore myself\r
+ if (this.m_index != i) {\r
+ if (this.m_map.m_ghostsX[i] == this.m_locX &&\r
+ this.m_map.m_ghostsY[i] == this.m_locY &&\r
+ this.m_map.m_ghostdirections[i] == this.m_direction) {\r
+ return true;\r
}\r
- } else if (bestDirection[i] == 4) {\r
- // try to move right\r
- if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) {\r
- //System.printString("d\n");\r
- if (getDestination (4, this.x, this.y, nextLocation)) {\r
- this.dx = 1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
+ }\r
+ }\r
+\r
+ // This will allow ghosts to often\r
+ // clump together for easier eating\r
+ dRandom = this.m_map.m_r.nextDouble();\r
+ if (dRandom < .90) { \r
+ //if (m_bInsaneAI && dRandom < .25)\r
+ // return false;\r
+ //else\r
+ return false;\r
+ }\r
+\r
+ // If ghost is moving to the same location and using the\r
+ // same direction, then it is following another ghost. \r
+ for (int i = 0; i < this.m_map.m_ghostsX.length; i++) { \r
+ // Ignore myself \r
+ if (this.m_index != i) {\r
+ if (this.m_map.m_targets[i] == this.m_target &&\r
+ this.m_map.m_ghostdirections[i] == this.m_direction) {\r
+ return true;\r
}\r
}\r
- i++;\r
}\r
- //System.printString("step 4\n");\r
+\r
+ return bFollowing;\r
}\r
\r
// This method will take the specified location and direction and determine\r
// for the given location if the thing moved in that direction, what the\r
// next possible turning location would be.\r
- boolean getDestination (int direction, int locX, int locY, int[] point) {\r
+ private boolean getDestination (int direction, int locX, int locY, int[] point) {\r
// If the request direction is blocked by a wall, then just return the current location\r
- if ((direction == 1 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up\r
- (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left\r
- (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down\r
- (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right \r
+ if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up\r
+ ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left\r
+ ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down\r
+ ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right \r
point[0] = locX;\r
point[1] = locY;\r
return false;\r
// then return false.\r
if (locY < 0 ||\r
locX < 0 ||\r
- locY == this.map.nrofblocks ||\r
- locX == this.map.nrofblocks) {\r
+ locY == this.m_map.m_nrofblocks ||\r
+ locX == this.m_map.m_nrofblocks) {\r
return false;\r
}\r
\r
boolean set = false;\r
- // Determine next turning location..\r
+ // Determine next turning location.\r
while (!set) {\r
if (direction == 1 || direction == 2) { \r
// up or down\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // down\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down\r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
// Check for Top Warp\r
if (locY == 0) {\r
point[0] = locX;\r
- point[1] = this.map.nrofblocks - 1;\r
+ point[1] = this.m_map.m_nrofblocks - 1;\r
set = true;\r
} else {\r
locY--;\r
}\r
} else {\r
// Check for Bottom Warp\r
- if (locY == this.map.nrofblocks - 1) {\r
+ if (locY == this.m_map.m_nrofblocks - 1) {\r
point[0] = locX;\r
point[1] = 0;\r
set = true;\r
}\r
} else {\r
// left or right\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left \r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left \r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
if (direction == 3) {\r
// Check for Left Warp\r
if (locX == 0) {\r
- point[0] = this.map.nrofblocks - 1;\r
+ point[0] = this.m_map.m_nrofblocks - 1;\r
point[1] = locY;\r
set = true;\r
} else {\r
}\r
} else {\r
// Check for Right Warp\r
- if (locX == this.map.nrofblocks - 1) {\r
+ if (locX == this.m_map.m_nrofblocks - 1) {\r
point[0] = 0;\r
point[1] = locY;\r
set = true;\r
}\r
\r
public void doMove() {\r
- this.x += this.dx;\r
- this.y += this.dy;\r
- //this.dx = 0;\r
- //this.dy = 0;\r
+ this.m_locX += this.m_dx;\r
+ this.m_locY += this.m_dy;\r
+ this.m_dx = 0;\r
+ this.m_dy = 0;\r
+ //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");\r
}\r
}
\ No newline at end of file
\r
int i = 0;\r
// create ghosts\r
- for(i = 0; i < map.nrofghosts; i++) {\r
+ for(i = 0; i < map.m_nrofghosts; i++) {\r
Ghost ghost = new Ghost(7, 7, map){move};\r
- ghost.setTarget(i%map.nrofpacs);\r
- ghost.index = i;\r
+ ghost.m_index = i;\r
map.placeGhost(ghost);\r
- map.targets[i] = ghost.target;\r
}\r
// create pacmen\r
int tx = 14;\r
int ty = 14;\r
- for(i = 0; i < map.nrofpacs; i++) {\r
+ for(i = 0; i < map.m_nrofpacs; i++) {\r
Pacman pacman = new Pacman(5, 7, map){move};\r
pacman.setTarget(tx*(i/2), ty*(i%2));\r
- pacman.index = i;\r
+ pacman.m_index = i;\r
map.placePacman(pacman);\r
- map.desX[i] = tx*(i/2);\r
- map.desY[i] = ty*(i%2);\r
+ map.m_desX[i] = tx*(i/2);\r
+ map.m_desY[i] = ty*(i%2);\r
}\r
\r
- map.ghostcount = 0;\r
- map.paccount = 0;\r
+ map.m_ghostcount = 0;\r
+ map.m_paccount = 0;\r
\r
taskexit(map{!init, updateGhost});\r
}\r
if(isavailable(g)) {\r
g.doMove();\r
map.placeGhost(g);\r
- map.ghostdirections[g.index] = g.direction;\r
} else {\r
- //System.printString("FAILURE ghost!!!\n");\r
- //map.failghostcount++;\r
- map.ghostcount++;\r
+ map.m_ghostcount++;\r
}\r
\r
- if(map.ghostcount == map.nrofghosts) {\r
- //map.nrofghosts -= map.failghostcount;\r
- map.ghostcount = 0;\r
- map.failghostcount = 0;\r
- /*for(int i = 0; i < map.ghostsX.length; i++) {\r
- System.printString("(" + map.ghostsX[i] + "," + map.ghostsY[i] + ") ");\r
+ if(map.m_ghostcount == map.m_nrofghosts) {\r
+ //map.m_nrofghosts -= map.m_failghostcount;\r
+ map.m_ghostcount = 0;\r
+ map.m_failghostcount = 0;\r
+ /*for(int i = 0; i < map.m_ghostsX.length; i++) {\r
+ System.printString("(" + map.m_ghostsX[i] + "," + map.m_ghostsY[i] + ") ");\r
}\r
System.printString("\n");*/\r
taskexit(map{updatePac, !updateGhost}, g{!update});\r
if(isavailable(p)) {\r
p.doMove();\r
map.placePacman(p);\r
- map.directions[p.index] = p.direction;\r
- //System.printString("Pacman " + p.index + ": (" + map.pacMenX[p.index] + "," + map.pacMenY[p.index] + ")\n");\r
+ //System.printString("Pacman " + p.m_index + ": (" + map.m_pacMenX[p.m_index] + "," + map.m_pacMenY[p.m_index] + ")\n");\r
boolean death = map.check(p);\r
/*if(death) {\r
- System.printString("Pacman " + p.index + " caught!\n");\r
+ System.printString("Pacman " + p.m_index + " caught!\n");\r
}*/\r
} else {\r
- //System.printString("FAILURE pacman!!!\n");\r
- map.deathcount++;\r
- map.paccount++;\r
+ map.m_deathcount++;\r
+ map.m_paccount++;\r
}\r
\r
- boolean finish = map.paccount == map.nrofpacs;\r
+ boolean finish = map.m_paccount == map.m_nrofpacs;\r
\r
if(finish) {\r
- map.nrofpacs -= map.deathcount;\r
- //System.printString(map.nrofpacs + " pacmen left. \n");\r
+ map.m_nrofpacs -= map.m_deathcount;\r
+ //System.printString(map.m_nrofpacs + " pacmen left. \n");\r
if(map.isfinish()) {\r
taskexit(map{finish, !updatePac}, p{!update, !move});\r
} else {\r
//System.printString("Task next\n");\r
\r
int i = 0;\r
- for(i = 0; i < map.nrofghosts; i++) {\r
- Ghost ghost = new Ghost(map.ghostsX[i], map.ghostsY[i], map){move};\r
- ghost.setTarget(map.targets[i]);\r
- ghost.index = i;\r
- ghost.direction = map.ghostdirections[i];\r
+ for(i = 0; i < map.m_nrofghosts; i++) {\r
+ Ghost ghost = new Ghost(map.m_ghostsX[i], map.m_ghostsY[i], map){move};\r
+ ghost.m_index = i;\r
+ ghost.m_direction = map.m_ghostdirections[i];\r
}\r
- for(i = 0; i < map.pacMenX.length; i++) {\r
- if(map.pacMenX[i] != -1) {\r
+ for(i = 0; i < map.m_pacMenX.length; i++) {\r
+ if(map.m_pacMenX[i] != -1) {\r
// still in the map\r
//System.printString("new Pacman\n");\r
- Pacman pacman = new Pacman(map.pacMenX[i], map.pacMenY[i], map){move};\r
- pacman.setTarget(map.desX[i], map.desY[i]);\r
- pacman.index = i;\r
- pacman.direction = map.directions[i];\r
+ Pacman pacman = new Pacman(map.m_pacMenX[i], map.m_pacMenY[i], map){move};\r
+ pacman.setTarget(map.m_desX[i], map.m_desY[i]);\r
+ pacman.m_index = i;\r
+ pacman.m_direction = map.m_directions[i];\r
}\r
}\r
\r
- map.paccount = 0;\r
- map.deathcount = 0;\r
+ map.m_paccount = 0;\r
+ map.m_deathcount = 0;\r
\r
taskexit(map{!next, updateGhost});\r
}\r
flag next;\r
flag finish;\r
\r
- public int[] map;\r
- public int[] pacMenX;\r
- public int[] pacMenY;\r
- public int[] directions;\r
- public int[] ghostsX;\r
- public int[] ghostsY;\r
- public int[] ghostdirections;\r
- public int[] targets;\r
- public int[] desX;\r
- public int[] desY;\r
+ // maze\r
+ private int m_nrofblocks;\r
+ public int[] m_map;\r
+ public Node[] m_mapNodes;\r
\r
- public int nrofghosts;\r
- public int nrofpacs;\r
- private int nrofblocks;\r
- //public boolean toupdate;\r
- public int ghostcount;\r
- public int paccount;\r
- public int deathcount;\r
- public int failghostcount;\r
+ // pacmen information\r
+ public int m_nrofpacs;\r
+ public int[] m_pacMenX;\r
+ public int[] m_pacMenY;\r
+ public int[] m_directions;\r
+ public int[] m_desX;\r
+ public int[] m_desY;\r
+ public int m_paccount;\r
+ public int m_deathcount;\r
\r
- public Random r;\r
+ // ghosts information\r
+ public int m_nrofghosts;\r
+ public int[] m_ghostsX;\r
+ public int[] m_ghostsY;\r
+ public int[] m_ghostdirections;\r
+ public int[] m_targets;\r
+ public int m_ghostcount;\r
+ public int m_failghostcount;\r
+ \r
+ // helper member\r
+ public Random m_r;\r
\r
public Map(int nrofpacs, int nrofghosts) {\r
//System.printString("step 1\n");\r
- this.nrofblocks = 15;\r
- this.map = new int[this.nrofblocks*this.nrofblocks];\r
- this.nrofpacs = nrofpacs;\r
- this.nrofghosts = nrofghosts;\r
- this.pacMenX = new int[this.nrofpacs];\r
- this.pacMenY = new int[this.nrofpacs];\r
- this.directions = new int[this.nrofpacs];\r
- this.ghostsX = new int[this.nrofghosts];\r
- this.ghostsY = new int[this.nrofghosts];\r
- this.ghostdirections = new int[this.nrofghosts];\r
- this.targets = new int[this.nrofghosts];\r
- this.desX = new int[this.nrofpacs];\r
- this.desY = new int[this.nrofpacs];\r
- //this.toupdate = false;\r
- this.ghostcount = 0;\r
- this.paccount = 0;\r
- this.deathcount = 0;\r
- this.failghostcount = 0;\r
+ this.m_nrofblocks = 15;\r
+ this.m_map = new int[this.m_nrofblocks*this.m_nrofblocks];\r
+ this.m_mapNodes = new Node[this.m_nrofblocks*this.m_nrofblocks];\r
+ \r
+ this.m_nrofpacs = nrofpacs;\r
+ this.m_pacMenX = new int[this.m_nrofpacs];\r
+ this.m_pacMenY = new int[this.m_nrofpacs];\r
+ this.m_directions = new int[this.m_nrofpacs];\r
+ this.m_desX = new int[this.m_nrofpacs];\r
+ this.m_desY = new int[this.m_nrofpacs];\r
+ this.m_paccount = 0;\r
+ this.m_deathcount = 0;\r
+ \r
+ this.m_nrofghosts = nrofghosts;\r
+ this.m_ghostsX = new int[this.m_nrofghosts];\r
+ this.m_ghostsY = new int[this.m_nrofghosts];\r
+ this.m_ghostdirections = new int[this.m_nrofghosts];\r
+ this.m_targets = new int[this.m_nrofghosts];\r
+ this.m_ghostcount = 0;\r
+ this.m_failghostcount = 0;\r
\r
- this.r = new Random();\r
+ this.m_r = new Random();\r
+ \r
+ for(int i = 0; i < this.m_nrofblocks*this.m_nrofblocks; i++) {\r
+ this.m_map[i] = -1;\r
+ this.m_mapNodes[i] = new Node(i%this.m_nrofblocks, i/this.m_nrofblocks, i);\r
+ }\r
\r
//System.printString("step 2\n");\r
- for(int i = 0; i < this.nrofpacs; i++) {\r
- this.pacMenX[i] = this.pacMenY[i] = -1;\r
- this.desX[i] = this.desY[i] = -1;\r
+ for(int i = 0; i < this.m_nrofpacs; i++) {\r
+ this.m_pacMenX[i] = this.m_pacMenY[i] = -1;\r
+ this.m_desX[i] = this.m_desY[i] = -1;\r
}\r
//System.printString("step 3\n");\r
- for(int i = 0; i < this.nrofghosts; i++) {\r
- this.ghostsX[i] = this.ghostsY[i] = -1;\r
- this.targets[i] = -1;\r
+ for(int i = 0; i < this.m_nrofghosts; i++) {\r
+ this.m_ghostsX[i] = this.m_ghostsY[i] = -1;\r
+ this.m_targets[i] = -1;\r
}\r
//System.printString("step 4\n");\r
}\r
\r
public void init() {\r
+ // initilize the maze\r
int i = 0;\r
- this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;this.map[i++]=9;this.map[i++]=12;this.map[i++]=3;this.map[i++]=10;this.map[i++]=6;this.map[i++]=9;this.map[i++]=12;this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;\r
- this.map[i++]=5;this.map[i++]=11;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=15;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=14;this.map[i++]=5;\r
- this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=6;this.map[i++]=1;this.map[i++]=10;this.map[i++]=4;this.map[i++]=3;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;\r
- this.map[i++]=5;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=6;this.map[i++]=5;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=5;this.map[i++]=3;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=5;\r
- this.map[i++]=5;this.map[i++]=9;this.map[i++]=8;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=8;this.map[i++]=12;this.map[i++]=5;\r
- this.map[i++]=9;this.map[i++]=2;this.map[i++]=10;this.map[i++]=2;this.map[i++]=8;this.map[i++]=2;this.map[i++]=12;this.map[i++]=5;this.map[i++]=9;this.map[i++]=2;this.map[i++]=8;this.map[i++]=2;this.map[i++]=10;this.map[i++]=2;this.map[i++]=12;\r
- this.map[i++]=6;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=11;this.map[i++]=8;this.map[i++]=14;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=7;this.map[i++]=5;this.map[i++]=3;\r
- this.map[i++]=4;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=10;this.map[i++]=10;this.map[i++]=10;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=5;this.map[i++]=1;\r
- this.map[i++]=12;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=10;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=13;this.map[i++]=5;this.map[i++]=9;\r
- this.map[i++]=3;this.map[i++]=8;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=0;this.map[i++]=10;this.map[i++]=2;this.map[i++]=10;this.map[i++]=0;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=8;this.map[i++]=6;\r
- this.map[i++]=5;this.map[i++]=3;this.map[i++]=2;this.map[i++]=2;this.map[i++]=6;this.map[i++]=5;this.map[i++]=15;this.map[i++]=5;this.map[i++]=15;this.map[i++]=5;this.map[i++]=3;this.map[i++]=2;this.map[i++]=2;this.map[i++]=6;this.map[i++]=5;\r
- this.map[i++]=5;this.map[i++]=9;this.map[i++]=8;this.map[i++]=8;this.map[i++]=4;this.map[i++]=1;this.map[i++]=10;this.map[i++]=8;this.map[i++]=10;this.map[i++]=4;this.map[i++]=1;this.map[i++]=8;this.map[i++]=8;this.map[i++]=12;this.map[i++]=5;\r
- this.map[i++]=1;this.map[i++]=10;this.map[i++]=10;this.map[i++]=6;this.map[i++]=13;this.map[i++]=5;this.map[i++]=11;this.map[i++]=2;this.map[i++]=14;this.map[i++]=5;this.map[i++]=13;this.map[i++]=3;this.map[i++]=10;this.map[i++]=10;this.map[i++]=4;\r
- this.map[i++]=5;this.map[i++]=11;this.map[i++]=14;this.map[i++]=1;this.map[i++]=10;this.map[i++]=8;this.map[i++]=6;this.map[i++]=13;this.map[i++]=3;this.map[i++]=8;this.map[i++]=10;this.map[i++]=4;this.map[i++]=11;this.map[i++]=14;this.map[i++]=5;\r
- this.map[i++]=9;this.map[i++]=10;this.map[i++]=10;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=10;this.map[i++]=12;this.map[i++]=3;this.map[i++]=6;this.map[i++]=9;this.map[i++]=10;this.map[i++]=10;this.map[i++]=12; // 15*15 \r
+ this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;\r
+ this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=15;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=5;\r
+ this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=6;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=3;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;\r
+ this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=5;\r
+ this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=8;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=8;this.m_map[i++]=12;this.m_map[i++]=5;\r
+ this.m_map[i++]=9;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=8;this.m_map[i++]=2;this.m_map[i++]=12;this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=2;this.m_map[i++]=8;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=12;\r
+ this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=8;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=7;this.m_map[i++]=5;this.m_map[i++]=3;\r
+ this.m_map[i++]=4;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=5;this.m_map[i++]=1;\r
+ this.m_map[i++]=12;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=10;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=9;\r
+ this.m_map[i++]=3;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=0;this.m_map[i++]=10;this.m_map[i++]=2;this.m_map[i++]=10;this.m_map[i++]=0;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=6;\r
+ this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=2;this.m_map[i++]=2;this.m_map[i++]=6;this.m_map[i++]=5;this.m_map[i++]=15;this.m_map[i++]=5;this.m_map[i++]=15;this.m_map[i++]=5;this.m_map[i++]=3;this.m_map[i++]=2;this.m_map[i++]=2;this.m_map[i++]=6;this.m_map[i++]=5;\r
+ this.m_map[i++]=5;this.m_map[i++]=9;this.m_map[i++]=8;this.m_map[i++]=8;this.m_map[i++]=4;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=1;this.m_map[i++]=8;this.m_map[i++]=8;this.m_map[i++]=12;this.m_map[i++]=5;\r
+ this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=6;this.m_map[i++]=13;this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=2;this.m_map[i++]=14;this.m_map[i++]=5;this.m_map[i++]=13;this.m_map[i++]=3;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=4;\r
+ this.m_map[i++]=5;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=1;this.m_map[i++]=10;this.m_map[i++]=8;this.m_map[i++]=6;this.m_map[i++]=13;this.m_map[i++]=3;this.m_map[i++]=8;this.m_map[i++]=10;this.m_map[i++]=4;this.m_map[i++]=11;this.m_map[i++]=14;this.m_map[i++]=5;\r
+ this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=12;this.m_map[i++]=3;this.m_map[i++]=6;this.m_map[i++]=9;this.m_map[i++]=10;this.m_map[i++]=10;this.m_map[i++]=12; // 15*15\r
+ \r
+ // initilize the graph of the maze\r
+ for(i = 0; i < this.m_nrofblocks*this.m_nrofblocks; i++) {\r
+ int tmp = this.m_map[i];\r
+ Node tmpNode = this.m_mapNodes[i];\r
+ int locX = tmpNode.getXLoc();\r
+ int locY = tmpNode.getYLoc();\r
+ if((int)(tmp & 1) == 0) {\r
+ // can go left\r
+ if(locX == 0) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[locY * this.m_nrofblocks + this.m_nrofblocks - 1]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[i - 1]);\r
+ }\r
+ } \r
+ if((int)(tmp & 2) == 0) {\r
+ // can go up\r
+ if(locY == 0) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[(this.m_nrofblocks - 1) * this.m_nrofblocks + locX]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[(locY - 1) * this.m_nrofblocks + locX]);\r
+ }\r
+ }\r
+ if((int)(tmp & 4) == 0) {\r
+ // can go right\r
+ if(locX == this.m_nrofblocks - 1) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[locY * this.m_nrofblocks]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[i + 1]);\r
+ }\r
+ }\r
+ if((int)(tmp & 8) == 0) {\r
+ // can go down\r
+ if(locY == this.m_nrofblocks - 1) {\r
+ tmpNode.addNeighbour(this.m_mapNodes[locX]);\r
+ } else {\r
+ tmpNode.addNeighbour(this.m_mapNodes[(locY + 1) * this.m_nrofblocks + locX]);\r
+ }\r
+ }\r
+ }\r
} \r
\r
public void placePacman(Pacman t) {\r
- this.pacMenX[t.index] = t.x;\r
- this.pacMenY[t.index] = t.y;\r
- //this.map[t.y * this.nrofblocks + t.x - 1] |= 16;\r
- this.paccount++;\r
+ this.m_pacMenX[t.m_index] = t.m_locX;\r
+ this.m_pacMenY[t.m_index] = t.m_locY;\r
+ this.m_paccount++;\r
}\r
\r
public void placeGhost(Ghost t) {\r
- this.ghostsX[t.index] = t.x;\r
- this.ghostsY[t.index] = t.y;\r
- //this.map[t.y * this.nrofblocks + t.x - 1] |= 32;\r
- this.ghostcount++;\r
+ this.m_ghostsX[t.m_index] = t.m_locX;\r
+ this.m_ghostsY[t.m_index] = t.m_locY;\r
+ this.m_ghostcount++;\r
}\r
\r
public boolean check(Pacman t) {\r
boolean death = false;\r
int i = 0;\r
- while((!death) && (i < this.nrofghosts)) {\r
- if((t.x == this.ghostsX[i]) && (t.y == this.ghostsY[i])) {\r
+ while((!death) && (i < this.m_ghostsX.length)) {\r
+ if((t.m_locX == this.m_ghostsX[i]) && (t.m_locY == this.m_ghostsY[i])) {\r
death = true;\r
}\r
i++;\r
}\r
- if((!death) && (t.x == t.tx) && (t.y == t.ty)) {\r
+ if((!death) && (t.m_locX == t.m_tx) && (t.m_locY == t.m_ty)) {\r
// reach the destination\r
//System.printString("Hit destination!\n");\r
death = true;\r
if(death) {\r
// pacman caught by ghost\r
// set pacman as death\r
- t.death = true;\r
+ t.m_death = true;\r
// kick it out\r
- //this.map[t.y * this.nrofblocks + t.x - 1] -= 16;\r
- this.deathcount++;\r
- this.pacMenX[t.index] = -1;\r
- this.pacMenY[t.index] = -1;\r
+ //this.m_map[t.y * this.m_nrofblocks + t.x - 1] -= 16;\r
+ this.m_deathcount++;\r
+ this.m_pacMenX[t.m_index] = -1;\r
+ this.m_pacMenY[t.m_index] = -1;\r
}\r
return death;\r
}\r
\r
public boolean isfinish() {\r
- return nrofpacs == 0;\r
+ return this.m_nrofpacs == 0;\r
}\r
}
\ No newline at end of file
--- /dev/null
+public class Node {
+
+ int m_locX;
+ int m_locY;
+ int m_index;
+ Vector m_neighbours;
+
+ public Node(int locX, int locY, int index) {
+ this.m_locX = locX;
+ this.m_locY = locY;
+ this.m_index = index;
+ this.m_neighbours = new Vector();
+ }
+
+ public void addNeighbour(Node n) {
+ this.m_neighbours.addElement(n);
+ }
+
+ public Vector getNeighbours() {
+ return this.m_neighbours;
+ }
+
+ public int getXLoc() {
+ return this.m_locX;
+ }
+
+ public int getYLoc() {
+ return this.m_locY;
+ }
+
+ public int getIndex() {
+ return this.m_index;
+ }
+}
\ No newline at end of file
flag move;\r
flag update;\r
\r
- public int x;\r
- public int y;\r
- public boolean death;\r
- public int index;\r
- public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
- int dx;\r
- int dy;\r
- public int tx;\r
- public int ty;\r
- int destinationX;\r
- int destinationY;\r
- Map map;\r
+ public int m_locX;\r
+ public int m_locY;\r
+ public boolean m_death;\r
+ public int m_index;\r
+ public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right\r
+ int m_dx;\r
+ int m_dy;\r
+ public int m_tx;\r
+ public int m_ty;\r
+ Map m_map;\r
\r
public Pacman(int x, int y, Map map) {\r
- this.x = x;\r
- this.y = y;\r
- this.dx = this.dy = 0;\r
- this.death = false;\r
- this.index = -1;\r
- this.tx = this.ty = -1;\r
- this.direction = 0;\r
- this.destinationX = -1;\r
- this.destinationY = -1;\r
- this.map = map;\r
+ this.m_locX = x;\r
+ this.m_locY = y;\r
+ this.m_dx = this.m_dy = 0;\r
+ this.m_death = false;\r
+ this.m_index = -1;\r
+ this.m_tx = this.m_ty = -1;\r
+ this.m_direction = 0;\r
+ this.m_map = map;\r
}\r
\r
public void setTarget(int x, int y) {\r
- this.tx = x;\r
- this.ty = y;\r
+ this.m_tx = x;\r
+ this.m_ty = y;\r
}\r
\r
public void tryMove() {\r
// decide dx & dy\r
-\r
- // Don't let the pacman go back the way it came.\r
- int prevDirection = 0;\r
-\r
- // If there is a destination, then check if the destination has been reached.\r
- if (destinationX >= 0 && destinationY >= 0) {\r
- // Check if the destination has been reached, if so, then\r
- // get new destination.\r
- if (destinationX == x && destinationY == y) {\r
- destinationX = -1;\r
- destinationY = -1;\r
- prevDirection = direction;\r
- } else {\r
- // Otherwise, we haven't reached the destionation so\r
- // continue in same direction.\r
- return;\r
- }\r
- }\r
- setNextDirection (prevDirection);\r
+ \r
+ // find the shortest possible way to the chosen target\r
+ setNextDirection();\r
}\r
\r
- private void setNextDirection(int prevDirection) {\r
+ private void setNextDirection() {\r
+ // current position of the ghost\r
+ Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];\r
+ \r
// get target's position\r
- int targetx = this.tx;\r
- //System.printString("aaa\n");\r
- int targety = this.ty;\r
+ int targetx = this.m_tx;\r
+ int targety = this.m_ty;\r
int[] nextLocation = new int[2];\r
nextLocation[0] = nextLocation[1] = -1;\r
\r
- //System.printString("bbb\n");\r
- getDestination (this.direction, targetx, targety, nextLocation);\r
- targetx = nextLocation[0];\r
- targety = nextLocation[1];\r
+ // target's position\r
+ Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];\r
\r
- //System.printString("step 2\n");\r
- // check the distance\r
- int deltax = this.x - targetx; // <0: move right; >0: move left\r
- int deltay = this.y - targety; // <0: move down; >0: move up\r
- // decide the priority of four moving directions\r
- int[] bestDirection = new int[4];\r
- //System.printString("dx: " + deltax + "; dy: " + deltay + "\n");\r
- if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) {\r
- // go first along y\r
- if(deltay > 0) {\r
- bestDirection[0] = 1;\r
- bestDirection[3] = 2;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
- }\r
+ // breadth-first traverse the graph view of the maze\r
+ // check the shortest path for the start node to the end node\r
+ boolean set = false;\r
+ Vector cuts = new Vector();\r
+ int tmpdx = 0;\r
+ int tmpdy = 0;\r
+ int tmpdirection = 0;\r
+ boolean first = true;\r
+ while(!set) {\r
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];\r
+ for(int i = 0; i < parents.length; i++) {\r
+ parents[i] = -1;\r
+ }\r
+ if(!BFS(start, end, parents, cuts)) {\r
+ this.m_dx = tmpdx;\r
+ this.m_dy = tmpdy;\r
+ this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;\r
+ set = true;\r
+ //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");\r
} else {\r
- bestDirection[0] = 2;\r
- bestDirection[3] = 1;\r
- if(deltax > 0) {\r
- bestDirection[1] = 3;\r
- bestDirection[2] = 4;\r
- } else {\r
- bestDirection[1] = 4;\r
- bestDirection[2] = 3;\r
+ // Reversely go over the parents array to find the next node to reach\r
+ boolean found = false;\r
+ int index = end.getIndex();\r
+ while(!found) {\r
+ int parent = parents[index];\r
+ if(parent == start.getIndex()) {\r
+ found = true;\r
+ } else {\r
+ index = parent;\r
+ }\r
}\r
- }\r
- } else {\r
- if(deltax > 0) {\r
- bestDirection[0] = 3;\r
- bestDirection[3] = 4;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+\r
+ // set the chase direction\r
+ int nx = this.m_map.m_mapNodes[index].getXLoc();\r
+ int ny = this.m_map.m_mapNodes[index].getYLoc();\r
+ this.m_dx = nx - this.m_locX;\r
+ this.m_dy = ny - this.m_locY;\r
+ if(this.m_dx > 0) {\r
+ // right\r
+ this.m_direction = 4;\r
+ } else if(this.m_dx < 0) {\r
+ // left\r
+ this.m_direction = 3;\r
+ } else if(this.m_dy > 0) {\r
+ // down\r
+ this.m_direction = 2;\r
+ } else if(this.m_dy < 0) {\r
+ // up\r
+ this.m_direction = 1;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ // still\r
+ this.m_direction = 0;\r
}\r
- } else {\r
- bestDirection[0] = 4;\r
- bestDirection[3] = 3;\r
- if(deltay > 0) {\r
- bestDirection[1] = 1;\r
- bestDirection[2] = 2;\r
+ if(first) {\r
+ tmpdx = this.m_dx;\r
+ tmpdy = this.m_dy;\r
+ tmpdirection = this.m_direction;\r
+ first = false;\r
+ //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");\r
+ }\r
+\r
+ // check if this choice follows some other ghosts' path\r
+ if(canFlee()) {\r
+ this.m_map.m_directions[this.m_index] = this.m_direction;\r
+ set = true;\r
} else {\r
- bestDirection[1] = 2;\r
- bestDirection[2] = 1;\r
+ cuts.addElement(new Integer(index));\r
+ /*for( int h = 0; h < cuts.size(); h++) {\r
+ System.printString(cuts.elementAt(h) + ", ");\r
+ }\r
+ System.printString("\n");*/\r
}\r
}\r
}\r
- /*for(int i = 0; i < 4; i++) {\r
- System.printString(bestDirection[i] + ",");\r
+ }\r
+ \r
+ // This methos do BFS from start node to end node\r
+ // If there is a path from start to end, return true; otherwise, return false\r
+ // Array parents records parent for a node in the BFS search, \r
+ // the last item of parents records the least steps to reach end node from start node\r
+ // Vector cuts specifies which nodes can not be the first one to access in this BFS\r
+ private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {\r
+ int steps = 0;\r
+ Vector toaccess = new Vector();\r
+ toaccess.addElement(start);\r
+ while(toaccess.size() > 0) {\r
+ // pull out the first one to access\r
+ Node access = (Node)toaccess.elementAt(0);\r
+ toaccess.removeElementAt(0);\r
+ if(access.getIndex() == end.getIndex()) {\r
+ // hit the end node\r
+ parents[parents.length - 1] = steps;\r
+ return true;\r
+ }\r
+ steps++;\r
+ Vector neighbours = access.getNeighbours();\r
+ for(int i = 0; i < neighbours.size(); i++) {\r
+ Node neighbour = (Node)neighbours.elementAt(i);\r
+ if(parents[neighbour.getIndex()] == -1) {\r
+ // not accessed\r
+ boolean ignore = false;\r
+ if(access.getIndex() == start.getIndex()) {\r
+ // start node, check if the neighbour node is in cuts\r
+ int j = 0;\r
+ while((!ignore) && (j < cuts.size())) {\r
+ int tmp = ((Integer)cuts.elementAt(j)).intValue();\r
+ if(tmp == neighbour.getIndex()) {\r
+ ignore = true;\r
+ }\r
+ j++;\r
+ }\r
+ }\r
+ if(!ignore) {\r
+ parents[neighbour.getIndex()] = access.getIndex();\r
+ toaccess.addElement(neighbour);\r
+ }\r
+ }\r
+ }\r
}\r
- System.printString("\n");*/\r
+ parents[parents.length - 1] = -1;\r
+ return false;\r
+ }\r
+ \r
+ // This method returns true if this pacmen can flee in this direction.\r
+ private boolean canFlee () {\r
+ int steps = 0;\r
+ int locX = this.m_locX;\r
+ int locY = this.m_locY;\r
+ int[] point = new int[2];\r
+ point[0] = point[1] = -1;\r
\r
- // There's a 50% chance that the ghost will try the sub-optimal direction first.\r
- // This will keep the ghosts from following each other and to trap Pacman.\r
- if (this.map.r.nextDouble() < .50) { \r
- int temp = bestDirection[0];\r
- bestDirection[0] = bestDirection[1];\r
- bestDirection[1] = temp;\r
+ // Start off by advancing one in direction for specified location\r
+ if (this.m_direction == 1) {\r
+ // up\r
+ locY--;\r
+ } else if (this.m_direction == 2) {\r
+ // down\r
+ locY++;\r
+ } else if (this.m_direction == 3) {\r
+ // left\r
+ locX--;\r
+ } else if (this.m_direction == 4) {\r
+ // right\r
+ locX++;\r
}\r
- \r
- //System.printString("step 3\n");\r
- // try to move one by one\r
- int i = 0;\r
+ steps++; \r
+ \r
boolean set = false;\r
- this.dx = 0;\r
- this.dy = 0;\r
- while((!set) && (i < 4)) {\r
- if(bestDirection[i] == 1) {\r
- // try to move up\r
- if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) {\r
- //System.printString("a\n");\r
- if (getDestination (1, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = -1;\r
- set = true;\r
- }\r
- }\r
- } else if (bestDirection[i] == 2) {\r
- // try to move down\r
- if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) {\r
- //System.printString("b\n");\r
- if (getDestination (2, this.x, this.y, nextLocation)) {\r
- this.dx = 0;\r
- this.dy = 1;\r
- set = true;\r
+ // Determine next turning location.\r
+ while (!set) {\r
+ if (this.m_direction == 1 || this.m_direction == 2) { \r
+ // up or down\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down\r
+ point[0] = locX;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ if (this.m_direction == 1) {\r
+ // Check for Top Warp\r
+ if (locY == 0) {\r
+ point[0] = locX;\r
+ point[1] = this.m_map.m_nrofblocks - 1;\r
+ set = true;\r
+ } else {\r
+ locY--;\r
+ steps++;\r
+ }\r
+ } else {\r
+ // Check for Bottom Warp\r
+ if (locY == this.m_map.m_nrofblocks - 1) {\r
+ point[0] = locX;\r
+ point[1] = 0;\r
+ set = true;\r
+ } else {\r
+ locY++;\r
+ steps++;\r
+ }\r
}\r
}\r
- } else if (bestDirection[i] == 3) {\r
- // try to move left\r
- if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) {\r
- //System.printString("c\n");\r
- if (getDestination (3, this.x, this.y, nextLocation)) {\r
- this.dx = -1;\r
- this.dy = 0;\r
- set = true;\r
+ } else {\r
+ // left or right\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left \r
+ point[0] = locX;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ if (this.m_direction == 3) {\r
+ // Check for Left Warp\r
+ if (locX == 0) {\r
+ point[0] = this.m_map.m_nrofblocks - 1;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ locX--;\r
+ steps++;\r
+ }\r
+ } else {\r
+ // Check for Right Warp\r
+ if (locX == this.m_map.m_nrofblocks - 1) {\r
+ point[0] = 0;\r
+ point[1] = locY;\r
+ set = true;\r
+ } else {\r
+ locX++;\r
+ steps++;\r
+ }\r
}\r
}\r
- } else if (bestDirection[i] == 4) {\r
- // try to move right\r
- if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) {\r
- //System.printString("d\n");\r
- if (getDestination (4, this.x, this.y, nextLocation)) {\r
- this.dx = 1;\r
- this.dy = 0;\r
- set = true;\r
- }\r
+ }\r
+ }\r
+ \r
+ // check the least steps for the ghosts to reach point location\r
+ int chasesteps = -1;\r
+ Node end = this.m_map.m_mapNodes[point[1] * this.m_map.m_nrofblocks + point[0]];\r
+ for(int i = 0; i < this.m_map.m_ghostsX.length; i++) {\r
+ Node start = this.m_map.m_mapNodes[this.m_map.m_ghostsY[i] * this.m_map.m_nrofblocks + this.m_map.m_ghostsX[i]];\r
+ int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];\r
+ for(int j = 0; j < parents.length; j++) {\r
+ parents[j] = -1;\r
+ }\r
+ if(BFS(start, end, parents, new Vector())) {\r
+ if((chasesteps == -1) ||\r
+ (chasesteps > parents[parents.length - 1])) {\r
+ chasesteps = parents[parents.length - 1];\r
}\r
}\r
- i++;\r
}\r
- //System.printString("step 4\n");\r
+\r
+ return ((chasesteps == -1) || (steps < chasesteps));\r
}\r
\r
// This method will take the specified location and direction and determine\r
// for the given location if the thing moved in that direction, what the\r
// next possible turning location would be.\r
- boolean getDestination (int direction, int locX, int locY, int[] point) {\r
+ private boolean getDestination (int direction, int locX, int locY, int[] point) {\r
// If the request direction is blocked by a wall, then just return the current location\r
- if ((direction == 1 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up\r
- (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left\r
- (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down\r
- (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right \r
+ if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up\r
+ ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left\r
+ ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down\r
+ ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right \r
point[0] = locX;\r
point[1] = locY;\r
return false;\r
// then return false.\r
if (locY < 0 ||\r
locX < 0 ||\r
- locY == this.map.nrofblocks ||\r
- locX == this.map.nrofblocks) {\r
+ locY == this.m_map.m_nrofblocks ||\r
+ locX == this.m_map.m_nrofblocks) {\r
return false;\r
}\r
\r
boolean set = false;\r
- // Determine next turning location..\r
+ // Determine next turning location.\r
while (!set) {\r
if (direction == 1 || direction == 2) { \r
// up or down\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // down\r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down\r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
// Check for Top Warp\r
if (locY == 0) {\r
point[0] = locX;\r
- point[1] = this.map.nrofblocks - 1;\r
+ point[1] = this.m_map.m_nrofblocks - 1;\r
set = true;\r
} else {\r
locY--;\r
}\r
} else {\r
// Check for Bottom Warp\r
- if (locY == this.map.nrofblocks - 1) {\r
+ if (locY == this.m_map.m_nrofblocks - 1) {\r
point[0] = locX;\r
point[1] = 0;\r
set = true;\r
}\r
} else {\r
// left or right\r
- if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right\r
- (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left \r
+ if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right\r
+ ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left \r
point[0] = locX;\r
point[1] = locY;\r
set = true;\r
if (direction == 3) {\r
// Check for Left Warp\r
if (locX == 0) {\r
- point[0] = this.map.nrofblocks - 1;\r
+ point[0] = this.m_map.m_nrofblocks - 1;\r
point[1] = locY;\r
set = true;\r
} else {\r
}\r
} else {\r
// Check for Right Warp\r
- if (locX == this.map.nrofblocks - 1) {\r
+ if (locX == this.m_map.m_nrofblocks - 1) {\r
point[0] = 0;\r
point[1] = locY;\r
set = true;\r
}\r
\r
public void doMove() {\r
- // System.printString("dx: " + this.dx + ", dy: " + this.dy + "\n");\r
- this.x += this.dx;\r
- this.y += this.dy;\r
- //this.dx = 0;\r
- //this.dy = 0;\r
+ this.m_locX += this.m_dx;\r
+ this.m_locY += this.m_dy;\r
+ this.m_dx = 0;\r
+ this.m_dy = 0;\r
+ //System.printString("Pacmen " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");\r
}\r
}
\ No newline at end of file