BWAPI
BasicAIModule/source/Strategizer.cpp
Go to the documentation of this file.
00001 /*
00002 *  Strategizer.cpp
00003 */
00004 #include "Strategizer.h"
00005 #include "IncludeAllManagers.h"
00006 #include "IncludeAllUnitAgents.h"
00007 #include "TacticalBuildingPlacer.h"
00008 #include "GameEvent.h"
00009 #include "Common.h"
00010 
00011 #include <BWAPI.h>
00012 
00013 using namespace BWAPI;
00014 
00015 using std::pair;
00016 
00017 
00018 /* 
00019 *  update()
00020 *
00021 *  Called by the AI module on each frame
00022 */
00023 void Strategizer::update()
00024 {
00025         // Draw "GUI"
00026         Broodwar->drawTextScreen(300, 0, "\x17 APM=%d", Broodwar->getAPM());
00027         Broodwar->drawTextScreen(300,10, "\x17 FPS=%d", Broodwar->getFPS());
00028         TacticalBuildingPlacer::instance().update(); // draw reserved map
00029         draw();  // draw managers
00030 
00031         if (Broodwar->getFrameCount() % 10 == 0)
00032         {
00033                 // Find new units, remove inactive ones
00034                 updateUnitAgentMap();
00035         
00036                 // Remap Agents to Managers (bid war)
00037                 updateAgentManagerMap();        
00038 
00039                 // Give Agents to updated Managers
00040                 redistributeAgents();
00041         
00042                 // Let Managers manager
00043                 updateManagers();
00044 
00045         if( checkForfeit() )
00046         {
00047             Broodwar->sendText("Surrendering match...");
00048             Broodwar->leaveGame();
00049         }
00050         }
00051 }
00052 /* 
00053 *  onMatchStart()
00054 *
00055 *  Called by the AI module when a new match begins
00056 */
00057 void Strategizer::onMatchStart()
00058 {
00059     buildManager.onMatchStart();
00060     combatManager.onMatchStart();
00061     gasManager.onMatchStart();
00062     productionManager.onMatchStart();
00063     resourceManager.onMatchStart();
00064     scoutManager.onMatchStart();
00065     supplyManager.onMatchStart();
00066 
00067         // Barracks do not ever leave idle state (for now), so 1 per unit type
00068         // Marines
00069         buildManager.build(UnitTypes::Terran_Barracks);
00070         buildManager.build(UnitTypes::Terran_Marine);
00071         
00072         // Marines
00073         buildManager.build(UnitTypes::Terran_Barracks);
00074         buildManager.build(UnitTypes::Terran_Marine);
00075 
00076         // Firebat
00077         buildManager.build(UnitTypes::Terran_Barracks);
00078         buildManager.build(UnitTypes::Terran_Firebat);
00079 
00080         // Expand
00081         buildManager.build(UnitTypes::Terran_Command_Center);
00082 
00083         // Vultures
00084         buildManager.build(UnitTypes::Terran_Factory);
00085         buildManager.build(UnitTypes::Terran_Vulture);
00086         buildManager.build(UnitTypes::Terran_Factory);
00087         buildManager.build(UnitTypes::Terran_Vulture);
00088 
00089         buildManager.build(UnitTypes::Terran_Battlecruiser);
00090 
00094 }
00095 
00096 /* 
00097 *  onEvent()
00098 *
00099 */
00100 void Strategizer::onEvent(GameEvent &e)
00101 {
00102 }
00103 
00104 /*
00105 * onMatchEnd()
00106 *
00107 * Called by the AI module when a match ends
00108 */
00109 void Strategizer::onMatchEnd(bool isWinner)
00110 {
00111         // Cleanup agents
00112         // Note: this is the safe way to do this
00113         // erasing by iterator invalidates the iterator, 
00114         // so if we just use map.erase(it), the loop gets screwed up, 
00115         // postfix increment inside the loop keeps the 
00116         // iterator valid as it traverses the map
00117         // Source: Effective STL (Scott Meyers - 2001)
00118         AgentManagerMapIter it  = agentManagerMap.begin();
00119         AgentManagerMapIter end = agentManagerMap.end();
00120         for(; it != end;)
00121         {
00122                 Agent* agent = it->first;
00123                 agentManagerMap.erase(it++);
00124                 delete agent;
00125         }
00126 }
00127 
00128 
00129 /*
00130 *  updateUnitAgentMap()
00131 *
00132 *  Maps new friendly units to agents
00133 */
00134 void Strategizer::updateUnitAgentMap()
00135 {
00136         // Create agents for newly found, friendly units.  Delete dead ones
00137     UnitSet units = Broodwar->self()->getUnits();
00138         for (UnitSetIter unit = units.begin(); unit != units.end(); ++unit)
00139         {
00140                 Unit *u = *unit;
00141 
00142                 // Only construct active units
00143                 if (!u->isCompleted())  // TODO: Determine a more robust conditional
00144                 {
00145                         continue;
00146                 }
00147                 // New agent
00148                 if (unitAgentMap[u] == NULL)
00149                 {
00150                         UnitType ut = u->getType();
00151                         Agent *a = NULL;
00152 
00153                         if (ut.isWorker())                              
00154                                 a = new SCVAgent(*u);
00155                         else if (ut.isResourceDepot())  
00156                                 a = new CommandCenterAgent(*u);
00157                         else if (ut == UnitTypes::Terran_Refinery)
00158                                 a = new RefineryAgent(*u);
00159                         else if (ut == UnitTypes::Terran_Barracks) 
00160                                 a = new BarracksAgent(*u);
00161                         else if (ut == UnitTypes::Terran_Marine) 
00162                                 a = new MarineAgent(*u);
00163                         else if (ut == UnitTypes::Terran_Firebat) 
00164                                 a = new FirebatAgent(*u);
00165                         else if (ut == UnitTypes::Terran_Medic)
00166                                 a = new MedicAgent(*u);
00167                         else if (ut.isBuilding())
00168                                 a = new StructureAgent(*u);
00169                         else
00170                                 a = new ActorAgent(*u);
00171 
00172                         if (a != NULL)
00173                                 unitAgentMap[u] = a;
00174                 }
00175         }
00176 
00177         // TODO: Cleanup inactive agents
00178 }
00179 
00180 
00181 /*
00182 *  updateAgentManagerMap()
00183 *
00184 *  Maps agents to managers based upon which managers
00185 *  need the agent
00186 */
00187 void Strategizer::updateAgentManagerMap()
00188 {
00189         // Normally, we would shuffle Units around by bid here..
00190         for (UnitAgentMapIter agent = unitAgentMap.begin(); agent != unitAgentMap.end(); agent++)
00191         {
00192                 Agent   *a  = (*agent).second;
00193                 UnitType ut = a->getUnit().getType();
00194 
00195                 // if Agent hasn't been assigned a manager
00196                 if (agentManagerMap[a] == NULL) {
00197 
00198                         // Resources:
00199                         // SCV -> ResourceManager
00200                         if (a->getUnit().getType().isWorker())
00201                                 agentManagerMap[a] = &buildManager;
00202                         // Refinery -> Gas Manager
00203                         else if (ut.isRefinery())
00204                                 agentManagerMap[a] = &gasManager;
00205 
00206                         // Command Center -> Production Manager
00207             // TODO: this is the wrong ProductionManager
00208             // we want to assign it to the one in BuildManager
00209                         //
00210                         // Left here until we find a way to generate SCVs in BM.
00211                         // -mike
00212                         else if (ut.isResourceDepot())
00213                                 agentManagerMap[a] = &productionManager;
00214 
00215                         // Army:
00216                         // Barracks -> BuildManager
00217                         else if (ut == UnitTypes::Terran_Barracks)
00218                                 agentManagerMap[a] = &buildManager;
00219                         else if (ut.isBuilding())
00220                                 agentManagerMap[a] = &buildManager;
00221 
00222                         // Combat:
00223                         // Marines -> CombatManager
00224                         else if (ut == UnitTypes::Terran_Marine)
00225                                 agentManagerMap[a] = &combatManager;
00226                         // Firebat -> CombatManager
00227                         else if (ut == UnitTypes::Terran_Firebat)
00228                                 agentManagerMap[a] = &combatManager;
00229             // Medic -> CombatManager
00230             else if (ut == UnitTypes::Terran_Medic)
00231                 agentManagerMap[a] = &combatManager;
00232                         else
00233                                 agentManagerMap[a] = &combatManager;
00234                 }
00235         }
00236 
00237         // If we are running low on supply, give an SCV to the SupplyManager
00238         /*
00239         const int remainingSupply = Broodwar->self()->supplyTotal() - Broodwar->self()->supplyUsed();
00240         if (remainingSupply < 6 && supplyManager.numAgents(UnitTypes::Terran_SCV) < 1)
00241         {
00242                 remap(UnitTypes::Terran_SCV, resourceManager, supplyManager);
00243         }
00244         */
00245 
00246         // If we have enough SCVs, let's try creating a Barracks/Army
00247 //      if (Broodwar->self()->supplyUsed() >= 20 &&
00248 //              combatManager.numAgents(UnitTypes::Terran_SCV) < 1 )
00249 //      {
00250 //              remap(UnitTypes::Terran_SCV, resourceManager, combatManager);
00251 //      }
00252 
00253         // take one of the resourceManager SCV's and give it to the gas manager
00254         if (Broodwar->self()->supplyUsed() >= 30 &&
00255                 gasManager.numAgents(UnitTypes::Terran_SCV) < 1)
00256         {
00257                 remap(UnitTypes::Terran_SCV, buildManager, gasManager);
00258         }
00259 }
00260 
00261 /*
00262 *  redistributeAgents()
00263 *
00264 *  This is what actually gives the managers their agents
00265 *  and takes agents away from other managers that have
00266 *  been re-assigned based upon the agentManagerMap
00267 */
00268 void Strategizer::redistributeAgents()
00269 {
00270         // Revoke all agents from managers
00271         buildManager.removeAllAgents();
00272         combatManager.removeAllAgents();
00273         gasManager.removeAllAgents();
00274         productionManager.removeAllAgents(); // remove once build mgr is more complete
00275         resourceManager.removeAllAgents();
00276         scoutManager.removeAllAgents();
00277         supplyManager.removeAllAgents();
00278 
00279         // Redistribute agents
00280     AgentManagerMapIter it  = agentManagerMap.begin();
00281     AgentManagerMapIter end = agentManagerMap.end();
00282         for(; it != end; ++it)
00283         {
00284         pair<Agent*, Manager*> agentManager = *it;
00285                 Agent   *a = agentManager.first;
00286                 Manager *m = agentManager.second;
00287                 // TODO : Change this to assert
00288                 if (a != NULL)
00289                 {
00290                         m->addAgent(*a);
00291                         a->setParentManager(m);
00292                 }
00293         }
00294 }
00295 
00296 void Strategizer::updateManagers()
00297 {
00298         buildManager.update();
00299         combatManager.update();
00300         gasManager.update();
00301         productionManager.update(); // remove once build mgr is more complete
00302         resourceManager.update();
00303         scoutManager.update();
00304         supplyManager.update();
00305 }
00306 
00307 void Strategizer::draw()
00308 {
00309         buildManager.draw();
00310         combatManager.draw();
00311         gasManager.draw();
00312         resourceManager.draw();
00313         supplyManager.draw();
00314 }
00315 
00316 bool Strategizer::remap(BWAPI::UnitType type, Manager &src, Manager &dst)
00317 {
00318     UnitAgentMapIter it  = unitAgentMap.begin();
00319     UnitAgentMapIter end = unitAgentMap.end();
00320         for(; it != end; ++it)
00321         {
00322         pair<Unit*, Agent*> unitAgent = *it;
00323                 Agent   *a  = unitAgent.second;
00324                 UnitType ut = a->getUnit().getType();
00325                 if (ut == type && agentManagerMap[a] == &src)
00326                 {
00327                         agentManagerMap[a] = &dst;
00328                         return false;
00329                 }
00330         }
00331         return true;
00332 }
00333 
00334 bool Strategizer::checkForfeit()
00335 {
00336     // TODO: will eventually be using productionMgr inside buildMgr?
00337     // if so, that change will mess this up
00338     AgentSet pmCC(productionManager.getAgentsOfType(UnitTypes::Terran_Command_Center));
00339     return pmCC.size() == 0;
00340 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines