BWAPI
Skynet/Skynet/DefenseSquad.cpp
Go to the documentation of this file.
00001 #include "DefenseSquad.h"
00002 
00003 #include "UnitTracker.h"
00004 #include "BaseTracker.h"
00005 #include "BorderTracker.h"
00006 #include "BuildOrderManager.h"
00007 #include "PlayerTracker.h"
00008 
00009 DefenseSquadTask::DefenseSquadTask(ArmyBehaviour behaviour)
00010         : BaseSquadTask(behaviour)
00011         , mNeededWorkers(0)
00012         , mDefenseGoal()
00013 {
00014 }
00015 
00016 int DefenseSquadTask::getEndTime() const
00017 {
00018         return Requirement::maxTime;
00019 }
00020 
00021 int DefenseSquadTask::getEndTime(Unit unit) const
00022 {
00023         return Requirement::maxTime;
00024 }
00025 
00026 int DefenseSquadTask::getPriority(Unit unit) const
00027 {
00028         if(!unit->getType().isWorker())
00029         {
00030                 bool isNeeded = false;
00031                 if(mNeedsAntiAir && unit->canAttackAir())
00032                         isNeeded = true;
00033                 
00034                 if(mNeedsAntiGround && unit->canAttackGround())
00035                         isNeeded = true;
00036 
00037                 if(isNeeded)
00038                         return 30;
00039                 else
00040                         return 1;
00041         }
00042 
00043         int workersToReturn = int(mWorkerDefenders.size()) - mNeededWorkers;
00044         if(workersToReturn > 0)
00045         {
00046                 int count = 1;
00047                 for each(Unit worker in mWorkerDefenders)
00048                 {
00049                         if(worker == unit)
00050                         {
00051                                 if(count <= workersToReturn)
00052                                         return 1;
00053                                 break;
00054                         }
00055                         ++count;
00056                 }
00057         }
00058 
00059         return 30;
00060 }
00061 
00062 Position DefenseSquadTask::getStartLocation(Unit unit) const
00063 {
00064         return unit->getPosition();
00065 }
00066 
00067 Position DefenseSquadTask::getEndLocation(Unit unit) const
00068 {
00069         return unit->getPosition();
00070 }
00071 
00072 bool DefenseSquadTask::preUpdate()
00073 {
00074         updateRequirements();
00075 
00076         return hasEnded();
00077 }
00078 
00079 bool DefenseSquadTask::update()
00080 {
00081         if(mDefenseGoal.getActionType() != ActionType::None)
00082         {
00083                 Goal enemiesGoal(ActionType::Attack, mDefenseGoal.getBase()->getEnemyThreats());
00084                 for(std::map<Unit, Behaviour>::iterator it = mUnitBehaviours.begin(); it != mUnitBehaviours.end(); ++it)
00085                         it->second.update(enemiesGoal, mUnits);
00086         }
00087 
00088         return hasEnded() && mUnits.empty();
00089 }
00090 
00091 bool DefenseSquadTask::waitingForUnit(Unit unit) const
00092 {
00093         return false;
00094 }
00095 
00096 void DefenseSquadTask::giveUnit(Unit unit)
00097 {
00098         if(unit->getType() == BWAPI::UnitTypes::Protoss_Observer)
00099                 mObserver = unit;
00100         else if(unit->getType().isWorker())
00101                 mWorkerDefenders.insert(unit);
00102 
00103         mUnits.insert(unit);
00104 
00105         mUnitBehaviours[unit] = Behaviour(unit);
00106 }
00107 
00108 void DefenseSquadTask::returnUnit(Unit unit)
00109 {
00110         mUnits.erase(unit);
00111 
00112         mUnitBehaviours[unit].onDeleted();
00113         mUnitBehaviours.erase(unit);
00114 
00115         mWorkerDefenders.erase(unit);
00116 
00117         if(unit == mObserver)
00118                 mObserver = StaticUnits::nullunit;
00119 }
00120 
00121 bool DefenseSquadTask::morph(Unit unit, BWAPI::UnitType previousType)
00122 {
00123         return false;
00124 }
00125 
00126 UnitGroup DefenseSquadTask::getFinishedUnits()
00127 {
00128         return mUnits;
00129 }
00130 
00131 void DefenseSquadTask::updateRequirements()
00132 {
00133         clearRequirements();
00134         mNeededWorkers = 0;
00135         mNeedsAntiAir = false;
00136         mNeedsAntiGround = false;
00137 
00138         // Basic idea is to have a defense goal for each base that will take only the amount of units it needs to take out the threat
00139         // and also take workers if it cannot take out the threat with the number of units it has
00140 
00141         // This should make it do important things such as kill the threat while the rest of the army in the default squad stay at the choke
00142         // stopping any other units from entering
00143         if(!hasEnded() && mDefenseGoal.getActionType() != ActionType::None)
00144         {
00145                 //TODO: currently picks units based on it getting units with a score higher than 100, if its zerg it could get zerglings in which case it wont have enough
00146                 // TODO: maybe do some modification based on current units health
00147                 int AirThreatScore = 0;
00148                 int GroundThreatScore = 0;
00149                 int GroundThreatCount = 0;
00150                 bool needsDetection = false;
00151                 for each(Unit enemy in mDefenseGoal.getBase()->getEnemyThreats())
00152                 {
00153                         if(!needsDetection && (enemy->getType().isCloakable() || enemy->getType().hasPermanentCloak() || enemy->isBurrowed() || enemy->getType() == BWAPI::UnitTypes::Zerg_Lurker))
00154                                 needsDetection = true;
00155 
00156                         if(enemy->isLifted() || enemy->getType().isFlyer())
00157                         {
00158                                 if(enemy->canAttackGround())
00159                                         AirThreatScore += enemy->getType().buildScore();
00160                                 else if(enemy->getType().spaceProvided() > 0)
00161                                 {
00162                                         if(enemy->getPlayer()->getRace() != BWAPI::Races::Zerg)
00163                                                 AirThreatScore += 400;
00164                                         else if(BWAPI::Broodwar->getFrameCount() > 24*60*6) //TODO: has the player researched drop?
00165                                                 AirThreatScore += 250;
00166                                         else
00167                                                 AirThreatScore += 50;
00168                                 }
00169                                 else
00170                                         AirThreatScore += 50;
00171                         }
00172                         else
00173                         {
00174                                 ++GroundThreatCount;
00175                                 if(enemy->canAttackGround())
00176                                         GroundThreatScore += enemy->getType().buildScore();
00177                                 else
00178                                         GroundThreatScore += 50;
00179                         }
00180                 }
00181 
00182                 // Temp till defense squad is good enough to use army units and not just workers
00183                 if(needsDetection)
00184                         return;
00185 
00186                 if(GroundThreatScore > 0)
00187                         mNeedsAntiGround = true;
00188                 if(AirThreatScore > 0)
00189                         mNeedsAntiAir = true;
00190 
00191                 int AntiAirScore = 0;
00192                 int AntiGroundScore = 0;
00193                 for each(Unit unit in mUnits)
00194                 {
00195                         if(unit->getType().isWorker())
00196                                 continue;
00197 
00198                         if(unit->canAttackGround())
00199                         {
00200                                 --GroundThreatCount;
00201                                 AntiGroundScore += unit->getType().buildScore();
00202                         }
00203                         if(unit->canAttackAir())
00204                                 AntiAirScore += unit->getType().buildScore();
00205                 }
00206 
00207                 mNeededWorkers = std::max((GroundThreatScore - AntiGroundScore) / 50, 0);
00208                 if(mNeededWorkers == 0 && (GroundThreatScore - AntiGroundScore) > 0)
00209                         mNeededWorkers = 1;
00210 
00211                 if(mNeededWorkers < GroundThreatCount)
00212                         mNeededWorkers = GroundThreatCount;
00213 
00214                 int canAttackGroundNeeded = mNeededWorkers / 2;
00215 
00216                 if(mNeededWorkers > 14) mNeededWorkers = 0; //If we cannot defend with 14 workers, don't try, probably not worth possible losses
00217                 if(mNeededWorkers > 1) mNeededWorkers += 1;
00218                 if(mNeededWorkers > 2) mNeededWorkers += 1;
00219                 if(mNeededWorkers > 14) mNeededWorkers = 14;
00220 
00221                 int workersNeeded = std::max(mNeededWorkers - int(mWorkerDefenders.size()), 0);
00222 
00223                 canAttackGroundNeeded -= (int(mWorkerDefenders.size()) / 2);
00224 
00225                 // Get as many as we can for now
00226                 // TODO: maybe check if its our only mining base or do something better
00227                 for(int i = 0; i < workersNeeded; ++i)
00228                 {
00229                         RequirementGroup reqWorkers;
00230                         reqWorkers.addUnitFilterRequirement(30, Requirement::maxTime, UnitFilter(UnitFilterFlags::type(UnitFilterFlags::IsWorker | UnitFilterFlags::IsComplete)), mDefenseGoal.getBase()->getCenterLocation());
00231                         addRequirement(reqWorkers);
00232                 }
00233 
00234                 // Temp till defense squad is good enough to use army units and not just workers
00235                 // in the below state can cause the bots army to get too seperated and cause the main army to get possibly destroyed engaging a group elsewhere
00236                 return;
00237 
00238                 RequirementGroup reqMain;
00239                 if(canAttackGroundNeeded > 0)
00240                         reqMain.addUnitFilterRequirement(30, Requirement::maxTime, UnitFilter(UnitFilterFlags::type(UnitFilterFlags::IsArmyUnit | UnitFilterFlags::CanAttackGround | UnitFilterFlags::IsComplete)), canAttackGroundNeeded, mDefenseGoal.getBase()->getCenterLocation());
00241 
00242                 int canAttackAirNeeded = std::max((AirThreatScore - AntiAirScore) / 100, 0);
00243                 if(canAttackAirNeeded > 0)
00244                         reqMain.addUnitFilterRequirement(30, Requirement::maxTime, UnitFilter(UnitFilterFlags::type(UnitFilterFlags::IsArmyUnit | UnitFilterFlags::CanAttackAir | UnitFilterFlags::IsComplete)), canAttackAirNeeded, mDefenseGoal.getBase()->getCenterLocation());
00245 
00246                 if(!mObserver && needsDetection)
00247                         reqMain.addUnitFilterRequirement(30, Requirement::maxTime, UnitFilter(BWAPI::UnitTypes::Protoss_Observer) && UnitFilter(UnitFilterFlags::IsComplete), mDefenseGoal.getBase()->getCenterLocation());
00248 
00249                 addRequirement(reqMain);
00250 
00251                 Position goalpos = mDefenseGoal.getBase()->getCenterLocation();
00252                 const int x = goalpos.x();
00253                 const int y = goalpos.y();
00254 
00255                 BWAPI::Broodwar->drawTextMap(x, y, "canAttackGroundNeeded : %d", canAttackGroundNeeded);
00256                 BWAPI::Broodwar->drawTextMap(x, y+10, "canAttackAirNeeded : %d", canAttackAirNeeded);
00257                 BWAPI::Broodwar->drawTextMap(x, y+20, "workersNeeded : %d", workersNeeded);
00258                 BWAPI::Broodwar->drawTextMap(x, y+30, "workers Have : %d", int(mWorkerDefenders.size()));
00259                 BWAPI::Broodwar->drawTextMap(x, y+40, "Units Have : %d", int(mUnits.size()));
00260                 if(!mObserver && needsDetection)
00261                         BWAPI::Broodwar->drawTextMap(x, y+50, "Needs Observer");
00262         }
00263 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines