Tetris World Model: Browser MaskGIT Dreams

Introduction
Discrete game world models keep shipping runnable toys, not just papers. Tetris world model (NullandKale / Alec Zinsli) is a ~2M-parameter spatiotemporal MaskGIT that predicts exact NES Tetris palette pixels from prior frames plus the controller — and the step-90,607 export runs entirely in the browser. The public ship landed on GitHub Oct 1 (NullandKale/tetris-world-model); the live player is at nullandkale.github.io/tetris-world-model. Every frame is model-generated; no emulator runs while you play.
What shipped
- Modality: action-conditioned discrete video world model for NES Tetris (exact palette indices, not a learned tokenizer)
- Open vs closed: open training + export code; browser ONNX graphs (
prefill.onnx~7 MB,step.onnx~9 MB) plus start context underweb/model/ - Where to run today: open the GitHub Pages demo (Chrome/Edge WebGPU; WASM fallback elsewhere), or clone and serve
web/locally afterscripts/export_onnx.py - One hard number: the published browser checkpoint is training step 90,607; on an RTX 3090 Chrome WebGPU path the docs clock a step at 14.4 ms (56 FPS play) after keeping the step graph on-GPU
Why makers should care
This sits in the same discrete-game lane as DashVMC, with a different contract: instead of dream-PPO for a live Geometry Dash agent, you get a playable NES Tetris dream you can drive with arrows / X·Z / Enter on any laptop that can load ONNX Runtime Web.
The recipe is Genie-style dynamics on exact frames:
- 16×16 tokens per frame — 256 tokens, palette-index embeddings, spatial then causal temporal blocks
- 64-frame window — covers Tetris’s slowest gravity timer (48 frames/drop at level 0)
- Controller conditioning — the button byte that produced frame t is embedded into that frame’s tokens
- Browser deploy —
prefillfills the KV cache from a real start context;stepemits the next frame and updated cache (GPU buffers stay on-device)
Training docs call out the usual exposure-bias stack: MaskGIT cosine masking, corrupted context, and scheduled-sampling rollouts so dreams do not melt after a few dozen frames. The Pages build freezes the checkpoint whose long dreams beat a later cooled-down step — a useful maker lesson when you export for demos.
Maker notes
git clone https://github.com/NullandKale/tetris-world-model
cd tetris-world-model
pip install -e '.[onnx]'
# Optional: re-export from a PyTorch checkpoint
# python scripts/export_onnx.py output/world_model_tetris_small/model_latest.pt
python -m http.server 8000 -d web
# then open http://localhost:8000 (or just use the Pages demo)Controls on the live page: ← → ↓ move/drop, X/Z rotate, Enter Start. Training itself still needs World NES plus your own Tetris (USA).nes ROM (TETRIS_ROM) — neither ships in the repo. The playable surface for readers is the exported ONNX demo, not the training loop.
Scope note: this is one deterministic NES title with a tiny MaskGIT, not an open-world video generator. Steal the exact-pixel + browser ONNX step/prefill pattern; do not expect Matrix-Game fidelity.
Conclusion
NullandKale’s Tetris world model is a same-day, click-to-play discrete world model: open code, shipped ONNX, and a GitHub Pages player that dreams NES Tetris from your buttons alone. For game-gen makers chasing runnable discrete stacks after DashVMC, this is the clean Tetris twin to try tonight.
—Titus
