This project has been created as part of the 42 curriculum by afeizi, mseghrou.
A-Maze-ing is a Python project that generates, solves, and interactively visualizes mazes in the terminal. The program takes a configuration file as input, generates a maze using a chosen algorithm (DFS or Prim), finds the shortest path from entry to exit using DFS, writes the result to an output file in hexadecimal format, and optionally launches an interactive ncurses-based visualizer.
When the maze is large enough, a stylized "42" pattern is embedded in the center, formed by fully closed (isolated) cells.
Features:
- Two generation algorithms:
dfs(recursive backtracker) andprim - Perfect or imperfect maze generation (with or without loops)
- Shortest path solver (DFS)
- Interactive terminal visualizer with color schemes, path toggle, and regeneration
- Reusable
MazeGeneratorclass available as a pip-installable package (mazegen)
Repository layout:
a_maze_ing.py— Main CLI: parses config, generates, solves, writes output, launches visualizerconfig_parser.py— Safe config file parser and validatorgenerator.py— Maze generation logic (bit-flag cells), embeds "42" patternsolver.py— DFS solver returning direction steps and path cellsvisualizer.py— Ncurses-based interactive maze visualizerconfig.txt— Default configuration filepyproject.toml— Build config for the reusablemazegenpackageMakefile— Automates install, run, debug, lint, clean, build
Requirements: Python 3.10+, a terminal that supports curses (Terminal.app, iTerm2, most Linux terminals).
Install dependencies:
make installRun:
make run
# or directly:
python3 a_maze_ing.py config.txtWhen prompted, enter Y to open the interactive visualizer. Controls:
| Key | Action |
|---|---|
R |
Regenerate a new maze |
P |
Toggle show/hide solution path |
C |
Cycle color schemes |
Q |
Quit |
Lint:
make lintClean:
make cleanThe configuration file uses KEY=VALUE pairs, one per line. Lines starting with # are ignored.
WIDTH=19 # Maze width (number of cells, positive integer)
HEIGHT=15 # Maze height (number of cells, positive integer)
ENTRY=0,0 # Entry coordinates x,y (0-indexed, inside bounds)
EXIT=18,14 # Exit coordinates x,y (0-indexed, inside bounds, different from ENTRY)
PERFECT=false # true = perfect maze (single path); false = loops added
OUTPUT_FILE=maze.txt # Path for the output maze file
ALGORITHM=prim # Generation algorithm: dfs or prim
All keys are mandatory. ENTRY and EXIT must be different and within maze bounds.
Output file format: Each row of the maze is written as a string of hexadecimal digits (one digit per cell), encoding which walls are closed using 4 bits:
| Bit | Direction |
|---|---|
| 1 (LSB) | North |
| 2 | East |
| 4 | South |
| 8 | West |
After an empty line, three metadata lines follow: entry coordinates, exit coordinates, and the shortest path as a string of N, E, S, W characters.
Two algorithms are implemented:
DFS (Recursive Backtracker) — Uses a stack-based depth-first traversal, carving passages by visiting unvisited neighbors randomly. It produces mazes with long, winding corridors. It was chosen because it is simple to implement correctly, guarantees a perfect maze, and produces aesthetically interesting results.
Prim's Algorithm — Grows the maze from a starting cell by maintaining a list of frontier walls and randomly selecting from them. It tends to produce mazes with more branches and a more organic structure.
The MazeGenerator class in generator.py is packaged as a standalone pip-installable module named mazegen.
Install from the built package:
pip install mazegen-1.0.0-py3-none-any.whlBuild the package from source:
pip install poetry
python -m poetry build
# or:
make buildBasic usage example:
from generator import MazeGenerator
# Instantiate with custom parameters
gen = MazeGenerator(
width=19,
height=15,
entry=(0, 0),
exit=(18, 14),
perfect=True, # Perfect maze (single path)
seed=42, # Optional: for reproducibility
algorithm="dfs" # "dfs" or "prim"
)
# Generate the maze
grid = gen.generate()
# Access the grid (list of lists of ints, bit-flag wall encoding)
print(grid)
# Access the "42" pattern cells
pattern_cells = gen.get_pattern_cells()
# Solve the maze
from solver import MazeSolver
solver = MazeSolver(grid, entry=(0, 0), exit=(18, 14))
solution = solver.solve() # List of directions: ['E', 'S', ...]
path_cells = solver.get_path_cells(solution) # List of (x, y) coordinatesCustom parameters:
width,height— Maze dimensions (positive integers)entry,exit— Tuples(x, y)for entry and exit coordinatesperfect—Truefor a perfect maze,Falseto add random loopsseed— Integer seed for reproducible generation (optional)algorithm—"dfs"or"prim"
The grid is a List[List[int]] where each integer encodes walls as 4 bits (N=1, E=2, S=4, W=8). A set bit means the wall is closed.
Team members: afeizi, mseghrou
Roles:
- afeizi — Maze generator logic, algorithm implementation, "42" pattern, reusable package
- mseghrou — Config parser, solver (DFS), visualizer (ncurses), Makefile, README
Planning: The project was split into four components: config parsing, generation, solving, and visualization. We started with a working CLI pipeline (parse → generate → solve → write), then added the visualizer last. We initially planned only DFS, but added Prim as a bonus after the core was stable. The "42" pattern integration took more time than expected due to connectivity constraints.
What worked well:
- The bit-flag wall encoding kept generation and visualization logic clean and consistent
- DFS for the solver was straightforward and guaranteed the shortest path
- Separating concerns into distinct modules made testing easier
What could be improved:
- Seed support is parsed but not yet in the default
config.txt - The visualizer could support mouse input
- More unit tests would improve confidence during refactors
Tools used: Python 3.13, VSCode, Git, flake8, mypy, poetry (for package build), Claude AI (for review and README structure)
AI usage: Claude (Anthropic) was used to review the project structure against subject requirements, identify missing README sections, and help format the final README. All code was written and reviewed by the team members.
- If the visualizer shows "Terminal too small", resize your terminal window
- If colors look off:
export TERM=xterm-256color - On macOS, run in Terminal.app or iTerm2, not IDE embedded consoles