-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPlayerAI.py
More file actions
436 lines (408 loc) · 18.7 KB
/
Copy pathPlayerAI.py
File metadata and controls
436 lines (408 loc) · 18.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
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
from PythonClientAPI.libs.Game.Enums import *
from PythonClientAPI.libs.Game.MapOutOfBoundsException import *
# PeaceBot v1.0
# Creator: HardcoreEgg
class PlayerAI:
def __init__(self):
# Define how paranoid PeaceBot will be
self.PARNOID_LEVEL = 6
# Dictionary that maps direction to action
self.direction_convert = {
Direction.UP: "FACE_UP",
Direction.DOWN: "FACE_DOWN",
Direction.LEFT: "FACE_LEFT",
Direction.RIGHT: "FACE_RIGHT",
False: "NO_MOVE"
}
# Dictionary that converts string to API commands
self.action_convert = {
"FACE_UP": Move.FACE_UP,
"FACE_DOWN": Move.FACE_DOWN,
"FACE_LEFT" : Move.FACE_LEFT,
"FACE_RIGHT": Move.FACE_RIGHT,
"FORWARD": Move.FORWARD,
"NO_MOVE": Move.NONE,
"SHOOT": Move.SHOOT,
"LASER": Move.LASER,
"TELEPORT1": Move.TELEPORT_0,
"TELEPORT2": Move.TELEPORT_2,
"TELEPORT3": Move.TELEPORT_3,
"TELEPORT4": Move.TELEPORT_4,
"TELEPORT5": Move.TELEPORT_5
}
self.timer = 0
self.turrets = []
def get_move(self, gameboard, player, opponent):
# LET'S DO THIS
#increment turn count
self.timer = self.timer + 1
# first move to initialize positions of static turrets
if (self.timer == 1):
self.turrets = gameboard.turrets
for turret in self.turrets:
turret.killzone = turret_kill_zone(turret.x, turret.y, gameboard.width, gameboard.height)
turret.schedule = [turret.fire_time, turret.cooldown_time, turret.fire_time + turret.cooldown_time]
return self.action_convert[find_move(self, gameboard, player, opponent)]
# HELPER METHODS #
# finds the best possible move
def find_move(self, gameboard, player, opponent):
# defensive maneuvre decision tree
defence = defensive_action(self, gameboard, player.x, player.y, 0, player, opponent)
if (defence != "Safe"):
return decide_direction(self.direction_convert, defence, player.direction)
return "NO_MOVE"
# This shit is recursive backtracking, handle it like it's a fucking time bomb dude
# Recursively searches through all possible defensive maneuvres and returns the first possible one
# which will ensure survival for the next 3 turns (hopefully)
def defensive_action(self, gameboard, x, y, turn, player, opponent):
# stop at depth 3, can increase if time permits
if (turn == 3):
return True
if (is_hit(self, gameboard, x, y, turn) and turn != 0):
return False
turn = turn + 1
# get possible directions that are not blocked by walls
directions = possible_moves(self, gameboard, x, y)
# dodge turrets
lethal_turrets = find_lethal_turrets(self, x, y)
for turret in lethal_turrets:
# turret will fire right when you land on the tile
if (turret_will_fire(turret, turn - 2 + self.timer)):
return False
# turret about to fire this turn
elif (turret_will_fire(turret, turn - 1 + self.timer)):
if (turret.y == y):
if (player.direction == Direction.UP):
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
return False
elif (player.direction == Direction.DOWN):
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
else:
return False
if (turret.x == x):
if (player.direction == Direction.LEFT):
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
return False
elif (player.direction == Direction.RIGHT):
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
else:
return False
# turret about to fire next turn
elif (turret_will_fire(turret, turn + self.timer)):
if (turret.y == y):
if (player.direction == Direction.UP):
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
elif (player.direction == Direction.DOWN):
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
return False
else:
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
if (turret.x == x):
if (player.direction == Direction.LEFT):
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
elif (player.direction == Direction.RIGHT):
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
return False
else:
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
# dodge bullets
bullets = gameboard.bullets
for bullet in bullets:
if (bullet.y == y and get_x(gameboard.width, bullet.x + turn) - x > -3 and get_x(gameboard.width, bullet.x + turn) - x < 0):
if (bullet.direction == Direction.RIGHT):
print("bullet coming from the left!")
if (player.direction == Direction.UP):
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
if (player.direction == Direction.DOWN):
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
return False
else:
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
if (bullet.y == y and get_x(gameboard.width, bullet.x - turn) - x < 3 and get_x(gameboard.width, bullet.x - turn) - x > 0):
if (bullet.direction == Direction.LEFT):
print("bullet coming from the right!")
if (player.direction == Direction.UP):
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
if (player.direction == Direction.DOWN):
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
return False
else:
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
if (bullet.x == x and get_y(gameboard.height, bullet.y - turn) - y < 3 and get_y(gameboard.height, bullet.y - turn) - y > 0):
if (bullet.direction == Direction.UP):
print("bullet coming from below!")
if (player.direction == Direction.LEFT):
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
if (player.direction == Direction.RIGHT):
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
return False
else:
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
if (bullet.x == x and get_y(gameboard.height, bullet.y + turn) - y > -3 and get_y(gameboard.height, bullet.y + turn) - y < 0):
if (bullet.direction == Direction.DOWN):
print("bullet coming from above!")
if (player.direction == Direction.LEFT):
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
if (player.direction == Direction.RIGHT):
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
return False
else:
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
# keep distance from opponent
if (opponent.y == player.y and (abs(opponent.x - player.x) < self.PARNOID_LEVEL or (gameboard.width - abs(opponent.x - player.x)) < self.PARNOID_LEVEL)):
if (player.direction == Direction.UP):
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
if (player.direction == Direction.DOWN):
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
return False
else:
up = defensive_action(self, gameboard, x, get_y(gameboard.height, y - 1), turn, player, opponent)
if (up and Direction.UP in directions):
return Direction.UP
down = defensive_action(self, gameboard, x, get_y(gameboard.height, y + 1), turn, player, opponent)
if (down and Direction.DOWN in directions):
return Direction.DOWN
return False
elif (opponent.x == player.x and (abs(opponent.y - player.y) < self.PARNOID_LEVEL or (gameboard.height - abs(opponent.y - player.y)) < self.PARNOID_LEVEL)):
if (player.direction == Direction.LEFT):
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
if (player.direction == Direction.RIGHT):
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
return False
else:
left = defensive_action(self, gameboard, get_x(gameboard.width, x - 1), y, turn, player, opponent)
if (left and Direction.LEFT in directions):
return Direction.LEFT
right = defensive_action(self, gameboard, get_x(gameboard.width, x + 1), y, turn, player, opponent)
if (right and Direction.RIGHT in directions):
return Direction.RIGHT
return False
# TO DO: implement this section so PeaceBot actually moves on its own
# if (self.count == 4):
# self.count = 0
# # if no defensive maneuvres required, go fuck shit up
# right = not is_hit(self, gameboard, get_x(gameboard.width, x + 1), y, turn - 1)
# if (right and Direction.RIGHT in directions):
# return Direction.RIGHT
# down = not is_hit(self, gameboard, x, get_y(gameboard.height, y + 1), turn - 1)
# if (down and Direction.DOWN in directions):
# return Direction.DOWN
# left = not is_hit(self, gameboard, get_x(gameboard.width, x - 1), y, turn - 1)
# if (left and Direction.LEFT in directions):
# return Direction.LEFT
# up = not is_hit(self, gameboard, x, get_y(gameboard.height, y - 1), turn - 1)
# if (up and Direction.UP in directions):
# return Direction.UP
# if no move is required
if (turn == 1):
return "Safe"
# went through a deep iterative check and there is no danger
else:
return True
# returns True if player will be hit at (x, y) at a particular turn
def is_hit(self, gameboard, x, y, turn):
turrets = find_lethal_turrets(self, x, y)
for turret in turrets:
if (turret_will_fire(turret, self.timer + turn)):
return True
for bullet in gameboard.bullets:
if (bullet.x == x and bullet.y == y):
return True
return False
# returns True if turret is designated to fire at the given turn
def turret_will_fire(turret, turn):
cycle = turret.schedule[2]
fire = turret.schedule[0]
if (turn % cycle < fire):
return True
else:
return False
# returns an array of turrets in range of player at turn
def find_lethal_turrets(self, x, y):
lethal_turrets = []
for turret in self.turrets:
if ([x,y] in turret.killzone):
lethal_turrets.append(turret)
return lethal_turrets
# returns a decision for which direction the player should turn
def decide_direction(map, tile_to_move, current_direction):
if (tile_to_move == current_direction):
return "FORWARD"
else:
return map[tile_to_move]
# returns an array containing the kill zone of a turret when it fires
def turret_kill_zone(x, y, width, height):
killzone = []
temp_x = x - 4
for i in range(-4, 5):
if (temp_x != 0):
killzone.append([get_x(width, temp_x), y])
temp_x = temp_x + 1
temp_y = y - 4
for i in range(-4, 5):
if (temp_y != 0):
killzone.append([x, get_y(height, temp_y)])
temp_y = temp_y + 1
return killzone
# returns the new x-coordinate after a move which compensates for wrap effect
def get_x(width, next_move):
if (next_move > width - 1):
return next_move - width
elif (next_move < 0):
return width + next_move
else:
return next_move
# returns the new y-coordinate after a move which compensates for wrap effect
def get_y(height, next_move):
if (next_move > height - 1):
return next_move - height
elif (next_move < 0):
return height + next_move
else:
return next_move
# returns array with all possible moves
def possible_moves(self, gameboard, x, y):
moves = []
if (not gameboard.is_wall_at_tile(get_x(gameboard.width, x + 1), y) and not gameboard.turret_at_tile[get_x(gameboard.width, x + 1)][y]):
moves.append(Direction.RIGHT)
if (not gameboard.is_wall_at_tile(get_x(gameboard.width, x - 1), y) and not gameboard.turret_at_tile[get_x(gameboard.width, x - 1)][y]):
moves.append(Direction.LEFT)
if (not gameboard.is_wall_at_tile(x, get_y(gameboard.height, y - 1)) and not gameboard.turret_at_tile[x][get_y(gameboard.height, y - 1)]):
moves.append(Direction.UP)
if (not gameboard.is_wall_at_tile(x, get_y(gameboard.height, y + 1)) and not gameboard.turret_at_tile[x][get_y(gameboard.height, y + 1)]):
moves.append(Direction.DOWN)
return moves