diff options
Diffstat (limited to 'referee.cpp')
-rw-r--r-- | referee.cpp | 127 |
1 files changed, 88 insertions, 39 deletions
diff --git a/referee.cpp b/referee.cpp index 15f49c3..ffcbd14 100644 --- a/referee.cpp +++ b/referee.cpp @@ -3,9 +3,15 @@ #include "referee.h" #include "params.h" +// Timeout in milliseconds for the feature negotiation at the start of the +// protocol. If the referee hasn't sent anything after this timeout, we assume +// the referee isn't capable of sending feature lines and will be treated as +// such for the duration of the competition. +#define FEATURE_TIMEOUT 200 + Referee::Referee(const string_view execname, const vector<string> &players) - : proc(execname) { + : proc(execname), refereeExecname(execname) { proc.run(); @@ -14,11 +20,15 @@ Referee::Referee(const string_view execname, const vector<string> &players) for (const string &p : players) cout << " " << p; cout << endl; } - + + queryFeatures(); + proc.writeLine(to_string(players.size())); for (const string &p : players) { proc.writeLine(p); } + + readWriteLines(); } Referee::~Referee() { @@ -39,49 +49,32 @@ bool Referee::moveValid(int player, const string_view line) { proc.writeLine(s); - optional<string> response = readLine(); + optional<string> response = proc.readLine(); if (response) { + if (referee_verbose) { + cout << "REF(" << proc.getPid() << ") read <" << *response << ">" << endl; + } + bool result; if (*response == "valid end") { isEnd = true; - readScores(); result = true; } else if (*response == "valid") { result = true; - } else { + } else if (*response == "invalid") { result = false; + } else { + cout << "REF(" << proc.getPid() << ") Invalid validity judgement '" << *response << "'!" << endl; + exit(1); } - 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; + readWriteLines(); - 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)); - } - } + if (isEnd) readScores(); return result; } else { - if (referee_verbose) { - cout << "REF(" << proc.getPid() << ") EOF!" << endl; - } + cout << "REF(" << proc.getPid() << ") EOF!" << endl; return false; } } @@ -94,28 +87,80 @@ bool Referee::gameEnded() { return isEnd; } -optional<string> Referee::readLine() { +void Referee::queryFeatures() { + bool first = true; + + while (true) { + optional<string> line; + if (first) { + line = proc.readLineTimeout(FEATURE_TIMEOUT); + if (!line) { + cout << "Referee '" << refereeExecname << "' seems to follow the old protocol!" << endl; + return; + } + + first = false; + } else { + line = proc.readLine(); + } + + if (!line) { + cout << "REF(" << proc.getPid() << ") EOF!" << endl; + exit(1); + } + + if (referee_verbose) { + cout << "REF(" << proc.getPid() << ") read <" << *line << ">" << endl; + } + + if (*line == "feature_end") { + return; + } else if (line->substr(0, 8) == "feature ") { + string featname = line->substr(8); + if (featname == "write_lines") features.writeLines = true; + else if (featname == "no_last_move") features.noLastMove = true; + else { + cerr << "REF(" << proc.getPid() << ") Referee requested unsupported feature '" << featname << "'" << endl; + exit(1); + } + } else { + cerr << "REF(" << proc.getPid() << ") Referee protocol violation in feature negotiation" << endl; + exit(1); + } + } +} + +void Referee::readWriteLines() { + writeLinesList.clear(); + + if (!features.writeLines) return; + while (true) { optional<string> line = proc.readLine(); - if (!line) return line; + if (!line) { + cout << "REF(" << proc.getPid() << ") EOF!" << endl; + break; + } if (referee_verbose) { cout << "REF(" << proc.getPid() << ") read <" << *line << ">" << endl; } - if (line->substr(0, 8) != "feature ") return line; + if (line == "write_end") break; - string featname = line->substr(8); - if (featname == "write_lines") featureWriteLines = true; - else { - cerr << "Referee requested unsupported feature '" << featname << "'" << endl; + size_t idx = line->find(' '); + if (idx == string::npos) { + cerr << "REF(" << proc.getPid() << ") Referee feature_write_lines protocol violation!" << endl; exit(1); } + + int player = stoi(line->substr(0, idx)); + writeLinesList.emplace_back(player, line->substr(idx + 1)); } } void Referee::readScores() { - optional<string> line = readLine(); + optional<string> line = proc.readLine(); if (!line) { cerr << "Referee stopped before providing scores" << endl; exit(1); @@ -138,3 +183,7 @@ optional<vector<int>> Referee::getScores() { void Referee::terminate() { proc.terminate(); } + +const Features& Referee::getFeatures() const { + return features; +} |