1 package com.codingame.game;
3 import java.util.ArrayList;
4 import java.util.Collections;
6 import java.util.Random;
8 import com.codingame.gameengine.core.AbstractPlayer.TimeoutException;
9 import com.codingame.gameengine.core.AbstractReferee;
10 import com.codingame.game.GodModeManager;
11 import com.google.inject.Inject;
12 import com.google.inject.Provider;
14 public class Referee extends AbstractReferee {
15 @Inject private GameManager gameManager;
16 @Inject private GodModeManager gm;
17 @Inject private LeagueManager league;
19 @Inject private View view;
20 @Inject private Model model;
22 boolean disqual = false;
28 gameManager.getPlayer(0).model = model.p0;
29 gameManager.getPlayer(1).model = model.p1;
31 for (Player p: gameManager.getPlayers()) {
32 p.gameInit(model.roadLength, model.initialStones,
33 model.seed, gm.getSalt());
37 gameManager.getPlayer(0).view = view.p0;
38 gameManager.getPlayer(1).view = view.p1;
41 private void disqualify(Player player, String popup, String message) {
42 player.deactivate(player.getNicknameToken() + " " + popup);
43 player.view.disqualify(message);
48 public void gameTurn(int turn) {
49 // System.err.println("Starting turn " + turn);
53 // Did I mention I hate Java? It didn't *have* to be this ugly!
54 if (disqual) { endGame(); return; }
55 if (model.exhausted()) { finishStones(); return ;}
56 if (model.haveWinner()) { endGame(); return; }
58 for (Player player : gameManager.getActivePlayers()) {
59 player.sendGameTurn();
61 // SDK @#%^&! arbitrary sequence point: last input < first output
63 /* Parse player actions and decide basic disqualifications.
64 * Display their optional message right now: if their action
65 * is ill-formed it could help them debug. Or shame them, at
68 for (Player player : gameManager.getActivePlayers()) {
69 player.receiveGameTurn(); gm.transcend(player);
70 switch (player.type) {
72 disqualify(player, "T/O", "timed out!");
73 player.view.markTimeout();
77 disqualify(player, "INVALID", "provided an ill-formed action");
78 player.view.markIllegal();
82 try { player.model.consumeStones(player.stoneThrow); }
83 catch (Model.Player.ThrewMoreStonesThanHad e) {
85 switch (league.fixLevel) {
87 FIX_IT = model.random.nextInt(10) > 0;
92 default: throw new JavaLimitationError();
95 player.view.threwMoreStonesThanHad();
96 player.stoneThrow = player.model.consumeMaxStones();
99 disqualify(player, "ILLEGAL", "tried to throw more stones than they had. They went into debt trying to provide. The economy tanked, recession and famine ensued; even the troll wouldn't have wanted to bash them anymore. But that's no victory.");
100 player.view.markIllegal();
104 catch (Model.Player.FailedToThrowStonesAndShouldHave e) {
106 switch (league.fixLevel) {
108 FIX_IT = model.random.nextInt(10) > 0;
113 default: throw new JavaLimitationError();
116 player.view.failedToThrowStonesAndShouldHave();
117 player.stoneThrow = player.model.consumeMinStones();
120 disqualify(player, "ILLEGAL", "tried not throwing any stones. They were then eaten by a grue.");
126 player.view.displayMessage(player.messageString);
130 /* Update game model and view, stones' part.
132 * As a special case, the "cheater" (sending out negative
133 * stones) handling is deferred here because we need to update
134 * its view for it to be funny. In the end, they're still
137 * Gather other game end scenarios (actual victory or stone
141 gm.update(gameManager.getPlayers());
142 for (Player player : gameManager.getActivePlayers()) {
143 player.view.throwStones(player.stoneThrow);
144 delta += player.model.getMultiplier() * player.stoneThrow;
146 if (player.stoneThrow < 0) {
147 switch(league.cheatLevel) {
151 player.view.markCheat();
152 if (model.random.nextInt(2) == 0) player.model.loseRound();
155 disqualify(player, "CHEAT", "cheated. Banning account.");
156 player.view.markCheat();
161 if (player.stoneThrow != 0) {
162 player.view.animateStones(player.stoneThrow);
163 player.view.updateStoneCounter();
167 /* Update game model and view, troll part.
169 * If a player cheated, delta is unusable as is.
170 * (Consider the case the player on the right sent
171 * INT_MIN. INT_MIN * (-1) = INT_MIN, so that player
172 * would both glean the stones *and* push the troll away.
173 * It would be unfair to have a cheating player "win"
174 * (earn the opponent castle destruction animation) this
177 boolean cheat0 = gameManager.getPlayer(0).isActive()
178 && gameManager.getPlayer(0).stoneThrow < 0;
179 boolean cheat1 = gameManager.getPlayer(1).isActive()
180 && gameManager.getPlayer(1).stoneThrow < 0;
181 if (cheat0 && cheat1); // here we can actually keep delta's value
182 else if (cheat0) delta = -1;
183 else if (cheat1) delta = 1;
187 view.moveTroll(View.Dir.RIGHT);
189 else if (delta < 0) {
191 view.moveTroll(View.Dir.LEFT);
194 view.moveTroll(View.Dir.STILL);
199 // XXX very similar to main turn pendant
200 private void finishStones() {
201 boolean noStones = true;
203 for (Player player : gameManager.getActivePlayers()) {
204 if (model.haveWinner() && player.getIndex() == model.getLoser())
206 player.stoneThrow = player.model.getStones();
207 player.model.setStones(0);
208 delta += player.stoneThrow * player.model.getMultiplier();
209 player.view.throwStones(player.stoneThrow);
210 if (player.stoneThrow != 0) {
212 player.view.animateStones(player.stoneThrow);
213 player.view.updateStoneCounter();
216 if (noStones) { endGame(); return; }
217 model.moveTroll(delta);
221 private void endGame() {
222 gameManager.endGame();
224 if (model.haveWinner()) {
225 int loser = model.getLoser();
226 gameManager.getPlayer(loser).view.defeat();
229 Player p0 = gameManager.getPlayer(0);
230 Player p1 = gameManager.getPlayer(1);
232 int s0 = p0.getScore();
233 int s1 = p1.getScore();