-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenv.py
168 lines (157 loc) · 4.43 KB
/
env.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
import logging
import numpy as np
def resolve_env(name):
envs = {
"Maze": Maze
}
return envs[name]
test_cases = {
"Maze": [
[[3,0,0,0],
[1,0,0,1],
[1,1,0,1],
[1,1,0,4]],
[[3,0,0,0,0,0,0,0,1,1],
[1,0,0,0,1,0,1,0,1,1],
[1,1,1,0,1,0,1,0,1,1],
[1,1,1,0,0,0,0,0,1,1],
[1,1,0,1,1,0,0,1,1,1],
[1,1,0,1,1,0,0,0,1,1],
[1,0,0,0,0,0,1,0,1,1],
[1,1,1,0,1,0,1,0,1,1],
[1,1,1,0,0,0,4,0,1,1],
[1,1,1,1,1,1,0,0,1,1]]
]
}
class Maze():
def __init__(self, matrix):
self.walls = []
self.empty = []
self.start = (0,0)
self.target = (0,0)
self.boundaries = (len(matrix),len(matrix[0]))
self.map = matrix
for i in range(len(matrix)):
for j in range(len(matrix[0])):
if matrix[i][j] == 3:
self.start = (i, j)
if matrix[i][j] == 4:
self.target = (i, j)
if matrix[i][j] == 1:
self.walls.append((i, j))
else:
self.empty.append((i, j))
self.current = self.start
logging.info("Maze: Target at {}".format(self.target))
logging.info(np.asmatrix(self.map))
def solution_exists(self):
"""
BFS to check if solution exists for the given maze.
Returns:
(bool): True if path from start to target exists, else False.
"""
print(np.asmatrix(self.map))
queue = [self.start]
visited = []
while queue:
x, y = queue.pop(0)
visited.append((x, y))
if self.map_location(x, y) == 4:
return True
for i in range(4):
next = self.next((x, y), i)
if not self.is_wall((x, y), i) and next not in visited:
queue.append(next)
return False
def reset(self):
"""
Reset current position to beginning.
"""
self.current = self.start
def direction_name(self, n):
"""
Map int directions to their corresponding strings for printing
Args:
n (int): Int corresponding to a direction.
Returns:
(string): String form of direction.
"""
if n == 0: return "^"
if n == 1: return "v"
if n == 2: return "<"
if n == 3: return ">"
def map_location(self, x, y):
"""
Given expected map location by human perception.
Args:
x (int): Row coordinate on map
y (int): Column coordinate on map
Returns:
(int): Item in map at the expected location
"""
return self.map[y][x]
def next(self, current_position, direction):
"""
Position reached if moved in direction from current_position
Args:
current_position (int tuple): x, y coordinates of a position
direction (int): Direction int
Returns:
(tuple): Destination coordinates after moving in direction from current_position
"""
if direction == 0:
y_next = current_position[1] - 1
if y_next < 0 or self.is_wall(current_position, 0):
y_next = current_position[1]
return (current_position[0], y_next)
if direction == 1:
y_next = current_position[1] + 1
if y_next >= self.boundaries[1] or self.is_wall(current_position, 1):
y_next = current_position[1]
return (current_position[0], y_next)
if direction == 2:
x_next = current_position[0] - 1
if x_next < 0 or self.is_wall(current_position, 2):
x_next = current_position[0]
return (x_next, current_position[1])
if direction == 3:
x_next = current_position[0] + 1
if x_next >= self.boundaries[0] or self.is_wall(current_position, 3):
x_next = current_position[0]
return (x_next, current_position[1])
def move(self, direction):
"""
Move current position coordinate in the given direction.
"""
past = self.current
self.current = self.next(self.current, direction)
return self.current != past
def is_wall(self, current_position, direction):
"""
Check if the object in direction from current_position is a wall
Args:
current_position (int tuple): x, y coordinates of a position
direction (int): Direction int
Returns:
(int): 1 if object in direction from current_position is a wall, else 0
"""
if direction == 0:
y_next = current_position[1] - 1
if y_next < 0 or self.map_location(current_position[0], y_next) == 1:
return 1
return 0
if direction == 1:
y_next = current_position[1] + 1
if y_next >= self.boundaries[1] or self.map_location(current_position[0], y_next) == 1:
return 1
return 0
if direction == 2:
x_next = current_position[0] - 1
if x_next < 0 or self.map_location(x_next, current_position[1]) == 1:
return 1
return 0
if direction == 3:
x_next = current_position[0] + 1
if x_next >= self.boundaries[0] or self.map_location(x_next, current_position[1]) == 1:
return 1
return 0