BWAPI
Skynet/Skynet/BorderTracker.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines