7 public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
\r
12 public Ghost(int x, int y, Map map) {
\r
15 this.m_dx = this.m_dy = 0;
\r
18 this.m_direction = 0;
\r
22 // 0:still, 1:up, 2:down, 3:left, 4:right
\r
23 public void tryMove() {
\r
24 // System.printString("step 1\n");
\r
27 // check the nearest pacman and set it as current target
\r
29 int deltaX = this.m_map.m_nrofblocks;
\r
30 int deltaY = this.m_map.m_nrofblocks;
\r
31 int distance = deltaX * deltaX + deltaY * deltaY;
\r
32 for(i = 0; i < this.m_map.m_nrofpacs; i++) {
\r
33 if(this.m_map.m_pacMenX[i] != -1) {
\r
34 int dx = this.m_locX - this.m_map.m_pacMenX[i];
\r
35 int dy = this.m_locY - this.m_map.m_pacMenY[i];
\r
36 int dd = dx*dx+dy*dy;
\r
45 // System.printString("target: " + this.m_target + "\n");
\r
47 if(this.m_target == -1) {
\r
48 // no more pacmen to chase, stay still
\r
51 this.m_direction = this.m_map.m_ghostdirections[this.m_index] = 0;
\r
55 // find the shortest way to the chosen target
\r
59 private void setNextDirection() {
\r
60 // current position of the ghost
\r
61 Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];
\r
63 // get target's position
\r
64 int targetx = this.m_map.m_pacMenX[this.m_target];
\r
65 int targety = this.m_map.m_pacMenY[this.m_target];
\r
66 int[] nextLocation = new int[2];
\r
67 nextLocation[0] = nextLocation[1] = -1;
\r
68 // check the target pacman's possible destination
\r
69 getDestination (this.m_map.m_directions[this.m_target], targetx, targety, nextLocation);
\r
70 targetx = nextLocation[0];
\r
71 targety = nextLocation[1];
\r
72 // target's position
\r
73 Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];
\r
74 // reset the target as index of the end node
\r
75 this.m_target = this.m_map.m_targets[this.m_index] = end.getIndex();
\r
77 // breadth-first traverse the graph view of the maze
\r
78 // check the shortest path for the start node to the end node
\r
79 boolean set = false;
\r
80 Vector cuts = new Vector();
\r
83 int tmpdirection = 0;
\r
84 boolean first = true;
\r
86 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks];
\r
87 for(int i = 0; i < parents.length; i++) {
\r
90 if(!BFS(start, end, parents, cuts)) {
\r
93 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
\r
95 //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
\r
97 // Reversely go over the parents array to find the next node to reach
\r
98 boolean found = false;
\r
99 int index = end.getIndex();
\r
101 int parent = parents[index];
\r
102 if(parent == start.getIndex()) {
\r
109 // set the chase direction
\r
110 int nx = this.m_map.m_mapNodes[index].getXLoc();
\r
111 int ny = this.m_map.m_mapNodes[index].getYLoc();
\r
112 this.m_dx = nx - this.m_locX;
\r
113 this.m_dy = ny - this.m_locY;
\r
114 if(this.m_dx > 0) {
\r
116 this.m_direction = 4;
\r
117 } else if(this.m_dx < 0) {
\r
119 this.m_direction = 3;
\r
120 } else if(this.m_dy > 0) {
\r
122 this.m_direction = 2;
\r
123 } else if(this.m_dy < 0) {
\r
125 this.m_direction = 1;
\r
128 this.m_direction = 0;
\r
133 tmpdirection = this.m_direction;
\r
135 //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
\r
138 // check if this choice follows some other ghosts' path
\r
139 if(!isFollowing()) {
\r
140 this.m_map.m_ghostdirections[this.m_index] = this.m_direction;
\r
143 cuts.addElement(new Integer(index));
\r
144 /*for( int h = 0; h < cuts.size(); h++) {
\r
145 System.printString(cuts.elementAt(h) + ", ");
\r
147 System.printString("\n");*/
\r
153 // This methos do BFS from start node to end node
\r
154 // If there is a path from start to end, return true; otherwise, return false
\r
155 // Array parents records parent for a node in the BFS search
\r
156 // Vector cuts specifies which nodes can not be the first one to access in this BFS
\r
157 private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {
\r
158 Vector toaccess = new Vector();
\r
159 toaccess.addElement(start);
\r
160 while(toaccess.size() > 0) {
\r
161 // pull out the first one to access
\r
162 Node access = (Node)toaccess.elementAt(0);
\r
163 toaccess.removeElementAt(0);
\r
164 if(access.getIndex() == end.getIndex()) {
\r
165 // hit the end node
\r
168 Vector neighbours = access.getNeighbours();
\r
169 for(int i = 0; i < neighbours.size(); i++) {
\r
170 Node neighbour = (Node)neighbours.elementAt(i);
\r
171 if(parents[neighbour.getIndex()] == -1) {
\r
173 boolean ignore = false;
\r
174 if(access.getIndex() == start.getIndex()) {
\r
175 // start node, check if the neighbour node is in cuts
\r
177 while((!ignore) && (j < cuts.size())) {
\r
178 int tmp = ((Integer)cuts.elementAt(j)).intValue();
\r
179 if(tmp == neighbour.getIndex()) {
\r
186 parents[neighbour.getIndex()] = access.getIndex();
\r
187 toaccess.addElement(neighbour);
\r
195 // This method returns true if this ghost is traveling to the same
\r
196 // destination with the same direction as another ghost.
\r
197 private boolean isFollowing () {
\r
198 boolean bFollowing = false;
\r
201 // If the ghost is in the same location as another ghost
\r
202 // and moving in the same direction, then they are on
\r
203 // top of each other and should not follow.
\r
204 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
\r
206 if (this.m_index != i) {
\r
207 if (this.m_map.m_ghostsX[i] == this.m_locX &&
\r
208 this.m_map.m_ghostsY[i] == this.m_locY &&
\r
209 this.m_map.m_ghostdirections[i] == this.m_direction) {
\r
215 // This will allow ghosts to often
\r
216 // clump together for easier eating
\r
217 dRandom = this.m_map.m_r.nextDouble();
\r
218 if (dRandom < .90) {
\r
219 //if (m_bInsaneAI && dRandom < .25)
\r
225 // If ghost is moving to the same location and using the
\r
226 // same direction, then it is following another ghost.
\r
227 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
\r
229 if (this.m_index != i) {
\r
230 if (this.m_map.m_targets[i] == this.m_target &&
\r
231 this.m_map.m_ghostdirections[i] == this.m_direction) {
\r
240 // This method will take the specified location and direction and determine
\r
241 // for the given location if the thing moved in that direction, what the
\r
242 // next possible turning location would be.
\r
243 private boolean getDestination (int direction, int locX, int locY, int[] point) {
\r
244 // If the request direction is blocked by a wall, then just return the current location
\r
245 if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
\r
246 ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
\r
247 ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
\r
248 ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
\r
254 // Start off by advancing one in direction for specified location
\r
255 if (direction == 1) {
\r
258 } else if (direction == 2) {
\r
261 } else if (direction == 3) {
\r
264 } else if (direction == 4) {
\r
269 // If we violate the grid boundary,
\r
270 // then return false.
\r
273 locY == this.m_map.m_nrofblocks ||
\r
274 locX == this.m_map.m_nrofblocks) {
\r
278 boolean set = false;
\r
279 // Determine next turning location.
\r
281 if (direction == 1 || direction == 2) {
\r
283 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
\r
284 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
\r
285 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
\r
286 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
\r
291 if (direction == 1) {
\r
292 // Check for Top Warp
\r
295 point[1] = this.m_map.m_nrofblocks - 1;
\r
301 // Check for Bottom Warp
\r
302 if (locY == this.m_map.m_nrofblocks - 1) {
\r
313 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
\r
314 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
\r
315 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
\r
316 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
\r
321 if (direction == 3) {
\r
322 // Check for Left Warp
\r
324 point[0] = this.m_map.m_nrofblocks - 1;
\r
331 // Check for Right Warp
\r
332 if (locX == this.m_map.m_nrofblocks - 1) {
\r
346 public void doMove() {
\r
347 this.m_locX += this.m_dx;
\r
348 this.m_locY += this.m_dy;
\r
351 //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");
\r