Skip to content

Replays

GameRunner records every action it applies, including random fallback actions, in runner.replay, a Replay. Write it to a gzipped JSON file that a viewer can read without the Python engine:

from tyrant import read_replay, write_replay

await runner.run()
write_replay(runner.replay, "game.json.gz")
data = read_replay("game.json.gz")

replay_dict returns the same data without writing a file.

File format

The file holds the setup with every hidden role, then one entry per applied action:

{
  "version": 2,
  "settings": {"player_count": 7, "discussion_enabled": false,
               "discussion_rounds": 2, "fascist_track": ["none", "investigate_loyalty", ...]},
  "players": [{"uid": 3, "seat": 0, "role": "hitler", "party": "fascist"}, ...],
  "initial": { <snapshot> },
  "steps": [
    {"index": 0, "uid": 3,
     "action": {"type": "nominate", "target_uid": 5},
     "fallback": false,
     "events": [{"type": "nomination", "president_uid": 3, "chancellor_uid": 5}],
     "knowledge": [],
     "state": { <snapshot> }}
  ],
  "result": {"winner": "liberal", "condition": "liberal_policies"}
}

Each step lists the events and private knowledge its action produced. fallback is true when the agent failed every attempt and the runner played a random legal action for it, so a step with fallback: false was the agent's own choice. Version 1 files have no fallback field and can't tell the two apart. Actions leave out description and message; speech text is in the step's speech event. result is null if the game has not ended.

Snapshots

Each state is a complete board snapshot: phase, president, chancellor, previous_president, previous_chancellor, alive, liberal_policies, fascist_policies, election_tracker, draw_pile and discard_pile (counts), hand, votes, active_power, and discussion (null or {context, round, rounds, speaker}). A viewer can jump straight to any step without replaying the rules.