7 public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
12 public Ghost(int x, int y, Map map) {
15 this.m_dx = this.m_dy = 0;
22 // 0:still, 1:up, 2:down, 3:left, 4:right
23 public void tryMove() {
24 //System.printString("step 1\n");
27 // find the shortest possible way to the chosen target
31 private void setNextDirection() {
32 // current position of the ghost
33 int start = this.m_locY * this.m_map.m_nrofblocks + this.m_locX;
35 Vector cuts = new Vector();
42 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
43 for(int i = 0; i < parents.length; i++) {
46 if(!BFS(start, parents, cuts)) {
47 this.m_target = tmptarget;
50 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
52 //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
54 // Reversely go over the parents array to find the next node to reach
55 int index = this.m_map.m_pacMenY[this.m_target] * this.m_map.m_nrofblocks + this.m_map.m_pacMenX[this.m_target];
56 int steps = parents[parents.length - 1];
58 // already caught one pacman, stay still
59 this.m_dx = this.m_dy = 0;
60 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = 0;
61 //System.printString("Stay still\n");
64 boolean found = false;
66 int parent = parents[index];
72 // System.printString("parent: " + parent + "\n");
74 //System.printString("Index: " + index + "\n");
76 // set the chase direction
77 int nx = index % this.m_map.m_nrofblocks;
78 int ny = index / this.m_map.m_nrofblocks;
79 this.m_dx = nx - this.m_locX;
80 this.m_dy = ny - this.m_locY;
84 } else if(this.m_dx < 0) {
87 } else if(this.m_dy > 0) {
90 } else if(this.m_dy < 0) {
98 tmptarget = this.m_target;
101 tmpdirection = this.m_direction;
103 //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
107 // check if this choice follows some other ghosts' path
109 this.m_map.m_ghostdirections[this.m_index] = this.m_direction;
112 cuts.addElement(new Integer(index));
113 /*for( int h = 0; h < cuts.size(); h++) {
114 System.printString(cuts.elementAt(h) + ", ");
116 System.printString("\n");*/
122 // This methos do BFS from start node to end node
123 // If there is a path from start to end, return true; otherwise, return false
124 // Array parents records parent for a node in the BFS search,
125 // the last item of parents records the least steps to reach end node from start node
126 // Vector cuts specifies which nodes can not be the first one to access in this BFS
127 private boolean BFS(int start, int[] parents, Vector cuts) {
129 Vector toaccess = new Vector();
130 toaccess.addElement(new Integer(start));
131 while(toaccess.size() > 0) {
132 //System.printString("bbb\n");
133 // pull out the first one to access
134 int access = ((Integer)toaccess.elementAt(0)).intValue();
135 toaccess.removeElementAt(0);
136 for(int i = 0; i < this.m_map.m_pacMenX.length; i++) {
137 if(((access%this.m_map.m_nrofblocks) == this.m_map.m_pacMenX[i]) && ((access/this.m_map.m_nrofblocks) == this.m_map.m_pacMenY[i])) {
140 parents[parents.length - 1] = steps;
145 Vector neighbours = this.m_map.getNeighbours(access);
146 for(int i = 0; i < neighbours.size(); i++) {
147 int neighbour = ((Integer)neighbours.elementAt(i)).intValue();
148 if(parents[neighbour] == -1) {
150 boolean ignore = false;
151 if(access == start) {
152 // start node, check if the neighbour node is in cuts
154 while((!ignore) && (j < cuts.size())) {
155 int tmp = ((Integer)cuts.elementAt(j)).intValue();
156 if(tmp == neighbour) {
163 parents[neighbour] = access;
164 toaccess.addElement(new Integer(neighbour));
169 parents[parents.length - 1] = -1;
173 // This method returns true if this ghost is traveling to the same
174 // destination with the same direction as another ghost.
175 private boolean isFollowing () {
176 boolean bFollowing = false;
179 // If the ghost is in the same location as another ghost
180 // and moving in the same direction, then they are on
181 // top of each other and should not follow.
182 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
184 if (this.m_index != i) {
185 if (this.m_map.m_ghostsX[i] == this.m_locX &&
186 this.m_map.m_ghostsY[i] == this.m_locY &&
187 this.m_map.m_ghostdirections[i] == this.m_direction) {
193 // This will allow ghosts to often
194 // clump together for easier eating
195 dRandom = this.m_map.m_r.nextDouble();
197 //if (m_bInsaneAI && dRandom < .25)
203 // If ghost is moving to the same location and using the
204 // same direction, then it is following another ghost.
205 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
207 if (this.m_index != i) {
208 if (this.m_map.m_targets[i] == this.m_target &&
209 this.m_map.m_ghostdirections[i] == this.m_direction) {
218 // This method will take the specified location and direction and determine
219 // for the given location if the thing moved in that direction, what the
220 // next possible turning location would be.
221 private boolean getDestination (int direction, int locX, int locY, int[] point) {
222 // If the request direction is blocked by a wall, then just return the current location
223 if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
224 ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
225 ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
226 ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
232 // Start off by advancing one in direction for specified location
233 if (direction == 1) {
236 } else if (direction == 2) {
239 } else if (direction == 3) {
242 } else if (direction == 4) {
247 // If we violate the grid boundary,
248 // then return false.
251 locY == this.m_map.m_nrofblocks ||
252 locX == this.m_map.m_nrofblocks) {
257 // Determine next turning location.
259 if (direction == 1 || direction == 2) {
261 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
262 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
263 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
264 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
269 if (direction == 1) {
270 // Check for Top Warp
273 point[1] = this.m_map.m_nrofblocks - 1;
279 // Check for Bottom Warp
280 if (locY == this.m_map.m_nrofblocks - 1) {
291 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
292 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
293 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
294 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
299 if (direction == 3) {
300 // Check for Left Warp
302 point[0] = this.m_map.m_nrofblocks - 1;
309 // Check for Right Warp
310 if (locX == this.m_map.m_nrofblocks - 1) {
324 public void doMove() {
325 if((this.m_dx == -1) && (this.m_locX == 0)) {
326 // go left and currently this.m_locX is 0
327 this.m_locX = this.m_map.m_nrofblocks - 1;
328 } else if((this.m_dx == 1) && (this.m_locX == this.m_map.m_nrofblocks - 1)) {
331 this.m_locX += this.m_dx;
334 if((this.m_dy == -1) && (this.m_locY == 0)) {
335 // go up and currently this.m_locY is 0
336 this.m_locY = this.m_map.m_nrofblocks - 1;
337 } else if((this.m_dy == 1) && (this.m_locY == this.m_map.m_nrofblocks - 1)) {
340 this.m_locY += this.m_dy;
344 //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");