BWAPI
Skynet/Skynet/PathFinder.cpp
Go to the documentation of this file.
00001 #include "PathFinder.h"
00002 #include "Heap.h"
00003 #include "BuildingPlacer.h"
00004 #include "TerrainAnaysis.h"
00005 #include "DrawBuffer.h"
00006 #include "Logger.h"
00007 
00008 BuildTilePath PathFinderClass::CreateTilePath(TilePosition start, TilePosition target, std::tr1::function<bool (TilePosition)> tileTest, std::tr1::function<int (TilePosition, TilePosition, int)> gFunction, std::tr1::function<int (TilePosition, TilePosition)> hFunction, int maxGValue, bool diaganol)
00009 {
00010         BuildTilePath path;
00011 
00012         Heap<TilePosition, int> openTiles(true);
00013         std::map<TilePosition, int> gmap;
00014         std::map<TilePosition, TilePosition> parent;
00015         std::set<TilePosition> closedTiles;
00016 
00017         openTiles.push(std::make_pair(start, 0));
00018         gmap[start] = 0;
00019         parent[start] = start;
00020 
00021         while(!openTiles.empty())
00022         {
00023                 TilePosition p = openTiles.top().first;
00024                 int gvalue = gmap[p];
00025 
00026                 if(p == target || (maxGValue != 0 && gvalue >= maxGValue))
00027                         break;
00028 
00029                 int fvalue = openTiles.top().second;
00030                 
00031                 openTiles.pop();
00032                 closedTiles.insert(p);
00033 
00034                 int minx = std::max(p.x() - 1, 0);
00035                 int maxx = std::min(p.x() + 1, BWAPI::Broodwar->mapWidth());
00036                 int miny = std::max(p.y() - 1, 0);
00037                 int maxy = std::min(p.y() + 1, BWAPI::Broodwar->mapHeight());
00038 
00039                 for(int x = minx; x <= maxx; x++)
00040                 {
00041                         for(int y = miny; y <= maxy; y++)
00042                         {
00043                                 if (x != p.x() && y != p.y() && !diaganol)
00044                                         continue;
00045 
00046                                 TilePosition t(x, y);
00047 
00048                                 if (closedTiles.find(t) != closedTiles.end())
00049                                         continue;
00050 
00051                                 if(!tileTest(t))
00052                                         continue;
00053 
00054                                 int g = gFunction(t, p, gvalue);
00055 
00056                                 int f = g + hFunction(t, target);
00057                                 if (gmap.find(t) == gmap.end() || g < gmap.find(t)->second)
00058                                 {
00059                                         gmap[t] = g;
00060                                         openTiles.set(t, f);
00061                                         parent[t] = p;
00062                                 }
00063                         }
00064                 }
00065         }
00066 
00067         if(!openTiles.empty())
00068         {
00069                 TilePosition p = openTiles.top().first;
00070                 while(p != parent[p])
00071                 {
00072                         path.addNode(p);
00073                         p = parent[p];
00074                 }
00075                 path.addNode(start);
00076                 path.isComplete = true;
00077         }
00078 
00079         return path;
00080 }
00081 
00082 class FleeGValue
00083 {
00084 public:
00085         int operator()(TilePosition currentTile, TilePosition previousTile, int gTotal)
00086         {
00087                 return gTotal + 1;
00088         }
00089 };
00090 
00091 class FleeHValue
00092 {
00093 public:
00094         FleeHValue(const UnitGroup &enemies)
00095                 : mEnemies(enemies)
00096         {
00097                 mMmaxHValue = std::max(BWAPI::Broodwar->mapHeight(), BWAPI::Broodwar->mapWidth());
00098         }
00099 
00100         int operator()(TilePosition position, TilePosition target)
00101         {
00102                 int h = 0;
00103 
00104                 for each(Unit enemy in mEnemies)
00105                 {
00106                         h += mMmaxHValue - (int)position.getDistance(enemy->getTilePosition());
00107                 }
00108 
00109                 h /= mEnemies.size();
00110 
00111                 return h;
00112         }
00113 
00114         const UnitGroup &mEnemies;
00115         int mMmaxHValue;
00116 };
00117 
00118 class FleeTileTest
00119 {
00120 public:
00121         FleeTileTest(bool stickToRegion, TilePosition start)
00122                 : mStickToRegion(stickToRegion)
00123                 , mStart(start)
00124         {}
00125 
00126         bool operator()(TilePosition position)
00127         {
00128                 if(!BuildingPlacer::Instance().isTileWalkable(position))
00129                         return false;
00130 
00131                 return !mStickToRegion || TerrainAnaysis::Instance().getRegion(position) == TerrainAnaysis::Instance().getRegion(mStart);
00132         }
00133 
00134         bool mStickToRegion;
00135         TilePosition mStart;
00136 };
00137 
00138 BuildTilePath PathFinderClass::CreateAdvancedFleePath(TilePosition start, const UnitGroup &enemies, bool stickToRegion)
00139 {
00140         return CreateTilePath(start, BWAPI::TilePositions::None, FleeTileTest(stickToRegion, start), FleeGValue(), FleeHValue(enemies), 20, false);
00141 }
00142 
00143 RegionPath PathFinderClass::CreateRegionPath(Region start, Region target)
00144 {
00145         RegionPath path;
00146 
00147         Heap<Region, int> openRegions(true);
00148         std::map<Region, int> gmap;
00149         std::map<Region, Region> parent;
00150         std::set<Region> closedRegions;
00151 
00152         openRegions.push(std::make_pair(start, 0));
00153         gmap[start] = 0;
00154         parent[start] = start;
00155 
00156         while(!openRegions.empty())
00157         {
00158                 Region region = openRegions.top().first;
00159 
00160                 if(region == target)
00161                 {
00162                         while(region != parent[region])
00163                         {
00164                                 path.addNode(region);
00165                                 region = parent[region];
00166                         }
00167                         path.addNode(start);
00168                         path.isComplete = true;
00169                         return path;
00170                 }
00171 
00172                 int gvalue = gmap[region];
00173                 int fvalue = openRegions.top().second;
00174 
00175                 openRegions.pop();
00176                 closedRegions.insert(region);
00177 
00178                 for each(Chokepoint choke in region->getChokepoints())
00179                 {
00180                         Region other = choke->getRegions().first;
00181                         if(other == region)
00182                                 other = choke->getRegions().second;
00183 
00184                         int g = gvalue + region->getCenter().getApproxDistance(other->getCenter());
00185                         int h = other->getCenter().getApproxDistance(target->getCenter());
00186 
00187                         int f = g + h;
00188                         if(gmap.count(other) == 0 || g < gmap.find(other)->second)
00189                         {
00190                                 gmap[other] = g;
00191                                 openRegions.set(other, f);
00192                                 parent[other] = region;
00193                         }
00194                 }
00195         }
00196 
00197         return path;
00198 }
00199 
00200 PositionPath PathFinderClass::CreateCheapWalkPath(Position start, Position target)
00201 {
00202         if(!BWAPI::Broodwar->hasPath(start, target))
00203                 return PositionPath();
00204 
00205         Region startRegion = TerrainAnaysis::Instance().getRegion(TilePosition(start));
00206         Region endRegion = TerrainAnaysis::Instance().getRegion(TilePosition(target));
00207 
00208         PositionPath path;
00209 
00210         if(startRegion == endRegion)
00211         {
00212                 path.addNode(target);
00213                 path.addNode(start);
00214                 path.isComplete = true;
00215 
00216                 return path;
00217         }
00218 
00219         RegionPath regionPath = CreateRegionPath(startRegion, endRegion);
00220 
00221         if(!regionPath.isComplete)
00222                 return path;
00223 
00224         regionPath.drawPath();
00225 
00226         path.path.push_back(start);
00227 
00228         Region previousRegion;
00229         for each(Region region in regionPath.path)
00230         {
00231                 if(previousRegion)
00232                 {
00233                         for each(Chokepoint choke in region->getChokepoints())
00234                         {
00235                                 if(choke->getRegions().first == previousRegion || choke->getRegions().second == previousRegion)
00236                                 {
00237                                         path.path.push_back(choke->getCenter());
00238                                         break;
00239                                 }
00240                         }
00241                 }
00242 
00243                 previousRegion = region;
00244         }
00245 
00246         path.path.push_back(target);
00247         path.isComplete = true;
00248 
00249         return path;
00250 }
00251 
00252 WalkPositionPath PathFinderClass::CreateWalkPath(WalkPosition start, WalkPosition target, std::tr1::function<bool (WalkPosition)> tileTest, std::tr1::function<int (WalkPosition, WalkPosition, int)> gFunction, std::tr1::function<int (WalkPosition, WalkPosition)> hFunction, int maxGValue, bool diaganol)
00253 {
00254         WalkPositionPath path;
00255 
00256         Heap<WalkPosition, int> openTiles(false);
00257         std::map<WalkPosition, int> gmap;
00258         std::map<WalkPosition, WalkPosition> parent;
00259         std::set<WalkPosition> closedTiles;
00260 
00261         int mapWidth = BWAPI::Broodwar->mapWidth() * 4;
00262         int mapHeight = BWAPI::Broodwar->mapHeight() * 4;
00263 
00264         openTiles.push(std::make_pair(start, 0));
00265         gmap[start] = 0;
00266         parent[start] = start;
00267 
00268         while(!openTiles.empty())
00269         {
00270                 WalkPosition p = openTiles.top().first;
00271                 int gvalue = gmap[p];
00272 
00273                 if(p == target || (maxGValue != 0 && gvalue >= maxGValue))
00274                         break;
00275 
00276                 int fvalue = openTiles.top().second;
00277 
00278                 openTiles.pop();
00279                 closedTiles.insert(p);
00280 
00281                 int minx = std::max(p.x - 1, 0);
00282                 int maxx = std::min(p.x + 1, mapWidth);
00283                 int miny = std::max(p.y - 1, 0);
00284                 int maxy = std::min(p.y + 1, mapHeight);
00285 
00286                 for(int x = minx; x <= maxx; x++)
00287                 {
00288                         for(int y = miny; y <= maxy; y++)
00289                         {
00290                                 if (x != p.x && y != p.y && !diaganol)
00291                                         continue;
00292 
00293                                 WalkPosition t(x, y);
00294 
00295                                 if(closedTiles.find(t) != closedTiles.end())
00296                                         continue;
00297 
00298                                 if(!tileTest(t))
00299                                         continue;
00300 
00301                                 int g = gFunction(t, p, gvalue);
00302 
00303                                 int f = g + hFunction(t, target);
00304                                 if (gmap.find(t) == gmap.end() || g < gmap.find(t)->second)
00305                                 {
00306                                         gmap[t] = g;
00307                                         openTiles.set(t, f);
00308                                         parent[t] = p;
00309                                 }
00310                         }
00311                 }
00312         }
00313 
00314         for each(std::pair<WalkPosition, int> pos in gmap)
00315         {
00316 //              DrawBuffer::Instance().drawBufferedLine(BWAPI::CoordinateType::Map, pos.first.x*8, pos.first.y*8, parent[pos.first].x*8, parent[pos.first].y*8, 999999);
00317 //              String_Builder string;
00318 //              string << pos.second;
00319 //              DrawBuffer::Instance().drawBufferedText(BWAPI::CoordinateType::Map, pos.first.x * 8, pos.first.y * 8, string, 999999);
00320         }
00321 
00322         if(!openTiles.empty())
00323         {
00324                 WalkPosition p = openTiles.top().first;
00325                 while(p != parent[p])
00326                 {
00327                         path.addNode(p);
00328                         p = parent[p];
00329                 }
00330                 path.addNode(start);
00331                 path.isComplete = true;
00332         }
00333 
00334         return path;
00335 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines