Problem
I wanted a single project to practice the things enterprise day-job work doesn’t give me: pure game architecture, procedural content generation, and a level of test coverage that borders on absurd. The theme — teaching mathematical concepts through ASCII exploration — came from wanting the game’s visual language to be the math it’s explaining.
What I built
An ASCII adventure game on MonoGame, C# 14 / .NET 10, cross-platform (Linux, Windows, macOS, Android, iOS). The game is scene-based, event-driven, procedurally generated, and — unusually for an indie game — covered by a test suite roughly twice the size of the source.
- ~703 source files, ~1,493 test files. Ratio is the point. Testing procedural generation (Wave Function Collapse, Perlin noise, Markov-chain dialogue) and math visualizations (fractals, attractors, chaos systems) as afterthoughts is how you end up with silent regressions nobody notices for weeks. Tests aren’t optional here.
- Scene state machine with 32+ scenes.
IScenewith lifecycle hooks (Initialize,OnEnter,OnExit,OnSuspend,OnResume) and a manager that handles transitions, suspension, and resumption properly — menus, overworld, combat, puzzle scenes, several pure-math visualization scenes. - Event-driven systems layer (90+ systems). Centralized
EventBuswith priority-based subscription, event filtering, one-time subscriptions, queued processing for frame consistency, and event history tracking for debugging. - Result pattern for error handling. Operations that can fail return
Result<T>instead of throwing. Font loading, asset operations, and config loading all use the same shape. - Service location via
GameContext. Testable, injectable, boring — in the good way.
Interesting bits
- Procedural generation is where tests earn their keep. A breaking change to Perlin noise parameters doesn’t crash — it just silently generates a slightly worse world for every subsequent seed. A golden-output test suite catches this immediately. Same for Wave Function Collapse constraint satisfaction: if one tile adjacency rule breaks, you want to know on the next build, not during playtest.
- The math visualization scenes are the game’s thesis. Mandelbrot zoom, strange attractors, prime-number sieves — rendered in ASCII at fixed 80-column width, animated in real time, playable as game spaces. The player walks through math instead of reading about it.
- Accessibility as a first-class system. Cognitive-load tracking, font scaling, color-blind-safe palette fallbacks, and text-to-speech integration. Not tacked on late — its own folder from the start.
- Cross-platform via MonoGame instead of Unity. Smaller runtime, full C# ecosystem access, no editor-vs-code friction. Target platforms include mobile (Android / iOS); the same codebase builds for all of them.