-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeep_orange.py
234 lines (183 loc) · 6.66 KB
/
deep_orange.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
'''
Smart Tree Class AGENT
What this agent does, is:
1. Looks for a block to explode
2. Finds the path toward that block
3. When reached, places a expl
4. Runs away from it
5. Waits till it explodes
6. Repeats
This is a good example if you want to use simple board search in
your agent. It uses the search twice. Once to find a block
and once to find somewhere safe to hideaway
It still needs lots of improvement
'''
import time
import random
import queue
MOVE_DIC = {
"none":0,
"left":1,
"right":2,
"up":3,
"down":4,
"bomb":5
}
class agent:
def __init__(self, player_num, env):
self.name = "deep orange"
self.player_num = player_num
self.env = env
self.reservedMoves = []
def give_next_move(self, solid_state):
'''
This method is called each time the player needs to choose an
action
solid_state: is a dictionary containing all the information about the board
'''
action = MOVE_DIC["none"] # just in case
self.board = solid_state["board"]
self.done = solid_state["done"]
self.bombs = solid_state["bombs"]
self.turn = solid_state["turn"]
self.player = solid_state["players"][self.player_num-1]
(x,y) = self.player.position
if (self.reservedMoves): #if we have already decided on what moves to play
return self.reservedMoves.pop()
tiles_in_range = self.get_tiles_in_range(solid_state) # dangerous tiles
(x, y) = self.player.position
if (self.player.position in tiles_in_range) or (self.board[x][y] >= 6) :#run away then
self.reservedMoves = find_path_to_safe_cell(self,Node_cell(self.player.position, None, None), tiles_in_range, [], self.board)
print(self.reservedMoves)
if (not self.reservedMoves):
print("I could not find an escape so I stand still")
#sys.exit()
action = (MOVE_DIC['none'])
else:
action = self.reservedMoves.pop()
else:
if (self.player.num_bombs < 1): #without this bot can jumpback into its explosion
return MOVE_DIC["none"]
current_node = Node_cell(self.player.position, None, None)
for child in current_node.generate_children():
if check_block_child(child.position,self.board):
action = MOVE_DIC["bomb"]
return action
#else find a place to do it
self.reservedMoves = find_path_next_to_block(self,Node_cell(self.player.position, None, None), tiles_in_range, [], self.board)
if (not self.reservedMoves):
print("I could not find a good block")
action = (MOVE_DIC['none'])
else:
action = self.reservedMoves.pop()
return action
def get_tiles_in_range(self, solid_state):
'''
get surrounding tiles impacted near bomb
'''
bombs = solid_state["bombs"]
all_tiles_in_range = []
for bo in bombs:
all_tiles_in_range.append(bo.tiles_in_range)
return all_tiles_in_range
class Node_cell:
def __init__(self, curr_pos, parent,parent_move):
self.position = curr_pos
self.parent_move = parent_move
self.children = [] # will be populated soon
self.parent = parent
#for child in possible_children:
#if check_legal_child(child.position, board) and child.position not in already_visited_cells:
#self.children.append(child)
#children are now populated for legal position.
def generate_children(self):
curr_pos = self.position
tile_up = (curr_pos[0]-1,curr_pos[1])
child_up = Node_cell(tile_up, self, MOVE_DIC["up"])
tile_down = (curr_pos[0]+1,curr_pos[1])
child_down = Node_cell(tile_down, self, MOVE_DIC["down"])
tile_left = (curr_pos[0],curr_pos[1]-1)
child_left = Node_cell(tile_left, self, MOVE_DIC["left"])
tile_right = (curr_pos[0],curr_pos[1]+1)
child_right = Node_cell(tile_right, self, MOVE_DIC["right"])
return [child_up, child_down, child_left, child_right]
def check_legal_child( p_child, already_visited_cells,board):
'''
p_child is a tuple (x,y)
'''
(x, y) = p_child
if x < 0 or x >= len(board) or y < 0 or y >= len(board[0]):
return False # if the child cell is out of range return false
elif board[x][y] != 5 and board[x][y] != 0:
return False # if it is anything but a b or empty cell
elif p_child in already_visited_cells: # child has been already generated
return False
else:
return True
def check_block_child( p_child,board):
'''
returns true if the position has a block
p_child is a tuple (x,y)
'''
(x, y) = p_child
if x < 0 or x >= len(board) or y < 0 or y >= len(board[0]):
return False # if the child cell is out of range return false
elif board[x][y] == 3:
return True # if it is anything but a b or empty cell
else:
return False
def find_path_to_safe_cell(self,starting_node, unsafe_cells, already_visited_cells, board):
answer = False
already_visited_cells.append(starting_node.position)
bfs_q = queue.Queue()
for ch in starting_node.generate_children():
if( check_legal_child(ch.position, already_visited_cells,board)):
bfs_q.put(ch)
safeNode = False
while(not bfs_q.empty()):
current_node = bfs_q.get()
if ( current_node.position not in unsafe_cells[0]):
safeNode = current_node
break
else:
for child in current_node.generate_children():
is_it_valid = check_legal_child(child.position, already_visited_cells,board)
already_visited_cells.append(child.position)
#print(is_it_valid)
if ( is_it_valid):
bfs_q.put(child)
if ( safeNode):
path_to_safe_cell = []
tempNode = safeNode
while(tempNode.parent_move):
path_to_safe_cell.append(tempNode.parent_move)
tempNode = tempNode.parent
return path_to_safe_cell
return False #if queue gets empty it means there is no solution
def find_path_next_to_block(self,starting_node, unsafe_cells, already_visited_cells, board):
#print("looking at cell:",starting_node.position )
answer = False
bfs_q = queue.Queue()
bfs_q.put(starting_node)
goalNode = False
while(not bfs_q.empty() and not goalNode):
current_node = bfs_q.get()
if ( current_node.position not in unsafe_cells):
for child in current_node.generate_children():
if check_block_child(child.position,board):
goalNode = current_node
for child in current_node.generate_children():
is_it_valid = check_legal_child(child.position, already_visited_cells,board)
already_visited_cells.append(child.position)
print(is_it_valid)
if ( is_it_valid):
bfs_q.put(child)
#print("bfs_q.qsize()",bfs_q.qsize())
if ( goalNode):
path_to_safe_cell = []
tempNode = goalNode
while(tempNode.parent_move):
path_to_safe_cell.append(tempNode.parent_move)
tempNode = tempNode.parent
return path_to_safe_cell
return False #if queue gets empty it means there is no solution