-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathHl.java
More file actions
331 lines (277 loc) · 13.7 KB
/
Hl.java
File metadata and controls
331 lines (277 loc) · 13.7 KB
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
// package esi18;
// import battleship.core.*;
// import java.util.List;
// /*
// * SimpleShip
// * @author Your Name
// */
// public class Hl extends Ship {
// private LinkedHashMap<Ship, int[][]> potentialThreat;
// public Hl() {
// this.initializeName("Cargo Ship");
// this.initializeOwner("Nick");
// this.initializeHull(2);
// this.initializeFirepower(3);
// this.initializeSpeed(1);
// this.initializeRange(4);
// }
// @Override
// public boolean equals(Ship other) {
// if (this instanceof other) {
// return true;
// }
// return false;
// }
// /*
// Goal: save information about each ship where they compose into a single action
// Individual map of all ship's firepower + range + speed in a list
// Filter the list with two cases:
// Ships that can be destroyed in a single turn:
// Destroying that ship will clear up potential threat map
// so we can optionally move in to attack if we know the threat will be destroyed
// Ships that cannot be destroyed in a single turn:
// In this case fire on the ship with the highest firepower/hull ratio that are within range
// target higher range as a tie breaker for the ratio
// Then move back into safety or into a group to lower risk of attack
// */
// private LinkedHashMap<Ship, int[][]> updateThreat(Arena arena) {
// LinkedHashMap<Ship, int[][]> result = new LinkedHashMap<>();
// List<Ship> allShips = arena.getAllShips();
// for (int shipIdx = 0; shipIdx < allShips.size(); shipIdx++) {
// Ship ship = allShips.get(shipIdx);
// int[][] heatmap = new int[arena.getXSize()][arena.getYSize()];
// // friendly ship will have a negative heatmap, foe ship positive
// int friendly = (this.isSameTeamAs(ship)) ? -1 : 1;
// // account for potential dangers from ship's movement then attack combo
// int multiplier = ship.getSpeed();
// // reduce the number of heatmap that needs to be traverse
// int minX = Math.max(0, ship.getX() - (ship.getRange() + ship.getSpeed()));
// int minY = Math.max(0, ship.getY() - (ship.getRange() + ship.getSpeed()));
// int maxX = Math.min(arena.getX(), ship.getX() + ship.getRange() + ship.getSpeed());
// int maxY = Math.min(arena.getY(), ship.getY() + ship.getRange() + ship.getSpeed());
// for (int mapX = minX; mapX < maxX; mapX++) {
// for (int mapY = minY; mapY < maxY; mapY++) {
// int xdiff = Math.abs(mapX - ship.getX());
// int ydiff = Math.abs(mapY - ship.getY());
// // if (x, y) is within the given ship's range
// if (xdiff <= ship.getRange() &&
// ydiff <= ship.getRange() ) {
// heatmap[mapX][mapY] += firepower * friendly * multiplier;
// }
// // these (x, y) areas are where movement is required inorder to attack a given ship
// else if (xdiff - ship.getSpeed() <= ship.getRange() &&
// ydiff - ship.getSpeed() <= ship.getRange() ) {
// int reducedMultiplier = Math.max(xdiff - ship.getSpeed(), ydiff - ship.getSpeed());
// if (reducedMultiplier < 0) {
// // negative only when shooting a ship that's already within range
// // this cannot happen because it's convered in the first if statement
// throw new AssertionError("Invalid Multiplier: " + reducedMultiplier);
// }
// heatmap[mapX][mapY] += firepower * friendly * (multiplier - reducedMultiplier);
// }
// }
// }
// result.put(ship, heatmap);
// }
// return result;
// }
// private LinkedHashMap<Ship, int[][]> filterNearby(LinkedHashMap<Ship, int[][]> data, boolean needMove) {
// LinkedHashMap<Ship, int[][]> result = new LinkedHashMap<>();
// int movement = 0;
// if (needMove) {
// // get remaining move is used to allow this method to be called multiple times in one turn
// movement = this.getRemainingMoves();
// }
// result = data.entrySet().stream().filter((ship) -> {
// if (Math.abs(this.getX() - ship.getX()) - movement <= this.getRange() &&
// Math.abs(this.getY() - ship.getY()) - movement <= this.getRange() ) {
// return true;
// }
// return false;
// }).collect(Collectors.toMap(ship -> ship.getKey(), ship -> ship.getValue()));
// return result;
// }
// private LinkedHashMap<Ship, int[][]> filterSinkable(LinkedHashMap<Ship, int[][]> data, boolean sinkable) {
// LinkedHashMap<Ship, int[][]> result = new LinkedHashMap<>();
// result = data.entrySet().stream().filter((ship) -> {
// if (ship.getHealth() <= this.getRemainingShots()) {
// return (true == sinkable);
// }
// return (false == sinkable);
// }).collect(Collectors.toMap(ship -> ship.getKey(), ship -> ship.getValue()));
// return result;
// }
// private LinkedHashMap<Ship, int[][]> filterFriendly(LinkedHashMap<Ship, int[][]> data, boolean foe) {
// LinkedHashMap<Ship, int[][]> result = new LinkedHashMap<>();
// result = data.entrySet().stream().filter((ship) -> {
// // filter out your own ship in all cases
// if (!this.equals(ship)) {
// if (!this.isSameTeamAs(ship) == foe) {
// return true;
// }
// return false;
// }
// return false;
// }).collect(Collectors.toMap(ship -> ship.getKey(), ship -> ship.getValue()));
// return result;
// }
// private LinkedHashMap<Ship, int[][]> sortPriority(LinkedHashMap<Ship, int[][]> data) {
// LinkedHashMap<Ship, int[][]> result = new LinkedHashMap<>();
// result = data.entrySet().stream().sorted((lhs, rhs) -> {
// // sort by highest firepower/health ratio first
// double rhsRatio = (double) rhs.getFirepower()/rhs.getHealth();
// double lhsRatio = (double) lhs.getFirepower()/lhs.getHealth();
// if ((int)rhsRatio != (int)lhsRatio) {
// return (int)(rhsRatio - lhsRatio);
// }
// // sort by the highest range first
// else if (rhs.getRange() != lhs.getRange()) {
// return rhs.getRange() - lhs.getRange();
// }
// // sort by lowest health first
// else if (lhs.getHealth() != rhs.getHealth()) {
// return lhs.getHealth() - rhs.getHealth();
// }
// else {
// return lhs.getName().compareTo(rhs.getName());
// }
// }).collect(Collectors.toMap(ship -> ship.getKey(), ship -> ship.getValue()));
// return result;
// }
// private int[][] composeMap(Arena arena, LinkedHashMap<Ship, int[][]> data) {
// int[][] heatmap = new int[arena.getXSize()][arena.getYSize()];
// for (Map.Entry<Ship, int[][]> entry : data.entrySet()) {
// for (int x = 0; x < arena.getXSize(); x++) {
// for (int y = 0; y < arena.getYSize(); y++) {
// heatmap[x][y] += entry.getValue()[x][y];
// }
// }
// }
// return heatmap;
// }
// // function only works for ship speed of 1
// private Direction deriveMovement(Coord start, Coord goal) {
// Direction result;
// if (start.getX() < goal.getX()) {
// result = Direction.EAST;
// }
// if (start.getX() > goal.getX()) {
// result = Direction.WEST;
// }
// if (start.getY() > goal.getY()) {
// result = Direction.SOUTH;
// }
// if (start.getY() < goal.getY()) {
// result = Direction.NORTH;
// }
// }
// private Coord offsetCoord(Coord start, Direction dir) {
// Coord result;
// if (dir == Direction.NORTH) {
// result = new Coord(start.getX(), start.getY()-1);
// }
// else if (dir == Direction.SOUTH) {
// result = new Coord(start.getX(), start.getY()+1);
// }
// else if (dir == Direction.WEST) {
// result = new Coord(start.getX()-1, start.getY());
// }
// else if (dir == Direction.EAST) {
// result = new Coord(start.getX()+1, start.getY());
// }
// else {
// result = start;
// }
// return result;
// }
// /* Offense Cases: (no nearby, nearby within movement, sinkables)
// * no nearby ships within own movement
// * Move closer (can be risky)
// * nearby ships within own movement
// * for sinkable ships
// if (low threat)
// * move closer / attack
// else
// * move closer to team if low hp / stay put
// Defense Cases: (non sinkeable nearby ships)
// * fire using priority filter
// * move closer to team
// */
// /*
// * Determines what actions the ship will take on a given turn
// * @param arena (Arena) the battlefield for the match
// * @return void
// */
// @Override
// protected void doTurn(Arena arena) {
// LinkedHashMap<Ship, int[][]> data = updateThreat(arena);
// LinkedHashMap<Ship, int[][]> nearby = filterNearby(data, true);
// LinkedHashMap<Ship, int[][]> moveNearby = filterNearby(data, false);
// LinkedHashMap<Ship, int[][]> nearbyEnemy = filterFriendly(nearby, true);
// LinkedHashMap<Ship, int[][]> moveNearbyEnemy = filterFriendly(moveNearby, true);
// // on offense if there are no nearby enemy that are shootable without movement
// boolean offense = nearbyEnemy.size() == 0;
// if (offense) {
// if (moveNearbyEnemy.size() == 0) {
// // move closer, need a easy wait to find a direction
// // This step will take a bit of a risk
// LinkedHashMap<Ship, int[][]> search = filterFriendly(data, true);
// LinkedHashMap<Ship, int[][]> priority = sortPriority(search);
// Ship first = priority.firstEntry().getKey();
// Direction moveDir = deriveMovement(this.getCoord(), first.getCoord());
// this.move(arena, moveDir);
// List<Ship> nearby = this.getNearbyShips(arena);
// for (Ship s : nearby) {
// if (!this.isSameTeamAs(s)) {
// Coord loc = s.getCoord();
// this.fire(arena, loc.getX(), loc.getY());
// }
// }
// } else {
// // find sinkables within movement
// LinkedHashMap<Ship, int[][]> priority = sortPriority(moveNearbyEnemy);
// int[][] currentThreats = composeMap(priority);
// LinkedHashMap<Ship, Integer> fireSolution = new LinkedHashMap<>();
// for (Map.Entry<Ship, int[][]> entry : priority.entrySet()) {
// Ship enemy = entry.getKey();
// int[][] negatedThreat = entry.getValue(); // once destroyed
// Direction moveDir = deriveMovement(this.getCoord(), enemy.getCoord());
// Coord moveTo = offsetCoord(this.getCoord(), moveDir);
// int threatAfterSink = currentThreats[moveTo.getX()][moveTo.getY()] - negatedThreat[moveTo.getX()][moveTo.getY()];
// fireSolution.put(enemy, threatAfterSink);
// }
// fireSolution.entrySet().stream()
// .sorted(Map.Entry.comparingByValue().reversed())
// .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
// // move to enemy first
// for (Map.Entry<Ship, Integer> entry : fireSolution.entrySet()) {
// Ship enemy = entry.getKey();
// Coord enemyLoc = enemy.getCoord();
// if (this.getRemainingMoves() > 0) {
// Direction moveDir = deriveMovement(this.getCoord(), enemyLoc);
// this.move(arena, moveDir);
// }
// if (this.getRemainingShots() == 0) {
// break;
// }
// else {
// while(this.getRemainingShots() > 0 && enemy.getHealth() > 0) {
// this.fire(arena, enemyLoc.getX(), enemyLoc.getY());
// }
// }
// }
// }
// } else {
// // find sinkables, and safety after shooting
// LinkedHashMap<Ship, int[][]> destroy = filterSinkable(nearbyEnemy, true);
// if (destroy.size() == 0) {
// // no sinkables, focus on shooting high firepower/hull ratio ships
// LinkedHashMap<Ship, int[][]> priority = sortPriority(nearbyEnemy);
// int[][] currentThreat = composeMap(priority);
// }
// else {
// // shoot sinkables, move back
// }
// }
// }
// }