BWAPI
SPAR/AIModule/SparAIModule/PerceptualState/PerceptualState.h
Go to the documentation of this file.
00001 #pragma once
00002 #include "../PersistentUnitGroup.h"
00003 //#include "../UnitManager.h"
00004 //#include "../UnitData.h"
00005 #include "../Scheduler/SchedulerTask.h"
00006 #include "../Utils/Functors.hpp"
00007 #include "../Utils/Vector2.h"
00008 #include "../Utils/Utils.h"
00009 #include "../Utils/Event.h"
00010 #include "../Utils/UnitGroup.h"
00011 #include "../Utils/Resources.h"
00012 #include "Locations/Common.h"
00013 #include "InfluenceMap/InfluenceMap.h"
00014 #include "InfluenceMap/StructuralImportance.h"
00015 #include "InfluenceMap/Threat.h"
00016 #include "InfluenceMap/Visibility.h"
00017 #include "Tasks/UpdateInfluenceMapTask.h"
00018 #include "Tasks/UpdateBuildingsTask.h"
00019 #include "Tasks/UpdateUnitsTask.h"
00020 #include "Techs/Techs.h"
00021 #include <algorithm>
00022 
00023 static const int SAFE_POSITION_RANGE = 3;
00024 static const int DODGE_DISTANCE = 90;
00025 
00030 class PerceptualState : public Component
00031 {
00032 public:
00033   PerceptualState();
00034 
00035   ~PerceptualState();
00036 
00041   template <class LocationTypes, class TechTypes>
00042   void onStart()
00043   {
00044     m_map = LocationTypes::instantiateMap();
00045     Techs::onStart<TechTypes>(m_map);
00046     activateTasks();
00047   }
00048 
00049   void onFrame()
00050   {
00051 #ifdef DRAW_ON_SCREEN
00052     if (Spar->getConfiguration().displayMap())
00053       displayMap();
00054 
00055     if (Spar->getConfiguration().displayEnemyInfluenceMap())
00056       m_enemyInfluenceMap.display();
00057     if (Spar->getConfiguration().displaySelfInfluenceMap())
00058       m_selfInfluenceMap.display();
00059     if (Spar->getConfiguration().displayVisibilityInfluenceMap())
00060       m_visibilityInfluenceMap.display();
00061     if (Spar->getConfiguration().displayStructureInfluenceMap())
00062       m_structureInfluenceMap.display();
00063 #endif
00064   }
00065 
00066   void onEnd()
00067   {
00068     Techs::onEnd();
00069   }
00070 
00071   void onUnitDiscover(BWAPI::Unit* unit);
00072   void onUnitEvade(BWAPI::Unit* unit);
00073   void onUnitShow(BWAPI::Unit* unit);
00074   void onUnitHide(BWAPI::Unit* unit);
00075   void onUnitCreate(BWAPI::Unit* unit);
00076   void onUnitDestroy(BWAPI::Unit* unit);
00077   void onUnitMorph(BWAPI::Unit* unit);
00078   void onUnitRenegade(BWAPI::Unit* unit);
00079 
00080   class ResearchInProgress;
00081   ResearchInProgress* onResearchStarted(const Process* parent, TechTypeTech* m_tech, BWAPI::Unit* m_building);
00082   ResearchInProgress* onUpgradeStarted(const Process* parent, UpgradeTypeTech* m_upgrade, BWAPI::Unit* m_building);
00083 
00084   // TODO: all this getUnits() stuff should go in Map, and should return enemy units in fog of war as well
00085   //       (hence units should be kept on a per-tile basis, as in BWAPI)
00086 
00087   template <class Predicate>
00088   UnitGroup getUnits(const CircularLocation& location, Predicate predicate) const
00089   {
00090     // TODO: this may crash before BWAPI is fixed!
00091     UnitGroup units(BWAPI::Broodwar->getUnitsInRadius(location.getCurrentCenter(), location.getRadius()));
00092     UnitGroup::iterator it = units.begin();
00093     while (it != units.end())
00094     {
00095       UnitGroup::iterator next = ++(UnitGroup::iterator(it));
00096       if (!predicate(*it))
00097         units.erase(it);
00098       it = next;
00099     }
00100     return units;
00101   }
00102 
00103   template <class Location>
00104   UnitGroup getUnits(const Location& lcoation)
00105   {
00106     return getUnits(location, True());
00107   }
00108 
00109   template <class Predicate>
00110   UnitGroup getUnits(const RectangularLocation& location, Predicate predicate) const
00111   {
00112     // TODO: use this when BWAPI is fixed!
00113     //UnitGroup units(BWAPI::Broodwar->getUnitsInRectangle(location.getTopLeftCorner().makeValid(), location.getBottomRightCorner().makeValid()));
00114     //UnitGroup::iterator it = units.begin();
00115     //while (it != units.end())
00116     //{
00117     //  UnitGroup::iterator next = ++(UnitGroup::iterator(it));
00118     //  if (!predicate(*it))
00119     //    units.erase(it);
00120     //  it = next;
00121     //}
00122     //return units;
00123 
00124     const BWAPI::TilePosition topLeft(location.getTopLeftCorner().makeValid());
00125     int tileLeft = topLeft.x();
00126     int tileTop = topLeft.y();
00127     const BWAPI::TilePosition bottomRight(location.getBottomRightCorner().makeValid());
00128     int tileRight = bottomRight.x();
00129     int tileBottom = bottomRight.y();
00130 
00131     UnitGroup allUnits;
00132     for (int x = tileLeft; x <= tileRight; ++x)
00133     {
00134       for (int y = tileTop; y <= tileBottom; ++y)
00135       {
00136         const std::set<BWAPI::Unit*>& units = BWAPI::Broodwar->getUnitsOnTile(x, y);
00137         for (std::set<BWAPI::Unit*>::const_iterator it = units.begin(); it != units.end(); ++it)
00138         {
00139           BWAPI::Unit* unit= *it;
00140           BWAPI::Position pos = unit->getPosition();
00141           if (is_between<int, true>(location.getTopLeftCorner().x(), location.getBottomRightCorner().x())(pos.x()) &&
00142               is_between<int, true>(location.getTopLeftCorner().y(), location.getBottomRightCorner().y())(pos.y()) &&
00143               predicate(unit))
00144             allUnits.insert(unit);
00145         }
00146       }
00147     }
00148 #ifdef _DEBUG
00149     for (UnitGroup::const_iterator it = allUnits.begin(); it != allUnits.end(); ++it)
00150     {
00151       BWAPI::Position pos = (*it)->getPosition();
00152       bool isBetweenX = is_between<int, true>(location.getTopLeftCorner().x(), location.getBottomRightCorner().x())(pos.x());
00153       bool isBetweenY = is_between<int, true>(location.getTopLeftCorner().y(), location.getBottomRightCorner().y())(pos.y());
00154       assert(isBetweenX && isBetweenY);
00155     }
00156 #endif
00157     return allUnits;
00158   }
00159   template <class Predicate>
00160   UnitGroup getUnits(const CircularUnitDynamicLocation& location, Predicate predicate) const
00161   {
00162     return getUnits(location.getCircularLocation(), predicate);
00163   }
00164   template <class Predicate>
00165   UnitGroup getUnits(const RectangularGroupDynamicLocation& location, Predicate predicate) const
00166   {
00167     if (location.getGroup()->empty())
00168       return UnitGroup();
00169     else
00170       return getUnits(location.getExpandedRectangularLocation(), predicate);
00171   }
00172 
00173   template <class LocationType>
00174   UnitGroup getOwnUnits(const LocationType& location) const
00175   {
00176     return getUnits(location, IsOwnUnit<BWAPI::Unit>());
00177   }
00178 
00179   template <class LocationType>
00180   UnitGroup getEnemyUnits(const LocationType& location) const
00181   {
00182     return getUnits(location, IsEnemyUnit<BWAPI::Unit>());
00183   }
00184 
00185   UnitGroup getEnemiesNearUnit(BWAPI::Unit* unit, int range) const
00186   {
00187     return getEnemyUnits(CircularLocation(unit->getPosition(), range));
00188   }
00189 
00190   bool unitInSight(BWAPI::Unit* unit) const
00191   {
00192     return tileInSight(unit->getTilePosition(), unit->getType());
00193   }
00194 
00195   bool tileInSight(BWAPI::TilePosition tile, BWAPI::UnitType unitType) const;
00196 
00197   //This check if the position is reachable by a ground unit.  
00198   //It checks if there is a static obstacle and if the position itself is obstructed (either by other units or by static obstacles)
00199   bool positionIsReachable( const BWAPI::Position& current_pos, const BWAPI::Position& destination) const;
00200 
00201   std::set<BWAPI::Unit*> PerceptualState::getTargetingUnits(BWAPI::Unit* unit) const;
00202   bool isUnitTargeted(BWAPI::Unit* unit) const;
00203 
00210   BWAPI::Position getGroundFrontier(const BWAPI::Position& position, const double angle) const;
00211 
00212   BWAPI::Position getBorder(const BWAPI::Position& position) const;
00213 
00214   BWAPI::Position getSafeDodgePosition(BWAPI::Unit* unit) const;
00215 
00216   BWAPI::Position getSafeRetreatPosition(BWAPI::Unit* unit) const;
00217 
00218   BWAPI::Position getSafeRetreatPosition(const PersistentUnitGroup* group, const UnitGroup& enemyUnits) const;
00219 
00220   BWAPI::Position getScoutingLocation(BWAPI::Unit* unit, const BWTA::Region* const region) const;
00221 
00222   Map* getMap() { return m_map; }
00223   const Map* getMap() const { return m_map; }
00224 
00225   PrimitiveLocation* getHostLocation(BWAPI::UnitType unitType, bool isLifted, BWAPI::Position position, BWAPI::TilePosition tilePosition) const;
00226   PrimitiveLocation* getHostLocation(BWAPI::Unit* unit) const
00227   {
00228     return getHostLocation(unit->getType(), unit->isLifted(), unit->getPosition(), unit->getTilePosition());
00229   }
00230   PrimitiveLocation* getHostLocation(const EnemyUnit::SavedState& state) const
00231   {
00232     return getHostLocation(state.getType(), state.isLifted(), state.getPosition(), state.getTilePosition());
00233   }
00234 
00235   // Dynamically creating static locations will require events if we allow them to be subsequently deleted
00236 
00237   DECLARE_EVENT1(OnUnitDiscover, BWAPI::Unit*);
00238   OnUnitDiscover& getUnitDiscoverEvent() const { return m_unitDiscoverEvent; }
00239   DECLARE_EVENT1(OnUnitEvade, BWAPI::Unit*);
00240   OnUnitEvade& getUnitEvadeEvent() const { return m_unitEvadeEvent; }
00241   DECLARE_EVENT1(OnUnitShow, BWAPI::Unit*);
00242   OnUnitShow& getUnitShowEvent() const { return m_unitShowEvent; }
00243   DECLARE_EVENT1(OnUnitHide, BWAPI::Unit*);
00244   OnUnitHide& getUnitHideEvent() const { return m_unitHideEvent; }
00245   DECLARE_EVENT1(OnUnitCreate, BWAPI::Unit*);
00246   OnUnitCreate& getUnitCreateEvent() const { return m_unitCreateEvent; }
00247   DECLARE_EVENT1(OnUnitDestroy, BWAPI::Unit*);
00248   OnUnitDestroy& getUnitDestroyEvent() const { return m_unitDestroyEvent; }
00249   DECLARE_EVENT1(OnUnitMorph, BWAPI::Unit*);
00250   OnUnitMorph& getUnitMorphEvent() const { return m_unitMorphEvent; }
00251   DECLARE_EVENT1(OnUnitRenegade, BWAPI::Unit*);
00252   OnUnitRenegade& getUnitRenegadeEvent() const { return m_unitRenegadeEvent; }
00253 
00254   typedef Map::OnUnitCompleted OnUnitCompleted;
00255   OnUnitCompleted& getUnitCompletedEvent() const
00256   {
00257     return m_map->getUnitCompletedEvent();
00258   }
00259 
00260   typedef Map::OnUnitMorphCompleted OnUnitMorphCompleted;
00261   OnUnitMorphCompleted& getUnitMorphCompletedEvent() const
00262   {
00263     return m_map->getUnitMorphCompletedEvent();
00264   }
00265 
00266   class ResearchInProgress : public Process
00267   {
00268   public:
00269     ResearchInProgress(const Process* parent, BWAPI::Unit* unit, TechTypeTech* tech);
00270     ResearchInProgress(const Process* parent, BWAPI::Unit* unit, UpgradeTypeTech* upgrade);
00271     void onTimeout();
00272     void onUnitDestroyed(void* data);
00273     void cancel();
00275     // GUI //
00277     virtual std::set<BWAPI::Unit*> getCommandedUnits() const
00278     {
00279       return std::set<BWAPI::Unit*>(&m_building, &m_building + 1);
00280     }
00281     static const TerminationMode ResearchCancelled;
00282     static const TerminationMode BuildingDestroyed;
00283   protected:
00284     virtual void output(std::ostream& out) const;
00285     virtual void executeImpl();
00286     virtual void terminateImpl();
00287 
00288     BWAPI::Unit* const m_building;
00289     UpgradeTypeTech* const m_upgrade;
00290     TechTypeTech* const m_tech;
00291     SCHEDULER_EVENT(ResearchInProgress, onTimeout) m_timeoutEvent;
00292     Event<boost::tuples::tuple<>>::SubscriberID m_unitDestroyedSubscriberId;
00293     EVENT_HANDLER(ResearchInProgress, onUnitDestroyed) m_unitDestroyedEventHandler;
00294   };
00295 
00296 private:
00297   friend class ResearchInProgress;
00298 
00299   // TODO: this should be a process
00300   class UnitInConstruction : public Component
00301   {
00302   public:
00303     UnitInConstruction(BWAPI::Unit* unit);
00304     UnitInConstruction(const UnitInConstruction& other);
00305     void setPosInContainer(stdext::hash_map<BWAPI::Unit*, UnitInConstruction>::iterator posInContainer) { m_posInContainer = posInContainer; }
00306     stdext::hash_map<BWAPI::Unit*, UnitInConstruction>::iterator getPosInContainer() const { return m_posInContainer; }
00307     void execute();
00308     void onTimeout();
00309     void onUnitDestroyed(void* data);
00310     void externalTerminate()
00311     {
00312       terminate();
00313     }
00314   private:
00315     void terminate();
00316 
00317     BWAPI::Unit* const m_unitInConstruction;
00318     SCHEDULER_EVENT(UnitInConstruction, onTimeout) m_timeoutEvent;
00319     Event<boost::tuples::tuple<>>::SubscriberID m_unitDestroyedSubscriberId;
00320     EVENT_HANDLER(UnitInConstruction, onUnitDestroyed) m_unitDestroyedEventHandler;
00321     stdext::hash_map<BWAPI::Unit*, UnitInConstruction>::iterator m_posInContainer;
00322   };
00323   friend class UnitInConstruction;
00324   
00325   class UnitMorphing : public Component
00326   {
00327   public:
00328     UnitMorphing(BWAPI::Unit* unit);
00329     UnitMorphing(const UnitMorphing& other);
00330     void setPosInContainer(stdext::hash_map<BWAPI::Unit*, UnitMorphing>::iterator posInContainer) { m_posInContainer = posInContainer; }
00331     stdext::hash_map<BWAPI::Unit*, UnitMorphing>::iterator getPosInContainer() const { return m_posInContainer; }
00332     void execute();
00333     void onTimeout();
00334     void onUnitDestroyed(void* data);
00335     void externalTerminate()
00336     {
00337       terminate();
00338     }
00339   private:
00340     void terminate();
00341 
00342     BWAPI::Unit* const m_unitMorphing;
00343     SCHEDULER_EVENT(UnitMorphing, onTimeout) m_timeoutEvent;
00344     Event<boost::tuples::tuple<>>::SubscriberID m_unitDestroyedSubscriberId;
00345     EVENT_HANDLER(UnitMorphing, onUnitDestroyed) m_unitDestroyedEventHandler;
00346     stdext::hash_map<BWAPI::Unit*, UnitMorphing>::iterator m_posInContainer;
00347   };
00348   friend class UnitMorphing;
00349 
00350 
00351   void monitorUnitCompletion(BWAPI::Unit* unit);
00352   void activateTasks();
00353   void displayMap();
00354 
00355   void onUnitInConstructionTerminate(UnitInConstruction* unitInConstruction)
00356   {
00357     m_unitsInConstruction.erase(unitInConstruction->getPosInContainer());
00358   }
00359 
00360   void onUnitMorphingTerminate(UnitMorphing* unitMorphing)
00361   {
00362     m_unitsMorphing.erase(unitMorphing->getPosInContainer());
00363   }
00364 
00365   stdext::hash_map<BWAPI::Unit*, UnitInConstruction> m_unitsInConstruction;
00366   stdext::hash_map<BWAPI::Unit*, UnitMorphing> m_unitsMorphing;
00367 
00368   Map* m_map;
00369 
00370   // Events
00371   EVENT(OnUnitDiscover) m_unitDiscoverEvent;
00372   EVENT(OnUnitEvade) m_unitEvadeEvent;
00373   EVENT(OnUnitShow) m_unitShowEvent;
00374   EVENT(OnUnitHide) m_unitHideEvent;
00375   EVENT(OnUnitCreate) m_unitCreateEvent;
00376   EVENT(OnUnitDestroy) m_unitDestroyEvent;
00377   EVENT(OnUnitMorph) m_unitMorphEvent;
00378   EVENT(OnUnitRenegade) m_unitRenegadeEvent;
00379 
00380   // Influence maps
00381   InfluenceMap<Threat> m_enemyInfluenceMap;
00382   InfluenceMap<Threat> m_selfInfluenceMap;
00383   InfluenceMap<Visibility> m_visibilityInfluenceMap;
00384   InfluenceMap<StructuralImportance> m_structureInfluenceMap;
00385 
00386   // Tasks
00387   UpdateInfluenceMapTask<Threat> m_updateEnemyThreatInfluenceMap;
00388   UpdateInfluenceMapTask<Threat> m_updateSelfThreatInfluenceMap;
00389   UpdateInfluenceMapTask<Visibility> m_updateVisibilityInfluenceMap;
00390   UpdateInfluenceMapTask<StructuralImportance> m_updateStructuralImportanceInfluenceMap;
00391   UpdateBuildingsTask* m_updateBuildings;
00392   UpdateUnitsTask* m_updateUnits;
00393 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines