From: jzhou Date: Wed, 3 Sep 2008 00:55:37 +0000 (+0000) Subject: use more sophiscated strategy for character moving X-Git-Tag: buildscript^6~63 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ffacb907d93e9915e58e033f4f82355a8e58fd1b;p=IRC.git use more sophiscated strategy for character moving --- diff --git a/Robust/src/Benchmarks/MMG/Java/Ghost.java b/Robust/src/Benchmarks/MMG/Java/Ghost.java index 8d1b1698..9e5659fa 100755 --- a/Robust/src/Benchmarks/MMG/Java/Ghost.java +++ b/Robust/src/Benchmarks/MMG/Java/Ghost.java @@ -1,223 +1,251 @@ public class Ghost { - public int x; - public int y; - public int index; - public int target; - public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right - int dx; - int dy; - int destinationX; - int destinationY; - Map map; - public Ghost(int x, int y, Map map) { - this.x = x; - this.y = y; - this.dx = this.dy = 0; - this.index = -1; - this.target = -1; - this.direction = 0; - this.destinationX = -1; - this.destinationY = -1; - this.map = map; - } + 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 void setTarget(int pacman) { - this.target = pacman; + 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"); - //System.printString("target: " + this.target + "\n"); - - // Don't let the ghost go back the way it came. - int prevDirection = 0; + // System.printString("step 1\n"); + int i = 0; - // If there is a destination, then check if the destination has been reached. - if (destinationX >= 0 && destinationY >= 0) { - // Check if the destination has been reached, if so, then - // get new destination. - if (destinationX == x && destinationY == y) { - destinationX = -1; - destinationY = -1; - prevDirection = direction; - } else { - // Otherwise, we haven't reached the destionation so - // continue in same direction. - return; + // 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; + } } } - setNextDirection (prevDirection); + // 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(int prevDirection) { + 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.map.pacMenX[this.target]; - //System.printString("aaa\n"); - int targety = this.map.pacMenY[this.target]; + 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; - - //System.printString("bbb\n"); - if(targetx == -1) { - //System.printString("a\n"); - // already kicked off, choose another target - int i = 0; - boolean found = false; - while((!found) && (i < map.pacMenX.length)) { - if(this.map.pacMenX[i] != -1) { - this.target = i; - targetx = this.map.pacMenX[i]; - targety = this.map.pacMenY[i]; - this.map.targets[i] = this.target; - found = true; - } - i++; - } - //System.printString("b\n"); - if(i == this.map.pacMenX.length) { - //System.printString("c\n"); - // no more pacmen to chase - this.dx = 0; - this.dy = 0; - this.direction = 0; - return; - } - //System.printString("d\n"); - } - getDestination (this.map.pacmen[this.target].direction, targetx, targety, nextLocation); + // 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(); - //System.printString("step 2\n"); - // check the distance - int deltax = this.x - targetx; // <0: move right; >0: move left - int deltay = this.y - targety; // <0: move down; >0: move up - // decide the priority of four moving directions - int[] bestDirection = new int[4]; - //System.printString("dx: " + deltax + "; dy: " + deltay + "\n"); - if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) { - // go first along y - if(deltay > 0) { - bestDirection[0] = 1; - bestDirection[3] = 2; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } + // 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 { - bestDirection[0] = 2; - bestDirection[3] = 1; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; + // 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; + } } - } - } else { - if(deltax > 0) { - bestDirection[0] = 3; - bestDirection[3] = 4; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + + // 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + // still + this.m_direction = 0; } - } else { - bestDirection[0] = 4; - bestDirection[3] = 3; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + cuts.addElement(new Integer(index)); + /*for( int h = 0; h < cuts.size(); h++) { + System.printString(cuts.elementAt(h) + ", "); + } + System.printString("\n");*/ } } } - /*for(int i = 0; i < 4; i++) { - System.printString(bestDirection[i] + ","); - } - System.printString("\n");*/ - - // There's a 50% chance that the ghost will try the sub-optimal direction first. - // This will keep the ghosts from following each other and to trap Pacman. - if (this.map.r.nextDouble() < .50) { - int temp = bestDirection[0]; - bestDirection[0] = bestDirection[1]; - bestDirection[1] = temp; - } - - //System.printString("step 3\n"); - // try to move one by one - int i = 0; - boolean set = false; - this.dx = 0; - this.dy = 0; - while((!set) && (i < 4)) { - if(bestDirection[i] == 1) { - // try to move up - if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) { - //System.printString("a\n"); - if (getDestination (1, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = -1; - set = true; + } + + // 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++; + } } - } - } else if (bestDirection[i] == 2) { - // try to move down - if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) { - //System.printString("b\n"); - if (getDestination (2, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = 1; - set = true; + if(!ignore) { + parents[neighbour.getIndex()] = access.getIndex(); + toaccess.addElement(neighbour); } } - } else if (bestDirection[i] == 3) { - // try to move left - if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) { - //System.printString("c\n"); - if (getDestination (3, this.x, this.y, nextLocation)) { - this.dx = -1; - this.dy = 0; - set = true; - } + } + } + 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; } - } else if (bestDirection[i] == 4) { - // try to move right - if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) { - //System.printString("d\n"); - if (getDestination (4, this.x, this.y, nextLocation)) { - this.dx = 1; - this.dy = 0; - set = 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; } } - i++; } - //System.printString("step 4\n"); + + 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. - boolean getDestination (int direction, int locX, int locY, int[] point) { + 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 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up - (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left - (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down - (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right + 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; @@ -242,20 +270,20 @@ public class Ghost { // then return false. if (locY < 0 || locX < 0 || - locY == this.map.nrofblocks || - locX == this.map.nrofblocks) { + locY == this.m_map.m_nrofblocks || + locX == this.m_map.m_nrofblocks) { return false; } boolean set = false; - // Determine next turning location.. + // Determine next turning location. while (!set) { if (direction == 1 || direction == 2) { // up or down - if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left - (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // 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; @@ -264,14 +292,14 @@ public class Ghost { // Check for Top Warp if (locY == 0) { point[0] = locX; - point[1] = this.map.nrofblocks - 1; + point[1] = this.m_map.m_nrofblocks - 1; set = true; } else { locY--; } } else { // Check for Bottom Warp - if (locY == this.map.nrofblocks - 1) { + if (locY == this.m_map.m_nrofblocks - 1) { point[0] = locX; point[1] = 0; set = true; @@ -282,10 +310,10 @@ public class Ghost { } } else { // left or right - if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down - (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left + 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; @@ -293,7 +321,7 @@ public class Ghost { if (direction == 3) { // Check for Left Warp if (locX == 0) { - point[0] = this.map.nrofblocks - 1; + point[0] = this.m_map.m_nrofblocks - 1; point[1] = locY; set = true; } else { @@ -301,7 +329,7 @@ public class Ghost { } } else { // Check for Right Warp - if (locX == this.map.nrofblocks - 1) { + if (locX == this.m_map.m_nrofblocks - 1) { point[0] = 0; point[1] = locY; set = true; @@ -316,9 +344,10 @@ public class Ghost { } public void doMove() { - this.x += this.dx; - this.y += this.dy; - //this.dx = 0; - //this.dy = 0; + 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 diff --git a/Robust/src/Benchmarks/MMG/Java/MMG.java b/Robust/src/Benchmarks/MMG/Java/MMG.java index 170039ca..d4c89bb6 100755 --- a/Robust/src/Benchmarks/MMG/Java/MMG.java +++ b/Robust/src/Benchmarks/MMG/Java/MMG.java @@ -11,69 +11,71 @@ public class MMG { // Initiate the map map.init(); - + //System.printString("Init finish\n"); int i = 0; // create ghosts - for(i = 0; i < map.nrofghosts; i++) { + for(i = 0; i < map.m_nrofghosts; i++) { Ghost ghost = new Ghost(7, 7, map); - ghost.setTarget(i%map.nrofpacs); - ghost.index = i; + ghost.m_index = i; map.placeGhost(ghost); - map.targets[i] = ghost.target; - map.ghosts[i] = ghost; + map.m_ghosts[i] = ghost; } // create pacmen int tx = 14; int ty = 14; - for(i = 0; i < map.nrofpacs; i++) { + for(i = 0; i < map.m_nrofpacs; i++) { Pacman pacman = new Pacman(5, 7, map); pacman.setTarget(tx*(i/2), ty*(i%2)); - pacman.index = i; + pacman.m_index = i; map.placePacman(pacman); - map.desX[i] = tx*(i/2); - map.desY[i] = ty*(i%2); - map.pacmen[i] = pacman; + map.m_desX[i] = tx*(i/2); + map.m_desY[i] = ty*(i%2); + map.m_pacmen[i] = pacman; //System.printString("destination: " + map.desX[i] + "," + map.desY[i] + "\n"); } - map.ghostcount = 0; - map.paccount = 0; + map.m_ghostcount = 0; + map.m_paccount = 0; - while(map.nrofpacs > 0) { + while(map.m_nrofpacs > 0) { // try to move ghost - for(i = 0; i < map.nrofghosts; i++) { - map.ghosts[i].tryMove(); + for(i = 0; i < nrofghosts; i++) { + map.m_ghosts[i].tryMove(); } // try to move pacmen - for(i = 0; i < map.nrofpacs; i++) { - map.pacmen[i].tryMove(); + for(i = 0; i < nrofpacs; i++) { + if(map.m_pacMenX[i] != -1) { + map.m_pacmen[i].tryMove(); + } } // update ghosts - for(i = 0; i < map.nrofghosts; i++) { - map.ghosts[i].doMove(); - map.placeGhost(map.ghosts[i]); + for(i = 0; i < nrofghosts; i++) { + map.m_ghosts[i].doMove(); + map.placeGhost(map.m_ghosts[i]); } - /*for(i = 0; i < map.nrofghosts; i++) { - System.printString("(" + map.ghostsX[i] + "," + map.ghostsY[i] + ") "); + /*for(i = 0; i < nrofghosts; i++) { + System.printString("(" + map.m_ghostsX[i] + "," + map.m_ghostsY[i] + ") "); } System.printString("\n");*/ // update pacmen - for(i = 0; i < map.nrofpacs; i++) { - map.pacmen[i].doMove(); - map.placePacman(map.pacmen[i]); - //System.printString("Pacman " + map.pacmen[i].index + ": (" + map.pacMenX[map.pacmen[i].index] + "," + map.pacMenY[map.pacmen[i].index] + ")\n"); - boolean death = map.check(map.pacmen[i]); - /*if(death) { - System.printString("Pacman " + map.pacmen[i].index + " caught!\n"); - }*/ + for(i = 0; i < nrofpacs; i++) { + if(map.m_pacMenX[i] != -1) { + map.m_pacmen[i].doMove(); + map.placePacman(map.m_pacmen[i]); + //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"); + boolean death = map.check(map.m_pacmen[i]); + /*if(death) { + System.printString("Pacman " + map.m_pacmen[i].m_index + " caught!\n"); + }*/ + } } - map.nrofpacs -= map.deathcount; - //System.printString(map.nrofpacs + " pacmen left. \n"); + map.m_nrofpacs -= map.m_deathcount; + //System.printString(map.m_nrofpacs + " pacmen left. \n"); // reset for next run - map.paccount = 0; - map.deathcount = 0; + map.m_paccount = 0; + map.m_deathcount = 0; } System.printString("Finish\n"); diff --git a/Robust/src/Benchmarks/MMG/Java/Map.java b/Robust/src/Benchmarks/MMG/Java/Map.java index b82e07e6..f87324d4 100755 --- a/Robust/src/Benchmarks/MMG/Java/Map.java +++ b/Robust/src/Benchmarks/MMG/Java/Map.java @@ -1,104 +1,161 @@ -public class Map { - public int[] map; - public int[] pacMenX; - public int[] pacMenY; - public int[] ghostsX; - public int[] ghostsY; - public int[] targets; - public int[] desX; - public int[] desY; - public Ghost[] ghosts; - public Pacman[] pacmen; +public class Map { + // maze + private int m_nrofblocks; + public int[] m_map; + public Node[] m_mapNodes; + public Ghost[] m_ghosts; + public Pacman[] m_pacmen; - public int nrofghosts; - public int nrofpacs; - private int nrofblocks; - //public boolean toupdate; - public int ghostcount; - public int paccount; - public int deathcount; + // 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; - public Random r; + // 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; + + // helper member + public Random m_r; public Map(int nrofpacs, int nrofghosts) { //System.printString("step 1\n"); - this.nrofblocks = 15; - this.map = new int[this.nrofblocks*this.nrofblocks]; - this.nrofpacs = nrofpacs; - this.nrofghosts = nrofghosts; - this.pacMenX = new int[this.nrofpacs]; - this.pacMenY = new int[this.nrofpacs]; - this.ghostsX = new int[this.nrofghosts]; - this.ghostsY = new int[this.nrofghosts]; - this.targets = new int[this.nrofghosts]; - this.desX = new int[this.nrofpacs]; - this.desY = new int[this.nrofpacs]; - this.ghosts = new Ghost[this.nrofghosts]; - this.pacmen = new Pacman[this.nrofpacs]; - //this.toupdate = false; - this.ghostcount = 0; - this.paccount = 0; - this.deathcount = 0; - this.r = new Random(); + 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_ghosts = new Ghost[this.m_nrofghosts]; + this.m_pacmen = new Pacman[this.m_nrofpacs]; + + 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.nrofpacs; i++) { - this.pacMenX[i] = this.pacMenY[i] = -1; - this.desX[i] = this.desY[i] = -1; - this.pacmen[i] = null; + 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; + this.m_pacmen[i] = null; } //System.printString("step 3\n"); - for(int i = 0; i < this.nrofghosts; i++) { - this.ghostsX[i] = this.ghostsY[i] = -1; - this.targets[i] = -1; - this.ghosts[i] = null; + for(int i = 0; i < this.m_nrofghosts; i++) { + this.m_ghostsX[i] = this.m_ghostsY[i] = -1; + this.m_targets[i] = -1; + this.m_ghosts[i] = null; } //System.printString("step 4\n"); } public void init() { + // initilize the maze int i = 0; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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 + 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.pacMenX[t.index] = t.x; - this.pacMenY[t.index] = t.y; - //this.map[t.y * this.nrofblocks + t.x - 1] |= 16; - this.paccount++; + 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.ghostsX[t.index] = t.x; - this.ghostsY[t.index] = t.y; - //this.map[t.y * this.nrofblocks + t.x - 1] |= 32; - this.ghostcount++; + 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.nrofghosts)) { - if((t.x == this.ghostsX[i]) && (t.y == this.ghostsY[i])) { + 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.x == t.tx) && (t.y == t.ty)) { + if((!death) && (t.m_locX == t.m_tx) && (t.m_locY == t.m_ty)) { // reach the destination //System.printString("Hit destination!\n"); death = true; @@ -106,17 +163,17 @@ public class Map { if(death) { // pacman caught by ghost // set pacman as death - t.death = true; + t.m_death = true; // kick it out - //this.map[t.y * this.nrofblocks + t.x - 1] -= 16; - this.deathcount++; - this.pacMenX[t.index] = -1; - this.pacMenY[t.index] = -1; + //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 nrofpacs == 0; + return this.m_nrofpacs == 0; } } \ 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 index 00000000..bcc4d3e1 --- /dev/null +++ b/Robust/src/Benchmarks/MMG/Java/Node.java @@ -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 diff --git a/Robust/src/Benchmarks/MMG/Java/Pacman.java b/Robust/src/Benchmarks/MMG/Java/Pacman.java index 1ab40031..6cbff494 100755 --- a/Robust/src/Benchmarks/MMG/Java/Pacman.java +++ b/Robust/src/Benchmarks/MMG/Java/Pacman.java @@ -1,199 +1,297 @@ public class Pacman { - public int x; - public int y; - public boolean death; - public int index; - public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right - int dx; - int dy; - public int tx; - public int ty; - int destinationX; - int destinationY; - Map map; + 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.x = x; - this.y = y; - this.dx = this.dy = 0; - this.death = false; - this.index = -1; - this.tx = this.ty = -1; - this.direction = 0; - this.destinationX = -1; - this.destinationY = -1; - this.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.tx = x; - this.ty = y; + this.m_tx = x; + this.m_ty = y; } public void tryMove() { // decide dx & dy - // Don't let the pacman go back the way it came. - int prevDirection = 0; - - // If there is a destination, then check if the destination has been reached. - if (destinationX >= 0 && destinationY >= 0) { - // Check if the destination has been reached, if so, then - // get new destination. - if (destinationX == x && destinationY == y) { - destinationX = -1; - destinationY = -1; - prevDirection = direction; - } else { - // Otherwise, we haven't reached the destionation so - // continue in same direction. - return; - } - } - setNextDirection (prevDirection); + // find the shortest possible way to the chosen target + setNextDirection(); } - private void setNextDirection(int prevDirection) { + 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.tx; - //System.printString("aaa\n"); - int targety = this.ty; + int targetx = this.m_tx; + int targety = this.m_ty; int[] nextLocation = new int[2]; nextLocation[0] = nextLocation[1] = -1; - //System.printString("bbb\n"); - getDestination (this.direction, 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]; - //System.printString("step 2\n"); - // check the distance - int deltax = this.x - targetx; // <0: move right; >0: move left - int deltay = this.y - targety; // <0: move down; >0: move up - // decide the priority of four moving directions - int[] bestDirection = new int[4]; - //System.printString("dx: " + deltax + "; dy: " + deltay + "\n"); - if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) { - // go first along y - if(deltay > 0) { - bestDirection[0] = 1; - bestDirection[3] = 2; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } + // 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 { - bestDirection[0] = 2; - bestDirection[3] = 1; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; + // 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; + } } - } - } else { - if(deltax > 0) { - bestDirection[0] = 3; - bestDirection[3] = 4; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + + // 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + // still + this.m_direction = 0; } - } else { - bestDirection[0] = 4; - bestDirection[3] = 3; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + cuts.addElement(new Integer(index)); + /*for( int h = 0; h < cuts.size(); h++) { + System.printString(cuts.elementAt(h) + ", "); + } + System.printString("\n");*/ } } } - /*for(int i = 0; i < 4; i++) { - System.printString(bestDirection[i] + ","); + } + + // 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); + } + } + } } - System.printString("\n");*/ + 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; - // There's a 50% chance that the ghost will try the sub-optimal direction first. - // This will keep the ghosts from following each other and to trap Pacman. - if (this.map.r.nextDouble() < .50) { - int temp = bestDirection[0]; - bestDirection[0] = bestDirection[1]; - bestDirection[1] = temp; + // 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++; } - - //System.printString("step 3\n"); - // try to move one by one - int i = 0; + steps++; + boolean set = false; - this.dx = 0; - this.dy = 0; - while((!set) && (i < 4)) { - if(bestDirection[i] == 1) { - // try to move up - if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) { - //System.printString("a\n"); - if (getDestination (1, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = -1; - set = true; - } - } - } else if (bestDirection[i] == 2) { - // try to move down - if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) { - //System.printString("b\n"); - if (getDestination (2, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = 1; - set = true; + // 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 if (bestDirection[i] == 3) { - // try to move left - if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) { - //System.printString("c\n"); - if (getDestination (3, this.x, this.y, nextLocation)) { - this.dx = -1; - this.dy = 0; - set = true; + } 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++; + } } } - } else if (bestDirection[i] == 4) { - // try to move right - if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) { - //System.printString("d\n"); - if (getDestination (4, this.x, this.y, nextLocation)) { - this.dx = 1; - this.dy = 0; - set = true; - } + } + } + + // 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]; } } - i++; } - //System.printString("step 4\n"); + + 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. - boolean getDestination (int direction, int locX, int locY, int[] point) { + 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 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up - (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left - (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down - (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right + 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; @@ -218,20 +316,20 @@ public class Pacman { // then return false. if (locY < 0 || locX < 0 || - locY == this.map.nrofblocks || - locX == this.map.nrofblocks) { + locY == this.m_map.m_nrofblocks || + locX == this.m_map.m_nrofblocks) { return false; } boolean set = false; - // Determine next turning location.. + // Determine next turning location. while (!set) { if (direction == 1 || direction == 2) { // up or down - if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left - (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // 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; @@ -240,14 +338,14 @@ public class Pacman { // Check for Top Warp if (locY == 0) { point[0] = locX; - point[1] = this.map.nrofblocks - 1; + point[1] = this.m_map.m_nrofblocks - 1; set = true; } else { locY--; } } else { // Check for Bottom Warp - if (locY == this.map.nrofblocks - 1) { + if (locY == this.m_map.m_nrofblocks - 1) { point[0] = locX; point[1] = 0; set = true; @@ -258,10 +356,10 @@ public class Pacman { } } else { // left or right - if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down - (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left + 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; @@ -269,7 +367,7 @@ public class Pacman { if (direction == 3) { // Check for Left Warp if (locX == 0) { - point[0] = this.map.nrofblocks - 1; + point[0] = this.m_map.m_nrofblocks - 1; point[1] = locY; set = true; } else { @@ -277,7 +375,7 @@ public class Pacman { } } else { // Check for Right Warp - if (locX == this.map.nrofblocks - 1) { + if (locX == this.m_map.m_nrofblocks - 1) { point[0] = 0; point[1] = locY; set = true; @@ -292,10 +390,10 @@ public class Pacman { } public void doMove() { - //System.printString("dx: " + this.dx + ", dy: " + this.dy + "\n"); - this.x += this.dx; - this.y += this.dy; - //this.dx = 0; - //this.dy = 0; + 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 diff --git a/Robust/src/Benchmarks/MMG/Nor/Ghost.java b/Robust/src/Benchmarks/MMG/Nor/Ghost.java index 31a85d42..b813147e 100755 --- a/Robust/src/Benchmarks/MMG/Nor/Ghost.java +++ b/Robust/src/Benchmarks/MMG/Nor/Ghost.java @@ -1,327 +1,355 @@ -public class Ghost { - flag move; - flag update; - - public int x; - public int y; - public int index; - public int target; - public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right - int dx; - int dy; - int destinationX; - int destinationY; - Map map; - - public Ghost(int x, int y, Map map) { - this.x = x; - this.y = y; - this.dx = this.dy = 0; - this.index = -1; - this.target = -1; - this.direction = 0; - this.destinationX = -1; - this.destinationY = -1; - this.map = map; - } - - public void setTarget(int pacman) { - this.target = pacman; - } - - // 0:still, 1:up, 2:down, 3:left, 4:right - public void tryMove() { - //System.printString("step 1\n"); - //System.printString("target: " + this.target + "\n"); - - // Don't let the ghost go back the way it came. - int prevDirection = 0; - - // If there is a destination, then check if the destination has been reached. - if (destinationX >= 0 && destinationY >= 0) { - // Check if the destination has been reached, if so, then - // get new destination. - if (destinationX == x && destinationY == y) { - destinationX = -1; - destinationY = -1; - prevDirection = direction; - } else { - // Otherwise, we haven't reached the destionation so - // continue in same direction. - return; - } - } - setNextDirection (prevDirection); - } - - private void setNextDirection(int prevDirection) { - // get target's position - int targetx = this.map.pacMenX[this.target]; - //System.printString("aaa\n"); - int targety = this.map.pacMenY[this.target]; - int[] nextLocation = new int[2]; - nextLocation[0] = nextLocation[1] = -1; - - //System.printString("bbb\n"); - if(targetx == -1) { - //System.printString("a\n"); - // already kicked off, choose another target - int i = 0; - boolean found = false; - while((!found) && (i < map.pacMenX.length)) { - if(this.map.pacMenX[i] != -1) { - this.target = i; - targetx = this.map.pacMenX[i]; - targety = this.map.pacMenY[i]; - this.map.targets[i] = this.target; - found = true; - } - i++; - } - //System.printString("b\n"); - if(i == this.map.pacMenX.length) { - //System.printString("c\n"); - // no more pacmen to chase - this.dx = 0; - this.dy = 0; - this.direction = 0; - return; - } - //System.printString("d\n"); - } - getDestination (this.map.directions[this.target], targetx, targety, nextLocation); - targetx = nextLocation[0]; - targety = nextLocation[1]; - - //System.printString("step 2\n"); - // check the distance - int deltax = this.x - targetx; // <0: move right; >0: move left - int deltay = this.y - targety; // <0: move down; >0: move up - // decide the priority of four moving directions - int[] bestDirection = new int[4]; - //System.printString("dx: " + deltax + "; dy: " + deltay + "\n"); - if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) { - // go first along y - if(deltay > 0) { - bestDirection[0] = 1; - bestDirection[3] = 2; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } - } else { - bestDirection[0] = 2; - bestDirection[3] = 1; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } - } - } else { - if(deltax > 0) { - bestDirection[0] = 3; - bestDirection[3] = 4; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; - } else { - bestDirection[1] = 2; - bestDirection[2] = 1; - } - } else { - bestDirection[0] = 4; - bestDirection[3] = 3; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; - } else { - bestDirection[1] = 2; - bestDirection[2] = 1; - } - } - } - /*for(int i = 0; i < 4; i++) { - System.printString(bestDirection[i] + ","); - } - System.printString("\n");*/ - - // There's a 50% chance that the ghost will try the sub-optimal direction first. - // This will keep the ghosts from following each other and to trap Pacman. - if (this.map.r.nextDouble() < .50) { - int temp = bestDirection[0]; - bestDirection[0] = bestDirection[1]; - bestDirection[1] = temp; - } - - //System.printString("step 3\n"); - // try to move one by one - int i = 0; - boolean set = false; - this.dx = 0; - this.dy = 0; - while((!set) && (i < 4)) { - if(bestDirection[i] == 1) { - // try to move up - if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) { - //System.printString("a\n"); - if (getDestination (1, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = -1; - set = true; - } - } - } else if (bestDirection[i] == 2) { - // try to move down - if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) { - //System.printString("b\n"); - if (getDestination (2, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = 1; - set = true; - } - } - } else if (bestDirection[i] == 3) { - // try to move left - if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) { - //System.printString("c\n"); - if (getDestination (3, this.x, this.y, nextLocation)) { - this.dx = -1; - this.dy = 0; - set = true; - } - } - } else if (bestDirection[i] == 4) { - // try to move right - if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) { - //System.printString("d\n"); - if (getDestination (4, this.x, this.y, nextLocation)) { - this.dx = 1; - this.dy = 0; - set = true; - } - } - } - i++; - } - //System.printString("step 4\n"); - } - - // 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. - 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 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up - (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left - (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down - (direction == 4 && (this.map.map[locX + locY * this.map.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.map.nrofblocks || - locX == this.map.nrofblocks) { - return false; - } - - boolean set = false; - // Determine next turning location.. - while (!set) { - if (direction == 1 || direction == 2) { - // up or down - if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left - (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up - (this.map.map[locX + locY * this.map.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.map.nrofblocks - 1; - set = true; - } else { - locY--; - } - } else { - // Check for Bottom Warp - if (locY == this.map.nrofblocks - 1) { - point[0] = locX; - point[1] = 0; - set = true; - } else { - locY++; - } - } - } - } else { - // left or right - if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down - (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right - (this.map.map[locX + locY * this.map.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.map.nrofblocks - 1; - point[1] = locY; - set = true; - } else { - locX--; - } - } else { - // Check for Right Warp - if (locX == this.map.nrofblocks - 1) { - point[0] = 0; - point[1] = locY; - set = true; - } else { - locX++; - } - } - } - } - } - return true; - } - - public void doMove() { - this.x += this.dx; - this.y += this.dy; - //this.dx = 0; - //this.dy = 0; - } -} +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 diff --git a/Robust/src/Benchmarks/MMG/Nor/MMG.java b/Robust/src/Benchmarks/MMG/Nor/MMG.java index 93dca6f7..16cb4965 100755 --- a/Robust/src/Benchmarks/MMG/Nor/MMG.java +++ b/Robust/src/Benchmarks/MMG/Nor/MMG.java @@ -1,147 +1,139 @@ -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.nrofghosts; i++) { - Ghost ghost = new Ghost(7, 7, map){move}; - ghost.setTarget(i%map.nrofpacs); - ghost.index = i; - map.placeGhost(ghost); - map.targets[i] = ghost.target; - } - // create pacmen - int tx = 14; - int ty = 14; - for(i = 0; i < map.nrofpacs; i++) { - Pacman pacman = new Pacman(5, 7, map){move}; - pacman.setTarget(tx*(i/2), ty*(i%2)); - pacman.index = i; - map.placePacman(pacman); - map.desX[i] = tx*(i/2); - map.desY[i] = ty*(i%2); - } - - map.ghostcount = 0; - map.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); - map.ghostdirections[g.index] = g.direction; - /*} else { - System.printString("FAILURE ghost!!!\n"); - //map.failghostcount++; - map.ghostcount++; - }*/ - - if(map.ghostcount == map.nrofghosts) { - //map.nrofghosts -= map.failghostcount; - map.ghostcount = 0; - map.failghostcount = 0; - /*for(int i = 0; i < map.ghostsX.length; i++) { - System.printString("(" + map.ghostsX[i] + "," + map.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); - map.directions[p.index] = p.direction; - //System.printString("Pacman " + p.index + ": (" + map.pacMenX[p.index] + "," + map.pacMenY[p.index] + ")\n"); - boolean death = map.check(p); - /*if(death) { - System.printString("Pacman " + p.index + " caught!\n"); - }*/ - /*} else { - System.printString("FAILURE pacman!!!\n"); - map.deathcount++; - map.paccount++; - }*/ - - boolean finish = map.paccount == map.nrofpacs; - - if(finish) { - map.nrofpacs -= map.deathcount; - //System.printString(map.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.nrofghosts; i++) { - Ghost ghost = new Ghost(map.ghostsX[i], map.ghostsY[i], map){move}; - ghost.setTarget(map.targets[i]); - ghost.index = i; - ghost.direction = map.ghostdirections[i]; - } - for(i = 0; i < map.pacMenX.length; i++) { - if(map.pacMenX[i] != -1) { - // still in the map - //System.printString("new Pacman\n"); - Pacman pacman = new Pacman(map.pacMenX[i], map.pacMenY[i], map){move}; - pacman.setTarget(map.desX[i], map.desY[i]); - pacman.index = i; - pacman.direction = map.directions[i]; - } - } - - map.paccount = 0; - map.deathcount = 0; - - taskexit(map{!next, updateGhost}); -} - -task finish(Map map{finish}) { - System.printString("Task Finish\n"); - taskexit(map{!finish}); -} +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 diff --git a/Robust/src/Benchmarks/MMG/Nor/Map.java b/Robust/src/Benchmarks/MMG/Nor/Map.java index 1a861b64..a75ec229 100755 --- a/Robust/src/Benchmarks/MMG/Nor/Map.java +++ b/Robust/src/Benchmarks/MMG/Nor/Map.java @@ -1,129 +1,180 @@ -public class Map { - flag init; - flag updateGhost; - flag updatePac; - flag next; - flag finish; - - public int[] map; - public int[] pacMenX; - public int[] pacMenY; - public int[] directions; - public int[] ghostsX; - public int[] ghostsY; - public int[] ghostdirections; - public int[] targets; - public int[] desX; - public int[] desY; - - public int nrofghosts; - public int nrofpacs; - private int nrofblocks; - //public boolean toupdate; - public int ghostcount; - public int paccount; - public int deathcount; - public int failghostcount; - - public Random r; - - public Map(int nrofpacs, int nrofghosts) { - //System.printString("step 1\n"); - this.nrofblocks = 15; - this.map = new int[this.nrofblocks*this.nrofblocks]; - this.nrofpacs = nrofpacs; - this.nrofghosts = nrofghosts; - this.pacMenX = new int[this.nrofpacs]; - this.pacMenY = new int[this.nrofpacs]; - this.directions = new int[this.nrofpacs]; - this.ghostsX = new int[this.nrofghosts]; - this.ghostsY = new int[this.nrofghosts]; - this.ghostdirections = new int[this.nrofghosts]; - this.targets = new int[this.nrofghosts]; - this.desX = new int[this.nrofpacs]; - this.desY = new int[this.nrofpacs]; - //this.toupdate = false; - this.ghostcount = 0; - this.paccount = 0; - this.deathcount = 0; - this.failghostcount = 0; - - this.r = new Random(); - - //System.printString("step 2\n"); - for(int i = 0; i < this.nrofpacs; i++) { - this.pacMenX[i] = this.pacMenY[i] = -1; - this.desX[i] = this.desY[i] = -1; - } - //System.printString("step 3\n"); - for(int i = 0; i < this.nrofghosts; i++) { - this.ghostsX[i] = this.ghostsY[i] = -1; - this.targets[i] = -1; - } - //System.printString("step 4\n"); - } - - public void init() { - int i = 0; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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 - } - - public void placePacman(Pacman t) { - this.pacMenX[t.index] = t.x; - this.pacMenY[t.index] = t.y; - //this.map[t.y * this.nrofblocks + t.x - 1] |= 16; - this.paccount++; - } - - public void placeGhost(Ghost t) { - this.ghostsX[t.index] = t.x; - this.ghostsY[t.index] = t.y; - //this.map[t.y * this.nrofblocks + t.x - 1] |= 32; - this.ghostcount++; - } - - public boolean check(Pacman t) { - boolean death = false; - int i = 0; - while((!death) && (i < this.nrofghosts)) { - if((t.x == this.ghostsX[i]) && (t.y == this.ghostsY[i])) { - death = true; - } - i++; - } - if((!death) && (t.x == t.tx) && (t.y == t.ty)) { - // reach the destination - //System.printString("Hit destination!\n"); - death = true; - } - if(death) { - // pacman caught by ghost - // set pacman as death - t.death = true; - // kick it out - //this.map[t.y * this.nrofblocks + t.x - 1] -= 16; - this.deathcount++; - this.pacMenX[t.index] = -1; - this.pacMenY[t.index] = -1; - } - return death; - } - - public boolean isfinish() { - return nrofpacs == 0; - } -} +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 index 00000000..bcc4d3e1 --- /dev/null +++ b/Robust/src/Benchmarks/MMG/Nor/Node.java @@ -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 diff --git a/Robust/src/Benchmarks/MMG/Nor/Pacman.java b/Robust/src/Benchmarks/MMG/Nor/Pacman.java index 3482a5e0..651b90dc 100755 --- a/Robust/src/Benchmarks/MMG/Nor/Pacman.java +++ b/Robust/src/Benchmarks/MMG/Nor/Pacman.java @@ -1,304 +1,402 @@ -public class Pacman { - flag move; - flag update; - - public int x; - public int y; - public boolean death; - public int index; - public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right - int dx; - int dy; - public int tx; - public int ty; - int destinationX; - int destinationY; - Map map; - - public Pacman(int x, int y, Map map) { - this.x = x; - this.y = y; - this.dx = this.dy = 0; - this.death = false; - this.index = -1; - this.tx = this.ty = -1; - this.direction = 0; - this.destinationX = -1; - this.destinationY = -1; - this.map = map; - } - - public void setTarget(int x, int y) { - this.tx = x; - this.ty = y; - } - - public void tryMove() { - // decide dx & dy - - // Don't let the pacman go back the way it came. - int prevDirection = 0; - - // If there is a destination, then check if the destination has been reached. - if (destinationX >= 0 && destinationY >= 0) { - // Check if the destination has been reached, if so, then - // get new destination. - if (destinationX == x && destinationY == y) { - destinationX = -1; - destinationY = -1; - prevDirection = direction; - } else { - // Otherwise, we haven't reached the destionation so - // continue in same direction. - return; - } - } - setNextDirection (prevDirection); - } - - private void setNextDirection(int prevDirection) { - // get target's position - int targetx = this.tx; - //System.printString("aaa\n"); - int targety = this.ty; - int[] nextLocation = new int[2]; - nextLocation[0] = nextLocation[1] = -1; - - //System.printString("bbb\n"); - getDestination (this.direction, targetx, targety, nextLocation); - targetx = nextLocation[0]; - targety = nextLocation[1]; - - //System.printString("step 2\n"); - // check the distance - int deltax = this.x - targetx; // <0: move right; >0: move left - int deltay = this.y - targety; // <0: move down; >0: move up - // decide the priority of four moving directions - int[] bestDirection = new int[4]; - //System.printString("dx: " + deltax + "; dy: " + deltay + "\n"); - if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) { - // go first along y - if(deltay > 0) { - bestDirection[0] = 1; - bestDirection[3] = 2; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } - } else { - bestDirection[0] = 2; - bestDirection[3] = 1; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } - } - } else { - if(deltax > 0) { - bestDirection[0] = 3; - bestDirection[3] = 4; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; - } else { - bestDirection[1] = 2; - bestDirection[2] = 1; - } - } else { - bestDirection[0] = 4; - bestDirection[3] = 3; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; - } else { - bestDirection[1] = 2; - bestDirection[2] = 1; - } - } - } - /*for(int i = 0; i < 4; i++) { - System.printString(bestDirection[i] + ","); - } - System.printString("\n");*/ - - // There's a 50% chance that the ghost will try the sub-optimal direction first. - // This will keep the ghosts from following each other and to trap Pacman. - if (this.map.r.nextDouble() < .50) { - int temp = bestDirection[0]; - bestDirection[0] = bestDirection[1]; - bestDirection[1] = temp; - } - - //System.printString("step 3\n"); - // try to move one by one - int i = 0; - boolean set = false; - this.dx = 0; - this.dy = 0; - while((!set) && (i < 4)) { - if(bestDirection[i] == 1) { - // try to move up - if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) { - //System.printString("a\n"); - if (getDestination (1, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = -1; - set = true; - } - } - } else if (bestDirection[i] == 2) { - // try to move down - if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) { - //System.printString("b\n"); - if (getDestination (2, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = 1; - set = true; - } - } - } else if (bestDirection[i] == 3) { - // try to move left - if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) { - //System.printString("c\n"); - if (getDestination (3, this.x, this.y, nextLocation)) { - this.dx = -1; - this.dy = 0; - set = true; - } - } - } else if (bestDirection[i] == 4) { - // try to move right - if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) { - //System.printString("d\n"); - if (getDestination (4, this.x, this.y, nextLocation)) { - this.dx = 1; - this.dy = 0; - set = true; - } - } - } - i++; - } - //System.printString("step 4\n"); - } - - // 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. - 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 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up - (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left - (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down - (direction == 4 && (this.map.map[locX + locY * this.map.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.map.nrofblocks || - locX == this.map.nrofblocks) { - return false; - } - - boolean set = false; - // Determine next turning location.. - while (!set) { - if (direction == 1 || direction == 2) { - // up or down - if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left - (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up - (this.map.map[locX + locY * this.map.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.map.nrofblocks - 1; - set = true; - } else { - locY--; - } - } else { - // Check for Bottom Warp - if (locY == this.map.nrofblocks - 1) { - point[0] = locX; - point[1] = 0; - set = true; - } else { - locY++; - } - } - } - } else { - // left or right - if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down - (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right - (this.map.map[locX + locY * this.map.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.map.nrofblocks - 1; - point[1] = locY; - set = true; - } else { - locX--; - } - } else { - // Check for Right Warp - if (locX == this.map.nrofblocks - 1) { - point[0] = 0; - point[1] = locY; - set = true; - } else { - locX++; - } - } - } - } - } - return true; - } - - public void doMove() { - // System.printString("dx: " + this.dx + ", dy: " + this.dy + "\n"); - this.x += this.dx; - this.y += this.dy; - //this.dx = 0; - //this.dy = 0; - } -} +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 diff --git a/Robust/src/Benchmarks/MMG/Tag/Ghost.java b/Robust/src/Benchmarks/MMG/Tag/Ghost.java index da511d05..b8d27981 100755 --- a/Robust/src/Benchmarks/MMG/Tag/Ghost.java +++ b/Robust/src/Benchmarks/MMG/Tag/Ghost.java @@ -2,225 +2,257 @@ public class Ghost { flag move; flag update; - public int x; - public int y; - public int index; - public int target; - public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right - int dx; - int dy; - int destinationX; - int destinationY; - Map map; + 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.x = x; - this.y = y; - this.dx = this.dy = 0; - this.index = -1; - this.target = -1; - this.direction = 0; - this.destinationX = -1; - this.destinationY = -1; - this.map = map; - } - - public void setTarget(int pacman) { - this.target = pacman; + 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"); - //System.printString("target: " + this.target + "\n"); - - // Don't let the ghost go back the way it came. - int prevDirection = 0; + int i = 0; - // If there is a destination, then check if the destination has been reached. - if (destinationX >= 0 && destinationY >= 0) { - // Check if the destination has been reached, if so, then - // get new destination. - if (destinationX == x && destinationY == y) { - destinationX = -1; - destinationY = -1; - prevDirection = direction; - } else { - // Otherwise, we haven't reached the destionation so - // continue in same direction. - return; + // 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; + } } } - setNextDirection (prevDirection); + // 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 possible way to the chosen target + setNextDirection(); } - private void setNextDirection(int prevDirection) { + 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.map.pacMenX[this.target]; - //System.printString("aaa\n"); - int targety = this.map.pacMenY[this.target]; + 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; - - //System.printString("bbb\n"); - if(targetx == -1) { - //System.printString("a\n"); - // already kicked off, choose another target - int i = 0; - boolean found = false; - while((!found) && (i < map.pacMenX.length)) { - if(this.map.pacMenX[i] != -1) { - this.target = i; - targetx = this.map.pacMenX[i]; - targety = this.map.pacMenY[i]; - this.map.targets[i] = this.target; - found = true; - } - i++; - } - //System.printString("b\n"); - if(i == this.map.pacMenX.length) { - //System.printString("c\n"); - // no more pacmen to chase - this.dx = 0; - this.dy = 0; - this.direction = 0; - return; - } - //System.printString("d\n"); - } - getDestination (this.map.directions[this.target], targetx, targety, nextLocation); + // 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(); - //System.printString("step 2\n"); - // check the distance - int deltax = this.x - targetx; // <0: move right; >0: move left - int deltay = this.y - targety; // <0: move down; >0: move up - // decide the priority of four moving directions - int[] bestDirection = new int[4]; - //System.printString("dx: " + deltax + "; dy: " + deltay + "\n"); - if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) { - // go first along y - if(deltay > 0) { - bestDirection[0] = 1; - bestDirection[3] = 2; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } + // 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 { - bestDirection[0] = 2; - bestDirection[3] = 1; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; + // 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; + } } - } - } else { - if(deltax > 0) { - bestDirection[0] = 3; - bestDirection[3] = 4; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + + // 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + // still + this.m_direction = 0; } - } else { - bestDirection[0] = 4; - bestDirection[3] = 3; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + cuts.addElement(new Integer(index)); + /*for( int h = 0; h < cuts.size(); h++) { + System.printString(cuts.elementAt(h) + ", "); + } + System.printString("\n");*/ } } } - /*for(int i = 0; i < 4; i++) { - System.printString(bestDirection[i] + ","); - } - System.printString("\n");*/ - - // There's a 50% chance that the ghost will try the sub-optimal direction first. - // This will keep the ghosts from following each other and to trap Pacman. - if (this.map.r.nextDouble() < .50) { - int temp = bestDirection[0]; - bestDirection[0] = bestDirection[1]; - bestDirection[1] = temp; - } - - //System.printString("step 3\n"); - // try to move one by one - int i = 0; - boolean set = false; - this.dx = 0; - this.dy = 0; - while((!set) && (i < 4)) { - if(bestDirection[i] == 1) { - // try to move up - if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) { - //System.printString("a\n"); - if (getDestination (1, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = -1; - set = true; + } + + // 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++; + } } - } - } else if (bestDirection[i] == 2) { - // try to move down - if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) { - //System.printString("b\n"); - if (getDestination (2, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = 1; - set = true; + if(!ignore) { + parents[neighbour.getIndex()] = access.getIndex(); + toaccess.addElement(neighbour); } } - } else if (bestDirection[i] == 3) { - // try to move left - if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) { - //System.printString("c\n"); - if (getDestination (3, this.x, this.y, nextLocation)) { - this.dx = -1; - this.dy = 0; - set = true; - } + } + } + parents[parents.length - 1] = -1; + 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; } - } else if (bestDirection[i] == 4) { - // try to move right - if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) { - //System.printString("d\n"); - if (getDestination (4, this.x, this.y, nextLocation)) { - this.dx = 1; - this.dy = 0; - set = 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; } } - i++; } - //System.printString("step 4\n"); + + 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. - boolean getDestination (int direction, int locX, int locY, int[] point) { + 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 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up - (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left - (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down - (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right + 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; @@ -245,20 +277,20 @@ public class Ghost { // then return false. if (locY < 0 || locX < 0 || - locY == this.map.nrofblocks || - locX == this.map.nrofblocks) { + locY == this.m_map.m_nrofblocks || + locX == this.m_map.m_nrofblocks) { return false; } boolean set = false; - // Determine next turning location.. + // Determine next turning location. while (!set) { if (direction == 1 || direction == 2) { // up or down - if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left - (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // 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; @@ -267,14 +299,14 @@ public class Ghost { // Check for Top Warp if (locY == 0) { point[0] = locX; - point[1] = this.map.nrofblocks - 1; + point[1] = this.m_map.m_nrofblocks - 1; set = true; } else { locY--; } } else { // Check for Bottom Warp - if (locY == this.map.nrofblocks - 1) { + if (locY == this.m_map.m_nrofblocks - 1) { point[0] = locX; point[1] = 0; set = true; @@ -285,10 +317,10 @@ public class Ghost { } } else { // left or right - if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down - (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left + 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; @@ -296,7 +328,7 @@ public class Ghost { if (direction == 3) { // Check for Left Warp if (locX == 0) { - point[0] = this.map.nrofblocks - 1; + point[0] = this.m_map.m_nrofblocks - 1; point[1] = locY; set = true; } else { @@ -304,7 +336,7 @@ public class Ghost { } } else { // Check for Right Warp - if (locX == this.map.nrofblocks - 1) { + if (locX == this.m_map.m_nrofblocks - 1) { point[0] = 0; point[1] = locY; set = true; @@ -319,9 +351,10 @@ public class Ghost { } public void doMove() { - this.x += this.dx; - this.y += this.dy; - //this.dx = 0; - //this.dy = 0; + 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 diff --git a/Robust/src/Benchmarks/MMG/Tag/MMG.java b/Robust/src/Benchmarks/MMG/Tag/MMG.java index 4be74680..7207bc60 100755 --- a/Robust/src/Benchmarks/MMG/Tag/MMG.java +++ b/Robust/src/Benchmarks/MMG/Tag/MMG.java @@ -14,27 +14,25 @@ task initMap(Map map{init}) { int i = 0; // create ghosts - for(i = 0; i < map.nrofghosts; i++) { + for(i = 0; i < map.m_nrofghosts; i++) { Ghost ghost = new Ghost(7, 7, map){move}; - ghost.setTarget(i%map.nrofpacs); - ghost.index = i; + ghost.m_index = i; map.placeGhost(ghost); - map.targets[i] = ghost.target; } // create pacmen int tx = 14; int ty = 14; - for(i = 0; i < map.nrofpacs; i++) { + 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.index = i; + pacman.m_index = i; map.placePacman(pacman); - map.desX[i] = tx*(i/2); - map.desY[i] = ty*(i%2); + map.m_desX[i] = tx*(i/2); + map.m_desY[i] = ty*(i%2); } - map.ghostcount = 0; - map.paccount = 0; + map.m_ghostcount = 0; + map.m_paccount = 0; taskexit(map{!init, updateGhost}); } @@ -61,19 +59,16 @@ task updateGhost(Map map{updateGhost}, optional Ghost g{update}) { if(isavailable(g)) { g.doMove(); map.placeGhost(g); - map.ghostdirections[g.index] = g.direction; } else { - //System.printString("FAILURE ghost!!!\n"); - //map.failghostcount++; - map.ghostcount++; + map.m_ghostcount++; } - if(map.ghostcount == map.nrofghosts) { - //map.nrofghosts -= map.failghostcount; - map.ghostcount = 0; - map.failghostcount = 0; - /*for(int i = 0; i < map.ghostsX.length; i++) { - System.printString("(" + map.ghostsX[i] + "," + map.ghostsY[i] + ") "); + 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}); @@ -87,23 +82,21 @@ task updatePac(Map map{updatePac}, optional Pacman p{update}) { if(isavailable(p)) { p.doMove(); map.placePacman(p); - map.directions[p.index] = p.direction; - //System.printString("Pacman " + p.index + ": (" + map.pacMenX[p.index] + "," + map.pacMenY[p.index] + ")\n"); + //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.index + " caught!\n"); + System.printString("Pacman " + p.m_index + " caught!\n"); }*/ } else { - //System.printString("FAILURE pacman!!!\n"); - map.deathcount++; - map.paccount++; + map.m_deathcount++; + map.m_paccount++; } - boolean finish = map.paccount == map.nrofpacs; + boolean finish = map.m_paccount == map.m_nrofpacs; if(finish) { - map.nrofpacs -= map.deathcount; - //System.printString(map.nrofpacs + " pacmen left. \n"); + 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 { @@ -118,25 +111,24 @@ task next(Map map{next}) { //System.printString("Task next\n"); int i = 0; - for(i = 0; i < map.nrofghosts; i++) { - Ghost ghost = new Ghost(map.ghostsX[i], map.ghostsY[i], map){move}; - ghost.setTarget(map.targets[i]); - ghost.index = i; - ghost.direction = map.ghostdirections[i]; + 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.pacMenX.length; i++) { - if(map.pacMenX[i] != -1) { + 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.pacMenX[i], map.pacMenY[i], map){move}; - pacman.setTarget(map.desX[i], map.desY[i]); - pacman.index = i; - pacman.direction = map.directions[i]; + 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.paccount = 0; - map.deathcount = 0; + map.m_paccount = 0; + map.m_deathcount = 0; taskexit(map{!next, updateGhost}); } diff --git a/Robust/src/Benchmarks/MMG/Tag/Map.java b/Robust/src/Benchmarks/MMG/Tag/Map.java index 906acdb2..eb0cef24 100755 --- a/Robust/src/Benchmarks/MMG/Tag/Map.java +++ b/Robust/src/Benchmarks/MMG/Tag/Map.java @@ -5,107 +5,158 @@ public class Map { flag next; flag finish; - public int[] map; - public int[] pacMenX; - public int[] pacMenY; - public int[] directions; - public int[] ghostsX; - public int[] ghostsY; - public int[] ghostdirections; - public int[] targets; - public int[] desX; - public int[] desY; + // maze + private int m_nrofblocks; + public int[] m_map; + public Node[] m_mapNodes; - public int nrofghosts; - public int nrofpacs; - private int nrofblocks; - //public boolean toupdate; - public int ghostcount; - public int paccount; - public int deathcount; - public int failghostcount; + // 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; - public Random r; + // 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.nrofblocks = 15; - this.map = new int[this.nrofblocks*this.nrofblocks]; - this.nrofpacs = nrofpacs; - this.nrofghosts = nrofghosts; - this.pacMenX = new int[this.nrofpacs]; - this.pacMenY = new int[this.nrofpacs]; - this.directions = new int[this.nrofpacs]; - this.ghostsX = new int[this.nrofghosts]; - this.ghostsY = new int[this.nrofghosts]; - this.ghostdirections = new int[this.nrofghosts]; - this.targets = new int[this.nrofghosts]; - this.desX = new int[this.nrofpacs]; - this.desY = new int[this.nrofpacs]; - //this.toupdate = false; - this.ghostcount = 0; - this.paccount = 0; - this.deathcount = 0; - this.failghostcount = 0; + 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.r = new Random(); + 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.nrofpacs; i++) { - this.pacMenX[i] = this.pacMenY[i] = -1; - this.desX[i] = this.desY[i] = -1; + 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.nrofghosts; i++) { - this.ghostsX[i] = this.ghostsY[i] = -1; - this.targets[i] = -1; + 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.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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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; - 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 + 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.pacMenX[t.index] = t.x; - this.pacMenY[t.index] = t.y; - //this.map[t.y * this.nrofblocks + t.x - 1] |= 16; - this.paccount++; + 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.ghostsX[t.index] = t.x; - this.ghostsY[t.index] = t.y; - //this.map[t.y * this.nrofblocks + t.x - 1] |= 32; - this.ghostcount++; + 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.nrofghosts)) { - if((t.x == this.ghostsX[i]) && (t.y == this.ghostsY[i])) { + 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.x == t.tx) && (t.y == t.ty)) { + if((!death) && (t.m_locX == t.m_tx) && (t.m_locY == t.m_ty)) { // reach the destination //System.printString("Hit destination!\n"); death = true; @@ -113,17 +164,17 @@ public class Map { if(death) { // pacman caught by ghost // set pacman as death - t.death = true; + t.m_death = true; // kick it out - //this.map[t.y * this.nrofblocks + t.x - 1] -= 16; - this.deathcount++; - this.pacMenX[t.index] = -1; - this.pacMenY[t.index] = -1; + //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 nrofpacs == 0; + return this.m_nrofpacs == 0; } } \ 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 index 00000000..bcc4d3e1 --- /dev/null +++ b/Robust/src/Benchmarks/MMG/Tag/Node.java @@ -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 diff --git a/Robust/src/Benchmarks/MMG/Tag/Pacman.java b/Robust/src/Benchmarks/MMG/Tag/Pacman.java index 48693a23..e75900eb 100755 --- a/Robust/src/Benchmarks/MMG/Tag/Pacman.java +++ b/Robust/src/Benchmarks/MMG/Tag/Pacman.java @@ -2,201 +2,299 @@ public class Pacman { flag move; flag update; - public int x; - public int y; - public boolean death; - public int index; - public int direction; // 0:still, 1:up, 2:down, 3:left, 4:right - int dx; - int dy; - public int tx; - public int ty; - int destinationX; - int destinationY; - Map map; + 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.x = x; - this.y = y; - this.dx = this.dy = 0; - this.death = false; - this.index = -1; - this.tx = this.ty = -1; - this.direction = 0; - this.destinationX = -1; - this.destinationY = -1; - this.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.tx = x; - this.ty = y; + this.m_tx = x; + this.m_ty = y; } public void tryMove() { // decide dx & dy - - // Don't let the pacman go back the way it came. - int prevDirection = 0; - - // If there is a destination, then check if the destination has been reached. - if (destinationX >= 0 && destinationY >= 0) { - // Check if the destination has been reached, if so, then - // get new destination. - if (destinationX == x && destinationY == y) { - destinationX = -1; - destinationY = -1; - prevDirection = direction; - } else { - // Otherwise, we haven't reached the destionation so - // continue in same direction. - return; - } - } - setNextDirection (prevDirection); + + // find the shortest possible way to the chosen target + setNextDirection(); } - private void setNextDirection(int prevDirection) { + 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.tx; - //System.printString("aaa\n"); - int targety = this.ty; + int targetx = this.m_tx; + int targety = this.m_ty; int[] nextLocation = new int[2]; nextLocation[0] = nextLocation[1] = -1; - //System.printString("bbb\n"); - getDestination (this.direction, 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]; - //System.printString("step 2\n"); - // check the distance - int deltax = this.x - targetx; // <0: move right; >0: move left - int deltay = this.y - targety; // <0: move down; >0: move up - // decide the priority of four moving directions - int[] bestDirection = new int[4]; - //System.printString("dx: " + deltax + "; dy: " + deltay + "\n"); - if((Math.abs(deltax) > Math.abs(deltay)) && (deltay != 0)) { - // go first along y - if(deltay > 0) { - bestDirection[0] = 1; - bestDirection[3] = 2; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; - } + // 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 { - bestDirection[0] = 2; - bestDirection[3] = 1; - if(deltax > 0) { - bestDirection[1] = 3; - bestDirection[2] = 4; - } else { - bestDirection[1] = 4; - bestDirection[2] = 3; + // 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; + } } - } - } else { - if(deltax > 0) { - bestDirection[0] = 3; - bestDirection[3] = 4; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + + // 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + // still + this.m_direction = 0; } - } else { - bestDirection[0] = 4; - bestDirection[3] = 3; - if(deltay > 0) { - bestDirection[1] = 1; - bestDirection[2] = 2; + 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 { - bestDirection[1] = 2; - bestDirection[2] = 1; + cuts.addElement(new Integer(index)); + /*for( int h = 0; h < cuts.size(); h++) { + System.printString(cuts.elementAt(h) + ", "); + } + System.printString("\n");*/ } } } - /*for(int i = 0; i < 4; i++) { - System.printString(bestDirection[i] + ","); + } + + // 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); + } + } + } } - System.printString("\n");*/ + 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; - // There's a 50% chance that the ghost will try the sub-optimal direction first. - // This will keep the ghosts from following each other and to trap Pacman. - if (this.map.r.nextDouble() < .50) { - int temp = bestDirection[0]; - bestDirection[0] = bestDirection[1]; - bestDirection[1] = temp; + // 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++; } - - //System.printString("step 3\n"); - // try to move one by one - int i = 0; + steps++; + boolean set = false; - this.dx = 0; - this.dy = 0; - while((!set) && (i < 4)) { - if(bestDirection[i] == 1) { - // try to move up - if((prevDirection != 2) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 2) == 0)) { - //System.printString("a\n"); - if (getDestination (1, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = -1; - set = true; - } - } - } else if (bestDirection[i] == 2) { - // try to move down - if((prevDirection != 1) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 8) == 0)) { - //System.printString("b\n"); - if (getDestination (2, this.x, this.y, nextLocation)) { - this.dx = 0; - this.dy = 1; - set = true; + // 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 if (bestDirection[i] == 3) { - // try to move left - if((prevDirection != 4) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 1) == 0)) { - //System.printString("c\n"); - if (getDestination (3, this.x, this.y, nextLocation)) { - this.dx = -1; - this.dy = 0; - set = true; + } 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++; + } } } - } else if (bestDirection[i] == 4) { - // try to move right - if((prevDirection != 3) && ((int)(this.map.map[y * this.map.nrofblocks + x] & 4) == 0)) { - //System.printString("d\n"); - if (getDestination (4, this.x, this.y, nextLocation)) { - this.dx = 1; - this.dy = 0; - set = true; - } + } + } + + // 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]; } } - i++; } - //System.printString("step 4\n"); + + 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. - boolean getDestination (int direction, int locX, int locY, int[] point) { + 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 && (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0) || // up - (direction == 3 && (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) || // left - (direction == 2 && (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) || // down - (direction == 4 && (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0)) { // right + 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; @@ -221,20 +319,20 @@ public class Pacman { // then return false. if (locY < 0 || locX < 0 || - locY == this.map.nrofblocks || - locX == this.map.nrofblocks) { + locY == this.m_map.m_nrofblocks || + locX == this.m_map.m_nrofblocks) { return false; } boolean set = false; - // Determine next turning location.. + // Determine next turning location. while (!set) { if (direction == 1 || direction == 2) { // up or down - if ((this.map.map[locX + locY * this.map.nrofblocks] & 4) == 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) == 0 || // left - (this.map.map[locX + locY * this.map.nrofblocks] & 2) != 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) != 0) { // 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; @@ -243,14 +341,14 @@ public class Pacman { // Check for Top Warp if (locY == 0) { point[0] = locX; - point[1] = this.map.nrofblocks - 1; + point[1] = this.m_map.m_nrofblocks - 1; set = true; } else { locY--; } } else { // Check for Bottom Warp - if (locY == this.map.nrofblocks - 1) { + if (locY == this.m_map.m_nrofblocks - 1) { point[0] = locX; point[1] = 0; set = true; @@ -261,10 +359,10 @@ public class Pacman { } } else { // left or right - if ((this.map.map[locX + locY * this.map.nrofblocks] & 2) == 0 || // up - (this.map.map[locX + locY * this.map.nrofblocks] & 8) == 0 || // down - (this.map.map[locX + locY * this.map.nrofblocks] & 4) != 0 || // right - (this.map.map[locX + locY * this.map.nrofblocks] & 1) != 0) { // left + 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; @@ -272,7 +370,7 @@ public class Pacman { if (direction == 3) { // Check for Left Warp if (locX == 0) { - point[0] = this.map.nrofblocks - 1; + point[0] = this.m_map.m_nrofblocks - 1; point[1] = locY; set = true; } else { @@ -280,7 +378,7 @@ public class Pacman { } } else { // Check for Right Warp - if (locX == this.map.nrofblocks - 1) { + if (locX == this.m_map.m_nrofblocks - 1) { point[0] = 0; point[1] = locY; set = true; @@ -295,10 +393,10 @@ public class Pacman { } public void doMove() { - // System.printString("dx: " + this.dx + ", dy: " + this.dy + "\n"); - this.x += this.dx; - this.y += this.dy; - //this.dx = 0; - //this.dy = 0; + 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