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