7 public boolean m_death;
9 public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
16 public Pacman(int x, int y, Map map) {
19 this.m_dx = this.m_dy = 0;
22 this.m_tx = this.m_ty = -1;
27 public void setTarget(int x, int y) {
32 public void tryMove() {
35 // find the shortest possible way to the chosen target
39 private void setNextDirection() {
40 // current position of the ghost
41 int start = this.m_locY * this.m_map.m_nrofblocks + this.m_locX;
43 // get target's position
44 int targetx = this.m_tx;
45 int targety = this.m_ty;
46 int[] nextLocation = new int[2];
47 nextLocation[0] = nextLocation[1] = -1;
50 int end = targety * this.m_map.m_nrofblocks + targetx;
52 // breadth-first traverse the graph view of the maze
53 // check the shortest path for the start node to the end node
55 Vector cuts = new Vector();
61 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
62 for(int i = 0; i < parents.length; i++) {
65 if(!BFS(start, end, parents, cuts)) {
68 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
70 //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
72 // Reversely go over the parents array to find the next node to reach
73 boolean found = false;
76 int parent = parents[index];
84 // set the chase direction
85 int nx = index % this.m_map.m_nrofblocks;
86 int ny = index / this.m_map.m_nrofblocks;
87 this.m_dx = nx - this.m_locX;
88 this.m_dy = ny - this.m_locY;
92 } else if(this.m_dx < 0) {
95 } else if(this.m_dy > 0) {
98 } else if(this.m_dy < 0) {
100 this.m_direction = 1;
103 this.m_direction = 0;
108 tmpdirection = this.m_direction;
110 //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
113 // check if this choice follows some other ghosts' path
115 this.m_map.m_directions[this.m_index] = this.m_direction;
118 cuts.addElement(new Integer(index));
119 /*for( int h = 0; h < cuts.size(); h++) {
120 System.printString(cuts.elementAt(h) + ", ");
122 System.printString("\n");*/
128 // This methos do BFS from start node to end node
129 // If there is a path from start to end, return true; otherwise, return false
130 // Array parents records parent for a node in the BFS search,
131 // the last item of parents records the least steps to reach end node from start node
132 // Vector cuts specifies which nodes can not be the first one to access in this BFS
133 private boolean BFS(int start, int end, int[] parents, Vector cuts) {
135 Vector toaccess = new Vector();
136 toaccess.addElement(new Integer(start));
137 while(toaccess.size() > 0) {
138 // pull out the first one to access
139 int access = ((Integer)toaccess.elementAt(0)).intValue();
140 toaccess.removeElementAt(0);
143 parents[parents.length - 1] = steps;
147 Vector neighbours = this.m_map.getNeighbours(access);
148 for(int i = 0; i < neighbours.size(); i++) {
149 int neighbour = ((Integer)neighbours.elementAt(i)).intValue();
150 if(parents[neighbour] == -1) {
152 boolean ignore = false;
153 if(access == start) {
154 // start node, check if the neighbour node is in cuts
156 while((!ignore) && (j < cuts.size())) {
157 int tmp = ((Integer)cuts.elementAt(j)).intValue();
158 if(tmp == neighbour) {
165 parents[neighbour] = access;
166 toaccess.addElement(new Integer(neighbour));
171 parents[parents.length - 1] = -1;
175 // This method returns true if this pacmen can flee in this direction.
176 private boolean canFlee () {
178 int locX = this.m_locX;
179 int locY = this.m_locY;
180 int[] point = new int[2];
181 point[0] = point[1] = -1;
183 // Start off by advancing one in direction for specified location
184 if (this.m_direction == 1) {
187 } else if (this.m_direction == 2) {
190 } else if (this.m_direction == 3) {
193 } else if (this.m_direction == 4) {
200 // Determine next turning location.
202 if (this.m_direction == 1 || this.m_direction == 2) {
204 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
205 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
206 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
207 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
212 if (this.m_direction == 1) {
213 // Check for Top Warp
216 point[1] = this.m_map.m_nrofblocks - 1;
223 // Check for Bottom Warp
224 if (locY == this.m_map.m_nrofblocks - 1) {
236 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
237 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
238 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
239 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
244 if (this.m_direction == 3) {
245 // Check for Left Warp
247 point[0] = this.m_map.m_nrofblocks - 1;
255 // Check for Right Warp
256 if (locX == this.m_map.m_nrofblocks - 1) {
269 // check the least steps for the ghosts to reach point location
271 int end = point[1] * this.m_map.m_nrofblocks + point[0];
272 for(int i = 0; i < this.m_map.m_ghostsX.length; i++) {
273 int start = this.m_map.m_ghostsY[i] * this.m_map.m_nrofblocks + this.m_map.m_ghostsX[i];
274 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
275 for(int j = 0; j < parents.length; j++) {
278 if(BFS(start, end, parents, new Vector())) {
279 if((chasesteps == -1) ||
280 (chasesteps > parents[parents.length - 1])) {
281 chasesteps = parents[parents.length - 1];
286 return ((chasesteps == -1) || (steps < chasesteps));
289 // This method will take the specified location and direction and determine
290 // for the given location if the thing moved in that direction, what the
291 // next possible turning location would be.
292 private boolean getDestination (int direction, int locX, int locY, int[] point) {
293 // If the request direction is blocked by a wall, then just return the current location
294 if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
295 ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
296 ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
297 ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
303 // Start off by advancing one in direction for specified location
304 if (direction == 1) {
307 } else if (direction == 2) {
310 } else if (direction == 3) {
313 } else if (direction == 4) {
318 // If we violate the grid boundary,
319 // then return false.
322 locY == this.m_map.m_nrofblocks ||
323 locX == this.m_map.m_nrofblocks) {
328 // Determine next turning location.
330 if (direction == 1 || direction == 2) {
332 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
333 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
334 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
335 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
340 if (direction == 1) {
341 // Check for Top Warp
344 point[1] = this.m_map.m_nrofblocks - 1;
350 // Check for Bottom Warp
351 if (locY == this.m_map.m_nrofblocks - 1) {
362 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
363 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
364 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
365 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
370 if (direction == 3) {
371 // Check for Left Warp
373 point[0] = this.m_map.m_nrofblocks - 1;
380 // Check for Right Warp
381 if (locX == this.m_map.m_nrofblocks - 1) {
395 public void doMove() {
396 this.m_locX += this.m_dx;
397 this.m_locY += this.m_dy;
400 //System.printString("Pacmen " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");