Compare commits

..

2 Commits

Author SHA1 Message Date
ilmabura
2af3d6c2e7 Last milestone completed
Completed the project. I wanted to replace the player with a penguin, but it didn't fit the maze, so I kept it as an '>'.
It shows where you begin and where you need to go to finish, and each game is a different maze. I thought this was very difficult and i needed to learn how to make a maze, I was not prepared for that.
2025-12-07 16:17:56 -05:00
ilmabura
e2273773eb created the maze walls and collision detection
the hardest part was creating a maze with a solution. I realized I didn't know how to do that and had to google how to create a maze.
Once I had a maze generator, I was unsure of whether there was a solution to it. Figuring that out took some time. Then I changed the look to be more digestible. I chose a maze game because I thought it would be simple, but it didn't feel simple.
2025-12-07 12:32:24 -05:00
7 changed files with 131 additions and 10 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,17 +1,87 @@
import random
from retro.game import Game from retro.game import Game
from player import Player from player import Player
from wall import Wall
from markers import StartMarker, FinishMarker
def generate_maze_grid(width, height):
"""
Generate a 'perfect' maze on a width x height grid.
1 = wall, 0 = passage.
"""
grid = [[1 for _ in range(width)] for _ in range(height)]
for y in range(1, height - 1, 2):
for x in range(1, width - 1, 2):
grid[y][x] = 0
visited = set()
def dfs(cx, cy):
visited.add((cx, cy))
directions = [(2, 0), (-2, 0), (0, 2), (0, -2)]
random.shuffle(directions)
for dx, dy in directions:
nx, ny = cx + dx, cy + dy
if 1 <= nx < width - 1 and 1 <= ny < height - 1 and (nx, ny) not in visited:
wall_x = cx + dx // 2
wall_y = cy + dy // 2
grid[wall_y][wall_x] = 0
dfs(nx, ny)
dfs(1, 1)
return grid
def create_maze_walls(board_size):
width, height = board_size
grid = generate_maze_grid(width, height)
center_x = (width // 2) | 1
center_y = (height // 2) | 1
grid[center_y][center_x] = 0
end_position = (center_x, center_y)
wall_positions = []
for y in range(height):
for x in range(width):
if grid[y][x] == 1:
wall_positions.append((x, y))
walls = [Wall(pos) for pos in wall_positions]
return walls, end_position
def main(): def main():
board_size = (100, 40) board_size = (100, 40)
player = Player(board_size) walls, end_position = create_maze_walls(board_size)
print("Exit (goal) will be around:", end_position)
start_position = (1, 1)
player = Player(board_size, end_position)
start_marker = StartMarker(start_position)
finish_marker = FinishMarker(end_position)
state = { state = {
"win": False, "win": False,
"message": "",
} }
game = Game( game = Game(
agents=[player], agents=[
start_marker,
finish_marker,
player,
] + walls,
state=state, state=state,
board_size=board_size, board_size=board_size,
debug=False, debug=False,

24
markers.py Normal file
View File

@@ -0,0 +1,24 @@
class StartMarker:
"""
Labels the start of the maze with 's'.
"""
character = "S"
color= "red_on_white"
blocks_movement = False
def __init__(self, position):
# position is a tuple (x, y)
self.position = position
class FinishMarker:
"""
Labels the finish of the maze with 'f'.
"""
character = "F"
color = "red_on_black"
blocks_movement = False
def __init__(self, position):
# position is a tuple (x, y)
self.position = position

View File

@@ -1,21 +1,36 @@
class Player: class Player:
""" """
Player agent for Escape the Maze. Player agent for Escape the Maze.
Moves one step at a time using the arrow keys. Moves one step at a time using the arrow keys.
Ends the game when it reaches the goal position.
""" """
name = "player" name = "player"
character = "🐧" # Penguin icon character = ">"
def __init__(self, board_size): def __init__(self, board_size, goal_position):
# Start near the top-left corner # Start near the top-left corner
width, height = board_size width, height = board_size
self.position = (1, 1) self.position = (1, 1)
self.goal_position = goal_position
def can_move_to(self, position, game):
"""
Returns True if there is no blocking agent (e.g., Wall) on this tile.
Non-blocking agents (like start/finish markers) are ignored.
"""
for agent in game.agents:
agent_pos = getattr(agent, "position", None)
if agent_pos == position:
if getattr(agent, "blocks_movement", False):
return False
return True
def handle_keystroke(self, keystroke, game): def handle_keystroke(self, keystroke, game):
""" """
Called once for each key pressed since the last turn. Called for each key pressed since the last turn.
Moves the player using the arrow keys. Moves the player using the arrow keys and checks for win.
""" """
x, y = self.position x, y = self.position
new_position = None new_position = None
@@ -29,10 +44,13 @@ class Player:
elif keystroke.name == "KEY_RIGHT": elif keystroke.name == "KEY_RIGHT":
new_position = (x + 1, y) new_position = (x + 1, y)
if new_position is None: if new_position is None:
return return
if game.on_board(new_position) and self.can_move_to(new_position, game):
self.position = new_position
if game.on_board(new_position) and game.is_empty(new_position): if self.position == self.goal_position:
self.position = new_position game.state["win"] = True
game.state["message"] = "Congratulations! You've escaped the maze!"
game.end()

9
wall.py Normal file
View File

@@ -0,0 +1,9 @@
class Wall:
"""
A simple wall tile. It just sits on the board and blocks movement.
"""
character = ""
blocks_movement = True
def __init__(self, position):
# position is a tuple (x, y)
self.position = position