BWAPI
SPAR/AIModule/SparAIModule/DecisionMaking/Layer1Reactive/FSM/Behaviors/GatherMinerals.h
Go to the documentation of this file.
00001 #pragma once
00002 #include "../GroupBehavior.h"
00003 #include "../BehaviorState.h"
00004 
00005 // TODO: Fail when there is no more Nexus
00006 // TODO: Keep next mineralPatchIterator to cycle the assignement of probes
00007 
00011 class GatherMinerals : public GroupBehavior<GatherMinerals>
00012 {
00013 protected:
00014   class Mining;
00015   friend class Mining;
00016 
00017   class Mining : public BehaviorState<GatherMinerals, Mining>
00018   {
00019   public:
00020     Mining(GatherMinerals& behavior);
00021     void onEnterImpl();
00022     void onExitImpl();
00023 
00024     void onTimer()
00025     {
00026       if(defence == NULL)
00027       {
00028         defence = new PersistentUnitGroup("Defence");
00029       }
00030       PersistentUnitGroup::const_iterator itUnit = m_context.getGroup()->begin();
00031       while(defence->size() < 3 && itUnit!=m_context.getGroup()->end())
00032       {
00033         if(defence->find((*itUnit))==defence->end())
00034         {
00035           defence->insert(defence->end(),(*itUnit));
00036         }
00037         ++itUnit;
00038       }
00039       bool doSomething = false;
00040       if(isAttacking){doSomething=true;}
00041       std::pair<BaseLocation::crystal_iterator, BaseLocation::crystal_iterator> crystals = m_context.m_baseLocation->getLastKnownCrystalsLeft();
00042       BaseLocation::crystal_iterator patch = crystals.first;
00043 
00044       if(crystals.first != crystals.second)
00045       {
00046         for(PersistentUnitGroup::const_iterator i = m_context.getGroup()->begin() ; i!=m_context.getGroup()->end() ; ++i)
00047         {
00048           if((*i)->isIdle())
00049           {
00050             if(patch != crystals.second)
00051             {
00052               (*i)->gather((*patch)->getUnit());
00053               patch++;
00054             }
00055             else
00056             {
00057               patch = crystals.first;
00058               (*i)->gather((*patch)->getUnit());
00059               patch++;
00060             }
00061           }
00062           if(!isAttacking && (*i)->isUnderAttack())
00063           {
00064             doSomething=true;
00065           }
00066           if(isAttacking && (*i)->isUnderAttack())
00067           {
00068             doSomething=false;
00069           }
00070         }
00071       }
00072 
00073       if(doSomething && isAttacking)
00074       {
00075         //stop attacking
00076         crystals = m_context.m_baseLocation->getLastKnownCrystalsLeft();
00077         patch = crystals.first;
00078         for(PersistentUnitGroup::const_iterator i = defence->begin() ; i!=defence->end() ; ++i)
00079         {
00080           if(patch != crystals.second)
00081           {
00082             (*i)->gather((*patch)->getUnit());
00083             patch++;
00084           }
00085           else
00086           {
00087             patch = crystals.first;
00088             (*i)->gather((*patch)->getUnit());
00089             patch++;
00090           }
00091         }
00092         isAttacking = false;
00093         m_target = NULL;
00094       }
00095       else if(doSomething && !isAttacking)
00096       {
00097         //start attacking
00098         isAttacking = true;
00099         //find a target
00100         UnitGroup units = Spar->getPerceptualState().getEnemyUnits(CircularLocation((*m_context.getGroup()->begin())->getPosition(), 7*TILE_SIZE));
00101         UnitGroup::iterator itEnemy = units.begin();
00102         m_target = NULL;
00103         while(m_target == NULL && itEnemy!=units.end())
00104         {
00105           if((*itEnemy)->isDetected() == true)
00106           {
00107             m_target = (*itEnemy);
00108           }
00109           itEnemy++;
00110         }
00111         //everybody attack move it
00112         if(m_target!=NULL)
00113         {
00114           defence->attackMove(m_target->getPosition());
00115         }
00116         else
00117         {
00118           isAttacking = false;
00119         }
00120       }
00121       else if(!doSomething && isAttacking)
00122       {
00123         //if target is dead
00124         
00125         if(!m_target->exists() || !m_target->isDetected())
00126         {
00127           UnitGroup units = Spar->getPerceptualState().getEnemyUnits(CircularLocation((*m_context.getGroup()->begin())->getPosition(), 7*TILE_SIZE));
00128           UnitGroup::iterator it = units.begin();
00129           m_target = NULL;
00130           while(m_target == NULL && it!=units.end())
00131           {
00132             if((*it)->isDetected() == true)
00133             {
00134               m_target = (*it);
00135             }
00136             it++;
00137           }
00138         }
00139         //change target
00140         //attack move target
00141         if(m_target != NULL)
00142         {
00143           defence->attackMove(m_target->getPosition());
00144         }
00145         else
00146         {
00147           isAttacking = false;
00148         }
00149       }
00150     };
00151 
00152     void onUnitAddedToGroup(BWAPI::Unit* unit);
00153     void onNeutralBuildingRemoved(void* data, NeutralUnit* crystal);
00154 
00155     typedef SCHEDULER_EVENT(Mining, onTimer) TimerEvent;
00156 
00157     typedef boost::tuple<
00158       TimerEvent&
00159     > Events;
00160     Events m_events;
00161 
00162     typedef boost::tuple<> Transitions;
00163     const Transitions m_transitions;
00164 
00165   protected:
00166     // Events
00167     Event<boost::tuples::tuple<NeutralUnit*>>::SubscriberID m_crystalRemovedSubscriberId;
00168     EVENT_HANDLER1(Mining, onNeutralBuildingRemoved, NeutralUnit*) m_crystalRemovedEventHandler;
00169 
00170     TimerEvent m_event;
00171 
00172     // Variables
00173     BWAPI::Unit* m_target;
00174     bool isAttacking;
00175     PersistentUnitGroup* defence;
00176     // Actions
00177 
00178     // Transitions
00179   };
00180 
00181 public:
00182   GatherMinerals(const Process* parent, unsigned int initialPriority, const PersistentUnitGroup* probes, BaseLocation* baseLocation)
00183     : GroupBehavior(parent, initialPriority, probes)
00184     , IGroupBehavior(parent, initialPriority, probes)
00185     , IBehavior(parent, initialPriority)
00186     , IFSM(parent)
00187     , Process(parent)
00188     , m_miningState(*this)
00189     , m_baseLocation(baseLocation)
00190     , m_lastMineral(NULL)
00191     , m_states(m_miningState)
00192   { }
00193 
00194   virtual std::string getName() const
00195   {
00196     return "GatherMinerals at " + getObjectDescription(m_baseLocation);
00197   }
00198 
00199   virtual void onUnitAddedToGroup(void*, BWAPI::Unit* unit)
00200   {
00201     assert(unit->getType() == BWAPI::UnitTypes::Protoss_Probe);
00202     if(m_currentState == &m_miningState)
00203       m_miningState.onUnitAddedToGroup(unit);
00204   }
00205 
00206   virtual void onUnitRemovedFromGroup(void*, BWAPI::Unit* unit)
00207   {
00208     unused(unit);
00209   }
00210 
00211   // TODO: Move elsewhere ?
00212   static const TerminationMode NoMoreMinerals;
00213 
00214   typedef boost::tuple<
00215     Mining&
00216   > States;
00217   const States m_states;
00218 
00219 protected:
00220   virtual void executeImpl()
00221   {
00222     GroupBehavior::executeImpl();
00223     m_miningState.onEnter();
00224   }
00225 
00226   BaseLocation* m_baseLocation;
00227   BWAPI::Unit* m_lastMineral;
00228 
00229   Mining m_miningState;
00230 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines