-
Notifications
You must be signed in to change notification settings - Fork 0
/
snake_AI.py
181 lines (143 loc) · 5.6 KB
/
snake_AI.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
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
import random
import curses
s = curses.initscr()
curses.curs_set(0)
sh, sw = s.getmaxyx()
w = curses.newwin(sh, sw, 0, 0)
w.keypad(1)
w.timeout(20)
snk_x = int(sw/4)
snk_y = int(sh/2)
snake = [
[snk_y, snk_x],
[snk_y, snk_x-1],
[snk_y, snk_x-2]
]
food = [int(sh/2), int(sw/2)]
w.addch(int(food[0]), int(food[1]), "F")
# return the same head if no wall around
# return the new position crossing the wall on the right otherwise
def cross_wall(snake_head):
if snake_head[1]>=sw-2: # only right border because snake never goes left
# touching right so appears left (same height)
return [snake_head[0], 2]
else:
return snake_head
# Never go left
# always up (to the top) or down (to the bottom)
# if too close to tail
# move toward center of screen or food otherwise
def AI(snake):
X_snake = snake[0][0]
Y_snake = snake[0][1]
# keep going right if no snake tail at least 2 y-axis points further away
# and if food also away
# gather all Y to check if current Y further away for Ys
Y_snakes = []
for pos in snake:
Y_snakes.append(pos[1])
# set the current Y to what it would be if 1/2/3 y-axis points more
Y_potential1 = Y_snake + 1
Y_potential2 = Y_snake + 2
Y_potential3 = Y_snake + 3
# in case the Y_potential are crossing the wall
if Y_potential3 >= sw-3 and Y_potential2 < sw-3 and Y_potential1 < sw-3:
Y_potential3 = 3
elif Y_potential3 >= sw-3 and Y_potential2 >= sw-3 and Y_potential1 < sw-3:
Y_potential2 = 3
Y_potential3 = 4
elif Y_potential3 >= sw-3 and Y_potential1 >= sw-3 and Y_potential2 >= sw-3:
Y_potential1 = 3
Y_potential2 = 4
Y_potential3 = 5
# if food further away and no tail within the next 3 y-axis points
if Y_snake != food[1] and Y_potential1 not in Y_snakes and Y_potential2 not in Y_snakes and Y_potential3 not in Y_snakes:
# move snake toward middle of screen if not already there
# move up or down toward center (if possible) otherwise
if X_snake in [int(sh/2 -1), int(sh/2), int(sh/2 +1)]:
snake_new_head = [X_snake, Y_snake + 1]
elif X_snake < sh/2:
snake_new_head = [X_snake + 1, Y_snake]
if snake_new_head in snake:
snake_new_head = [X_snake, Y_snake + 1]
elif X_snake > sh/2:
snake_new_head = [X_snake -1, Y_snake]
if snake_new_head in snake:
snake_new_head = [X_snake, Y_snake + 1]
# if snake already on same y-axis
elif Y_snake == food[1]:
# move toward the food if possible, move right otherwise
if food[0] > X_snake:
snake_new_head = [X_snake + 1, Y_snake]
if snake_new_head in snake[:]:
snake_new_head = [X_snake, Y_snake + 1]
elif food[0] < X_snake:
snake_new_head = [X_snake - 1, Y_snake]
if snake_new_head in snake[:]:
snake_new_head = [X_snake, Y_snake + 1]
# if food further away but tail is close (within the next 3 y-axis points)
else:
# snake was going up
if X_snake == snake[1][0] + 1:
# if wall coming, move right
if X_snake == sh-3 and snake[1][1] == Y_snake:
snake_new_head = [X_snake, Y_snake + 1]
# if wall coming, and already moved right, go down
elif X_snake == sh-3 and snake[1][1] == Y_snake + 1:
snake_new_head = [X_snake - 1, Y_snake]
# if no wall coming, keep going up
else:
snake_new_head = [X_snake + 1, Y_snake]
if snake_new_head in snake:
snake_new_head = [X_snake, Y_snake + 1]
# snake was going down
elif X_snake == snake[1][0] - 1:
# if wall coming, move right
if X_snake == 3 and snake[1][1] == Y_snake:
snake_new_head = [X_snake, Y_snake + 1]
# if wall coming, and already moved right, go up
elif X_snake == 3 and snake[1][1] == Y_snake + 1:
snake_new_head = [X_snake + 1, Y_snake]
# if no wall coming, keep going down
else:
snake_new_head = [X_snake - 1, Y_snake]
if snake_new_head in snake:
snake_new_head = [X_snake, Y_snake + 1]
# snake was moving right
else:
# snake at the bottom so move up
if X_snake == 3:
snake_new_head = [X_snake + 1, Y_snake]
# snake move down (could have been up)
else:
snake_new_head = [X_snake - 1, Y_snake]
return snake_new_head
key = curses.KEY_RIGHT
while True:
next_key = w.getch()
key = key if next_key == -1 else next_key
# Check if snake is touching wall or itself
if snake[0][0] in [0, sh] or snake[0][1] in [0, sw] or snake[0] in snake[1:]:
curses.endwin()
print("Success!")
# AI chooses the next move
snake_new_head = AI(snake)
# snake cross the right wall if necessary
snake_new_head = cross_wall(snake_new_head)
# Make the move
snake.insert(0, snake_new_head)
if snake[0] == food:
food = None
while food is None:
nf = [
random.randint(3, sh-3),
random.randint(3, sw-3)
]
food = nf if nf not in snake else None
w.addch(food[0], food[1], "F")
else:
tail = snake.pop()
w.addch(int(tail[0]), int(tail[1]), ' ')
for pos in snake[1:]:
w.addch(pos[0], pos[1], 'O')
w.addch(int(snake[0][0]), int(snake[0][1]), '0')