Early termination
[troll.git] / src / main / java / com / codingame / game / Referee.java
1 package com.codingame.game;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.List;
6 import java.util.Random;
7
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;
19
20 public class Referee extends AbstractReferee {
21     @Inject private MultiplayerGameManager<Player> gameManager;
22     @Inject private GraphicEntityModule graphicEntityModule;
23
24     int roadLength;
25     int initialStones;
26     int trollPosition;
27     Player p0, p1;
28     Sprite troll;
29     Text trollPositionGauge;
30     
31     @Override
32     public void init() {
33         switch (new Random(gameManager.getSeed()).nextInt(4)) {
34         case 0:
35             roadLength = 7;
36             initialStones = 15;
37             break;
38         case 1:
39             roadLength = 7;
40             initialStones = 30;
41             break;
42         case 2:
43             roadLength = 15;
44             initialStones = 30;
45             break;
46         case 3:
47             roadLength = 15;
48             initialStones = 50;
49             break;
50         }
51
52         trollPosition = (roadLength - 1) / 2;
53
54         p0 = gameManager.getPlayer(0);
55         p0.setCastlePosition(0);
56         p0.setMultiplier(1);
57         p0.adjustScore(trollPosition);
58         p0.sendInputLine(String.format("%d %d", roadLength - 1, initialStones));
59
60         p1 = gameManager.getPlayer(1);
61         p1.setCastlePosition(roadLength-1);
62         p1.setMultiplier(-1);
63         p1.adjustScore(trollPosition);
64         p1.sendInputLine(String.format("%d %d", roadLength - 1, initialStones));
65
66         drawBackground();
67         drawPlayer();
68         drawTroll();
69
70         // result in text display, so do last:
71         p0.setStones(initialStones);
72         p1.setStones(initialStones);
73
74         gameManager.setFrameDuration(2000);
75     }
76
77     private void drawBackground() {
78         graphicEntityModule.createSprite()
79                 .setImage("background.png")
80                 .setAnchor(0);
81     }
82
83     private void drawPlayer() {
84         for (Player player : gameManager.getPlayers()) {
85             boolean p0 = player.getIndex() == 0;
86             int x = p0 ? 280 : 1920 - 280;
87             int y = 220;
88
89             Rectangle border1 = graphicEntityModule
90                     .createRectangle()
91                     .setWidth(140)
92                     .setHeight(140)
93                     .setX(x - 70)
94                     .setY(y - 70)
95                     .setLineWidth(0)
96                     .setFillColor(player.getColorToken());
97
98             Rectangle border2 = graphicEntityModule
99                     .createRectangle()
100                     .setWidth(120)
101                     .setHeight(120)
102                     .setX(x - 60)
103                     .setY(y - 60)
104                     .setLineWidth(0)
105                     .setFillColor(0xffffff);
106
107             Text text = graphicEntityModule.createText(player.getNicknameToken())
108                     .setX(x)
109                     .setY(y + 120)
110                     .setZIndex(20)
111                     .setFontSize(40)
112                     .setFillColor(0x7f3f00)
113                     .setAnchor(0.5);
114
115             Sprite avatar = graphicEntityModule.createSprite()
116                     .setX(x)
117                     .setY(y)
118                     .setZIndex(20)
119                     .setImage(player.getAvatarToken())
120                     .setAnchor(0.5)
121                     .setBaseHeight(116)
122                     .setBaseWidth(116);
123
124             Text stoneCounter = graphicEntityModule.createText("S")
125                 .setX(x)
126                 .setY(y+200)
127                 .setZIndex(20)
128                 .setFontSize(40)
129                 .setFillColor(0x7f3f00)
130                 .setAnchor(0.5);
131
132             player.castle = graphicEntityModule.createSprite()
133                 .setImage("castle.png")
134                 .setX(p0 ? 160 : 1920-160)
135                 .setY(p0 ? 890 : 880)
136                 .setZIndex(1)
137                 .setAnchorX(0.5)
138                 .setAnchorY(1);
139
140             player.stone = graphicEntityModule.createText()
141                 .setZIndex(3)
142                 .setFontSize(150)
143                 .setFillColor(0x12322a)
144                 .setAnchor(0.5)
145                 .setAlpha(0);
146
147             player.hud = graphicEntityModule.createGroup(border1, border2, text, avatar, stoneCounter, player.castle);
148             player.stoneCounter = stoneCounter;
149         }
150     }
151
152     private void drawTroll() {
153         troll = graphicEntityModule.createSprite()
154             .setImage("troll.png")
155             .setAnchorX(0.5)
156             .setAnchorY(1)
157             .setX(1920/2)
158             .setY(880)
159             .setZIndex(2);
160         trollPositionGauge = graphicEntityModule.createText()
161             .setZIndex(2)
162             .setAnchor(0.5)
163             .setFontSize(40)
164             .setX(1980/2)
165             .setY(980)
166             .setFillColor(0xffffff);
167     }
168
169     private void moveTroll() {
170         graphicEntityModule.commitEntityState(0.5, troll, trollPositionGauge);
171         int x0 = p0.castle.getX(), x1 = p1.castle.getX();
172         int y0 = p0.castle.getY(), y1 = p1.castle.getY();
173         troll.setX(x0 + trollPosition * (x1-x0) / (roadLength - 1),
174                    Curve.ELASTIC);
175         troll.setY(y0 + trollPosition * (y1-y0) / (roadLength - 1),
176                    Curve.ELASTIC);
177
178         trollPositionGauge.setX((trollPositionGauge.getX() + troll.getX()) / 2);
179         int delta = trollPosition - (roadLength - 1) / 2;
180         if (delta < 0) {
181             trollPositionGauge.setText("← " + Math.abs(delta));
182         }
183         else if (delta > 0) {
184             trollPositionGauge.setText(Math.abs(delta) + " →");
185         }
186         else {
187             trollPositionGauge.setText("↔");
188         }
189         graphicEntityModule.commitEntityState(0.75, trollPositionGauge);
190         trollPositionGauge.setX(troll.getX());
191     }
192
193     @Override
194     public void gameTurn(int turn) {
195
196         p0.sendInputLine(String.format("%d %d %d", p0.getScore(), p0.getStones(), p1.getStones()));
197         p1.sendInputLine(String.format("%d %d %d", p1.getScore(), p1.getStones(), p0.getStones()));
198
199         for (Player player : gameManager.getActivePlayers()) {
200             player.execute();
201         }
202
203         int delta = 0;
204         for (Player player : gameManager.getActivePlayers()) {
205             try {
206                 final int stones = player.getAction();
207                 player.consumeStones(stones);
208                 gameManager.addToGameSummary(String.format("%s throws %d stone%s at the troll.", player.getNicknameToken(), stones, stones == 1 ? "" : "s"));
209                 delta += player.getMultiplier() * stones;
210
211                 if (stones > 0) {
212                     player.stone.setX(player.castle.getX());
213                     player.stone.setY(player.castle.getY() - 100);
214                     player.stone.setText(new Integer(stones).toString());
215                     player.stone.setAlpha(1);
216                     graphicEntityModule.commitEntityState(0, player.stone);
217     
218                     int peakX = (player.castle.getX() + troll.getX()) / 2;
219                     int peakY = 540;
220                     player.stone.setX(peakX);
221                     player.stone.setY(peakY, Curve.EASE_OUT);
222                     graphicEntityModule.commitEntityState(0.25, player.stone,
223                                                           player.stoneCounter);
224     
225                     player.stone.setX(troll.getX());
226                     player.stone.setY(troll.getY() - 50, Curve.EASE_IN);
227                     player.stone.setAlpha(0, Curve.EASE_IN);
228                     graphicEntityModule.commitEntityState(0.5, player.stone);
229                 }
230             }
231             catch (InvalidAction e) {
232                 player.deactivate(player.getNicknameToken() + " INVALID");
233                 gameManager.addToGameSummary(GameManager.formatErrorMessage(player.getNicknameToken() + " " + e.getMessage()));
234                 player.setScore(-1);
235                 endGame();
236             }
237             catch (NumberFormatException e) {
238                 player.deactivate(player.getNicknameToken() + " ERROR");
239                 gameManager.addToGameSummary(GameManager.formatErrorMessage(player.getNicknameToken() + " provided malformed input!"));
240                 player.setScore(-1);
241                 endGame();
242             }
243             catch (TimeoutException e) {
244                 gameManager.addToGameSummary(player.getNicknameToken() + " timed out!");
245                 player.deactivate(player.getNicknameToken() + " T/O");
246                 player.setScore(-1);
247                 endGame();
248             }
249         }
250
251         if (delta > 0) {
252             gameManager.addToGameSummary("Troll walks right.");
253             trollPosition++;
254             moveTroll();
255         }
256         else if (delta < 0) {
257             gameManager.addToGameSummary("Troll walks left.");
258             trollPosition--;
259             moveTroll();
260         }
261         else {
262             gameManager.addToGameSummary("Troll stands still.");
263         }
264
265         for (Player player : gameManager.getActivePlayers()) {
266             player.adjustScore(trollPosition);
267             if (trollPosition == player.getCastlePosition()) {
268                 gameManager.addToGameSummary(GameManager.formatErrorMessage("Troll destroys " + player.getNicknameToken()));
269                 endGame();
270             }
271         }
272
273         if (p0.getStones() <= 0 && p1.getStones() <= 0) {
274             endGame();
275         }
276     }
277
278     private void endGame() {
279         gameManager.endGame();
280
281         if (p0.getScore() > p1.getScore()) {
282             gameManager.addToGameSummary(GameManager.formatSuccessMessage(p0.getNicknameToken() + " wins"));
283             p1.hud.setAlpha(0.3);
284         }
285         else if (p0.getScore() < p1.getScore()) {
286             gameManager.addToGameSummary(GameManager.formatSuccessMessage(p1.getNicknameToken() + " wins"));
287             p0.hud.setAlpha(0.3);
288         }
289         else {
290             gameManager.addToGameSummary(GameManager.formatErrorMessage("Everybody loses!"));
291             p0.hud.setAlpha(0.3);
292             p1.hud.setAlpha(0.3);
293         }
294     }
295 }