From f9c59ff052481f5462b09d6ed1683db0015de420 Mon Sep 17 00:00:00 2001 From: ajurna Date: Wed, 15 Sep 2021 15:14:36 +0100 Subject: [PATCH] added maze generator --- .gitignore | 1 + agent.py | 0 game.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ maze.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+) create mode 100644 agent.py create mode 100644 game.py create mode 100644 maze.py diff --git a/.gitignore b/.gitignore index 7f7cccc..a1b41dd 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ docs/_build/ # PyBuilder target/ +.idea/ \ No newline at end of file diff --git a/agent.py b/agent.py new file mode 100644 index 0000000..e69de29 diff --git a/game.py b/game.py new file mode 100644 index 0000000..6a9c56f --- /dev/null +++ b/game.py @@ -0,0 +1,83 @@ +import sys +from itertools import product + +import pygame +from pygame.locals import * +from maze import Maze + +pygame.init() +vec = pygame.math.Vector2 # 2 for two dimensional + +HEIGHT = 450 +WIDTH = 400 + +FPS = 60 + +FramePerSec = pygame.time.Clock() + +displaysurface = pygame.display.set_mode((WIDTH, HEIGHT)) +pygame.display.set_caption("Game") + +SCREEN_BUFFER = 10 +MAZE_SIZE = 15 +GRID_SIZE = 25 + + +class Player(pygame.sprite.Sprite): + def __init__(self): + super().__init__() + self.surf = pygame.Surface((30, 30)) + self.surf.fill((0, 255, 0)) + self.rect = self.surf.get_rect(center=(10, 420)) + + +class MazeWall(pygame.sprite.Sprite): + def __init__(self, wall): + wall_width = 2 + super().__init__() + start_cell, end_cell = wall + x,y = start_cell + vertical = start_cell[1] == end_cell[1] + if vertical: + self.surf = pygame.Surface((wall_width, GRID_SIZE)) + else: + self.surf = pygame.Surface((GRID_SIZE, wall_width)) + self.surf.fill((0, 0, 255)) + if vertical: + self.rect = self.surf.get_rect(midtop=((x+1) * GRID_SIZE + SCREEN_BUFFER, y * GRID_SIZE + SCREEN_BUFFER)) + else: + self.rect = self.surf.get_rect(midleft=(x * GRID_SIZE + SCREEN_BUFFER, (y + 1) * GRID_SIZE + SCREEN_BUFFER)) + + +all_sprites = pygame.sprite.Group() + + +maze_sprites = pygame.sprite.Group() + +maze = Maze(MAZE_SIZE, MAZE_SIZE) + +for wall in maze.walls: + wall_sprite = MazeWall(wall) + maze_sprites.add(wall_sprite) + + +while True: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + # wipe buffer + displaysurface.fill((0, 0, 0)) + # draw border + pygame.draw.rect(displaysurface, (255, 0, 0), + pygame.Rect((SCREEN_BUFFER, SCREEN_BUFFER, MAZE_SIZE * GRID_SIZE, MAZE_SIZE * GRID_SIZE)), 2) + pygame.draw.circle(displaysurface, (0, 255, 0), (25, 25), GRID_SIZE / 3) + + # for entity in all_sprites: + # displaysurface.blit(entity.surf, entity.rect) + for entity in maze_sprites: + displaysurface.blit(entity.surf, entity.rect) + + + pygame.display.update() + FramePerSec.tick(FPS) \ No newline at end of file diff --git a/maze.py b/maze.py new file mode 100644 index 0000000..5439dee --- /dev/null +++ b/maze.py @@ -0,0 +1,75 @@ +import random +from itertools import product +from typing import Tuple, Set, Union, Any, List, NamedTuple +from pprint import pprint + + +class Cell(NamedTuple): + x: int + y: int + + +class Wall(NamedTuple): + first_cell: Cell + second_cell: Cell + + +class Maze: + def __init__(self, width: int, height: int): + self.cells = set(Cell(*c) for c in product(range(width), range(height))) + self.maze = dict() + for cell in self.cells: + self.maze[cell] = self.get_neighbours(cell) + self.walls = self.get_walls() + self.generate_maze() + + def get_neighbours(self, cell: Cell) -> Set[Cell]: + diffs = ((0, 1), (0, -1), (1, 0), (-1, 0)) + return set(Cell(cell.x + x, cell.y + y) for x, y in diffs if Cell(cell.x + x, cell.y + y) in self.cells) + + def get_walls(self) -> Set[Wall]: + walls = set() + for cell in self.cells: + walls.update(set(Wall(*sorted([cell, c])) for c in self.maze[cell])) + return walls + + def generate_maze(self) -> None: + visited = set() + unvisited = list(self.cells) + node = random.choice(unvisited) + visited.add(node) + unvisited.remove(node) + while unvisited: + random_neighbour = random.choice(list(self.maze[node])) + if random_neighbour not in visited: + self.walls.remove(Wall(*sorted([node, random_neighbour]))) + visited.add(random_neighbour) + try: + unvisited.remove(random_neighbour) + except ValueError: + pass + node = random_neighbour + + def generate_prim_maze(self) -> None: + visited = set() + node = random.choice(list(self.cells)) + visited.add(node) + removed_walls = set() + wall_list = [w for w in self.walls if node in w] + while wall_list: + random_wall = random.choice(wall_list) + wall_list.remove(random_wall) + cell1, cell2 = random_wall + if (cell1 in visited) != (cell2 in visited): + removed_walls.add(random_wall) + self.walls.remove(random_wall) + visited.add(cell1) + visited.add(cell2) + wall_list.extend( + set(w for w in self.walls if (cell1 in w) or (cell2 in w)).difference(removed_walls) + ) + + +if __name__ == "__main__": + maze = Maze(3, 3) + pprint(maze.walls)