BWAPI
|
00001 #include "MapHelper.h" 00002 00003 #include <regex> 00004 00005 #include "UnitTracker.h" 00006 #include "Heap.h" 00007 #include "BaseTracker.h" 00008 #include "PathFinder.h" 00009 00010 TilePosition MapHelper::spiralSearch(TilePosition startLocation, std::tr1::function<bool (TilePosition)> testFunction, int maxRadius) 00011 { 00012 int x = startLocation.x(); 00013 int y = startLocation.y(); 00014 00015 int length = 1; 00016 int j = 0; 00017 bool first = true; 00018 int dx = 0; 00019 int dy = 1; 00020 00021 if(maxRadius == 0) 00022 maxRadius = std::max(BWAPI::Broodwar->mapWidth(), BWAPI::Broodwar->mapHeight()); 00023 00024 while(length < maxRadius) 00025 { 00026 if(x >= 0 && x < BWAPI::Broodwar->mapWidth() && y >= 0 && y < BWAPI::Broodwar->mapHeight()) 00027 { 00028 TilePosition location(x, y); 00029 if(testFunction(location)) 00030 return location; 00031 } 00032 00033 x = x + dx; 00034 y = y + dy; 00035 00036 //count how many steps we take in this direction 00037 ++j; 00038 if(j == length) //if we've reached the end, its time to turn 00039 { 00040 //reset step counter 00041 j = 0; 00042 00043 //Spiral out. Keep going. 00044 if(!first) 00045 ++length; //increment step counter if needed 00046 00047 //first=true for every other turn so we spiral out at the right rate 00048 first = !first; 00049 00050 //turn counter clockwise 90 degrees: 00051 if (dx == 0) 00052 { 00053 dx = dy; 00054 dy = 0; 00055 } 00056 else 00057 { 00058 dy = -dx; 00059 dx = 0; 00060 } 00061 } 00062 //Spiral out. Keep going. 00063 } 00064 00065 return BWAPI::TilePositions::None; 00066 } 00067 00068 std::set<TilePosition> MapHelper::floodFill(TilePosition start, std::tr1::function<bool (TilePosition)> testFunction, std::set<TilePosition> targets, std::set<TilePosition> ignoreTiles) 00069 { 00070 bool noTargets = targets.empty(); 00071 00072 std::set<TilePosition> remainingTiles; 00073 remainingTiles.insert(start); 00074 00075 while(!remainingTiles.empty()) 00076 { 00077 if(!noTargets && targets.empty()) 00078 return targets; 00079 00080 TilePosition tile = *remainingTiles.begin(); 00081 00082 ignoreTiles.insert(tile); 00083 remainingTiles.erase(tile); 00084 00085 if(!tile.isValid()) 00086 continue; 00087 00088 if(!testFunction(tile)) 00089 continue; 00090 00091 if(noTargets) 00092 targets.insert(tile); 00093 else 00094 targets.erase(tile); 00095 00096 if(ignoreTiles.count(TilePosition(tile.x() + 1, tile.y())) == 0) 00097 remainingTiles.insert(TilePosition(tile.x() + 1, tile.y())); 00098 if(ignoreTiles.count(TilePosition(tile.x() - 1, tile.y())) == 0) 00099 remainingTiles.insert(TilePosition(tile.x() - 1, tile.y())); 00100 if(ignoreTiles.count(TilePosition(tile.x(), tile.y() + 1)) == 0) 00101 remainingTiles.insert(TilePosition(tile.x(), tile.y() + 1)); 00102 if(ignoreTiles.count(TilePosition(tile.x(), tile.y() - 1)) == 0) 00103 remainingTiles.insert(TilePosition(tile.x(), tile.y() - 1)); 00104 } 00105 00106 return targets; 00107 } 00108 00109 std::map<WalkPosition, int> MapHelper::walkSearch(WalkPosition start, std::tr1::function<bool (WalkPosition)> testFunction, std::set<WalkPosition> targets, std::set<WalkPosition> ignoreTiles) 00110 { 00111 std::map<WalkPosition, int> returnDistances; 00112 00113 int mapWidth = BWAPI::Broodwar->mapWidth() * 4; 00114 int mapHeight = BWAPI::Broodwar->mapHeight() * 4; 00115 00116 Heap<WalkPosition, int> openTiles(true); 00117 std::map<WalkPosition, int> gmap; 00118 std::set<WalkPosition> closedTiles; 00119 00120 openTiles.push(std::make_pair(start, 0)); 00121 gmap[start] = 0; 00122 00123 int maxhvalue = std::max(mapHeight, mapWidth); 00124 00125 while(!openTiles.empty()) 00126 { 00127 WalkPosition p = openTiles.top().first; 00128 00129 int fvalue = openTiles.top().second; 00130 int gvalue = gmap[p]; 00131 00132 openTiles.pop(); 00133 closedTiles.insert(p); 00134 returnDistances[p] = gvalue; 00135 00136 for(int i = 0; i < 4; ++i) 00137 { 00138 int x = i == 0 ? 1 : i == 1 ? -1 : 0; 00139 int y = i == 2 ? 1 : i == 3 ? -1 : 0; 00140 WalkPosition tile(p.x + x, p.y + y); 00141 00142 if(tile.x < 0 || tile.y < 0 || tile.x >= mapWidth || tile.y >= mapHeight) 00143 continue; 00144 00145 if(closedTiles.find(tile) != closedTiles.end()) 00146 continue; 00147 00148 if(!testFunction(tile)) 00149 continue; 00150 00151 int g = gvalue + 1; 00152 00153 int f = g; 00154 if(gmap.find(tile) == gmap.end() || gmap[tile] > g) 00155 { 00156 gmap[tile] = g; 00157 openTiles.set(tile, f); 00158 } 00159 } 00160 } 00161 00162 return returnDistances; 00163 } 00164 00165 bool MapHelper::isAnyVisible(TilePosition location, BWAPI::UnitType type) 00166 { 00167 for(int x = location.x(); x < location.x() + type.tileWidth(); ++x) 00168 { 00169 for(int y = location.y(); y < location.y() + type.tileHeight(); ++y) 00170 { 00171 if(BWAPI::Broodwar->isVisible(x, y)) 00172 return true; 00173 } 00174 } 00175 00176 return false; 00177 } 00178 00179 bool MapHelper::isAllVisible(TilePosition location, BWAPI::UnitType type) 00180 { 00181 for(int x = location.x(); x < location.x() + type.tileWidth(); ++x) 00182 { 00183 for(int y = location.y(); y < location.y() + type.tileHeight(); ++y) 00184 { 00185 if(!BWAPI::Broodwar->isVisible(x, y)) 00186 return false; 00187 } 00188 } 00189 00190 return true; 00191 } 00192 00193 bool MapHelper::isTileWalkable(TilePosition location) 00194 { 00195 return isTileWalkable(location.x(), location.y()); 00196 } 00197 00198 bool MapHelper::isTileWalkable(int x, int y) 00199 { 00200 for(int nx = x * 4; nx < x * 4 + 4; ++nx) 00201 { 00202 for(int ny = y * 4; ny < y * 4 + 4; ++ny) 00203 { 00204 if(!BWAPI::Broodwar->isWalkable(nx, ny)) 00205 return false; 00206 } 00207 } 00208 00209 return true; 00210 } 00211 00212 bool MapHelper::mapIs(std::string name) 00213 { 00214 std::string mapName = BWAPI::Broodwar->mapName(); 00215 std::transform(mapName.begin(), mapName.end(), mapName.begin(), tolower); 00216 00217 std::string mapFileName = BWAPI::Broodwar->mapFileName(); 00218 std::transform(mapFileName.begin(), mapFileName.end(), mapFileName.begin(), tolower); 00219 00220 std::transform(name.begin(), name.end(), name.begin(), tolower); 00221 00222 return std::tr1::regex_search(mapName.begin(), mapName.end(), std::tr1::regex(name)) || std::tr1::regex_search(mapFileName.begin(), mapFileName.end(), std::tr1::regex(name)); 00223 } 00224 00225 int MapHelper::getGroundDistance(Position start, Position end) 00226 { 00227 if(!BWAPI::Broodwar->hasPath(start, end)) 00228 return std::numeric_limits<int>::max(); 00229 00230 int groundDistance = PathFinder::Instance().CreateCheapWalkPath(start, end).getLength(); 00231 int linearDistance = start.getApproxDistance(end); 00232 00233 if(groundDistance < linearDistance) 00234 return linearDistance; 00235 00236 return groundDistance; 00237 }