Skip to main content

Game

Trait Game 

Source
pub trait Game {
    type State;
    type Action: PartialEq;
    type View;

    // Required methods
    fn new_initial_state(&self, seed: u64) -> Self::State;
    fn num_players(&self) -> usize;
    fn active_players(&self, state: &Self::State) -> ActivePlayers;
    fn legal_actions(
        &self,
        state: &Self::State,
        player: PlayerId,
    ) -> Vec<Self::Action>;
    fn apply(
        &self,
        state: &mut Self::State,
        player: PlayerId,
        action: Self::Action,
    );
    fn is_terminal(&self, state: &Self::State) -> bool;
    fn reward(&self, state: &Self::State, player: PlayerId) -> f64;
    fn view(&self, state: &Self::State, viewer: Option<PlayerId>) -> Self::View;

    // Provided methods
    fn is_legal(
        &self,
        state: &Self::State,
        player: PlayerId,
        action: &Self::Action,
    ) -> bool { ... }
    fn chance_outcomes(&self, state: &Self::State) -> Vec<(Self::Action, f64)> { ... }
    fn apply_cloned(
        &self,
        state: &Self::State,
        player: PlayerId,
        action: Self::Action,
    ) -> Result<Self::State, Error>
       where Self::State: Clone { ... }
    fn step_reward(&self, state: &Self::State, player: PlayerId) -> f64 { ... }
}
Expand description

A turn-based game defined as pure functions from state and action to new state.

Per-match configuration (player count, board size, variant rules) lives on the implementing value (&self), so Self::State stays lean and cheap to clone (cloning is the default backtracking primitive) and there is one home for num_players and variant flags. Everything is synchronous and side-effect-free; randomness comes from a generator stored inside the state.

Required Associated Types§

Source

type State

A full position in a match.

Source

type Action: PartialEq

A single decision. PartialEq powers the default Self::is_legal membership check; it is trivially derivable for the small enums and indices actions usually are.

Source

type View

What a player or spectator observes, produced by Self::view.

Required Methods§

Source

fn new_initial_state(&self, seed: u64) -> Self::State

Returns the initial position for a match, its generator seeded from seed.

Source

fn num_players(&self) -> usize

Returns the number of seats in this match: the fixed roster, seats 0..num_players, excluding the chance pseudo-player.

A constant property of the configured match, not a live count and not a capacity. It does not shrink when a player is eliminated (an eliminated seat simply stops appearing in Self::active_players and has no legal actions). “Who owes a decision right now” is Self::active_players; the seats valid for Self::reward and Self::legal_actions are 0..num_players.

Source

fn active_players(&self, state: &Self::State) -> ActivePlayers

Returns the players who owe a decision right now.

Empty during engine-only resolution, one for alternating play, many during simultaneous or secret phases. May contain PlayerId::CHANCE when a committed random outcome is pending.

Source

fn legal_actions( &self, state: &Self::State, player: PlayerId, ) -> Vec<Self::Action>

Returns the actions available to player at this decision point.

A full turn is a sequence of apply calls until Self::active_players changes; this enumerates one decision point, not a whole turn.

Source

fn apply(&self, state: &mut Self::State, player: PlayerId, action: Self::Action)

Advances state in place by applying player’s action.

Assumes the action is legal for an active player; callers that want checking use Self::apply_cloned. Draw any randomness from the generator inside state so the effect stays reproducible.

Source

fn is_terminal(&self, state: &Self::State) -> bool

Returns whether the match has ended.

Source

fn reward(&self, state: &Self::State, player: PlayerId) -> f64

Returns player’s terminal outcome as a single scalar (the minimal win/loss signal for search and RL). Meaningful only when Self::is_terminal holds; richer scoring belongs in public state.

Source

fn view(&self, state: &Self::State, viewer: Option<PlayerId>) -> Self::View

Returns what viewer is allowed to observe. None is a seatless spectator and observes the public projection only.

Provided Methods§

Returns whether action is legal for player right now.

Defaults to membership in Self::legal_actions. Override with a direct check for decision points whose legal set is too large to enumerate (arbitrary map targeting, payment combinatorics).

Source

fn chance_outcomes(&self, state: &Self::State) -> Vec<(Self::Action, f64)>

Returns the probability distribution over chance outcomes while PlayerId::CHANCE is active: each possible outcome action paired with its probability. The probabilities should sum to 1.

Defaults to uniform over legal_actions(state, CHANCE). Override for non-uniform chance (loaded dice, weighted decks). Mirrors OpenSpiel’s chance_outcomes. The committed outcome is chosen by a chance sampler (see sample_chance) using a generator owned by the driver, distinct from any per-state generator used for implicit rolls inside apply.

Returns a materialized Vec, not an iterator, because callers pass over it more than once — summing the weights and then sampling, or enumerating every outcome for expectiminimax. Chance branching is small, so the allocation is negligible (this matches OpenSpiel’s materialized ChanceOutcomes).

Source

fn apply_cloned( &self, state: &Self::State, player: PlayerId, action: Self::Action, ) -> Result<Self::State, Error>
where Self::State: Clone,

Returns a copy of state advanced by action, without mutating the original. The default backtracking primitive for search and tests.

§Errors

Returns Error::NotActive if player is not currently active, or Error::IllegalAction if the action is not legal for them.

Source

fn step_reward(&self, state: &Self::State, player: PlayerId) -> f64

Returns player’s immediate reward for the last step.

Defaults to 0 (all signal at the terminal). Override to give RL trainers a dense, per-step, per-player signal.

Implementors§