use more sophiscated strategy for character moving
authorjzhou <jzhou>
Wed, 3 Sep 2008 00:55:37 +0000 (00:55 +0000)
committerjzhou <jzhou>
Wed, 3 Sep 2008 00:55:37 +0000 (00:55 +0000)
15 files changed:
Robust/src/Benchmarks/MMG/Java/Ghost.java
Robust/src/Benchmarks/MMG/Java/MMG.java
Robust/src/Benchmarks/MMG/Java/Map.java
Robust/src/Benchmarks/MMG/Java/Node.java [new file with mode: 0644]
Robust/src/Benchmarks/MMG/Java/Pacman.java
Robust/src/Benchmarks/MMG/Nor/Ghost.java
Robust/src/Benchmarks/MMG/Nor/MMG.java
Robust/src/Benchmarks/MMG/Nor/Map.java
Robust/src/Benchmarks/MMG/Nor/Node.java [new file with mode: 0644]
Robust/src/Benchmarks/MMG/Nor/Pacman.java
Robust/src/Benchmarks/MMG/Tag/Ghost.java
Robust/src/Benchmarks/MMG/Tag/MMG.java
Robust/src/Benchmarks/MMG/Tag/Map.java
Robust/src/Benchmarks/MMG/Tag/Node.java [new file with mode: 0644]
Robust/src/Benchmarks/MMG/Tag/Pacman.java

index 8d1b1698baebb6c1bed47dc051b38b6e6e55c8cc..9e5659fa9b60e5636b1cd2fa67885d07911f6c07 100755 (executable)
 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
@@ -242,20 +270,20 @@ public class Ghost {
        // 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
@@ -264,14 +292,14 @@ public class Ghost {
                       // 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
@@ -282,10 +310,10 @@ public class Ghost {
                }\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
@@ -293,7 +321,7 @@ public class Ghost {
                  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
@@ -301,7 +329,7 @@ public class Ghost {
                      }\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
@@ -316,9 +344,10 @@ public class Ghost {
     }\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
index 170039ca3a80876e18e439399ca753181c00e3f0..d4c89bb63a613c89a038871196f499a42c754fbf 100755 (executable)
@@ -11,69 +11,71 @@ public class MMG {
        \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
index b82e07e6aa03717c2d6dcde530210b729cfc4c70..f87324d40ab3e3e816dc3c9661458ea7b35c8b4c 100755 (executable)
-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
@@ -106,17 +163,17 @@ public class Map {
        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
diff --git a/Robust/src/Benchmarks/MMG/Java/Node.java b/Robust/src/Benchmarks/MMG/Java/Node.java
new file mode 100644 (file)
index 0000000..bcc4d3e
--- /dev/null
@@ -0,0 +1,34 @@
+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
index 1ab40031094de27216feeab327fb7b2a057b205a..6cbff494525518dd421dc0ea5963045a2c136943 100755 (executable)
 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
@@ -218,20 +316,20 @@ public class Pacman {
        // 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
@@ -240,14 +338,14 @@ public class Pacman {
                       // 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
@@ -258,10 +356,10 @@ public class Pacman {
                }\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
@@ -269,7 +367,7 @@ public class Pacman {
                  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
@@ -277,7 +375,7 @@ public class Pacman {
                      }\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
@@ -292,10 +390,10 @@ public class Pacman {
     }\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
index 31a85d425c37c793c286e88a2f10d9279dd05290..b813147e97e0f1e13b25969ba7a77df2e42ae637 100755 (executable)
-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
index 93dca6f7c9bfa0f25896ac2e94c0f382d6a72cfc..16cb4965d1fb745c317a8264c09f7e0e4f5e0b75 100755 (executable)
-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
index 1a861b64f35bcfcc40bb1af984c9ddd707562cc7..a75ec229ac2d52fb0c90f842d6bf75aa4d819f8a 100755 (executable)
-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
diff --git a/Robust/src/Benchmarks/MMG/Nor/Node.java b/Robust/src/Benchmarks/MMG/Nor/Node.java
new file mode 100644 (file)
index 0000000..bcc4d3e
--- /dev/null
@@ -0,0 +1,34 @@
+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
index 3482a5e0d7aa59bd7cab2629707605fdc1d0cdf2..651b90dc8e2419c095a107a55cb45a94adb57a6b 100755 (executable)
-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
index da511d05f2df5a1809b8c49f06422824fa46473f..b8d27981ed5c56c78b5dea9c29fe790eee63abfa 100755 (executable)
@@ -2,225 +2,257 @@ public class Ghost {
     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
@@ -245,20 +277,20 @@ public class Ghost {
        // 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
@@ -267,14 +299,14 @@ public class Ghost {
                       // 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
@@ -285,10 +317,10 @@ public class Ghost {
                }\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
@@ -296,7 +328,7 @@ public class Ghost {
                  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
@@ -304,7 +336,7 @@ public class Ghost {
                      }\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
@@ -319,9 +351,10 @@ public class Ghost {
     }\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
index 4be74680d1fec906a3866d14f149b56300071c39..7207bc60921b753567efe03b3e137f69a32e0d07 100755 (executable)
@@ -14,27 +14,25 @@ task initMap(Map map{init}) {
     \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
@@ -61,19 +59,16 @@ task updateGhost(Map map{updateGhost}, optional Ghost g{update}) {
     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
@@ -87,23 +82,21 @@ task updatePac(Map map{updatePac}, optional Pacman p{update}) {
     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
@@ -118,25 +111,24 @@ task next(Map map{next}) {
     //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
index 906acdb29b28120950fcb01653afb0651bbc586a..eb0cef24d9e65ccaaf076de22556c51515dd86f5 100755 (executable)
@@ -5,107 +5,158 @@ public class Map {
     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
@@ -113,17 +164,17 @@ public class Map {
        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
diff --git a/Robust/src/Benchmarks/MMG/Tag/Node.java b/Robust/src/Benchmarks/MMG/Tag/Node.java
new file mode 100644 (file)
index 0000000..bcc4d3e
--- /dev/null
@@ -0,0 +1,34 @@
+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
index 48693a23508d9e3f59e4caecd64468e20dc295f2..e75900eb3bdbed390d532ecf2446b37e4c92e2c9 100755 (executable)
@@ -2,201 +2,299 @@ public class Pacman {
     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
@@ -221,20 +319,20 @@ public class Pacman {
        // 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
@@ -243,14 +341,14 @@ public class Pacman {
                       // 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
@@ -261,10 +359,10 @@ public class Pacman {
                }\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
@@ -272,7 +370,7 @@ public class Pacman {
                  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
@@ -280,7 +378,7 @@ public class Pacman {
                      }\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
@@ -295,10 +393,10 @@ public class Pacman {
     }\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