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