SIP/core/a_star.py
2021-06-10 21:23:58 +02:00

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))