diff --git a/semyanovra/scr/maze.py b/semyanovra/scr/maze.py index 8d1f340..fcefc9f 100644 --- a/semyanovra/scr/maze.py +++ b/semyanovra/scr/maze.py @@ -290,8 +290,9 @@ class EventListener: class ConsoleDisplay(EventListener): - def __init__(self): + def __init__(self, walker=None): self._last_path = None + self._walker = walker def update(self, event_type, data): if event_type == "maze_loaded": @@ -299,6 +300,8 @@ class ConsoleDisplay(EventListener): elif event_type == "path_found": self._last_path = data self._render_path(data) + elif event_type == "player_moved": + self._render_maze_with_player(data) def _render_maze(self, maze): os.system('cls' if os.name == 'nt' else 'clear') @@ -322,6 +325,30 @@ class ConsoleDisplay(EventListener): print("=" * (maze.width * 2 + 4)) print(" S - start E - exit # - wall . - path") + def _render_maze_with_player(self, maze): + os.system('cls' if os.name == 'nt' else 'clear') + print("=" * (maze.width * 2 + 4)) + print(" LABYRINTH (P - player)") + print("=" * (maze.width * 2 + 4)) + + for y in range(maze.height): + print(" ", end='') + for x in range(maze.width): + cell = maze.cell_at(x, y) + if self._walker and cell == self._walker.current: + print('P', end=' ') + elif cell == maze.start: + print('S', end=' ') + elif cell == maze.exit: + print('E', end=' ') + elif cell.is_wall: + print('#', end=' ') + else: + print('.', end=' ') + print() + print("=" * (maze.width * 2 + 4)) + print(f" Player position: ({self._walker.current.x}, {self._walker.current.y})") + def _render_path(self, path): if not path: print("\n Path not found!") @@ -329,17 +356,76 @@ class ConsoleDisplay(EventListener): print(f"\n Path found! Length: {len(path)}") +# ----------------------------- Игрок и команды ----------------------------- +class Walker: + def __init__(self, start_cell, lab): + self._current = start_cell + self._previous = None + self._labyrinth = lab + + @property + def current(self): + return self._current + + def move_to(self, cell): + if cell and cell.passable(): + self._previous = self._current + self._current = cell + return True + return False + + def undo_move(self): + if self._previous: + self._current, self._previous = self._previous, None + return True + return False + + +class Action: + def execute(self): + raise NotImplementedError + + def undo(self): + raise NotImplementedError + + +class MoveAction(Action): + def __init__(self, walker, direction, lab): + self._walker = walker + self._dx, self._dy = direction + self._lab = lab + self._executed = False + + def execute(self): + new_x = self._walker.current.x + self._dx + new_y = self._walker.current.y + self._dy + target = self._lab.cell_at(new_x, new_y) + + if target and target.passable(): + self._walker.move_to(target) + self._executed = True + return True + return False + + def undo(self): + if self._executed: + self._walker.undo_move() + self._executed = False + return True + return False + + if __name__ == "__main__": builder = TxtLabyrinthBuilder() maze = builder.build_from_file("maze/level1.txt") - view = ConsoleDisplay() - view.update("maze_loaded", maze) + walker = Walker(maze.start, maze) + view = ConsoleDisplay(walker) + view._render_maze_with_player(maze) + print("Player created at start position!") - pf = Pathfinder(maze) - pf.attach(view) - - for algo, name in [(BFS(), "BFS"), (DFS(), "DFS"), (AStar(), "A*")]: - pf.set_algorithm(algo) - stats = pf.solve() - print(f"{name}: {stats.time_ms:.3f}ms, visited={stats.visited_cells}, length={stats.path_length}") \ No newline at end of file + # Test movement + test_move = MoveAction(walker, (1, 0), maze) + if test_move.execute(): + print("Moved right!") + view._render_maze_with_player(maze) \ No newline at end of file