Jev Games
September 17, 2026 · View on GitHub
A visual lab where Jev plays multiple games. This is the next step after mario-jev: the same Jev controller style, a Zero-shot Lab UI, and a plugin split so new games and emulator platforms can be added without rewriting the loop.
Bundled titles:
| Game | Platform | How it runs |
|---|---|---|
| Super Mario Bros. | NES (nes-py) | gym-super-mario-bros (SMB1 RAM observations from mario-jev) |
| Kung Fu / Spartan X | NES (nes-py) | roms/kungfu.nes (or KUNGFU_NES); RAM map from the NES original |
| Doom | ViZDoom | Original E1M1 Hangar from roms/doom1.wad (shareware) or doom.wad; otherwise Freedoom (different first map) |
The model stays Jev. Code owns buttons, hold duration, and (for Mario) landing interrupts.
Setup
Python 3.13 via uv, frontend via bun.
uv sync
# TYPESAFE_API_KEY is already in .env for this checkout
cd frontend && bun install && bun run build && cd ..
Atari is no longer used for Kung Fu. Put a legally obtained NES kungfu.nes in roms/ (or set KUNGFU_NES). Doom uses original E1M1 Hangar when roms/doom1.wad (shareware) or doom.wad is present; otherwise ViZDoom's Freedoom Phase 1 (a different first map).
Visual lab
Two terminals:
uv run jev-games lab
cd frontend && bun run dev
Open http://127.0.0.1:5173. After bun run build, the API also serves frontend/dist at http://127.0.0.1:8000 (or JEV_GAMES_PORT).
- Run / F5 starts Jev (or the scripted baseline)
- Step / F10 takes one decision
- Reset / R restarts the episode
- Cartridges in the header switch Mario, Kung-Fu, and Doom
- History / Tape lists attempts; Replay re-runs recorded buttons on the emulator (Esc returns to live)
- Jev vs Scripted avoids spending API calls while you check the emulator
Every Jev decision is a paid TypeSafe request. Use Step or a short Run, and prefer Scripted until the picture and buttons look right.
Headless play
uv run jev-games play --game mario --policy scripted --decisions 20
uv run jev-games play --game kungfu --policy scripted --decisions 20
uv run jev-games play --game doom --policy scripted --decisions 20
uv run jev-games play --game mario --policy jev --decisions 10
Adding a game
- Pick or add a platform under
src/jev_games/platforms/(NES, Atari, Doom today). - Add
src/jev_games/games/<name>/game.pyimplementingGame:create_env,observe,questions,compose,scripted,advance. - Register it in
src/jev_games/catalog.py.
Adding another NES game
from jev_games.platforms.nes import make_nes_rom_env
env = make_nes_rom_env("roms/zelda.nes", action_button_lists)
ram = env.unwrapped.ram
Put a legally obtained .nes ROM in roms/, decode that game’s RAM, and write Jev questions the same way Mario does.
A new console (SNES, GB, …) is a new platform module with create_env / frame / memory access. Games should not import emulator libraries directly if the platform can own that.
Layout
src/jev_games/engine.py— run/step/reset worker, WebSocket snapshotssrc/jev_games/platforms/— emulator adapterssrc/jev_games/games/— per-title observations and Jev policiesfrontend/— Zero-shot Lab UI (inspired bydesign-concept.png)
uv run pytest
uv run ruff check src tests