BWAPI
|
00001 #include "BorderTracker.h" 00002 00003 #include "TerrainAnaysis.h" 00004 #include "BaseTracker.h" 00005 00006 void BorderTrackerClass::onBegin() 00007 { 00008 for each(Region region in TerrainAnaysis::Instance().getRegions()) 00009 { 00010 if(region->getSize() > 100000) 00011 mLargeRegions.insert(region); 00012 } 00013 } 00014 00015 void BorderTrackerClass::update() 00016 { 00017 std::set<Base> myBases = BaseTracker::Instance().getImportantBases(); 00018 std::set<Base> enemyBases = BaseTracker::Instance().getEnemyImportantBases(); 00019 if(enemyBases != mEnemyBases || myBases != mMyBases) 00020 { 00021 mMyBases = myBases; 00022 mEnemyBases = enemyBases; 00023 recalculateBorders(); 00024 } 00025 00026 drawDebugInfo(mBorderPositions.find(PositionType::TechDefenseChokepoint)); 00027 00028 if(mShowDebugInfo) 00029 { 00030 for each(Region region in mLargeRegions) 00031 { 00032 region->draw(BWAPI::Colors::Red); 00033 } 00034 drawDebugInfo(mBorderPositions.find(PositionType::EnemyControlRegion)); 00035 drawDebugInfo(mBorderPositions.find(PositionType::BotControlRegion)); 00036 drawDebugInfo(mBorderPositions.find(PositionType::ForwardRegion)); 00037 drawDebugInfo(mBorderPositions.find(PositionType::ContainChokepoint)); 00038 drawDebugInfo(mBorderPositions.find(PositionType::ForwardChokepoint)); 00039 drawDebugInfo(mBorderPositions.find(PositionType::EnemyChokepoint)); 00040 drawDebugInfo(mBorderPositions.find(PositionType::DefenseChokepoint)); 00041 drawDebugInfo(mBorderPositions.find(PositionType::SharedChokepoint)); 00042 drawDebugInfo(mBorderPositions.find(PositionType::Position)); 00043 drawDebugInfo(mBorderPositions.find(PositionType::HoldBase)); 00044 } 00045 } 00046 00047 void BorderTrackerClass::recalculateBorders() 00048 { 00049 mMyRegions.clear(); 00050 mMyForwardRegions.clear(); 00051 mMyBorder.clear(); 00052 mMyForwardBorder.clear(); 00053 mEnemyRegions.clear(); 00054 mEnemyBorder.clear(); 00055 mBorderPositions.clear(); 00056 00057 std::set<Region> canReachSelf; 00058 std::set<Region> canReachEnemy; 00059 std::map<Region, int> regionTech; 00060 00061 //Add all my regions to the set 00062 for each(Base base in mMyBases) 00063 { 00064 if(mLargeRegions.count(base->getRegion()) == 0) 00065 { 00066 regionTech[base->getRegion()] += base->getNumberOfTechBuildings(); 00067 mMyRegions.insert(base->getRegion()); 00068 canReachSelf.insert(base->getRegion()); 00069 } 00070 } 00071 00072 //Add all enemy regions to the set 00073 for each(Base base in mEnemyBases) 00074 { 00075 if(mLargeRegions.count(base->getRegion()) == 0) 00076 { 00077 regionTech[base->getRegion()] += base->getNumberOfTechBuildings(); 00078 mEnemyRegions.insert(base->getRegion()); 00079 canReachEnemy.insert(base->getRegion()); 00080 } 00081 } 00082 00083 //If there are enemy bases 00084 if(!mEnemyBases.empty()) 00085 { 00086 bool exploring = true; 00087 while(exploring) 00088 { 00089 exploring = false; 00090 00091 //Go through the regions 00092 for each(Region region in TerrainAnaysis::Instance().getRegions()) 00093 { 00094 for each(Chokepoint chokepoint in region->getChokepoints()) 00095 { 00096 Region secondRegion = chokepoint->getRegions().first; 00097 if(region == secondRegion) 00098 secondRegion = chokepoint->getRegions().second; 00099 00100 //if this region is in the set and the connected region cannot be reached by the enemy, it can be considered ours. 00101 if(canReachSelf.count(region) != 0 && mEnemyRegions.count(secondRegion) == 0 && canReachSelf.count(secondRegion) == 0) 00102 { 00103 canReachSelf.insert(secondRegion); 00104 exploring = true; 00105 } 00106 00107 //if this region is in the set and the connected region cannot be reached by me, it can be considered the enemies. 00108 if(canReachEnemy.count(region) != 0 && mMyRegions.count(secondRegion) == 0 && canReachEnemy.count(secondRegion) == 0) 00109 { 00110 canReachEnemy.insert(secondRegion); 00111 exploring = true; 00112 } 00113 } 00114 } 00115 } 00116 } 00117 00118 for each(Region region in TerrainAnaysis::Instance().getRegions()) 00119 { 00120 //if we can reach this region and the enemy can't, it can be ours 00121 if(canReachSelf.count(region) != 0 && canReachEnemy.count(region) == 0) 00122 { 00123 mBorderPositions[PositionType::BotControlRegion].insert(BorderPosition(PositionType::BotControlRegion, region)); 00124 mMyRegions.insert(region); 00125 mMyForwardRegions.insert(region); 00126 } 00127 00128 //if we cant reach this region and the enemy can, it can be the enemies 00129 if(canReachSelf.count(region) == 0 && canReachEnemy.count(region) != 0) 00130 { 00131 mBorderPositions[PositionType::EnemyControlRegion].insert(BorderPosition(PositionType::EnemyControlRegion, region)); 00132 mEnemyRegions.insert(region); 00133 } 00134 } 00135 00136 //any chokepoints that dont straddle 2 regions are defense chokepoints 00137 for each(Region region in mMyRegions) 00138 { 00139 for each(Chokepoint chokepoint in region->getChokepoints()) 00140 { 00141 if(mMyBorder.count(chokepoint) == 0) 00142 mMyBorder.insert(chokepoint); 00143 else 00144 mMyBorder.erase(chokepoint); 00145 } 00146 } 00147 00148 std::map<Chokepoint, int> borderChokeTech; 00149 for each(Chokepoint chokepoint in mMyBorder) 00150 { 00151 Region startRegion = chokepoint->getRegions().first; 00152 if(mMyRegions.count(startRegion) == 0) 00153 startRegion = chokepoint->getRegions().second; 00154 00155 std::set<Region> visitedRegions; 00156 std::set<Region> unvisitedRegions; 00157 int controlledAreaTech = 0; 00158 unvisitedRegions.insert(startRegion); 00159 00160 while(!unvisitedRegions.empty()) 00161 { 00162 std::set<Region>::iterator it = unvisitedRegions.begin(); 00163 visitedRegions.insert(*it); 00164 00165 controlledAreaTech += regionTech[*it]; 00166 00167 for each(Chokepoint connectedChoke in (*it)->getChokepoints()) 00168 { 00169 if(mMyBorder.count(connectedChoke) != 0) 00170 continue; 00171 00172 Region connectedRegion = connectedChoke->getRegions().first; 00173 if(connectedRegion == *it) 00174 connectedRegion = connectedChoke->getRegions().second; 00175 00176 if(visitedRegions.count(connectedRegion) == 0) 00177 unvisitedRegions.insert(connectedRegion); 00178 } 00179 00180 unvisitedRegions.erase(it); 00181 } 00182 00183 borderChokeTech[chokepoint] = controlledAreaTech; 00184 } 00185 00186 for each(Region region in mEnemyRegions) 00187 { 00188 for each(Chokepoint chokepoint in region->getChokepoints()) 00189 { 00190 if (mEnemyBorder.count(chokepoint) == 0) 00191 mEnemyBorder.insert(chokepoint); 00192 else 00193 mEnemyBorder.erase(chokepoint); 00194 } 00195 } 00196 00197 mMyForwardBorder = mMyBorder; 00198 for each(Chokepoint chokepoint in mMyBorder) 00199 { 00200 mBorderPositions[PositionType::DefenseChokepoint].insert(BorderPosition(PositionType::DefenseChokepoint, chokepoint)); 00201 00202 if(mEnemyBorder.count(chokepoint) != 0) 00203 mBorderPositions[PositionType::SharedChokepoint].insert(BorderPosition(PositionType::SharedChokepoint, chokepoint)); 00204 00205 if(borderChokeTech[chokepoint] > 0) 00206 mBorderPositions[PositionType::TechDefenseChokepoint].insert(BorderPosition(PositionType::TechDefenseChokepoint, chokepoint)); 00207 } 00208 00209 for each(Chokepoint chokepoint in mEnemyBorder) 00210 { 00211 mBorderPositions[PositionType::EnemyChokepoint].insert(BorderPosition(PositionType::EnemyChokepoint, chokepoint)); 00212 } 00213 00214 if(!mEnemyBases.empty()) 00215 { 00216 bool expanding = true; 00217 while(expanding) 00218 { 00219 expanding = false; 00220 00221 for each(Chokepoint chokepoint in mMyForwardBorder) 00222 { 00223 //get the region the otherside of this chokepoint 00224 Region region = chokepoint->getRegions().first; 00225 if(mMyForwardRegions.count(region) != 0) 00226 region = chokepoint->getRegions().second; 00227 00228 //make sure it isn't an enemy region 00229 if(mEnemyRegions.find(region) != mEnemyRegions.end()) 00230 continue; 00231 00232 int oldCount = 0; 00233 int newCount = 0; 00234 00235 //count the number of chokepoints part of our border and those not 00236 for each(Chokepoint chokepoint in region->getChokepoints()) 00237 { 00238 if(mMyForwardBorder.find(chokepoint) != mMyForwardBorder.end()) 00239 ++oldCount; 00240 else 00241 ++newCount; 00242 } 00243 00244 //if we can reduce the number of chokepoints 00245 if(newCount <= oldCount) 00246 { 00247 //reverse regions, so we consider this region ours. 00248 for each(Chokepoint chokepoint in region->getChokepoints()) 00249 { 00250 if(mMyForwardBorder.count(chokepoint) != 0) 00251 mMyForwardBorder.erase(chokepoint); 00252 else 00253 mMyForwardBorder.insert(chokepoint); 00254 } 00255 00256 mMyForwardRegions.insert(region); 00257 00258 expanding = true; 00259 break; 00260 } 00261 } 00262 } 00263 } 00264 00265 for each(Chokepoint chokepoint in mMyForwardBorder) 00266 { 00267 if(mMyBorder.count(chokepoint) == 0) 00268 mBorderPositions[PositionType::ForwardChokepoint].insert(BorderPosition(PositionType::ForwardChokepoint, chokepoint)); 00269 } 00270 00271 for each(Region region in mMyForwardRegions) 00272 { 00273 if(mMyRegions.count(region) == 0) 00274 mBorderPositions[PositionType::ForwardRegion].insert(BorderPosition(PositionType::ForwardRegion, region)); 00275 } 00276 } 00277 00278 void BorderTrackerClass::drawDebugInfo(std::map<PositionType, std::set<BorderPosition>>::const_iterator it) 00279 { 00280 if(it == mBorderPositions.end() || it->second.size() == 0) 00281 return; 00282 00283 for(std::set<BorderPosition>::const_iterator bp = it->second.begin(); bp != it->second.end(); ++bp) 00284 { 00285 switch(bp->mType.underlying()) 00286 { 00287 case PositionType::ContainChokepoint: 00288 case PositionType::ForwardChokepoint: 00289 case PositionType::EnemyChokepoint: 00290 case PositionType::DefenseChokepoint: 00291 { 00292 BWAPI::Color color = bp->mType == PositionType::DefenseChokepoint ? BWAPI::Colors::Green : (bp->mType == PositionType::EnemyChokepoint ? BWAPI::Colors::Red : (bp->mType == PositionType::ForwardChokepoint ? BWAPI::Colors::Blue : BWAPI::Colors::Yellow)); 00293 bp->mChoke->draw(color); 00294 break; 00295 } 00296 case PositionType::EnemyControlRegion: 00297 case PositionType::BotControlRegion: 00298 case PositionType::ForwardRegion: 00299 { 00300 BWAPI::Color color = bp->mType == PositionType::BotControlRegion ? BWAPI::Colors::Grey : (bp->mType == PositionType::ForwardRegion ? BWAPI::Colors::Orange : BWAPI::Colors::Purple); 00301 bp->mRegion->draw(color); 00302 break; 00303 } 00304 } 00305 } 00306 }