Added Sidewinder Alg

This commit is contained in:
Kyler Olsen 2024-11-04 21:54:23 -07:00
parent 025f00f6aa
commit 2b505bf9a9
3 changed files with 172 additions and 9 deletions

21
main.py
View File

@ -6,7 +6,7 @@ import sys
pygame.init()
# Constants
CELL_SIZE = 10
# CELL_SIZE = 10
HIGHLIGHT_COLOR = (0, 0, 255) # Blue for highlighted cells
WALL_COLOR = (0, 0, 0) # Black for walls
PATH_COLOR = (255, 255, 255) # White for paths
@ -64,12 +64,19 @@ class MazeVisualizer:
pygame.quit()
sys.exit()
# my_maze = maze.RecursiveBacktracker(63)
# my_maze = maze.VectorWrapper(maze.OriginShift(32))
# my_maze = maze.VectorWrapper(maze.BinaryTree(32, bias=maze.VectorEnum.Up | maze.VectorEnum.Left))
# my_maze = maze.VectorWrapper(maze.BinaryTree(32, bias=maze.VectorEnum.Up | maze.VectorEnum.Right))
# my_maze = maze.VectorWrapper(maze.BinaryTree(32, bias=maze.VectorEnum.Down | maze.VectorEnum.Left))
my_maze = maze.VectorWrapper(maze.BinaryTree(32, bias=maze.VectorEnum.Down | maze.VectorEnum.Right))
CELL_SIZE = 20
MAZE_SIZE = 31
VEC_MAZE_SIZE = (MAZE_SIZE + 1) // 2
# my_maze = maze.RecursiveBacktracker(MAZE_SIZE)
# my_maze = maze.VectorWrapper(maze.OriginShift(VEC_MAZE_SIZE))
# my_maze = maze.VectorWrapper(maze.BinaryTree(VEC_MAZE_SIZE, bias=maze.VectorEnum.Up | maze.VectorEnum.Left))
# my_maze = maze.VectorWrapper(maze.BinaryTree(VEC_MAZE_SIZE, bias=maze.VectorEnum.Up | maze.VectorEnum.Right))
# my_maze = maze.VectorWrapper(maze.BinaryTree(VEC_MAZE_SIZE, bias=maze.VectorEnum.Down | maze.VectorEnum.Left))
# my_maze = maze.VectorWrapper(maze.BinaryTree(VEC_MAZE_SIZE, bias=maze.VectorEnum.Down | maze.VectorEnum.Right))
# my_maze = maze.Sidewinder(MAZE_SIZE, run_param=0.2)
my_maze = maze.Sidewinder(MAZE_SIZE, run_param=0.5)
# my_maze = maze.Sidewinder(MAZE_SIZE, run_param=0.8)
# for _ in range(512): my_maze.step()
# for _ in range(2048): my_maze.step()

158
maze.py
View File

@ -1,5 +1,4 @@
import abc, enum, random
from types import UnionType
class Maze(abc.ABC):
@ -351,3 +350,160 @@ class BinaryTree(VectorMaze):
neighbors.append((x,y + 1))
return neighbors
class Sidewinder(Maze):
__cells: list[list[bool]]
__run: list[tuple[int,int]]
__run_param: float
__start: VectorEnum
__width: int
__height: int
def __init__(
self,
width: int,
height: int | None = None,
*,
run_param: float = 0.5,
start: VectorEnum = VectorEnum.Up,
):
self.__width = width
self.__height = height or width
self.__cells = [list([False for _ in range(self.width)]) for _ in range(self.height)]
self.__start = start
self.__run_param = run_param
if self.__start == VectorEnum.Up:
self.__run = [(1,1)]
elif self.__start == VectorEnum.Down:
self.__run = [(self.width-2,self.height-2)]
elif self.__start == VectorEnum.Right:
self.__run = [(self.width-2,self.height-2)]
elif self.__start == VectorEnum.Left:
self.__run = [(1,1)]
else:
self.__run = []
self.__cells[self.highlighted[1]][self.highlighted[0]] = True # type: ignore
@property
def width(self) -> int:
return self.__width
@property
def height(self) -> int:
return self.__height
@property
def highlighted(self) -> tuple[int,int] | None:
if self.__run: return self.__run[-1]
else: return None
def __getitem__(self, index: tuple[int,int]) -> bool:
return self.__cells[index[1]][index[0]]
def step(self) -> bool:
if self.highlighted is not None:
hx, hy = self.highlighted
if hx - 2 >= 0 and self.__start == VectorEnum.Down:
cell = (hx - 2, hy)
carve = hy + 2 >= self.height or random.random() > self.__run_param
elif hx + 2 < self.width and self.__start == VectorEnum.Up:
cell = (hx + 2, hy)
carve = hy - 2 < 0 or random.random() > self.__run_param
elif hy - 2 >= 0 and self.__start == VectorEnum.Right:
cell = (hx, hy - 2)
carve = hx + 2 >= self.width or random.random() > self.__run_param
elif hy + 2 < self.height and self.__start == VectorEnum.Left:
cell = (hx, hy + 2)
carve = hx - 2 < 0 or random.random() > self.__run_param
else:
cell = None
carve = False
if cell is not None and carve:
x = (hx + cell[0]) // 2
y = (hy + cell[1]) // 2
self.__cells[y][x] = True
self.__cells[cell[1]][cell[0]] = True
self.__run.append(cell)
else:
hx, hy = self.highlighted
sx, sy = self.__run[random.randint(0,len(self.__run)-1)]
self.__run.clear()
if self.__start == VectorEnum.Down:
if hx - 2 >= 0:
x, y = (hx - 2, hy)
self.__run.append((x,y))
self.__cells[y][x] = True
else:
if hy - 2 >= 0:
x, y = (self.width - 2, hy - 2)
self.__run.append((x,y))
self.__cells[y][x] = True
if sy + 2 < self.height: cell = (sx, sy + 2)
else: cell = None
elif self.__start == VectorEnum.Up:
if hx + 2 < self.width:
x, y = (hx + 2, hy)
self.__run.append((x,y))
self.__cells[y][x] = True
else:
if hy + 2 < self.height:
x, y = (1, hy + 2)
self.__run.append((x,y))
self.__cells[y][x] = True
if sy - 2 >= 0: cell = (sx, sy - 2)
else: cell = None
elif self.__start == VectorEnum.Right:
if hy - 2 >= 0:
x, y = (hx, hy - 2)
self.__run.append((x,y))
self.__cells[y][x] = True
else:
if hx - 2 >= 0:
x, y = (hx - 2, self.height - 2)
self.__run.append((x,y))
self.__cells[y][x] = True
if sx + 2 < self.height: cell = (sx + 2, sy)
else: cell = None
elif self.__start == VectorEnum.Left:
if hy + 2 < self.height:
x, y = (hx, hy + 2)
self.__run.append((x,y))
self.__cells[y][x] = True
else:
if hx + 2 < self.width:
x, y = (hx + 2, 1)
self.__run.append((x,y))
self.__cells[y][x] = True
if sx - 2 >= 0: cell = (sx - 2, sy)
else: cell = None
if cell is not None:
x = (sx + cell[0]) // 2
y = (sy + cell[1]) // 2
self.__cells[y][x] = True
return True
else: return False
def _neighbors(self, index: tuple[int,int]) -> list[tuple[int,int]]:
neighbors: list[tuple[int,int]] = []
x, y = index
# if x - 2 >= 0:
# neighbors.append((x - 2,y))
if x + 2 < self.width:
neighbors.append((x + 2,y))
# if y - 2 >= 0:
# neighbors.append((x,y - 2))
# if y + 2 < self.height:
# neighbors.append((x,y + 2))
return neighbors

View File

@ -1,7 +1,7 @@
+ Recursive Backtracking
+ Origin Shift
+ Binary Tree
- Sidewinder
+ Sidewinder
- Recursive Division
- Binary Division
- Prim's Algorithm