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 // find the shortest possible way to the chosen target
\r
31 private void setNextDirection() {
\r
32 // current position of the ghost
\r
33 Node start = this.m_map.m_mapNodes[this.m_locY * this.m_map.m_nrofblocks + this.m_locX];
\r
34 boolean set = false;
\r
35 Vector cuts = new Vector();
\r
39 int tmpdirection = 0;
\r
40 boolean first = true;
\r
42 int parents[] = new int[this.m_map.m_nrofblocks * this.m_map.m_nrofblocks + 1];
\r
43 for(int i = 0; i < parents.length; i++) {
\r
46 if(!BFS(start, parents, cuts)) {
\r
47 this.m_target = tmptarget;
\r
50 this.m_map.m_ghostdirections[this.m_index] = this.m_direction = tmpdirection;
\r
52 //System.printString("Use first choice: (" + this.m_dx + ", " + this.m_dy + ")\n");
\r
54 // Reversely go over the parents array to find the next node to reach
\r
55 boolean found = false;
\r
56 int index = this.m_map.m_pacMenY[this.m_target] * this.m_map.m_nrofblocks + this.m_map.m_pacMenX[this.m_target];
\r
57 //System.printString("Target: " + this.m_target + "\n");
\r
59 int parent = parents[index];
\r
60 if(parent == start.getIndex()) {
\r
67 // set the chase direction
\r
68 int nx = this.m_map.m_mapNodes[index].getXLoc();
\r
69 int ny = this.m_map.m_mapNodes[index].getYLoc();
\r
70 this.m_dx = nx - this.m_locX;
\r
71 this.m_dy = ny - this.m_locY;
\r
74 this.m_direction = 4;
\r
75 } else if(this.m_dx < 0) {
\r
77 this.m_direction = 3;
\r
78 } else if(this.m_dy > 0) {
\r
80 this.m_direction = 2;
\r
81 } else if(this.m_dy < 0) {
\r
83 this.m_direction = 1;
\r
86 this.m_direction = 0;
\r
89 tmptarget = this.m_target;
\r
92 tmpdirection = this.m_direction;
\r
94 //System.printString("First choice: (" + tmpdx + ", " + tmpdy + ")\n");
\r
97 // check if this choice follows some other ghosts' path
\r
98 if(!isFollowing()) {
\r
99 this.m_map.m_ghostdirections[this.m_index] = this.m_direction;
\r
102 cuts.addElement(new Integer(index));
\r
103 /*for( int h = 0; h < cuts.size(); h++) {
\r
104 System.printString(cuts.elementAt(h) + ", ");
\r
106 System.printString("\n");*/
\r
112 // This methos do BFS from start node to end node
\r
113 // If there is a path from start to end, return true; otherwise, return false
\r
114 // Array parents records parent for a node in the BFS search,
\r
115 // the last item of parents records the least steps to reach end node from start node
\r
116 // Vector cuts specifies which nodes can not be the first one to access in this BFS
\r
118 private boolean BFS(Node start, int[] parents, Vector cuts) {
\r
119 //System.printString("aaa\n");
\r
122 private boolean BFS(Node start, Node end, int[] parents, Vector cuts) {
\r
125 Vector toaccess = new Vector();
\r
126 toaccess.addElement(start);
\r
127 while(toaccess.size() > 0) {
\r
128 //System.printString("bbb\n");
\r
129 // pull out the first one to access
\r
130 Node access = (Node)toaccess.elementAt(0);
\r
131 toaccess.removeElementAt(0);
\r
133 for(int i = 0; i < this.m_map.m_pacMenX.length; i++) {
\r
134 if((access.getXLoc() == this.m_map.m_pacMenX[i]) && (access.getYLoc() == this.m_map.m_pacMenY[i])) {
\r
137 parents[parents.length - 1] = steps;
\r
141 if(access.getIndex() == end.getIndex()) {
\r
142 // hit the end node
\r
143 parents[parents.length - 1] = steps;
\r
148 Vector neighbours = access.getNeighbours();
\r
149 for(int i = 0; i < neighbours.size(); i++) {
\r
150 Node neighbour = (Node)neighbours.elementAt(i);
\r
151 if(parents[neighbour.getIndex()] == -1) {
\r
153 boolean ignore = false;
\r
154 if(access.getIndex() == start.getIndex()) {
\r
155 // start node, check if the neighbour node is in cuts
\r
157 while((!ignore) && (j < cuts.size())) {
\r
158 int tmp = ((Integer)cuts.elementAt(j)).intValue();
\r
159 if(tmp == neighbour.getIndex()) {
\r
166 parents[neighbour.getIndex()] = access.getIndex();
\r
167 toaccess.addElement(neighbour);
\r
173 //System.printString("ccc\n");
\r
174 parents[parents.length - 1] = -1;
\r
176 parents[parents.length - 1] = -1;
\r
181 // This method returns true if this ghost is traveling to the same
\r
182 // destination with the same direction as another ghost.
\r
183 private boolean isFollowing () {
\r
184 boolean bFollowing = false;
\r
187 // If the ghost is in the same location as another ghost
\r
188 // and moving in the same direction, then they are on
\r
189 // top of each other and should not follow.
\r
190 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
\r
192 if (this.m_index != i) {
\r
193 if (this.m_map.m_ghostsX[i] == this.m_locX &&
\r
194 this.m_map.m_ghostsY[i] == this.m_locY &&
\r
195 this.m_map.m_ghostdirections[i] == this.m_direction) {
\r
201 // This will allow ghosts to often
\r
202 // clump together for easier eating
\r
203 dRandom = this.m_map.m_r.nextDouble();
\r
204 if (dRandom < .90) {
\r
205 //if (m_bInsaneAI && dRandom < .25)
\r
211 // If ghost is moving to the same location and using the
\r
212 // same direction, then it is following another ghost.
\r
213 for (int i = 0; i < this.m_map.m_ghostsX.length; i++) {
\r
215 if (this.m_index != i) {
\r
216 if (this.m_map.m_targets[i] == this.m_target &&
\r
217 this.m_map.m_ghostdirections[i] == this.m_direction) {
\r
226 // This method will take the specified location and direction and determine
\r
227 // for the given location if the thing moved in that direction, what the
\r
228 // next possible turning location would be.
\r
229 private boolean getDestination (int direction, int locX, int locY, int[] point) {
\r
230 // If the request direction is blocked by a wall, then just return the current location
\r
231 if (((direction == 1) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0)) || // up
\r
232 ((direction == 3) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) || // left
\r
233 ((direction == 2) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) || // down
\r
234 ((direction == 4) && ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0))) { // right
\r
240 // Start off by advancing one in direction for specified location
\r
241 if (direction == 1) {
\r
244 } else if (direction == 2) {
\r
247 } else if (direction == 3) {
\r
250 } else if (direction == 4) {
\r
255 // If we violate the grid boundary,
\r
256 // then return false.
\r
259 locY == this.m_map.m_nrofblocks ||
\r
260 locX == this.m_map.m_nrofblocks) {
\r
264 boolean set = false;
\r
265 // Determine next turning location.
\r
267 if (direction == 1 || direction == 2) {
\r
269 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) == 0) || // right
\r
270 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) == 0) || // left
\r
271 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) != 0) || // up
\r
272 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) != 0)) { // down
\r
277 if (direction == 1) {
\r
278 // Check for Top Warp
\r
281 point[1] = this.m_map.m_nrofblocks - 1;
\r
287 // Check for Bottom Warp
\r
288 if (locY == this.m_map.m_nrofblocks - 1) {
\r
299 if (((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 2) == 0) || // up
\r
300 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 8) == 0) || // down
\r
301 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 4) != 0) || // right
\r
302 ((int)(this.m_map.m_map[locX + locY * this.m_map.m_nrofblocks] & 1) != 0)) { // left
\r
307 if (direction == 3) {
\r
308 // Check for Left Warp
\r
310 point[0] = this.m_map.m_nrofblocks - 1;
\r
317 // Check for Right Warp
\r
318 if (locX == this.m_map.m_nrofblocks - 1) {
\r
332 public void doMove() {
\r
333 this.m_locX += this.m_dx;
\r
334 this.m_locY += this.m_dy;
\r
337 //System.printString("Ghost " + this.m_index + ": (" + this.m_locX + ", " + this.m_locY + ")\n");
\r