summaryrefslogtreecommitdiff
path: root/referee.h
blob: 82b8b0219ae65873ad3f7c0e557bd435e519806d (plain)
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
#pragma once

#include <vector>
#include <string>
#include <string_view>
#include <optional>
#include <utility>
#include "process.h"

using namespace std;


struct Features {
	// If true, players should not receive the last move on stdin.
	// Used by the match runner.
	bool noLastMove = false;

	// If true, the referee program can write additional lines to the players.
	// Used by the Referee class to produce playerWriteLines() output.
	bool writeLines = false;
};

class Referee {
	Process proc;
	string refereeExecname;
	bool isEnd = false;
	vector<int> scores;

	Features features;
	vector<pair<int, string>> writeLinesList;

	void queryFeatures();
	void readScores();
	void readWriteLines();

public:
	Referee(const string_view execname, const vector<string> &players);
	~Referee();

	// player: 0 = first player, 1 = second player
	bool moveValid(int player, const string_view line);
	vector<pair<int, string>> playerWriteLines();

	bool gameEnded();
	optional<vector<int>> getScores();

	// Kills the referee process
	void terminate();

	const Features& getFeatures() const;
};

/*
Referee protocol:

At startup, the referee should write a number of lines to stdout of the form
'feature <name>', indicating that the referee supports the feature given by
<name>. The list of features should be ended with a line containing
'feature_end'. For supported features and their effect, see below.

The referee then receives a line containing the number of players in the game,
followed by that number of lines containing the players' names.

Then, it repeatedly receives a line on stdin of the form '<player> <line>',
where <player> is the index of the player in the game (0 is first, 1 is second,
etc.) and <line> is the line as written out by the player. The referee should
then write a line to stdout that is equal to either 'valid', 'invalid', or
'valid end'. 'valid' and 'invalid' indicate a valid and invalid move, while
'valid end' indicates a valid move that ends the game. After writing the line
'valid end', the referee should write a line containing as many integers
(separated by spaces) as there are players, giving their scores at the end of
the game.

FEATURES
The following features are supported:
- 'write_lines': After having received the list of players at the start of the
  protocol, and after a move validity judgement, the referee should write lines
  of the form '<player> <line>' to stdout, where <player> is the index of the
  player on whose stdin to write <line>. The referee should signal the end of
  this list by writing a line 'write_end' to stdout. This allows the referee to
  write additional data to players' inputs after they have written their moves.
  Note that 'valid end' is also a move validity judgement, and the player lines
  should be written *before* writing the scores.
- 'no_last_move': Prevent the competition manager from writing the last player's
  last move to stdin of the next player. Should probably be used in conjunction
  with 'write_lines'.
*/