BWAPI
|
00001 #include "BuildOrderManager.h" 00002 00003 #include "Logger.h" 00004 #include "MacroManager.h" 00005 #include "SquadManager.h" 00006 00007 #include <ctime> 00008 #include <boost/random.hpp> 00009 00010 BuildOrderManagerClass::BuildOrderManagerClass() 00011 : mCurrentBuild(BuildOrderID::None) 00012 , mFinishedBuild(false) 00013 , mBuildFinishTime(0) 00014 { 00015 } 00016 00017 void BuildOrderManagerClass::onBegin() 00018 { 00019 LoadOtherBuilds(); 00020 LoadProtossBuilds(); 00021 LoadTerranBuilds(); 00022 LoadZergBuilds(); 00023 } 00024 00025 BuildOrderID getRandomBuild(const std::vector<BuildOrderID> &builds) 00026 { 00027 if(builds.empty()) 00028 return BuildOrderID::Unknown; 00029 00030 static boost::mt19937 rng(static_cast<unsigned int>(std::time(0))); 00031 boost::uniform_int<> dist(0, builds.size() - 1); 00032 boost::variate_generator<boost::mt19937, boost::uniform_int<>> randIndex(rng, dist); 00033 00034 return builds[randIndex()]; 00035 } 00036 00037 void BuildOrderManagerClass::update() 00038 { 00039 if(mCurrentBuild == BuildOrderID::None) 00040 { 00041 std::vector<BuildOrderID> viableBuilds; 00042 for each(std::pair<BuildOrderID, BuildOrder> build in mBuildOrders) 00043 { 00044 if(build.second.getRace() != BWAPI::Broodwar->self()->getRace()) 00045 continue; 00046 00047 if(build.second.isStartBuild()) 00048 viableBuilds.push_back(build.first); 00049 } 00050 00051 changeCurrentBuild(getRandomBuild(viableBuilds)); 00052 } 00053 00054 if(BuildOrderFinished()) 00055 { 00056 if(!mFinishedBuild) 00057 { 00058 mBuildFinishTime = BWAPI::Broodwar->getFrameCount(); 00059 mFinishedBuild = true; 00060 } 00061 00062 std::vector<BuildOrderID> viableBuilds; 00063 for(std::map<BuildOrderID, Condition>::const_iterator i = mBuildOrders[mCurrentBuild].getNextBuilds().begin(); i != mBuildOrders[mCurrentBuild].getNextBuilds().end(); ++i) 00064 { 00065 if(i->second.evauluate()) 00066 viableBuilds.push_back(i->first); 00067 } 00068 00069 if(!viableBuilds.empty()) 00070 changeCurrentBuild(getRandomBuild(viableBuilds)); 00071 else if(mBuildOrders[mCurrentBuild].getFallbackBuild() != BuildOrderID::None && mBuildOrders[mCurrentBuild].getFallbackTime() < BWAPI::Broodwar->getFrameCount() - mBuildFinishTime) 00072 changeCurrentBuild(mBuildOrders[mCurrentBuild].getFallbackBuild()); 00073 } 00074 checkBuildStatus(); 00075 00076 if(mShowDebugInfo) 00077 { 00078 int y = 25; 00079 BWAPI::Broodwar->drawTextScreen(5, 5, "Build: %s", mBuildOrders[mCurrentBuild].getName().c_str()); 00080 BWAPI::Broodwar->drawTextScreen(5, 15, "Orders:"); 00081 for(std::map<Order, bool>::iterator it = mControlValues.begin(); it != mControlValues.end(); ++it) 00082 { 00083 if(it->second) 00084 { 00085 BWAPI::Broodwar->drawTextScreen(5, y, "%s", getOrderName(it->first).c_str()); 00086 y += 10; 00087 } 00088 } 00089 } 00090 } 00091 00092 void BuildOrderManagerClass::BuildCallback(int buildID, CallBackType callbackType) 00093 { 00094 for(std::list<BuildItem>::iterator buildItem = mItemsWaiting.begin(); buildItem != mItemsWaiting.end();) 00095 { 00096 buildItem->removeCallback(buildID, callbackType); 00097 00098 if(buildItem->isFulfilled()) 00099 { 00100 handleBuildItem(*buildItem); 00101 mItemsWaiting.erase(buildItem++); 00102 } 00103 else 00104 ++buildItem; 00105 } 00106 00107 for(std::list<OrderItem>::iterator orderItem = mOrdersWaiting.begin(); orderItem != mOrdersWaiting.end();) 00108 { 00109 orderItem->removeCallback(buildID, callbackType); 00110 00111 if(orderItem->isFulfilled()) 00112 { 00113 handleOrderItem(*orderItem); 00114 mOrdersWaiting.erase(orderItem++); 00115 } 00116 else 00117 ++orderItem; 00118 } 00119 } 00120 00121 bool BuildOrderManagerClass::BuildOrderFinished() 00122 { 00123 return mItemsWaiting.empty() && mOrdersWaiting.empty(); 00124 } 00125 00126 void BuildOrderManagerClass::changeCurrentBuild(BuildOrderID ID) 00127 { 00128 if(mBuildOrders.find(ID) == mBuildOrders.end()) 00129 { 00130 LOGMESSAGEWARNING(String_Builder() << "Couldn't find Build Order"); 00131 changeCurrentBuild(BuildOrderID::Unknown); 00132 return; 00133 } 00134 00135 if(mBuildOrders[ID].getRace() != BWAPI::Broodwar->self()->getRace() && mBuildOrders[ID].getRace() != BWAPI::Races::Unknown) 00136 { 00137 LOGMESSAGE(String_Builder() << "Build " << mBuildOrders[ID].getName() << " is for " << mBuildOrders[ID].getRace().getName()); 00138 return; 00139 } 00140 00141 mFinishedBuild = false; 00142 mItemsWaiting.clear(); 00143 mOrdersWaiting.clear(); 00144 mControlValues.clear(); 00145 00146 const BuildOrder &order = mBuildOrders[ID]; 00147 00148 if(ID != BuildOrderID::Unknown) 00149 LOGMESSAGEWARNING(String_Builder() << ((mCurrentBuild == BuildOrderID::None) ? "Opening with " : "Transitioning to ") << order.getName()); 00150 00151 mCurrentBuild = ID; 00152 00153 for each(const OrderItem &item in order.getOrderItems()) 00154 { 00155 if(item.isFulfilled()) 00156 handleOrderItem(item); 00157 else 00158 mOrdersWaiting.push_back(item); 00159 } 00160 00161 for each(const BuildItem &item in order.getBuildItems()) 00162 { 00163 if(item.isFulfilled()) 00164 handleBuildItem(item); 00165 else 00166 mItemsWaiting.push_back(item); 00167 } 00168 00169 MacroManager::Instance().onChangeBuild(); 00170 SquadManager::Instance().onChangeBuild(); 00171 } 00172 00173 void BuildOrderManagerClass::handleOrderItem(const OrderItem &item) 00174 { 00175 toggleOrder(item.getType()); 00176 00177 LOGMESSAGE(String_Builder() << "Handled Order " << getOrderName(item.getType()) << (getOrder(item.getType()) ? ": Set to True" : ": Set to False")); 00178 LOGMESSAGE(String_Builder() ); 00179 } 00180 00181 void BuildOrderManagerClass::toggleOrder(Order type) 00182 { 00183 if(mControlValues.find(type) != mControlValues.end()) 00184 { 00185 mControlValues[type] = !mControlValues[type]; 00186 } 00187 else 00188 mControlValues[type] = true; 00189 } 00190 00191 void BuildOrderManagerClass::checkBuildStatus() 00192 { 00193 for(std::map<CallBackType, std::map<TaskPointer, int>>::iterator i = mWaitingItems.begin(); i != mWaitingItems.end();) 00194 { 00195 for(std::map<TaskPointer, int>::iterator u = i->second.begin(); u != i->second.end();) 00196 { 00197 if(i->first == CallBackType::onDispatched && u->first->hasDispatched()) 00198 { 00199 BuildCallback(u->second, CallBackType::onDispatched); 00200 i->second.erase(u++); 00201 } 00202 else if(i->first == CallBackType::onStarted && u->first->inProgress()) 00203 { 00204 BuildCallback(u->second, CallBackType::onStarted); 00205 i->second.erase(u++); 00206 } 00207 else if(i->first == CallBackType::onCompleted && u->first->isCompleted()) 00208 { 00209 BuildCallback(u->second, CallBackType::onCompleted); 00210 i->second.erase(u++); 00211 } 00212 else 00213 ++u; 00214 } 00215 00216 if(i->second.empty()) 00217 mWaitingItems.erase(i++); 00218 else 00219 ++i; 00220 } 00221 } 00222 00223 void BuildOrderManagerClass::handleBuildItem(const BuildItem &item) 00224 { 00225 TaskPointer ptr = item.createTask(); 00226 if(ptr) 00227 { 00228 mWaitingItems[CallBackType::onDispatched][ptr] = item.getID(); 00229 mWaitingItems[CallBackType::onStarted][ptr] = item.getID(); 00230 mWaitingItems[CallBackType::onCompleted][ptr] = item.getID(); 00231 } 00232 else 00233 { 00234 BuildCallback(item.getID(), CallBackType::onDispatched); 00235 BuildCallback(item.getID(), CallBackType::onStarted); 00236 BuildCallback(item.getID(), CallBackType::onCompleted); 00237 } 00238 } 00239 00240 std::string BuildOrderManagerClass::getOrderName(Order type) 00241 { 00242 switch(type.underlying()) 00243 { 00244 case Order::TrainWorkers: 00245 return "Train Workers"; 00246 case Order::Scout: 00247 return "Scout"; 00248 case Order::SupplyManager: 00249 return "Supply Manager"; 00250 case Order::RefineryManager: 00251 return "Refinery Manager"; 00252 case Order::MacroArmyProduction: 00253 return "Army Train Manager"; 00254 case Order::CanRemoveSquads: 00255 return "Can Remove Squads"; 00256 case Order::ExpansionManager: 00257 return "Expansion Manager"; 00258 case Order::MacroProductionFacilities: 00259 return "Macro : Can Produce Production Facilities"; 00260 case Order::MacroCanTech: 00261 return "Macro : Can Tech"; 00262 } 00263 return "None"; 00264 }