Roguelike Game Engine
Complete dungeon-based roguelike in C/C++ with procedural generation, Dijkstra pathfinding for intelligent NPC behavior, and persistent save/load mechanics.
The Challenge
Build a complete game engine from scratch in C/C++: dungeon generation, NPC AI, player mechanics, save/load system, all rendered in a terminal. The capstone project required deep systems thinking: memory management, algorithmic efficiency, and architecture that supports extensibility.
No game engines, no graphics libraries just raw systems programming. Com S 327 final project.
Your Role
Game Engine Architecture
Designed modular engine with clear separation: game state, rendering, AI, physics. Extensible architecture allows adding new features without rewriting core systems.
Procedural Dungeon Generation
Implemented recursive room generation ensuring playable dungeons. Configured room sizes, corridors, spawn points. Every dungeon is guaranteed solvable.
Pathfinding & AI
Built Dijkstra's algorithm for intelligent enemy pathfinding. Monsters can navigate obstacles and hunt the player. Handles both tunneling and non-tunneling enemies.
Persistence & Serialization
Implemented binary save/load system preserving game state: dungeon layout, enemy positions, player inventory. Fast loading, minimal file size.
Technical Architecture
Layered architecture: Game State → Logic Layer → Rendering → I/O. Each layer communicates through well-defined interfaces.
Game Logic
Core Systems
- Player mechanics
- Combat system
- Equipment management
- Turn-based gameplay
AI & Pathfinding
Enemy Behavior
- Dijkstra's algorithm
- Monster states
- Line-of-sight
- Difficulty scaling
I/O & Persistence
Data Management
- Ncurses rendering
- Keyboard input
- Save/load system
- File serialization
Key Technical Decisions
1. Dijkstra's Algorithm Over A*
Both solve pathfinding, but Dijkstra is simpler to implement and sufficient for small dungeons. A* would be overkill.
- Why Dijkstra: Guarantees shortest path, computationally simpler than A*
- Benefit: Believable NPC movement without complex heuristics
- Constraint: Doesn't scale to massive maps, but dungeons are small
2. Turn-Based Over Real-Time
Real-time roguelikes require sophisticated input handling and frame-perfect gameplay. Turn-based is simpler and classic roguelike style.
- Why turn-based: Reduces complexity, matches roguelike tradition
- Benefit: No frame-rate dependencies, clean logic
3. Binary Serialization for Saves
Could use JSON, but binary is faster and more compact. Given game runs in terminal, file size matters.
- Speed: Binary I/O 10× faster than parsing JSON
- Size: ~5KB save vs. ~50KB JSON
- Trade-off: Not human-readable, but simpler for binary data
4. Ncurses for Terminal Rendering
Terminal game constraint. Ncurses abstracts platform differences and provides color, cursor control, etc.
- Portable: Works on Linux, macOS, Windows
- Color support: Limited but sufficient for roguelike
What I Learned
1. Low-Level Programming Teaches Discipline
No frameworks, no abstractions. Memory management, pointer arithmetic, algorithmic complexity all matter. Learned to write efficient code.
2. Pathfinding is Fundamental
Dijkstra, A*, BFS these algorithms appear everywhere. Understanding them deeply is essential for game/AI development.
3. Testing Saves Time
Procedural generation is tricky easy to create unplayable dungeons. Automated testing caught edge cases early.
4. Systems Thinking Scales
Modular design meant adding features (new enemy types, items, dungeon obstacles) was easy. Architecture matters.
Let's talk
Interested in game development, algorithms, or systems programming? Let's connect.