import numpy as np import random NORTH, SOUTH, EAST, WEST = 0, 1, 2, 3 _DX = [0, 0, 1, -1] # col delta for N,S,E,W _DY = [-1, 1, 0, 0] # row delta _OPP = [1, 0, 3, 2] # opposite direction def generate(rows: int, cols: int, seed: int | None = None) -> np.ndarray: rng = random.Random(seed) grid = np.full((rows, cols), 0b1111, dtype=np.uint8) visited = np.zeros((rows, cols), dtype=bool) start_r, start_c = 0, 0 visited[start_r, start_c] = True stack = [(start_r, start_c)] while stack: row, col = stack[-1] directions = [NORTH, SOUTH, EAST, WEST] rng.shuffle(directions) moved = False for d in directions: nr = row + _DY[d] nc = col + _DX[d] if 0 <= nr < rows and 0 <= nc < cols and not visited[nr, nc]: # Carve passage: clear wall bit on current cell grid[row, col] &= (~(1 << d)) & 0xFF # Clear opposite wall bit on neighbour grid[nr, nc] &= (~(1 << _OPP[d])) & 0xFF visited[nr, nc] = True stack.append((nr, nc)) moved = True break if not moved: stack.pop() return grid def get_walls(grid: np.ndarray, row: int, col: int) -> tuple[bool, bool, bool, bool]: cell = int(grid[row, col]) wall_n = float((cell >> NORTH) & 1) wall_s = float((cell >> SOUTH) & 1) wall_e = float((cell >> EAST) & 1) wall_w = float((cell >> WEST) & 1) return (wall_n, wall_s, wall_e, wall_w) def is_passable(grid: np.ndarray, row: int, col: int, direction: int) -> bool: cell = int(grid[row, col]) return not bool((cell >> direction) & 1) def render_static(grid: np.ndarray, cfg) -> 'pygame.Surface': import pygame rows, cols = grid.shape cell_size = getattr(cfg, 'cell_size', 32) wall_thickness = getattr(cfg, 'wall_thickness', 2) width = cols * cell_size height = rows * cell_size surface = pygame.Surface((width, height)) surface.fill((15, 15, 20)) wall_color = (40, 40, 50) t = wall_thickness for row in range(rows): for col in range(cols): x = col * cell_size y = row * cell_size cell = int(grid[row, col]) # North wall if (cell >> NORTH) & 1: pygame.draw.rect(surface, wall_color, (x, y, cell_size, t)) # South wall if (cell >> SOUTH) & 1: pygame.draw.rect(surface, wall_color, (x, y + cell_size - t, cell_size, t)) # East wall if (cell >> EAST) & 1: pygame.draw.rect(surface, wall_color, (x + cell_size - t, y, t, cell_size)) # West wall if (cell >> WEST) & 1: pygame.draw.rect(surface, wall_color, (x, y, t, cell_size)) # Start cell (0, 0): small cyan circle start_cx = cell_size // 2 start_cy = cell_size // 2 start_radius = max(2, cell_size // 6) pygame.draw.circle(surface, (0, 220, 220), (start_cx, start_cy), start_radius) # Goal cell (rows-1, cols-1): green filled circle goal_x = (cols - 1) * cell_size + cell_size // 2 goal_y = (rows - 1) * cell_size + cell_size // 2 goal_radius = max(3, cell_size // 4) pygame.draw.circle(surface, (0, 200, 80), (goal_x, goal_y), goal_radius) return surface