TorchCraftAI
A bot for machine learning research on StarCraft: Brood War
autobuild.h
1 /*
2  * Copyright (c) 2017-present, Facebook, Inc.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #pragma once
9 
10 #include "buildtype.h"
11 #include "cherrypi.h"
12 #include "module.h"
13 #include "state.h"
14 
15 #include <array>
16 #include <deque>
17 #include <functional>
18 #include <unordered_map>
19 #include <unordered_set>
20 #include <vector>
21 
22 namespace cherrypi {
23 
24 namespace autobuild {
25 
27  const BuildType* type = nullptr;
28  int busyUntil = 0;
29  const BuildType* addon = nullptr;
30  int larvaTimer = 0;
31 };
32 
33 struct BuildEntry {
34  const BuildType* type = nullptr;
36  std::function<void()> builtCallback;
37 
38  bool operator==(BuildEntry n) const {
39  return type == n.type && pos == n.pos;
40  }
41  bool operator!=(BuildEntry n) const {
42  return type != n.type || pos != n.pos;
43  }
44 };
45 
46 /**
47  * Describes a state of the game, either now or in a hypothetical future,
48  * for use in AutoBuilds.
49  *
50  * At the start of an AutoBuild, this reflects the current game state.
51  * At each buildStep(), the BuildState is updated to reflect the
52  * units/upgrades/tech purchased in the previous buildSteps().
53  */
54 struct BuildState {
55  int frame = 0;
56  int race = 0;
57  double minerals = 0;
58  double gas = 0;
59  double mineralsPerFramePerGatherer = 0;
60  double gasPerFramePerGatherer = 0;
61  std::array<double, 3> usedSupply{};
62  std::array<double, 3> maxSupply{};
63  std::array<double, 3> inprodSupply{};
64  std::unordered_map<const BuildType*, std::vector<BuildStateUnit>> units;
65  std::unordered_set<const BuildType*> upgradesAndTech;
66  std::deque<std::pair<int, const BuildType*>> production;
67  std::vector<std::pair<int, BuildEntry>> buildOrder;
68  std::vector<BuildStateUnit> morphingHatcheries;
69 
70  int workers = 0;
71  int refineries = 0;
72  int availableGases = 0;
73 
74  bool autoBuildRefineries = true;
75  bool autoBuildHatcheries = true;
76  bool isExpanding = false;
77 };
78 
79 // Cerealization
80 // XXX This is quite a hack, but for now we can't build this on Windows. We'll
81 // have to figure this out together with the Windows build. If we can't get it
82 // to work it's not dramatic, we just might have to add a few ifdefs to the BOS
83 // training code.
84 template <class Archive>
85 void save(Archive& archive, BuildStateUnit const& stu);
86 template <class Archive>
87 void load(Archive& archive, BuildStateUnit& stu);
88 template <class Archive>
89 void save(Archive& archive, BuildEntry const& e);
90 template <class Archive>
91 void load(Archive& archive, BuildEntry& e);
92 template <class Archive>
93 void save(Archive& archive, BuildState const& stu);
94 template <class Archive>
95 void load(Archive& archive, BuildState& stu);
96 
97 } // namespace autobuild
98 
99 /**
100  * AutoBuildTasks are "build orders" in the colloquial sense.
101  * You can subclass AutoBuildTask to design a build order.
102  *
103  * In practice, build orders are usually based on a subclass of AutoBuildTask
104  * called ABBOBase (AutoBuild Build Order Base) which provides handy
105  * convenience methods.
106  */
108  private:
109  autobuild::BuildState targetBuildState;
110  Module* module_ = nullptr;
111 
112  public:
113  int lastEvaluate = 0;
114 
117 
118  State* state_ = nullptr;
119 
120  bool isSimulation = false;
121 
122  /// Each of these UPCs is being proxied by this task.
123  std::unordered_map<UpcId, std::tuple<autobuild::BuildEntry, float>>
125  std::function<bool(autobuild::BuildState&)> queue;
126 
127  void postBlackboardKey(std::string const& key, Blackboard::Data const& data);
128  bool cancelGas();
129 
130  AutoBuildTask(int upcId, State* state, Module* module)
131  : MultiProxyTask({}, upcId), module_(module), state_(state) {
132  setStatus(TaskStatus::Ongoing);
133  }
134  virtual ~AutoBuildTask() override {}
135 
136  virtual void update(State* state) override;
137 
138  void evaluate(State* state, Module* module);
139 
140  void simEvaluateFor(autobuild::BuildState& st, FrameNum frames);
141 
142  /**
143  * One of the three steps of processing a build order.
144  * preBuild() is invoked once before stepping through the build order.
145  *
146  * Because it's invoked exactly once (unlike buildStep() which is invoked
147  * repeatedly) preBuild is a good place for making decisions that don't
148  * directly involve the build queue, like deciding whether to attack or
149  * deciding whether to mine gas.
150  */
151  virtual void preBuild(autobuild::BuildState& st) {}
152 
153  /**
154  * The meat of a build order lives in buildStep(). This is where you decide
155  * what to build, and in what order.
156  *
157  * Here's how buildStep() works:
158  *
159  * After preBuild(), AutoBuildTask invokes buildStep() with a BuildState
160  * reflecting the current state of the game. That includes the amount of
161  * minerals, gas, and supply you have. It also has an empty queue of things
162  * to build.
163  *
164  * In your implementation of buildStep(), you can specify everything you want
165  * to build, via methods like build() and upgrade(). These methods add
166  * your requested items to the queue in BuildState.
167  *
168  * However, *only the last request* which would modify the queue actually
169  * modifies the BuildState. This request goes to the end of the build queue.
170  * The BuildState updates to reflect the request: minerals/gas is spent,
171  * supply is updated, etc.
172  *
173  * Then, if anything was changed, buildStep() is invoked again with the new
174  * BuildState. The last request from the previous build is now reflected in
175  * the new BuildState. For example, if you have no Spawning Pool, and the
176  * last request was buildN(Spawning_Pool, 1), the BuildState will now
177  * contain the Spawning Pool you requested.
178  *
179  * This continues until either the queue has reached a certain length
180  * (several minutes into the future) or all requests are enqueued.
181  */
182  virtual void buildStep(autobuild::BuildState& st) {}
183 
184  /**
185  * The final step of processing a build order.
186  * postBuild() is invoked after the last invocation of buildStep().
187  */
188  virtual void postBuild(autobuild::BuildState& st) {}
189 
190  /// Builds a building at a specific position.
191  /// Invokes a callback when we attempt to begin construction.
192  /// Enqueues any required but missing prerequisites
193  /// (like adding a Lair if you request a Spire).
194  void build(
195  const BuildType* type,
196  Position pos,
197  std::function<void()> builtCallback);
198 
199  /// Builds a unit/building, upgrade, or technology.
200  /// Invokes a callback when we attempt to begin construction.
201  /// Enqueues any required but missing prerequisites
202  /// (like adding a Spire if you request a Mutalisk).
203  void build(const BuildType* type, std::function<void()> builtCallback);
204 
205  /// Builds a building at a specific position.
206  /// Enqueues any required but missing prerequisites
207  /// (like adding a Lair if you request a Spire).
208  void build(const BuildType* type, Position pos);
209 
210  /// Builds a unit/building, upgrade, or technology.
211  /// Enqueues any required but missing prerequisites
212  /// (like adding a Lair if you request a Spire).
213  void build(const BuildType* type);
214 
215  /// Builds up to N of a unit/building.
216  /// Enqueues any required but missing prerequisites
217  /// like adding a Lair if you request a Spire).
218  bool buildN(const BuildType* type, int n);
219 
220  /// Builds up to N of a unit/building,
221  /// with an optional limit on how many to build consecutively.
222  /// Enqueues any required but missing prerequisites
223  /// like adding a Lair if you request a Spire).
224  bool buildN(const BuildType* type, int n, int simultaneous);
225 
226  /// Builds up to N of a building, specifying a position for the next
227  /// new building.
228  /// Enqueues any required but missing prerequisites
229  /// (like adding a Lair if you request a Spire).
230  bool buildN(const BuildType* type, int n, Position positionIfWeBuildMore);
231 
232  /// Researches an Upgrade or Tech
233  /// Enqueues any required but missing prerequisites
234  /// (like adding a Lair if you request Lurker Aspect).
235  bool upgrade(const BuildType* type);
236 
238  return initialBuildState;
239  }
241  return targetBuildState;
242  }
243 
244  private:
245  std::string frameToString(State* state);
246  std::vector<std::vector<std::string>> unitsToString(State* state);
247  std::vector<std::vector<std::string>> productionToString(State* state);
248  std::vector<std::vector<std::string>> queueToString(State* state);
249  std::vector<std::string> upgradesToString(State* state);
250  std::vector<std::string> describeState(State* state);
251  int logInvocations = 0;
252  void log(State* state);
253 
254  protected:
255  /**
256  * Draws any debugging information to the screen
257  */
258  virtual void draw(State* state);
259 };
260 
261 class AutoBuildModule : public Module {
262  public:
263  virtual ~AutoBuildModule() = default;
264 
265  virtual std::shared_ptr<AutoBuildTask>
266  createTask(State* state, int srcUpcId, std::shared_ptr<UPCTuple> srcUpc);
267 
268  virtual void checkForNewUPCs(State* state);
269 
270  virtual void step(State* state) override;
271 };
272 
273 /**
274  * A very simple build order which builds a fixed list of targets and then
275  * stops.
276  *
277  * Intended for testing purposes.
278  */
280  public:
281  struct Target {
282  BuildType const* type;
283  int n;
284 
285  Target(BuildType const* type, int n = -1) : type(type), n(n) {}
286  };
287 
288  std::vector<Target> targets;
289 
291  int upcId,
292  State* state,
293  Module* module,
294  std::vector<Target> targets)
295  : AutoBuildTask(upcId, state, module), targets(std::move(targets)) {}
296  virtual ~DefaultAutoBuildTask() override {}
297 
298  virtual void buildStep(autobuild::BuildState& st) override {
299  for (auto& target : targets) {
300  if (target.n == -1) {
301  build(target.type);
302  } else {
303  buildN(target.type, target.n);
304  }
305  }
306  }
307 };
308 
309 namespace autobuild {
310 BuildState getMyState(State* state);
311 
312 /// Returns true if we have this unit in this BuildState.
313 bool hasUnit(const BuildState& st, const BuildType* type);
314 
315 /// Returns true if we have this upgrade in this BuildState.
316 bool hasUpgrade(const BuildState& st, const BuildType* type);
317 
318 /// Returns true if we have this tech in this BuildState.
319 bool hasTech(const BuildState& st, const BuildType* type);
320 
321 /// Returns true if we have any of this BuildType completed in this BuildState.
322 bool has(const BuildState& st, const BuildType* type);
323 
324 /// Returns the number of completed units of this BuildType in this BuildState.
325 int countUnits(const BuildState& st, const BuildType* type);
326 
327 /// Returns true if we are currently producing this BuildType in this
328 /// BuildState.
329 bool isInProduction(const BuildState& st, const BuildType* type);
330 
331 /// Returns true if we have this BuildType in this
332 /// BuildState, either complete or in production.
333 bool hasOrInProduction(const BuildState& st, const BuildType* type);
334 
335 /// Returns how many frames before a type will be available
336 /// Defaults to kForever if the type isn't complete or enqueued
337 int framesUntil(const BuildState& st, const BuildType* type);
338 
339 /// Returns the number of this BuildType in production in this BuildState.
340 int countProduction(const BuildState& st, const BuildType* type);
341 
342 /// Returns the number of this BuildType this BuildState, either complete or
343 /// in production.
344 int countPlusProduction(const BuildState& st, const BuildType* type);
345 
346 /// Returns the number of Larva at this Hatchery/Lair/Hive in this BuildState.
347 int larvaCount(const BuildState& st, const BuildStateUnit&);
348 } // namespace autobuild
349 
350 } // namespace cherrypi
BuildType const * type
Definition: autobuild.h:282
BuildState getMyState(State *state)
Definition: autobuild.cpp:212
Game state.
Definition: state.h:42
Definition: autobuild.h:26
bool operator!=(BuildEntry n) const
Definition: autobuild.h:41
std::unordered_map< UpcId, std::tuple< autobuild::BuildEntry, float > > scheduledUpcs
Each of these UPCs is being proxied by this task.
Definition: autobuild.h:124
int FrameNum
Definition: basetypes.h:22
Target(BuildType const *type, int n=-1)
Definition: autobuild.h:285
autobuild::BuildState initialBuildState
Definition: autobuild.h:115
DefaultAutoBuildTask(int upcId, State *state, Module *module, std::vector< Target > targets)
Definition: autobuild.h:290
int busyUntil
Definition: autobuild.h:28
Represents and holds information about buildable types (units, upgrades, techs).
Definition: buildtype.h:36
int larvaCount(const autobuild::BuildState &st, const autobuild::BuildStateUnit &u)
Returns the number of Larva at this Hatchery/Lair/Hive in this BuildState.
Definition: autobuild.cpp:160
STL namespace.
bool has(const BuildState &st, const BuildType *type)
Returns true if we have any of this BuildType completed in this BuildState.
Definition: autobuild.cpp:77
Task is currently ongoing.
A very simple build order which builds a fixed list of targets and then stops.
Definition: autobuild.h:279
std::vector< BuildStateUnit > morphingHatcheries
Definition: autobuild.h:68
int larvaTimer
Definition: autobuild.h:30
void load(Archive &ar, BuildStateUnit &stu)
Definition: autobuild.cpp:1696
autobuild::BuildState & lastEvaluateTargetState()
Definition: autobuild.h:240
const BuildType * type
Definition: autobuild.h:27
Describes a state of the game, either now or in a hypothetical future, for use in AutoBuilds...
Definition: autobuild.h:54
virtual void buildStep(autobuild::BuildState &st)
The meat of a build order lives in buildStep().
Definition: autobuild.h:182
bool isInProduction(const BuildState &st, const BuildType *type)
Returns true if we are currently producing this BuildType in this BuildState.
Definition: autobuild.cpp:106
mapbox::util::variant< bool, int, float, double, std::string, Position, std::shared_ptr< SharedController >, std::unordered_map< int, int >> Data
A variant of types that are allowed in the Blackboard&#39;s key-value storage.
Definition: blackboard.h:99
std::function< bool(autobuild::BuildState &)> queue
Definition: autobuild.h:125
bool operator==(BuildEntry n) const
Definition: autobuild.h:38
A task that tracks execution of multiple other tasks.
Definition: task.h:173
bool hasUnit(const BuildState &st, const BuildType *type)
Returns true if we have this unit in this BuildState.
Definition: autobuild.cpp:61
std::unordered_map< const BuildType *, std::vector< BuildStateUnit > > units
Definition: autobuild.h:64
bool hasTech(const BuildState &st, const BuildType *type)
Returns true if we have this tech in this BuildState.
Definition: autobuild.cpp:73
std::function< void()> builtCallback
Definition: autobuild.h:36
const BuildType * addon
Definition: autobuild.h:29
int countPlusProduction(const BuildState &st, const BuildType *type)
Returns the number of this BuildType this BuildState, either complete or in production.
Definition: autobuild.cpp:140
Definition: autobuild.h:33
virtual ~AutoBuildTask() override
Definition: autobuild.h:134
virtual void postBuild(autobuild::BuildState &st)
The final step of processing a build order.
Definition: autobuild.h:188
int n
Definition: autobuild.h:283
virtual ~DefaultAutoBuildTask() override
Definition: autobuild.h:296
Definition: autobuild.h:261
int countUnits(const BuildState &st, const BuildType *type)
Returns the number of completed units of this BuildType in this BuildState.
Definition: autobuild.cpp:85
AutoBuildTask(int upcId, State *state, Module *module)
Definition: autobuild.h:130
AutoBuildTasks are "build orders" in the colloquial sense.
Definition: autobuild.h:107
void save(Archive &ar, BuildStateUnit const &stu)
Definition: autobuild.cpp:1688
std::vector< std::pair< int, BuildEntry > > buildOrder
Definition: autobuild.h:67
virtual void preBuild(autobuild::BuildState &st)
One of the three steps of processing a build order.
Definition: autobuild.h:151
autobuild::BuildState currentBuildState
Definition: autobuild.h:116
Definition: autobuild.h:281
Position pos
Definition: autobuild.h:35
bool hasOrInProduction(const BuildState &st, const BuildType *type)
Returns true if we have this BuildType in this BuildState, either complete or in production.
Definition: autobuild.cpp:115
int countProduction(const BuildState &st, const BuildType *type)
Returns the number of this BuildType in production in this BuildState.
Definition: autobuild.cpp:131
Main namespace for bot-related code.
Definition: areainfo.cpp:17
virtual void buildStep(autobuild::BuildState &st) override
The meat of a build order lives in buildStep().
Definition: autobuild.h:298
std::unordered_set< const BuildType * > upgradesAndTech
Definition: autobuild.h:65
std::deque< std::pair< int, const BuildType * > > production
Definition: autobuild.h:66
autobuild::BuildState & lastEvaluateCurrentState()
Definition: autobuild.h:237
int framesUntil(const BuildState &st, const BuildType *type)
Returns how many frames before a type will be available Defaults to kForever if the type isn&#39;t comple...
Definition: autobuild.cpp:119
bool hasUpgrade(const BuildState &st, const BuildType *type)
Returns true if we have this upgrade in this BuildState.
Definition: autobuild.cpp:69
std::vector< Target > targets
Definition: autobuild.h:288
Interface for bot modules.
Definition: module.h:30
const BuildType * type
Definition: autobuild.h:34