the-maze-py 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. the_maze_py-0.1.0/LICENSE +7 -0
  2. the_maze_py-0.1.0/PKG-INFO +93 -0
  3. the_maze_py-0.1.0/README.md +76 -0
  4. the_maze_py-0.1.0/pyproject.toml +29 -0
  5. the_maze_py-0.1.0/setup.cfg +4 -0
  6. the_maze_py-0.1.0/src/mazepy/__init__.py +14 -0
  7. the_maze_py-0.1.0/src/mazepy/algorithms/__init__.py +87 -0
  8. the_maze_py-0.1.0/src/mazepy/algorithms/aldous_broder.py +32 -0
  9. the_maze_py-0.1.0/src/mazepy/algorithms/binary_tree.py +65 -0
  10. the_maze_py-0.1.0/src/mazepy/algorithms/ellers.py +143 -0
  11. the_maze_py-0.1.0/src/mazepy/algorithms/fractal_tesselation.py +74 -0
  12. the_maze_py-0.1.0/src/mazepy/algorithms/growing_tree.py +40 -0
  13. the_maze_py-0.1.0/src/mazepy/algorithms/hunt_and_kill.py +45 -0
  14. the_maze_py-0.1.0/src/mazepy/algorithms/kruskals.py +105 -0
  15. the_maze_py-0.1.0/src/mazepy/algorithms/origin_shift.py +163 -0
  16. the_maze_py-0.1.0/src/mazepy/algorithms/prims.py +126 -0
  17. the_maze_py-0.1.0/src/mazepy/algorithms/recursive_backtrack.py +38 -0
  18. the_maze_py-0.1.0/src/mazepy/algorithms/recursive_division.py +78 -0
  19. the_maze_py-0.1.0/src/mazepy/algorithms/sidewinder.py +93 -0
  20. the_maze_py-0.1.0/src/mazepy/algorithms/wilsons.py +51 -0
  21. the_maze_py-0.1.0/src/mazepy/cells/__init__.py +53 -0
  22. the_maze_py-0.1.0/src/mazepy/cells/cell.py +72 -0
  23. the_maze_py-0.1.0/src/mazepy/cells/hex_cell.py +28 -0
  24. the_maze_py-0.1.0/src/mazepy/cells/polar_cell.py +27 -0
  25. the_maze_py-0.1.0/src/mazepy/cells/triangle_cell.py +21 -0
  26. the_maze_py-0.1.0/src/mazepy/cells/weave_cells.py +80 -0
  27. the_maze_py-0.1.0/src/mazepy/cells/weighted_cell.py +24 -0
  28. the_maze_py-0.1.0/src/mazepy/create_animation_2d.py +838 -0
  29. the_maze_py-0.1.0/src/mazepy/deadends.py +72 -0
  30. the_maze_py-0.1.0/src/mazepy/distances.py +48 -0
  31. the_maze_py-0.1.0/src/mazepy/fill_animation_2d.py +88 -0
  32. the_maze_py-0.1.0/src/mazepy/grid_not_supported_exception.py +5 -0
  33. the_maze_py-0.1.0/src/mazepy/grids/__init__.py +138 -0
  34. the_maze_py-0.1.0/src/mazepy/grids/colored_grid.py +75 -0
  35. the_maze_py-0.1.0/src/mazepy/grids/colored_hex_grid.py +28 -0
  36. the_maze_py-0.1.0/src/mazepy/grids/colored_polar_grid.py +31 -0
  37. the_maze_py-0.1.0/src/mazepy/grids/colored_triangle_grid.py +28 -0
  38. the_maze_py-0.1.0/src/mazepy/grids/colored_weave_grid.py +54 -0
  39. the_maze_py-0.1.0/src/mazepy/grids/cube_grid.py +267 -0
  40. the_maze_py-0.1.0/src/mazepy/grids/cylinder_grid.py +86 -0
  41. the_maze_py-0.1.0/src/mazepy/grids/distance_grid.py +35 -0
  42. the_maze_py-0.1.0/src/mazepy/grids/grid.py +354 -0
  43. the_maze_py-0.1.0/src/mazepy/grids/grid_3D.py +187 -0
  44. the_maze_py-0.1.0/src/mazepy/grids/hex_grid.py +98 -0
  45. the_maze_py-0.1.0/src/mazepy/grids/masked_grid.py +18 -0
  46. the_maze_py-0.1.0/src/mazepy/grids/mobius_grid.py +137 -0
  47. the_maze_py-0.1.0/src/mazepy/grids/polar_grid.py +145 -0
  48. the_maze_py-0.1.0/src/mazepy/grids/sphere_grid.py +170 -0
  49. the_maze_py-0.1.0/src/mazepy/grids/toroidal_grid.py +77 -0
  50. the_maze_py-0.1.0/src/mazepy/grids/triangle_grid.py +87 -0
  51. the_maze_py-0.1.0/src/mazepy/grids/weave_grid.py +87 -0
  52. the_maze_py-0.1.0/src/mazepy/grids/weighted_grid.py +36 -0
  53. the_maze_py-0.1.0/src/mazepy/longest_path.py +14 -0
  54. the_maze_py-0.1.0/src/mazepy/mask.py +98 -0
  55. the_maze_py-0.1.0/src/mazepy/preconfigure_grid_example.py +19 -0
  56. the_maze_py-0.1.0/src/mazepy/weighted_shortest_path_example.py +27 -0
  57. the_maze_py-0.1.0/src/the_maze_py.egg-info/PKG-INFO +93 -0
  58. the_maze_py-0.1.0/src/the_maze_py.egg-info/SOURCES.txt +60 -0
  59. the_maze_py-0.1.0/src/the_maze_py.egg-info/dependency_links.txt +1 -0
  60. the_maze_py-0.1.0/src/the_maze_py.egg-info/requires.txt +4 -0
  61. the_maze_py-0.1.0/src/the_maze_py.egg-info/top_level.txt +1 -0
  62. the_maze_py-0.1.0/tests/TestScript.py +160 -0
@@ -0,0 +1,7 @@
1
+ Copyright © 2026 CaptaininjaGuy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.4
2
+ Name: the-maze-py
3
+ Version: 0.1.0
4
+ Summary: A package that generates mazes
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/Captaininja-Guy/mazepy
7
+ Keywords: maze
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Natural Language :: English
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy>=2.4.6
13
+ Requires-Dist: pyvista>=0.48.4
14
+ Requires-Dist: matplotlib>=3.10.9
15
+ Requires-Dist: pillow>=12.2.0
16
+ Dynamic: license-file
17
+
18
+ mazepy
19
+ =======
20
+
21
+ A maze library based off of the book [Mazes for Programmers](https://pragprog.com/titles/jbmaze/mazes-for-programmers/) by Jamis Buck but with more stuff.
22
+
23
+ Installation
24
+ ```bash
25
+ pip install maze-py
26
+ ```
27
+
28
+ Maze Shapes Supported
29
+ ---------------------
30
+ #### 2D
31
+ * Rectangular
32
+ * Polar (Circular)
33
+ * Hexagonal
34
+ * Triangular
35
+ * Arbitrary shapes with masking
36
+ #### 3D
37
+ * Layers (Grid 3D)
38
+ * Cylindrical
39
+ * Spherical
40
+ * Cube
41
+ * Toroidal
42
+ * Möbius Strip
43
+
44
+ Generation Algorithms Supported
45
+ -------------------------------
46
+ * Aldous Broder
47
+ * Binary Tree (not triangular)
48
+ * Ellers (not triangular)
49
+ * Fractal Tesselation (only rectangualar)
50
+ * Growing Tree
51
+ * Hunt and Kill
52
+ * Kruskals (not polar, haxagonal, or triangular)
53
+ * Origin Shift
54
+ * Prims (Simplified, True, Modified)
55
+ * Recursive Backtrack (DFS)
56
+ * Recursive Division (only Rectangular)
57
+ * Sidewinder
58
+ * Wilsons
59
+
60
+ Other Features
61
+ --------------
62
+ * Printing rectangular mazes
63
+ * Generating pngs of mazes
64
+ * Color grids based on distance
65
+ * Viewing 3d grids in 3d
66
+ * Animations of maze creation and filling with color gradient
67
+
68
+
69
+ Examples
70
+ ========
71
+ Showing a colored maze
72
+ ----------------------
73
+ ```python
74
+ import mazepy as mp
75
+
76
+ grid = mp.grids.ColoredGrid(10,10, base='red', end='blue')
77
+ mp.algorithms.Ellers(grid)
78
+ grid.distances = grid[5, 5].distances() # Set starting cell (this is required)
79
+ grid.show()
80
+ ```
81
+
82
+ <img src="https://raw.githubusercontent.com/Captaininja-Guy/mazepy/refs/heads/main/pictures/colored.png" width="400"/>
83
+
84
+ Mazes of different shapes
85
+ -------------------------
86
+ ```python
87
+ import mazepy as mp
88
+
89
+ grid = mp.grids.PolarGrid(10)
90
+ mp.algorithms.RecursiveBacktrack(grid)
91
+ grid.show()
92
+ ```
93
+ <img src="https://raw.githubusercontent.com/Captaininja-Guy/mazepy/refs/heads/main/pictures/polar.png" width="400"/>
@@ -0,0 +1,76 @@
1
+ mazepy
2
+ =======
3
+
4
+ A maze library based off of the book [Mazes for Programmers](https://pragprog.com/titles/jbmaze/mazes-for-programmers/) by Jamis Buck but with more stuff.
5
+
6
+ Installation
7
+ ```bash
8
+ pip install maze-py
9
+ ```
10
+
11
+ Maze Shapes Supported
12
+ ---------------------
13
+ #### 2D
14
+ * Rectangular
15
+ * Polar (Circular)
16
+ * Hexagonal
17
+ * Triangular
18
+ * Arbitrary shapes with masking
19
+ #### 3D
20
+ * Layers (Grid 3D)
21
+ * Cylindrical
22
+ * Spherical
23
+ * Cube
24
+ * Toroidal
25
+ * Möbius Strip
26
+
27
+ Generation Algorithms Supported
28
+ -------------------------------
29
+ * Aldous Broder
30
+ * Binary Tree (not triangular)
31
+ * Ellers (not triangular)
32
+ * Fractal Tesselation (only rectangualar)
33
+ * Growing Tree
34
+ * Hunt and Kill
35
+ * Kruskals (not polar, haxagonal, or triangular)
36
+ * Origin Shift
37
+ * Prims (Simplified, True, Modified)
38
+ * Recursive Backtrack (DFS)
39
+ * Recursive Division (only Rectangular)
40
+ * Sidewinder
41
+ * Wilsons
42
+
43
+ Other Features
44
+ --------------
45
+ * Printing rectangular mazes
46
+ * Generating pngs of mazes
47
+ * Color grids based on distance
48
+ * Viewing 3d grids in 3d
49
+ * Animations of maze creation and filling with color gradient
50
+
51
+
52
+ Examples
53
+ ========
54
+ Showing a colored maze
55
+ ----------------------
56
+ ```python
57
+ import mazepy as mp
58
+
59
+ grid = mp.grids.ColoredGrid(10,10, base='red', end='blue')
60
+ mp.algorithms.Ellers(grid)
61
+ grid.distances = grid[5, 5].distances() # Set starting cell (this is required)
62
+ grid.show()
63
+ ```
64
+
65
+ <img src="https://raw.githubusercontent.com/Captaininja-Guy/mazepy/refs/heads/main/pictures/colored.png" width="400"/>
66
+
67
+ Mazes of different shapes
68
+ -------------------------
69
+ ```python
70
+ import mazepy as mp
71
+
72
+ grid = mp.grids.PolarGrid(10)
73
+ mp.algorithms.RecursiveBacktrack(grid)
74
+ grid.show()
75
+ ```
76
+ <img src="https://raw.githubusercontent.com/Captaininja-Guy/mazepy/refs/heads/main/pictures/polar.png" width="400"/>
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "the-maze-py"
7
+ version = "0.1.0"
8
+ description = "A package that generates mazes"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ dependencies = [
13
+ "numpy>=2.4.6",
14
+ "pyvista>=0.48.4",
15
+ "matplotlib>=3.10.9",
16
+ "pillow>=12.2.0",
17
+ ]
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "Natural Language :: English",
21
+ ]
22
+ keywords = ["maze"]
23
+
24
+
25
+ [project.urls]
26
+ Homepage = "https://github.com/Captaininja-Guy/mazepy"
27
+
28
+ [tool.setuptools.packages.find]
29
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,14 @@
1
+ from . import grids
2
+ from . import algorithms
3
+ from . import cells
4
+ from .create_animation_2d import play_create_2d
5
+ from .deadends import Deadends
6
+ from .fill_animation_2d import play_fill_2d
7
+ from .longest_path import longest_path
8
+ from .mask import Mask
9
+ from .preconfigure_grid_example import precon_grid_ex
10
+ from .weighted_shortest_path_example import weight_grid_ex
11
+
12
+ __all__ = ["grids", "algorithms", "cells", "play_create_2d",
13
+ "Deadends", "play_fill_2d", "longest_path",
14
+ "Mask", "precon_grid_ex", "weight_grid_ex"]
@@ -0,0 +1,87 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING:
4
+ from .aldous_broder import AldousBroder
5
+ from .binary_tree import BinaryTree
6
+ from .ellers import Ellers
7
+ from .fractal_tesselation import FractalTessalation
8
+ from .growing_tree import GrowingTree
9
+ from .hunt_and_kill import HuntandKill
10
+ from .kruskals import Kruskals
11
+ from .origin_shift import OriginShift
12
+ from .prims import Prims, TruePrims, ModifiedPrims, SimplifiedPrims
13
+ from .recursive_backtrack import RecursiveBacktrack
14
+ from .recursive_division import RecursiveDivision
15
+ from .sidewinder import Sidewinder
16
+ from .wilsons import Wilsons
17
+
18
+
19
+ def __getattr__(name):
20
+ if name == "AldousBroder":
21
+ from .aldous_broder import AldousBroder
22
+ return AldousBroder
23
+ if name == "BinaryTree":
24
+ from .binary_tree import BinaryTree
25
+ return BinaryTree
26
+ if name == "Ellers":
27
+ from .ellers import Ellers
28
+ return Ellers
29
+ if name == "FractalTessalation":
30
+ from .fractal_tesselation import FractalTessalation
31
+ return FractalTessalation
32
+ if name == "GrowingTree":
33
+ from .growing_tree import GrowingTree
34
+ return GrowingTree
35
+ if name == "HuntandKill":
36
+ from .hunt_and_kill import HuntandKill
37
+ return HuntandKill
38
+ if name == "Kruskals":
39
+ from .kruskals import Kruskals
40
+ return Kruskals
41
+ if name == "OriginShift":
42
+ from .origin_shift import OriginShift
43
+ return OriginShift
44
+ if name == "Prims":
45
+ from .prims import Prims
46
+ return Prims
47
+ if name == "TruePrims":
48
+ from .prims import TruePrims
49
+ return TruePrims
50
+ if name == "ModifiedPrims":
51
+ from .prims import ModifiedPrims
52
+ return ModifiedPrims
53
+ if name == "SimplifiedPrims":
54
+ from .prims import SimplifiedPrims
55
+ return SimplifiedPrims
56
+ if name == "RecursiveBacktrack":
57
+ from .recursive_backtrack import RecursiveBacktrack
58
+ return RecursiveBacktrack
59
+ if name == "RecursiveDivision":
60
+ from .recursive_division import RecursiveDivision
61
+ return RecursiveDivision
62
+ if name == "Sidewinder":
63
+ from .sidewinder import Sidewinder
64
+ return Sidewinder
65
+ if name == "Wilsons":
66
+ from .wilsons import Wilsons
67
+ return Wilsons
68
+
69
+ raise AttributeError(name)
70
+
71
+
72
+ __all__ = ["AldousBroder",
73
+ "BinaryTree",
74
+ "Ellers",
75
+ "FractalTessalation",
76
+ "GrowingTree",
77
+ "HuntandKill",
78
+ "Kruskals",
79
+ "OriginShift",
80
+ "Prims",
81
+ "TruePrims",
82
+ "ModifiedPrims",
83
+ "SimplifiedPrims",
84
+ "RecursiveBacktrack",
85
+ "RecursiveDivision",
86
+ "Sidewinder",
87
+ "Wilsons"]
@@ -0,0 +1,32 @@
1
+ import random as rand
2
+ from ..grids.grid import Grid
3
+
4
+ def AldousBroder(grid: Grid) -> None:
5
+ '''
6
+ Performs the AldousBroder algorithm on a given Grid in place.
7
+ Any type of grid can be used
8
+
9
+ Parameters:
10
+ grid (Grid)
11
+
12
+ Returns:
13
+ None, the grid is modified in place
14
+
15
+ Example:
16
+ import mazepy as mp
17
+
18
+ grid = mp.grids.Grid(20,20)
19
+ mp.algorithms.AldousBroder(grid)
20
+ grid.show()
21
+ '''
22
+ cell = grid.random_cell()
23
+ unvisited = grid.size - 1
24
+
25
+ while unvisited > 0:
26
+ neighbor = rand.choice(cell.neighbors())
27
+
28
+ if not neighbor.links():
29
+ cell.link(neighbor)
30
+ unvisited -= 1
31
+
32
+ cell = neighbor
@@ -0,0 +1,65 @@
1
+ import random as rand
2
+ from ..grids.grid import Grid
3
+ from ..grid_not_supported_exception import GridNotSupportedException
4
+ import warnings
5
+
6
+
7
+
8
+ def BinaryTree(grid: Grid) -> None:
9
+ '''
10
+ Performs Binary Tree algorithm on a given Grid in place
11
+ Most non-triangle Grids can be used with satisfactory results
12
+
13
+ Parameters:
14
+ grid (Grid)
15
+
16
+ Returns:
17
+ None the grid is modified in place
18
+
19
+ Warnings:
20
+ RuntimeWarning Binary tree cannot produce weaving on weaved grids
21
+
22
+ Errors:
23
+ Throws GridNotSupportedException when given a TriangleGrid
24
+
25
+ Example:
26
+ import mazepy as mp
27
+
28
+ grid = mp.grids.Grid(20,20)
29
+ mp.algorithms.BinaryTree(grid)
30
+ grid.show()
31
+ '''
32
+
33
+ if grid.type_of_grid == 'triangle':
34
+ raise GridNotSupportedException('TriangleGrid not compatible with Binary Tree')
35
+ if grid.type_of_grid == 'weave': # Warning for Weaved Grids as weaving will not occur
36
+ warnings.warn('Binary Tree will NOT produce weaved grid')
37
+
38
+ _hex, polar, three_d = grid.type_of_grid == 'hex', grid.type_of_grid == 'polar', grid.type_of_grid == '3d'
39
+
40
+ for cell in grid.each_cell():
41
+ neighbors = []
42
+ if cell.north:
43
+ neighbors.append(cell.north)
44
+ if cell.east:
45
+ neighbors.append(cell.east)
46
+ if _hex: # HexGrid support
47
+ if cell.northeast:
48
+ neighbors.append(cell.northeast)
49
+ elif cell.southeast:
50
+ neighbors.append(cell.southeast)
51
+ elif polar: # Polar support
52
+ if cell is grid[0,0]:
53
+ neighbors = cell.outward[0:2]
54
+ else:
55
+ if cell.column != 0:
56
+ neighbors.append(cell.ccw)
57
+ if cell.outward:
58
+ neighbors.append(cell.outward[0])
59
+
60
+ if three_d and cell.up:
61
+ neighbors.append(cell.up)
62
+
63
+ if len(neighbors) > 0:
64
+ neighbor = rand.choice(neighbors)
65
+ cell.link(neighbor)
@@ -0,0 +1,143 @@
1
+ from ..grids.grid import Grid
2
+ from ..cells.cell import Cell
3
+ import random as rand
4
+ from ..grid_not_supported_exception import GridNotSupportedException
5
+ import warnings
6
+
7
+ class _RowState:
8
+ def __init__(self, starting_set: int = 0):
9
+ self.cells_in_set = {}
10
+ self.set_for_cell = []
11
+ self.next_set = starting_set
12
+
13
+ def record(self, _set: int, cell: Cell) -> None:
14
+ while cell.column >= len(self.set_for_cell):
15
+ self.set_for_cell.append(None)
16
+
17
+ self.set_for_cell[cell.column] = _set
18
+ self.cells_in_set.setdefault(_set, [])
19
+ self.cells_in_set[_set].append(cell)
20
+
21
+ def set_for(self, cell: Cell) -> int:
22
+ if cell.column >= len(self.set_for_cell) or self.set_for_cell[cell.column] is None:
23
+ self.record(self.next_set, cell)
24
+ self.next_set += 1
25
+
26
+ return self.set_for_cell[cell.column]
27
+
28
+ def merge(self, winner: int, loser: int) -> None:
29
+ for cell in self.cells_in_set[loser]:
30
+ self.set_for_cell[cell.column] = winner
31
+ self.cells_in_set[winner].append(cell)
32
+
33
+ del self.cells_in_set[loser]
34
+
35
+ def _next(self):
36
+ return _RowState(self.next_set)
37
+
38
+ def each_set(self):
39
+ for set_, cells in self.cells_in_set.items():
40
+ yield set_, cells
41
+
42
+ def Ellers(grid: Grid) -> None:
43
+ '''
44
+ Performs Ellers algorithm on a given Grid in place.
45
+ Triangle grids not supported 3d and cube Grids are not perfect
46
+
47
+ Parameters:
48
+ grid (Grid)
49
+
50
+ Returns:
51
+ None, the grid is modified in place
52
+
53
+ Errors:
54
+ GridNotSupportedException if Grid is triangular
55
+
56
+ Warnings:
57
+ RuntimeWarning Ellers produced non-perfect mazes on 3d and cube grids
58
+
59
+ Example:
60
+ import mazepy as mp
61
+
62
+ grid = mp.grids.Grid(20,20)
63
+ mp.algorithms.Ellers(grid)
64
+ grid.show()
65
+ '''
66
+
67
+ if grid.type_of_grid == 'triangle':
68
+ raise GridNotSupportedException('Triangle Grids not compatible with Ellers')
69
+ _hex = grid.type_of_grid == 'hex'
70
+ polar = grid.type_of_grid == 'polar'
71
+ if threed := grid.type_of_grid == '3d':
72
+ warnings.warn('Ellers on 3d grids produces seperate 2d grids with no up/down connections', RuntimeWarning)
73
+ if grid.type_of_grid == 'cube':
74
+ warnings.warn('Ellers on a cube grid may not produce a perfect maze', RuntimeWarning)
75
+
76
+ if threed:
77
+ each_level = grid.each_level()
78
+ else:
79
+ each_level = [grid]
80
+
81
+ for level in each_level:
82
+ row_state = _RowState()
83
+ if threed:
84
+ rows = level
85
+ else:
86
+ rows = level.each_row()
87
+
88
+ for row in rows:
89
+ for cell in row:
90
+ if not _hex and not polar and not cell.west: continue
91
+ elif _hex and cell.column%2 == 0 and not cell.northwest: continue
92
+ elif polar and len(row) == 1: continue
93
+
94
+
95
+ _set = row_state.set_for(cell)
96
+ if not _hex and not polar:
97
+ prior_set = row_state.set_for(cell.west)
98
+ elif _hex:
99
+ prior_set = row_state.set_for(cell.southwest) if cell.column%2 == 1 else row_state.set_for(cell.northwest)
100
+ elif polar:
101
+ prior_set = row_state.set_for(cell.ccw)
102
+
103
+
104
+ if not polar and _set != prior_set and (cell.south is None or rand.randrange(2) == 0):
105
+ if not _hex and not polar:
106
+ cell.link(cell.west)
107
+ else:
108
+ if cell.column % 2 == 1:
109
+ cell.link(cell.southwest)
110
+ else:
111
+ cell.link(cell.northwest)
112
+ row_state.merge(prior_set, _set)
113
+
114
+ elif polar and _set != prior_set and (not cell.outward or rand.randrange(2) == 0):
115
+ cell.link(cell.ccw)
116
+ row_state.merge(prior_set, _set)
117
+
118
+ if row[0].south:
119
+ next_row = row_state._next()
120
+
121
+ for _, _list in row_state.each_set():
122
+ list2 = _list.copy()
123
+ rand.shuffle(list2)
124
+
125
+ for index, cell in enumerate(list2):
126
+ if index == 0 or rand.randrange(3) == 0:
127
+ cell.link(cell.south)
128
+ next_row.record(row_state.set_for(cell), cell.south)
129
+
130
+ elif polar and row[0].outward:
131
+ next_row = row_state._next()
132
+
133
+ for _, _list in row_state.each_set():
134
+ list2 = _list.copy()
135
+ rand.shuffle(list2)
136
+ for index, cell in enumerate(list2):
137
+ if index == 0 or rand.randrange(3) == 0:
138
+ cell2 = cell.outward[rand.randrange(len(cell.outward))]
139
+ cell.link(cell2)
140
+ next_row.record(row_state.set_for(cell), cell2)
141
+
142
+
143
+ row_state = next_row
@@ -0,0 +1,74 @@
1
+ from ..grids.grid import Grid
2
+ from ..grids.colored_grid import ColoredGrid
3
+ import random as rand
4
+ from itertools import product
5
+ from ..grid_not_supported_exception import GridNotSupportedException
6
+
7
+ def FractalTessalation(grid: Grid|None = None, times: int = 4, base: tuple[int]|str|None = None, end: tuple[int]|str|None = None) -> ColoredGrid|None:
8
+ '''
9
+ Performs fractal tesselation on an existing Grid or generates a Grid
10
+
11
+ Parameters:
12
+ grid (optional Grid)
13
+ times (optional int) = 4, how many iterations to perform
14
+ base (optional tuple[int]|str) PIL/pillow valid color for return grid
15
+ end (optional tuple[int]|str) PIL/pillow valid color for return grid
16
+
17
+ Returns:
18
+ ColoredGrid
19
+
20
+ Errors:
21
+ GridNotSupportedException if grid is not rectangular
22
+ '''
23
+ if grid is None:
24
+ grid = Grid(1, 1)
25
+ elif hasattr(grid, 'base'):
26
+ base = grid.base
27
+ end = grid.end
28
+
29
+ if grid.type_of_grid != 'regular':
30
+ raise GridNotSupportedException('Non-rectangular grids not compatible with Fractal Tessalation')
31
+
32
+ for i in range(times):
33
+ if base is not None and i == times - 1:
34
+ grid_new = ColoredGrid(grid.rows*2, grid.columns*2, base=base, end=end)
35
+ else:
36
+ grid_new = Grid(grid.rows*2, grid.columns*2)
37
+ for cell in grid.each_cell():
38
+ new_row, new_column = cell.row+grid.rows, cell.column+grid.columns
39
+ for row, col in product((cell.row, new_row), (cell.column, new_column)):
40
+ links = cell.links()
41
+ cell2 = grid_new[row, col]
42
+ if cell.north in links:
43
+ cell2.link(cell2.north)
44
+ if cell.east in links:
45
+ cell2.link(cell2.east)
46
+ if cell.south in links:
47
+ cell2.link(cell2.south)
48
+ if cell.west in links:
49
+ cell2.link(cell2.west)
50
+
51
+ exc_path = rand.randrange(2)
52
+ if exc_path == 0:
53
+ num1, num2, num3 = rand.randrange(grid.columns), rand.randrange(grid.columns), rand.randrange(grid.rows)
54
+ cell1 = grid_new[grid.rows, num1]
55
+ cell2 = grid_new[grid.rows, grid.columns+num2]
56
+ cell3 = grid_new[grid.rows*rand.randrange(2) + num3, grid.columns]
57
+
58
+ cell1.link(cell1.north)
59
+ cell2.link(cell2.north)
60
+ cell3.link(cell3.west)
61
+ else:
62
+ num1, num2, num3 = rand.randrange(grid.columns), rand.randrange(grid.rows), rand.randrange(grid.rows)
63
+ cell1 = grid_new[grid.rows, num1 + grid.columns*rand.randrange(2)]
64
+ cell2 = grid_new[num2, grid.columns]
65
+ cell3 = grid_new[grid.rows + num3, grid.columns]
66
+
67
+ cell1.link(cell1.north)
68
+ cell2.link(cell2.west)
69
+ cell3.link(cell3.west)
70
+
71
+ grid = grid_new
72
+
73
+ return grid_new
74
+
@@ -0,0 +1,40 @@
1
+ from ..grids.grid import Grid
2
+ from ..cells.cell import Cell
3
+ import random as rand
4
+ from typing import Callable
5
+
6
+ def GrowingTree(grid: Grid, func: Callable = lambda x: rand.choice(x), start_at: Cell|None = None) -> None:
7
+ '''
8
+ Performs the GrowingTree algorithm on a given Grid in place.
9
+ Any type of grid can be used
10
+
11
+ Parameters:
12
+ grid (Grid)
13
+ func (optional Callable) = lambda x: rand.choice(x), function to select next cell from visited list (list -> element from it)
14
+ start_at (optional Cell) = grid.random_cell(), which cell to start algorithm at
15
+
16
+ Returns:
17
+ None, the grid is modified in place
18
+
19
+ Example:
20
+ import mazepy as mp
21
+
22
+ grid = mp.grids.Grid(20,20)
23
+ mp.algorithms.GrowingGree(grid)
24
+ grid.show()
25
+ '''
26
+ if start_at is None:
27
+ start_at = grid.random_cell()
28
+
29
+ active = [start_at]
30
+
31
+ while active:
32
+ cell = func(active) # func takes a list and returns an element of it
33
+ availible_neighbors = [c for c in cell.neighbors() if not c.links()]
34
+
35
+ if availible_neighbors:
36
+ neighbor = rand.choice(availible_neighbors)
37
+ cell.link(neighbor)
38
+ active.append(neighbor)
39
+ else:
40
+ active.remove(cell)