implemented a* with manhattan heuristics and nodes
This commit is contained in:
parent
da9fdc0bb9
commit
e0cd0a5d85
114
hero.py
114
hero.py
@ -1,4 +1,5 @@
|
|||||||
import random
|
import random
|
||||||
|
import heapq
|
||||||
|
|
||||||
from mesa import Agent
|
from mesa import Agent
|
||||||
|
|
||||||
@ -6,6 +7,7 @@ from othercharacters import dice, Box, Creature, Armor, Weapon
|
|||||||
from actions import actions, actionsInterpreter
|
from actions import actions, actionsInterpreter
|
||||||
from state import AgentState
|
from state import AgentState
|
||||||
from direction import Direction
|
from direction import Direction
|
||||||
|
from node import Node
|
||||||
|
|
||||||
|
|
||||||
class Player(Creature):
|
class Player(Creature):
|
||||||
@ -117,7 +119,7 @@ class Player(Creature):
|
|||||||
|
|
||||||
def openChest(self, chest):
|
def openChest(self, chest):
|
||||||
self.gold = self.gold + chest.gold
|
self.gold = self.gold + chest.gold
|
||||||
print("Chest opened. Gold inside:", chest.gold)
|
print("------Chest opened. Gold inside:", chest.gold,"-----")
|
||||||
chest.gold = 0
|
chest.gold = 0
|
||||||
self.openedchests += 1
|
self.openedchests += 1
|
||||||
self.hasgoalchest = False
|
self.hasgoalchest = False
|
||||||
@ -183,9 +185,15 @@ class Player(Creature):
|
|||||||
[actions["rotateRight"], rotateRight]
|
[actions["rotateRight"], rotateRight]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def heuristics(self, state, target_state):
|
||||||
|
# cost is initially step distance in manhattan metric
|
||||||
|
return abs(state.get_x() - target_state.get_x()) + abs(state.get_y() - target_state.get_y())
|
||||||
|
|
||||||
def graphsearch(self, fringe, explored, istate, succesorFunction, goalState):
|
def graphsearch(self, fringe, explored, istate, succesorFunction, goalState):
|
||||||
finalActionList = []
|
finalActionList = []
|
||||||
fringe.append([None, istate]) # at beginning do nothing
|
init_state = [None, istate]
|
||||||
|
root = Node(None, init_state, 0)
|
||||||
|
heapq.heappush(fringe, (0, root)) # at beginning do nothing
|
||||||
|
|
||||||
while len(fringe) != 0:
|
while len(fringe) != 0:
|
||||||
_flag = True
|
_flag = True
|
||||||
@ -193,41 +201,68 @@ class Player(Creature):
|
|||||||
if len(fringe) == 0:
|
if len(fringe) == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
tmpState = fringe.pop(0)
|
tmpNode = (heapq.heappop(fringe))[1] # node
|
||||||
|
|
||||||
# build dictionary
|
# build dictionary
|
||||||
parent = tmpState[1].get_predecessor() #fetch paren state
|
# parent = tmpNode.get_predecessor() # fetch parent state
|
||||||
tmpState[1].set_predecessor(None) # clear predecessor - don't build a tree chain
|
# tmpNode.set_predecessor(None) # clear predecessor - don't build a tree chain
|
||||||
if parent is None:
|
# if parent is None:
|
||||||
finalActionList.append([parent, tmpState])
|
# finalActionList.append([parent, tmpNode])
|
||||||
else:
|
# else:
|
||||||
finalActionList.append([parent[1], tmpState]) # pair(key, value) - key: parent state, value: current state + action
|
# finalActionList.append(
|
||||||
|
# [parent[1], tmpNode]) # pair(key, value) - key: parent state, value: current state + action
|
||||||
|
|
||||||
|
if tmpNode._state.get_x() == goalState.get_x() and tmpNode._state.get_y() == goalState.get_y():
|
||||||
|
while tmpNode._parent is not None:
|
||||||
|
finalActionList.append(tmpNode._action)
|
||||||
|
tmpNode = tmpNode._parent
|
||||||
|
finalActionList = list(reversed(finalActionList))
|
||||||
|
return finalActionList # TODO change step!
|
||||||
|
|
||||||
if tmpState[1].get_x() == goalState.get_x() and tmpState[1].get_y() == goalState.get_y():
|
explored.append(tmpNode)
|
||||||
return finalActionList
|
|
||||||
|
|
||||||
explored.append(tmpState)
|
tmpList = succesorFunction(tmpNode._state)
|
||||||
|
|
||||||
tmpList = succesorFunction(tmpState[1])
|
|
||||||
for newState in tmpList:
|
for newState in tmpList:
|
||||||
_flag = True
|
_flag = True
|
||||||
|
_flagFringe = True
|
||||||
|
_flagExplored = True
|
||||||
|
|
||||||
if newState[1] is None:
|
if newState[1] is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for fringeState in fringe:
|
# calculating priority
|
||||||
if fringeState[1].get_x() == newState[1].get_x() and fringeState[1].get_y() == newState[1].get_y() and fringeState[1].get_direction() == newState[1].get_direction():
|
monster = 0
|
||||||
|
if any([thing.isCreature for thing in self.model.grid.get_cell_list_contents([(newState[1].get_x(), newState[1].get_y())])]):
|
||||||
|
if newState[0] == 0:
|
||||||
|
monster = 10
|
||||||
|
p = self.heuristics(newState[1], goalState) + tmpNode._cost + monster + 1
|
||||||
|
|
||||||
|
r = 0
|
||||||
|
counter = 0
|
||||||
|
pos = 0
|
||||||
|
for fringeNode in fringe:
|
||||||
|
if fringeNode[1]._state.get_x() == newState[1].get_x() and fringeNode[1]._state.get_y() == newState[1].get_y() and fringeNode[1]._state.get_direction() == newState[1].get_direction():
|
||||||
|
_flagFringe = False
|
||||||
|
_flag = False
|
||||||
|
r = fringeNode[0]
|
||||||
|
pos = counter
|
||||||
|
counter = counter + 1
|
||||||
|
|
||||||
|
for exploredNode in explored:
|
||||||
|
if exploredNode._state.get_x() == newState[1].get_x() and exploredNode._state.get_y() == newState[1].get_y() and exploredNode._state.get_direction() == newState[1].get_direction():
|
||||||
|
_flagExplored = False
|
||||||
_flag = False
|
_flag = False
|
||||||
|
|
||||||
for exploredState in explored:
|
# if _flag:
|
||||||
if exploredState[1].get_x() == newState[1].get_x() and exploredState[1].get_y() == newState[1].get_y() and exploredState[1].get_direction() == newState[1].get_direction():
|
# newState[1].set_predecessor(tmpNode)
|
||||||
_flag = False
|
|
||||||
|
|
||||||
if _flag:
|
|
||||||
newState[1].set_predecessor(tmpState)
|
|
||||||
fringe.append(newState)
|
|
||||||
|
|
||||||
|
if _flagFringe and _flagExplored:
|
||||||
|
newNode = Node(tmpNode, newState, tmpNode._cost + 1 + monster)
|
||||||
|
heapq.heappush(fringe, (p, newNode))
|
||||||
|
elif not _flagFringe and (p < r):
|
||||||
|
newNode = Node(tmpNode, newState, tmpNode._cost + 1 + monster)
|
||||||
|
fringe[pos][0] = p
|
||||||
|
fringe[pos][1] = newNode
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -256,38 +291,7 @@ class Player(Creature):
|
|||||||
if self.__actionsCollection is None:
|
if self.__actionsCollection is None:
|
||||||
raise Exception("CRITICAL ERROR - Algorithm error - Path doesn't exist!!! ://")
|
raise Exception("CRITICAL ERROR - Algorithm error - Path doesn't exist!!! ://")
|
||||||
|
|
||||||
else: #build list from dictionary by last element
|
else:
|
||||||
goalActionsList = []
|
|
||||||
#keysList = list(self.__actionsCollection.keys())
|
|
||||||
#valuesList = list(self.__actionsCollection.values())
|
|
||||||
|
|
||||||
stateWithChest = self.__actionsCollection[-1] # fetch last item
|
|
||||||
|
|
||||||
#stateWithChest:
|
|
||||||
# [
|
|
||||||
# [0] key - parent ActionState: object,
|
|
||||||
# [1] value - node successor:
|
|
||||||
# {
|
|
||||||
# [0] action: string - action to get state
|
|
||||||
# [1] AgentState: object - current state
|
|
||||||
# }
|
|
||||||
# ]
|
|
||||||
|
|
||||||
goalActionsList.append(stateWithChest[1][0]) # save action
|
|
||||||
tmpState = stateWithChest[0]
|
|
||||||
while tmpState is not None: # iterate while key (parent state) != None
|
|
||||||
|
|
||||||
index = 0
|
|
||||||
for valeState in self.__actionsCollection: # find new key(parent status) index in array data
|
|
||||||
if valeState[1][1].get_x() == tmpState.get_x() and valeState[1][1].get_y() == tmpState.get_y() and valeState[1][1].get_direction() == tmpState.get_direction():
|
|
||||||
break
|
|
||||||
index += 1
|
|
||||||
|
|
||||||
|
|
||||||
goalActionsList.append(self.__actionsCollection[index][1][0]) # get action
|
|
||||||
tmpState = self.__actionsCollection[index][0] # get state - and next we will find key equal it's value
|
|
||||||
|
|
||||||
self.__actionsCollection = list(reversed(goalActionsList))
|
|
||||||
self.__actionsCollection = [action for action in self.__actionsCollection if action is not None] # remove first None action
|
self.__actionsCollection = [action for action in self.__actionsCollection if action is not None] # remove first None action
|
||||||
else:
|
else:
|
||||||
raise Exception("WIN!!! :D")
|
raise Exception("WIN!!! :D")
|
||||||
|
15
node.py
Normal file
15
node.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class Node:
|
||||||
|
def __init__(self, parent, state_tuple, cost):
|
||||||
|
self._cost = cost
|
||||||
|
self._action = state_tuple[0]
|
||||||
|
self._state = state_tuple[1]
|
||||||
|
self._parent = parent
|
||||||
|
|
||||||
|
def get_predecessor(self):
|
||||||
|
return self._parent
|
||||||
|
|
||||||
|
def set_predecessor(self, predecessor):
|
||||||
|
self._parent = predecessor
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
return self._cost < other._cost
|
@ -18,5 +18,5 @@ server = ModularServer(GameMap,
|
|||||||
[grid],
|
[grid],
|
||||||
"Map",
|
"Map",
|
||||||
{"x":10, "y":10})
|
{"x":10, "y":10})
|
||||||
server.port = 8080
|
server.port = 8081
|
||||||
server.launch()
|
server.launch()
|
9
state.py
9
state.py
@ -1,9 +1,8 @@
|
|||||||
class AgentState:
|
class AgentState:
|
||||||
def __init__(self, x, y, direction, predecessor = None):
|
def __init__(self, x, y, direction):
|
||||||
self.__x = x
|
self.__x = x
|
||||||
self.__y = y
|
self.__y = y
|
||||||
self.__direction = direction
|
self.__direction = direction
|
||||||
self.__predecessor = predecessor
|
|
||||||
|
|
||||||
def get_x(self):
|
def get_x(self):
|
||||||
return self.__x
|
return self.__x
|
||||||
@ -28,9 +27,3 @@ class AgentState:
|
|||||||
|
|
||||||
def set_direction(self, direction):
|
def set_direction(self, direction):
|
||||||
self.__direction = direction
|
self.__direction = direction
|
||||||
|
|
||||||
def get_predecessor(self):
|
|
||||||
return self.__predecessor
|
|
||||||
|
|
||||||
def set_predecessor(self, predecessor):
|
|
||||||
self.__predecessor = predecessor
|
|
Loading…
Reference in New Issue
Block a user