9 public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
14 public Ghost(int x, int y, Map map) {
17 this.m_dx = this.m_dy = 0;
24 // 0:still, 1:up, 2:down, 3:left, 4:right
25 public void tryMove() {
26 //System.printString("step 1\n");
29 // find the shortest possible way to the chosen target
33 private void setNextDirection() {
34 // current position of the ghost
35 int start = this.m_locY * this.m_map.m_nrofblocks + this.m_locX;
37 Vector cuts = new Vector();
44 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
45 for(int i = 0; i < parents.length; i++) {
48 if(!BFS(start, parents, cuts)) {
49 this.m_target = tmptarget;
52 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
54 //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
56 // Reversely go over the parents array to find the next node to reach
57 boolean found = false;
58 int index = this.m_map.m_pacMenY[this.m_target] * this.m_map.m_nrofblocks + this.m_map.m_pacMenX[this.m_target];
59 //System.printString("Target: " + this.m_target + "\n");
61 int parent = parents[index];
69 // set the chase direction
70 int nx = index % this.m_map.m_nrofblocks;
71 int ny = index / this.m_map.m_nrofblocks;
72 this.m_dx = nx - this.m_locX;
73 this.m_dy = ny - this.m_locY;
77 } else if(this.m_dx < 0) {
80 } else if(this.m_dy > 0) {
83 } else if(this.m_dy < 0) {
91 tmptarget = this.m_target;
94 tmpdirection = this.m_direction;
96 //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
99 // check if this choice follows some other ghosts' path
101 this.m_map.m_ghostdirections[this.m_index] = this.m_direction;
104 cuts.addElement(new Integer(index));
105 /*for( int h = 0; h < cuts.size(); h++) {
106 System.printString(cuts.elementAt(h) + ", ");
108 System.printString("\n");*/
114 // This methos do BFS from start node to end node
115 // If there is a path from start to end, return true; otherwise, return false
116 // Array parents records parent for a node in the BFS search,
117 // the last item of parents records the least steps to reach end node from start node
118 // Vector cuts specifies which nodes can not be the first one to access in this BFS
119 private boolean BFS(int start, int[] parents, Vector cuts) {
120 //System.printString("aaa\n");
122 Vector toaccess = new Vector();
123 toaccess.addElement(new Integer(start));
124 while(toaccess.size() > 0) {
125 //System.printString("bbb\n");
126 // pull out the first one to access
127 int access = ((Integer)toaccess.elementAt(0)).intValue();
128 toaccess.removeElementAt(0);
129 for(int i = 0; i < this.m_map.m_pacMenX.length; i++) {
130 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])) {
133 parents[parents.length - 1] = steps;
138 Vector neighbours = this.m_map.getNeighbours(access);
139 for(int i = 0; i < neighbours.size(); i++) {
140 int neighbour = ((Integer)neighbours.elementAt(i)).intValue();
141 if(parents[neighbour] == -1) {
143 boolean ignore = false;
144 if(access == start) {
145 // start node, check if the neighbour node is in cuts
147 while((!ignore) && (j < cuts.size())) {
148 int tmp = ((Integer)cuts.elementAt(j)).intValue();
149 if(tmp == neighbour) {
156 parents[neighbour] = access;
157 toaccess.addElement(new Integer(neighbour));
162 //System.printString("ccc\n");
163 parents[parents.length - 1] = -1;
167 // This method returns true if this ghost is traveling to the same
168 // destination with the same direction as another ghost.
169 private boolean isFollowing () {
170 boolean bFollowing = false;
173 // If the ghost is in the same location as another ghost
174 // and moving in the same direction, then they are on
175 // top of each other and should not follow.
176 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
178 if (this.m_index != i) {
179 if (this.m_map.m_ghostsX[i] == this.m_locX &&
180 this.m_map.m_ghostsY[i] == this.m_locY &&
181 this.m_map.m_ghostdirections[i] == this.m_direction) {
187 // This will allow ghosts to often
188 // clump together for easier eating
189 dRandom = this.m_map.m_r.nextDouble();
191 //if (m_bInsaneAI && dRandom < .25)
197 // If ghost is moving to the same location and using the
198 // same direction, then it is following another ghost.
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_targets[i] == this.m_target &&
203 this.m_map.m_ghostdirections[i] == this.m_direction) {
212 // This method will take the specified location and direction and determine
213 // for the given location if the thing moved in that direction, what the
214 // next possible turning location would be.
215 private boolean getDestination (int direction, int locX, int locY, int[] point) {
216 // If the request direction is blocked by a wall, then just return the current location
217 if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
218 ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
219 ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
220 ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
226 // Start off by advancing one in direction for specified location
227 if (direction == 1) {
230 } else if (direction == 2) {
233 } else if (direction == 3) {
236 } else if (direction == 4) {
241 // If we violate the grid boundary,
242 // then return false.
245 locY == this.m_map.m_nrofblocks ||
246 locX == this.m_map.m_nrofblocks) {
251 // Determine next turning location.
253 if (direction == 1 || direction == 2) {
255 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
256 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
257 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
258 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
263 if (direction == 1) {
264 // Check for Top Warp
267 point[1] = this.m_map.m_nrofblocks - 1;
273 // Check for Bottom Warp
274 if (locY == this.m_map.m_nrofblocks - 1) {
285 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
286 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
287 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
288 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
293 if (direction == 3) {
294 // Check for Left Warp
296 point[0] = this.m_map.m_nrofblocks - 1;
303 // Check for Right Warp
304 if (locX == this.m_map.m_nrofblocks - 1) {
318 public void doMove() {
319 this.m_locX += this.m_dx;
320 this.m_locY += this.m_dy;
323 //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");