From a8b807016506f1eadf145fa101a4b111240fe4d9 Mon Sep 17 00:00:00 2001 From: Axy Date: Wed, 11 Mar 2026 04:49:24 +0100 Subject: [PATCH] Pathfinding optimizations --- __main__.py | 54 +++++++++++++++++++++++++++---- amazeing/maze_class/maze.py | 2 +- amazeing/maze_class/maze_walls.py | 20 ++++++++++++ example.conf | 12 +++---- 4 files changed, 74 insertions(+), 14 deletions(-) diff --git a/__main__.py b/__main__.py index 0a8ab19..77a6493 100644 --- a/__main__.py +++ b/__main__.py @@ -109,27 +109,67 @@ def poll_events(timeout_ms: int = -1) -> None: backend.present() -prev_path: list[IVec2] = [] +prev_solution: list[Cardinal] = [] + + +def manhattan_distance(a: IVec2, b: IVec2) -> int: + return sum(map(abs, (a - b).xy())) + + +def elipse_manhattan(a: IVec2, b: IVec2, a2: IVec2, b2: IVec2) -> int: + return min( + manhattan_distance(a1, a2) + manhattan_distance(b1, b2) + for a1, b1 in ((a, b), (b, a)) + ) + + +def pathfind_necessary() -> bool: + entry = config.entry + exit = config.exit + if entry is None or exit is None: + return False + if len(prev_solution) == 0: + return True + if any( + map( + lambda e: e in maze.walls_dirty() and maze.get_wall(e).is_full(), + Cardinal.path_to_walls(prev_solution, CellCoord(entry)), + ) + ): + return True + if any( + map( + lambda e: elipse_manhattan(entry, exit, *e.neighbour_cells()) + < len(prev_solution), + filter( + lambda wall: not maze.get_wall(wall).is_full(), + maze.walls_dirty(), + ), + ) + ): + return True + return False def pathfind() -> None: + if not pathfind_necessary(): + return if config.entry is None or config.exit is None: return solution = maze.pathfind(CellCoord(config.entry), CellCoord(config.exit)) - if solution is None: + if solution is None or prev_solution == solution: return + prev_tiles = Cardinal.path_to_tiles(prev_solution, CellCoord(config.entry)) tiles = Cardinal.path_to_tiles(solution, CellCoord(config.entry)) - if prev_path == tiles: - return backend.set_style(empty.curr_style()) - for tile in prev_path: + for tile in prev_tiles: backend.draw_tile(tile) - prev_path.clear() - prev_path.extend(tiles) backend.set_style(path.curr_style()) for tile in tiles: backend.draw_tile(tile) backend.present() + prev_solution.clear() + prev_solution.extend(solution) maze_make_perfect(maze, callback=display_maze) diff --git a/amazeing/maze_class/maze.py b/amazeing/maze_class/maze.py index 1d303b3..58cfd92 100644 --- a/amazeing/maze_class/maze.py +++ b/amazeing/maze_class/maze.py @@ -143,7 +143,7 @@ class Maze: def walls_full(self) -> Iterable[WallCoord]: return filter(lambda w: self.get_wall(w).is_full(), self.all_walls()) - def walls_dirty(self) -> Iterable[WallCoord]: + def walls_dirty(self) -> set[WallCoord]: return self.__dirty def walls_empty(self) -> Iterable[WallCoord]: diff --git a/amazeing/maze_class/maze_walls.py b/amazeing/maze_class/maze_walls.py index 9baf9a9..3507a8c 100644 --- a/amazeing/maze_class/maze_walls.py +++ b/amazeing/maze_class/maze_walls.py @@ -1,3 +1,4 @@ +from collections.abc import Generator from enum import Enum, auto from typing import Iterable, Optional, cast, overload from ..maze_display import IVec2 @@ -90,6 +91,25 @@ class Cardinal(Enum): src = nxt return res + @staticmethod + def path_to_cells( + path: list["Cardinal"], src: "CellCoord" + ) -> list["CellCoord"]: + res = [src] + for card in path: + src = src.get_neighbour(card) + res.append(src) + return res + + @staticmethod + def path_to_walls( + path: list["Cardinal"], src: "CellCoord" + ) -> list["WallCoord"]: + return [ + cell.get_wall(card) + for cell, card in zip(Cardinal.path_to_cells(path, src), path) + ] + class WallCoord: def __init__(self, orientation: Orientation, a: int, b: int) -> None: diff --git a/example.conf b/example.conf index fbec71b..0e05908 100644 --- a/example.conf +++ b/example.conf @@ -1,7 +1,7 @@ -WIDTH=40 -HEIGHT=40 -ENTRY=5,5 -EXIT=25,25 +WIDTH=100 +HEIGHT=100 +ENTRY=0,0 +EXIT=99,99 OUTPUT_FILE=test PERFECT=False SEED=111 @@ -38,9 +38,9 @@ TILEMAP_BACKGROUND=1"{100,1000,1000:0,0,0}## ## " #MAZE_PATTERN="# # #" #MAZE_PATTERN=" ## ## " MAZE_PATTERN=" ### " -MAZE_PATTERN=" # # # " +MAZE_PATTERN=" ## ## " +MAZE_PATTERN="# # #" MAZE_PATTERN="# # #" -MAZE_PATTERN="# #" MAZE_PATTERN="## # " MAZE_PATTERN="# # #" MAZE_PATTERN=" # # " -- 2.53.0