Trait Game

Source
pub trait Game: Sized {
    type S;
    type M: Copy;

    // Required methods
    fn generate_moves(state: &Self::S, moves: &mut Vec<Self::M>);
    fn apply(state: &mut Self::S, m: Self::M) -> Option<Self::S>;
    fn get_winner(state: &Self::S) -> Option<Winner>;

    // Provided methods
    fn undo(_state: &mut Self::S, _m: Self::M) { ... }
    fn zobrist_hash(_state: &Self::S) -> u64 { ... }
    fn null_move(_state: &Self::S) -> Option<Self::M> { ... }
    fn notation(_state: &Self::S, _move: Self::M) -> Option<String> { ... }
    fn table_index(_: Self::M) -> u16 { ... }
    fn max_table_index() -> u16 { ... }
}
Expand description

Defines the rules for a two-player, perfect-knowledge game.

A game ties together types for the state and moves, generates the possible moves from a particular state, and determines whether a state is terminal.

This is meant to be defined on an empty newtype so that a game engine can be implemented in a separate crate without having to know about these minimax traits.

Required Associated Types§

Source

type S

The type of the game state.

Source

type M: Copy

The type of game moves.

Required Methods§

Source

fn generate_moves(state: &Self::S, moves: &mut Vec<Self::M>)

Generate moves at the given state.

Source

fn apply(state: &mut Self::S, m: Self::M) -> Option<Self::S>

Apply a move to get a new state.

If the method returns a new state, the caller should use that. If the method returns None, the caller should use the original. This enables two different implementation strategies:

  1. Games with large state that want to update in place.
struct BigBoard([u8; 4096]);
struct BigMove(u16);
fn apply(state: &mut BigBoard, m: BigMove) -> Option<BigBoard> {
    state.0[m.0 as usize] += 1;
    None
}
fn undo(state: &mut BigBoard, m: BigMove) {
    state.0[m.0 as usize] -= 1;
}
  1. Games with small state that don’t want to implement undo.
struct SmallBoard(u64);
struct SmallMove(u8);
fn apply(state: &mut SmallBoard, m: SmallMove) -> Option<SmallBoard> {
    Some(SmallBoard(state.0 | (1<<m.0)))
}
Source

fn get_winner(state: &Self::S) -> Option<Winner>

Returns Some(PlayerJustMoved) or Some(PlayerToMove) if there’s a winner, Some(Draw) if the state is terminal without a winner, and None if the state is non-terminal.

Provided Methods§

Source

fn undo(_state: &mut Self::S, _m: Self::M)

Undo mutation done in apply, if any.

Source

fn zobrist_hash(_state: &Self::S) -> u64

Hash of the game state. Expected to be pre-calculated and cheaply updated with each apply.

Source

fn null_move(_state: &Self::S) -> Option<Self::M>

Optional method to return a move that does not change the board state. This does not need to be a legal move from this position, but it is used in some strategies to reject a position early if even passing gives a good position for the opponent.

Source

fn notation(_state: &Self::S, _move: Self::M) -> Option<String>

Return a human-readable notation for this move in this game state.

Source

fn table_index(_: Self::M) -> u16

Return a small index for this move for position-independent tables.

Source

fn max_table_index() -> u16

Maximum index value.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§