diff options
-rw-r--r-- | main.cpp | 6 | ||||
-rw-r--r-- | referee.cpp | 70 | ||||
-rw-r--r-- | referee.h | 16 |
3 files changed, 79 insertions, 13 deletions
@@ -296,11 +296,17 @@ static void playMatch(Player &p1, Player &p2, int index, const Params ¶ms) { throw StopCompetitionError(); } + for (const auto &p : referee.playerWriteLines()) { + assert(0 <= p.first && p.first < 2); + procs[p.first].writeLine(p.second); + } + if (referee.gameEnded()) { mres.status = MatchResult::Status::ok; optional<vector<int>> oscores = referee.getScores(); assert(oscores); + assert(oscores->size() == 2); mres.sc1 = oscores->at(0); mres.sc2 = oscores->at(1); diff --git a/referee.cpp b/referee.cpp index 7bf3a93..15f49c3 100644 --- a/referee.cpp +++ b/referee.cpp @@ -39,21 +39,45 @@ bool Referee::moveValid(int player, const string_view line) { proc.writeLine(s); - optional<string> response = proc.readLine(); + optional<string> response = readLine(); if (response) { - if (referee_verbose) { - cout << "REF(" << proc.getPid() << ") read <" << *response << ">" << endl; - } - + bool result; if (*response == "valid end") { isEnd = true; readScores(); - return true; + result = true; } else if (*response == "valid") { - return true; + result = true; } else { - return false; + result = false; + } + + if (featureWriteLines) { + writeLinesList.clear(); + + while (true) { + optional<string> line = readLine(); + if (!line) { + if (referee_verbose) { + cout << "REF(" << proc.getPid() << ") EOF!" << endl; + } + return false; + } + + if (line == "write_end") break; + + size_t idx = line->find(' '); + if (idx == string::npos) { + cerr << "Referee feature_write_lines protocol violation!" << endl; + exit(1); + } + + int player = stoi(line->substr(0, idx)); + writeLinesList.emplace_back(player, line->substr(idx + 1)); + } } + + return result; } else { if (referee_verbose) { cout << "REF(" << proc.getPid() << ") EOF!" << endl; @@ -62,21 +86,41 @@ bool Referee::moveValid(int player, const string_view line) { } } +vector<pair<int, string>> Referee::playerWriteLines() { + return writeLinesList; +} + bool Referee::gameEnded() { return isEnd; } +optional<string> Referee::readLine() { + while (true) { + optional<string> line = proc.readLine(); + if (!line) return line; + + if (referee_verbose) { + cout << "REF(" << proc.getPid() << ") read <" << *line << ">" << endl; + } + + if (line->substr(0, 8) != "feature ") return line; + + string featname = line->substr(8); + if (featname == "write_lines") featureWriteLines = true; + else { + cerr << "Referee requested unsupported feature '" << featname << "'" << endl; + exit(1); + } + } +} + void Referee::readScores() { - optional<string> line = proc.readLine(); + optional<string> line = readLine(); if (!line) { cerr << "Referee stopped before providing scores" << endl; exit(1); } - if (referee_verbose) { - cout << "REF(" << proc.getPid() << ") readScores <" << *line << ">" << endl; - } - size_t cursor = 0; while (cursor < line->size()) { size_t idx = line->find(' ', cursor); @@ -4,6 +4,7 @@ #include <string> #include <string_view> #include <optional> +#include <utility> #include "process.h" using namespace std; @@ -14,6 +15,10 @@ class Referee { bool isEnd = false; vector<int> scores; + bool featureWriteLines = false; + vector<pair<int, string>> writeLinesList; + + optional<string> readLine(); void readScores(); public: @@ -22,6 +27,7 @@ public: // 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(); @@ -45,4 +51,14 @@ then write a line to stdout that is equal to either 'valid', 'invalid', or '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 +At any time the referee may write 'feature <name>' to stdout, which enables the +protocol feature with the given name. The following features are supported: +- 'write_lines': 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. */ |