1 public class Pacman {
\r
4 public boolean m_death;
\r
6 public int m_direction; // 0:still, 1:up, 2:down, 3:left, 4:right
\r
13 public Pacman(int x, int y, Map map) {
\r
16 this.m_dx = this.m_dy = 0;
\r
17 this.m_death = false;
\r
19 this.m_tx = this.m_ty = -1;
\r
20 this.m_direction = 0;
\r
24 public void setTarget(int x, int y) {
\r
29 public void tryMove() {
\r
32 // find the shortest possible way to the chosen target
\r
36 private void setNextDirection() {
\r
37 // current position of the ghost
\r
38 Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];
\r
40 // get target's position
\r
41 int targetx = this.m_tx;
\r
42 int targety = this.m_ty;
\r
43 int[] nextLocation = new int[2];
\r
44 nextLocation[0] = nextLocation[1] = -1;
\r
46 // target's position
\r
47 Node end = this.m_map.m_mapNodes[targety * this.m_map.m_nrofblocks + targetx];
\r
49 // breadth-first traverse the graph view of the maze
\r
50 // check the shortest path for the start node to the end node
\r
51 boolean set = false;
\r
52 Vector cuts = new Vector();
\r
55 int tmpdirection = 0;
\r
56 boolean first = true;
\r
58 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
\r
59 for(int i = 0; i < parents.length; i++) {
\r
62 if(!BFS(start, end, parents, cuts)) {
\r
65 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
\r
67 //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
\r
69 // Reversely go over the parents array to find the next node to reach
\r
70 boolean found = false;
\r
71 int index = end.getIndex();
\r
73 int parent = parents[index];
\r
74 if(parent == start.getIndex()) {
\r
81 // set the chase direction
\r
82 int nx = this.m_map.m_mapNodes[index].getXLoc();
\r
83 int ny = this.m_map.m_mapNodes[index].getYLoc();
\r
84 this.m_dx = nx - this.m_locX;
\r
85 this.m_dy = ny - this.m_locY;
\r
88 this.m_direction = 4;
\r
89 } else if(this.m_dx < 0) {
\r
91 this.m_direction = 3;
\r
92 } else if(this.m_dy > 0) {
\r
94 this.m_direction = 2;
\r
95 } else if(this.m_dy < 0) {
\r
97 this.m_direction = 1;
\r
100 this.m_direction = 0;
\r
105 tmpdirection = this.m_direction;
\r
107 //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
\r
110 // check if this choice follows some other ghosts' path
\r
112 this.m_map.m_directions[this.m_index] = this.m_direction;
\r
115 cuts.addElement(new Integer(index));
\r
116 /*for( int h = 0; h < cuts.size(); h++) {
\r
117 System.printString(cuts.elementAt(h) + ", ");
\r
119 System.printString("\n");*/
\r
125 // This methos do BFS from start node to end node
\r
126 // If there is a path from start to end, return true; otherwise, return false
\r
127 // Array parents records parent for a node in the BFS search,
\r
128 // the last item of parents records the least steps to reach end node from start node
\r
129 // Vector cuts specifies which nodes can not be the first one to access in this BFS
\r
130 private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {
\r
132 Vector toaccess = new Vector();
\r
133 toaccess.addElement(start);
\r
134 while(toaccess.size() > 0) {
\r
135 // pull out the first one to access
\r
136 Node access = (Node)toaccess.elementAt(0);
\r
137 toaccess.removeElementAt(0);
\r
138 if(access.getIndex() == end.getIndex()) {
\r
139 // hit the end node
\r
140 parents[parents.length - 1] = steps;
\r
144 Vector neighbours = access.getNeighbours();
\r
145 for(int i = 0; i < neighbours.size(); i++) {
\r
146 Node neighbour = (Node)neighbours.elementAt(i);
\r
147 if(parents[neighbour.getIndex()] == -1) {
\r
149 boolean ignore = false;
\r
150 if(access.getIndex() == start.getIndex()) {
\r
151 // start node, check if the neighbour node is in cuts
\r
153 while((!ignore) && (j < cuts.size())) {
\r
154 int tmp = ((Integer)cuts.elementAt(j)).intValue();
\r
155 if(tmp == neighbour.getIndex()) {
\r
162 parents[neighbour.getIndex()] = access.getIndex();
\r
163 toaccess.addElement(neighbour);
\r
168 parents[parents.length - 1] = -1;
\r
172 // This method returns true if this pacmen can flee in this direction.
\r
173 private boolean canFlee () {
\r
175 int locX = this.m_locX;
\r
176 int locY = this.m_locY;
\r
177 int[] point = new int[2];
\r
178 point[0] = point[1] = -1;
\r
180 // Start off by advancing one in direction for specified location
\r
181 if (this.m_direction == 1) {
\r
184 } else if (this.m_direction == 2) {
\r
187 } else if (this.m_direction == 3) {
\r
190 } else if (this.m_direction == 4) {
\r
196 boolean set = false;
\r
197 // Determine next turning location.
\r
199 if (this.m_direction == 1 || this.m_direction == 2) {
\r
201 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
\r
202 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
\r
203 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
\r
204 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
\r
209 if (this.m_direction == 1) {
\r
210 // Check for Top Warp
\r
213 point[1] = this.m_map.m_nrofblocks - 1;
\r
220 // Check for Bottom Warp
\r
221 if (locY == this.m_map.m_nrofblocks - 1) {
\r
233 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
\r
234 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
\r
235 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
\r
236 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
\r
241 if (this.m_direction == 3) {
\r
242 // Check for Left Warp
\r
244 point[0] = this.m_map.m_nrofblocks - 1;
\r
252 // Check for Right Warp
\r
253 if (locX == this.m_map.m_nrofblocks - 1) {
\r
266 // check the least steps for the ghosts to reach point location
\r
267 int chasesteps = -1;
\r
268 Node end = this.m_map.m_mapNodes[point[1] * this.m_map.m_nrofblocks + point[0]];
\r
269 for(int i = 0; i < this.m_map.m_ghostsX.length; i++) {
\r
270 Node start = this.m_map.m_mapNodes[this.m_map.m_ghostsY[i] * this.m_map.m_nrofblocks + this.m_map.m_ghostsX[i]];
\r
271 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
\r
272 for(int j = 0; j < parents.length; j++) {
\r
275 if(BFS(start, end, parents, new Vector())) {
\r
276 if((chasesteps == -1) ||
\r
277 (chasesteps > parents[parents.length - 1])) {
\r
278 chasesteps = parents[parents.length - 1];
\r
283 return ((chasesteps == -1) || (steps < chasesteps));
\r
286 // This method will take the specified location and direction and determine
\r
287 // for the given location if the thing moved in that direction, what the
\r
288 // next possible turning location would be.
\r
289 private boolean getDestination (int direction, int locX, int locY, int[] point) {
\r
290 // If the request direction is blocked by a wall, then just return the current location
\r
291 if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
\r
292 ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
\r
293 ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
\r
294 ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
\r
300 // Start off by advancing one in direction for specified location
\r
301 if (direction == 1) {
\r
304 } else if (direction == 2) {
\r
307 } else if (direction == 3) {
\r
310 } else if (direction == 4) {
\r
315 // If we violate the grid boundary,
\r
316 // then return false.
\r
319 locY == this.m_map.m_nrofblocks ||
\r
320 locX == this.m_map.m_nrofblocks) {
\r
324 boolean set = false;
\r
325 // Determine next turning location.
\r
327 if (direction == 1 || direction == 2) {
\r
329 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
\r
330 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
\r
331 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
\r
332 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
\r
337 if (direction == 1) {
\r
338 // Check for Top Warp
\r
341 point[1] = this.m_map.m_nrofblocks - 1;
\r
347 // Check for Bottom Warp
\r
348 if (locY == this.m_map.m_nrofblocks - 1) {
\r
359 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
\r
360 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
\r
361 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
\r
362 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
\r
367 if (direction == 3) {
\r
368 // Check for Left Warp
\r
370 point[0] = this.m_map.m_nrofblocks - 1;
\r
377 // Check for Right Warp
\r
378 if (locX == this.m_map.m_nrofblocks - 1) {
\r
392 public void doMove() {
\r
393 this.m_locX += this.m_dx;
\r
394 this.m_locY += this.m_dy;
\r
397 //System.printString("Pacmen " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");
\r