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