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