1 /****************************************************************************
4 Copyright (c) 1997-2001 Jerome Jacovella-St-Louis
7 astar.ec - A* Path Finding Algorithm
8 ****************************************************************************/
11 #define TILE(a,b,d) ((b)*d.x+(a))
12 #define TILENUM(p,d) TILE((p).x,(p).y,d)
17 ASNode *child[8]; // a node may have up to 8+(NULL) children
18 ASNode *nextNode; // for filing purposes
36 void AStarTerminate(AStar * aStar)
40 if(aStar->stack) delete aStar->stack;
41 if(aStar->openMap) delete aStar->openMap;
42 if(aStar->closedMap) delete aStar->closedMap;
47 AStar * AStarInitialize(int width, int height, int stackSize)
49 AStar * aStar = new0 AStar[1];
52 aStar->stackSize = stackSize;
53 aStar->stack = new0 void *[stackSize];
54 aStar->stackIndex = 0;
55 aStar->openMap = new0 ASNode *[width*height];
56 aStar->closedMap=new0 ASNode *[width*height];
61 static ASNode * AStarRBestNode(AStar * aStar)
65 if(!aStar->open->nextNode)
68 tmp=aStar->open->nextNode;
69 aStar->open->nextNode=tmp->nextNode;
71 tmp->nextNode=aStar->closed->nextNode;
72 aStar->closed->nextNode=tmp;
73 aStar->openMap[tmp->nodeNum]=null;
74 aStar->closedMap[tmp->nodeNum]=tmp;
78 static void AStarPropagateDown(AStar * aStar, ASNode *old)
81 ASNode *child, *father;
91 child->f=child->g+child->h;
93 if(aStar->stackIndex>=aStar->stackSize)
95 aStar->stack[aStar->stackIndex++] = child;
99 while(aStar->stackIndex > 0)
101 father=aStar->stack[--aStar->stackIndex];
104 child=father->child[c];
106 if(father->g+1<child->g)
108 child->g=father->g+1;
109 child->f=child->g+child->h;
110 child->parent=father;
111 if(aStar->stackIndex>=aStar->stackSize)
113 aStar->stack[aStar->stackIndex++] = child;
119 static void AStarInsert(AStar * aStar, ASNode *successor)
124 aStar->openMap[successor->nodeNum]=successor;
125 if(!aStar->open->nextNode)
127 aStar->open->nextNode=successor;
133 tmp2=aStar->open->nextNode;
135 while(tmp2&&(tmp2->f<f))
140 successor->nextNode=tmp2;
141 tmp1->nextNode=successor;
144 static void AStarGenerateSucc(AStar * aStar, ASNode *bestNode, int positionX, int positionY, int tileNumS,Point destination)
147 ASNode *old,*successor;
151 if((old=aStar->openMap[tileNumS]))
154 if(!bestNode->child[c]) break;
155 bestNode->child[c]=old;
159 old->parent=bestNode;
164 else if((old=aStar->closedMap[tileNumS]))
167 if(!bestNode->child[c]) break;
168 bestNode->child[c]=old;
172 old->parent=bestNode;
175 AStarPropagateDown(aStar, old);
180 successor = new0 ASNode[1];
181 successor->parent=bestNode;
183 successor->h=(positionX-destination.x)*(positionX-destination.x)+
184 (positionY-destination.y)*(positionY-destination.y);
185 successor->f=g+successor->h;
186 successor->position.x=positionX;
187 successor->position.y=positionY;
188 successor->nodeNum=tileNumS;
189 AStarInsert(aStar, successor);
191 if(!bestNode->child[c]) break;
192 bestNode->child[c]=successor;
196 static void AStarGenerateSuccessors(AStar * aStar, ASNode *bestNode, byte *map, Point dim, Point destination)
200 for(y = bestNode->position.y - 1; y < bestNode->position.y + 2; y++)
201 for(x = bestNode->position.x - 1; x < bestNode->position.x + 2; x++)
202 if((x >= 0) && (y >= 0) && (x < dim.x) && (y < dim.y))
203 if(x < bestNode->position.x || y < bestNode->position.y || x >= bestNode->position.x + 1 || y >= bestNode->position.y + 1)
205 if(map[TILE(x,y,dim)])
206 AStarGenerateSucc(aStar, bestNode,x,y,TILE(x,y,dim),destination);
210 ASNode * AStarFindPath(AStar * aStar, byte * map,Point dim,Point start,Point destination, int iterations)
212 ASNode *node, *bestNode;
216 tileNumDest = TILENUM(destination,dim);
218 aStar->open = new0 ASNode[1];
219 aStar->closed = new0 ASNode[1];
221 node = new0 ASNode[1];
223 node->h=(start.x-destination.x)*(start.x-destination.x)+
224 (start.y-destination.y)*(start.y-destination.y);
225 node->f=node->g+node->h;
226 node->nodeNum = TILENUM(start,dim);
227 node->position = start;
229 aStar->open->nextNode=node;
230 aStar->openMap[node->nodeNum]=node;
232 if(!map[TILENUM(destination,dim)])
234 for(c=0;c<iterations;c++)
236 bestNode=AStarRBestNode(aStar);
237 if(!bestNode) return null;
238 if(bestNode->nodeNum==tileNumDest)
240 AStarGenerateSuccessors(aStar, bestNode,map,dim,destination);
245 void AStarFreeNodes(AStar * aStar)
251 aStar->openMap[node->nodeNum]=null;
259 aStar->closedMap[node->nodeNum]=null;