from __future__ import annotations import argparse from maze_solver import ( AStarStrategy, BFSStrategy, ConsoleView, DFSStrategy, DijkstraStrategy, Direction, MazeSolver, MoveCommand, Player, TextFileMazeBuilder, ) STRATEGIES = { "bfs": BFSStrategy, "dfs": DFSStrategy, "astar": AStarStrategy, "dijkstra": DijkstraStrategy, } def main() -> None: parser = argparse.ArgumentParser(description="Find a path through a text maze.") parser.add_argument("--maze", default="data/mazes/small.txt") parser.add_argument( "--strategy", choices=sorted(STRATEGIES), default="astar", help="Path-finding algorithm.", ) parser.add_argument("--render", action="store_true", help="Print maze with path.") parser.add_argument( "--manual", action="store_true", help="Manual W/A/S/D mode with Z undo and Q quit.", ) args = parser.parse_args() maze = TextFileMazeBuilder().build_from_file(args.maze) strategy = STRATEGIES[args.strategy]() solver = MazeSolver(maze, strategy) view = ConsoleView() solver.add_observer(view) stats = solver.solve() print( f"Summary: strategy={stats.strategy_name}, time={stats.time_ms:.3f} ms, " f"visited={stats.visited_cells}, path_length={stats.path_length}" ) if args.render: print(view.render(maze, path=stats.path)) if args.manual: run_manual_mode(maze, view) def run_manual_mode(maze, view: ConsoleView) -> None: player = Player.at_start(maze) history: list[MoveCommand] = [] while True: print(view.render(maze, player_position=player.current_cell)) if player.current_cell == maze.exit: print("Exit reached.") return key = input("Move W/A/S/D, undo Z, quit Q: ").strip().lower() if key == "q": return if key == "z": if history: history.pop().undo() continue try: command = MoveCommand(player, Direction.from_key(key)) except ValueError as exc: print(exc) continue if command.execute(): history.append(command) else: print("Move blocked.") if __name__ == "__main__": main()