|
BWAPI
|
00001 #include "Base.h" 00002 00003 #include <boost/bind.hpp> 00004 00005 #include "DrawBuffer.h" 00006 #include "UnitTracker.h" 00007 #include "Chokepoint.h" 00008 #include "MapHelper.h" 00009 #include "UnitHelper.h" 00010 00011 BaseClass::BaseClass(Region region, std::set<TilePosition> tiles, bool startLocation) 00012 : mCenterTilePosition(BWAPI::TilePositions::None) 00013 , mCenterPosition(region->getCenter()) 00014 , mMinedOut(true) 00015 , mRegion(region) 00016 , mIsStartLocation(startLocation) 00017 , mPlayer(NULL) 00018 , mBuildings() 00019 , mTiles(tiles) 00020 , mIsUnderAttack(false) 00021 , mIsContested(false) 00022 , mTechBuildings(0) 00023 { 00024 } 00025 00026 BaseClass::BaseClass(TilePosition position, const UnitGroup &resources, Region region, std::set<TilePosition> tiles, bool startLocation) 00027 : mCenterTilePosition(position) 00028 , mCenterPosition(Position(position.x()*32+64, position.y()*32+48)) 00029 , mMinedOut(false) 00030 , mRegion(region) 00031 , mIsStartLocation(startLocation) 00032 , mPlayer(NULL) 00033 , mBuildings() 00034 , mTiles(tiles) 00035 , mIsUnderAttack(false) 00036 , mIsContested(false) 00037 , mTechBuildings(0) 00038 { 00039 for each(Unit resource in resources) 00040 { 00041 if(resource->getType() == BWAPI::UnitTypes::Resource_Mineral_Field) 00042 mMinerals.insert(resource); 00043 else 00044 mGeysers.insert(resource); 00045 } 00046 } 00047 00048 void BaseClass::update() 00049 { 00050 if(!mMinedOut) 00051 { 00052 bool noGas = true; 00053 for each(Unit geyser in mGeysers) 00054 { 00055 if(geyser->getResources() > 0) 00056 noGas = false; 00057 } 00058 for each(Unit geyser in mRefineries) 00059 { 00060 if(geyser->getResources() > 0) 00061 noGas = false; 00062 } 00063 00064 if(mMinerals.empty() && noGas) 00065 mMinedOut = true; 00066 } 00067 00068 for(UnitGroup::iterator it = mBuildings.begin(); it != mBuildings.end();) 00069 { 00070 if((*it)->isLifted() || (*it)->accessibility() == AccessType::Lost) 00071 { 00072 Unit unit = *it; 00073 ++it; 00074 removeUnit(unit, unit->getPlayer(), unit->getType()); 00075 } 00076 else 00077 ++it; 00078 } 00079 00080 // TODO: Move this to the base manager and make a generic add building and remove building 00081 for each(Unit unit in mLiftedBuildings) 00082 { 00083 if(!unit->isLifted() && unit->exists()) 00084 addUnit(unit); 00085 } 00086 00087 mLiftedBuildings.clear(); 00088 for each(Unit unit in UnitTracker::Instance().getAllUnits()) 00089 { 00090 if(unit->getType().isBuilding() && unit->isLifted()) 00091 mLiftedBuildings.insert(unit); 00092 } 00093 00094 mAllThreats.clear(); 00095 mThreatTypes.clear(); 00096 mAllDefenders.clear(); 00097 int workerCount = 0; 00098 00099 if(mPlayer && mPlayer != BWAPI::Broodwar->neutral()) 00100 { 00101 for each(Unit defender in UnitTracker::Instance().selectAllUnits(mPlayer)) 00102 { 00103 if(!defender->isCompleted()) 00104 continue; 00105 00106 const BWAPI::UnitType &type = defender->getType(); 00107 if(!UnitHelper::isArmyUnit(type) && !type.isWorker()) 00108 continue; 00109 00110 if(mTiles.count(defender->getTilePosition()) == 0) 00111 continue; 00112 00113 if(type.isWorker()) 00114 { 00115 if(workerCount > 14)//Only count 14 as thats the only amount it will pull from the mineral line 00116 continue; 00117 else 00118 ++workerCount; 00119 } 00120 00121 mAllDefenders.insert(defender); 00122 } 00123 00124 for each(Unit enemy in UnitTracker::Instance().selectAllEnemy(mPlayer)) 00125 { 00126 if(enemy->getType().isBuilding() && !enemy->isLifted()) 00127 continue; 00128 00129 if(enemy->accessibility() == AccessType::Lost) 00130 continue; 00131 00132 if(mTiles.count(enemy->getTilePosition()) != 0) 00133 { 00134 mAllThreats.insert(enemy); 00135 mThreatTypes[UnitThreatType::Scout].insert(enemy); 00136 } 00137 00138 if(enemy->getType().isWorker()) 00139 continue; 00140 00141 const int maxRange = std::max(48, 24 + std::max(enemy->getGroundWeaponMaxRange(), enemy->getAirWeaponMaxRange())); 00142 00143 for each(Unit building in mBuildings) 00144 { 00145 if(enemy->getDistance(building) <= maxRange) 00146 { 00147 mAllThreats.insert(enemy); 00148 00149 if(enemy->getType().isFlyer() || enemy->isLifted()) 00150 { 00151 if(enemy->canAttackGround()) 00152 mThreatTypes[UnitThreatType::AirToGround].insert(enemy); 00153 if(enemy->canAttackAir()) 00154 mThreatTypes[UnitThreatType::AirToAir].insert(enemy); 00155 } 00156 else 00157 { 00158 if(enemy->canAttackGround()) 00159 mThreatTypes[UnitThreatType::GroundToGround].insert(enemy); 00160 if(enemy->canAttackAir()) 00161 mThreatTypes[UnitThreatType::GroundToAir].insert(enemy); 00162 } 00163 00164 break; 00165 } 00166 } 00167 } 00168 } 00169 00170 mActive = false; 00171 mActiveInFuture = false; 00172 mActivateTime = std::numeric_limits<int>::max(); 00173 mIsUnderAttack = !mThreatTypes[UnitThreatType::AirToGround].empty() || !mThreatTypes[UnitThreatType::GroundToGround].empty(); 00174 if(!mResourceDepots.empty()) 00175 { 00176 if(!mMinedOut) 00177 { 00178 if(!mIsUnderAttack && mResourceDepots[0]->isCompleted()) 00179 { 00180 mActive = true; 00181 mActiveInFuture = true; 00182 mActivateTime = 0; 00183 } 00184 else if(!mIsUnderAttack || (mAllDefenders.size() > 6 && mAllDefenders.ratingDifference(mThreatTypes[UnitThreatType::AirToGround] + mThreatTypes[UnitThreatType::GroundToGround]) >= 150)) 00185 { 00186 mActiveInFuture = true; 00187 mActivateTime = mResourceDepots[0]->getCompletedTime(); 00188 } 00189 } 00190 } 00191 00192 //drawDebugInfo(); 00193 } 00194 00195 bool BaseClass::depotCompare(const Unit &depotOne, const Unit &depotTwo) 00196 { 00197 int thisDistance = depotOne->getPosition().getApproxDistance(mCenterPosition); 00198 int currentDistance = depotTwo->getPosition().getApproxDistance(mCenterPosition); 00199 00200 return thisDistance < currentDistance; 00201 } 00202 00203 void BaseClass::onDiscover(Unit unit) 00204 { 00205 addUnit(unit); 00206 } 00207 00208 void BaseClass::onMorphRenegade(Unit unit, Player previousPlayer, BWAPI::UnitType previousType) 00209 { 00210 removeUnit(unit, previousPlayer != NULL ? previousPlayer : unit->getPlayer(), previousType != BWAPI::UnitTypes::None ? previousType : unit->getType()); 00211 addUnit(unit); 00212 } 00213 00214 void BaseClass::onDestroy(Unit unit) 00215 { 00216 removeUnit(unit, unit->getPlayer(), unit->getType()); 00217 } 00218 00219 void BaseClass::drawDebugInfo() const 00220 { 00221 if(mPlayer != NULL) 00222 BWAPI::Broodwar->drawCircle(BWAPI::CoordinateType::Map, mCenterPosition.x(), mCenterPosition.y(), 78, mPlayer->getColor(), false); 00223 else 00224 BWAPI::Broodwar->drawCircle(BWAPI::CoordinateType::Map, mCenterPosition.x(), mCenterPosition.y(), 78, BWAPI::Broodwar->neutral()->getColor(), false); 00225 00226 bool showtitle = false; 00227 int ypos = 30; 00228 00229 if(mIsStartLocation) 00230 { 00231 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Start Location"); 00232 ypos -= 10; 00233 showtitle = true; 00234 } 00235 00236 if(!mBuildings.empty()) 00237 { 00238 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Buildings: %u", mBuildings.size()); 00239 ypos -= 10; 00240 showtitle = true; 00241 } 00242 00243 if(mTechBuildings > 0) 00244 { 00245 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Number of Tech Buildings: %d", mTechBuildings); 00246 ypos -= 10; 00247 showtitle = true; 00248 } 00249 00250 if(mPlayer != NULL) 00251 { 00252 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Owner: %s", mPlayer->getName().c_str()); 00253 ypos -= 10; 00254 showtitle = true; 00255 } 00256 00257 if(isEnemyBase()) 00258 { 00259 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Is Enemy"); 00260 ypos -= 10; 00261 showtitle = true; 00262 } 00263 00264 if(isAllyBase()) 00265 { 00266 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Is Ally"); 00267 ypos -= 10; 00268 showtitle = true; 00269 } 00270 00271 if(isMyBase()) 00272 { 00273 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Is Mine"); 00274 ypos -= 10; 00275 showtitle = true; 00276 } 00277 00278 if(mIsContested) 00279 { 00280 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Base is Contested"); 00281 ypos -= 10; 00282 showtitle = true; 00283 } 00284 00285 if(mIsUnderAttack) 00286 { 00287 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Base is Under Attack"); 00288 ypos -= 10; 00289 showtitle = true; 00290 } 00291 00292 if(mActive) 00293 { 00294 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Base is Active"); 00295 ypos -= 10; 00296 showtitle = true; 00297 } 00298 else if(mActiveInFuture) 00299 { 00300 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Base is Active In Future"); 00301 ypos -= 10; 00302 showtitle = true; 00303 } 00304 00305 if(mMinedOut) 00306 { 00307 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - ypos, "Base is mined out"); 00308 ypos -= 10; 00309 showtitle = true; 00310 } 00311 00312 if(showtitle) 00313 BWAPI::Broodwar->drawTextMap(mCenterPosition.x() + 60, mCenterPosition.y() - 40, "Base Info:"); 00314 00315 for each(Unit unit in mAllThreats) 00316 { 00317 BWAPI::Broodwar->drawLineMap(unit->getPosition().x(), unit->getPosition().y(), mCenterPosition.x(), mCenterPosition.y(), BWAPI::Colors::Red); 00318 } 00319 for each(Unit building in mBuildings) 00320 { 00321 BWAPI::Broodwar->drawLine(BWAPI::CoordinateType::Map, building->getPosition().x(), building->getPosition().y(), mCenterPosition.x(), mCenterPosition.y(), building->getPlayer()->getColor()); 00322 } 00323 00324 for each(Unit mineral in mMinerals) 00325 { 00326 BWAPI::Broodwar->drawCircleMap(mineral->getPosition().x(), mineral->getPosition().y(), 32, BWAPI::Colors::Blue); 00327 BWAPI::Broodwar->drawLineMap(mineral->getPosition().x(), mineral->getPosition().y(), mCenterPosition.x(), mCenterPosition.y(), BWAPI::Colors::Blue); 00328 } 00329 for each(Unit geyser in mGeysers) 00330 { 00331 BWAPI::Broodwar->drawCircleMap(geyser->getPosition().x(), geyser->getPosition().y(), 32, BWAPI::Colors::Green); 00332 BWAPI::Broodwar->drawLineMap(geyser->getPosition().x(), geyser->getPosition().y(), mCenterPosition.x(), mCenterPosition.y(), BWAPI::Colors::Green); 00333 } 00334 for each(Unit geyser in mRefineries) 00335 { 00336 BWAPI::Broodwar->drawCircleMap(geyser->getPosition().x(), geyser->getPosition().y(), 32, BWAPI::Colors::Orange); 00337 BWAPI::Broodwar->drawLineMap(geyser->getPosition().x(), geyser->getPosition().y(), mCenterPosition.x(), mCenterPosition.y(), BWAPI::Colors::Green); 00338 } 00339 } 00340 00341 Unit BaseClass::getClosestEnemyBuilding(Position pos) 00342 { 00343 int minDist = std::numeric_limits<int>::max(); 00344 Unit bestBuilding; 00345 00346 for each(Unit unit in mBuildings) 00347 { 00348 if(!BWAPI::Broodwar->self()->isEnemy(unit->getPlayer())) 00349 continue; 00350 00351 int thisDist = pos.getApproxDistance(unit->getPosition()); 00352 if(thisDist < minDist) 00353 { 00354 minDist = thisDist; 00355 bestBuilding = unit; 00356 } 00357 } 00358 00359 return bestBuilding; 00360 } 00361 00362 void BaseClass::updatePlayer() 00363 { 00364 mIsContested = false; 00365 if(mPlayerBuildingNumbers.empty()) 00366 mPlayer = NULL; 00367 else if(mPlayerBuildingNumbers.size() == 1) 00368 mPlayer = mPlayerBuildingNumbers.begin()->first; 00369 else 00370 { 00371 mIsContested = true; 00372 if(!mResourceDepots.empty()) 00373 mPlayer = mResourceDepots[0]->getPlayer(); 00374 else 00375 { 00376 mPlayer = NULL; 00377 int number = 0; 00378 for each(std::pair<Player, int> pair in mPlayerBuildingNumbers) 00379 { 00380 if(pair.second > number) 00381 { 00382 mPlayer = pair.first; 00383 number = pair.second; 00384 } 00385 } 00386 } 00387 } 00388 } 00389 00390 void BaseClass::addUnit(Unit unit) 00391 { 00392 if(mTiles.count(unit->getTilePosition()) == 0) 00393 return; 00394 00395 const BWAPI::UnitType &type = unit->getType(); 00396 00397 if(type == BWAPI::UnitTypes::Resource_Vespene_Geyser) 00398 mGeysers.insert(unit); 00399 00400 if(type.isBuilding() && unit->getPlayer() != BWAPI::Broodwar->neutral() && !unit->isLifted()) 00401 { 00402 mBuildings.insert(unit); 00403 ++mPlayerBuildingNumbers[unit->getPlayer()]; 00404 00405 if(type.isResourceDepot()) 00406 { 00407 mResourceDepots.push_front(unit); 00408 if(mResourceDepots.size() > 1) 00409 std::sort(mResourceDepots.begin(), mResourceDepots.end(), boost::bind<bool>(&BaseClass::depotCompare, this, _1, _2)); 00410 } 00411 00412 if(!type.isResourceDepot() && type.supplyProvided() == 0 && !UnitHelper::isStaticDefense(type) && !type.isRefinery()) 00413 ++mTechBuildings; 00414 00415 updatePlayer(); 00416 } 00417 00418 if(type.isRefinery()) 00419 mRefineries.insert(unit); 00420 } 00421 00422 void BaseClass::removeUnit(Unit unit, Player playerToRemove, BWAPI::UnitType typeToRemove) 00423 { 00424 mRefineries.erase(unit); 00425 mGeysers.erase(unit); 00426 mMinerals.erase(unit); 00427 00428 std::set<Unit>::iterator it = mBuildings.find(unit); 00429 if(it != mBuildings.end()) 00430 { 00431 mBuildings.erase(it); 00432 --mPlayerBuildingNumbers[playerToRemove]; 00433 if(mPlayerBuildingNumbers[playerToRemove] == 0) 00434 mPlayerBuildingNumbers.erase(playerToRemove); 00435 00436 mResourceDepots.erase(std::remove(mResourceDepots.begin(), mResourceDepots.end(), unit), mResourceDepots.end()); 00437 00438 if(!typeToRemove.isResourceDepot() && typeToRemove.supplyProvided() == 0 && !UnitHelper::isStaticDefense(typeToRemove) && !typeToRemove.isRefinery()) 00439 --mTechBuildings; 00440 00441 updatePlayer(); 00442 } 00443 }
1.7.6.1