Skip to content

UAlbertaBot Build Orders

David Churchill edited this page Mar 6, 2020 · 10 revisions

Build Order Overview

Strategies in UAlbertaBot are defined in the bot's configuration file. You define a strategy by giving it a name and declaring an opening build order. You then specify which strategy that the bot is currently using.

All unit production in UAlbertaBot is handled by the ProductionManager class, which is a globally accessible singleton class. To access it from outside itself, call Global::Production()

ProductionManager's constructor sets the opening build order that you specified in your strategy:

  • Initially set build order to 'opening book' build order from StrategyManager
    • These opening book build orders will occur in entirety until an event happens which triggers a new build order to be searched

The control flow for ProductionManager.update() which is called every frame:

  • If an event occurs which triggers a new build order (events listed below)
    • Clear the current build order
    • Get new build order goal from StrategyManager. The goal returned is dependent on which strategy is currently active.
    • Pass goal into the BOSS (Build Order Search System) Project
    • Set build order to the returned result
  • If current build order contains items
    • If the highest priority item can be built
      • Build the highest priority item

The events under which a new build order are triggered are listed below

Implementation

Build orders in UAlbertaBot are handled by the BuildOrderQueue class, which stores a priority-sorted queue of BuildOrderItem objects.

class BuildOrderItem 
{
   MetaType   metaType;
   int        priority;
   bool       blocking;
};

A BuildOrderItem is a container which holds

  • MetaType object - A custom container for all BWAPI buildable types
  • priority - The priority of the item in the queue
  • blocking - Whether the object 'blocks' the next item in the build order. If an item is blocking, items with lower priority in the queue can be built until it is made. If an item is not blocking, the next item in the queue will be built if its resources are available before the that item. To ensure a build order will be executed in exact order, set all items blocking to true.

A MetaType object is a custom class which is able to store either of the three BWAPI buildable/trainable types. It holds either a BWAPI::UnitType, BWAPI::TechType or BWAPI::UpgradeType. It was created so that the BuildOrderQueue only needs to store a single object type. To create a MetaType simply call its constructor with one of the 3 listed types, or a string corresponding to a type:

MetaType type(BWAPI::UnitTypes::Marine);
MetaType type2(BWAPI::UpgradeTypes::Leg_Enhancements);
MetaType type3("Protoss_Probe");

BuildOrderItems are then inserted into the BuildOrderQueue by calling one of the following:

void BuildOrderQueue::queueItem(BuildOrderItem<PRIORITY_TYPE> b);
void BuildOrderQueue::queueAsHighestPriority(MetaType m, bool blocking);
void BuildOrderQueue::queueAsLowestPriority(MetaType m, bool blocking);

If queueItem is called, its priority level must be set manually by the user. It is recommended to only use the highest / lowest priority insert methods.

Example Build Order

As an example, let's say we want to build the following items in order:

  1. Protoss Probe
  2. Protoss Probe
  3. Protoss Pylon
  4. Protoss Probe
  5. Protoss Gateway
  6. Protoss Zealot

You could insert each of these items into the BuildOrderQueue yourself from the ProductionManager, however a function already exists to do this job for you:

void ProductionManager::setBuildOrder(const BuildOrder & buildOrder);

This method takes as input a BuildOrder object, clears the current BuildOrderQueue and inserts each type to be built in order. So the safest and easiest way to set a custom build order is to call the following code somewhere within ProductionManager:

BuildOrder buildOrder;

buildOrder.add(MetaType(BWAPI::UnitTypes::Protoss_Probe));
buildOrder.add(MetaType(BWAPI::UnitTypes::Protoss_Probe));
buildOrder.add(MetaType(BWAPI::UnitTypes::Protoss_Pylon));
buildOrder.add(MetaType(BWAPI::UnitTypes::Protoss_Probe));
buildOrder.add(MetaType(BWAPI::UnitTypes::Protoss_Gateway));
buildOrder.add(MetaType(BWAPI::UnitTypes::Protoss_Zealot));

setBuildOrder(buildOrder);

Build Order Goals & Planning

UAlbertaBot uses a heuristic search algorithm to dynamically plan all build orders, which is included as the BOSS project. All interaction to the algorithms in this project are handled in UAlbertaBot via the BOSSManager class, which is called from ProductionManager.performBuildOrderSearch(). You can treat the BOSS system as a black box which when given a build order goal, creates an ordered vector of MetaType objects similar to the example above.

ProductionManager will trigger a new build order to be planned based on one of the following events occurring:

  • The first build order of the game is obtained via an 'opening book' of build orders in the constructor of ProductionManager
  • If the current BuildOrderQueue is empty
  • If a supply deadlock is detected (we have too little supply to build a unit)
  • If a critical unit (building or worker) has died
  • If an enemy cloaked unit is detected

For each of these events, a new build order goal is obtained via

const MetaPairVector StrategyManager::getBuildOrderGoal()

If you wish to alter the build order goal strategy of UAlbertaBot, you simply need to modify that function. However if you want to alter UAlbertaBot to not use its automatic planning system, this must be done by rewriting your own planning system inside

void ProductionManager::performBuildOrderSearch(const std::vector & goal)

Overriding Build Order Search

As mentioned above, by default UAlbertaBot uses a heuristic search algorithm to determine build orders from a goal vector of units. This system can be overridden by constructing your own build orders. Simply remove any code inside ProductionManager which calls the function performBuildOrderSearch() which sets the build order based on the search algorithm and replace this with your own custom build order code. You can then set the build order in ProductionManager using the method described above in the "Example Build Order" section.