123 lines
3.8 KiB
Python
123 lines
3.8 KiB
Python
|
from typing import List
|
||
|
|
||
|
from core.mushroom import Mushroom
|
||
|
from core.node import Node
|
||
|
from core.tree import Tree
|
||
|
|
||
|
|
||
|
def a_star(board, fringe, explored, istate, successor, get_cost, goaltest):
|
||
|
agent_x = istate[0]
|
||
|
agent_y = istate[1]
|
||
|
agent_angle = istate[2]
|
||
|
fringe: List[Node] = [Node(agent_x, agent_y, agent_angle)]
|
||
|
|
||
|
while fringe:
|
||
|
|
||
|
if not fringe:
|
||
|
return False, False
|
||
|
|
||
|
node = min(fringe, key=lambda x: x.cost)
|
||
|
fringe.remove(node)
|
||
|
|
||
|
if (node.x, node.y) == goaltest:
|
||
|
actions = []
|
||
|
while node.parent is not None:
|
||
|
actions.append(node.action)
|
||
|
node = node.parent
|
||
|
actions.reverse()
|
||
|
return actions
|
||
|
|
||
|
explored.append(node)
|
||
|
|
||
|
for action, x, y, angle in successor(board, node.x, node.y, node.angle):
|
||
|
next_node = Node(x, y, angle)
|
||
|
next_node.parent = node
|
||
|
next_node.action = action
|
||
|
next_node.cost = get_cost(next_node, goaltest, board) + heuristic_function(next_node, goaltest, board)
|
||
|
|
||
|
if next_node not in fringe and next_node not in explored:
|
||
|
fringe.append(next_node)
|
||
|
else:
|
||
|
for checked_node in fringe:
|
||
|
if checked_node == next_node and next_node.cost < checked_node.cost:
|
||
|
fringe[fringe.index(checked_node)] = next_node
|
||
|
|
||
|
|
||
|
def successor(board, x, y, angle):
|
||
|
result = []
|
||
|
|
||
|
result.append(("rotate_left", x, y, (angle + 1) % 4))
|
||
|
result.append(("rotate_right", x, y, (angle - 1) % 4))
|
||
|
|
||
|
if angle == 1:
|
||
|
if x > 0:
|
||
|
result.append(("move", x - 1, y, angle))
|
||
|
elif angle == 0:
|
||
|
if y > 0:
|
||
|
result.append(("move", x, y - 1, angle))
|
||
|
elif angle == 3:
|
||
|
if x < board.col - 1:
|
||
|
result.append(("move", x + 1, y, angle))
|
||
|
elif angle == 2:
|
||
|
if y < board.row - 1:
|
||
|
result.append(("move", x, y + 1, angle))
|
||
|
|
||
|
return result
|
||
|
|
||
|
|
||
|
def get_cost(node, goal: Mushroom, board):
|
||
|
if (node.parent.x, node.parent.y) == (node.x, node.y):
|
||
|
weight = 1
|
||
|
elif isinstance((board.board[node.x][node.y]), Tree):
|
||
|
weight = 1000
|
||
|
elif isinstance((board.board[node.x][node.y]), Mushroom) and board.dt.predict(board.board[node.x][node.y]):
|
||
|
weight = 1000
|
||
|
else:
|
||
|
weight = 2
|
||
|
|
||
|
return weight + node.parent.cost
|
||
|
|
||
|
|
||
|
def heuristic_function(node, goal, board):
|
||
|
try:
|
||
|
return abs(node.x - goal[0]) + abs(node.y - goal[1])
|
||
|
except:
|
||
|
print("No more edible mushrooms on the board. Score: " + str(board.agent.points))
|
||
|
exit(0)
|
||
|
|
||
|
|
||
|
def bfs(istate, successor, board):
|
||
|
fringe = []
|
||
|
explored = []
|
||
|
fringe_states = set()
|
||
|
explored_states = set()
|
||
|
|
||
|
agent_x = istate[0]
|
||
|
agent_y = istate[1]
|
||
|
agent_angle = istate[2]
|
||
|
fringe.append(Node(agent_x, agent_y, agent_angle))
|
||
|
fringe_states.add((agent_x, agent_y, agent_angle))
|
||
|
|
||
|
while fringe:
|
||
|
|
||
|
if not fringe:
|
||
|
return False, False
|
||
|
|
||
|
node = fringe.pop(0)
|
||
|
fringe_states.remove((node.x, node.y, node.angle))
|
||
|
|
||
|
if isinstance((board.board[node.x][node.y]), Mushroom):
|
||
|
if not board.dt.predict(board.board[node.x][node.y]):
|
||
|
return node.x, node.y
|
||
|
|
||
|
explored.append(node)
|
||
|
explored_states.add((node.x, node.y, node.angle))
|
||
|
|
||
|
for action, x, y, angle in successor(board, node.x, node.y, node.angle):
|
||
|
if ((x, y, angle) not in explored_states and (x, y, angle) not in fringe_states):
|
||
|
next_node = Node(x, y, angle)
|
||
|
next_node.parent = node
|
||
|
next_node.action = action
|
||
|
fringe.append(next_node)
|
||
|
fringe_states.add((x, y, angle))
|