from warehouse import Coordinates, Tile, Pack from attributes import PackStatus, TURN_LEFT_DIRECTIONS, TURN_RIGHT_DIRECTIONS from queue import PriorityQueue from pathfinder import Node class Agent: def __init__(self, start_x, start_y, assigned_warehouse, radius=5): self.x = start_x self.y = start_y self.direction = 'down' self.radius = radius self.assigned_warehouse = assigned_warehouse self.is_loaded = False self.transported_package = None def demo_agent_move(self, demo_agent_step, demo_step_max=5): demo_agent_sign = 0 next_coords = self.get_next_move_coordinates() can_move = self.check_if_can_move(next_coords) if demo_agent_step >= demo_step_max: demo_agent_sign = -1 self.direction = 'up' elif demo_agent_step == 0: demo_agent_sign = 1 self.direction = 'down' if not can_move: alternative_move = ('left' if self.check_if_can_move(self.move_left()) else None) or ('right' if self.check_if_can_move(self.move_right()) else self.direction) self.direction = alternative_move else: self.x = next_coords.x self.y = next_coords.y def turn_left(self): new_direction = TURN_LEFT_DIRECTIONS.get(self.direction, self.direction) self.direction = new_direction def turn_right(self): new_direction = TURN_RIGHT_DIRECTIONS.get(self.direction, self.direction) self.direction = new_direction def move(self): next_coords = self.get_next_move_coordinates() can_move = self.check_if_can_move(next_coords) if can_move: self.x = next_coords.x self.y = next_coords.y def get_next_move_coordinates(self): direction_moves = { 'up': self.move_up(), 'down': self.move_down(), 'left': self.move_left(), 'right': self.move_right() } next_coords = direction_moves.get(self.direction, Coordinates(self.x, self.y)) return next_coords def check_if_can_move(self, next_coords: Coordinates): next_tile = self.assigned_warehouse.tiles[next_coords.x][next_coords.y] tile_passable = isinstance(next_tile, Tile) and next_tile.category.passable tile_on_map = 0 <= next_coords.x < self.assigned_warehouse.width and 0 <= next_coords.y < self.assigned_warehouse.height return tile_passable and tile_on_map def move_right(self): pos_x = self.x + 1 if pos_x > self.assigned_warehouse.width - 1: pos_x = self.assigned_warehouse.width - 1 return Coordinates(x=pos_x, y=self.y) def move_left(self): pos_x = self.x - 1 if pos_x < 0: pos_x = 0 return Coordinates(x=pos_x, y=self.y) def move_down(self): pos_y = self.y + 1 if pos_y > self.assigned_warehouse.height - 1: pos_y = self.assigned_warehouse.height - 1 return Coordinates(x=self.x, y=pos_y) def move_up(self): pos_y = self.y - 1 if pos_y < 0: pos_y = 0 return Coordinates(x=self.x, y=pos_y) def package_ahead(self): next_coords = self.get_next_move_coordinates() potential_package = self.assigned_warehouse.tiles[next_coords.x][next_coords.y] return isinstance(potential_package, Pack) and potential_package.status != PackStatus.STORED 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 def find_route(self, goal): explored = [] # tu trzeba dodać kolejkę priorytetową fringe fringe = PriorityQueue() current_tile = self.assigned_warehouse.tiles[self.x][self.y] fringe.put((1, current_tile)) while True: if len(fringe) == 0: return False # elem to węzeł z kolejki o najmniejszym priorytecie (najlepszy) elem = fringe.get() # jeśli zgadzają się współrzędne x i y wybranego węzłą oraz celu if elem.x_position == goal.x_position and elem.y_position == goal.y_position: # tu powinna zostać zwrócona ścieżka print("doszedl") return True # przeniesienie wybranego węzłą z fringe do explored explored.append(elem) # dla każdego następnika węzła elem # trzeba napisać funkcję succ wyznaczającą następników elem # succesor[0] - akcja # succesor[1] - stan czyli współrzędne i zwrot # succesor[2] - rodzic succ = self.get_succ(elem) for action, state in succ: new_node = Node(elem, elem.x_position, elem.y_position) # x[1] = succesor[1] # x[2] = elem # x[0] = akcja # trzeba napisać funkcję f(x) liczącą priorytet danego węzła # p = f(x) # if x[1] not in fringe and x[1] not in explored: # fringe.append(x[1]) # nie wiem jak wyznaczyć priorytet który x już ma w kolejce # elif x[1] in fringe and priorytet który stan x już ma w kolejce > p: # tu chodzi o to że zmieni się akcja i rodzić, ale stan nie # zamień w fringe stary węzeł o stanie x[1] z węzłem x def get_succ(self, elem): move = self.move turn_left = self.turn_left turn_right = self.turn_right successors = [ (move, self.get_next_move_coordinates()), (turn_right, TURN_RIGHT_DIRECTIONS.get(self.direction, self.direction)), (turn_left, TURN_LEFT_DIRECTIONS.get(self.direction, self.direction)) ] return successors