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