BWAPI
|
00001 #pragma once 00002 #include "StaticLocation.h" 00003 #include "PrimitiveLocationBase.h" 00004 #include "../../../SparAIContainer.h" 00005 #include "../../../UnitManager.h" 00006 #include "../../../Utils/Utils.h" 00007 00008 // 00009 // onUnitRenegade events are not handled since we only store buildings and they cannot be mind-controlled 00010 // (and geysers->refineries are handled by the onUnitMorph event). 00011 // 00012 // Other implementations are possible (for CompositeLocation also) 00013 // - unit types in std::map ([min-max] unit types for buildings) 00014 // - one container for units and one container for buildings 00015 // 00016 // Additionally, the same containers could be used for PrimitiveLocation/CompositeLocation, to avoid 00017 // duplicating code and to offer the same kind of iterators (instead of general_iterator) in StaticLocation. 00018 // 00019 00020 static const bool KEEP_UNITS_IN_FOG_OF_WAR = true; 00021 00022 class CompositeLocation; 00023 class PerceptualState; 00024 00029 class PrimitiveLocation : public virtual PrimitiveLocationBase, public virtual StaticLocation 00030 { 00031 public: 00032 typedef PrimitiveLocationBase::own_unit_const_iterator own_unit_const_iterator; 00033 typedef PrimitiveLocationBase::own_unit_type_const_iterator own_unit_type_const_iterator; 00034 typedef PrimitiveLocationBase::own_building_const_iterator own_building_const_iterator; 00035 00036 typedef PrimitiveLocationBase::enemy_unit_iterator enemy_unit_iterator; 00037 typedef PrimitiveLocationBase::enemy_unit_const_iterator enemy_unit_const_iterator; 00038 typedef PrimitiveLocationBase::enemy_unit_type_iterator enemy_unit_type_iterator; 00039 typedef PrimitiveLocationBase::enemy_unit_type_const_iterator enemy_unit_type_const_iterator; 00040 typedef PrimitiveLocationBase::enemy_building_iterator enemy_building_iterator; 00041 typedef PrimitiveLocationBase::enemy_building_const_iterator enemy_building_const_iterator; 00042 00043 typedef PrimitiveLocationBase::neutral_unit_iterator neutral_unit_iterator; 00044 typedef PrimitiveLocationBase::neutral_unit_const_iterator neutral_unit_const_iterator; 00045 typedef PrimitiveLocationBase::neutral_unit_type_iterator neutral_unit_type_iterator; 00046 typedef PrimitiveLocationBase::neutral_unit_type_const_iterator neutral_unit_type_const_iterator; 00047 typedef PrimitiveLocationBase::neutral_building_iterator neutral_building_iterator; 00048 typedef PrimitiveLocationBase::neutral_building_const_iterator neutral_building_const_iterator; 00049 00054 PrimitiveLocation(CompositeLocation* parent) 00055 : StaticLocation(parent) 00056 , m_unitDestroyEventHandler(*this) 00057 , m_unitMorphEventHandler(*this) 00058 , m_unitRenegadeEventHandler(*this) 00059 , m_unitEvadeEventHandler(*this) 00060 { 00061 } 00062 00063 ~PrimitiveLocation() 00064 { 00065 std::pair<own_unit_wrapper_iterator, own_unit_wrapper_iterator> ownBuildings = getOwnUnitWrappers(); 00066 while (ownBuildings.first != ownBuildings.second) 00067 { 00068 own_unit_wrapper_iterator next = ++(own_unit_wrapper_iterator(ownBuildings.first)); 00069 OwnUnit* ownUnit = (*ownBuildings.first).getUnit(); 00070 removeUnitInternal(ownUnit); 00071 delete ownUnit; 00072 ownBuildings.first = next; 00073 } 00074 00075 std::pair<enemy_unit_wrapper_iterator, enemy_unit_wrapper_iterator> enemyBuildings = getEnemyUnitWrappers(); 00076 while (enemyBuildings.first != enemyBuildings.second) 00077 { 00078 enemy_unit_wrapper_iterator next = ++(enemy_unit_wrapper_iterator(enemyBuildings.first)); 00079 EnemyUnit* enemyUnit = (*enemyBuildings.first).getUnit(); 00080 removeUnitInternal(enemyUnit); 00081 delete enemyUnit; 00082 enemyBuildings.first = next; 00083 } 00084 00085 std::pair<neutral_unit_wrapper_iterator, neutral_unit_wrapper_iterator> neutralUnits = getNeutralUnitWrappers(); 00086 while (neutralUnits.first != neutralUnits.second) 00087 { 00088 neutral_unit_wrapper_iterator next = ++(neutral_unit_wrapper_iterator(neutralUnits.first)); 00089 NeutralUnit* neutralUnit = (*neutralUnits.first).getUnit(); 00090 removeUnitInternal(neutralUnit); 00091 delete neutralUnit; 00092 neutralUnits.first = next; 00093 } 00094 } 00095 00096 #pragma region Own_Units 00097 00098 std::pair<own_unit_const_iterator, own_unit_const_iterator> 00099 getOwnUnits() const 00100 { 00101 return std::make_pair(own_unit_const_iterator(own_unit_wrapper_const_iterator(m_ownUnits.begin())), 00102 own_unit_const_iterator(own_unit_wrapper_const_iterator(m_ownUnits.end()))); 00103 } 00104 00105 std::pair<own_unit_type_const_iterator, own_unit_type_const_iterator> 00106 getOwnUnits(BWAPI::UnitType unitType) const 00107 { 00108 std::pair<stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<OwnUnit>>::const_iterator, stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<OwnUnit>>::const_iterator> iterators = m_ownUnits.equal_range(unitType); 00109 return std::make_pair(own_unit_type_const_iterator(own_unit_wrapper_const_iterator(iterators.first)), 00110 own_unit_type_const_iterator(own_unit_wrapper_const_iterator(iterators.second))); 00111 } 00112 00113 std::pair<own_building_const_iterator, own_building_const_iterator> 00114 getOwnBuildings() const 00115 { 00116 // Note that this could be implemented in log n (instead of n) by using a std::map with BWAPI::UnitTypes building ID ranges 00117 00118 std::pair<own_unit_const_iterator, own_unit_const_iterator> ownUnits = getOwnUnits(); 00119 return std::make_pair(own_building_const_iterator(IsBuilding<OwnUnit>(), ownUnits.first, ownUnits.second), 00120 own_building_const_iterator(IsBuilding<OwnUnit>(), ownUnits.second, ownUnits.second)); 00121 } 00122 00123 size_t getNbOwnUnits() const 00124 { 00125 return m_ownUnits.size(); 00126 } 00127 00128 size_t getNbOwnUnits(BWAPI::UnitType unitType) const 00129 { 00130 return m_ownUnits.count(unitType); 00131 } 00132 00133 size_t getNbOwnBuildings() const 00134 { 00135 // Note that this could be implemented in log n (instead of n) by using a std::map with BWAPI::UnitTypes building ID ranges 00136 00137 std::pair<own_building_const_iterator, own_building_const_iterator> ownBuildings = getOwnBuildings(); 00138 return std::distance(ownBuildings.first, ownBuildings.second); 00139 } 00140 00141 void updateOwnUnits() 00142 { 00143 std::pair<own_unit_iterator, own_unit_iterator> ownUnits = getOwnUnits(); 00144 updateUnits(ownUnits.first, ownUnits.second); 00145 } 00146 00147 #pragma endregion Own_Units 00148 00149 #pragma region Enemy_Units 00150 00151 std::pair<enemy_unit_iterator, enemy_unit_iterator> 00152 getEnemyUnits() 00153 { 00154 return std::make_pair(enemy_unit_iterator(enemy_unit_wrapper_iterator(m_enemyUnits.begin())), 00155 enemy_unit_iterator(enemy_unit_wrapper_iterator(m_enemyUnits.end()))); 00156 } 00157 00158 std::pair<enemy_unit_const_iterator, enemy_unit_const_iterator> 00159 getEnemyUnits() const 00160 { 00161 return std::make_pair(enemy_unit_const_iterator(enemy_unit_wrapper_const_iterator(m_enemyUnits.begin())), 00162 enemy_unit_const_iterator(enemy_unit_wrapper_const_iterator(m_enemyUnits.end()))); 00163 } 00164 00165 std::pair<enemy_unit_type_iterator, enemy_unit_type_iterator> 00166 getEnemyUnits(BWAPI::UnitType unitType) 00167 { 00168 std::pair<stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<EnemyUnit>>::iterator, stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<EnemyUnit>>::iterator> iterators = m_enemyUnits.equal_range(unitType); 00169 return std::make_pair(enemy_unit_type_iterator(enemy_unit_wrapper_iterator(iterators.first)), 00170 enemy_unit_type_iterator(enemy_unit_wrapper_iterator(iterators.second))); 00171 } 00172 00173 std::pair<enemy_unit_type_const_iterator, enemy_unit_type_const_iterator> 00174 getEnemyUnits(BWAPI::UnitType unitType) const 00175 { 00176 std::pair<stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<EnemyUnit>>::const_iterator, stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<EnemyUnit>>::const_iterator> iterators = m_enemyUnits.equal_range(unitType); 00177 return std::make_pair(enemy_unit_type_const_iterator(enemy_unit_wrapper_const_iterator(iterators.first)), 00178 enemy_unit_type_const_iterator(enemy_unit_wrapper_const_iterator(iterators.second))); 00179 } 00180 00181 std::pair<enemy_building_iterator, enemy_building_iterator> 00182 getEnemyBuildings() 00183 { 00184 std::pair<enemy_building_wrapper_iterator, enemy_building_wrapper_iterator> enemyWrappers = getEnemyBuildingWrappers(); 00185 return std::make_pair(enemy_building_iterator(enemyWrappers.first), 00186 enemy_building_iterator(enemyWrappers.second)); 00187 } 00188 00189 std::pair<enemy_building_const_iterator, enemy_building_const_iterator> 00190 getEnemyBuildings() const 00191 { 00192 std::pair<enemy_building_wrapper_const_iterator, enemy_building_wrapper_const_iterator> enemyWrappers = getEnemyBuildingWrappers(); 00193 return std::make_pair(enemy_building_const_iterator(enemyWrappers.first), 00194 enemy_building_const_iterator(enemyWrappers.second)); 00195 } 00196 00197 size_t getNbEnemyUnits() const 00198 { 00199 return m_enemyUnits.size(); 00200 } 00201 00202 size_t getNbEnemyUnits(BWAPI::UnitType unitType) const 00203 { 00204 return m_enemyUnits.count(unitType); 00205 } 00206 00207 size_t getNbEnemyBuildings() const 00208 { 00209 std::pair<enemy_building_const_iterator, enemy_building_const_iterator> enemyBuildings = getEnemyBuildings(); 00210 return std::distance(enemyBuildings.first, enemyBuildings.second); 00211 } 00212 00213 void updateEnemyBuildings() 00214 { 00215 std::pair<enemy_building_iterator, enemy_building_iterator> enemyBuildings = getEnemyBuildings(); 00216 updateUnits(enemyBuildings.first, enemyBuildings.second); 00217 } 00218 00219 void updateEnemyUnits() 00220 { 00221 std::pair<enemy_unit_iterator, enemy_unit_iterator> enemyUnits = getEnemyUnits(); 00222 updateUnits(enemyUnits.first, enemyUnits.second); 00223 } 00224 00225 #pragma endregion Enemy_Units 00226 00227 #pragma region Neutral_Units 00228 00229 std::pair<neutral_unit_iterator, neutral_unit_iterator> 00230 getNeutralUnits() 00231 { 00232 return std::make_pair(neutral_unit_iterator(neutral_unit_wrapper_iterator(m_neutralUnits.begin())), 00233 neutral_unit_iterator(neutral_unit_wrapper_iterator(m_neutralUnits.end()))); 00234 } 00235 00236 std::pair<neutral_unit_const_iterator, neutral_unit_const_iterator> 00237 getNeutralUnits() const 00238 { 00239 return std::make_pair(neutral_unit_const_iterator(neutral_unit_wrapper_const_iterator(m_neutralUnits.begin())), 00240 neutral_unit_const_iterator(neutral_unit_wrapper_const_iterator(m_neutralUnits.end()))); 00241 } 00242 00243 std::pair<neutral_unit_type_iterator, neutral_unit_type_iterator> 00244 getNeutralUnits(BWAPI::UnitType unitType) 00245 { 00246 std::pair<stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<NeutralUnit>>::iterator, stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<NeutralUnit>>::iterator> iterators = m_neutralUnits.equal_range(unitType); 00247 return std::make_pair(neutral_unit_type_iterator(neutral_unit_wrapper_iterator(iterators.first)), 00248 neutral_unit_type_iterator(neutral_unit_wrapper_iterator(iterators.second))); 00249 } 00250 00251 std::pair<neutral_unit_type_const_iterator, neutral_unit_type_const_iterator> 00252 getNeutralUnits(BWAPI::UnitType unitType) const 00253 { 00254 std::pair<stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<NeutralUnit>>::const_iterator, stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<NeutralUnit>>::const_iterator> iterators = m_neutralUnits.equal_range(unitType); 00255 return std::make_pair(neutral_unit_type_const_iterator(neutral_unit_wrapper_const_iterator(iterators.first)), 00256 neutral_unit_type_const_iterator(neutral_unit_wrapper_const_iterator(iterators.second))); 00257 } 00258 00259 std::pair<neutral_building_iterator, neutral_building_iterator> 00260 getNeutralBuildings() 00261 { 00262 std::pair<neutral_building_wrapper_iterator, neutral_building_wrapper_iterator> neutralWrappers = getNeutralBuildingWrappers(); 00263 return std::make_pair(neutral_building_iterator(neutralWrappers.first), 00264 neutral_building_iterator(neutralWrappers.second)); 00265 } 00266 00267 std::pair<neutral_building_const_iterator, neutral_building_const_iterator> 00268 getNeutralBuildings() const 00269 { 00270 std::pair<neutral_building_wrapper_const_iterator, neutral_building_wrapper_const_iterator> neutralWrappers = getNeutralBuildingWrappers(); 00271 return std::make_pair(neutral_building_const_iterator(neutralWrappers.first), 00272 neutral_building_const_iterator(neutralWrappers.second)); 00273 } 00274 00275 size_t getNbNeutralUnits() const 00276 { 00277 return m_neutralUnits.size(); 00278 } 00279 00280 size_t getNbNeutralUnits(BWAPI::UnitType unitType) const 00281 { 00282 return m_neutralUnits.count(unitType); 00283 } 00284 00285 size_t getNbNeutralBuildings() const 00286 { 00287 std::pair<neutral_building_const_iterator, neutral_building_const_iterator> neutralBuildings = getNeutralBuildings(); 00288 return std::distance(neutralBuildings.first, neutralBuildings.second); 00289 } 00290 00291 void updateNeutralBuildings() 00292 { 00293 std::pair<neutral_building_iterator, neutral_building_iterator> neutralBuildings = getNeutralBuildings(); 00294 updateUnits(neutralBuildings.first, neutralBuildings.second); 00295 } 00296 00297 void updateNeutralUnits() 00298 { 00299 std::pair<neutral_unit_iterator, neutral_unit_iterator> neutralUnits = getNeutralUnits(); 00300 updateUnits(neutralUnits.first, neutralUnits.second); 00301 } 00302 00303 #pragma endregion Neutral_Units 00304 00305 void onUnitDestroy(void* data); 00306 void onUnitMorph(void* data); 00307 void onUnitRenegade(void* data); 00308 void onUnitEvade(void* data); 00309 00310 protected: 00311 friend class PerceptualState; 00312 00313 template <class UnitType> 00314 struct UnitManagement : public StaticLocation::UnitManagement<UnitType> 00315 { 00316 }; 00317 template <> 00318 struct UnitManagement<OwnUnit> : public StaticLocation::UnitManagement<OwnUnit> 00319 { 00320 static stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<OwnUnit>>& getUnits(PrimitiveLocation* location) 00321 { 00322 return location->m_ownUnits; 00323 } 00324 }; 00325 template <> 00326 struct UnitManagement<EnemyUnit> : public StaticLocation::UnitManagement<EnemyUnit> 00327 { 00328 static stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<EnemyUnit>>& getUnits(PrimitiveLocation* location) 00329 { 00330 return location->m_enemyUnits; 00331 } 00332 }; 00333 template <> 00334 struct UnitManagement<NeutralUnit> : public StaticLocation::UnitManagement<NeutralUnit> 00335 { 00336 static stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<NeutralUnit>>& getUnits(PrimitiveLocation* location) 00337 { 00338 return location->m_neutralUnits; 00339 } 00340 }; 00341 template <class UnitType> friend struct UnitManagement; 00342 00343 void onUnitDiscover(BWAPI::Unit* unit); 00344 00345 std::pair<own_unit_iterator, own_unit_iterator> 00346 getOwnUnits() 00347 { 00348 return std::make_pair(own_unit_iterator(own_unit_wrapper_iterator(m_ownUnits.begin())), 00349 own_unit_iterator(own_unit_wrapper_iterator(m_ownUnits.end()))); 00350 } 00351 00352 std::pair<own_unit_wrapper_iterator, own_unit_wrapper_iterator> 00353 getOwnUnitWrappers() 00354 { 00355 return std::make_pair(own_unit_wrapper_iterator(m_ownUnits.begin()), 00356 own_unit_wrapper_iterator(m_ownUnits.end())); 00357 } 00358 00359 std::pair<own_unit_wrapper_const_iterator, own_unit_wrapper_const_iterator> 00360 getOwnUnitWrappers() const 00361 { 00362 return std::make_pair(own_unit_wrapper_const_iterator(m_ownUnits.begin()), 00363 own_unit_wrapper_const_iterator(m_ownUnits.end())); 00364 } 00365 00366 std::pair<enemy_unit_wrapper_iterator, enemy_unit_wrapper_iterator> 00367 getEnemyUnitWrappers() 00368 { 00369 return std::make_pair(enemy_unit_wrapper_iterator(m_enemyUnits.begin()), 00370 enemy_unit_wrapper_iterator(m_enemyUnits.end())); 00371 } 00372 00373 std::pair<enemy_unit_wrapper_const_iterator, enemy_unit_wrapper_const_iterator> 00374 getEnemyUnitWrappers() const 00375 { 00376 return std::make_pair(enemy_unit_wrapper_const_iterator(m_enemyUnits.begin()), 00377 enemy_unit_wrapper_const_iterator(m_enemyUnits.end())); 00378 } 00379 00380 std::pair<enemy_building_wrapper_iterator, enemy_building_wrapper_iterator> 00381 getEnemyBuildingWrappers() 00382 { 00383 std::pair<enemy_unit_wrapper_iterator, enemy_unit_wrapper_iterator> unitWrappers = getEnemyUnitWrappers(); 00384 return std::make_pair(enemy_building_wrapper_iterator(WrapperIsBuilding(), unitWrappers.first, unitWrappers.second), 00385 enemy_building_wrapper_iterator(WrapperIsBuilding(), unitWrappers.second, unitWrappers.second)); 00386 } 00387 00388 std::pair<enemy_building_wrapper_const_iterator, enemy_building_wrapper_const_iterator> 00389 getEnemyBuildingWrappers() const 00390 { 00391 std::pair<enemy_unit_wrapper_const_iterator, enemy_unit_wrapper_const_iterator> unitWrappers = getEnemyUnitWrappers(); 00392 return std::make_pair(enemy_building_wrapper_const_iterator(WrapperIsBuilding(), unitWrappers.first, unitWrappers.second), 00393 enemy_building_wrapper_const_iterator(WrapperIsBuilding(), unitWrappers.second, unitWrappers.second)); 00394 } 00395 00396 std::pair<neutral_unit_wrapper_iterator, neutral_unit_wrapper_iterator> 00397 getNeutralUnitWrappers() 00398 { 00399 return std::make_pair(neutral_unit_wrapper_iterator(m_neutralUnits.begin()), 00400 neutral_unit_wrapper_iterator(m_neutralUnits.end())); 00401 } 00402 00403 std::pair<neutral_unit_wrapper_const_iterator, neutral_unit_wrapper_const_iterator> 00404 getNeutralUnitWrappers() const 00405 { 00406 return std::make_pair(neutral_unit_wrapper_const_iterator(m_neutralUnits.begin()), 00407 neutral_unit_wrapper_const_iterator(m_neutralUnits.end())); 00408 } 00409 00410 std::pair<neutral_building_wrapper_iterator, neutral_building_wrapper_iterator> 00411 getNeutralBuildingWrappers() 00412 { 00413 std::pair<neutral_unit_wrapper_iterator, neutral_unit_wrapper_iterator> unitWrappers = getNeutralUnitWrappers(); 00414 return std::make_pair(neutral_building_wrapper_iterator(WrapperIsBuilding(), unitWrappers.first, unitWrappers.second), 00415 neutral_building_wrapper_iterator(WrapperIsBuilding(), unitWrappers.second, unitWrappers.second)); 00416 } 00417 00418 std::pair<neutral_building_wrapper_const_iterator, neutral_building_wrapper_const_iterator> 00419 getNeutralBuildingWrappers() const 00420 { 00421 std::pair<neutral_unit_wrapper_const_iterator, neutral_unit_wrapper_const_iterator> unitWrappers = getNeutralUnitWrappers(); 00422 return std::make_pair(neutral_building_wrapper_const_iterator(WrapperIsBuilding(), unitWrappers.first, unitWrappers.second), 00423 neutral_building_wrapper_const_iterator(WrapperIsBuilding(), unitWrappers.second, unitWrappers.second)); 00424 } 00425 00426 virtual size_t getNbOwnUnitsV() const { return getNbOwnUnits(); } 00427 virtual size_t getNbOwnUnitsV(BWAPI::UnitType unitType) const { return getNbOwnUnits(unitType); } 00428 virtual size_t getNbOwnBuildingsV() const { return getNbOwnBuildings(); } 00429 00430 virtual size_t getNbEnemyUnitsV() const { return getNbEnemyUnits(); } 00431 virtual size_t getNbEnemyUnitsV(BWAPI::UnitType unitType) const { return getNbEnemyUnits(unitType); } 00432 virtual size_t getNbEnemyBuildingsV() const { return getNbEnemyBuildings(); } 00433 00434 virtual size_t getNbNeutralUnitsV() const { return getNbNeutralUnits(); } 00435 virtual size_t getNbNeutralUnitsV(BWAPI::UnitType unitType) const { return getNbNeutralUnits(unitType); } 00436 virtual size_t getNbNeutralBuildingsV() const { return getNbNeutralBuildings(); } 00437 00438 virtual void updateOwnUnitsV() 00439 { 00440 updateOwnUnits(); 00441 } 00442 virtual void updateEnemyBuildingsV() 00443 { 00444 updateEnemyBuildings(); 00445 } 00446 virtual void updateEnemyUnitsV() 00447 { 00448 updateEnemyUnits(); 00449 } 00450 virtual void updateNeutralBuildingsV() 00451 { 00452 updateNeutralBuildings(); 00453 } 00454 virtual void updateNeutralUnitsV() 00455 { 00456 updateNeutralUnits(); 00457 } 00458 00459 template <class UnitIterator> 00460 void updateUnits(UnitIterator unitBegin, UnitIterator unitEnd); 00461 00462 class UpdateOwnUnit 00463 { 00464 public: 00465 UpdateOwnUnit(PrimitiveLocation* thisLocation) 00466 : m_thisLocation(thisLocation) 00467 {} 00468 void update(OwnUnit* ownUnit) 00469 { 00470 PrimitiveLocation* newLocation = m_thisLocation->getHostLocation(ownUnit->getUnit()); 00471 if (newLocation != m_thisLocation) 00472 { 00473 m_thisLocation->transferUnitTo(ownUnit, newLocation); 00474 } 00475 } 00476 protected: 00477 PrimitiveLocation* const m_thisLocation; 00478 }; 00479 friend class UpdateOwnUnit; 00480 00481 class UpdateForeignUnit 00482 { 00483 public: 00484 UpdateForeignUnit(PrimitiveLocation* thisLocation) 00485 : m_thisLocation(thisLocation) 00486 {} 00487 template <class UnitType> 00488 void update(UnitType* unitType) 00489 { 00490 if (unitType->isAccessible()) 00491 { 00492 PrimitiveLocation* newLocation = m_thisLocation->getHostLocation(unitType->getUnit()); 00493 if (newLocation != m_thisLocation) 00494 { 00495 m_thisLocation->transferUnitTo(unitType, newLocation); 00496 } 00497 } 00498 else 00499 { 00500 // Remove unit if its last known position is visible but the building isn't there anymore (since the building was destroyed or moved away) 00501 assert(Spar->getPerceptualState().getHostLocation(unitType->getLastKnownState()) == m_thisLocation); 00502 00503 const typename UnitType::SavedState& state = unitType->getLastKnownState(); 00504 if (Spar->getPerceptualState().tileInSight(state.getTilePosition(), state.getType())) 00505 { 00506 m_thisLocation->removeUnit(unitType); 00507 } 00508 } 00509 } 00510 protected: 00511 PrimitiveLocation* const m_thisLocation; 00512 }; 00513 friend class UpdateForeignUnit; 00514 00515 private: 00516 00517 template <class UnitType> 00518 void onUnitDestroy(UnitType* unitWrapper); 00519 template <class UnitType> 00520 void onUnitMorph(UnitType* unitWrapper); 00521 template <class UnitType> 00522 void onUnitRenegade(UnitType* unitWrapper); 00523 template <class UnitType> 00524 void onUnitEvade(UnitType* unitWrapper); 00525 00526 PrimitiveLocation* getHostLocation(BWAPI::Unit* unit); 00527 00528 template <class UnitType> 00529 UnitWrapper<UnitType>* transferUnitTo(UnitType* unitWrapper, PrimitiveLocation* toLocation); 00530 template <class UnitType> 00531 UnitWrapper<UnitType>* transferUnitFrom(UnitType* unit, PrimitiveLocation* fromLocation); 00532 00533 void addUnit(BWAPI::Unit* unit); 00534 template <class UnitType> 00535 UnitWrapper<UnitType>* addUnit(BWAPI::Unit* unit); 00536 template <class UnitType> 00537 UnitWrapper<UnitType>* addUnitInternal(UnitType* unit); 00538 00539 void updateUnit(BWAPI::Unit* unit); 00540 00541 void removeUnit(BWAPI::Unit* unit); 00542 template <class UnitType> 00543 void removeUnit(UnitType* unitWrapper); 00544 template <class UnitType> 00545 void removeUnitInternal(UnitType* unit); 00546 00550 EVENT_HANDLER(PrimitiveLocation, onUnitDestroy) m_unitDestroyEventHandler; 00551 EVENT_HANDLER(PrimitiveLocation, onUnitEvade) m_unitEvadeEventHandler; 00552 EVENT_HANDLER(PrimitiveLocation, onUnitMorph) m_unitMorphEventHandler; 00553 EVENT_HANDLER(PrimitiveLocation, onUnitRenegade) m_unitRenegadeEventHandler; 00554 00558 stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<OwnUnit>> m_ownUnits; 00559 00560 stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<EnemyUnit>> m_enemyUnits; 00561 00562 stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<NeutralUnit>> m_neutralUnits; 00563 }; 00564 00565 template <class UnitType> 00566 void PrimitiveLocation::onUnitDestroy(UnitType* unitType) 00567 { 00568 unitType->markAsAccessible(); 00569 00570 removeUnit(unitType); 00571 } 00572 00573 template <class UnitType> 00574 void PrimitiveLocation::onUnitMorph(UnitType* unitType) 00575 { 00576 BWAPI::Unit* unit = unitType->getUnit(); 00577 00578 // If player has changed the modifications will be handled in the next onUnitRenegade event 00579 if (unitType->getPlayer() == unit->getPlayer()) 00580 { 00581 // TODO: no UnitRemoved/UnitAdded events should be raised here 00582 00583 if (unitType->getLastType() != unit->getType()) 00584 { 00585 removeUnit(unitType); 00586 00587 getHostLocation(unit)->addUnit(unit); 00588 00589 // ################################################ 00590 //other possible implementation: no events 00591 //removeUnitInternal(unitWrapper); 00592 //unitWrapper = addUnitInternal(unit); 00593 //if (m_parent != NULL) 00594 // m_parent->onUnitMorphed(unit); 00595 //PrimitiveLocation* newLocation = getHostLocation(unit->getUnit()); 00596 //if (newLocation != this) 00597 //{ 00598 // transferUnitTo(unitWrapper, newLocation); 00599 //} 00600 } 00601 } 00602 } 00603 00604 template <class UnitType> 00605 void PrimitiveLocation::onUnitRenegade(UnitType* unitType) 00606 { 00607 BWAPI::Unit* unit = unitType->getUnit(); 00608 00609 if (unitType->getPlayer() != unit->getPlayer()) 00610 { 00611 removeUnit(unitType); 00612 00613 getHostLocation(unit)->addUnit(unit); 00614 } 00615 } 00616 00617 template <class UnitType> 00618 void PrimitiveLocation::onUnitEvade(UnitType* unitType) 00619 { 00620 BWAPI::Unit* unit = unitType->getUnit(); 00621 assert(unit->getType() == unitType->getType()); 00622 assert(unit->getPlayer() == unitType->getPlayer()); 00623 00624 if (KEEP_UNITS_IN_FOG_OF_WAR || unit->getType().isBuilding()) 00625 { 00626 UnitWrapper<UnitType>* unitWrapper = static_cast<UnitWrapper<UnitType>*>(unitType->m_primitiveLocationData); 00627 PrimitiveLocation* newLocation = getHostLocation(unit); 00628 if (newLocation != this) 00629 { 00630 UnitWrapper<UnitType>* otherLocationWrapper = transferUnitTo(unitType, newLocation); 00631 unitWrapper = otherLocationWrapper; 00632 } 00633 //Spar->getUnitManager().unsubscribeIndividualUnitDestroy(unit, unitWrapper->m_unitDestroyID); 00634 Spar->getUnitManager().unsubscribeIndividualUnitEvade(unit, unitWrapper->m_unitEvadeID); 00635 Spar->getUnitManager().unsubscribeIndividualUnitMorph(unit, unitWrapper->m_unitMorphID); 00636 Spar->getUnitManager().unsubscribeIndividualUnitRenegade(unit, unitWrapper->m_unitRenegadeID); 00637 00638 unitType->markAsInaccessible(); 00639 } 00640 else 00641 { 00642 removeUnit(unitType); 00643 } 00644 } 00645 00646 template <class UnitType> 00647 PrimitiveLocation::UnitWrapper<UnitType>* PrimitiveLocation::addUnit(BWAPI::Unit* unit) 00648 { 00649 UnitType* unitType = new UnitType(unit, this); 00650 00651 UnitWrapper<UnitType>* unitWrapper = addUnitInternal(unitType); 00652 00653 if (boost::is_same<UnitType, EnemyUnit>::value) 00654 { 00655 SPAR_LOG(LogTypes::PERCEPTUAL_STATE, "Enemy unit manager: Add \"%s\" to \"%s\"", 00656 getObjectDescription(unitType).c_str(), 00657 getObjectDescription(this).c_str()); 00658 } 00659 00660 UnitManagement<UnitType>::getUnitAddedEvent(this).raise(unitType); 00661 00662 if (m_parent != NULL) 00663 m_parent->onUnitAdded(unitType); 00664 00665 return unitWrapper; 00666 } 00667 00668 template <class UnitType> 00669 void PrimitiveLocation::removeUnit(UnitType* unitType) 00670 { 00671 if (boost::is_same<UnitType, EnemyUnit>::value) 00672 { 00673 SPAR_LOG(LogTypes::PERCEPTUAL_STATE, "Enemy unit manager: Remove \"%s\" from \"%s\"", 00674 getObjectDescription(unitType).c_str(), 00675 getObjectDescription(this).c_str()); 00676 } 00677 00678 removeUnitInternal(unitType); 00679 UnitManagement<UnitType>::getUnitRemovedEvent(this).raise(unitType); 00680 00681 if (m_parent != NULL) 00682 m_parent->onUnitRemoved(unitType); 00683 00684 Spar->addZombieComponent(unitType); 00685 } 00686 00687 template <class UnitType> 00688 PrimitiveLocation::UnitWrapper<UnitType>* PrimitiveLocation::addUnitInternal(UnitType* unitType) 00689 { 00690 BWAPI::Unit* unit = unitType->m_unit; 00691 00692 stdext::hash_multimap<BWAPI::UnitType, UnitWrapper<UnitType>>::iterator it = 00693 UnitManagement<UnitType>::getUnits(this).insert(std::make_pair(unit->getType().getID(), UnitWrapper<UnitType>(unitType))); 00694 UnitWrapper<UnitType>& unitWrapper = it->second; 00695 unitWrapper.m_posInContainer = it; 00696 if (unitType->isAccessible()) 00697 { 00698 unitWrapper.m_unitDestroyID = Spar->getUnitManager().subscribeIndividualUnitDestroy(unit, &m_unitDestroyEventHandler, unitType); 00699 unitWrapper.m_unitEvadeID = Spar->getUnitManager().subscribeIndividualUnitEvade(unit, &m_unitEvadeEventHandler, unitType); 00700 unitWrapper.m_unitMorphID = Spar->getUnitManager().subscribeIndividualUnitMorph(unit, &m_unitMorphEventHandler, unitType); 00701 unitWrapper.m_unitRenegadeID = Spar->getUnitManager().subscribeIndividualUnitRenegade(unit, &m_unitRenegadeEventHandler, unitType); 00702 } 00703 unitType->m_primitiveLocationData = &unitWrapper; 00704 unitType->updateLocation(this); 00705 Spar->getUnitManager().setUnitLocation(unit, this, unitType); 00706 00707 assert(&unitWrapper.m_posInContainer->second == &unitWrapper); 00708 assert(Spar->getUnitManager().getUnitData(unit).m_data == unitType); 00709 00710 return &unitWrapper; 00711 } 00712 00713 template <class UnitType> 00714 void PrimitiveLocation::removeUnitInternal(UnitType* unitType) 00715 { 00716 BWAPI::Unit* unit = unitType->m_unit; // To avoid the assert() in getUnit() 00717 00718 UnitWrapper<UnitType>* unitWrapper = static_cast<UnitWrapper<UnitType>*>(unitType->m_primitiveLocationData); 00719 Spar->getUnitManager().unsubscribeIndividualUnitDestroy(unit, unitWrapper->m_unitDestroyID); 00720 Spar->getUnitManager().unsubscribeIndividualUnitEvade(unit, unitWrapper->m_unitEvadeID); 00721 Spar->getUnitManager().unsubscribeIndividualUnitMorph(unit, unitWrapper->m_unitMorphID); 00722 Spar->getUnitManager().unsubscribeIndividualUnitRenegade(unit, unitWrapper->m_unitRenegadeID); 00723 00724 UnitManagement<UnitType>::getUnits(this).erase(unitWrapper->m_posInContainer); 00725 unitType->m_primitiveLocationData = NULL; 00726 Spar->getUnitManager().getUnitData(unit).m_data = NULL; 00727 } 00728 00729 template <class UnitType> 00730 PrimitiveLocation::UnitWrapper<UnitType>* PrimitiveLocation::transferUnitFrom(UnitType* unit, PrimitiveLocation* fromLocation) 00731 { 00732 PrimitiveLocation::UnitWrapper<UnitType>* unitWrapper = addUnitInternal(unit); 00733 UnitManagement<UnitType>::getUnitAddedEvent(this).raise(unit); 00734 00735 if (m_parent != NULL) 00736 m_parent->onUnitTransferred(unit, fromLocation, this); 00737 00738 return unitWrapper; 00739 } 00740 00741 template <class UnitType> 00742 PrimitiveLocation::UnitWrapper<UnitType>* PrimitiveLocation::transferUnitTo(UnitType* unitType, PrimitiveLocation* toLocation) 00743 { 00744 if (boost::is_same<UnitType, EnemyUnit>::value) 00745 { 00746 SPAR_LOG(LogTypes::PERCEPTUAL_STATE, "Enemy unit manager: Transfer \"%s\" from \"%s\" to \"%s\"", 00747 getObjectDescription(unitType).c_str(), 00748 getObjectDescription(this).c_str(), 00749 getObjectDescription(toLocation).c_str()); 00750 } 00751 00752 if (m_parent != NULL) 00753 m_parent->onUnitTransferred(unitType, this, toLocation); 00754 00755 removeUnitInternal(unitType); 00756 00757 UnitWrapper<UnitType>* toLocationWrapper = toLocation->transferUnitFrom(unitType, this); 00758 00759 UnitManagement<UnitType>::getUnitRemovedEvent(this).raise(unitType); 00760 00761 return toLocationWrapper; 00762 } 00763 00764 template <class UnitIterator> 00765 void PrimitiveLocation::updateUnits(UnitIterator unitBegin, UnitIterator unitEnd) 00766 { 00767 static_if_else<boost::is_same<typename UnitIterator::value_type, OwnUnit*>::value, UpdateOwnUnit, UpdateForeignUnit>::type updater(this); 00768 00769 while (unitBegin != unitEnd) 00770 { 00771 UnitIterator next = ++(UnitIterator(unitBegin)); 00772 typename UnitIterator::value_type unit = *unitBegin; 00773 00774 updater.update(unit); 00775 00776 unitBegin = next; 00777 } 00778 }