Jev plays Budokai 3
How a small judgment model pilots a 2004 fighting game, and how the harness turns its choices into controller inputs.
Scope
TypeSafe's Jev model plays player 1 in Dragon Ball Z: Budokai 3 (PAL) inside a control build of the PCSX2 emulator. Code reads the fight from emulator memory and describes it in plain labels. Jev picks one tactic, or the next input of a combo. Code turns that pick into frame-exact controller input.
How a decision is made
The harness reads the fight, describes it and presents named options to Jev. Jev scores those options. The harness checks which choice can run, executes it and records the result.
Read
Health, ki, position, action codes and move IDs.
Read from emulator memory.
Describe
Plain labels for distance, openings and the last exchange.
Only information Jev can use.
Jev picks
Score the available tactics with a probability for each.
The model’s role.
Mask
Filter choices by reach, ki cost and timing windows.
Highest probability × weight wins.
Play
Execute frame-exact controller input, checking every four frames.
A defensive reflex can interrupt.
Settle
Wait until the fighter can act, then write the trace row.
Return to Read for the next turn.
The trace row records the state before, the probabilities Jev gave, the tactic that actually ran, and the health change on both sides. Replaying the pad inputs from the checkpoint reproduces the match exactly.
When the tactic that ran differs from Jev's pick, because its pick was masked, the row records both. The score shown for a decision is always the probability Jev gave the tactic that actually ran, or nothing when there is none. A rule-only stop never gets a made-up score.
What Jev sees
Jev never sees pixels or raw memory. It receives a short description built from about a dozen verified memory fields: both fighters' health and ki, their current action, the distance between them, which tactics are available right now, and what the last tactic dealt and took.
Three things keep this honest:
- Every field is verified. Each memory address in the map was confirmed by frame-by-frame diffs before it was used. Unmapped states are passed to Jev as "another action (code N)", not guessed.
- The description is the same for every strategy. Strategy files change weights, legality rules and the string list. They never change what Jev is told about the fight.
- Hints are labelled as hints. When a rule wants to steer Jev, such as "fire the finisher", it says so in the opening text. Jev can still choose otherwise.
One inference is made in code, not read: the opponent's Hyper Mode. No memory flag has been found for it, so the pilot infers it from three consecutive ki drops and ends it at the breather codes. That inference is named in the description as an inference.
The options Jev receives
Jev chooses from named options, not an open-ended request to play the game. Each tactical option has a what description and a not_for warning. These explain the action, its cost or purpose, and situations where it is a poor choice.
One tactical option, as defined in the harness
block
- what
- Hold guard. Reduces damage and builds ki while blocking, but builds fatigue.
- not_for
- Idle or distant opponents; long stretches of blocking under cancel pressure.
Other options include sidestep, dash in, back off, throw and Kamehameha. Alongside these descriptions, Jev receives the current fight state and which tactics are available now.
The question changes with the decision. A tactical choice uses action descriptions. A combo continuation or follow-up uses a smaller set of named options with a description for each, including a choice to stop. Jev judges the options it is given; the harness defines the choices and executes the inputs.
Jev returns a selected option and a probability for each option. The harness applies legality rules and strategy weights, then executes the highest-scoring legal choice. Those rules and weights belong to the harness, not Jev.
Defensive reflexes
While a tactic runs, code checks the opponent every four frames. When it recognises the start of a super, a grab, a charged guard break or a ki-blast volley, it stops the tactic and answers. For supers, Jev chooses the defence and sees the measured cost of each. For the faster threats, the answer is a fixed reflex, because there is no time for a model call.
Fixed reflexes cover grabs, charged guard breaks and ki-blast volleys. The harness can only execute them when the fighter is free to act.
Definitions
The terms used on this page:
- Decision
- One turn of the loop: one description sent to Jev, one tactic played, one trace row. A match has a few hundred.
- Tactic
- A named action Jev can choose, such as block, sidestep, dash in, a combo opener, or Kamehameha. Code turns a tactic into pad input.
- Score
The probability Jev gave the tactic that actually ran. When the executed tactic differs from Jev's pick, this is the executed tactic's probability, or blank if there is none.
score=pJev(tactic that ran)- Played choice
Among the tactics that pass the legality rules, the one with the highest probability times its strategy weight. A weight of 1 is neutral, 0 bans the tactic.
played=argmax over legal t ofp(t) × w(t)- Reflex
- A fixed answer to a recognised threat, run by code without a model call. Each was chosen by probing every candidate input from a checkpoint cut just before the threat.
- Checkpoint
- A full emulator save state. The harness can restore it to replay the same fight state.
- Trace
- One JSON row per decision: state before, Jev's probabilities, the tactic that ran, contact records, junctions, and the health change. The trace preserves what Jev chose and what the harness executed.
- Replay tape
- The pad inputs of a match, frame by frame. Played back from the checkpoint with no model calls, it must end on the same health values as the live match, and the clean video is cut from that playback.
- Strategy
- A YAML file of tactic weights, legality rules, reflex gates and the string list. It never changes what Jev is told. Each trace names its strategy and file hash.