Skip to content

pjperez/moon-below

Repository files navigation

Moon Below

A generative horror adventure running entirely on the Nintendo Game Boy.

Moon Below contains a small transformer that generates narration token by token from the current game state. The world, puzzles, threat, and endings are deterministic. The wording is generated locally inside the cartridge.

No server. No API. No runtime sentence table.

Moon Below title, gameplay, and ML proof

Download the release candidate · How it works · Build it · What proof mode proves

The game

You wake beneath a ruined observatory during an eclipse. Before morning, reach the Moon Gate and decide what comes through—or what remains below.

The observatory has 14 locations, ten important objects, three materially different routes, and six deterministic endings. Its Warden hunts sound rather than following a fixed room script: loud actions change its target and movement, while darkness, flooding, fuel, corruption, mechanisms, and inventory interact with the route you take.

Play slowly. Listen before committing to noisy machinery. Light helps you read the observatory, but it is limited. Replays expose different routes, discoveries, wording, and consequences without changing the underlying world rules.

Controls

  • D-pad — move through the two-column action grid.
  • A — choose an action or continue generated prologue/ending text.
  • SELECT — open readable inventory, condition, and clue status.
  • START — open ML context proof from gameplay.
  • B — return from status/proof, or return gameplay to the title.

The ROM is Game Boy-compatible. Current performance and screenshots are measured under PyBoy DMG timing; original-hardware validation is still pending.

The technical idea

The game engine owns truth: rooms, items, puzzles, Warden movement, resources, and ending predicates. After a valid action it encodes the resulting state as a nine-token structured prompt. A one-layer quantized transformer consumes that prompt and generates up to ten visible tokens plus EOS autoregressively.

Semantic masks remove impossible vocabulary for the current state. They do not contain ordered phrases or completed sentences. Model logits still rank the allowed next tokens, and a persistent cartridge PRNG samples among model-scored candidates. A different seed can therefore change valid wording for the same state; a changed state changes the contextual candidate surface.

Game state → 9 prompt tokens → transformer → semantic mask
           → seeded sampling → generated words → Game Boy tiles

Verified release metrics

Property Production value
Parameters 15,840
Vocabulary 232 tokens
Context 20 tokens
Structured prompt 9 tokens
Visible generation up to 10 tokens plus EOS
Average inference 1.784 s/token
Worst inference 1.892 s/token
Static WRAM 4,487 bytes
Bank 0 headroom 1,671 bytes
ROM size 131,072 bytes
Model fingerprint E4757CDAC4FD154C
ROM SHA-256 9606843EF6F5E19C0985D6D7332FFE3845C095CADD159107890400204F448B30

The 2 KiB Bank 0 preference is advisory; the release passes its 1 KiB hard gate. See benchmarks for timing and memory methodology.

Is this just choosing canned sentences?

No complete runtime narration sentences are stored in the ROM.

  • The transformer computes logits for every generated position.
  • Seeded sampling selects among model-scored valid tokens.
  • Masks remove words that would contradict the deterministic state.
  • Masks are unordered token sets plus grammatical constraints, not sentence templates or ordered phrase tables.
  • Exact Python/native/Game Boy traces verify the same logits, attention, and sampled tokens.
  • The ROM audit scans for all reference narrations and known sentence-table symbols and fails if it finds them.

Examples captured by the release test:

Same state, different seeds:
soft sound remains under the cellar .
in the cellar your breath answers water .

Changed state:
iron steps answer in the cellar .

Press START during gameplay to see the exact challenge state, model fingerprint, seed, active mask size, candidates, selected token, and attention checksum used by production inference.

Build and verify

Requirements are pinned and documented in reproducibility.md. With GBDK-2020 4.5.0 available through GBDK_HOME or PATH:

make rom
make test
make verify

On Windows use mingw32-make and, if needed, PYTHON=python.

make rom regenerates world tables, the dataset, model headers, banked model storage, prefix projections, and semantic masks before linking gb/moon-below.gb. make verify starts from deleted generated C artifacts, links twice to prove byte reproducibility, executes all game/ML/ROM checks, captures media, scans public files, and builds the release archive.

The committed 96-epoch model is a versioned release artifact. Reproducing its 92-epoch training plus four-epoch fine-tune is documented separately and is not silently performed by a normal ROM build.

Repository map

  • adventure/game/ — deterministic engine, dataset, training, model, masks.
  • gb/src/ — game-owned Game Boy runtime snapshot, engine, UI, generated data.
  • native/ — desktop integer reference used for exact parity.
  • train/ — shared integer graph/export helpers inherited from DMGFormer.
  • tests/ — world, route, engine, narration, native, and model gates.
  • tools/ — clean build, audits, emulator verification, media, and packaging.
  • docs/ — player guide, architecture, model card, proof, and limitations.
  • releases/ — generated release archive and checksums.

Moon Below builds on DMGFormer, the reusable transformer runtime and research project. The runtime code needed by the game is included here, so a clean checkout never needs the original repository.

Citation

@software{perez2026moonbelow,
  author  = {Pedro Perez},
  title   = {Moon Below: A Generative Transformer Adventure for Game Boy},
  year    = {2026},
  version = {1.0.0-rc1},
  url     = {https://github.com/pjperez/moon-below}
}

License

Project-authored code is MIT licensed. The model, dataset, and visual assets have explicit MIT statements under LICENSES/. Toolchains are not vendored; their notices are in THIRD_PARTY_NOTICES.md.

About

Generative horror adventure with a quantized transformer running locally in a Game Boy-compatible ROM.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors