forked from monkey-music-challenge/python-starter-kit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ai.py
265 lines (228 loc) · 10 KB
/
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
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
import random
score = None
buffs = None
inventory = None
current_level_layout = None
picked_up_music_items = None
current_position_of_monkey = None
remaining_turns = None
inventory_is_full = False
def move(current_game_state):
global current_position_of_monkey
global current_level_layout
global inventory_is_full
global remaining_turns
global inventory_size
global inventory
global buffs
global score
current_position_of_monkey = tuple(current_game_state['position'])
remaining_turns = current_game_state['remainingTurns']
inventory_size = current_game_state['inventorySize']
current_level_layout = current_game_state['layout']
inventory = current_game_state['inventory']
buffs = current_game_state['buffs']
score = current_game_state['score']
inventory_is_full =len(inventory) >= inventory_size
# Map the game board and get the distance to everything on the map
game_board_map = create_map_from(current_position_of_monkey, None)
# print 'game_board_map: ' + str(game_board_map)
## Decide what to do, wheter it is to go to the user och collect something
# Strategy:
# If no points - get a point then spank the monkey till inventory is full
# when inventory is full, get more points
# When number of moves left is ecual to distance to closest user, go to hen
## Dictande to user:
closest_user = find_destination(["user"], game_board_map)
print 'closest_user: ' + str(closest_user)
if closest_user:
dictance_to_user = closest_user[2]
else:
dictance_to_user = 1000
if "banana" in inventory and "speedy" not in buffs:
return {"command": "use", "item": "banana"}
# Real game strategy here:
if (inventory_is_full or (dictance_to_user < 3 and len(inventory) >= 1)
or (remaining_turns + 2 >= dictance_to_user and len(inventory) >= 1)):
#inventory full, close to user or soon end of game
destination = find_destination(["user"], game_board_map)
elif score <= 0: # if score is less than 1, get some!
if len(inventory) <= 0: # Go pick up something
destination = find_destination(["song", "album", "playlist", "banana", "trap"],
game_board_map)
else: # then return it to user
destination = find_destination(["user"], game_board_map)
else: #TODO: Spank the monkey
destination = find_destination(["monkey"], game_board_map)
# Create the path to the destination
if destination is not None:
astar_array = create_map_from(destination, current_position_of_monkey)
else:
print 'Error: destination is: ' + str(destination)
print ' returning: idle'
return {'command': 'idle'}
if ("trap" in inventory and dictance_to_user <= 1):
return {"command": "use", "item": "trap"}
move = get_move(astar_array, current_position_of_monkey)
print "get move returned: " + str(move)
print 'destination: ' + str(destination)
print 'current_position_of_monkey: ' + str(current_position_of_monkey)
#if move is not None evaluate else return idle
#if speedy and move_2 is not None return Directions command
#else return direction with move
if move is not None:
direction = get_one_direction(move, current_position_of_monkey)
if 'speedy' in buffs:
move_2 = get_move(astar_array, move)
if move_2 is not None:
direction_2 = get_one_direction(move_2, move)
print 'Directions: ' + str(direction) + ' and ' + str(direction_2)
return {'command': 'move',
'directions': [direction, direction_2]}
else:
return {'command': 'move',
'direction': direction}
else:
return {'command': 'move',
'direction': direction}
else:
return {'command': 'idle'}
def find_destination(search_for, game_board_map):
possible_destinations = []
for element in game_board_map:
#print "element:" + str(element) + " looking for: " + str(search_for)
for destination in search_for:
if element[3] == destination:
possible_destinations.append(element)
if len(possible_destinations) > 0:
if search_for[0] == 'monkey':
destination = max(possible_destinations,
key=lambda destination: destination[2])
else:
destination = min(possible_destinations,
key=lambda destination: destination[2])
else:
return None
return destination
def print_game_board():
print current_position_of_monkey
print inventory
for row in current_level_layout:
print row
def create_map_from(coordinate, stop_at):
astar_array = []
destination_coordinates = (coordinate[0], coordinate[1])
astar_array.append(destination_coordinates + (0,
get_value_from_coordinate(destination_coordinates)))
for element in astar_array:
astar_array = add_coordinate(element, stop_at, element[2], astar_array)
return astar_array
def add_coordinate(coordinate, stop_at, current_counter, astar_array):
coordinates_around = get_coordinates_around((coordinate[0], coordinate[1]),
['wall', 'closed-door'])
# coordinates_around have +1 in dictance
counter = current_counter + 1
for c in coordinates_around:
#Check if c is a tunnel, if so set c to the tunnel exit
value = get_value_from_coordinate(c)
if (value.startswith("tunnel")):
# find other entrance
tunnels = find_elements_on_map(current_level_layout,
value)
for tunnel in tunnels:
if not is_coordinates_equal(tunnel, c):
c = tunnel
break
if stop_at is not None:
if (c[0] == current_position_of_monkey[0] and
c[1] == current_position_of_monkey[1]):
1 + 1
else:
astar_array = append_element_to_astar_array(c, counter,
astar_array)
else:
astar_array = append_element_to_astar_array(c, counter,
astar_array)
return astar_array
# careful when changing, map_game_board() and create_astar_array() use this
def append_element_to_astar_array(coordinate, counter, current_astar_array):
existingElements = [element for element in current_astar_array if
element[0] == coordinate[0] and element[1] ==
coordinate[1]]
# print str(existingElements)
if len(existingElements) > 0:
for element in existingElements:
if element[2] >= counter:
#substitute for the new one
current_astar_array.remove(element)
current_astar_array.append(coordinate + (counter,
get_value_from_coordinate(coordinate)))
else:
current_astar_array.append(coordinate + (counter,
get_value_from_coordinate(coordinate)))
return current_astar_array
def get_move(astar_array, from_coordinate):
possible_moves_list = possible_moves(astar_array, from_coordinate)
if len(possible_moves_list) > 0:
move = min(possible_moves_list, key=lambda move: move[2])
return move
else:
return None
def get_one_direction(move, from_coordinate):
# import pdb; pdb.set_trace()
print "from_coordinate: " + str(from_coordinate) + " type: " + str(type(from_coordinate))
print "move: " + str(move) + " type: " + str(type(move))
if move[0] == from_coordinate[0]:
if from_coordinate[1] - move[1] > 0:
return "left"
else:
return "right"
elif from_coordinate[0] - move[0] > 0:
return "up"
else:
return "down"
def possible_moves(astar_array, from_coordinate):
# print 'astar_array: ' + str(astar_array)
goalcoordinate = astar_array[0][0:2]
print 'goalcoordinate: ' + str(goalcoordinate)
going_to_user = get_value_from_coordinate(goalcoordinate) == "user"
if inventory_is_full:
avoid = ['wall', 'closed-door', 'song', 'album', 'playlist', 'banana', 'trap']
else:
avoid = ['wall', 'closed-door', 'user']
if going_to_user:
avoid.remove('user')
possible_moves = [move for move in astar_array if move_is_possible(move, avoid, from_coordinate)]
print "possible_moves: " + str(possible_moves)
return possible_moves
def move_is_possible(move, avoid, from_coordinate):
coordinates_around = get_coordinates_around(from_coordinate, avoid)
for c in coordinates_around:
if c[0] == move[0] and c[1] == move[1]:
return True
return False
def get_coordinates_around(coordinate, avoid):
# print "get coordinates for: " + str(coordinate)
coordinates_around = [(coordinate[0] - 1, coordinate[1]),
(coordinate[0] + 1, coordinate[1]),
(coordinate[0], coordinate[1] - 1),
(coordinate[0], coordinate[1] + 1)]
# print "surrounding coordinates: " + str(coordinates_around)
filtered_list = [c for c in coordinates_around if c[0] >= 0 and
c[0] < len(current_level_layout) and c[1] >= 0 and
c[1] < len(current_level_layout[0]) and
get_value_from_coordinate(c) not in avoid]
# print filtered_list
return filtered_list
def find_elements_on_map(game_board, looking_for):
coordinates = []
for i in range(len(game_board)):
for j in range(len(game_board[0])):
value = get_value_from_coordinate([i, j])
if value == looking_for:
coordinates.append((i, j))
return coordinates
def get_value_from_coordinate(coordinate):
return current_level_layout[coordinate[0]][coordinate[1]]
def is_coordinates_equal(coordinate1, coordinate2):
return coordinate1[0] == coordinate2[0] and coordinate1[1] == coordinate2[1]