summaryrefslogtreecommitdiff
path: root/referee.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'referee.cpp')
-rw-r--r--referee.cpp127
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;
+}