BWAPI
Skynet/Skynet/DefaultSquad.cpp
Go to the documentation of this file.
00001 #include "DefaultSquad.h"
00002 
00003 #include "UnitTracker.h"
00004 #include "BaseTracker.h"
00005 #include "BorderTracker.h"
00006 #include "BuildOrderManager.h"
00007 #include "PlayerTracker.h"
00008 #include "UnitHelper.h"
00009 #include "GameProgressDetection.h"
00010 
00011 DefaultSquadTask::DefaultSquadTask(ArmyBehaviour behaviour)
00012         : BaseSquadTask(behaviour)
00013         , mEngageFull(false)
00014 {
00015 }
00016 
00017 int DefaultSquadTask::getEndTime() const
00018 {
00019         return Requirement::maxTime;
00020 }
00021 
00022 int DefaultSquadTask::getEndTime(Unit unit) const
00023 {
00024         return Requirement::maxTime;
00025 }
00026 
00027 int DefaultSquadTask::getPriority(Unit unit) const
00028 {
00029         return unit->getType().isWorker() ? 5 : 20;
00030 }
00031 
00032 Position DefaultSquadTask::getStartLocation(Unit unit) const
00033 {
00034         return unit->getPosition();
00035 }
00036 
00037 Position DefaultSquadTask::getEndLocation(Unit unit) const
00038 {
00039         return unit->getPosition();
00040 }
00041 
00042 bool DefaultSquadTask::preUpdate()
00043 {
00044         updateRequirements();
00045 
00046         return hasEnded();
00047 }
00048 
00049 BorderPosition getLargestChoke(const std::set<BorderPosition> &chokes)
00050 {
00051         int largestChokeSize = 0;
00052         BorderPosition largestChoke;
00053         for each(BorderPosition border in chokes)
00054         {
00055                 int chokeSize = border.mChoke->getClearance();
00056                 if(chokeSize > largestChokeSize)
00057                 {
00058                         largestChoke = border;
00059                         largestChokeSize = chokeSize;
00060                 }
00061         }
00062 
00063         return largestChoke;
00064 }
00065 
00066 bool DefaultSquadTask::update()
00067 {
00068         Goal squadsGoal;
00069 
00070         // Just attack if its not mining anywhere
00071         bool hasMiningBases = false;
00072         int techStructures = 0;
00073         Base baseToDefend;
00074         bool baseUnderAttack = false;
00075         const int mySupply = BWAPI::Broodwar->self()->supplyUsed();
00076         for each(Base base in BaseTracker::Instance().getPlayerBases())
00077         {
00078                 const int techBuildings = base->getNumberOfTechBuildings();
00079                 if(!base->getEnemyThreats().empty() && (techBuildings > 0 || (!base->isMinedOut() && base->getResourceDepot())))
00080                 {
00081                         bool thisUnderAttack = base->isUnderAttack();
00082                         if((thisUnderAttack && !baseUnderAttack) || (thisUnderAttack == baseUnderAttack && techBuildings > techStructures))
00083                         {
00084                                 baseUnderAttack = thisUnderAttack;
00085                                 baseToDefend = base;
00086                                 techStructures = techBuildings;
00087                         }
00088                 }
00089 
00090                 if(!base->getMinerals().empty() && base->getResourceDepot() && base->getResourceDepot()->exists())
00091                         hasMiningBases = true;
00092         }
00093 
00094         UnitGroup avoidGroup;
00095         UnitGroup engageGroup;
00096         for each(const UnitGroup &unitGroup in PlayerTracker::Instance().getEnemyClusters())
00097         {
00098                 if(!hasMiningBases && mUnits.canMajorityAttack(unitGroup))
00099                 {
00100                         engageGroup += unitGroup;
00101                         continue;
00102                 }
00103 
00104                 if(mUnits.minDistanceBetween(unitGroup) > 540)
00105                         continue;
00106 
00107                 const int rating = mUnits.ratingDifference(unitGroup);
00108                 if(mySupply < 360 && ((!mEngageFull && rating < -350) || rating < -1000))
00109                         avoidGroup += unitGroup;
00110                 else if(mUnits.canMajorityAttack(unitGroup) && (mUnits.isWorthEngaging(unitGroup) || unitGroup.isAnyInRange(mUnits)))
00111                         engageGroup += unitGroup;
00112         }
00113 
00114         mEngageFull = !engageGroup.empty();
00115         if(mEngageFull)
00116                 squadsGoal = Goal(ActionType::Attack, engageGroup, avoidGroup);
00117         else if(baseUnderAttack)
00118         {
00119                 const int rating = mUnits.ratingDifference(baseToDefend->getEnemyThreats());
00120                 if(rating >= 0 || (rating > -1000 && baseUnderAttack))
00121                         squadsGoal = Goal(ActionType::Defend, baseToDefend->getEnemyThreats(), avoidGroup);
00122         }
00123 
00124         if(squadsGoal.getGoalType() == GoalType::None)
00125         {
00126                 for each(Base base in BaseTracker::Instance().getPlayerBases())
00127                 {
00128                         if(base->isContested())
00129                         {
00130                                 for each(Unit building in base->getBuildings())
00131                                 {
00132                                         if(BWAPI::Broodwar->self()->isEnemy(building->getPlayer()))
00133                                         {
00134                                                 squadsGoal = Goal(ActionType::Attack, building, engageGroup, avoidGroup);
00135                                                 break;
00136                                         }
00137                                 }
00138                         }
00139 
00140                         if(squadsGoal.getGoalType() != GoalType::None)
00141                                 break;
00142                 }
00143         }
00144 
00145         if(squadsGoal.getGoalType() == GoalType::None)
00146         {
00147                 int enemyKnownSupply = 0;
00148                 int enemyGuessSupply = 0;
00149 
00150                 for each(Unit unit in UnitTracker::Instance().selectAllEnemy())
00151                 {
00152                         int supply = unit->getType().supplyRequired();
00153                         if(UnitHelper::isStaticDefense(unit->getType()))
00154                                 supply = 7;
00155 
00156                         if(unit->accessibility() != AccessType::Lost)
00157                                 enemyKnownSupply += supply;
00158 
00159                         enemyGuessSupply += supply;
00160                 }
00161 
00162                 int alliesSize = 1;
00163                 std::map<BWAPI::Force*, int> enemyForces;
00164                 for each(Player player in BWAPI::Broodwar->getPlayers())
00165                 {
00166                         if(player == BWAPI::Broodwar->self())
00167                                 continue;
00168 
00169                         if(BWAPI::Broodwar->self()->isAlly(player))
00170                                 ++alliesSize;
00171 
00172                         if(BWAPI::Broodwar->self()->isEnemy(player))
00173                                 ++enemyForces[player->getForce()];
00174                 }
00175 
00176                 int maxEnemiesSize = 0;
00177                 for each(std::pair<BWAPI::Force*, int> force in enemyForces)
00178                 {
00179                         if(force.second > maxEnemiesSize)
00180                                 maxEnemiesSize = force.second;
00181                 }
00182 
00183                 bool shouldAttackBase = !hasMiningBases;
00184                 if(mUnits.size() >= 3)
00185                 {
00186                         if(mySupply > 380)
00187                                 shouldAttackBase = true;
00188                         else if(GameProgressDetection::Instance().getState() != StateType::TechHigh)
00189                         {
00190                                 // If its a terran with siege tanks don't attack a base without leg speed and also ensure we are better matched as siege tanks can hurt
00191                                 bool isTerranWithSiege = PlayerTracker::Instance().isEnemyRace(BWAPI::Races::Terran) && PlayerTracker::Instance().enemyHasReseached(BWAPI::TechTypes::Tank_Siege_Mode);
00192                                 if(isTerranWithSiege && BWAPI::Broodwar->self()->getUpgradeLevel(BWAPI::UpgradeTypes::Leg_Enhancements) > 0 && mUnits.size() > 45 && mySupply > (enemyGuessSupply * 4))
00193                                         shouldAttackBase = true;
00194                                 else if(!isTerranWithSiege && mUnits.size() > 35 && mySupply > (enemyKnownSupply * 4))
00195                                         shouldAttackBase = true;
00196                                 else if(mArmyBehaviour <= ArmyBehaviour::Aggresive)
00197                                 {
00198                                         if(maxEnemiesSize <= alliesSize)
00199                                                 shouldAttackBase = true;
00200                                 }
00201 
00202                                 // Agains't weak opponents it can usually attack when these pass
00203                                 // how ever against stronger opponents, or terran with siege tanks it will just lose a few units time and again then lose to a push
00204                                 // easier to just sit back and turtle alittle
00205                                 /*else if(mArmyBehaviour <= ArmyBehaviour::Default)
00206                                 {
00207                                         if(mySupply > (enemyGuessSupply * 4))
00208                                                 shouldAttackBase = true;
00209                                 }
00210                                 else if(mArmyBehaviour == ArmyBehaviour::Defensive)
00211                                 {
00212                                         if(mySupply > (enemyGuessSupply * 5))
00213                                                 shouldAttackBase = true;
00214                                 }*/
00215                         }
00216                 }
00217 
00218                 if(shouldAttackBase)
00219                 {
00220                         Base bestBaseToAttack;
00221                         if(mLastGoal.getGoalType() == GoalType::Base && mLastGoal.getActionType() == ActionType::Attack && mLastGoal.getBase()->isEnemyBase())
00222                                 bestBaseToAttack = mLastGoal.getBase();
00223 
00224                         for each(Base base in BaseTracker::Instance().getEnemyBases())
00225                         {
00226                                 if(!bestBaseToAttack || base->getBuildings().size() < bestBaseToAttack->getBuildings().size())
00227                                         bestBaseToAttack = base;
00228                         }
00229 
00230                         if(bestBaseToAttack)
00231                                 squadsGoal = Goal(ActionType::Attack, bestBaseToAttack, engageGroup, avoidGroup);
00232                 }
00233         }
00234 
00235         if(squadsGoal.getGoalType() == GoalType::None && baseToDefend && mUnits.canMajorityAttack(baseToDefend->getEnemyThreats()))
00236                 squadsGoal = Goal(ActionType::Defend, baseToDefend->getCenterLocation(), engageGroup, avoidGroup);
00237 
00238         if(squadsGoal.getGoalType() == GoalType::None)
00239         {
00240                 if(!BorderTracker::Instance().getBorderPositions(PositionType::TechDefenseChokepoint).empty())
00241                         squadsGoal = Goal(ActionType::Hold, getLargestChoke(BorderTracker::Instance().getBorderPositions(PositionType::TechDefenseChokepoint)).mChoke->getCenter(), engageGroup, avoidGroup);
00242         }
00243 
00244         if(squadsGoal.getGoalType() == GoalType::None)
00245         {
00246                 if(!BorderTracker::Instance().getBorderPositions(PositionType::DefenseChokepoint).empty())
00247                         squadsGoal = Goal(ActionType::Hold, getLargestChoke(BorderTracker::Instance().getBorderPositions(PositionType::DefenseChokepoint)).mChoke->getCenter(), engageGroup, avoidGroup);
00248         }
00249 
00250         if(squadsGoal.getGoalType() == GoalType::None)
00251                 squadsGoal = Goal(ActionType::Attack, Position(BWAPI::Broodwar->mapWidth()*24, BWAPI::Broodwar->mapHeight()*16), engageGroup, avoidGroup);
00252 
00253         if(!mEngageFull && !avoidGroup.empty() && squadsGoal.getActionType() == ActionType::Attack && squadsGoal.getGoalType() == GoalType::Base)
00254                 squadsGoal = Goal(ActionType::Attack, avoidGroup.getCenter(), engageGroup, avoidGroup);
00255 
00256         mLastGoal = squadsGoal;
00257         if(squadsGoal.getGoalType() != GoalType::None)
00258         {
00259                 for(std::map<Unit, Behaviour>::iterator it = mUnitBehaviours.begin(); it != mUnitBehaviours.end(); ++it)
00260                         it->second.update(squadsGoal, mUnits);
00261         }
00262 
00263         return hasEnded() && mUnits.empty();
00264 }
00265 
00266 bool DefaultSquadTask::waitingForUnit(Unit unit) const
00267 {
00268         return false;
00269 }
00270 
00271 void DefaultSquadTask::giveUnit(Unit unit)
00272 {
00273         if(unit->getType() == BWAPI::UnitTypes::Protoss_Observer)
00274                 mObserver = unit;
00275         
00276         mUnits.insert(unit);
00277 
00278         mUnitBehaviours[unit] = Behaviour(unit);
00279 }
00280 
00281 void DefaultSquadTask::returnUnit(Unit unit)
00282 {
00283         mUnits.erase(unit);
00284 
00285         mUnitBehaviours[unit].onDeleted();
00286         mUnitBehaviours.erase(unit);
00287 
00288         if(unit == mObserver)
00289                 mObserver = StaticUnits::nullunit;
00290 }
00291 
00292 bool DefaultSquadTask::morph(Unit unit, BWAPI::UnitType previousType)
00293 {
00294         return false;
00295 }
00296 
00297 UnitGroup DefaultSquadTask::getFinishedUnits()
00298 {
00299         return mUnits;
00300 }
00301 
00302 void DefaultSquadTask::updateRequirements()
00303 {
00304         clearRequirements();
00305 
00306         if(!hasEnded())
00307         {
00308                 for each(Unit unit in UnitTracker::Instance().selectAllUnits())
00309                 {
00310                         if(!unit->isCompleted())
00311                                 continue;
00312 
00313                         if(mUnits.count(unit) != 0)
00314                                 continue;
00315 
00316                         const BWAPI::UnitType &type = unit->getType();
00317                         if(type.isBuilding())
00318                                 continue;
00319                         if(type.isAddon())
00320                                 continue;
00321                         if(type == BWAPI::Broodwar->self()->getRace().getSupplyProvider())
00322                                 continue;
00323                         if(type == BWAPI::UnitTypes::Zerg_Egg)
00324                                 continue;
00325                         if(type == BWAPI::UnitTypes::Protoss_Interceptor)
00326                                 continue;
00327                         if(type == BWAPI::UnitTypes::Zerg_Larva)
00328                                 continue;
00329                         if(type == BWAPI::UnitTypes::Protoss_Scarab)
00330                                 continue;
00331                         if(type == BWAPI::UnitTypes::Protoss_Observer)
00332                                 continue;
00333 
00334                         RequirementGroup req;
00335 
00336                         req.addUnitRequirement(unit, type.isWorker() ? 5 : 20, Requirement::maxTime);
00337 
00338                         addRequirement(req);
00339                 }
00340 
00341                 if(!mObserver)
00342                 {
00343                         RequirementGroup req;
00344 
00345                         req.addUnitFilterRequirement(20, Requirement::maxTime, UnitFilter(BWAPI::UnitTypes::Protoss_Observer) && UnitFilter(UnitFilterFlags::IsComplete));
00346 
00347                         addRequirement(req);
00348                 }
00349         }
00350 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines