From ac81b1ed95e6c282d42a9d97fa0a93aed1a533e9 Mon Sep 17 00:00:00 2001 From: Axy Date: Thu, 5 Feb 2026 23:45:25 +0100 Subject: [PATCH] 42 pattern added, next is fully cyclic generation --- __main__.py | 8 +++++- amazeing/__init__.py | 11 +++++++- amazeing/display.py | 10 ++++--- amazeing/maze.py | 65 +++++++++++++++++++++++++++++++++++--------- pyproject.toml | 3 ++ 5 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 pyproject.toml diff --git a/__main__.py b/__main__.py index 8e366f8..6989c13 100644 --- a/__main__.py +++ b/__main__.py @@ -1,8 +1,14 @@ -from amazeing import * +from amazeing import Maze, TTYBackend, Pattern import random + maze = Maze(50, 20) + maze.outline() + +pattern = Pattern(Pattern.FT_PATTERN).centered_for((50, 20)) +pattern.fill(maze) + empty = list(maze.walls_empty()) random.shuffle(empty) for wall in empty: diff --git a/amazeing/__init__.py b/amazeing/__init__.py index 1375e19..6a7d189 100644 --- a/amazeing/__init__.py +++ b/amazeing/__init__.py @@ -1,4 +1,13 @@ __version__ = "0.0.0" from .display import Backend, PixelCoord, TTYBackend -from .maze import WallCoord, Maze +from .maze import WallCoord, Maze, Pattern + +__all__ = [ + "Backend", + "PixelCoord", + "TTYBackend", + "WallCoord", + "Maze", + "Pattern", +] diff --git a/amazeing/display.py b/amazeing/display.py index 835e1a0..c1619c5 100644 --- a/amazeing/display.py +++ b/amazeing/display.py @@ -1,5 +1,4 @@ from abc import ABC, abstractmethod -from typing import Iterable import sys @@ -16,19 +15,22 @@ class Backend(ABC): class TTYBackend(Backend): - def __init__(self, maze_width: int, maze_height: int, style: str = " ") -> None: + def __init__( + self, maze_width: int, maze_height: int, style: str = " " + ) -> None: super().__init__() self.width: int = maze_width * 2 + 1 self.height: int = maze_height * 2 + 1 self.style: str = style self.lines: list[list[str]] = [ - [style for _ in range(0, self.width)] for _ in range(0, self.height) + [style for _ in range(0, self.width)] + for _ in range(0, self.height) ] def draw_pixel(self, pos: PixelCoord) -> None: self.lines[pos.y][pos.x] = self.style - def set_style(self, style: str): + def set_style(self, style: str) -> None: self.style = style def present(self) -> None: diff --git a/amazeing/maze.py b/amazeing/maze.py index 30a1f05..65b6956 100644 --- a/amazeing/maze.py +++ b/amazeing/maze.py @@ -1,6 +1,5 @@ from enum import Enum, auto -from re import X -from typing import Generator, Iterable, Optional, cast +from typing import Callable, Generator, Iterable, Optional, cast from amazeing.display import PixelCoord @@ -57,8 +56,12 @@ class WallCoord: def pixel_coords(self) -> Iterable[PixelCoord]: a: Iterable[int] = [self.a * 2] b: Iterable[int] = [self.b * 2, self.b * 2 + 1, self.b * 2 + 2] - x_iter: Iterable[int] = a if self.orientation == Orientation.VERTICAL else b - y_iter: Iterable[int] = a if self.orientation == Orientation.HORIZONTAL else b + x_iter: Iterable[int] = ( + a if self.orientation == Orientation.VERTICAL else b + ) + y_iter: Iterable[int] = ( + a if self.orientation == Orientation.HORIZONTAL else b + ) return (PixelCoord(x, y) for x in x_iter for y in y_iter) @@ -82,17 +85,23 @@ class CellCoord: def walls(self) -> Iterable[WallCoord]: return [ - WallCoord(Orientation.HORIZONTAL, self.__x, self.__y), - WallCoord(Orientation.HORIZONTAL, self.__x + 1, self.__y), - WallCoord(Orientation.VERTICAL, self.__y, self.__x), - WallCoord(Orientation.VERTICAL, self.__y + 1, self.__x), + WallCoord(Orientation.HORIZONTAL, self.__y, self.__x), + WallCoord(Orientation.HORIZONTAL, self.__y + 1, self.__x), + WallCoord(Orientation.VERTICAL, self.__x, self.__y), + WallCoord(Orientation.VERTICAL, self.__x + 1, self.__y), ] def pixel_coords(self) -> Iterable[PixelCoord]: return [PixelCoord(self.__x * 2 + 1, self.__y * 2 + 1)] - def offset(self, by: "CellCoord") -> "CellCoord": - return CellCoord(self.__x + by.__x, self.__y + by.__y) + def offset(self, by: tuple[int, int]) -> "CellCoord": + return CellCoord(self.__x + by[0], self.__y + by[1]) + + def x(self) -> int: + return self.__x + + def y(self) -> int: + return self.__y class Pattern: @@ -112,11 +121,39 @@ class Pattern: if char != " " } - def offset(self, offset: CellCoord) -> "Pattern": + def offset(self, by: tuple[int, int]) -> "Pattern": pattern: Pattern = Pattern([]) - pattern.cells = {cell.offset(offset) for cell in pattern.cells} + pattern.cells = {cell.offset(by) for cell in self.cells} return pattern + def dims(self) -> tuple[int, int]: + dim_by: Callable[[Callable[[CellCoord], int]], int] = lambda f: ( + max(map(lambda c: f(c) + 1, self.cells), default=0) + - min(map(f, self.cells), default=0) + ) + return (dim_by(CellCoord.x), dim_by(CellCoord.y)) + + def normalized(self) -> "Pattern": + min_by: Callable[[Callable[[CellCoord], int]], int] = lambda f: min( + map(f, self.cells), default=0 + ) + offset: tuple[int, int] = (-min_by(CellCoord.x), -min_by(CellCoord.y)) + return self.offset(offset) + + def centered_for(self, canvas: tuple[int, int]) -> "Pattern": + normalized: Pattern = self.normalized() + dims: tuple[int, int] = normalized.dims() + offset: tuple[int, int] = ( + (canvas[0] - dims[0]) // 2, + (canvas[1] - dims[1]) // 2, + ) + return normalized.offset(offset) + + def fill(self, maze: "Maze") -> None: + for cell in self.cells: + for wall in cell.walls(): + maze.fill_wall(wall) + class WallNetwork: def __init__(self) -> None: @@ -225,7 +262,9 @@ class Maze: return filter(lambda w: self._get_wall(w).is_full(), self.all_walls()) def walls_empty(self) -> Iterable[WallCoord]: - return filter(lambda w: not self._get_wall(w).is_full(), self.all_walls()) + return filter( + lambda w: not self._get_wall(w).is_full(), self.all_walls() + ) def wall_bisects(self, wall: WallCoord) -> bool: a = { diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f3497b3 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[tool.black] +line-length = 79 + -- 2.52.0