from warehouse import Coordinates, Tile, Pack from queue import PriorityQueue from math import sqrt import pdb class Node: def __init__(self, coord_x, coord_y): self.x = coord_x self.y = coord_y self.parent = None self.g_cost = 0 self.h_cost = 0 def __eq__(self, other): if isinstance(other, Node): return self.x == other.x and self.y == self.y return False def __lt__(self, other): return isinstance(other, Node) and self.g_cost < other.g_cost def __repr__(self): return "Node:{}x{}".format(self.x, self.y) class Agent: def __init__(self, start_x, start_y, assigned_warehouse, radius=5): self.x = start_x self.y = start_y self.radius = radius self.warehouse = assigned_warehouse self.is_loaded = False self.transported_package = None self.dest = Node(1, 1) self.closed = list() self.open = PriorityQueue() self.path = list() def find_path(self): self.closed = [] self.open = PriorityQueue() start_node = Node(self.x, self.y) self.open.put((0, start_node)) while self.open: _, current_node = self.open.get() print(current_node.x, current_node.y) self.closed.append(current_node) if current_node.x == self.dest.x and current_node.y == self.dest.y: while current_node.x != start_node.x or current_node.y != start_node.y: self.path.append(current_node) current_node = current_node.parent return True neighbour_list = self.get_neighbours(current_node) for neighbour in neighbour_list: cost = current_node.g_cost + self.heuristic(current_node, neighbour) if self.check_if_closed(neighbour): continue if self.check_if_open(neighbour): if neighbour.g_cost > cost: neighbour.g_cost = cost neighbour.parent = current_node else: neighbour.g_cost = cost neighbour.h_cost = self.heuristic(neighbour, self.dest) neighbour.parent = current_node self.open.put((neighbour.g_cost, neighbour)) return False def heuristic(self, start: Node, goal: Node): diff_x = pow(goal.x - start.x, 2) diff_y = pow(goal.y - start.y, 2) return round(sqrt(diff_x + diff_y), 3) def check_if_open(self, node: Node): return (node.x, node.y) in [(n.x, n.y) for (_,n) in self.open.queue] def check_if_closed(self, node: Node): return (node.x, node.y) in [(n.x, n.y) for n in self.closed] def get_neighbours(self, node: Node): neighbours = [] if self.check_if_can_move(Coordinates(node.x + 1, node.y)): neighbours.append(Node(node.x + 1, node.y)) if self.check_if_can_move(Coordinates(node.x - 1, node.y)): neighbours.append(Node(node.x - 1, node.y)) if self.check_if_can_move(Coordinates(node.x, node.y + 1)): neighbours.append(Node(node.x, node.y + 1)) if self.check_if_can_move(Coordinates(node.x, node.y - 1)): neighbours.append(Node(node.x, node.y - 1)) return neighbours def move(self): if not self.path: if not self.find_path(): return else: next = self.path.pop() print(next.x, next.y) self.x = next.x self.y = next.y self.closed = [] def check_if_can_move(self, next_coords: Coordinates): tile_on_map = 0 <= next_coords.x < self.warehouse.width and 0 <= next_coords.y < self.warehouse.height if not tile_on_map: return False next_tile = self.warehouse.tiles[next_coords.x][next_coords.y] tile_passable = isinstance(next_tile, Tile) and next_tile.category.passable return tile_passable def pick_up_package(self, pack): tile = pack.lays_on_field self.assigned_warehouse.tiles[tile.x_position][tile.y_position] = tile self.is_loaded = True pack.lays_on_field = None self.transported_package = pack