Skip to content

Commit 14cbf4b

Browse files
committed
feat(sdk): Game manager handles FAIL command and crashes cleanly
1 parent d7a1ccc commit 14cbf4b

File tree

2 files changed

+67
-48
lines changed

2 files changed

+67
-48
lines changed

engine/core/src/main/java/com/codingame/gameengine/core/GameManager.java

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.io.InputStream;
44
import java.io.PrintStream;
5+
import java.io.PrintWriter;
6+
import java.io.StringWriter;
57
import java.util.ArrayList;
68
import java.util.HashMap;
79
import java.util.List;
@@ -74,7 +76,7 @@ abstract public class GameManager<T extends AbstractPlayer> {
7476
private int totalTurnTime = 0;
7577

7678
private boolean viewWarning, summaryWarning;
77-
79+
7880
/**
7981
* GameManager main loop.
8082
*
@@ -85,65 +87,72 @@ abstract public class GameManager<T extends AbstractPlayer> {
8587
*/
8688
void start(InputStream is, PrintStream out) {
8789
s = new Scanner(is);
88-
this.out = out;
89-
this.referee = refereeProvider.get();
90-
91-
// Init ---------------------------------------------------------------
92-
log.info("Init");
93-
InputCommand iCmd = InputCommand.parse(s.nextLine());
94-
int playerCount = s.nextInt();
95-
s.nextLine();
96-
players = new ArrayList<T>(playerCount);
97-
98-
for (int i = 0; i < playerCount; i++) {
99-
T player = playerProvider.get();
100-
player.setIndex(i);
101-
players.add(player);
102-
}
90+
try {
91+
this.out = out;
92+
this.referee = refereeProvider.get();
93+
94+
// Init ---------------------------------------------------------------
95+
log.info("Init");
96+
InputCommand iCmd = InputCommand.parse(s.nextLine());
97+
int playerCount = s.nextInt();
98+
s.nextLine();
99+
players = new ArrayList<T>(playerCount);
100+
101+
for (int i = 0; i < playerCount; i++) {
102+
T player = playerProvider.get();
103+
player.setIndex(i);
104+
players.add(player);
105+
}
103106

104-
readGameProperties(iCmd, s);
107+
readGameProperties(iCmd, s);
105108

106-
prevViewData = null;
107-
currentViewData = new JsonObject();
109+
prevViewData = null;
110+
currentViewData = new JsonObject();
108111

109-
referee.init();
110-
registeredModules.forEach(Module::onGameInit);
111-
initDone = true;
112+
referee.init();
113+
registeredModules.forEach(Module::onGameInit);
114+
initDone = true;
112115

113-
// Game Loop ----------------------------------------------------------
114-
for (turn = 0; turn < getMaxTurns() && !isGameEnd() && !allPlayersInactive(); turn++) {
115-
swapInfoAndViewData();
116-
log.info("Turn " + turn);
117-
newTurn = true;
118-
outputsRead = false; // Set as true after first getOutputs() to forbib sendInputs
116+
// Game Loop ----------------------------------------------------------
117+
for (turn = 0; turn < getMaxTurns() && !isGameEnd() && !allPlayersInactive(); turn++) {
118+
swapInfoAndViewData();
119+
log.info("Turn " + turn);
120+
newTurn = true;
121+
outputsRead = false; // Set as true after first getOutputs() to forbib sendInputs
119122

120-
referee.gameTurn(turn);
121-
registeredModules.forEach(Module::onAfterGameTurn);
123+
referee.gameTurn(turn);
124+
registeredModules.forEach(Module::onAfterGameTurn);
122125

123-
// reset players' outputs
124-
for (AbstractPlayer player : players) {
125-
player.resetOutputs();
126-
player.setHasBeenExecuted(false);
126+
// reset players' outputs
127+
for (AbstractPlayer player : players) {
128+
player.resetOutputs();
129+
player.setHasBeenExecuted(false);
130+
}
127131
}
128-
}
129132

130-
log.info("End");
133+
log.info("End");
131134

132-
referee.onEnd();
133-
registeredModules.forEach(Module::onAfterOnEnd);
135+
referee.onEnd();
136+
registeredModules.forEach(Module::onAfterOnEnd);
134137

135-
// Send last frame ----------------------------------------------------
136-
swapInfoAndViewData();
137-
newTurn = true;
138+
// Send last frame ----------------------------------------------------
139+
swapInfoAndViewData();
140+
newTurn = true;
138141

139-
dumpView();
140-
dumpInfos();
142+
dumpView();
143+
dumpInfos();
141144

142-
dumpGameProperties();
143-
dumpMetadata();
144-
dumpScores();
145+
dumpGameProperties();
146+
dumpMetadata();
147+
dumpScores();
145148

146-
s.close();
149+
s.close();
150+
151+
} catch (RuntimeException e) {
152+
dumpFail(e);
153+
s.close();
154+
throw e;
155+
}
147156
}
148157

149158
abstract protected boolean allPlayersInactive();
@@ -231,6 +240,16 @@ private void dumpScores() {
231240
out.println(data);
232241
}
233242

243+
private void dumpFail(RuntimeException e) {
244+
OutputData data = new OutputData(OutputCommand.FAIL);
245+
StringWriter sw = new StringWriter();
246+
PrintWriter pw = new PrintWriter(sw);
247+
e.printStackTrace(pw);
248+
249+
data.add(sw.toString());
250+
out.println(data);
251+
}
252+
234253
private void dumpView() {
235254
OutputData data = new OutputData(OutputCommand.VIEW);
236255
if (newTurn) {

engine/core/src/main/java/com/codingame/gameengine/core/OutputCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.codingame.gameengine.core;
22
enum OutputCommand {
3-
VIEW, INFOS, NEXT_PLAYER_INPUT, NEXT_PLAYER_INFO, SCORES, UINPUT, TOOLTIP, SUMMARY, METADATA;
3+
VIEW, INFOS, NEXT_PLAYER_INPUT, NEXT_PLAYER_INFO, SCORES, UINPUT, TOOLTIP, SUMMARY, METADATA, FAIL;
44
public String format(int lineCount) {
55
return String.format("[[%s] %d]", this.name(), lineCount);
66
}

0 commit comments

Comments
 (0)