00001 #ifndef _pathfinder_astar_tile4dir_cached_
00002 #define _pathfinder_astar_tile4dir_cached_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00032 #include "pathfinder.h"
00033
00034 #include <functional>
00035 #include <algorithm>
00036 #include <map>
00037
00038 namespace Pathfinder
00039 {
00040
00041
00052 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE=double>
00053 class AStarTile4DirCached
00054 {
00055 public:
00056 AStarTile4DirCached();
00057 ~AStarTile4DirCached();
00058
00072 const PathResult FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, DESTCOST &destinationcost);
00087 const PathResult FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, MOVEBLOCKED &moveblocked, DESTCOST &destinationcost);
00088
00096 void SetMapWidth(const long width);
00097
00101 void ClearCache();
00102
00110 void ClearCachePosition(const std::pair<long,long> &pos);
00111
00112 private:
00113
00114 AStarTile4DirCached(const AStarTile4DirCached &rhs);
00115 AStarTile4DirCached &operator=(const AStarTile4DirCached &rhs);
00116
00117 struct astarnode
00118 {
00119 std::pair<long,long> m_node;
00120 astarnode *m_parent;
00121 COSTTYPE m_f;
00122 COSTTYPE m_g;
00123 COSTTYPE m_h;
00124 };
00125
00126 struct astarnodecompare:public std::binary_function<astarnode *, astarnode *, bool>
00127 {
00128 inline bool operator()(const astarnode *left, const astarnode *right)
00129 {
00130 return right->m_f<left->m_f;
00131 }
00132 };
00133
00134 class astarallocator:public std::allocator<astarnode>
00135 {
00136 public:
00137 astarallocator()
00138 {
00139 m_mempos=0;
00140 m_mem.resize(1000,NULL);
00141 }
00142
00143 ~astarallocator()
00144 {
00145 for(std::vector<astarnode *>::size_type i=0; i<m_mempos; i++)
00146 {
00147 delete m_mem[i];
00148 }
00149 }
00150
00151 pointer allocate(size_type count)
00152 {
00153 return m_mempos>0 ? m_mem[--m_mempos] : new astarnode;
00154 }
00155
00156 void deallocate(pointer ptr, size_type count)
00157 {
00158 if(m_mempos==m_mem.size())
00159 {
00160 m_mem.resize(m_mem.size()+1000,NULL);
00161 }
00162 m_mem[m_mempos++]=ptr;
00163 }
00164
00165 private:
00166 std::vector<astarnode *> m_mem;
00167 typename std::vector<astarnode *>::size_type m_mempos;
00168 };
00169
00170 struct listelement
00171 {
00172 listelement():m_node(NULL),m_onopen(false),m_onclosed(false) {}
00173 astarnode *m_node;
00174 bool m_onopen;
00175 bool m_onclosed;
00176 };
00177
00178 void ClearOpenList();
00179 void ClearClosedList();
00180
00181 astarallocator m_astarnodeallocator;
00182
00183 std::vector<astarnode *> m_openlist;
00184 std::vector<astarnode *> m_closedlist;
00185 std::vector<listelement> m_helperlist;
00186 long m_helperliststartindex;
00187
00188 long m_mapwidth;
00189
00190 struct cacheelement
00191 {
00192 cacheelement():m_hascache(false) {}
00193 bool m_hascache;
00194 std::vector<std::pair<std::pair<long,long> ,COSTTYPE> > m_neighbors;
00195 };
00196 std::vector<cacheelement> m_cache;
00197 long m_cachestartindex;
00198
00199 inline listelement &hl(const long index)
00200 {
00201 if(m_helperlist.size()==0)
00202 {
00203 m_helperlist.push_back(listelement());
00204 m_helperliststartindex=index;
00205 }
00206 else if(index<m_helperliststartindex)
00207 {
00208 m_helperlist.insert(m_helperlist.begin(),m_helperliststartindex-index,listelement());
00209 m_helperliststartindex=index;
00210 }
00211 else if(index-m_helperliststartindex>=m_helperlist.size())
00212 {
00213 m_helperlist.insert(m_helperlist.end(),((index-m_helperliststartindex)+1)-m_helperlist.size(),listelement());
00214 }
00215
00216 return m_helperlist[index-m_helperliststartindex];
00217 }
00218
00219 };
00220
00221 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00222 AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::AStarTile4DirCached():m_mapwidth(0),m_cachestartindex(0),m_helperliststartindex(0)
00223 {
00224
00225 }
00226
00227 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00228 AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::~AStarTile4DirCached()
00229 {
00230 ClearOpenList();
00231 ClearClosedList();
00232 }
00233
00234 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00235 void AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearCache()
00236 {
00237 m_cache.clear();
00238 m_cachestartindex=0;
00239 }
00240
00241 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00242 void AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearCachePosition(const std::pair<long,long> &pos)
00243 {
00244 long index=(pos.second*m_mapwidth)+pos.first;
00245 if(index>=m_cachestartindex && index-m_cachestartindex<m_cache.size())
00246 {
00247 m_cache[index-m_cachestartindex].m_hascache=false;
00248 m_cache[index-m_cachestartindex].m_neighbors.clear();
00249 }
00250 }
00251
00252 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00253 void AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearClosedList()
00254 {
00255 for(std::vector<astarnode *>::iterator i=m_closedlist.begin(); i!=m_closedlist.end(); i++)
00256 {
00257 m_astarnodeallocator.deallocate((*i),1);
00258 }
00259 m_closedlist.clear();
00260 }
00261
00262 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00263 void AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::ClearOpenList()
00264 {
00265 for(std::vector<astarnode *>::iterator i=m_openlist.begin(); i!=m_openlist.end(); i++)
00266 {
00267 m_astarnodeallocator.deallocate((*i),1);
00268 }
00269 m_openlist.clear();
00270 }
00271
00272 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00273 const PathResult AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, DESTCOST &destinationcost)
00274 {
00275
00276 ClearOpenList();
00277 ClearClosedList();
00278 m_helperlist.clear();
00279 m_helperliststartindex=0;
00280
00281 long xx;
00282 long yy;
00283
00284 astarnode *astaropen;
00285
00286
00287 astarnode *currentnode;
00288 astarnode *newnode=m_astarnodeallocator.allocate(1);
00289 newnode->m_node=start;
00290 newnode->m_parent=NULL;
00291 newnode->m_g=destinationcost(start,goal);
00292 newnode->m_h=0;
00293 newnode->m_f=newnode->m_g+newnode->m_h;
00294
00295
00296 m_openlist.push_back(newnode);
00297 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00298 hl((newnode->m_node.second*m_mapwidth)+newnode->m_node.first).m_node=newnode;
00299 m_helperlist[((newnode->m_node.second*m_mapwidth)+newnode->m_node.first)-m_helperliststartindex].m_onopen=true;
00300
00301 while(m_openlist.size()>0)
00302 {
00303 currentnode=m_openlist.front();
00304 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00305 m_openlist.pop_back();
00306 m_helperlist[((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first)-m_helperliststartindex].m_onopen=false;
00307
00308
00309 m_closedlist.push_back(currentnode);
00310 m_helperlist[((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first)-m_helperliststartindex].m_onclosed=true;
00311
00312 if(currentnode->m_node!=goal)
00313 {
00314 long currentnodeindex=((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first);
00315 if(currentnodeindex>=m_cachestartindex && currentnodeindex<m_cachestartindex+m_cache.size() && m_cache[currentnodeindex-m_cachestartindex].m_hascache)
00316 {
00317
00318 for(std::vector<std::pair<std::pair<long,long> ,COSTTYPE> >::iterator i=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.begin(); i!=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.end(); i++)
00319 {
00320 xx=(*i).first.first;
00321 yy=(*i).first.second;
00322 if(hl((yy*m_mapwidth)+xx).m_onclosed==false)
00323 {
00324
00325
00326 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00327
00328
00329 if(astaropen!=NULL)
00330 {
00331 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00332 {
00333 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00334 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00335 astaropen->m_parent=currentnode;
00336 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00337 }
00338 }
00339
00340 else
00341 {
00342 newnode=m_astarnodeallocator.allocate(1);
00343 newnode->m_node=std::pair<long,long>(xx,yy);
00344 newnode->m_parent=currentnode;
00345 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00346 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00347 newnode->m_f=newnode->m_g+newnode->m_h;
00348
00349 m_openlist.push_back(newnode);
00350 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00351 hl((yy*m_mapwidth)+xx).m_onopen=true;
00352 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00353 }
00354 }
00355 }
00356 }
00357
00358 else
00359 {
00360
00361 if(m_cache.size()==0)
00362 {
00363 m_cache.push_back(cacheelement());
00364 m_cachestartindex=currentnodeindex;
00365 }
00366 else if(currentnodeindex<m_cachestartindex)
00367 {
00368 m_cache.insert(m_cache.begin(),m_cachestartindex-currentnodeindex,cacheelement());
00369 m_cachestartindex=currentnodeindex;
00370 }
00371 else if(currentnodeindex-m_cachestartindex>=m_cache.size())
00372 {
00373 m_cache.insert(m_cache.end(),((currentnodeindex-m_cachestartindex)+1)-m_cache.size(),cacheelement());
00374 }
00375 m_cache[currentnodeindex-m_cachestartindex].m_hascache=true;
00376
00377 for(long i=1; i<8; i+=2)
00378 {
00379 xx=currentnode->m_node.first+(i%3)-1;
00380 yy=currentnode->m_node.second+(i/3)-1;
00381
00382
00383 if(hl((yy*m_mapwidth)+xx).m_onclosed==false)
00384 {
00385
00386
00387 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00388
00389
00390 if(astaropen!=NULL)
00391 {
00392 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00393 {
00394 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00395 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00396 astaropen->m_parent=currentnode;
00397 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00398 }
00399 }
00400
00401 else
00402 {
00403 newnode=m_astarnodeallocator.allocate(1);
00404 newnode->m_node=std::pair<long,long>(xx,yy);
00405 newnode->m_parent=currentnode;
00406 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00407 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00408 newnode->m_f=newnode->m_g+newnode->m_h;
00409
00410 m_openlist.push_back(newnode);
00411 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00412 hl((yy*m_mapwidth)+xx).m_onopen=true;
00413 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00414 }
00415
00416 m_cache[currentnodeindex-m_cachestartindex].m_neighbors.push_back(std::pair<std::pair<long,long> ,COSTTYPE>(std::pair<long,long>(xx,yy),movecost(currentnode->m_node,std::pair<long,long>(xx,yy))));
00417
00418 }
00419 }
00420 }
00421 }
00422 else
00423 {
00424 finalpath.clear();
00425 while(currentnode)
00426 {
00427 finalpath.push_back(currentnode->m_node);
00428 currentnode=currentnode->m_parent;
00429 }
00430 return PATH_FOUND;
00431 }
00432
00433 }
00434
00435 return PATH_NOTFOUND;
00436 }
00437
00438 template <class MOVECOST, class DESTCOST, class MOVEBLOCKED, class COSTTYPE>
00439 const PathResult AStarTile4DirCached<MOVECOST,DESTCOST,MOVEBLOCKED,COSTTYPE>::FindPath(const std::pair<long,long> &start, const std::pair<long,long> &goal, std::vector<std::pair<long,long> > &finalpath, MOVECOST &movecost, MOVEBLOCKED &moveblocked, DESTCOST &destinationcost)
00440 {
00441
00442 ClearOpenList();
00443 ClearClosedList();
00444 m_helperlist.clear();
00445 m_helperliststartindex=0;
00446
00447 long xx;
00448 long yy;
00449
00450 astarnode *astaropen;
00451
00452
00453 astarnode *currentnode;
00454 astarnode *newnode=m_astarnodeallocator.allocate(1);
00455 newnode->m_node=start;
00456 newnode->m_parent=NULL;
00457 newnode->m_g=destinationcost(start,goal);
00458 newnode->m_h=0;
00459 newnode->m_f=newnode->m_g+newnode->m_h;
00460
00461
00462 m_openlist.push_back(newnode);
00463 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00464 hl((newnode->m_node.second*m_mapwidth)+newnode->m_node.first).m_node=newnode;
00465 m_helperlist[((newnode->m_node.second*m_mapwidth)+newnode->m_node.first)-m_helperliststartindex].m_onopen=true;
00466
00467 while(m_openlist.size()>0)
00468 {
00469 currentnode=m_openlist.front();
00470 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00471 m_openlist.pop_back();
00472 m_helperlist[((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first)-m_helperliststartindex].m_onopen=false;
00473
00474
00475 m_closedlist.push_back(currentnode);
00476 m_helperlist[((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first)-m_helperliststartindex].m_onclosed=true;
00477
00478 if(currentnode->m_node!=goal)
00479 {
00480 long currentnodeindex=((currentnode->m_node.second*m_mapwidth)+currentnode->m_node.first);
00481 if(currentnodeindex>=m_cachestartindex && currentnodeindex<m_cachestartindex+m_cache.size() && m_cache[currentnodeindex-m_cachestartindex].m_hascache)
00482 {
00483
00484 for(std::vector<std::pair<std::pair<long,long> ,COSTTYPE> >::iterator i=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.begin(); i!=m_cache[currentnodeindex-m_cachestartindex].m_neighbors.end(); i++)
00485 {
00486 xx=(*i).first.first;
00487 yy=(*i).first.second;
00488 if(hl((yy*m_mapwidth)+xx).m_onclosed==false)
00489 {
00490
00491
00492 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00493
00494
00495 if(astaropen!=NULL)
00496 {
00497 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00498 {
00499 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00500 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00501 astaropen->m_parent=currentnode;
00502 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00503 }
00504 }
00505
00506 else
00507 {
00508 newnode=m_astarnodeallocator.allocate(1);
00509 newnode->m_node=std::pair<long,long>(xx,yy);
00510 newnode->m_parent=currentnode;
00511 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00512 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00513 newnode->m_f=newnode->m_g+newnode->m_h;
00514
00515 m_openlist.push_back(newnode);
00516 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00517 hl((yy*m_mapwidth)+xx).m_onopen=true;
00518 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00519 }
00520 }
00521 }
00522 }
00523
00524 else
00525 {
00526
00527 if(m_cache.size()==0)
00528 {
00529 m_cache.push_back(cacheelement());
00530 m_cachestartindex=currentnodeindex;
00531 }
00532 else if(currentnodeindex<m_cachestartindex)
00533 {
00534 m_cache.insert(m_cache.begin(),m_cachestartindex-currentnodeindex,cacheelement());
00535 m_cachestartindex=currentnodeindex;
00536 }
00537 else if(currentnodeindex-m_cachestartindex>=m_cache.size())
00538 {
00539 m_cache.insert(m_cache.end(),((currentnodeindex-m_cachestartindex)+1)-m_cache.size(),cacheelement());
00540 }
00541 m_cache[currentnodeindex-m_cachestartindex].m_hascache=true;
00542
00543 for(long i=1; i<8; i+=2)
00544 {
00545 xx=currentnode->m_node.first+(i%3)-1;
00546 yy=currentnode->m_node.second+(i/3)-1;
00547
00548
00549 if(moveblocked(currentnode->m_node,std::pair<long,long>(xx,yy))==false && hl((yy*m_mapwidth)+xx).m_onclosed==false)
00550 {
00551
00552
00553 astaropen=m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node;
00554
00555
00556 if(astaropen!=NULL)
00557 {
00558 if(currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy))<astaropen->m_g)
00559 {
00560 astaropen->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00561 astaropen->m_f=astaropen->m_g+astaropen->m_h;
00562 astaropen->m_parent=currentnode;
00563 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00564 }
00565 }
00566
00567 else
00568 {
00569 newnode=m_astarnodeallocator.allocate(1);
00570 newnode->m_node=std::pair<long,long>(xx,yy);
00571 newnode->m_parent=currentnode;
00572 newnode->m_g=currentnode->m_g+movecost(currentnode->m_node,std::pair<long,long>(xx,yy));
00573 newnode->m_h=destinationcost(std::pair<long,long>(xx,yy),goal);
00574 newnode->m_f=newnode->m_g+newnode->m_h;
00575
00576 m_openlist.push_back(newnode);
00577 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00578 hl((yy*m_mapwidth)+xx).m_onopen=true;
00579 m_helperlist[((yy*m_mapwidth)+xx)-m_helperliststartindex].m_node=newnode;
00580 }
00581
00582 m_cache[currentnodeindex-m_cachestartindex].m_neighbors.push_back(std::pair<std::pair<long,long> ,COSTTYPE>(std::pair<long,long>(xx,yy),movecost(currentnode->m_node,std::pair<long,long>(xx,yy))));
00583
00584 }
00585 }
00586 }
00587 }
00588 else
00589 {
00590 finalpath.clear();
00591 while(currentnode)
00592 {
00593 finalpath.push_back(currentnode->m_node);
00594 currentnode=currentnode->m_parent;
00595 }
00596 return PATH_FOUND;
00597 }
00598
00599 }
00600
00601 return PATH_NOTFOUND;
00602 }
00603
00604 }
00605
00606 #endif // _pathfinder_astar_tile4dir_cached_