BWAPI
Skynet/Skynet/PsiStormAction.cpp
Go to the documentation of this file.
00001 #include "PsiStormAction.h"
00002 
00003 #include "UnitTracker.h"
00004 #include "UnitInformation.h"
00005 #include "LatencyTracker.h"
00006 #include "Logger.h"
00007 
00008 bool PsiStormAction::update(const Goal &squadGoal, const UnitGroup &squadUnitGroup)
00009 {
00010         if(mUnit->getOrder() == BWAPI::Orders::CastPsionicStorm)
00011                 return true;
00012 
00013         //TODO : Morph arcon temp in here with some non ideal code till group micro actions is complete, checks if it can actually morph the archon,
00014         // ie not using 3.6
00015         static bool allowsArchonMorph = true;
00016         if(allowsArchonMorph)
00017         {
00018                 if(mUnit->getOrder() == BWAPI::Orders::ArchonWarp)
00019                         return true;
00020 
00021                 bool warpPriorityLow = squadGoal.getActionType() != ActionType::Attack || squadGoal.getGoalType() != GoalType::Base || mUnit->getPosition().getApproxDistance(squadGoal.getBase()->getCenterLocation()) > 32*20;
00022                 const int energyToTransformAt = warpPriorityLow ? 48 : 65;
00023                 if(mUnit->getEnergy() <= energyToTransformAt)
00024                 {
00025                         Unit otherTemp;
00026                         int closestDistance = std::numeric_limits<int>::max();
00027                         for each(Unit ht in UnitTracker::Instance().selectAllUnits(BWAPI::UnitTypes::Protoss_High_Templar))
00028                         {
00029                                 if(ht == mUnit)
00030                                         continue;
00031 
00032                                 if(ht->getOrder() == BWAPI::Orders::ArchonWarp)
00033                                         continue;
00034 
00035                                 if(ht->getEnergy() > energyToTransformAt)
00036                                         continue;
00037 
00038                                 int distance = mUnit->getDistance(ht);
00039                                 if(distance < closestDistance)
00040                                 {
00041                                         closestDistance = distance;
00042                                         otherTemp = ht;
00043                                 }
00044                         }
00045 
00046                         if(otherTemp)
00047                         {
00048                                 Unit otherClosestTemp;
00049                                 int otherClosestDistance = std::numeric_limits<int>::max();
00050                                 for each(Unit ht in UnitTracker::Instance().selectAllUnits(BWAPI::UnitTypes::Protoss_High_Templar))
00051                                 {
00052                                         if(ht == otherTemp)
00053                                                 continue;
00054 
00055                                         if(ht->getOrder() == BWAPI::Orders::ArchonWarp)
00056                                                 continue;
00057 
00058                                         if(ht->getEnergy() > energyToTransformAt)
00059                                                 continue;
00060 
00061                                         int distance = otherTemp->getDistance(ht);
00062                                         if(distance < otherClosestDistance)
00063                                         {
00064                                                 otherClosestDistance = distance;
00065                                                 otherClosestTemp = ht;
00066                                         }
00067                                 }
00068 
00069                                 if(otherClosestTemp == mUnit)
00070                                 {
00071                                         mUnit->useTech(BWAPI::TechTypes::Archon_Warp, otherTemp);
00072                                         otherTemp->useTech(BWAPI::TechTypes::Archon_Warp, mUnit);
00073 
00074                                         if(BWAPI::Broodwar->getLastError() == BWAPI::Errors::Incompatible_TechType)
00075                                         {
00076                                                 LOGMESSAGEERROR("Archon Warp Failed, Old BWAPI Version?");
00077                                                 allowsArchonMorph = false;
00078                                         }
00079 
00080                                         return true;
00081                                 }
00082                         }
00083                 }
00084         }
00085 
00086         if(mUnit->getSpellCooldown() > BWAPI::Broodwar->getRemainingLatencyFrames())
00087                 return false;
00088 
00089         if(BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Psionic_Storm) && mUnit->getEnergy() >= BWAPI::TechTypes::Psionic_Storm.energyUsed())
00090         {
00091                 int numTargetting = UnitInformation::Instance().getUnitsTargetting(mUnit).size();
00092 
00093                 UnitGroup targetsToChooseFrom;
00094 
00095                 for each(Unit unit in UnitTracker::Instance().selectAllEnemy())
00096                 {
00097                         if(!unit->exists() || unit->isStasised() || unit->isUnderStorm())
00098                                 continue;
00099 
00100                         const BWAPI::UnitType &type = unit->getType();
00101                         if(type.isBuilding() || type == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine || type == BWAPI::UnitTypes::Zerg_Egg || type == BWAPI::UnitTypes::Protoss_Interceptor || type == BWAPI::UnitTypes::Zerg_Larva || type == BWAPI::UnitTypes::Protoss_Scarab)
00102                                 continue;
00103 
00104                         if(mUnit->getDistance(unit) > BWAPI::TechTypes::Psionic_Storm.getWeapon().maxRange())
00105                                 continue;
00106 
00107                         targetsToChooseFrom.insert(unit);
00108                 }
00109 
00110                 UnitGroup targets(targetsToChooseFrom);
00111 
00112                 bool castUrgenty = (numTargetting > 2 || (numTargetting > 0 && mUnit->totalHitPointFraction() < 0.6));
00113 
00114                 int tries = 0;
00115                 bool tryAgain = true;
00116                 while(tryAgain)
00117                 {
00118                         tryAgain = false;
00119 
00120                         /* There are 3 targets or there are targets and we need to cast urgently */
00121                         if(targets.size() >= 3 || (castUrgenty && !targets.empty()))
00122                         {
00123                                 targets = targets.getBestFittingToCircle(64, BWAPI::Broodwar->getRemainingLatencyFrames()+BWAPI::Broodwar->getLatencyFrames());
00124                                 if(targets.size() >= 3 || (castUrgenty && !targets.empty()))
00125                                 {
00126                                         BWAPI::Position castLocation = targets.getCenter();
00127 
00128                                         int inStormCount = 0;
00129                                         for each(Unit unit in UnitTracker::Instance().selectAllUnits())
00130                                         {
00131                                                 if(!unit->isUnderStorm() && unit->getDistance(castLocation) < 64)
00132                                                         ++inStormCount;
00133 
00134                                                 if(inStormCount > 1)
00135                                                         break;
00136                                         }
00137 
00138                                         if(inStormCount <= 1)
00139                                         {
00140                                                 int distanceToStorm = mUnit->getDistance(castLocation);
00141                                                 if(distanceToStorm <= BWAPI::TechTypes::Psionic_Storm.getWeapon().maxRange())
00142                                                 {
00143                                                         mUnit->useTech(BWAPI::TechTypes::Psionic_Storm, castLocation);
00144                                                         LatencyTracker::Instance().placingStorm(mUnit, castLocation);
00145                                                 }
00146                                                 else
00147                                                 {
00148                                                         Vector newCastLocation = mUnit->getPosition() - castLocation;
00149 
00150                                                         newCastLocation.normalise();
00151 
00152                                                         newCastLocation *= float(distanceToStorm - BWAPI::TechTypes::Psionic_Storm.getWeapon().maxRange());
00153 
00154                                                         newCastLocation += Vector(castLocation);
00155 
00156                                                         mUnit->useTech(BWAPI::TechTypes::Psionic_Storm, newCastLocation);
00157                                                         LatencyTracker::Instance().placingStorm(mUnit, newCastLocation);
00158                                                 }
00159 
00160                                                 return true;
00161                                         }
00162                                         else
00163                                         {
00164                                                 ++tries;
00165                                                 if(tries < 3)
00166                                                 {
00167                                                         targets = targetsToChooseFrom;
00168                                                         for each(Unit unit in targetsToChooseFrom)
00169                                                         {
00170                                                                 if(unit->getDistance(castLocation) < 64)
00171                                                                         targets.erase(unit);
00172                                                         }
00173 
00174                                                         if(targets.size() >= 3 || (castUrgenty && !targets.empty()))
00175                                                                 tryAgain = true;
00176                                                 }
00177                                         }
00178                                 }
00179                         }
00180                 }
00181         }
00182 
00183         return false;
00184 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines