BWAPI
SPAR/AIModule/SparAIModule/PerceptualState/Locations/Static/PrimitiveLocation.h
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines