Pyrogenesis  trunk
RLInterface.h
Go to the documentation of this file.
1 /* Copyright (C) 2021 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_RLINTERFACE
19 #define INCLUDED_RLINTERFACE
20 
23 
24 #include <condition_variable>
25 #include <mutex>
26 #include <vector>
27 
28 namespace RL
29 {
31 {
32  bool saveReplay;
34  std::string content;
35 };
36 
38 {
39  int playerID;
40  std::string json_cmd;
41 };
42 
43 enum class GameMessageType
44 {
45  None,
46  Reset,
47  Commands,
48  Evaluate,
49 };
50 
51 /**
52  * Holds messages from the RL client to the game.
53  */
55 {
57  std::vector<GameCommand> commands;
58 };
59 
60 /**
61  * Implements an interface providing fundamental capabilities required for reinforcement
62  * learning (over HTTP).
63  *
64  * This consists of enabling an external script to configure the scenario (via Reset) and
65  * then step the game engine manually and apply player actions (via Step). The interface
66  * also supports querying unit templates to provide information about max health and other
67  * potentially relevant game state information.
68  *
69  * See source/tools/rlclient/ for the external client code.
70  *
71  * The HTTP server is threaded.
72  * Flow of data (with the interface active):
73  * 0. The game/main thread calls TryApplyMessage()
74  * - If no messages are pending, GOTO 0 (the simulation is not advanced).
75  * 1. TryApplyMessage locks m_MsgLock, pulls the message, processes it, advances the simulation, and sets m_ReturnValue.
76  * 2. TryApplyMessage notifies the RL thread that it can carry on and unlocks m_MsgLock. The main thread carries on frame rendering and goes back to 0.
77  * 3. The RL thread locks m_MsgLock, reads m_ReturnValue, unlocks m_MsgLock, and sends the gamestate as HTTP Response to the RL client.
78  * 4. The client processes the response and ultimately sends a new HTTP message to the RL Interface.
79  * 5. The RL thread locks m_MsgLock, pushes the message, and starts waiting on the game/main thread to notify it (step 2).
80  * - GOTO 0.
81  */
82 class Interface
83 {
85 public:
86  Interface(const char* server_address);
87 
88  /**
89  * Non-blocking call to process any pending messages from the RL client.
90  * Updates m_ReturnValue to the gamestate after messages have been processed.
91  */
92  void TryApplyMessage();
93 
94 private:
95  static void* MgCallback(mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info);
96  static std::string GetRequestContent(struct mg_connection *conn);
97 
98  /**
99  * Process commands, update the simulation by one turn.
100  * @return the gamestate after processing commands.
101  */
102  std::string Step(std::vector<GameCommand>&& commands);
103 
104  /**
105  * Reset the game state according to scenario, cleaning up existing games if required.
106  * @return the gamestate after resetting.
107  */
108  std::string Reset(ScenarioConfig&& scenario);
109 
110  /**
111  * Evaluate JS code in the engine such as applying arbitrary modifiers.
112  * @return the gamestate after script evaluation.
113  */
114  std::string Evaluate(std::string&& code);
115 
116  /**
117  * @return template data for all templates of @param names.
118  */
119  std::vector<std::string> GetTemplates(const std::vector<std::string>& names) const;
120 
121  /**
122  * @return true if a game is currently running.
123  */
124  bool IsGameRunning() const;
125 
126  /**
127  * Internal helper. Move @param msg into m_GameMessage, wait until it has been processed by the main thread,
128  * and @return the gamestate after that message is processed.
129  * It is invalid to call this if m_GameMessage is not currently empty.
130  */
131  std::string SendGameMessage(GameMessage&& msg);
132 
133  /**
134  * Internal helper.
135  * @return true if m_GameMessage is not empty, and updates @param msg, false otherwise (msg is then unchanged).
136  */
137  bool TryGetGameMessage(GameMessage& msg);
138 
139  /**
140  * Process any pending messages from the RL client.
141  * Updates m_ReturnValue to the gamestate after messages have been processed.
142  */
143  void ApplyMessage(const GameMessage& msg);
144 
145  /**
146  * @return the full gamestate as a JSON strong.
147  * This uses the AI representation since it is readily available in the JS Engine.
148  */
149  std::string GetGameState() const;
150 
151 private:
154  std::string m_ReturnValue;
155  bool m_NeedsGameState = false;
156 
157  mutable std::mutex m_Lock;
158  std::mutex m_MsgLock;
159  std::condition_variable m_MsgApplied;
160  std::string m_Code;
161 };
162 
163 }
164 
165 extern std::unique_ptr<RL::Interface> g_RLInterface;
166 
167 #endif // INCLUDED_RLINTERFACE
#define NONCOPYABLE(className)
Indicates that a class is noncopyable (usually due to const or reference members, or because the clas...
Definition: code_annotation.h:227
std::string json_cmd
Definition: RLInterface.h:40
std::condition_variable m_MsgApplied
Definition: RLInterface.h:159
std::string m_Code
Definition: RLInterface.h:160
bool saveReplay
Definition: RLInterface.h:32
std::string content
Definition: RLInterface.h:34
std::mutex m_Lock
Definition: RLInterface.h:157
std::unique_ptr< RL::Interface > g_RLInterface
Definition: RLInterface.cpp:42
Definition: RLInterface.h:37
GameMessageType
Definition: RLInterface.h:43
GameMessage m_GameMessage
Definition: RLInterface.h:152
int32_t player_id_t
valid player IDs are non-negative (see ICmpOwnership)
Definition: Player.h:24
Definition: RLInterface.h:30
std::vector< GameCommand > commands
Definition: RLInterface.h:57
Definition: mongoose.h:35
ScenarioConfig m_ScenarioConfig
Definition: RLInterface.h:153
int playerID
Definition: RLInterface.h:39
Implements an interface providing fundamental capabilities required for reinforcement learning (over ...
Definition: RLInterface.h:82
mg_event
Definition: mongoose.h:55
static void * MgCallback(mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info)
Mongoose callback.
Definition: Profiler2.cpp:71
Definition: mongoose.cpp:509
std::mutex m_MsgLock
Definition: RLInterface.h:158
std::string m_ReturnValue
Definition: RLInterface.h:154
Holds messages from the RL client to the game.
Definition: RLInterface.h:54
Definition: RLInterface.cpp:44
GameMessageType type
Definition: RLInterface.h:56
player_id_t playerID
Definition: RLInterface.h:33