from warehouse import Coordinates, Tile, Pack 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 self.g_cost > other.g_cost 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 = list() self.path = list() def find_path(self): start_node = Node(self.x, self.y) self.open.append(start_node) while self.open: self.open = sorted(self.open) current_node = self.open.pop() 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 and 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: if not self.check_if_closed(neighbour): cost = current_node.g_cost + self.heur_cost_est(current_node, neighbour) if (cost < neighbour.g_cost) or not self.check_if_open(neighbour): neighbour.g_cost = cost neighbour.h_cost = self.heur_cost_est(neighbour, self.dest) neighbour.parent = current_node if not self.check_if_open(neighbour): self.open.append(neighbour); return False def heur_cost_est(self, nodeA: Node, nodeB: Node): deltaX = abs(nodeA.x - nodeB.x) deltaY = abs(nodeA.y - nodeB.y) if deltaX > deltaY: return (14 * deltaY) + (10 * (deltaX - deltaY)) return (14 * deltaX) + (10 *(deltaY - deltaX)) def check_if_open(self, nodeA: Node): for node in self.open: if node.x == nodeA.x and node.y == nodeA.y: return True return False def check_if_closed(self, nodeA: Node): for node in self.closed: if node.x == nodeA.x and node.y == nodeA.y: return True return False 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 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