from operator import itemgetter import constants class Istate: def __init__(self, direction, horizontal_index, vertical_index): self.__direction = direction self.__horizontal_index = horizontal_index self.__vertical_index = vertical_index @property def direction(self): return self.__direction @property def horizontal_index(self): return self.__horizontal_index @property def vertical_index(self): return self.__vertical_index class Node: def __init__(self, action, direction, parent, horizontal_index, vertical_index): self.__action = action self.__direction = direction self.__parent = parent self.__horizontal_index = horizontal_index self.__vertical_index = vertical_index @property def action(self): return self.__action @property def direction(self): return self.__direction @property def parent(self): return self.__parent @property def horizontal_index(self): return self.__horizontal_index @property def vertical_index(self): return self.__vertical_index def goal_test(elem, goaltest): if elem.horizontal_index == goaltest[0] and elem.vertical_index == goaltest[1]: return True else: # print("Traktor wartosc horizontal_index: ", elem.horizontal_index) # print("Traktor wartosc vertical_index: ", elem.vertical_index) return False def print_moves(elem): moves_list = [] while elem.parent is not None: moves_list.append(elem.action) elem = elem.parent moves_list.reverse() return moves_list def cost(board, node): cost_value = 0 while node.parent is not None: field = board[node.horizontal_index][node.vertical_index] cost_value = cost_value + field.cost + 1 node = node.parent return cost_value def heuristic(node, goaltest): return abs(node.horizontal_index - goaltest[0]) + abs(node.vertical_index - goaltest[1]) def f(board, node, goaltest): cost_value = cost(board, node) return cost_value + heuristic(node, goaltest) def succ(elem): actions_list = [] direction = elem.direction if direction == "UP": direction = "RIGHT" elif direction == "RIGHT": direction = "DOWN" elif direction == "DOWN": direction = "LEFT" elif direction == "LEFT": direction = "UP" actions_list.append(("Right_Rotation", (direction, elem.horizontal_index, elem.vertical_index))) direction = elem.direction if direction == "UP": direction = "LEFT" elif direction == "LEFT": direction = "DOWN" elif direction == "DOWN": direction = "RIGHT" elif direction == "RIGHT": direction = "UP" actions_list.append(("Left_Rotation", (direction, elem.horizontal_index, elem.vertical_index))) horizontal_change = 0 vertical_change = 0 if elem.direction == "RIGHT" and elem.horizontal_index < constants.HORIZONTAL_TILES_NUMBER - 1: horizontal_change = 1 elif elem.direction == "LEFT" and elem.horizontal_index > 0: horizontal_change = -1 elif elem.direction == "UP" and elem.vertical_index > 0: vertical_change = -1 elif elem.direction == "DOWN" and elem.vertical_index < constants.VERTICAL_TILES_NUMBER - 1: vertical_change = 1 actions_list.append(("Move", (elem.direction, elem.horizontal_index + horizontal_change, elem.vertical_index + vertical_change))) return actions_list def graphsearch(fringe, explored, istate, goaltest, board): node = Node(None, istate.direction, None, istate.horizontal_index, istate.vertical_index) fringe.append((node, 0)) while True: if not fringe: return False elem = fringe.pop(0) temp = elem[0] if goal_test(elem[0], goaltest) is True: return print_moves(elem[0]) explored.append(elem) for (action, state) in succ(temp): fringe_list = [] fringe_list_priority = [] explored_list = [] for (x, y) in fringe: fringe_list.append((x.direction, x.horizontal_index, x.vertical_index)) fringe_list_priority.append(((x.direction, x.horizontal_index, x.vertical_index), y)) for (x, y) in explored: explored_list.append((x.direction, x.horizontal_index, x.vertical_index)) x = Node(action, state[0], elem[0], state[1], state[2]) p = f(board, x, goaltest) if state not in fringe_list and state not in explored_list: fringe.append((x, p)) fringe = sorted(fringe, key=itemgetter(1)) elif state in fringe_list: index = 0 for (state_priority, r) in fringe_list_priority: if state_priority == state: if r > p: fringe.insert(index, (x, p)) fringe.pop(index + 1) fringe = sorted(fringe, key=itemgetter(1)) break index = index + 1