]> Untitled Git - axy/ft/a-maze-ing.git/commitdiff
Simple maze stuff, soon generator master
authorAxy <gilliardmarthey.axel@gmail.com>
Wed, 4 Feb 2026 18:40:15 +0000 (19:40 +0100)
committerAxy <gilliardmarthey.axel@gmail.com>
Wed, 4 Feb 2026 18:40:15 +0000 (19:40 +0100)
mase.py [deleted file]
maze.py [new file with mode: 0644]

diff --git a/mase.py b/mase.py
deleted file mode 100644 (file)
index 8b13789..0000000
--- a/mase.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/maze.py b/maze.py
new file mode 100644 (file)
index 0000000..9ec3e72
--- /dev/null
+++ b/maze.py
@@ -0,0 +1,134 @@
+from enum import Enum
+from typing import Optional, cast
+
+
+class NetworkID:
+    __uuid_gen: int = 0
+
+    def __init__(self) -> None:
+        self.uuid = NetworkID.__uuid_gen
+        NetworkID.__uuid_gen += 1
+
+
+class MazeWall:
+    def __init__(self, network_id: Optional[NetworkID] = None) -> None:
+        self.network_id: Optional[NetworkID] = network_id
+
+    def is_full(self) -> bool:
+        return self.network_id is not None
+
+
+class Orientation(Enum):
+    HORIZONTAL = "horizontal"
+    VERTICAL = "vertical"
+
+    def opposite(self) -> "Orientation":
+        if self == Orientation.HORIZONTAL:
+            return Orientation.VERTICAL
+        return Orientation.HORIZONTAL
+
+
+class WallId:
+    def __init__(self, orientation: Orientation, a: int, b: int) -> None:
+        self.orientation: Orientation = orientation
+        self.a: int = a
+        self.b: int = b
+
+    def a_neighbours(self) -> list["WallId"]:
+        return [
+            WallId(self.orientation.opposite(), self.b - 1, self.a),
+            WallId(self.orientation, self.a - 1, self.b),
+            WallId(self.orientation.opposite(), self.b, self.a),
+        ]
+
+    def b_neighbours(self) -> list["WallId"]:
+        return [
+            WallId(self.orientation.opposite(), self.b - 1, self.a + 1),
+            WallId(self.orientation, self.a + 1, self.b),
+            WallId(self.orientation.opposite(), self.b, self.a + 1),
+        ]
+
+    def neighbours(self) -> list["WallId"]:
+        return self.a_neighbours() + self.b_neighbours()
+
+
+class WallNetwork:
+    def __init__(self) -> None:
+        self.walls: set[WallId] = set()
+
+    def size(self) -> int:
+        return len(self.walls)
+
+    def add_wall(self, id: WallId) -> None:
+        self.walls.add(id)
+
+
+class Maze:
+    def __init__(self, width: int, height: int) -> None:
+        self.width: int = width
+        self.height: int = height
+        self.horizontal: list[list[MazeWall]] = [
+            [MazeWall() for _ in range(0, width)] for _ in range(0, height + 1)
+        ]
+        self.vertical: list[list[MazeWall]] = [
+            [MazeWall() for _ in range(0, height)] for _ in range(0, width + 1)
+        ]
+        self.networks: dict[NetworkID, WallNetwork] = {}
+
+    def _get_wall(self, id: WallId) -> MazeWall:
+        if id.orientation == Orientation.HORIZONTAL:
+            return self.horizontal[id.a][id.b]
+        return self.vertical[id.a][id.b]
+
+    def _check_id(self, id: WallId) -> bool:
+        if id.a < 0 or id.b < 0:
+            return False
+        (a_max, b_max) = (
+            (self.height + 1, self.width)
+            if id.orientation == Orientation.HORIZONTAL
+            else (self.width + 1, self.height)
+        )
+        if id.a > a_max or id.b > b_max:
+            return False
+        return True
+
+    def get_walls_checked(self, ids: list[WallId]) -> list[MazeWall]:
+        return [self._get_wall(id) for id in ids if self._check_id(id)]
+
+    def get_neighbours(self, id: WallId) -> list[MazeWall]:
+        return self.get_walls_checked(id.neighbours())
+
+    def _fill_wall_alone(self, id: WallId, wall: MazeWall) -> None:
+        network_id: NetworkID = NetworkID()
+        wall.network_id = network_id
+        network = WallNetwork()
+        network.add_wall(id)
+        self.networks[network_id] = network
+
+    def fill_wall(self, id: WallId) -> None:
+        wall: MazeWall = self._get_wall(id)
+
+        if wall.is_full():
+            return
+
+        networks = {
+            cast(NetworkID, neighbour.network_id)
+            for neighbour in self.get_neighbours(id)
+            if neighbour.is_full()
+        }
+
+        if networks == {}:
+            return self._fill_wall_alone(id, wall)
+
+        dest_id = max(networks, key=lambda n: self.networks[n].size())
+        dest = self.networks[dest_id]
+
+        wall.network_id = dest_id
+        dest.add_wall(id)
+
+        for to_merge in filter(lambda n: n != dest_id, networks):
+            for curr in self.networks[to_merge].walls:
+                self._get_wall(curr).network_id = dest_id
+                dest.add_wall(curr)
+
+            del self.networks[to_merge]