BWAPI
Skynet/Skynet/BuildOrderManager.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines