Recursive AI

Record and replay a game

All onegame recipes

Record a run of a C# game to a file, replay it later and check every tick’s state hash, and find the first tick where a code change makes the game behave differently.

A recording holds the starting state and every command. Because the simulation is deterministic, replaying it rebuilds the same world tick by tick, and onegame replay compares the state hash at each one.

Record the pick-apples scenario while it runs:

Terminal
onegame run --headless -- --scenario scenarios/pick-apples.yaml --record run.ogrp --artifacts .
Text
PASS pick-apples (39 ms, tick 302, hash 9a447aae324c764b)
1 passed, 0 failed

Replay it:

Terminal
onegame replay run.ogrp
onegame replay run.ogrp --json
Text
replay identical: 302 ticks, 3 commands, final hash 9a447aae324c764b
{"ok":true,"identical":true,"ticks":302,"commands":3,"finalHash":"9a447aae324c764b","segments":1}

The three commands are the two clicks on Pick and the refused Pick(99). Refused commands are recorded too.

Find where a change diverges

Change the simulation, here apples growing every 20 ticks instead of every 30, and replay the same file:

Text
replay DIFFERS (segment 0 of 1): Checkpoint at tick 20 (last good 19): 2 part(s) of the state differ.
Text
{"ok":false,"identical":false,"ticks":302,"commands":3,"tick":20,"expected":"36918dc7c358bda6","actual":"7915daf0d5a403bb","finalHash":"7915daf0d5a403bb","segments":1,"segment":0}

The replay exits 1 and names the first tick that differs and both hashes. Put the change back and the replay is identical again. This makes a recording a regression test for the simulation: keep the file, replay it in CI, and any change that alters what a player saw fails at the exact tick.

Good to know

  • --record and --scenario are options of the game, so they go after --. --artifacts . puts output files in the current folder.
  • A recording starts from a snapshot, so a bug caught in a long session can be replayed after the fix without replaying the whole session.
  • A recording is a session of segments. Anything that replaces the world (a scenario reset:, fixture: or snapshot:, a set:) ends one segment and starts the next, and the replay reports segments.
  • A recording with no ticks and no commands replays as identical: false, because nothing was compared.
  • In C#: game.StartSessionRecording(), RecordingFile.Save(session, path) and game.Replay(session). Determinism.Replay in Test a game from C# records and replays a scripted run in one call.

More in Driving a game.