BWAPI
|
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 }