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.gameengine.core.GameManager;
11 import com.codingame.gameengine.core.MultiplayerGameManager;
12 import com.codingame.gameengine.module.entities.GraphicEntityModule;
13 import com.codingame.gameengine.module.entities.Rectangle;
14 import com.codingame.gameengine.module.entities.Sprite;
15 import com.codingame.gameengine.module.entities.Text;
16 import com.codingame.gameengine.module.entities.Curve;
17 import com.google.inject.Inject;
18 import com.google.inject.Provider;
20 public class Referee extends AbstractReferee {
21 @Inject private MultiplayerGameManager<Player> gameManager;
22 @Inject private GraphicEntityModule graphicEntityModule;
24 @Inject private View view;
25 @Inject private Model model;
27 boolean disqual = false;
31 model.init(gameManager.getSeed());
32 gameManager.getPlayer(0).model = model.p0;
33 gameManager.getPlayer(1).model = model.p1;
35 for (Player p: gameManager.getPlayers()) {
36 p.gameInit(model.roadLength, model.initialStones,
37 gameManager.getSeed());
41 gameManager.getPlayer(0).view = view.p0;
42 gameManager.getPlayer(1).view = view.p1;
43 gameManager.setFrameDuration(2000);
46 private void disqualify(Player player, String popup, String message) {
47 player.deactivate(player.getNicknameToken() + " " + popup);
48 gameManager.addToGameSummary(GameManager.formatErrorMessage(player.getNicknameToken() + " " + message));
53 public void gameTurn(int turn) {
54 // System.err.println("Starting turn " + turn);
58 // Did I mention I hate Java? It didn't *have* to be this ugly!
59 if (disqual) { endGame(); return; }
60 if (model.exhausted()) { finishStones(); return ;}
61 if (model.haveWinner()) { endGame(); return; }
63 for (Player player : gameManager.getActivePlayers()) {
64 player.sendGameTurn();
66 // SDK @#%^&! arbitrary sequence point: last input < first output
68 /* Parse player actions and decide basic disqualifications.
69 * Display their optional message right now: if their action
70 * is ill-formed it could help them debug. Or shame them, at
73 for (Player player : gameManager.getActivePlayers()) {
74 player.receiveGameTurn();
75 switch (player.type) {
77 disqualify(player, "T/O", "timed out!");
78 player.view.markTimeout();
82 disqualify(player, "INVALID", "provided an ill-formed action");
83 player.view.markIllegal();
87 try { player.model.consumeStones(player.stoneThrow); }
88 catch (Model.Player.ThrewMoreStonesThanHad e) {
89 if (model.random.nextInt(10) > 0) {
90 player.view.threwMoreStonesThanHad();
91 player.stoneThrow = player.model.consumeMaxStones();
94 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.");
95 player.view.markIllegal();
99 catch (Model.Player.FailedToThrowStonesAndShouldHave e) {
100 if (model.random.nextInt(10) > 0) {
101 player.view.failedToThrowStonesAndShouldHave();
102 player.stoneThrow = player.model.consumeMinStones();
105 disqualify(player, "ILLEGAL", "tried not throwing any stones. They were then eaten by a grue.");
111 player.view.displayMessage(player.messageString);
114 /* Update game model and view.
116 * As a special case, the "cheater" (sending out negative
117 * stones) handling is deferred here because we need to update
118 * its view for it to be funny. In the end, they're still
121 * Gather other game end scenarios (actual victory or stone
125 for (Player player : gameManager.getActivePlayers()) {
126 player.view.throwStones(player.stoneThrow);
127 delta += player.model.getMultiplier() * player.stoneThrow;
129 if (player.stoneThrow < 0) {
130 disqualify(player, "CHEAT", "cheated. Banning account.");
131 player.view.markCheat();
134 if (player.stoneThrow != 0) {
135 player.view.animateStones(player.stoneThrow);
136 player.view.updateStoneCounter();
140 /* If a player cheated, delta is unusable as is.
141 * (Consider the case the player on the right sent
142 * INT_MIN. INT_MIN * (-1) = INT_MIN, so that player
143 * would both glean the stones *and* push the troll away.
144 * It would be unfair to have a cheating player "win"
145 * (earn the opponent castle destruction animation) this
148 boolean cheat0 = gameManager.getPlayer(0).isActive()
149 && gameManager.getPlayer(0).stoneThrow < 0;
150 boolean cheat1 = gameManager.getPlayer(1).isActive()
151 && gameManager.getPlayer(1).stoneThrow < 0;
152 if (cheat0 && cheat1); // here we can actually keep delta's value
153 else if (cheat0) delta = -1;
154 else if (cheat1) delta = 1;
158 view.moveTroll(View.Dir.RIGHT);
160 else if (delta < 0) {
162 view.moveTroll(View.Dir.LEFT);
165 view.moveTroll(View.Dir.STILL);
170 // XXX very similar to main turn pendant
171 private void finishStones() {
172 boolean noStones = true;
174 for (Player player : gameManager.getActivePlayers()) {
175 if (model.haveWinner() && player.getIndex() == model.getLoser())
177 player.stoneThrow = player.model.getStones();
178 player.model.setStones(0);
179 delta += player.stoneThrow * player.model.getMultiplier();
180 player.view.throwStones(player.stoneThrow);
181 if (player.stoneThrow != 0) {
183 player.view.animateStones(player.stoneThrow);
184 player.view.updateStoneCounter();
187 if (noStones) { endGame(); return; }
188 model.moveTroll(delta);
192 private void endGame() {
193 gameManager.endGame();
195 if (model.haveWinner()) {
196 int loser = model.getLoser();
197 gameManager.getPlayer(loser).view.defeat();
200 Player p0 = gameManager.getPlayer(0);
201 Player p1 = gameManager.getPlayer(1);
203 int s0 = p0.getScore();
204 int s1 = p1.getScore();