-
Notifications
You must be signed in to change notification settings - Fork 0
/
Castle.java
executable file
·343 lines (310 loc) · 8.61 KB
/
Castle.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/*******************************************************************************
* Copyright (C) 2019-2020 ROMAINPC
* Copyright (C) 2019-2020 Picachoc
*
* This file is part of PICROM-Wars
*
* PICROM-Wars is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PICROM-Wars is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package picrom.entity.castle;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import picrom.entity.Entity;
import picrom.entity.unit.Unit;
import picrom.gameboard.World;
import picrom.owner.Owner;
import picrom.utils.Drawables;
import picrom.utils.Settings;
import picrom.utils.Utils.Direction;
/**
* Castles are the main objectiv of this game. Castles are town wich contain
* garrisons of Units, but also doors and production centers.
*
* Castles have a treasure that they enrich over time.
*
* It's possible to improve the level of a Castle to enrich quicker, Castle
* class is a Producible.
*
* Castles are also JavaFX components and must be added in a World context.
*
* @see picrom.entity.unit.Unit
* @see picrom.entity.castle.Courtyard
* @see picrom.entity.castle.Door
* @see picrom.entity.castle.ProductionUnit
* @see picrom.entity.castle.Producible
*/
public class Castle extends Entity implements Producible {
private ProductionUnit productionUnit;
private int level;
private int treasure;
private Door door;
private Courtyard court;
private int nextLevelCost, nextLevelTime;
private int income;
private Class<? extends Producible> productionType;
/**
* Construct a new Castle in a World gameboard.
*
* @param owner The Owner of the castle
* @param X X coordinate of the Castle in the World coordinate system.
* @param Y Y coordinate of the Castle in the World coordinate system.
* @param doorDir Orientation of the Door
* @param context World context.
*/
public Castle(Owner owner, int X, int Y, Direction doorDir, World context) {
super(Drawables.castle, owner, X, Y, context);
level = 1;
productionUnit = new ProductionUnit(this);
this.door = new Door(doorDir, false);
switch (doorDir) {
case East:
image.setImage(Drawables.castle_e);
break;
case South:
image.setImage(Drawables.castle_s);
break;
case West:
image.setImage(Drawables.castle_w);
break;
default:
break;
}
court = new Courtyard();
nextLevelCost = 1000 * level;
nextLevelTime = 100 + 50 * level;
income = level * Settings.INCOME_MULTIPLIER;
productionType = null;
setTreasure(Settings.START_TREASURE);
}
/**
* To add an Unit to the garrison (For instance produced Unit or entered Unit)
*
* @param u the Unit
*/
public void enterUnit(Unit u) {
court.addUnit(u);
u.setWorldX(this.getWorldX());
u.setWorldY(this.getWorldY());
u.setOrigin(this);
u.setObjective(null);
}
/**
* To exit an Unit from the Castle.
*
* @param u the Unit
*/
public void launchUnit(Unit u) {
court.removeUnit(u);
u.setObjective(court.getObjective());
getContext().engageUnit(u);
}
/**
* @return Level of the Castle
*/
public int getLevel() {
return level;
}
/**
* Set Level of the Castle, affect income.
*
* @param level new level
*/
public void setLevel(int level) {
this.level = level;
income = level * Settings.INCOME_MULTIPLIER;
}
/**
* @return Amount of money in the Castle
*/
public int getTreasure() {
return treasure;
}
/**
* Set Amount of money in the Castle
*
* @param treasure new treasure
*/
public void setTreasure(int treasure) {
this.treasure = treasure;
}
/**
* @return Income of money per turn for the Castle
*/
public int getIncome() {
return income;
}
/**
* @return the only Door of the Castle
*/
public Door getDoor() {
return door;
}
/**
* @return true if there is at least on Unit in the Castle
*/
public boolean isGarrison() {
return !court.getUnits().isEmpty();
}
/**
* Increase level of the Castle.
*
* @param castle unused
*/
public void produce(Castle castle) {
setLevel(getLevel() + 1);
nextLevelCost = 1000 * level;
nextLevelTime = 100 + 50 * level;
}
@Override
public int getProductionCost() {
return nextLevelCost;
}
@Override
public int getProductionTime() {
return nextLevelTime;
}
/**
* @return Castle target of the Castle
*/
public Castle getObjective() {
return court.getObjective();
}
/**
* Set Castle target of the Castle
*
* @param objective new objectiv
*/
public void setObjective(Castle objective) {
court.setObjective(objective);
}
/**
* Start stop or advance current production, relaunch same production if that
* was an Unit.
*/
public void updateProduction() {
if (productionType != null) {
if (productionUnit.isProduced()) { // start or restart new production
if (productionType == Castle.class) {
productionUnit.setProduction(this);
} else {
try {
productionUnit
.setProduction(productionType.getDeclaredConstructor(Castle.class).newInstance(this));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
productionUnit.update();
if (productionUnit.isProduced()) {
productionType = (productionType == Castle.class ? null : productionType); // stop production if it was
// castle improvments
}
}
/**
* Get the time remaining to finish production choosed.
*
* @return Number of update of updateProduction() needed to finish production.
* Also consider turns to have enough money.
*/
public int getProductionTimeLeft() {
int leftTime = productionUnit.getTimeLeft() + 1; // +1 because TimeLeft is from X-1 to 0. We want from X to 0.
int leftMoney = (productionUnit.getCost() - treasure) / income;
leftTime = leftTime < 0 ? 0 : leftTime;
leftMoney = leftMoney < 0 ? 0 : leftMoney;
return Math.max(leftTime, leftMoney);
}
/**
* Set the type of class to produce. Can be null.
*
* @param productionType (use ".class")
*/
public void setProduction(Class<? extends Producible> productionType) {
this.productionType = productionType;
this.productionUnit.stop();
}
/**
* @return Current type of production. Can be null.
*/
public Class<? extends Producible> getProduction() {
return productionType;
}
/**
* Call this method to trigger an attack on the Castle. Will inflict damages on
* the garrison.
*
* @param attacker The ennemy Unit which attack the Castle
* @param damage The amount of damages that the Unit will inflict.
*/
public void attackWith(Unit attacker, int damage) {
court.assault(damage);
attacker.setDamage(attacker.getDamage() - damage);
}
/**
* To know which unit is launchable, have an objective to do and the door open.
*
* @return One unit to launch toward the objectiv (gameplay choice)
*/
public List<Unit> getLaunchList() {
List<Unit> l = new LinkedList<Unit>();
if (court.getObjective() != null && door.isOpen())
l.addAll(court.getReadyUnits(1)); // one at each execution, because
return l;
}
/*
* Get number of each kind of unit currently in the castle.
*
* @return Map which associate to a class of units the number of units of this
* type in garrison.
*/
public Map<Class<? extends Unit>, Integer> getGarrisonQuantity() {
Map<Class<? extends Unit>, Integer> map = new HashMap<Class<? extends Unit>, Integer>();
for (Unit unit : court.getUnits()) {
Integer n = map.get(unit.getClass());
if (n == null)
n = 0;
n++;
map.put(unit.getClass(), n);
}
return map;
}
/**
* @return The sum of all health points of Units in garrison.
*/
public int getGarrisonDefense() {
int result = 0;
for (Unit unit : court.getUnits()) {
result += unit.getHp();
}
return result;
}
/**
* @return The sum of all damage points of Units in garrison.
*/
public int getGarrisonAttack() {
int result = 0;
for (Unit unit : court.getUnits()) {
result += unit.getDamage();
}
return result;
}
@Override
public String toString() {
return "Castle (" + getWorldX() + ", " + getWorldY() + "), Owner: " + getOwner() + ", Level: " + level
+ ", Target: " + getObjective();
}
}