-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlocal_referee.cpp
More file actions
122 lines (106 loc) · 2.92 KB
/
local_referee.cpp
File metadata and controls
122 lines (106 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <array>
#include <cstdlib>
#include <iostream>
#include <string>
#include "GameEngine.hpp"
#include "referee/bot_process.hpp"
#include "referee/replay_writer.hpp"
namespace
{
struct Cli
{
std::string bot1;
std::string bot2;
std::string output = "replay_spring_native_cpp.json";
long long seed = 12345;
int league = 3;
int turns = 300;
};
Cli parse_cli(int argc, char **argv)
{
if (argc < 3)
{
throw std::runtime_error("Usage: spring_referee_native \"bot1\" \"bot2\" [--seed N] [--league L] [--turns N] [--output FILE]");
}
Cli c;
c.bot1 = argv[1];
c.bot2 = argv[2];
for (int i = 3; i < argc; ++i)
{
const std::string arg = argv[i];
if (arg == "--seed" && i + 1 < argc)
c.seed = std::atoll(argv[++i]);
else if (arg == "--league" && i + 1 < argc)
c.league = std::atoi(argv[++i]);
else if (arg == "--turns" && i + 1 < argc)
c.turns = std::atoi(argv[++i]);
else if (arg == "--output" && i + 1 < argc)
c.output = argv[++i];
}
return c;
}
} // namespace
int main(int argc, char **argv)
{
try
{
const Cli cli = parse_cli(argc, argv);
referee::BotProcess p1(cli.bot1);
referee::BotProcess p2(cli.bot2);
if (!p1.valid() || !p2.valid())
{
std::cerr << "Failed to spawn one or both bots" << std::endl;
return 2;
}
spring_native::GameEngine engine;
auto state = spring_native::GameEngine::create_map_from_seed(cli.seed, cli.league);
referee::ReplayData replay{state, {}, {}, cli.seed, cli.league};
for (int pid = 0; pid < 2; ++pid)
{
const auto init_inputs = spring_native::GameEngine::get_initial_inputs(state, pid);
auto &bot = (pid == 0) ? p1 : p2;
for (const auto &line : init_inputs)
{
bot.send_line(line);
}
}
for (int t = 0; t < cli.turns; ++t)
{
for (int pid = 0; pid < 2; ++pid)
{
const auto turn_inputs = spring_native::GameEngine::get_turn_inputs(state, pid);
auto &bot = (pid == 0) ? p1 : p2;
for (const auto &line : turn_inputs)
{
bot.send_line(line);
}
}
const std::string out1 = p1.read_line_with_timeout(t == 0 ? 1000 : 60);
const std::string out2 = p2.read_line_with_timeout(t == 0 ? 1000 : 60);
std::array<std::string, 2> cmds{out1, out2};
auto turn = engine.apply_turn(state, cmds, cli.league);
turn.errors[0] += p1.read_stderr_available();
turn.errors[1] += p2.read_stderr_available();
replay.turns.push_back(turn);
replay.states.push_back(state);
if (state.game_over)
{
break;
}
}
replay.initial_state = state;
if (!referee::ReplayWriter::write_synthetic_json(replay, cli.output))
{
std::cerr << "Failed to write replay: " << cli.output << std::endl;
return 3;
}
std::cout << "Replay written: " << cli.output << std::endl;
std::cout << "Final scores P0=" << state.players[0].score << " P1=" << state.players[1].score << std::endl;
return 0;
}
catch (const std::exception &ex)
{
std::cerr << ex.what() << std::endl;
return 1;
}
}