Skip to content

Engine

The game loop, legal move routing, state rendering and replays.

GameRunner

Plays a game by asking agents for actions until it ends.

Each iteration, every agent with legal actions is asked at the same time, with the state scrubbed for that agent. A failed attempt is retried, and after max_retries failed retries the runner plays a random legal action for the agent.

Attributes:

Name Type Description
state

The current, unscrubbed game state.

replay

Every action applied so far.

agents

Each agent, keyed by UID.

max_retries

Retries allowed after an agent's first failed attempt.

timeout

Seconds allowed for each attempt, or None for no limit.

rng

Random generator that picks fallback actions.

faults tuple[AgentFault, ...]

Every failed attempt, in order.

__init__

__init__(
    agents: Sequence[Agent],
    initial_state: GameState | None = None,
    seed: int | None = None,
    roles: Mapping[int, Role] | None = None,
    shuffle_players: bool = True,
    discussion_enabled: bool = False,
    discussion_rounds: int = 2,
    max_retries: int = 2,
    timeout: float | None = 120.0,
)

Sets up the runner and, unless initial_state is given, a new game.

Parameters:

Name Type Description Default
agents Sequence[Agent]

The players. Each agent's uid becomes a player UID.

required
initial_state GameState | None

A state to start from instead of a new game.

None
seed int | None

Seed for the new game and for fallback actions, or None for random.

None
roles Mapping[int, Role] | None

Fixed role for each UID, or None to deal roles at random.

None
shuffle_players bool

Whether to shuffle the seating order.

True
discussion_enabled bool

Whether to hold discussions.

False
discussion_rounds int

How many times the table goes around in each discussion.

2
max_retries int

Retries allowed after an agent's first failed attempt.

2
timeout float | None

Seconds allowed for each attempt, or None for no limit.

120.0

Raises:

Type Description
TyrantError

If the settings are not valid for a new game.

run async

run() -> GameState

Plays the game until it ends.

Returns:

Type Description
GameState

The final, unscrubbed game state.

Raises:

Type Description
TyrantError

If no player has a legal action.

render_dict

render_dict(state: GameState, viewer_uid: int) -> dict

Returns a JSON-serializable view of the state, scrubbed for the given viewer.

Parameters:

Name Type Description Default
state GameState

The game state to render; it is scrubbed for the viewer first.

required
viewer_uid int

UID of the player who will see the view.

required

Returns:

Type Description
dict

A dict with viewer, players, board, government, turn, timeline and knowledge sections.

Raises:

Type Description
TyrantError

If the viewer is not in the game.

render_text

render_text(state: GameState, viewer_uid: int) -> str

Returns a prompt-ready Markdown view of the state, scrubbed for the given viewer.

Parameters:

Name Type Description Default
state GameState

The game state to render; it is scrubbed for the viewer first.

required
viewer_uid int

UID of the player who will see the view.

required

Returns:

Type Description
str

Markdown with sections for the viewer, the players, private knowledge, the timeline, the board, the government and the current turn.

Raises:

Type Description
TyrantError

If the viewer is not in the game.

read_replay

read_replay(path: str | Path) -> dict

Reads a gzipped JSON replay file into plain dicts.

Parameters:

Name Type Description Default
path str | Path

The file to read.

required

Returns:

Type Description
dict

The replay in the format returned by replay_dict.

replay_dict

replay_dict(replay: Replay) -> dict

Returns a JSON-serializable replay with a full board snapshot after every step.

Parameters:

Name Type Description Default
replay Replay

The replay to convert.

required

Returns:

Type Description
dict

Plain JSON values holding the settings, every player's hidden role, the initial snapshot, one entry per step and the result.

write_replay

write_replay(replay: Replay, path: str | Path) -> None

Writes the replay to a gzipped JSON file.

Parameters:

Name Type Description Default
replay Replay

The replay to write.

required
path str | Path

The file to write.

required

apply_action

apply_action(
    state: GameState, action: Action, player_uid: int
) -> GameState

Applies a player's action to the game.

Parameters:

Name Type Description Default
state GameState

The full game state.

required
action Action

The action to apply, usually one returned by get_legal_actions.

required
player_uid int

UID of the acting player.

required

Returns:

Type Description
GameState

The new game state.

Raises:

Type Description
InvalidMoveError

If the action is not legal in this state.

TyrantError

If the action type is not recognized.

get_legal_actions(
    state: GameState, player_uid: int
) -> tuple[Action, ...]

Lists the actions a player may take now.

Parameters:

Name Type Description Default
state GameState

The current game state.

required
player_uid int

UID of the player.

required

Returns:

Type Description
tuple[Action, ...]

The legal actions, or an empty tuple if the player is dead or not due to act.

Raises:

Type Description
TyrantError

If the player is not in the game.