TorchCraftAI
A bot for machine learning research on StarCraft: Brood War
blackboard.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 "cherrypi.h"
11 #include "common/circularbuffer.h"
12 #include "module.h"
13 #include "task.h"
14 #include "unitsinfo.h"
15 #include "upc.h"
16 #include "upcfilter.h"
17 
18 #include <chrono>
19 #include <list>
20 #include <map>
21 #include <memory>
22 
23 #include <gflags/gflags.h>
24 #include <glog/logging.h>
25 #include <mapbox/variant.hpp>
26 #include <torchcraft/client.h>
27 
28 namespace cherrypi {
29 
30 class UpcStorage;
31 struct UpcPostData;
32 class SharedController;
33 class CherryVisDumperModule;
34 
35 /// UPCTuple and associated origin
36 struct UPCData {
37  public:
38  std::shared_ptr<UPCTuple> upc = nullptr;
40  Module* origin = nullptr;
41 
42  UPCData() {}
43  UPCData(std::shared_ptr<UPCTuple> upc, UpcId source, Module* origin)
44  : upc(upc), source(source), origin(origin) {}
45 };
46 
47 /// Task and associated owner
48 struct TaskData {
49  public:
50  std::shared_ptr<Task> task = nullptr;
51  Module* owner = nullptr;
52  bool autoRemove = true;
53  FrameNum creationFrame = -1;
54 
55  TaskData() {}
57  std::shared_ptr<Task> task,
58  Module* owner,
59  bool autoRemove,
60  FrameNum creationFrame)
61  : task(std::move(task)),
62  owner(owner),
63  autoRemove(autoRemove),
64  creationFrame(creationFrame) {}
65 };
66 
67 /**
68  * Game command are posted with an associated UPC ID.
69  */
70 struct CommandPost {
71  tc::Client::Command command;
73 };
74 
75 /**
76  * An access-aware blackboard.
77  *
78  * The blackboard provides a means for modules to exchange UPCTuples while
79  * keeping track of producers and consumers.
80  *
81  * Furthermore, there is functionality for holding global state via a simple
82  * key-value store (post(), hasKey(), get() and remove()).
83  *
84  * The blackboard itself will only store active UPCTuple objects, i.e. UPCs
85  * that have not been consumed and UPCs (as well as their sources) for which
86  * there are active tasks.
87  */
88 class Blackboard {
89  public:
90  /// A variant of types that are allowed in the Blackboard's key-value storage.
91  using Data = mapbox::util::variant<
92  bool,
93  int,
94  float,
95  double,
96  std::string,
97  Position,
98  std::shared_ptr<SharedController>,
99  std::unordered_map<int, int>>;
100  using UPCMap = std::map<UpcId, std::shared_ptr<UPCTuple>>;
101 
102  using TaskTimeStats =
103  std::tuple<UpcId, std::string, std::chrono::milliseconds>;
104 
105  // A few commonly used keys for post() and get()
106  static char const* kEnemyRaceKey;
107  static char const* kEnemyNameKey;
108  static char const* kBuildOrderKey;
109  static char const* kBuildOrderSwitchEnabledKey;
110  static char const* kOpeningBuildOrderKey;
111  static char const* kMinScoutFrameKey;
112  static char const* kMaxScoutWorkersKey;
113  static char const* kMaxScoutExplorersKey;
114  static char const* kGameUidKey;
115  static char const* kMineralsPerFramePerGatherer;
116  static char const* kGasPerFramePerGatherer;
117  static char const* kGathererMinGasWorkers;
118  static char const* kGathererMaxGasWorkers;
119  static char const* kBanditRootKey;
120 
121  Blackboard(State* state);
122  virtual ~Blackboard();
123 
124  void init();
125 
126  /// Clears the queue of commands
127  void clearCommands();
128 
129  /// Updates internal mappings after the torchcraft state has been updated.
130  void update();
131 
132  void post(std::string const& key, Data const& data) {
133  map_[key] = data;
134  }
135  bool hasKey(std::string const& key) {
136  return map_.find(key) != map_.end();
137  }
138  Data const& get(std::string const& key) const {
139  return map_.at(key);
140  }
141  template <typename T>
142  T const& get(std::string const& key) const {
143  return map_.at(key).get<T>();
144  }
145  template <typename T>
146  T const& get(std::string const& key, T const& defaultValue) const {
147  auto it = map_.find(key);
148  if (it == map_.end()) {
149  return defaultValue;
150  }
151  return it->second.get<T>();
152  }
153  void remove(std::string const& key) {
154  map_.erase(key);
155  }
156  template <typename T>
157  void iterValues(T f_do) const {
158  for (auto it = map_.begin(); it != map_.end(); ++it) {
159  f_do(it->first, it->second);
160  }
161  }
162 
163  bool isTracked(UnitId uid) const;
164  void track(UnitId uid);
165  void untrack(UnitId uid);
166 
167  // UPC post/query/consume
168 
169  /**
170  * Post a UPC tuple.
171  *
172  * The UPC tuple will be subject to filtering via UPCFilter objects. The
173  * filtered UPCTuple object will end up in the Blackboard, and the function
174  * will return a resulting UPC ID that is unique for this Blackboard instance.
175  * If the UPCTuple was rejected by a filter, kFilteredUpcId will be returned.
176  *
177  * The signature of this function enforces posting UPC tuples via move() as
178  * UPC filters modify UPC tuples by creating a copy of them. Hence, the
179  * UPCTuple instance ending up in the Blackboard might be different from the
180  * one provided to this function.
181  */
182  UpcId postUPC(
183  std::shared_ptr<UPCTuple>&& upc,
184  UpcId sourceId,
185  Module* origin,
186  std::shared_ptr<UpcPostData> data = nullptr);
187  void consumeUPCs(std::vector<UpcId> const& ids, Module* consumer);
188  void consumeUPC(UpcId id, Module* consumer) {
189  consumeUPCs({id}, consumer);
190  }
191  void removeUPCs(std::vector<UpcId> const& ids);
192  /// Returns all non-consumed UPCs
193  UPCMap upcs() const;
194  /// Returns all non-consumed UPCs from a given module
195  UPCMap upcsFrom(Module* origin) const;
196  /// Returns all non-consumed UPCs from a given module
197  UPCMap upcsFrom(std::shared_ptr<Module> origin) const {
198  return upcsFrom(origin.get());
199  }
200  /// Returns all non-consumed UPCs with a Dirac command distribution on cmd
201  UPCMap upcsWithSharpCommand(Command cmd) const;
202  /// Returns all non-consumed UPCs with a command distribution where cmd has at
203  /// least a probability of minProb
204  UPCMap upcsWithCommand(Command cmd, float minProb) const;
205  /// Returns the non-consumed UPC with the given ID
206  std::shared_ptr<UPCTuple> upcWithId(UpcId id) const;
207  UpcStorage* upcStorage() const;
208 
209  // UPC filters
210  void addUPCFilter(std::shared_ptr<UPCFilter> filter);
211  void removeUPCFilter(std::shared_ptr<UPCFilter> filter);
212 
213  // Task post/query
214  void
215  postTask(std::shared_ptr<Task> task, Module* owner, bool autoRemove = false);
216  std::shared_ptr<Task> taskForId(UpcId id) const;
217  std::vector<std::shared_ptr<Task>> tasksOfModule(Module* module) const;
218  std::shared_ptr<Task> taskWithUnit(Unit* unit) const;
219  TaskData taskDataWithUnit(Unit* unit) const;
220  std::shared_ptr<Task> taskWithUnitOfModule(Unit* unit, Module* module) const;
221  void markTaskForRemoval(UpcId upcId);
222  void markTaskForRemoval(std::shared_ptr<Task> task) {
223  markTaskForRemoval(task->upcId());
224  }
225 
226  /// This will return `Unknown` for tasks that were never registered
227  TaskStatus lastStatusOfTask(UpcId id) const;
228 
229  void updateUnitAccessCounts(tc::Client::Command const& command);
230 
231  // Game commands
232  void postCommand(tc::Client::Command const& command, UpcId sourceId);
233  std::vector<tc::Client::Command> commands(int stepsBack = 0) const;
234  size_t pastCommandsAvailable() const {
235  return commands_.size();
236  }
237 
238  /// Updates the taskByUnit mapping, should be called after setUnits on a task
239  void updateTasksByUnit(Task* task);
240 
241  /// UPC consistency checks
242  /// Calling this only makes sense in the player's postStep function, once
243  /// all the UPCs have been converted into commands to be posted to the game.
244  void checkPostStep();
245 
246  std::vector<TaskTimeStats> getTaskTimeStats() const {
247  return taskTimeStats_;
248  }
249 
250  void setCollectTimers(bool collect);
251 
252  void setTraceDumper(std::shared_ptr<CherryVisDumperModule> tracer) {
253  traceDumper_ = tracer;
254  }
255 
256  std::shared_ptr<CherryVisDumperModule> getTraceDumper() {
257  return traceDumper_;
258  }
259 
260  private:
261  State* state_;
262  std::unordered_map<std::string, Data> map_;
264  std::map<UpcId, UPCData> upcs_;
265  std::unique_ptr<UpcStorage> upcStorage_;
266 
267  /// UPCs that are on the Blackboard or have active tasks
268  std::unordered_map<UpcId, std::shared_ptr<UPCTuple>> activeUpcs_;
269  std::list<std::shared_ptr<UPCFilter>> upcFilters_;
270  std::set<UnitId> tracked_;
271 
272  std::list<TaskData> tasks_;
273  std::map<UpcId, std::list<TaskData>::iterator> tasksById_;
274  std::unordered_multimap<Module*, std::list<TaskData>::iterator>
275  tasksByModule_;
276  std::unordered_map<Unit*, std::list<TaskData>::iterator> tasksByUnit_;
277  std::vector<UpcId> tasksToBeRemoved_;
278  std::map<UnitId, size_t> unitAccessCounts_;
279  std::vector<TaskTimeStats> taskTimeStats_;
280  std::unordered_map<UpcId, TaskStatus> lastTaskStatus_;
281  std::shared_ptr<CherryVisDumperModule> traceDumper_;
282 
283  bool collectTimers_ = false;
284 };
285 
286 } // namespace cherrypi
Game state.
Definition: state.h:42
int FrameNum
Definition: basetypes.h:22
void setTraceDumper(std::shared_ptr< CherryVisDumperModule > tracer)
Definition: blackboard.h:252
Stores a graph of UPC communication, including any transactional data.
Definition: upcstorage.h:72
Module * origin
Definition: blackboard.h:40
TaskData(std::shared_ptr< Task > task, Module *owner, bool autoRemove, FrameNum creationFrame)
Definition: blackboard.h:56
Command
Abstract "meta" commands for UPCTuples.
Definition: basetypes.h:314
UpcId source
Definition: blackboard.h:39
UPCMap upcsFrom(std::shared_ptr< Module > origin) const
Returns all non-consumed UPCs from a given module.
Definition: blackboard.h:197
static char const * kMaxScoutExplorersKey
Definition: blackboard.h:113
TaskData()
Definition: blackboard.h:55
std::tuple< UpcId, std::string, std::chrono::milliseconds > TaskTimeStats
Definition: blackboard.h:103
STL namespace.
The primary way for modules to publish their activity.
Definition: task.h:50
static char const * kGathererMinGasWorkers
Definition: blackboard.h:117
bool hasKey(std::string const &key)
Definition: blackboard.h:135
UPCData()
Definition: blackboard.h:42
static char const * kEnemyRaceKey
Definition: blackboard.h:106
static char const * kGameUidKey
Definition: blackboard.h:114
Task and associated owner.
Definition: blackboard.h:48
static char const * kBuildOrderSwitchEnabledKey
Definition: blackboard.h:109
int32_t UnitId
Definition: unitsinfo.h:26
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
tc::Client::Command command
Definition: blackboard.h:71
static char const * kMineralsPerFramePerGatherer
Definition: blackboard.h:115
void post(std::string const &key, Data const &data)
Definition: blackboard.h:132
Represents a unit in the game.
Definition: unitsinfo.h:35
static char const * kMinScoutFrameKey
Definition: blackboard.h:111
static char const * kMaxScoutWorkersKey
Definition: blackboard.h:112
void consumeUPC(UpcId id, Module *consumer)
Definition: blackboard.h:188
static char const * kBanditRootKey
Definition: blackboard.h:119
An access-aware blackboard.
Definition: blackboard.h:88
TaskStatus
Describes the current status of a task.
Definition: task.h:23
Game command are posted with an associated UPC ID.
Definition: blackboard.h:70
size_t pastCommandsAvailable() const
Definition: blackboard.h:234
UpcId sourceId
Definition: blackboard.h:72
static char const * kOpeningBuildOrderKey
Definition: blackboard.h:110
std::vector< TaskTimeStats > getTaskTimeStats() const
Definition: blackboard.h:246
static char const * kGasPerFramePerGatherer
Definition: blackboard.h:116
std::map< UpcId, std::shared_ptr< UPCTuple >> UPCMap
Definition: blackboard.h:100
static char const * kBuildOrderKey
Definition: blackboard.h:108
UPCData(std::shared_ptr< UPCTuple > upc, UpcId source, Module *origin)
Definition: blackboard.h:43
Main namespace for bot-related code.
Definition: areainfo.cpp:17
UPCTuple and associated origin.
Definition: blackboard.h:36
void init(int64_t randomSeed)
Definition: cherrypi.cpp:293
int UpcId
Definition: basetypes.h:23
Definition: circularbuffer.h:20
void iterValues(T f_do) const
Definition: blackboard.h:157
static char const * kEnemyNameKey
Definition: blackboard.h:107
std::shared_ptr< UPCTuple > upc
Definition: blackboard.h:38
Interface for bot modules.
Definition: module.h:30
std::shared_ptr< CherryVisDumperModule > getTraceDumper()
Definition: blackboard.h:256
Vec2T< int > Position
Definition: basetypes.h:178
static char const * kGathererMaxGasWorkers
Definition: blackboard.h:118
UpcId constexpr kInvalidUpcId
Definition: basetypes.h:25
void markTaskForRemoval(std::shared_ptr< Task > task)
Definition: blackboard.h:222