-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsnake_game.py
70 lines (56 loc) · 1.94 KB
/
snake_game.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
from collections import namedtuple
import numpy as np
Fruit = namedtuple('Fruit', ['x', 'y'])
def snake_game(width=15, height=10, snake_length=3):
assert width - 2 > snake_length
possible_actions = ((0, 1), (0, -1), (1, 0), (-1, 0), (0, 0))
forbidden_actions = {
(0, 1): (0, -1),
(0, -1): (0, 1),
(1, 0): (-1, 0),
(-1, 0): (1, 0)
}
action = (-1, 0)
prev_action = action
head_x = width // 2 - snake_length // 2
snake = [(x, height//2) for x in xrange(head_x, head_x+snake_length)]
grow = False
screen = np.zeros((height, width))
screen[[0, -1]] = 1
screen[:, [0, -1]] = 1
boarders_sum = screen.sum()
for seg in snake:
screen[seg[1], seg[0]] = 1
fruit = getFruit(screen, width, height)
screen[fruit.y, fruit.x] = .5
while True:
game_end = (len(snake) > len(set(snake)) or
screen.sum() < boarders_sum + len(snake))
reward = -1 * game_end
if screen[fruit.y, fruit.x] > .5:
grow = True
reward = len(snake)
fruit = getFruit(screen, width, height)
screen[fruit.y, fruit.x] = .5
action = yield screen, reward
assert action in possible_actions, "Invalid action"
if game_end:
break
if sum(action) == 0 or forbidden_actions[action] == prev_action:
action = prev_action
else:
prev_action = action
new_seg = (snake[0][0] + action[0], snake[0][1] + action[1])
screen[new_seg[1], new_seg[0]] = 1
snake.insert(0, new_seg)
if grow:
grow = False
else:
screen[snake[-1][1], snake[-1][0]] = 0
snake.pop()
def getFruit(screen, width, height):
while True:
rand_pt = [np.random.randint(1, width-1), np.random.randint(1, height-1)]
fruit = Fruit(*rand_pt)
if screen[fruit.y, fruit.x] < 1:
return fruit