-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAnts.java
503 lines (448 loc) · 13.3 KB
/
Ants.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
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Holds all game data and current game state.
*/
public class Ants {
/** Maximum map size. */
public static final int MAX_MAP_SIZE = 256 * 2;
private final int loadTime;
private final int turnTime;
private final int rows;
private final int cols;
private final int turns;
private final int viewRadius2;
private final int attackRadius2;
private final int spawnRadius2;
private final boolean visible[][];
private final Set<Tile> visionOffsets;
private long turnStartTime;
private final Ilk map[][];
private final Set<Tile> myAnts = new HashSet<Tile>();
private final Set<Tile> enemyAnts = new HashSet<Tile>();
private final Set<Tile> myHills = new HashSet<Tile>();
private final Set<Tile> enemyHills = new HashSet<Tile>();
private final Set<Tile> foodTiles = new HashSet<Tile>();
private final Set<Order> orders = new HashSet<Order>();
/**
* Creates new {@link Ants} object.
*
* @param loadTime timeout for initializing and setting up the bot on turn 0
* @param turnTime timeout for a single game turn, starting with turn 1
* @param rows game map height
* @param cols game map width
* @param turns maximum number of turns the game will be played
* @param viewRadius2 squared view radius of each ant
* @param attackRadius2 squared attack radius of each ant
* @param spawnRadius2 squared spawn radius of each ant
*/
public Ants(int loadTime, int turnTime, int rows, int cols, int turns, int viewRadius2,
int attackRadius2, int spawnRadius2) {
this.loadTime = loadTime;
this.turnTime = turnTime;
this.rows = rows;
this.cols = cols;
this.turns = turns;
this.viewRadius2 = viewRadius2;
this.attackRadius2 = attackRadius2;
this.spawnRadius2 = spawnRadius2;
map = new Ilk[rows][cols];
for (Ilk[] row : map) {
Arrays.fill(row, Ilk.LAND);
}
visible = new boolean[rows][cols];
for (boolean[] row : visible) {
Arrays.fill(row, false);
}
// calc vision offsets
visionOffsets = new HashSet<Tile>();
int mx = (int)Math.sqrt(viewRadius2);
for (int row = -mx; row <= mx; ++row) {
for (int col = -mx; col <= mx; ++col) {
int d = row * row + col * col;
if (d <= viewRadius2) {
visionOffsets.add(new Tile(row, col));
}
}
}
}
/**
* Returns timeout for initializing and setting up the bot on turn 0.
*
* @return timeout for initializing and setting up the bot on turn 0
*/
public int getLoadTime() {
return loadTime;
}
/**
* Returns timeout for a single game turn, starting with turn 1.
*
* @return timeout for a single game turn, starting with turn 1
*/
public int getTurnTime() {
return turnTime;
}
/**
* Returns game map height.
*
* @return game map height
*/
public int getRows() {
return rows;
}
/**
* Returns game map width.
*
* @return game map width
*/
public int getCols() {
return cols;
}
/**
* Returns maximum number of turns the game will be played.
*
* @return maximum number of turns the game will be played
*/
public int getTurns() {
return turns;
}
/**
* Returns squared view radius of each ant.
*
* @return squared view radius of each ant
*/
public int getViewRadius2() {
return viewRadius2;
}
/**
* Returns squared attack radius of each ant.
*
* @return squared attack radius of each ant
*/
public int getAttackRadius2() {
return attackRadius2;
}
/**
* Returns squared spawn radius of each ant.
*
* @return squared spawn radius of each ant
*/
public int getSpawnRadius2() {
return spawnRadius2;
}
/**
* Sets turn start time.
*
* @param turnStartTime turn start time
*/
public void setTurnStartTime(long turnStartTime) {
this.turnStartTime = turnStartTime;
}
/**
* Returns how much time the bot has still has to take its turn before timing out.
*
* @return how much time the bot has still has to take its turn before timing out
*/
public int getTimeRemaining() {
return turnTime - (int)(System.currentTimeMillis() - turnStartTime);
}
/**
* Returns ilk at the specified location.
*
* @param tile location on the game map
*
* @return ilk at the <cod>tile</code>
*/
public Ilk getIlk(Tile tile) {
return map[tile.getRow()][tile.getCol()];
}
/**
* Sets ilk at the specified location.
*
* @param tile location on the game map
* @param ilk ilk to be set at <code>tile</code>
*/
public void setIlk(Tile tile, Ilk ilk) {
map[tile.getRow()][tile.getCol()] = ilk;
}
/**
* Returns ilk at the location in the specified direction from the specified location.
*
* @param tile location on the game map
* @param direction direction to look up
*
* @return ilk at the location in <code>direction</code> from <cod>tile</code>
*/
public Ilk getIlk(Tile tile, Aim direction) {
Tile newTile = getTile(tile, direction);
return map[newTile.getRow()][newTile.getCol()];
}
/**
* Returns location in the specified direction from the specified location.
*
* @param tile location on the game map
* @param direction direction to look up
*
* @return location in <code>direction</code> from <cod>tile</code>
*/
public Tile getTile(Tile tile, Aim direction) {
int row = (tile.getRow() + direction.getRowDelta()) % rows;
if (row < 0) {
row += rows;
}
int col = (tile.getCol() + direction.getColDelta()) % cols;
if (col < 0) {
col += cols;
}
return new Tile(row, col);
}
/**
* Returns location with the specified offset from the specified location.
*
* @param tile location on the game map
* @param offset offset to look up
*
* @return location with <code>offset</code> from <cod>tile</code>
*/
public Tile getTile(Tile tile, Tile offset) {
int row = (tile.getRow() + offset.getRow()) % rows;
if (row < 0) {
row += rows;
}
int col = (tile.getCol() + offset.getCol()) % cols;
if (col < 0) {
col += cols;
}
return new Tile(row, col);
}
/**
* Returns a set containing all my ants locations.
*
* @return a set containing all my ants locations
*/
public Set<Tile> getMyAnts() {
return myAnts;
}
/**
* Returns a set containing all enemy ants locations.
*
* @return a set containing all enemy ants locations
*/
public Set<Tile> getEnemyAnts() {
return enemyAnts;
}
/**
* Returns a set containing all my hills locations.
*
* @return a set containing all my hills locations
*/
public Set<Tile> getMyHills() {
return myHills;
}
/**
* Returns a set containing all enemy hills locations.
*
* @return a set containing all enemy hills locations
*/
public Set<Tile> getEnemyHills() {
return enemyHills;
}
/**
* Returns a set containing all food locations.
*
* @return a set containing all food locations
*/
public Set<Tile> getFoodTiles() {
return foodTiles;
}
/**
* Returns all orders sent so far.
*
* @return all orders sent so far
*/
public Set<Order> getOrders() {
return orders;
}
/**
* Returns true if a location is visible this turn
*
* @param tile location on the game map
*
* @return true if the location is visible
*/
public boolean isVisible(Tile tile) {
return visible[tile.getRow()][tile.getCol()];
}
/**
* Calculates distance between two locations on the game map.
*
* @param t1 one location on the game map
* @param t2 another location on the game map
*
* @return distance between <code>t1</code> and <code>t2</code>
*/
public int getDistance(Tile t1, Tile t2) {
int rowDelta = Math.abs(t1.getRow() - t2.getRow());
int colDelta = Math.abs(t1.getCol() - t2.getCol());
rowDelta = Math.min(rowDelta, rows - rowDelta);
colDelta = Math.min(colDelta, cols - colDelta);
return rowDelta * rowDelta + colDelta * colDelta;
}
/**
* Returns one or two orthogonal directions from one location to the another.
*
* @param t1 one location on the game map
* @param t2 another location on the game map
*
* @return orthogonal directions from <code>t1</code> to <code>t2</code>
*/
public List<Aim> getDirections(Tile t1, Tile t2) {
List<Aim> directions = new ArrayList<Aim>();
if (t1.getRow() < t2.getRow()) {
if (t2.getRow() - t1.getRow() >= rows / 2) {
directions.add(Aim.NORTH);
} else {
directions.add(Aim.SOUTH);
}
} else if (t1.getRow() > t2.getRow()) {
if (t1.getRow() - t2.getRow() >= rows / 2) {
directions.add(Aim.SOUTH);
} else {
directions.add(Aim.NORTH);
}
}
if (t1.getCol() < t2.getCol()) {
if (t2.getCol() - t1.getCol() >= cols / 2) {
directions.add(Aim.WEST);
} else {
directions.add(Aim.EAST);
}
} else if (t1.getCol() > t2.getCol()) {
if (t1.getCol() - t2.getCol() >= cols / 2) {
directions.add(Aim.EAST);
} else {
directions.add(Aim.WEST);
}
}
return directions;
}
/**
* Clears game state information about my ants locations.
*/
public void clearMyAnts() {
for (Tile myAnt : myAnts) {
map[myAnt.getRow()][myAnt.getCol()] = Ilk.LAND;
}
myAnts.clear();
}
/**
* Clears game state information about enemy ants locations.
*/
public void clearEnemyAnts() {
for (Tile enemyAnt : enemyAnts) {
map[enemyAnt.getRow()][enemyAnt.getCol()] = Ilk.LAND;
}
enemyAnts.clear();
}
/**
* Clears game state information about food locations.
*/
public void clearFood() {
for (Tile food : foodTiles) {
map[food.getRow()][food.getCol()] = Ilk.LAND;
}
foodTiles.clear();
}
/**
* Clears game state information about my hills locations.
*/
public void clearMyHills() {
myHills.clear();
}
/**
* Clears game state information about enemy hills locations.
*/
public void clearEnemyHills() {
enemyHills.clear();
}
/**
* Clears game state information about dead ants locations.
*/
public void clearDeadAnts() {
//currently we do not have list of dead ants, so iterate over all map
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (map[row][col] == Ilk.DEAD) {
map[row][col] = Ilk.LAND;
}
}
}
}
/**
* Clears visible information
*/
public void clearVision() {
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < cols; ++col) {
visible[row][col] = false;
}
}
}
/**
* Calculates visible information
*/
public void setVision() {
for (Tile antLoc : myAnts) {
for (Tile locOffset : visionOffsets) {
Tile newLoc = getTile(antLoc, locOffset);
visible[newLoc.getRow()][newLoc.getCol()] = true;
}
}
}
/**
* Updates game state information about new ants and food locations.
*
* @param ilk ilk to be updated
* @param tile location on the game map to be updated
*/
public void update(Ilk ilk, Tile tile) {
map[tile.getRow()][tile.getCol()] = ilk;
switch (ilk) {
case FOOD:
foodTiles.add(tile);
break;
case MY_ANT:
myAnts.add(tile);
break;
case ENEMY_ANT:
enemyAnts.add(tile);
break;
}
}
/**
* Updates game state information about hills locations.
*
* @param owner owner of hill
* @param tile location on the game map to be updated
*/
public void updateHills(int owner, Tile tile) {
if (owner > 0)
enemyHills.add(tile);
else
myHills.add(tile);
}
/**
* Issues an order by sending it to the system output.
*
* @param myAnt map tile with my ant
* @param direction direction in which to move my ant
*/
public void issueOrder(Tile myAnt, Aim direction) {
Order order = new Order(myAnt, direction);
orders.add(order);
System.out.println(order);
}
}