Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
RLInterface.h
Go to the documentation of this file.
1/* Copyright (C) 2024 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
22#include "third_party/mongoose/mongoose.h"
23
24#include <condition_variable>
25#include <mutex>
26#include <vector>
27
28namespace RL
29{
31{
34 std::string content;
35};
36
38{
40 std::string json_cmd;
41};
42
44{
45 None,
46 Reset,
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 */
83{
85public:
86 Interface(const char* server_address);
87 ~Interface();
88
89 /**
90 * Non-blocking call to process any pending messages from the RL client.
91 * Updates m_ReturnValue to the gamestate after messages have been processed.
92 */
93 void TryApplyMessage();
94
95private:
96 static void* MgCallback(mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info);
97 static std::string GetRequestContent(struct mg_connection *conn);
98
99 /**
100 * Process commands, update the simulation by one turn.
101 * @return the gamestate after processing commands.
102 */
103 std::string Step(std::vector<GameCommand>&& commands);
104
105 /**
106 * Reset the game state according to scenario, cleaning up existing games if required.
107 * @return the gamestate after resetting.
108 */
109 std::string Reset(ScenarioConfig&& scenario);
110
111 /**
112 * Evaluate JS code in the engine such as applying arbitrary modifiers.
113 * @return the gamestate after script evaluation.
114 */
115 std::string Evaluate(std::string&& code);
116
117 /**
118 * @return template data for all templates of @param names.
119 */
120 std::vector<std::string> GetTemplates(const std::vector<std::string>& names) const;
121
122 /**
123 * @return true if a game is currently running.
124 */
125 bool IsGameRunning() const;
126
127 /**
128 * Internal helper. Move @param msg into m_GameMessage, wait until it has been processed by the main thread,
129 * and @return the gamestate after that message is processed.
130 * It is invalid to call this if m_GameMessage is not currently empty.
131 */
132 std::string SendGameMessage(GameMessage&& msg);
133
134 /**
135 * Internal helper.
136 * @return true if m_GameMessage is not empty, and updates @param msg, false otherwise (msg is then unchanged).
137 */
139
140 /**
141 * Process any pending messages from the RL client.
142 * Updates m_ReturnValue to the gamestate after messages have been processed.
143 */
144 void ApplyMessage(const GameMessage& msg);
145
146 /**
147 * @return the full gamestate as a JSON strong.
148 * This uses the AI representation since it is readily available in the JS Engine.
149 */
150 std::string GetGameState() const;
151
152private:
155 std::string m_ReturnValue;
156 bool m_NeedsGameState = false;
157
158 mutable std::mutex m_Lock;
159 std::mutex m_MsgLock;
160 std::condition_variable m_MsgApplied;
161 std::string m_Code;
162
163 mg_context* m_Context;
164};
165
166}
167
168#endif // INCLUDED_RLINTERFACE
int32_t player_id_t
valid player IDs are non-negative (see ICmpOwnership)
Definition: Player.h:24
Implements an interface providing fundamental capabilities required for reinforcement learning (over ...
Definition: RLInterface.h:83
std::string Step(std::vector< GameCommand > &&commands)
Process commands, update the simulation by one turn.
Definition: RLInterface.cpp:73
bool TryGetGameMessage(GameMessage &msg)
Internal helper.
Definition: RLInterface.cpp:297
void ApplyMessage(const GameMessage &msg)
Process any pending messages from the RL client.
Definition: RLInterface.cpp:332
std::vector< std::string > GetTemplates(const std::vector< std::string > &names) const
Definition: RLInterface.cpp:93
mg_context * m_Context
Definition: RLInterface.h:163
ScenarioConfig m_ScenarioConfig
Definition: RLInterface.h:154
static void * MgCallback(mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info)
Definition: RLInterface.cpp:111
std::mutex m_MsgLock
Definition: RLInterface.h:159
NONCOPYABLE(Interface)
std::string m_ReturnValue
Definition: RLInterface.h:155
std::string SendGameMessage(GameMessage &&msg)
Internal helper.
Definition: RLInterface.cpp:64
std::string m_Code
Definition: RLInterface.h:161
static std::string GetRequestContent(struct mg_connection *conn)
Definition: RLInterface.cpp:282
~Interface()
Definition: RLInterface.cpp:56
void TryApplyMessage()
Non-blocking call to process any pending messages from the RL client.
Definition: RLInterface.cpp:308
std::condition_variable m_MsgApplied
Definition: RLInterface.h:160
bool m_NeedsGameState
Definition: RLInterface.h:156
std::mutex m_Lock
Definition: RLInterface.h:158
std::string GetGameState() const
Definition: RLInterface.cpp:435
Interface(const char *server_address)
Definition: RLInterface.cpp:43
bool IsGameRunning() const
Definition: RLInterface.cpp:446
GameMessage m_GameMessage
Definition: RLInterface.h:153
std::string Reset(ScenarioConfig &&scenario)
Reset the game state according to scenario, cleaning up existing games if required.
Definition: RLInterface.cpp:79
std::string Evaluate(std::string &&code)
Evaluate JS code in the engine such as applying arbitrary modifiers.
Definition: RLInterface.cpp:86
@ None
Definition: main.cpp:135
Definition: RLInterface.cpp:42
GameMessageType
Definition: RLInterface.h:44
Definition: RLInterface.h:38
int playerID
Definition: RLInterface.h:39
std::string json_cmd
Definition: RLInterface.h:40
Holds messages from the RL client to the game.
Definition: RLInterface.h:55
std::vector< GameCommand > commands
Definition: RLInterface.h:57
GameMessageType type
Definition: RLInterface.h:56
Definition: RLInterface.h:31
bool saveReplay
Definition: RLInterface.h:32
std::string content
Definition: RLInterface.h:34
player_id_t playerID
Definition: RLInterface.h:33