BWAPI
Skynet/Skynet/ConstructionTask.cpp
Go to the documentation of this file.
00001 #include "ConstructionTask.h"
00002 #include "Logger.h"
00003 #include "ResourceTracker.h"
00004 #include "MapHelper.h"
00005 #include "DrawBuffer.h"
00006 
00007 ConstructionTask::ConstructionTask(TaskType priority, BuildingLocation position, BWAPI::UnitType type)
00008         : Task(priority)
00009         , mType(type)
00010         , mBuildingLocation(position)
00011         , mReservedResources(false)
00012         , mRequiredSatisfyTime(BWAPI::Broodwar->getFrameCount())
00013         , mRequiredDelayTime(BWAPI::Broodwar->getFrameCount())
00014 {
00015 }
00016 
00017 int ConstructionTask::getEndTime() const
00018 {
00019         if(mProducedUnit)
00020                 return mProducedUnit->getCompletedTime();
00021 
00022         if(mBuilder)
00023                 return BWAPI::Broodwar->getFrameCount() + mType.buildTime();
00024 
00025         if(mRequiredSatisfyTime == Requirement::maxTime)
00026                 return mRequiredSatisfyTime;
00027 
00028         return std::max(mRequiredSatisfyTime, BWAPI::Broodwar->getFrameCount()) + mType.buildTime();
00029 }
00030 
00031 int ConstructionTask::getEndTime(Unit unit) const
00032 {
00033         if(unit->getType() == mType || mType.getRace() == BWAPI::Races::Terran)
00034                 return getEndTime();
00035 
00036         if(mType.getRace() == BWAPI::Races::Protoss)
00037         {
00038                 if(mRequiredSatisfyTime == Requirement::maxTime)
00039                         return mRequiredSatisfyTime;
00040 
00041                 return std::max(BWAPI::Broodwar->getFrameCount(), mRequiredSatisfyTime) + BWAPI::Broodwar->getLatencyFrames();
00042         }
00043         
00044         return Requirement::maxTime;
00045 }
00046 
00047 Position ConstructionTask::getStartLocation(Unit unit) const
00048 {
00049         if(mReservedLocation)
00050                 return mReservedLocation->getPosition();
00051 
00052         return unit->getPosition();
00053 }
00054 
00055 Position ConstructionTask::getEndLocation(Unit unit) const
00056 {
00057         if(mReservedLocation)
00058                 return mReservedLocation->getPosition();
00059 
00060         return unit->getPosition();
00061 }
00062 
00063 bool ConstructionTask::preUpdate()
00064 {
00065         if(mProducedUnit)
00066         {
00067                 if(mProducedUnit->exists())
00068                 {
00069                         freeResources();
00070                         freeLocation();
00071                 }
00072 
00073                 if(!isStopped() && !isCanceled() && mProducedUnit->isCompleted())
00074                 {
00075                         complete();
00076                         return true;
00077                 }
00078         }
00079 
00080         if(mReservedLocation)
00081         {
00082                 if(hasEnded())
00083                         freeLocation();
00084                 else if(isPaused() || isStopped())
00085                 {
00086                         freeResources();
00087 
00088                         mRequiredSatisfyTime = Requirement::maxTime;
00089                         mRequiredDelayTime = Requirement::maxTime;
00090                         mReservedLocation->setStartTime(Requirement::maxTime);
00091                 }
00092         }
00093 
00094         if(!shouldReturnUnit())
00095                 updateRequirements();
00096 
00097         if(mBuilder && finishedWithBuilder() && (mType.getRace() == BWAPI::Races::Protoss || !mBuilder->isConstructing()))
00098                 return true;
00099 
00100         return false;
00101 }
00102 
00103 bool ConstructionTask::update()
00104 {
00105         if(mBuilder)
00106         {
00107                 if(shouldReturnUnit())
00108                 {
00109                         if(!mBuilder->cancel())
00110                                 mBuilder->stop();
00111                 }
00112                 else
00113                 {
00114                         if(!mProducedUnit || !mProducedUnit->exists())
00115                         {
00116                                 if(mReservedLocation && mReservedLocation->isCalculated())
00117                                         mBuilder->build(mReservedLocation->getTilePosition(), mType);
00118                         }
00119                         else if(mType.getRace() == BWAPI::Races::Terran && (!mBuilder->isConstructing() || !mProducedUnit->isBeingConstructed()))
00120                                 mBuilder->build(mProducedUnit);
00121                 }
00122         }
00123 
00124         if((isStopped() || isCanceled()) && mProducedUnit && mProducedUnit->exists())
00125         {
00126                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Attempting to cancel build");
00127                 mProducedUnit->cancel();
00128         }
00129 
00130         return hasEnded() && !mBuilder && !mProducedUnit;
00131 }
00132 
00133 bool ConstructionTask::waitingForUnit(Unit unit) const
00134 {
00135         if(mReservedLocation && mReservedLocation->isCalculated())
00136         {
00137                 if(mReservedLocation->getUnitPrediction() == unit)
00138                         return true;
00139 
00140                 if(mType.isRefinery() && unit->getTilePosition() == mReservedLocation->getTilePosition())
00141                         return true;
00142         }
00143 
00144         return false;
00145 }
00146 
00147 void ConstructionTask::giveUnit(Unit unit)
00148 {
00149         if(unit->getType() == mType.whatBuilds().first)
00150         {
00151                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Given Builder");
00152                 assert(!mBuilder);
00153                 mBuilder = unit;
00154                 reserveResources();
00155         }
00156         else if(unit == mReservedLocation->getUnitPrediction() || unit->getTilePosition() == mReservedLocation->getTilePosition())
00157         {
00158                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Given Produced Unit");
00159 
00160                 assert(!mProducedUnit || !mProducedUnit->exists());
00161 
00162                 mProducedUnit = unit;
00163                 if(mProducedUnit->exists())
00164                 {
00165                         freeResources();
00166                         freeLocation();
00167                 }
00168         }
00169         else
00170                 assert(false);
00171 }
00172 
00173 void ConstructionTask::returnUnit(Unit unit)
00174 {
00175         if(unit == mBuilder)
00176         {
00177                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Returning Builder");
00178                 freeResources();
00179                 mBuilder = StaticUnits::nullunit;
00180         }
00181         else if(unit == mProducedUnit)
00182         {
00183                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Returning Produced Unit");
00184                 freeResources();
00185                 mProducedUnit = StaticUnits::nullunit;
00186         }
00187         else
00188                 assert(!unit->exists());//If it doesn't exist it was a prediction that has been replaced
00189 }
00190 
00191 bool ConstructionTask::morph(Unit unit, BWAPI::UnitType previousType)
00192 {
00193         if(unit == mBuilder && unit->getType() == mType)
00194         {
00195                 freeLocation();
00196                 freeResources();
00197 
00198                 mProducedUnit = unit;
00199                 mBuilder = StaticUnits::nullunit;
00200 
00201                 return false;
00202         }
00203 
00204         return true;
00205 }
00206 
00207 UnitGroup ConstructionTask::getFinishedUnits()
00208 {
00209         UnitGroup returnUnits;
00210 
00211         if(mBuilder && finishedWithBuilder())
00212                 returnUnits.insert(mBuilder);
00213 
00214         if(mProducedUnit && mProducedUnit->exists() && isCompleted())
00215                 returnUnits.insert(mProducedUnit);
00216 
00217         return returnUnits;
00218 }
00219 
00220 int ConstructionTask::getPriority(Unit unit) const
00221 {
00222         if(unit == mProducedUnit || (mReservedLocation && unit == mReservedLocation->getUnitPrediction()))
00223                 return 100;
00224 
00225         return 40;
00226 }
00227 
00228 void ConstructionTask::updateRequirements()
00229 {
00230         clearRequirements();
00231 
00232         if(!hasEnded())
00233         {
00234                 reserveLocation();
00235 
00236                 if(!finishedWithBuilder() && !mBuilder && (mProducedUnit || (mReservedLocation && mReservedLocation->isCalculated())))
00237                 {
00238                         Position location = mProducedUnit ? mProducedUnit->getPosition() : mReservedLocation->getPosition();
00239                         int neededDuration = mType.getRace() == BWAPI::Races::Protoss ? BWAPI::Broodwar->getLatencyFrames() : mType.getRace() == BWAPI::Races::Zerg ? Requirement::maxTime : mType.buildTime();
00240 
00241                         RequirementGroup requiredConditions;
00242                         requiredConditions.addUnitFilterRequirement(40, neededDuration, UnitFilter(mType.whatBuilds().first) && UnitFilter(UnitFilterFlags::IsComplete), location);
00243 
00244                         if(!mReservedResources && (!mProducedUnit || !mProducedUnit->exists()))
00245                         {
00246                                 requiredConditions.addTechForTypeRequirement(mType);
00247 
00248                                 if(mType.mineralPrice() > 0) requiredConditions.addMineralRequirement(mType.mineralPrice());
00249                                 if(mType.gasPrice() > 0) requiredConditions.addGasRequirement(mType.gasPrice());
00250                                 if(mType.supplyRequired() > 0) requiredConditions.addSupplyRequirement(mType.supplyRequired());
00251                         }
00252 
00253                         addRequirement(requiredConditions);
00254                 }
00255         }
00256 }
00257 
00258 void ConstructionTask::reserveResources()
00259 {
00260         if(!mReservedResources && !inProgress() && !hasEnded())
00261         {
00262                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Reserving Resources");
00263 
00264                 ResourceTracker::Instance().reserveCurrentMinerals(mRequiredSatisfyTime, mType.mineralPrice());
00265                 ResourceTracker::Instance().reserveCurrentGas(mRequiredSatisfyTime, mType.gasPrice());
00266                 ResourceTracker::Instance().reserveCurrentSupply(mRequiredSatisfyTime, mType.supplyRequired());
00267                 mReservedResources = true;
00268         }
00269 }
00270 
00271 void ConstructionTask::freeResources()
00272 {
00273         if(mReservedResources)
00274         {
00275                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Freeing Resources");
00276 
00277                 ResourceTracker::Instance().releaseCurrentMinerals(mRequiredSatisfyTime, mType.mineralPrice());
00278                 ResourceTracker::Instance().releaseCurrentGas(mRequiredSatisfyTime, mType.gasPrice());
00279                 ResourceTracker::Instance().releaseCurrentSupply(mRequiredSatisfyTime, mType.supplyRequired());
00280                 mReservedResources = false;
00281         }
00282 }
00283 
00284 void ConstructionTask::reserveLocation()
00285 {
00286         if(!mReservedLocation && !inProgress() && !hasEnded())
00287         {
00288                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Reserving Location");
00289                 mReservedLocation = BuildingPlacer::Instance().getBuildingReservation(mBuildingLocation, mType);
00290                 assert(!mReservedLocation->update());
00291         }
00292 }
00293 
00294 void ConstructionTask::freeLocation()
00295 {
00296         if(mReservedLocation)
00297         {
00298                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Freeing Location");
00299                 mReservedLocation->forceCompleted();
00300                 mReservedLocation.reset();
00301         }
00302 }
00303 
00304 void ConstructionTask::setRequiredSatisfyTime(RequirementGroup requirements, int time, int delay)
00305 {
00306         if(!mReservedResources)
00307         {
00308                 mRequiredSatisfyTime = time;
00309                 mRequiredDelayTime = delay;
00310         }
00311         else
00312                 LOGMESSAGE(String_Builder() << "ConstructionTask : " << mType.getName() << " : Required Satisfy Time changed while resources are reserved");
00313 
00314         if(mReservedLocation)
00315                 mReservedLocation->setStartTime(time);
00316 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines