BWAPI
|
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 }