BWAPI
|
00001 #include "MacroManager.h" 00002 #include "PlayerTracker.h" 00003 #include "BuildOrderManager.h" 00004 #include "TaskManager.h" 00005 #include "UnitTracker.h" 00006 #include "ResourceTracker.h" 00007 00008 void MacroManagerClass::onBegin() 00009 { 00010 using namespace BWAPI::TechTypes; 00011 using namespace BWAPI::UpgradeTypes; 00012 00013 //Terran Tech 00014 mTechPriorityMap[Tank_Siege_Mode] = 110; 00015 mTechPriorityMap[Spider_Mines] = 100; 00016 mTechPriorityMap[Stim_Packs] = 90; 00017 mTechPriorityMap[Yamato_Gun] = 90; //Battlecruiser 00018 mTechPriorityMap[Cloaking_Field] = 85; 00019 mTechPriorityMap[Irradiate] = PlayerTracker::Instance().isEnemyRace(BWAPI::Races::Zerg) ? 89 : 0; 00020 mTechPriorityMap[EMP_Shockwave] = PlayerTracker::Instance().isEnemyRace(BWAPI::Races::Protoss) ? 99 : 0; 00021 mTechPriorityMap[Personnel_Cloaking] = 75; 00022 mTechPriorityMap[Healing] = 10; 00023 mTechPriorityMap[Lockdown] = 10; 00024 mTechPriorityMap[Restoration] = 10; 00025 mTechPriorityMap[Optical_Flare] = 5; 00026 00027 //Pre Researched 00028 mTechPriorityMap[Nuclear_Strike] = 0; 00029 mTechPriorityMap[Scanner_Sweep] = 0; 00030 mTechPriorityMap[Defensive_Matrix] = 0; 00031 00032 //Zerg Tech 00033 mTechPriorityMap[Burrowing] = 100; 00034 mTechPriorityMap[Consume] = 100; 00035 mTechPriorityMap[Dark_Swarm] = 100; 00036 mTechPriorityMap[Ensnare] = 100; 00037 mTechPriorityMap[Infestation] = 100; 00038 mTechPriorityMap[Lurker_Aspect] = 100; 00039 mTechPriorityMap[Parasite] = 100; 00040 mTechPriorityMap[Plague] = 100; 00041 mTechPriorityMap[Spawn_Broodlings] = 100; 00042 00043 //Protoss Tech 00044 mTechPriorityMap[Disruption_Web] = 0; 00045 mTechPriorityMap[Feedback] = 0; 00046 mTechPriorityMap[Hallucination] = 0; 00047 mTechPriorityMap[Maelstrom] = 0; //Dark Arcon freezes targeted units 00048 mTechPriorityMap[Mind_Control] = 0; 00049 mTechPriorityMap[Psionic_Storm] = 120; 00050 mTechPriorityMap[Recall] = 90; 00051 mTechPriorityMap[Stasis_Field] = 80; 00052 00053 //Pre Researched 00054 mTechPriorityMap[Archon_Warp] = 0; 00055 mTechPriorityMap[Dark_Archon_Meld] = 0; 00056 00057 //Terran Upgrades 00058 mUpgradePriorityMap[Terran_Infantry_Armor] = 85; 00059 mUpgradePriorityMap[Terran_Infantry_Weapons] = 90; 00060 mUpgradePriorityMap[Terran_Ship_Plating] = 65; 00061 mUpgradePriorityMap[Terran_Ship_Weapons] = 60; 00062 mUpgradePriorityMap[Terran_Vehicle_Plating] = 85; 00063 mUpgradePriorityMap[Terran_Vehicle_Weapons] = 90; 00064 mUpgradePriorityMap[U_238_Shells] = 85; //Marine Range 00065 mUpgradePriorityMap[Charon_Boosters] = 85; //Goliath Range 00066 mUpgradePriorityMap[Ion_Thrusters] = 95; //Vulture Speed 00067 mUpgradePriorityMap[Apollo_Reactor] = 40; //Wraith Energy 00068 mUpgradePriorityMap[Caduceus_Reactor] = 60; //Medic Energy 00069 mUpgradePriorityMap[Colossus_Reactor] = 40; //Battlecruiser Energy 00070 mUpgradePriorityMap[Moebius_Reactor] = 40; //Ghost Energy Upgrade 00071 mUpgradePriorityMap[Ocular_Implants] = 40; //Ghost Sight Range 00072 mUpgradePriorityMap[Titan_Reactor] = 70; //Science Vessel Energy 00073 00074 //Zerg Upgrades 00075 mUpgradePriorityMap[Ventral_Sacs] = 80; //Overlord drop 00076 mUpgradePriorityMap[Zerg_Carapace] = 95; 00077 mUpgradePriorityMap[Zerg_Flyer_Attacks] = 100; 00078 mUpgradePriorityMap[Zerg_Flyer_Carapace] = 95; 00079 mUpgradePriorityMap[Zerg_Melee_Attacks] = 100; 00080 mUpgradePriorityMap[Zerg_Missile_Attacks] = 100; 00081 mUpgradePriorityMap[Metabolic_Boost] = 100; //Zergling Movement Speed 00082 mUpgradePriorityMap[Adrenal_Glands] = 100; //Zergling Attack Speed 00083 mUpgradePriorityMap[Anabolic_Synthesis] = 100; //Ultralisk Speed 00084 mUpgradePriorityMap[Antennae] = 100; //Overlord Sight Range 00085 mUpgradePriorityMap[Chitinous_Plating] = 100; //Ultralisk +2 armor 00086 mUpgradePriorityMap[Gamete_Meiosis] = 100; // Zerg queen Energy 00087 mUpgradePriorityMap[Grooved_Spines] = 100; // Hydralisk range 00088 mUpgradePriorityMap[Metasynaptic_Node] = 100; // Defiler Energy 00089 mUpgradePriorityMap[Muscular_Augments] = 100; //Hydralisk Speed 00090 mUpgradePriorityMap[Pneumatized_Carapace] = 100; //Overlord Speed 00091 00092 //Protoss Upgrades 00093 mUpgradePriorityMap[Protoss_Air_Weapons] = 0; 00094 mUpgradePriorityMap[Protoss_Air_Armor] = 0; 00095 mUpgradePriorityMap[Protoss_Ground_Weapons] = 100; 00096 mUpgradePriorityMap[Protoss_Plasma_Shields] = 70; 00097 mUpgradePriorityMap[Protoss_Ground_Armor] = 95; 00098 mUpgradePriorityMap[Reaver_Capacity] = 85; //More scarabs 00099 mUpgradePriorityMap[Scarab_Damage] = 100; //Increase Reaver Scarab Damage 00100 mUpgradePriorityMap[Singularity_Charge] = 110; //Dragoon Range 00101 mUpgradePriorityMap[Carrier_Capacity] = 110; //MOAR INTERCEPTORS! 00102 mUpgradePriorityMap[Apial_Sensors] = 100; //Scout Sight 00103 mUpgradePriorityMap[Argus_Jewel] = 100; //Cosair Energy 00104 mUpgradePriorityMap[Argus_Talisman] = 100; //Dark Archon Energy 00105 mUpgradePriorityMap[Gravitic_Boosters] = 80; //Observer Speed 00106 mUpgradePriorityMap[Gravitic_Drive] = 97; //Shuttle Speed 00107 mUpgradePriorityMap[Gravitic_Thrusters] = 100; //Scout Speed 00108 mUpgradePriorityMap[Khaydarin_Amulet] = 90; //High Templar Energy 00109 mUpgradePriorityMap[Khaydarin_Core] = 80; //Arbitor Energy 00110 mUpgradePriorityMap[Leg_Enhancements] = 110; //Zealot Speed Upgrades 00111 mUpgradePriorityMap[Sensor_Array] = 60; // Observer Sight 00112 } 00113 00114 void MacroManagerClass::update() 00115 { 00116 updateTaskLists(); 00117 00118 if(BuildOrderManager::Instance().getOrder(Order::MacroArmyProduction)) 00119 { 00120 updateObserverProduction(); 00121 updateUnitProduction(); 00122 } 00123 00124 if(BuildOrderManager::Instance().getOrder(Order::MacroProductionFacilities)) 00125 updateProductionProduction(); 00126 00127 if(BuildOrderManager::Instance().getOrder(Order::MacroCanTech)) 00128 createTechItems(); 00129 updateTech(); 00130 00131 /*int y = 60; 00132 for each(std::pair<MacroItem, TaskPointer> item in mTechItems) 00133 { 00134 if(item.second->inProgress()) 00135 BWAPI::Broodwar->drawTextScreen(5, y, "%s : (In Progress)", item.first.getDebugInfo().c_str()); 00136 else 00137 BWAPI::Broodwar->drawTextScreen(5, y, "%s", item.first.getDebugInfo().c_str()); 00138 00139 y += 10; 00140 }*/ 00141 } 00142 00143 void MacroManagerClass::updateUnitProduction() 00144 { 00145 TrainType trainType = TrainType::Normal; 00146 00147 int mineral = ResourceTracker::Instance().availableMineralAtTime(BWAPI::Broodwar->getFrameCount() + 450); 00148 int gas = ResourceTracker::Instance().availableGasAtTime(BWAPI::Broodwar->getFrameCount() + 450); 00149 00150 double LowMineralRatio = gas == 0 ? 1 : double(mineral)/double(gas); 00151 double LowGasRatio = mineral == 0 ? 1 : double(gas)/double(mineral); 00152 00153 if(std::max(gas, mineral) > 500) 00154 { 00155 if(LowMineralRatio < 0.4) 00156 trainType = TrainType::LowMineral; 00157 else if(LowGasRatio < 0.4) 00158 trainType = TrainType::LowGas; 00159 } 00160 00161 std::list<UnitToProduce> unitsToProduce; 00162 if(trainType == TrainType::LowMineral) 00163 unitsToProduce = mLowMineralUnits; 00164 else if(trainType == TrainType::LowGas) 00165 unitsToProduce = mLowGasUnits; 00166 else if(trainType == TrainType::Normal) 00167 unitsToProduce = mNormalUnits; 00168 00169 for(std::list<UnitToProduce>::iterator it = unitsToProduce.begin(); it != unitsToProduce.end();) 00170 { 00171 if(!hasRequirements(it->getUnitType()) || !it->canBuildUnit()) 00172 unitsToProduce.erase(it++); 00173 else 00174 ++it; 00175 } 00176 00177 if(trainType != TrainType::Normal) 00178 { 00179 std::set<BWAPI::UnitType> unitsWeAreProducing; 00180 for each(UnitToProduce unit in unitsToProduce) 00181 { 00182 unitsWeAreProducing.insert(unit.getUnitType()); 00183 } 00184 00185 for(std::list<std::pair<TaskPointer, BWAPI::UnitType>>::reverse_iterator it = mUnitProduce.rbegin(); it != mUnitProduce.rend(); ++it) 00186 { 00187 if(!it->first->inProgress() && unitsWeAreProducing.count(it->second) == 0) 00188 { 00189 it->first->cancel(); 00190 mUnitProduce.erase( --(it.base()) ); 00191 break; 00192 } 00193 } 00194 } 00195 00196 // cancel and non dispatched unit that is normal but not this type 00197 00198 std::map<BWAPI::UnitType, int> totalPerProductionBuilding; 00199 std::map<BWAPI::UnitType, int> UnitTotals; 00200 std::map<BWAPI::UnitType, std::map<BWAPI::UnitType, int>> UnitToBuilding; 00201 std::map<BWAPI::UnitType, int> totalWeightPerBuilding; 00202 00203 // TODO: try to maintain some sort of balance between buildings 00204 00205 for each(UnitToProduce unit in unitsToProduce) 00206 { 00207 int plannedTotalUnit = UnitTracker::Instance().selectAllUnits(unit.getUnitType()).size(); 00208 totalPerProductionBuilding[unit.getUnitType().whatBuilds().first] += plannedTotalUnit; 00209 UnitTotals[unit.getUnitType()] += plannedTotalUnit; 00210 00211 totalWeightPerBuilding[unit.getUnitType().whatBuilds().first] += unit.getUnitWeight(); 00212 UnitToBuilding[unit.getUnitType().whatBuilds().first][unit.getUnitType()] = unit.getUnitWeight(); 00213 } 00214 00215 for each(std::pair<BWAPI::UnitType, int> totalPair in totalPerProductionBuilding) 00216 { 00217 int buildings = UnitTracker::Instance().selectAllUnits(totalPair.first).size() * 2; 00218 int queued = mTasksPerProductionType[totalPair.first].size(); 00219 int freeProductionBuildings = buildings - queued; 00220 if(freeProductionBuildings > 0) 00221 { 00222 BWAPI::UnitType chosenUnit = BWAPI::UnitTypes::None; 00223 double biggestDifference = std::numeric_limits<double>::max(); 00224 for each(std::pair<BWAPI::UnitType, int> producePair in UnitToBuilding[totalPair.first]) 00225 { 00226 double neededRatio = double(producePair.second) / double(totalWeightPerBuilding[totalPair.first]); 00227 double currentRatio = 0; 00228 if(totalPair.second != 0) 00229 currentRatio = double(UnitTotals[producePair.first]) / double(totalPair.second); 00230 00231 double difference = currentRatio - neededRatio; 00232 00233 if(difference < biggestDifference) 00234 { 00235 biggestDifference = difference; 00236 chosenUnit = producePair.first; 00237 } 00238 } 00239 00240 if(chosenUnit != BWAPI::UnitTypes::None) 00241 mUnitProduce.push_back(std::make_pair(TaskManager::Instance().build(chosenUnit, TaskType::Army), chosenUnit)); 00242 00243 freeProductionBuildings--; 00244 } 00245 } 00246 } 00247 00248 bool macroCompare(const MacroItem &first, const MacroItem &second) 00249 { 00250 return first.getPriority() > second.getPriority(); 00251 } 00252 00253 void MacroManagerClass::onChangeBuild() 00254 { 00255 mNormalUnits.clear(); 00256 mLowMineralUnits.clear(); 00257 mLowGasUnits.clear(); 00258 00259 mNormalUnits = BuildOrderManager::Instance().getCurrentBuild().getUnitsToProduce(); 00260 00261 for each(UnitToProduce unit in mNormalUnits) 00262 { 00263 double mineralToGasRatio = unit.getUnitType().gasPrice() == 0 ? 1 : double(unit.getUnitType().mineralPrice())/double(unit.getUnitType().gasPrice()); 00264 double gasToMineralRatio = unit.getUnitType().mineralPrice() == 0 ? 1 : double(unit.getUnitType().gasPrice())/double(unit.getUnitType().mineralPrice()); 00265 00266 if(gasToMineralRatio < 0.4) 00267 mLowGasUnits.push_back(unit); 00268 else if(mineralToGasRatio < 0.4) 00269 mLowMineralUnits.push_back(unit); 00270 } 00271 00272 for(std::list<std::pair<MacroItem, TaskPointer>>::iterator it = mTechItems.begin(); it != mTechItems.end(); ++it) 00273 { 00274 if(!it->second->inProgress()) 00275 it->second->cancel(); 00276 } 00277 mTechItems.clear(); 00278 mTechItemsToCreate.clear(); 00279 00280 updateTaskLists(); 00281 00282 std::list<UnitToProduce> normalWithExtra = mNormalUnits; 00283 00284 if(BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Protoss) 00285 { 00286 normalWithExtra.push_back(UnitToProduce(BWAPI::UnitTypes::Protoss_Observer, 1, 115)); 00287 normalWithExtra.push_back(UnitToProduce(BWAPI::UnitTypes::Protoss_Photon_Cannon, 1, 95)); 00288 } 00289 00290 std::set<BWAPI::TechType> techSet; 00291 std::set<BWAPI::UpgradeType> upgradeSet; 00292 00293 for each(UnitToProduce unit in normalWithExtra) 00294 { 00295 for each(BWAPI::UnitType type in getNeededUnits(unit.getUnitType())) 00296 { 00297 mTechItemsToCreate.push_back(MacroItem(type, unit.getPriority())); 00298 } 00299 00300 for each(BWAPI::TechType tech in unit.getUnitType().abilities()) 00301 { 00302 techSet.insert(tech); 00303 } 00304 00305 for each(BWAPI::UpgradeType upgrade in unit.getUnitType().upgrades()) 00306 { 00307 upgradeSet.insert(upgrade); 00308 } 00309 00310 if(unit.getUnitType() == BWAPI::UnitTypes::Protoss_Reaver) 00311 { 00312 // Scarab damage doesn't pick up under its upgrades 00313 upgradeSet.insert(BWAPI::UpgradeTypes::Scarab_Damage); 00314 00315 // Reaver is usually used with shuttle, speed upgrade will probably help 00316 upgradeSet.insert(BWAPI::UpgradeTypes::Gravitic_Drive); 00317 } 00318 else if(unit.getUnitType() == BWAPI::UnitTypes::Protoss_Carrier) 00319 upgradeSet.insert(BWAPI::UpgradeTypes::Protoss_Air_Weapons); 00320 } 00321 00322 for each(BWAPI::TechType tech in techSet) 00323 { 00324 if(mTechPriorityMap[tech] < 30) 00325 continue; 00326 00327 mTechItemsToCreate.push_back(MacroItem(tech, mTechPriorityMap[tech])); 00328 00329 for each(BWAPI::UnitType type in getNeededUnits(tech)) 00330 { 00331 mTechItemsToCreate.push_back(MacroItem(type, mTechPriorityMap[tech])); 00332 } 00333 } 00334 00335 for each(BWAPI::UpgradeType upgrade in upgradeSet) 00336 { 00337 if(mUpgradePriorityMap[upgrade] < 30) 00338 continue; 00339 00340 for(int i = 1; i <= upgrade.maxRepeats(); ++i) 00341 { 00342 int priority = mUpgradePriorityMap[upgrade] - ((i-1)*10); 00343 mTechItemsToCreate.push_back(MacroItem(upgrade, i, priority)); 00344 00345 for each(BWAPI::UnitType type in getNeededUnits(upgrade, i)) 00346 { 00347 mTechItemsToCreate.push_back(MacroItem(type, priority)); 00348 } 00349 } 00350 } 00351 00352 mTechItemsToCreate.sort(macroCompare); 00353 00354 //remove duplicates now so the highest is kept 00355 std::set<BWAPI::UnitType> unitSet; 00356 for(std::list<MacroItem>::iterator it = mTechItemsToCreate.begin(); it != mTechItemsToCreate.end();) 00357 { 00358 if(it->isUnitType()) 00359 { 00360 if(unitSet.count(it->getUnitType()) != 0) 00361 { 00362 mTechItemsToCreate.erase(it++); 00363 continue; 00364 } 00365 else 00366 unitSet.insert(it->getUnitType()); 00367 } 00368 00369 ++it; 00370 } 00371 00372 createTechItems(); 00373 } 00374 00375 void MacroManagerClass::updateObserverProduction() 00376 { 00377 if(BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Protoss) 00378 { 00379 if(hasRequirements(BWAPI::UnitTypes::Protoss_Observer)) 00380 { 00381 TaskType type = TaskType::Defense; 00382 int num = getPlannedTotal(BWAPI::UnitTypes::Protoss_Observer); 00383 if(num > 3) 00384 return; 00385 else if(num == 0) 00386 type = TaskType::MacroUrgent; 00387 else if(num == 1) 00388 type = TaskType::Army; 00389 00390 // Cancel and recreate if its the wrong type incase it was create when we had more but are now low on observers 00391 if(!mObserver || mObserver->inProgress() || mObserver->hasEnded() || mObserver->getType() != type) 00392 { 00393 if(mObserver && !mObserver->inProgress()) 00394 mObserver->cancel(); 00395 00396 mObserver = TaskManager::Instance().build(BWAPI::UnitTypes::Protoss_Observer, type); 00397 } 00398 } 00399 } 00400 } 00401 00402 void MacroManagerClass::updateProductionProduction() 00403 { 00404 for each(UnitToProduce unit in mNormalUnits) 00405 { 00406 if(hasRequirements(unit.getUnitType()) && unit.canBuildFactory()) 00407 { 00408 BWAPI::UnitType whatBuilds = unit.getUnitType().whatBuilds().first; 00409 if(whatBuilds == BWAPI::UnitTypes::Zerg_Larva) 00410 whatBuilds = BWAPI::UnitTypes::Zerg_Hatchery; 00411 00412 bool unstartedBuild = false; 00413 for each(TaskPointer task in mTasksPerProducedType[whatBuilds]) 00414 { 00415 if(!task->inProgress()) 00416 unstartedBuild = true; 00417 } 00418 if(unstartedBuild) 00419 continue; 00420 00421 int idleOfThis = 0; 00422 for each(Unit building in UnitTracker::Instance().selectAllUnits(whatBuilds)) 00423 { 00424 if(building->isCompleted() && !building->isTraining()) 00425 ++idleOfThis; 00426 } 00427 00428 if(idleOfThis == 0) 00429 TaskManager::Instance().build(whatBuilds, TaskType::MacroExtraProduction); 00430 } 00431 } 00432 } 00433 bool MacroManagerClass::hasRequirements(BWAPI::UnitType type) 00434 { 00435 if(BWAPI::Broodwar->self()->completedUnitCount(type.whatBuilds().first) == 0) 00436 return false; 00437 00438 for(std::map<BWAPI::UnitType, int>::const_iterator it = type.requiredUnits().begin(); it != type.requiredUnits().end(); ++it) 00439 { 00440 if(BWAPI::Broodwar->self()->completedUnitCount(it->first) == 0) 00441 return false; 00442 } 00443 00444 return true; 00445 } 00446 00447 bool MacroManagerClass::hasRequirements(BWAPI::TechType type) 00448 { 00449 if(BWAPI::Broodwar->self()->completedUnitCount(type.whatResearches()) == 0) 00450 return false; 00451 00452 return true; 00453 } 00454 00455 bool MacroManagerClass::hasRequirements(BWAPI::UpgradeType type, int level) 00456 { 00457 if(BWAPI::Broodwar->self()->completedUnitCount(type.whatUpgrades()) == 0) 00458 return false; 00459 00460 if(level != 1 && BWAPI::Broodwar->self()->getUpgradeLevel(type) != (level - 1)) 00461 return false; 00462 00463 if(level > 1) 00464 { 00465 if((type == BWAPI::UpgradeTypes::Protoss_Ground_Weapons || type == BWAPI::UpgradeTypes::Protoss_Ground_Armor) && BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Protoss_Templar_Archives) == 0) 00466 return false; 00467 else if(type == BWAPI::UpgradeTypes::Protoss_Plasma_Shields && BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Protoss_Cybernetics_Core) == 0) 00468 return false; 00469 else if((type == BWAPI::UpgradeTypes::Protoss_Air_Armor || type == BWAPI::UpgradeTypes::Protoss_Air_Weapons) && BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Protoss_Fleet_Beacon) == 0) 00470 return false; 00471 } 00472 00473 return true; 00474 } 00475 00476 std::set<BWAPI::UnitType> MacroManagerClass::getNeededUnits(BWAPI::UnitType type) 00477 { 00478 std::set<BWAPI::UnitType> neededUnits; 00479 00480 BWAPI::UnitType whatBuilds = type.whatBuilds().first; 00481 if(whatBuilds == BWAPI::UnitTypes::Zerg_Larva) 00482 whatBuilds = BWAPI::UnitTypes::Zerg_Hatchery; 00483 00484 if(!isPlanningUnit(whatBuilds)) 00485 neededUnits.insert(whatBuilds); 00486 00487 for(std::map<BWAPI::UnitType, int>::const_iterator it = type.requiredUnits().begin(); it != type.requiredUnits().end(); ++it) 00488 { 00489 if(it->first == BWAPI::UnitTypes::Zerg_Larva) 00490 continue; 00491 00492 if(!isPlanningUnit(it->first)) 00493 neededUnits.insert(it->first); 00494 00495 } 00496 00497 addNeeded(neededUnits); 00498 00499 return neededUnits; 00500 } 00501 00502 std::set<BWAPI::UnitType> MacroManagerClass::getNeededUnits(BWAPI::TechType type) 00503 { 00504 std::set<BWAPI::UnitType> neededUnits; 00505 if(!isPlanningUnit(type.whatResearches())) 00506 neededUnits.insert(type.whatResearches()); 00507 00508 addNeeded(neededUnits); 00509 00510 return neededUnits; 00511 } 00512 00513 std::set<BWAPI::UnitType> MacroManagerClass::getNeededUnits(BWAPI::UpgradeType type, int level) 00514 { 00515 std::set<BWAPI::UnitType> neededUnits; 00516 if(!isPlanningUnit(type.whatUpgrades())) 00517 neededUnits.insert(type.whatUpgrades()); 00518 00519 if(level > 1) 00520 { 00521 if((type == BWAPI::UpgradeTypes::Protoss_Ground_Weapons || type == BWAPI::UpgradeTypes::Protoss_Ground_Armor) && !isPlanningUnit(BWAPI::UnitTypes::Protoss_Templar_Archives)) 00522 neededUnits.insert(BWAPI::UnitTypes::Protoss_Templar_Archives); 00523 else if(type == BWAPI::UpgradeTypes::Protoss_Plasma_Shields && !isPlanningUnit(BWAPI::UnitTypes::Protoss_Cybernetics_Core)) 00524 neededUnits.insert(BWAPI::UnitTypes::Protoss_Cybernetics_Core); 00525 else if((type == BWAPI::UpgradeTypes::Protoss_Air_Armor || type == BWAPI::UpgradeTypes::Protoss_Air_Weapons) && !isPlanningUnit(BWAPI::UnitTypes::Protoss_Fleet_Beacon)) 00526 neededUnits.insert(BWAPI::UnitTypes::Protoss_Fleet_Beacon); 00527 } 00528 00529 addNeeded(neededUnits); 00530 00531 return neededUnits; 00532 } 00533 00534 void MacroManagerClass::addNeeded(std::set<BWAPI::UnitType> &neededUnits) 00535 { 00536 bool addedUnits = false; 00537 std::set<BWAPI::UnitType> tempList; 00538 for each(BWAPI::UnitType type in neededUnits) 00539 { 00540 BWAPI::UnitType whatBuilds = type.whatBuilds().first; 00541 if(whatBuilds == BWAPI::UnitTypes::Zerg_Larva) 00542 whatBuilds = BWAPI::UnitTypes::Zerg_Hatchery; 00543 00544 if(!isPlanningUnit(whatBuilds) && neededUnits.count(whatBuilds) == 0) 00545 { 00546 addedUnits = true; 00547 tempList.insert(whatBuilds); 00548 } 00549 00550 for(std::map<BWAPI::UnitType, int>::const_iterator it = type.requiredUnits().begin(); it != type.requiredUnits().end(); ++it) 00551 { 00552 if (it->first == BWAPI::UnitTypes::Zerg_Larva) 00553 continue; 00554 00555 if(!isPlanningUnit(it->first) && neededUnits.count(it->first) == 0) 00556 { 00557 addedUnits = true; 00558 tempList.insert(it->first); 00559 } 00560 } 00561 } 00562 00563 neededUnits.insert(tempList.begin(), tempList.end()); 00564 00565 if(addedUnits) 00566 addNeeded(neededUnits); 00567 } 00568 00569 int MacroManagerClass::getPlannedCount(BWAPI::UnitType unitType) 00570 { 00571 int count = 0; 00572 for each(TaskPointer task in mTasksPerProducedType[unitType]) 00573 { 00574 if(!task->inProgress()) 00575 ++count; 00576 } 00577 00578 return count; 00579 } 00580 00581 int MacroManagerClass::getPlannedTotal(BWAPI::UnitType unitType) 00582 { 00583 return getPlannedCount(unitType) + BWAPI::Broodwar->self()->allUnitCount(unitType); 00584 } 00585 00586 bool MacroManagerClass::isPlanningUnit(BWAPI::UnitType unitType) 00587 { 00588 return getPlannedTotal(unitType) != 0; 00589 } 00590 00591 int MacroManagerClass::getPlannedCount(BWAPI::TechType techType) 00592 { 00593 int count = 0; 00594 for each(TaskPointer task in mTasksPerTechType[techType]) 00595 { 00596 if(!task->inProgress()) 00597 ++count; 00598 } 00599 00600 return count; 00601 } 00602 00603 int MacroManagerClass::getPlannedTotal(BWAPI::TechType techType) 00604 { 00605 return getPlannedCount(techType) + (BWAPI::Broodwar->self()->hasResearched(techType) ? 1 : 0); 00606 } 00607 00608 bool MacroManagerClass::isPlanningTech(BWAPI::TechType techType) 00609 { 00610 return getPlannedTotal(techType) != 0; 00611 } 00612 00613 int MacroManagerClass::getPlannedCount(BWAPI::UpgradeType upgradeType, int level) 00614 { 00615 int count = 0; 00616 for each(TaskPointer task in mTasksPerUpgradeType[upgradeType][level]) 00617 { 00618 if(!task->inProgress()) 00619 ++count; 00620 } 00621 00622 return count; 00623 } 00624 00625 int MacroManagerClass::getPlannedTotal(BWAPI::UpgradeType upgradeType, int level) 00626 { 00627 return getPlannedCount(upgradeType, level) + (BWAPI::Broodwar->self()->getUpgradeLevel(upgradeType) >= level ? 1 : 0); 00628 } 00629 00630 bool MacroManagerClass::isPlanningUpgrade(BWAPI::UpgradeType upgradeType, int level) 00631 { 00632 return getPlannedTotal(upgradeType, level) != 0; 00633 } 00634 00635 void MacroManagerClass::updateTaskLists() 00636 { 00637 for(std::list<std::pair<TaskPointer, BWAPI::UnitType>>::iterator it = mUnitProduce.begin(); it != mUnitProduce.end();) 00638 { 00639 if(it->first->hasEnded()) mUnitProduce.erase(it++); 00640 else ++it; 00641 } 00642 00643 for(std::map<BWAPI::UnitType, std::list<TaskPointer>>::iterator it = mTasksPerProductionType.begin(); it != mTasksPerProductionType.end(); ++it) 00644 { 00645 for(std::list<TaskPointer>::iterator it2 = it->second.begin(); it2 != it->second.end();) 00646 { 00647 if((*it2)->hasEnded()) it->second.erase(it2++); 00648 else ++it2; 00649 } 00650 } 00651 00652 for(std::map<BWAPI::UnitType, std::list<TaskPointer>>::iterator it = mTasksPerProducedType.begin(); it != mTasksPerProducedType.end(); ++it) 00653 { 00654 for(std::list<TaskPointer>::iterator it2 = it->second.begin(); it2 != it->second.end();) 00655 { 00656 if((*it2)->hasEnded()) it->second.erase(it2++); 00657 else ++it2; 00658 } 00659 } 00660 00661 for(std::map<BWAPI::TechType, std::list<TaskPointer>>::iterator it = mTasksPerTechType.begin(); it != mTasksPerTechType.end(); ++it) 00662 { 00663 for(std::list<TaskPointer>::iterator it2 = it->second.begin(); it2 != it->second.end();) 00664 { 00665 if((*it2)->hasEnded()) it->second.erase(it2++); 00666 else ++it2; 00667 } 00668 } 00669 00670 for(std::map<BWAPI::UpgradeType, std::map<int, std::list<TaskPointer>>>::iterator it = mTasksPerUpgradeType.begin(); it != mTasksPerUpgradeType.end(); ++it) 00671 { 00672 for(std::map<int, std::list<TaskPointer>>::iterator it1 = it->second.begin(); it1 != it->second.end(); ++it1) 00673 { 00674 for(std::list<TaskPointer>::iterator it2 = it1->second.begin(); it2 != it1->second.end();) 00675 { 00676 if((*it2)->hasEnded()) it1->second.erase(it2++); 00677 else ++it2; 00678 } 00679 } 00680 } 00681 } 00682 00683 void MacroManagerClass::updateTech() 00684 { 00685 for(std::list<std::pair<MacroItem, TaskPointer>>::iterator it = mTechItems.begin(); it != mTechItems.end();) 00686 { 00687 // if its ended or something else is creating this, cancel it to avoid duplicates 00688 if(it->second->hasEnded() || (!it->second->inProgress() && it->first.inProgress())) 00689 { 00690 it->second->cancel(); 00691 mTechItems.erase(it++); 00692 } 00693 else 00694 ++it; 00695 } 00696 } 00697 00698 void MacroManagerClass::onBuildTask(TaskPointer task, BWAPI::UnitType unitType) 00699 { 00700 mTasksPerProductionType[unitType.whatBuilds().first].push_back(task); 00701 mTasksPerProducedType[unitType].push_back(task); 00702 } 00703 00704 void MacroManagerClass::onTechTask(TaskPointer task,BWAPI::TechType techType) 00705 { 00706 mTasksPerProductionType[techType.whatResearches()].push_back(task); 00707 mTasksPerTechType[techType].push_back(task); 00708 } 00709 00710 void MacroManagerClass::onUpgradeTask(TaskPointer task, BWAPI::UpgradeType upgradeType, int level) 00711 { 00712 mTasksPerProductionType[upgradeType.whatUpgrades()].push_back(task); 00713 mTasksPerUpgradeType[upgradeType][level].push_back(task); 00714 } 00715 00716 void MacroManagerClass::createTechItems() 00717 { 00718 if(!mTechItemsToCreate.empty() && BuildOrderManager::Instance().getOrder(Order::MacroCanTech)) 00719 { 00720 for(std::list<MacroItem>::iterator it = mTechItemsToCreate.begin(); it != mTechItemsToCreate.end(); ++it) 00721 { 00722 TaskPointer task = it->createTask(TaskType::MacroTech); 00723 if(task) 00724 mTechItems.push_back(std::make_pair(*it, task)); 00725 } 00726 00727 mTechItemsToCreate.clear(); 00728 } 00729 } 00730 00731 bool MacroItem::inProgress() const 00732 { 00733 if(isUnitType()) 00734 return MacroManager::Instance().getPlannedTotal(mUnit) > 1; 00735 else if(isTechType()) 00736 return MacroManager::Instance().getPlannedTotal(mTech) > 1; 00737 else if(isUpgradeType()) 00738 return MacroManager::Instance().getPlannedTotal(mUpgrade, mLevel) > 1; 00739 else 00740 return true; 00741 } 00742 00743 TaskPointer MacroItem::createTask(TaskType taskType) const 00744 { 00745 if(isUnitType()) 00746 return TaskManager::Instance().build(mUnit, taskType); 00747 else if(isTechType()) 00748 return TaskManager::Instance().research(mTech, taskType); 00749 else if(isUpgradeType()) 00750 return TaskManager::Instance().upgrade(mUpgrade, mLevel, taskType); 00751 else 00752 return TaskPointer(); 00753 }