Skip to content

JaffarPlus User & Developer Manual

JaffarPlus is a high-performance, general-purpose best-first search optimizer, specially tailored for producing tool-assisted speedruns (TAS). You give it a game (through an emulation core), a description of which inputs are allowed, and a reward function that says what "better" means; it searches the reachable game states in parallel and returns the best input sequence it can find (for a TAS: usually the fastest path to a win).

This manual is the missing piece between the project README (what JaffarPlus is and which cores it supports) and the 700+ example configurations under examples/: it explains how to drive the tool and why it behaves the way it does.

How this manual is organized

The chapters are ordered for a first-time reader. The first half is for users (people who run searches and write configurations); the second half is for contributors (people who extend the engine or add new games).

# Chapter Audience What you'll learn
1 Getting Started User Build JaffarPlus, run your first search with no ROM required, read the output, replay a solution.
2 Configuration Reference User Every section and key of a .jaffar file: type, default, meaning.
3 Rules, Conditions & Rewards User How to steer the search: properties, conditions, reward actions and magnets.
4 Search Concepts & Tuning User / Contributor How best-first search, state hashing, and the NUMA/threading model work — and which knobs to turn.
5 Adding a Game or Emulator Contributor Register a new game or emulator (now fully automatic) and expose its properties and actions.
6 Tooling Reference User / Contributor jaffar, jaffar-player, headless screenshots, video rendering, and environment overrides.
7 Understanding the Output User What every field of jaffar's per-step report means, and how to read a run at a glance.
8 Jaffar Player Interface User jaffar-player's interactive commands, options, and common workflows: replay, navigate, extract a save-state, screenshots.

An auto-generated C++ API reference (Doxygen) covers the engine internals in source/; see Adding a Game or Emulator for the entry points.

The 60-second tour

# 1. Build with the ROM-free test core
meson setup build -Demulator=TestEmulator
ninja -C build

# 2. Validate a configuration without running a search
./build/jaffar docs/examples/gridwalker.jaffar --dryRun

# 3. Run the search (finds the optimal 8-move path across a 5x5 grid)
./build/jaffar docs/examples/gridwalker.jaffar

# 4. Replay the solution it found
./build/jaffar-player docs/examples/gridwalker.jaffar /tmp/jaffar.gridwalker.best.sol --reproduce --unattended --exitOnEnd

Everything above runs with no game ROM and no emulator submodule — it uses the in-repo TestEmulator. Start with Getting Started for the full walkthrough.

A note on accuracy

The configuration keys documented here are validated against the source in continuous integration by two checks (run via ninja test, suite docs):

  • Forward (DocsExamples): every example configuration under docs/examples/ must pass jaffar --dryRun, so a renamed or removed key breaks the example — and the build.
  • Backward (DocsConfigReference): a coverage check confirms that every configuration key the engine core (source/*.hpp) reads is documented in the configuration reference, and flags documented core keys that have disappeared from the code. (Emulator- and game-specific keys live in emulators/ and games/ and are documented as patterns rather than checked key-by-key.)

If you find a discrepancy, it is a bug in the docs or the check — please report it.