9 public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
16 public Ghost(int x, int y, Map map) {
19 this.m_dx = this.m_dy = 0;
23 //this.m_destinationX = this.m_destinationY = -1;
27 // 0:still, 1:up, 2:down, 3:left, 4:right
28 public void tryMove() {
29 //System.printString("step 1\n");
32 // find the shortest possible way to the chosen target
36 private void setNextDirection() {
37 // current position of the ghost
38 int start = this.m_locY * this.m_map.m_nrofblocks + this.m_locX;
40 Vector cuts = new Vector();
45 //int tmpdestinationX = -1;
46 //int tmpdestinationY = -1;
48 /*int[] candidateDesX = new int[this.m_map.m_destinationX.length];
49 int[] candidateDesY = new int[this.m_map.m_destinationX.length];
50 for(int i = 0; i < this.m_map.m_destinationX.length; i++) {
51 candidateDesX = this.m_map.m_destinationX[i];
55 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
56 for(int i = 0; i < parents.length; i++) {
59 if(!BFS(start, parents, cuts)) {
60 this.m_target = tmptarget;
63 //this.m_destinationX = tmpdestinationX;
64 //this.m_destinationY = tmpdestinationY;
65 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
67 //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
69 // Reversely go over the parents array to find the next node to reach
70 int index = this.m_map.m_pacMenY[this.m_target] * this.m_map.m_nrofblocks + this.m_map.m_pacMenX[this.m_target];
71 int steps = parents[parents.length - 1];
73 // already caught one pacman, stay still
74 this.m_dx = this.m_dy = 0;
75 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = 0;
76 //System.printString("Stay still\n");
79 boolean found = false;
81 int parent = parents[index];
87 // System.printString("parent: " + parent + "\n");
89 //System.printString("Index: " + index + "\n");
91 // set the chase direction
92 int nx = index % this.m_map.m_nrofblocks;
93 int ny = index / this.m_map.m_nrofblocks;
94 this.m_dx = nx - this.m_locX;
95 this.m_dy = ny - this.m_locY;
99 } else if(this.m_dx < 0) {
101 this.m_direction = 3;
102 } else if(this.m_dy > 0) {
104 this.m_direction = 2;
105 } else if(this.m_dy < 0) {
107 this.m_direction = 1;
110 this.m_direction = 0;
113 tmptarget = this.m_target;
116 tmpdirection = this.m_direction;
118 //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
122 // check if this choice follows some other ghosts' path
124 this.m_map.m_ghostdirections[this.m_index] = this.m_direction;
127 cuts.addElement(new Integer(index));
128 /*for( int h = 0; h < cuts.size(); h++) {
129 System.printString(cuts.elementAt(h) + ", ");
131 System.printString("\n");*/
137 // This methos do BFS from start node to end node
138 // If there is a path from start to end, return true; otherwise, return false
139 // Array parents records parent for a node in the BFS search,
140 // the last item of parents records the least steps to reach end node from start node
141 // Vector cuts specifies which nodes can not be the first one to access in this BFS
142 private boolean BFS(int start, int[] parents, Vector cuts) {
143 //System.printString("aaa\n");
145 Vector toaccess = new Vector();
146 toaccess.addElement(new Integer(start));
147 while(toaccess.size() > 0) {
148 //System.printString("bbb\n");
149 // pull out the first one to access
150 int access = ((Integer)toaccess.elementAt(0)).intValue();
151 toaccess.removeElementAt(0);
152 for(int i = 0; i < this.m_map.m_pacMenX.length; i++) {
153 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])) {
156 parents[parents.length - 1] = steps;
161 Vector neighbours = this.m_map.getNeighbours(access);
162 for(int i = 0; i < neighbours.size(); i++) {
163 int neighbour = ((Integer)neighbours.elementAt(i)).intValue();
164 if(parents[neighbour] == -1) {
166 boolean ignore = false;
167 if(access == start) {
168 // start node, check if the neighbour node is in cuts
170 while((!ignore) && (j < cuts.size())) {
171 int tmp = ((Integer)cuts.elementAt(j)).intValue();
172 if(tmp == neighbour) {
179 parents[neighbour] = access;
180 toaccess.addElement(new Integer(neighbour));
185 //System.printString("ccc\n");
186 parents[parents.length - 1] = -1;
190 // This method returns true if this ghost is traveling to the same
191 // destination with the same direction as another ghost.
192 private boolean isFollowing () {
193 boolean bFollowing = false;
196 // If the ghost is in the same location as another ghost
197 // and moving in the same direction, then they are on
198 // top of each other and should not follow.
199 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
201 if (this.m_index != i) {
202 if (this.m_map.m_ghostsX[i] == this.m_locX &&
203 this.m_map.m_ghostsY[i] == this.m_locY &&
204 this.m_map.m_ghostdirections[i] == this.m_direction) {
210 // This will allow ghosts to often
211 // clump together for easier eating
212 dRandom = this.m_map.m_r.nextDouble();
214 //if (m_bInsaneAI && dRandom < .25)
220 // If ghost is moving to the same location and using the
221 // same direction, then it is following another ghost.
222 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
224 if (this.m_index != i) {
225 if (this.m_map.m_targets[i] == this.m_target &&
226 this.m_map.m_ghostdirections[i] == this.m_direction) {
235 // This method will take the specified location and direction and determine
236 // for the given location if the thing moved in that direction, what the
237 // next possible turning location would be.
238 private boolean getDestination (int direction, int locX, int locY, int[] point) {
239 // If the request direction is blocked by a wall, then just return the current location
240 if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
241 ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
242 ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
243 ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
249 // Start off by advancing one in direction for specified location
250 if (direction == 1) {
253 } else if (direction == 2) {
256 } else if (direction == 3) {
259 } else if (direction == 4) {
264 // If we violate the grid boundary,
265 // then return false.
268 locY == this.m_map.m_nrofblocks ||
269 locX == this.m_map.m_nrofblocks) {
274 // Determine next turning location.
276 if (direction == 1 || direction == 2) {
278 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
279 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
280 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
281 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
286 if (direction == 1) {
287 // Check for Top Warp
290 point[1] = this.m_map.m_nrofblocks - 1;
296 // Check for Bottom Warp
297 if (locY == this.m_map.m_nrofblocks - 1) {
308 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
309 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
310 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
311 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
316 if (direction == 3) {
317 // Check for Left Warp
319 point[0] = this.m_map.m_nrofblocks - 1;
326 // Check for Right Warp
327 if (locX == this.m_map.m_nrofblocks - 1) {
341 public void doMove() {
342 if((this.m_dx == -1) && (this.m_locX == 0)) {
343 // go left and currently this.m_locX is 0
344 this.m_locX = this.m_map.m_nrofblocks - 1;
345 } else if((this.m_dx == 1) && (this.m_locX == this.m_map.m_nrofblocks - 1)) {
348 this.m_locX += this.m_dx;
351 if((this.m_dy == -1) && (this.m_locY == 0)) {
352 // go up and currently this.m_locY is 0
353 this.m_locY = this.m_map.m_nrofblocks - 1;
354 } else if((this.m_dy == 1) && (this.m_locY == this.m_map.m_nrofblocks - 1)) {
357 this.m_locY += this.m_dy;
361 //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");