![]() |
Unuk 1.0
|
00001 #include <stdlib.h> 00002 #include "AStar.h" 00003 #include "Node.h" 00004 00005 AStar::AStar(void) { 00006 m_open = NULL; 00007 m_stack = NULL; 00008 m_best = NULL; 00009 00010 udCost = NULL; 00011 udValid = NULL; 00012 udNotifyChild = NULL; 00013 udNotifyList = NULL; 00014 } 00015 00016 AStar::~AStar(void) { 00017 ClearNodes(); 00018 } 00019 00020 bool AStar::GeneratePath(int startx, int starty, int destx, int desty) { 00021 // Grab the next node from the f position. 00022 InitStep(startx, starty, destx, desty); 00023 00024 int retval = 0; 00025 while(retval == 0) { 00026 // Go find the next node. 00027 retval = Step(); 00028 } 00029 00030 if(retval == 0 || !m_best) { 00031 // Set m_best to NULL so we can go and check for the next best node. 00032 m_best = NULL; 00033 return false; 00034 } 00035 return true; 00036 } 00037 00038 int AStar::Step(void) { 00039 // If we don't get the most efficent route, then go back 00040 // and check some more nodes plox! 00041 if(!(m_best == GetBest())) { return -1; } 00042 // Ok, we found the best route. 00043 if(m_best->id == m_ID) { return 1; } 00044 00045 // Please set the best route as a child node. 00046 CreateChildren(m_best); 00047 00048 return 0; 00049 } 00050 00051 int AStar::InitStep(int startx, int starty, int destx, int desty) { 00052 // Prepare for the next pass by clearing our previous nodes. 00053 ClearNodes(); 00054 00055 // Initialize our variables. 00056 m_startx = startx; 00057 m_starty = starty; 00058 m_destx = destx; 00059 m_desty = desty; 00060 m_ID = Coord2Id(destx, desty); 00061 00062 // Set the node for our start location. 00063 Node *temp = new Node(startx, starty); 00064 temp->g = 0; 00065 temp->h = abs(destx - startx) + abs(desty - starty); 00066 temp->f = temp->g + temp->h; 00067 temp->id = Coord2Id(startx, starty); 00068 m_open = temp; 00069 00070 return 0; 00071 } 00072 00073 void AStar::AddToOpen(Node *addnode) { 00074 Node *node = m_open; 00075 Node *prev = NULL; 00076 00077 if(!m_open) { 00078 // Add a a new node to the open list. 00079 m_open = addnode; 00080 00081 m_open->next = NULL; 00082 00083 // Start a new open list with our new node. 00084 //Func(udNotifyList, NULL, addnode, NL_STARTOPEN, NCData); 00085 00086 return; 00087 } 00088 00089 while(node) { 00090 // If our addnode's f is greater than the currently open node 00091 // then add the open node to the to previous to make room for 00092 // add node to be on the open list. 00093 if(addnode->f > node->f) { 00094 prev = node; 00095 // Now we have our new node go to next. 00096 node = node->next; 00097 } else { 00098 // go to the next node, and set it on our open list to check it's 00099 // f value. 00100 if(prev) { 00101 prev->next = addnode; 00102 addnode->next = node; 00103 Func(udNotifyList, prev, addnode, NL_ADDOPEN, NCData); 00104 } else { 00105 // We will only ever run through this once per instance. We have no nodes currently 00106 // so we set an open list with this node. 00107 Node *temp = m_open; 00108 00109 m_open = addnode; 00110 m_open->next = temp; 00111 //Func(udNotifyList, temp, addnode, NL_STARTOPEN, NCData); 00112 } 00113 return; 00114 } 00115 } 00116 // Get the next node and add it to the open list. 00117 prev->next = addnode; 00118 //Func(udNotifyList, prev, addnode, NL_ADDOPEN, NCData); 00119 } 00120 00121 void AStar::ClearNodes(void) { 00122 Node *temp = NULL; 00123 Node *temp2 = NULL; 00124 00125 if(m_open) { 00126 while(m_open) { 00127 temp = m_open->next; 00128 delete m_open; 00129 m_open = temp; 00130 } 00131 } 00132 if(m_closed) { 00133 while(m_closed) { 00134 temp = m_closed->next; 00135 delete m_closed; 00136 m_closed = temp; 00137 } 00138 } 00139 } 00140 00141 void AStar::CreateChildren(Node *node) { 00142 Node temp; 00143 int x = node->x; 00144 int y = node->y; 00145 00146 // Loop through the grid and add the children to the list. 00147 for(int i = -1; i < 2; i++) { 00148 for(int j = -1; j < 2; j++) { 00149 temp.x = x+i; 00150 temp.y = y+j; 00151 if((i == 0) && (j == 0) || !Func(udValid, node, &temp, NC_INITIALADD, CBData)) continue; 00152 00153 LinkChild(node, &temp); 00154 } 00155 } 00156 } 00157 00158 void AStar::LinkChild(Node *node, Node *temp) { 00159 // Initialize variables for our temp node. 00160 int x = temp->x; 00161 int y = temp->y; 00162 int g = temp->g + Func(udCost, node, temp, 0, CBData); 00163 // Grabbing a unique ID before adding the node to the open list. 00164 int id = Coord2Id(x, y); 00165 00166 Node *check = NULL; 00167 00168 if(check = CheckList(m_open, id)) { 00169 node->children[node->numChildren++] = check; 00170 00171 // We have found an awesome route, update the node and variables. 00172 if(g < check->g) { 00173 check->parent = node; 00174 check->g = g; 00175 check->f = g+check->h; 00176 //Func(udNotifyChild, node, check, NC_OPENADD_UP, NCData); 00177 } else { 00178 //Func(udNotifyChild, node, check, 2, NCData); 00179 } 00180 } else if(check = CheckList(m_closed, id)) { 00181 node->children[node->numChildren++] = check; 00182 00183 if(g < check->g) { 00184 check->parent = node; 00185 check->g = g; 00186 check->f = g+check->h; 00187 //Func(udNotifyChild, node, check, 3, NCData); 00188 00189 // Update the parents. 00190 UpdateParents(check); 00191 } else { 00192 //Func(udNotifyChild, node, check, 4, NCData); 00193 } 00194 } else { 00195 Node *newnode = new Node(x, y); 00196 newnode->parent = node; 00197 newnode->g = g; 00198 newnode->h = abs(x - m_destx) + abs(y - m_desty); 00199 newnode->f = newnode->g + newnode->h; 00200 newnode->id = Coord2Id(x, y); 00201 00202 AddToOpen(newnode); 00203 node->children[node->numChildren++] = newnode; 00204 00205 //Func(udNotifyChild, node, newnode, 5, NCData); 00206 } 00207 } 00208 00209 00210 void AStar::UpdateParent(Node *node) { 00211 int g = node->g; 00212 int c = node->numChildren; 00213 00214 Node *child = NULL; 00215 for(int i = 0; i < c; i++) { 00216 child = node->children[i]; 00217 if(g + 1 < child->g) { 00218 child->g = g + 1; 00219 child->f = child->g + child->h; 00220 child->parent = node; 00221 Push(child); 00222 } 00223 } 00224 Node *parent; 00225 00226 while(m_stack) { 00227 parent = Pop(); 00228 c = parent->numC22hildren; 00229 for(int i = 0; i < c; i++) { 00230 child = parent->children[i]; 00231 00232 if(parent->g + 1 < child->g) { 00233 child->g = parent->g + Func(udCost, parent, child, NC_INITIALADD, CBData); 00234 child->f = child->g + child->h; 00235 child->parent = parent; 00236 Push(child); 00237 } 00238 } 00239 } 00240 } 00241 00242 void AStar::Push(Node *node) { 00243 if(!m_stack) { 00244 m_stack = new Stack; 00245 m_stack->data = node; 00246 m_stack->next = NULL; 00247 } else { 00248 Stack *temp = new Stack; 00249 temp->data = node; 00250 temp->next = m_stack; 00251 m_stack = temp; 00252 } 00253 } 00254 00255 Node AStar::*Pop(void) { 00256 Node *data = m_stack->data; 00257 Stack *temp = m_stack; 00258 00259 m_stack = temp->next; 00260 delete temp; 00261 00262 return data; 00263 } 00264 00265 Node AStar::*CheckList(Node *node, int id) { 00266 while(node) { 00267 if(node->id == id) return node; 00268 00269 node = node->next; 00270 } 00271 return NULL; 00272 } 00273 00274 // Get the best node in the open list to enable us to find 00275 // the best route to take. 00276 Node AStar::*GetBest(void) { 00277 if(!m_open) { return NULL; } 00278 00279 Node *temp = m_open; 00280 Node *temp2 = m_closed; 00281 m_open = temp->next; 00282 00283 //Func(udNotifyList, NULL, temp, NL_DELETEOPEN, NCData); 00284 m_closed = temp; 00285 m_closed->next = temp2; 00286 //Func(udNotifyList, NULL, m_closed, NL_ADDCLOSED, NCData); 00287 00288 return temp; 00289 }