-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnode.py
297 lines (247 loc) · 10 KB
/
node.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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
def calculateHeuristic(manhattanDistance):
heuristic = 0
# assuming Kirby has both stars, only a max. of 12 squares would cost half as much.
if manhattanDistance > 12:
heuristic = manhattanDistance - 6
else:
heuristic = manhattanDistance / 2
return heuristic
def rightMovement(kirbyPos):
return [kirbyPos[0], kirbyPos[1] + 1 if kirbyPos[1] < 9 else False]
def leftMovement(kirbyPos):
return [kirbyPos[0], kirbyPos[1] - 1 if kirbyPos[1] > 0 else False]
def upMovement(kirbyPos):
return [kirbyPos[0] - 1 if kirbyPos[0] > 0 else False, kirbyPos[1]]
def downMovement(kirbyPos):
return [kirbyPos[0] + 1 if kirbyPos[0] < 9 else False, kirbyPos[1]]
class Node:
EMPTY = 0
BLOCK = 1
kirby = 2
STAR = 3
KOOPA = 5
FLOWER = 4
Wandana = 6
RESCUED_Wandana = 8
def __init__(self, state, father, operator, depth, cost, star, flower):
self.__state = state
self.__father = father
self.__operator = operator
self.__depth = depth
self.__cost = cost
self.__star = star # It lasts 6 grids - cost 1/2 and they accumulate
self.__flower = flower # Cost to go through a koopa when having a flower comes down to 1
self.__kirbyPos = []
self.__heuristic = 0 # The correct value is given only when the greedy algorithm is used
self.__sumCostHeuristic = 0
self.__awaitingCharacter = 0
def getRightCount(self):
count = 0
currentNode = self
operator = currentNode.getOperator()
while operator != "first father":
if operator == "right":
count += 1
currentNode = currentNode.getFather()
operator = currentNode.getOperator()
return count
def getState(self):
return self.__state
def getFather(self):
return self.__father
def getOperator(self):
return self.__operator
def getDepth(self):
return self.__depth
def getCost(self):
return self.__cost
def getHeuristic(self):
return self.__heuristic
def getKirbyPos(self):
return self.__kirbyPos
def getStar(self):
return self.__star
def getFlower(self):
return self.__flower
def getState(self):
return self.__state.copy()
def getAwaitingCharacter(self):
return self.__awaitingCharacter
def getSumCostHeuristic(self):
return self.__sumCostHeuristic
def setState(self, newState):
self.__state = newState
def setFather(self, newFather):
self.__father = newFather
def setOperator(self, newOperator):
self.__operator = newOperator
def setDepth(self, newDepth):
self.__depth = newDepth
def setCost(self, newCost):
self.__cost = newCost
def setHeuristic(self, newHeuristic):
self.__heuristic = newHeuristic
def setKirbyPos(self, newKirbyPos):
self.__kirbyPos = newKirbyPos
def setStar(self, newStarValue):
self.__star = newStarValue
def setFlower(self, newFlowerValue):
self.__flower = newFlowerValue
def setAwaitingCharacter(self, awaitingCharacter):
self.__awaitingCharacter = awaitingCharacter
def setSumCostHeuristic(self, newValue):
self.__sumCostHeuristic = newValue
def calculateManhattanDistance(self, wandanaPos):
iDistance = wandanaPos[0] - self.getKirbyPos()[0]
jDistance = wandanaPos[1] - self.getKirbyPos()[1]
manhattanDistance = abs(iDistance) + abs(jDistance)
return manhattanDistance
# True means that the node can expand their sons, false means it can't
def avoidGoBack2(self, nextKirbyPos):
currentNode = self
fatherNode = self.getFather()
grandFatherNode = fatherNode.getFather()
nextNodePosition = nextKirbyPos
if grandFatherNode.getOperator() != "first father":
if grandFatherNode.getKirbyPos() == nextNodePosition:
if (
grandFatherNode.getStar() != currentNode.getStar() or grandFatherNode.getFlower() != currentNode.getFlower() or (
fatherNode.getFlower() == 1 and currentNode.getFlower() == 0)):
return True
else:
return False
return True
def compareCircles2(self, nextKirbyPos):
currentNode = self
fatherNode = self.getFather()
grandFatherNode = fatherNode.getFather()
nextNodePosition = nextKirbyPos
while grandFatherNode.getOperator() != "first father":
if grandFatherNode.getKirbyPos() == nextNodePosition:
if (
grandFatherNode.getStar() != currentNode.getStar() or grandFatherNode.getFlower() != currentNode.getFlower() or (
fatherNode.getFlower() == 1 and currentNode.getFlower() == 0)):
grandFatherNode = grandFatherNode.getFather()
else:
return False
else:
grandFatherNode = grandFatherNode.getFather()
return True
def moveRight(self, posKirby):
i = posKirby[0]
j = posKirby[1]
self.__state[i, j] = self.getFather().getAwaitingCharacter()
self.takeDecision([i, j + 1])
return self
def moveLeft(self, posKirby):
i = posKirby[0]
j = posKirby[1]
self.__state[i, j] = self.getFather().getAwaitingCharacter()
self.takeDecision([i, j - 1])
return self
def moveDown(self, posKirby):
i = posKirby[0]
j = posKirby[1]
self.__state[i, j] = self.getFather().getAwaitingCharacter()
self.takeDecision([i + 1, j])
return self
def moveUp(self, posKirby):
i = posKirby[0]
j = posKirby[1]
self.__state[i, j] = self.getFather().getAwaitingCharacter()
self.takeDecision([i - 1, j])
return self
def setNewCost(self, pos):
i = pos[0]
j = pos[1]
state = self.getState()
currentCost = self.getCost() # Current cost is the one from the father
# If the position where Kirby will move into has a Koopa inside then:
if state[i, j] == self.KOOPA:
if self.getStar() > 0: # If true, Koopa will not affect Kirby
self.setCost(currentCost + 0.5)
elif self.getFlower() > 0: # If true, Kirby can use the flower to kill Koopa
self.setCost(currentCost + 1)
else: # If all the cases above did not meet, Kirby is affected by Koopa
self.setCost(currentCost + 6)
elif state[i, j] == self.FLOWER:
if self.getStar() > 0:
self.setCost(currentCost + 0.5)
else:
self.setCost(currentCost + 1)
# If it is not a Koopa, I still need to check whether Kirby has a star or not,
# if so Kirby needs 0.5 of effort to move across the grid
else:
if self.getStar() > 0:
self.setCost(currentCost + 0.5)
else:
self.setCost(currentCost + 1)
# pos is the future position of Kirby
def takeDecision(self, pos):
i = pos[0]
j = pos[1]
if self.__state[i, j] == self.Wandana:
self.setAwaitingCharacter(self.EMPTY)
self.setStar(self.getStar() - 1 if self.getStar() > 0 else 0)
self.__state[i, j] = self.RESCUED_Wandana
elif self.__state[i, j] == self.KOOPA:
if self.getFlower() > 0 or self.getStar() > 0:
self.setAwaitingCharacter(self.EMPTY)
self.setFlower(self.getFlower() -
1 if self.getFlower() > 0 else 0)
self.setStar(self.getStar() - 1 if self.getStar() > 0 else 0)
else:
self.setAwaitingCharacter(self.KOOPA)
elif self.__state[i, j] == self.FLOWER:
if self.getStar() == 0: # Kirby can get the flower
self.setFlower(self.getFlower() + 1)
# print("cantidad flowers", self.getFlower())
self.setAwaitingCharacter(self.EMPTY)
else:
self.setStar(self.getStar() - 1 if self.getStar() > 0 else 0)
self.setAwaitingCharacter(self.FLOWER)
elif self.__state[i, j] == self.STAR:
if self.getFlower() == 0: # Kirby can get the star
self.setStar(self.getStar() - 1 if self.getStar() > 0 else 0)
self.setStar(self.getStar() + 6)
self.setAwaitingCharacter(self.EMPTY)
else:
self.setAwaitingCharacter(self.STAR)
else:
self.setStar(self.getStar() - 1 if self.getStar() > 0 else 0)
self.setAwaitingCharacter(self.EMPTY)
if self.__state[i, j] != self.RESCUED_Wandana:
self.__state[i, j] = self.kirby
def recreateSolution(self):
directions = []
currentNode = self
while currentNode.getOperator() != "first father":
directions.append(
str(currentNode.getOperator() + " " + str(currentNode.getCost()) + " Star: " + str(
currentNode.getStar())))
currentNode = currentNode.getFather()
return directions
def recreateSolutionWorld(self):
directions = []
currentNode = self
while currentNode.getOperator() != "first father":
directions.append(currentNode.getState())
currentNode = currentNode.getFather()
return directions
def searchForKirby(self):
kirbyPos = [-1, -1] # Kirby position [x,y]
state = self.__state
for i in range(15):
for j in range(15):
if state[i, j] == self.kirby:
kirbyPos[0] = i
kirbyPos[1] = j
self.setKirbyPos(kirbyPos)
return kirbyPos
def isGoal(self):
state = self.__state
for i in range(15):
for j in range(15):
if state[i, j] == self.RESCUED_Wandana:
return True
return False