-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmaze.py
240 lines (181 loc) · 6.28 KB
/
maze.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
'''
Brian Orbegoso
July 25, 2016
Entry point: maze()
'''
import math
import itertools
from Node import Node
from BuildMaze import BuildMaze
def maze():
x = BuildMaze()
start = x.start
exit = x.exit
cost, master_path = AStar(start, exit, x.specialList)
tempCost = 0
acumulate_cost = 0
final_path = []
for index, node in enumerate(master_path):
if node is None:
tempStart = master_path[index - 1]
tempExit = master_path[index + 1]
tempStart.gValue = 0
tempExit.gValue = 0
tempExit.specialValue = 0
tempCost, tempPath = AStar(tempStart, tempExit, x.specialList)
final_path.append(tempPath[1:])
# Don't count the fee twice
tempCost -= tempStart.fee
# Don't count the same step twice
tempCost -= 1
acumulate_cost += tempCost
# Replace every occurence of None in the master_path with the backtracked path the Agent traveled
tempCount = 0
master_list = [[]]
for item in master_path:
if item is not None:
master_list[tempCount].append(item)
elif item is None:
tempCount += 1
master_list.append(list())
all_list = interleave(master_list, final_path)
all_list = list(itertools.chain.from_iterable(all_list))
# Append the exit that was left out in AStar previously
all_list.append(exit)
WriteReport(cost + acumulate_cost, len(all_list) - 1, all_list)
'''
AStar()
In: start: The starting Node for the Agent
exit: The exit Node for the Agent
specialList: The list of Nodes that have a fee or are a trap
Out: cost: The amount of steps taken plus the fees incurred. The total amount of money spent.
path: A list of the Nodes traveled by the Agent, excluding the exit Node.
'''
def AStar(start, exit, specialList):
closedList = []
openList = []
path = []
cost = 0
openList.append(start)
# Loop while openList is not empty
while openList:
currentNode = openList[0]
#currentitem = openList[0]
# Remove the first item from openList
openList.pop(0)
# Check if the Agent 'jumped' from the previous node to the current node
if closedList and not Neighbors(currentNode, closedList[-1]):
path.append(None)
path.append(currentNode)
cost += currentNode.fee
children = currentNode.GenerateChildren()
for child in children:
# Initialize all the children with their fees and specialValues
isinList, member = inSpecialList(child, specialList)
if isinList:
child.fee = member.fee
child.specialValue = member.specialValue
new_cost = currentNode.gValue + child.fee + 1
# Check if the child is the exit
if SameLocation(child, exit):
# Leave the exit out of the path for now
# path.append(child)
return cost + child.fee + 1, path
if inList(child, closedList):
continue
if inList(child, openList):
if currentNode.gValue > new_cost:
child.gValue = new_cost
child.fValue = f(child, exit, new_cost)
openList.insert(0, child)
else:
child.gValue = new_cost
# Not appended, current node's children would be a tiebreaker if same g-value as other nodes
child.fValue = f(child, exit, new_cost)
openList.insert(0, child)
cost += 1
closedList.append(currentNode)
# Sort the openList by each item's f-value in increasing order. Note: sorted() is a stable sort.
openList = sorted(openList, key=lambda k: k.fValue, reverse=False)
return _,_
'''
Heuristic functions
'''
def f(node, exit, cost):
return g(node) + h(node, exit)
# Number of nodes from current position to exit
def h(node, exit):
return ManhattanDistance(node, exit) + node.specialValue
# Amount of money spent so far
def g(node):
# current.gValue + node.fee + 1
return node.gValue
def ManhattanDistance(firstNode, secondNode):
x = abs(firstNode.x - secondNode.x)
y = abs(firstNode.y - secondNode.y)
return 1 * (x + y)
'''
Helper functions
'''
def interleave(l1, l2):
'''
Interleave two lists.
http://stackoverflow.com/a/29566946/3423701
'''
iter1 = iter(l1)
iter2 = iter(l2)
while True:
try:
if iter1 != None:
yield next(iter1)
except StopIteration:
iter1 = None
try:
if iter2 != None:
yield next(iter2)
except StopIteration:
iter2 = None
if iter1 == None and iter2 == None:
raise StopIteration()
def SameLocation(firstNode, secondNode):
'''
Determines if two nodes are at the same location
'''
if firstNode == None or secondNode == None:
return False
if firstNode.x == secondNode.x and firstNode.y == secondNode.y:
return True
else:
return False
def inSpecialList(node, specialList):
for member in specialList:
if SameLocation(node, member):
return True, member
return False, None
def inList(node, queuelist):
for member in queuelist:
if SameLocation(node, member):
return True
return False
def Neighbors(first, second):
x = abs(first.x - second.x)
y = abs(first.y - second.y)
if x + y >= 2:
return False
else:
return True
def WriteReport(cost, steps, path):
with open('output.txt', 'w') as f:
f.write('Total cost: $'+ str(cost) + '\n')
f.write('Steps taken: ' + str(steps) + '\n')
f.write('Path taken: ')
print('Total cost: $' + str(cost))
print('Steps taken: ' + str(steps))
print('Path taken: ', end='')
temp = ''
for node in path:
temp += node.PrettyStringNode() + ' '
f.write(temp)
print(temp)
if __name__ == '__main__':
maze()