Home
See competition on link.
See some games my bot won by colliding (one, two), starving (one) and blocking (one, two, three). It got to 7th place at the overall leaderboard: link.
See my source code on github (source, commits).
data = bottle.request.json
board_data = data['board']
self.height = board_data['height']
self.width = board_data['width']
self.board = [
[0 for _ in range(self.width)]
for _ in range(self.height)]
snakes = board_data['snakes']
for snake in snakes:
for part in snake['body'][:-1]:
self.board[part['y']][part['x']] = 1
if exclude_heads_of_other_snakes:
if (snake['id'] != self.id
and len(snake['body']) >= len(body)):
head = snake['body'][0]
for (_, nx, ny) in self.adjacent(
head['x'], head['y']):
self.board[ny][nx] = 1
DIRECTIONS = ['up', 'down', 'left', 'right']
DELTAS = {
'up' : { 'x': 0, 'y': -1, },
'down' : { 'x': 0, 'y': +1, },
'left' : { 'x': -1, 'y': 0, },
'right': { 'x': +1, 'y': 0, },
}
def adjacent(self, x, y):
res = []
for direction in DIRECTIONS:
delta = DELTAS[direction]
nx = x + delta['x']
ny = y + delta['y']
if (nx >= 0 and nx < self.width and
ny >= 0 and ny < self.height and
self.board[ny][nx] == 0):
res.append((direction, nx, ny))
return res
NO_DISTANCE = -1
NO_MOVE = '?'
def distances(self, x, y):
res = [
[NO_DISTANCE for _ in range(self.width)]
for _ in range(self.height)]
move = [
[NO_MOVE for _ in range(self.width)]
for _ in range(self.height)]
move_debug = [
[NO_MOVE for _ in range(self.width)]
for _ in range(self.height)]
# Flood fill.
res[y][x] = 0
deque = collections.deque()
for (m, nx, ny) in self.adjacent(x, y):
deque.append((nx, ny, 1, m))
while deque:
(x, y, d, m) = deque.popleft()
if res[y][x] != NO_DISTANCE:
continue
res[y][x] = d
move[y][x] = m
move_debug[y][x] = m[0]
for (_, nx, ny) in self.adjacent(x, y):
if res[ny][nx] == NO_DISTANCE:
deque.append((nx, ny, d + 1, m))
def move_to_pos(self, x, y, moves):
res = moves[y][x]
print (
'move_to_pos', 'x', x, 'y', y,
'res', res)
return res
def move_to_max(self, distances, moves):
maxdist = -1
res = NO_MOVE
for x in range(self.width):
for y in range(self.height):
if distances[y][x] > maxdist:
maxdist = distances[y][x]
res = moves[y][x]
print (
'move_to_max', 'maxdist', maxdist,
'res', res)
return res
def move_to_food(
self, distances, moves, tail_distances):
res = NO_MOVE
mindist = sys.maxint
for food in self.food:
x = food['x']
y = food['y']
dist = distances[y][x]
if (dist != NO_DISTANCE and
dist < mindist and (
(tail_distances[y][x] != NO_DISTANCE
and tail_distances[y][x] >= 2)
or self.health <= 25)):
mindist = dist
res = moves[y][x]
print (
'move_to_food', 'mindist', mindist,
'res', res)
return res
def run(data, exclude_heads_of_other_snakes):
game = Game(
data, exclude_heads_of_other_snakes)
distances, moves, moves_debug = (
game.distances(
game.head['x'], game.head['y']))
tail_distances, _, _ = game.distances(
game.tail['x'], game.tail['y'])
tails = (
[(_, game.tail['x'], game.tail['y'])] +
game.adjacent(
game.tail['x'], game.tail['y']))
for (_, x, y) in tails:
direction = game.move_to_pos(x, y, moves)
if direction != NO_MOVE:
break
if direction == NO_MOVE:
direction = game.move_to_max(
distances, moves)
if game.health <= get_min_health(
game.name):
food_direction = game.move_to_food(
distances, moves, tail_distances)
if food_direction != NO_MOVE:
direction = food_direction
return direction
@bottle.post('/move')
def move():
data = bottle.request.json
direction = run(
data, exclude_heads_of_other_snakes=True)
if direction == NO_MOVE:
direction = run(
data,
exclude_heads_of_other_snakes=False)
return move_response(direction)