Skip to content
Juozas Žilys
← All projects

ASCII Psychomath Adventure

An educational ASCII adventure game that teaches mathematical concepts through procedural generation and interactive exploration — built on MonoGame with a serious test suite.

Role
Solo build
Period
2024 – present
Repo
github

C# 14 · .NET 10 · MonoGame 3.8 · xUnit

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. IScene with 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 EventBus with 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.