-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMyBot.py
97 lines (74 loc) · 3.52 KB
/
MyBot.py
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
from networking import *
import os
import sys
import numpy as np
VISIBLE_DISTANCE = 4
input_dim = 4 * (2 * VISIBLE_DISTANCE + 1) * (2 * VISIBLE_DISTANCE + 1)
myID, gameMap = getInit()
game_map = gameMap
with open(os.devnull, 'w') as sys.stderr:
from keras.models import load_model
model = load_model('model.h5')
model.predict(np.random.randn(1, input_dim)).shape # make sure model is compiled during init
def stack_to_input(stack, position):
return np.take(np.take(stack,
np.arange(-VISIBLE_DISTANCE, VISIBLE_DISTANCE + 1) + position[0], axis=1, mode='wrap'),
np.arange(-VISIBLE_DISTANCE, VISIBLE_DISTANCE + 1) + position[1], axis=2, mode='wrap').flatten()
def frame_to_stack(frame):
game_map = np.array([[(x.owner, x.production, x.strength) for x in row] for row in frame.contents])
return np.array([(game_map[:, :, 0] == myID), # 0 : owner is me
((game_map[:, :, 0] != 0) & (game_map[:, :, 0] != myID)), # 1 : owner is enemy
game_map[:, :, 1] / 20, # 2 : production
game_map[:, :, 2] / 255, # 3 : strength
]).astype(np.float32)
def find_nearest_enemy_direction(square):
direction = NORTH
max_distance = min(game_map.width, game_map.height) / 2
for d in (NORTH, EAST, SOUTH, WEST):
distance = 0
current = square
while current.owner == myID and distance < max_distance:
distance += 1
current = game_map.get_target(current, d)
if distance < max_distance:
direction = d
max_distance = distance
return direction
def heuristic(square):
if square.owner == 0 and square.strength > 0:
return square.production / square.strength
else:
# return total potential damage caused by overkill when attacking this square
return sum(neighbor.strength for neighbor in game_map.neighbors(square) if neighbor.owner not in (0, myID))
# Maximum 1 second
def get_move(square):
target, direction = max(((neighbor, direction) for direction, neighbor in enumerate(game_map.neighbors(square))
if neighbor.owner != myID), default=(None, None), key=lambda t: heuristic(t[0]))
if target is not None and target.strength < square.strength:
return Move(square, direction)
return Move(square, find_nearest_enemy_direction(square))
# elif square.strength < square.production * 5:
# return Move(square, STILL)
#
# border = any(neighbor.owner != myID for neighbor in game_map.neighbors(square))
# if not border:
# return Move(square, find_nearest_enemy_direction(square))
#
# # Wait till strong enough to attack
# return Move(square, STILL)
sendInit('brianvanleeuwen')
while True:
stack = frame_to_stack(getFrame())
positions = np.transpose(np.nonzero(stack[0]))
output = model.predict(np.array([stack_to_input(stack, p) for p in positions]))
# Manual output corrections to avoid obviously bad moves
moves_output = []
for i in range(len(positions)):
try:
if gameMap.contents[positions[i][1]][positions[i][0]].production >= 255:
moves_output.append(get_move(gameMap.contents[positions[i][1]][positions[i][0]]))
else:
moves_output.append(Move(Location(positions[i][1], positions[i][0]), output[i].argmax()))
except:
moves_output.append(Move(Location(positions[i][1], positions[i][0]), output[i].argmax()))
sendFrame(moves_output)