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§
Required Methods§
sourcefn generate_moves(state: &Self::S, moves: &mut Vec<Self::M>)
fn generate_moves(state: &Self::S, moves: &mut Vec<Self::M>)
Generate moves at the given state.
sourcefn apply(state: &mut Self::S, m: Self::M) -> Option<Self::S>
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:
- 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;
}
- 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)))
}
sourcefn get_winner(state: &Self::S) -> Option<Winner>
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§
sourcefn zobrist_hash(_state: &Self::S) -> u64
fn zobrist_hash(_state: &Self::S) -> u64
Hash of the game state. Expected to be pre-calculated and cheaply updated with each apply.
sourcefn null_move(_state: &Self::S) -> Option<Self::M>
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.
sourcefn notation(_state: &Self::S, _move: Self::M) -> Option<String>
fn notation(_state: &Self::S, _move: Self::M) -> Option<String>
Return a human-readable notation for this move in this game state.
sourcefn table_index(_: Self::M) -> u16
fn table_index(_: Self::M) -> u16
Return a small index for this move for position-independent tables.
sourcefn max_table_index() -> u16
fn max_table_index() -> u16
Maximum index value.