BWAPI
Skynet/Skynet/WorkerScoutTask.cpp
Go to the documentation of this file.
00001 #include "WorkerScoutTask.h"
00002 #include "ScoutManager.h"
00003 #include "MapHelper.h"
00004 #include "UnitInformation.h"
00005 #include "PathFinder.h"
00006 #include "UnitTracker.h"
00007 #include "BaseTracker.h"
00008 
00009 WorkerScoutTask::WorkerScoutTask(TaskType priority, ScoutData data)
00010         : Task(priority)
00011         , mData(data)
00012         , mFailTime(Requirement::maxTime)
00013 {
00014 }
00015 
00016 int WorkerScoutTask::getEndTime() const
00017 {
00018         return Requirement::maxTime;
00019 }
00020 
00021 int WorkerScoutTask::getEndTime(Unit unit) const
00022 {
00023         return getEndTime();
00024 }
00025 
00026 Position WorkerScoutTask::getStartLocation(Unit unit) const
00027 {
00028         if(mData)
00029                 return mData->getNextPosition(unit->getPosition());
00030 
00031         return unit->getPosition();
00032 }
00033 
00034 Position WorkerScoutTask::getEndLocation(Unit unit) const
00035 {
00036         if(mData)
00037                 return mData->getLastPosition(unit->getPosition());
00038 
00039         return unit->getPosition();
00040 }
00041 
00042 bool WorkerScoutTask::preUpdate()
00043 {
00044         if(!mData)
00045         {
00046                 complete();
00047         }
00048         else if(mCurrentState == ScoutState::Searching)
00049         {
00050                 if(mData->isAchieved())
00051                 {
00052                         if(mData->getBase()->isEnemyBase())
00053                                 mCurrentState = ScoutState::Harassing;
00054                         else if(mData->getType() == ScoutType::InitialBaseLocationScout && !mData->getBase()->isEnemyBase())
00055                                 mCurrentState = ScoutState::DoubleCheck;
00056                         else
00057                                 getNewData();
00058                 }
00059                 else if(mFailTime < BWAPI::Broodwar->getFrameCount())
00060                 {
00061                         ScoutManager::Instance().updateLastScoutType(mData, ScoutType::CouldNotReachWithGround);
00062                         getNewData();
00063                 }
00064         }
00065         else if(mCurrentState == ScoutState::Harassing)
00066         {
00067                 if(!mData->getBase()->isEnemyBase() || (mUnit && BaseTracker::Instance().getBase(mUnit->getTilePosition()) != mData->getBase()))
00068                         complete();
00069         }
00070         else if(mCurrentState == ScoutState::DoubleCheck)
00071         {
00072                 if(mData->getBase()->isEnemyBase())
00073                         mCurrentState = ScoutState::Harassing;
00074                 else if(MapHelper::isAnyVisible(mData->getBase()->getCenterBuildLocation(), BWAPI::UnitTypes::Terran_Command_Center))
00075                         getNewData();
00076         }
00077 
00078         return hasEnded() && mUnit;
00079 }
00080 
00081 bool WorkerScoutTask::update()
00082 {
00083         //if(mData)
00084         //      mData->drawDebug(BWAPI::Colors::Blue);
00085         //if(mUnit)
00086         //      mUnit->drawUnitPosition();
00087 
00088         //TODO: change to use goal / behavior system that squads use
00089         if(mUnit && mData)
00090         {
00091                 if(mCurrentState == ScoutState::Searching)
00092                 {
00093                         Position target = mData->getNextPosition(mUnit->getPosition());
00094 
00095                         if(target != BWAPI::Positions::None)
00096                                 mUnit->move(target);
00097                 }
00098                 else if(mCurrentState == ScoutState::Harassing)
00099                 {
00100                         bool doneSomething = false;
00101                         const UnitGroup &targetting = UnitInformation::Instance().getUnitsTargetting(mUnit);
00102                         bool targetsChanged = mLastUnitsTargetting != targetting;
00103                         if(targetsChanged)
00104                                 mLastUnitsTargetting = targetting;
00105 
00106                         //TODO: add units that could be targetting it, including enemy workers so it thinks they are scary and doesn't get surrounded attacking one of them
00107 
00108                         if(mLastUnitsTargetting.size() > 0)
00109                         {
00110                                 mHarrasTimer = 72;
00111 
00112                                 int targettingSupply = 0;
00113                                 for each(Unit unit in mLastUnitsTargetting)
00114                                 {
00115                                         if(!unit->getType().isWorker() && (unit->getType().groundWeapon().maxRange() > 32 || unit->getType().topSpeed() > mUnit->getType().topSpeed()))
00116                                                 targettingSupply += unit->getType().supplyRequired();
00117                                 }
00118 
00119                                 //TODO: fight back against other workers if it has the advantage
00120                                 if(!doneSomething)
00121                                 {
00122                                         bool isEnemyToClose = false;
00123                                         for each(Unit unit in mLastUnitsTargetting)
00124                                         {
00125                                                 if(unit->isInRange(mUnit))
00126                                                 {
00127                                                         isEnemyToClose = true;
00128                                                         break;
00129                                                 }
00130                                         }
00131 
00132                                         //If the enemy is too close, don't use the path as it lacks precision
00133                                         if(!isEnemyToClose)
00134                                         {
00135                                                 if(targetsChanged || mTilePath.path.size() <= 7 || !mTilePath.isComplete || !mTilePath.isStillValid())
00136                                                 {
00137                                                         bool stickToRegion = targettingSupply == 0;
00138                                                         if(mData->getBase()->getNumberOfTechBuildings() == 0 && BWAPI::Broodwar->getFrameCount() > 24*60*4)
00139                                                                 stickToRegion = false;
00140 
00141                                                         mTilePath = PathFinder::Instance().CreateAdvancedFleePath(mUnit->getTilePosition(), mLastUnitsTargetting, stickToRegion);
00142                                                 }
00143 
00144                                                 if(mTilePath.isComplete)
00145                                                 {
00146                                                         while(!mTilePath.path.empty())
00147                                                         {
00148                                                                 std::list<TilePosition>::iterator currentTile = mTilePath.path.begin();
00149                                                                 const Position pos(currentTile->x()*32 + 16, currentTile->y()*32 + 16);
00150                                                                 
00151                                                                 if(pos.getApproxDistance(mUnit->getPosition()) <= 64)
00152                                                                         mTilePath.path.erase(currentTile);
00153                                                                 else
00154                                                                 {
00155                                                                         mUnit->move(pos);
00156 
00157                                                                         doneSomething = true;
00158                                                                         //BWAPI::Broodwar->drawTextMap(mUnit->getPosition().x(), mUnit->getPosition().y() - 10, "Fleeing with path");
00159                                                                         //mTilePath.drawPath();
00160                                                                         break;
00161                                                                 }
00162                                                         }
00163                                                 }
00164                                         }
00165                                 }
00166 
00167                                 // If we haven't done anything to avoid targets, steer away from them
00168                                 if(!doneSomething)
00169                                 {
00170                                         mTilePath.path.clear();
00171                                         mTilePath.isComplete = false;
00172 
00173                                         //TODO: dont just use the the group center, 
00174 
00175                                         Vector direction = mUnit->getPosition() - mLastUnitsTargetting.getCenter();
00176 
00177                                         direction.normalise();
00178                                         direction *= float(TILE_SIZE * 4);
00179                                         direction += Vector(mUnit->getPosition());
00180 
00181                                         //BWAPI::Broodwar->drawLineMap(mUnit->getPosition().x(), mUnit->getPosition().y(), (int)direction.x, (int)direction.y, BWAPI::Colors::Red);
00182 
00183                                         mUnit->move(direction);
00184 
00185                                         doneSomething = true;
00186                                         //BWAPI::Broodwar->drawTextMap(mUnit->getPosition().x(), mUnit->getPosition().y() - 10, "Fleeing with vectors");
00187                                 }
00188                         }
00189 
00190                         if(!doneSomething)
00191                         {
00192                                 mTilePath.path.clear();
00193                                 mTilePath.isComplete = false;
00194 
00195                                 // If we have been provoking units for abit plain out attack them
00196                                 if(mHarrasTimer == 0)
00197                                 {
00198                                         //TODO: change when better unit search functions are added
00199                                         bool oneConstructing = false;
00200                                         Unit closestUnit;
00201                                         double minDist = std::numeric_limits<double>::max();
00202 
00203                                         for each(Unit unit in UnitTracker::Instance().selectAllUnits(mData->getBase()->getPlayer()->getRace().getWorker(), mData->getBase()->getPlayer()))
00204                                         {
00205                                                 if(mData->getBase() != BaseTracker::Instance().getBase(unit->getTilePosition()))
00206                                                         continue;
00207                                                 
00208                                                 if(!oneConstructing || unit->isConstructing())
00209                                                 {
00210                                                         double thisDist = mUnit->getPosition().getDistance(unit->getPosition());
00211                                                         if(thisDist < minDist || (oneConstructing && unit->isConstructing()))
00212                                                         {
00213                                                                 oneConstructing = unit->isConstructing();
00214                                                                 closestUnit = unit;
00215                                                                 minDist = thisDist;
00216                                                         }
00217                                                 }
00218                                         }
00219 
00220                                         if(closestUnit)
00221                                         {
00222                                                 doneSomething = true;
00223                                                 mUnit->attack(closestUnit);
00224                                                 //BWAPI::Broodwar->drawTextMap(mUnit->getPosition().x(), mUnit->getPosition().y() - 10, "Attacking Unit");
00225                                         }
00226                                 }
00227                         }
00228 
00229                         if(!doneSomething)
00230                         {
00231                                 if(mUnit->getDistance(mData->getBase()->getCenterLocation()) > 320)
00232                                 {
00233                                         doneSomething = true;
00234                                         mUnit->move(mData->getBase()->getCenterLocation());
00235                                         //BWAPI::Broodwar->drawTextMap(mUnit->getPosition().x(), mUnit->getPosition().y() - 10, "Moving Closer to base");
00236                                 }
00237                         }
00238 
00239                         if(!doneSomething)
00240                         {
00241                                 Unit unit = mData->getBase()->getClosestEnemyBuilding(mData->getBase()->getCenterLocation());
00242 
00243                                 if(unit)
00244                                 {
00245                                         if(mUnit->isInRange(unit))
00246                                         {
00247                                                 doneSomething = true;
00248                                                 mUnit->attack(unit);
00249                                         }
00250                                         else
00251                                         {
00252                                                 doneSomething = true;
00253                                                 mHarrasTimer = 72;
00254                                                 mUnit->move(unit->getPosition());
00255                                         }
00256 
00257                                         if(mHarrasTimer > 0)
00258                                                 --mHarrasTimer;
00259                                 }
00260                         }
00261                 }
00262                 else if(mCurrentState == ScoutState::DoubleCheck)
00263                         mUnit->move(mData->getBase()->getCenterLocation());
00264         }
00265 
00266         return hasEnded() && !mUnit;
00267 }
00268 
00269 bool WorkerScoutTask::waitingForUnit(Unit unit) const
00270 {
00271         return false;
00272 }
00273 
00274 void WorkerScoutTask::giveUnit(Unit unit)
00275 {
00276         assert(mUnit == StaticUnits::nullunit);
00277         mUnit = unit;
00278         mFailTime = BWAPI::Broodwar->getFrameCount() + 24*60;
00279 }
00280 
00281 void WorkerScoutTask::returnUnit(Unit unit)
00282 {
00283         assert(mUnit == unit);
00284 
00285         if(mData && !mUnit->exists())
00286         {
00287                 ScoutManager::Instance().updateLastScoutType(mData, mCurrentState == ScoutState::Harassing ? ScoutType::BaseSearch : BWAPI::Broodwar->getFrameCount() < 8000 ? ScoutType::FailedWithGroundLow : ScoutType::FailedWithGroundHigh);
00288                 complete();
00289         }
00290         
00291         mUnit = StaticUnits::nullunit;
00292 }
00293 
00294 bool WorkerScoutTask::morph(Unit unit, BWAPI::UnitType previousType)
00295 {
00296         return true;
00297 }
00298 
00299 UnitGroup WorkerScoutTask::getFinishedUnits()
00300 {
00301         UnitGroup returnUnits;
00302 
00303         returnUnits.insert(mUnit);
00304 
00305         return returnUnits;
00306 }
00307 
00308 int WorkerScoutTask::getPriority(Unit unit) const
00309 {
00310         if(unit == mUnit && mCurrentState != ScoutState::Harassing)
00311                 return 50;
00312         else
00313                 return 30;
00314 }
00315 
00316 void WorkerScoutTask::updateRequirements()
00317 {
00318         clearRequirements();
00319 
00320         if(!mUnit && !shouldReturnUnit() && mData)
00321         {
00322                 mFailTime = BWAPI::Broodwar->getFrameCount() + 24*10;
00323 
00324                 RequirementGroup requirementOne;
00325                 requirementOne.addUnitFilterRequirement(30, Requirement::maxTime, UnitFilter(UnitFilterFlags::IsWorker) && UnitFilter(UnitFilterFlags::IsComplete), mData->getNextPosition());
00326                 addRequirement(requirementOne);
00327         }
00328 }
00329 
00330 void WorkerScoutTask::getNewData()
00331 {
00332         mData = ScoutManager::Instance().getScoutData(ScoutUnitType::Worker);
00333         if(!mData)
00334                 complete();
00335         else if(mUnit && !mUnit->hasPath(mData->getNextPosition(mUnit->getPosition())))
00336         {
00337                 ScoutManager::Instance().updateLastScoutType(mData, ScoutType::CouldNotReachWithGround);
00338                 getNewData();
00339         }
00340         else
00341         {
00342                 mFailTime = BWAPI::Broodwar->getFrameCount() + 24*60;
00343                 mCurrentState = ScoutState::Searching;
00344         }
00345 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines