108b5a669aeb26cd3d6b7d878c1ccf854bf1d45a
[troll.git] / src / main / java / com / codingame / game / Model.java
1 package com.codingame.game;
2
3 import java.util.Random;
4 import java.util.Properties;
5
6 import com.codingame.gameengine.core.GameManager;
7 import com.codingame.gameengine.core.MultiplayerGameManager;
8 import com.google.inject.Inject;
9
10 class Model {
11     @Inject private MultiplayerGameManager<com.codingame.game.Player> gameManager;
12     long seed;
13     Random random;
14     int roadLength;
15     int initialStones;
16     int trollPosition;
17     Player p0, p1;
18
19     class Player {
20         com.codingame.game.Player gp;
21         int index;
22         boolean hit;
23
24         Player(int i) {
25             index = i;
26             hit = false;
27         }
28
29         private int castlePosition;
30         public int getCastlePosition() { return castlePosition; }
31         public void setCastlePosition(int pos) { castlePosition = pos; }
32
33         private int multiplier;
34         public int getMultiplier() { return multiplier; }
35         public void setMultiplier(int m) { multiplier = m; }
36
37         class FailedToThrowStonesAndShouldHave extends Exception {}
38         class ThrewMoreStonesThanHad extends Exception {}
39
40         private int stones;
41         public int getStones() { return stones; }
42         public void consumeStones(int n)
43             throws ThrewMoreStonesThanHad,
44                    FailedToThrowStonesAndShouldHave
45         {
46             if (n > stones) {
47                 throw new ThrewMoreStonesThanHad();
48             }
49             if (n == 0 && stones > 0) {
50                 throw new FailedToThrowStonesAndShouldHave();
51             }
52             setStones(stones - n);
53         }
54         public int consumeMaxStones() {
55             int r = stones;
56             stones = 0;
57             return r;
58         }
59         public int consumeMinStones() {
60             if (stones < 1) {
61                 throw new Error("Internal error: tried to consume min stones on an empty heap.");
62             }
63             stones--;
64             return 1;
65         }
66         public void setStones(int n) {
67             stones = n;
68         }
69         public int getOppStones() {
70             return p0.stones + p1.stones - stones;
71         }
72
73         public void adjustScore(int trollPosition) {
74             if (gp.isActive()) {
75                 gp.setScore(Math.abs(castlePosition - trollPosition));
76             }
77         }
78
79         public int getTrollDistance() {
80             return Math.abs(castlePosition - trollPosition);
81         }
82     }
83
84     void init() {
85         seed = gameManager.getSeed();
86         random = new Random(seed);
87         switch (random.nextInt(4)) {
88         case 0:
89             roadLength = 6;
90             initialStones = 15;
91             break;
92         case 1:
93             roadLength = 6;
94             initialStones = 30;
95             break;
96         case 2:
97             roadLength = 14;
98             initialStones = 30;
99             break;
100         case 3:
101             roadLength = 14;
102             initialStones = 50;
103             break;
104         }
105
106         Properties ps = gameManager.getGameParameters();
107         String buf = ps.getProperty("roadLength");
108         if (buf != null) {
109             try {
110                 int i = Integer.parseInt(buf);
111                 if (i < 0 || i > 20 || (i & 1) != 0) {
112                     gameManager.addToGameSummary(GameManager.formatErrorMessage("Ignoring invalid road length: " + buf));
113                 }
114                 else {
115                     roadLength = i;
116                     gameManager.addToGameSummary("Road length overridden to " + i);
117                 }
118             }
119             catch(NumberFormatException e) {
120                 gameManager.addToGameSummary(GameManager.formatErrorMessage("Ill-formed road length: " + buf));
121             }
122         }
123         ps.setProperty("roadLength", new Integer(roadLength).toString());
124
125         buf = ps.getProperty("initialStones");
126         if (buf != null) {
127             try {
128                 int i = Integer.parseInt(buf);
129                 if (i > 50) {
130                     gameManager.addToGameSummary(GameManager.formatErrorMessage("Ignoring invalid initial stone count: " + buf));
131                 }
132                 else {
133                     initialStones = i;
134                     gameManager.addToGameSummary("Initial stone count overridden to " + buf);
135                 }
136             }
137             catch (NumberFormatException e) {
138                 gameManager.addToGameSummary(GameManager.formatErrorMessage("Ill-formed initial stone count: " + buf));
139             }
140         }
141         ps.setProperty("initialStones", new Integer(initialStones).toString());
142
143         trollPosition = roadLength / 2;
144
145         p0 = new Player(0);
146         p0.gp = gameManager.getPlayer(0);
147         p0.setCastlePosition(0);
148         p0.setMultiplier(1);
149         p0.adjustScore(trollPosition);
150         p0.setStones(initialStones);
151
152         p1 = new Player(1);
153         p1.gp = gameManager.getPlayer(1);
154         p1.setCastlePosition(roadLength);
155         p1.setMultiplier(-1);
156         p1.adjustScore(trollPosition);
157         p1.setStones(initialStones);
158     }
159
160     void moveTroll(int delta) {
161         trollPosition += delta;
162         if (trollPosition <= 0) {
163             trollPosition = 0;
164             winner = 1;
165         }
166         if (trollPosition >= roadLength) {
167             trollPosition = roadLength;
168             winner = 0;
169         }
170
171         p0.adjustScore(trollPosition);
172         p1.adjustScore(trollPosition);
173     }
174
175     private Integer winner;
176     boolean haveWinner() {
177         return winner != null;
178     }
179
180     int getWinner() { return winner; }
181     int getLoser() { return 1 - winner; }
182
183     boolean exhausted() {
184         return p0.getStones() <= 0 || p1.getStones() <= 0;
185     }
186 }