State

Trait State 

Source
pub trait State: Sized {
    type Action: Clone;

    // Required methods
    fn fingerprint(&self) -> u64;
    fn whose_turn(&self) -> u8;
    fn is_terminal(&self) -> bool;
    fn apply(&self, action: &Self::Action) -> Self;
}
Expand description

A trait representing the state.

This trait defines the core interface that a game-specific state must implement.

§Core Concepts

§Fingerprinting

A state must provide a unique fingerprint (hash) that can be used for:

  • Transposition tables in game tree search
  • Duplicate position detection
  • State caching and memoization

§Turn Management

The trait tracks which player should move next, enabling:

  • Alternating play enforcement
  • Player-specific evaluation functions
  • Turn-based game logic

§State Transitions

Game states can store references to expected responses, allowing:

  • Pre-computed move sequences
  • Principal variation storage
  • Game tree navigation

§Examples


#[derive(Clone, Default)]
struct MyAction;

#[derive(Clone, Copy)]
struct MyGameState {
    board: [u8; 64],
    current_player: PlayerId,
    game_over: bool,
    // other game-specific fields...
}

impl State for MyGameState {
   type Action = MyAction;
    fn fingerprint(&self) -> u64 {
        // Generate unique hash for this position
        // Implementation depends on game specifics
        42 // placeholder
    }

    fn whose_turn(&self) -> u8 {
        self.current_player as u8
    }

    fn is_terminal(&self) -> bool {
        self.game_over
    }

    fn apply(&self, _action: &MyAction) -> Self {
        MyGameState {
            board: self.board,
            current_player: self.current_player.other(),
            game_over: false,
        }
    }
}

Required Associated Types§

Source

type Action: Clone

The type representing actions/moves in this game

Required Methods§

Source

fn fingerprint(&self) -> u64

Returns a unique fingerprint (hash) for this state.

The fingerprint must be statistically unique across all possible game states to avoid hash collisions in transposition tables and state caches. Identical game positions must always produce identical fingerprints.

§Implementation Requirements
  • Deterministic: Same position always produces same fingerprint
  • Collision-resistant: Different positions should produce different and uncorrelated fingerprints
  • Fast: Called frequently during game tree search
  • Position-dependent: Only depends on the current state and independent of move history.
§Returns

A 64-bit unsigned integer representing the unique fingerprint

§Examples
let state = create_initial_state();
let fingerprint = state.fingerprint();

// Same position should produce same fingerprint
let same_state = create_initial_state();
assert_eq!(fingerprint, same_state.fingerprint());
Source

fn whose_turn(&self) -> u8

Returns the ID of the player whose turn it is to move.

§Returns

The id of the player of the player who should move next

§Examples
let state = MyGameState { current_player: PlayerId::ALICE };
match state.whose_turn() {
    0 => println!("Alice to move"), // PlayerId::ALICE as u8
    1 => println!("Bob to move"),   // PlayerId::BOB as u8
    _ => unreachable!(),
}
Source

fn is_terminal(&self) -> bool

Checks if the game cannot continue.

§Returns

true if the game cannot continue, false otherwise.

§Examples
let state = MyGameState { game_is_over: true };
assert!(state.is_terminal());
Source

fn apply(&self, action: &Self::Action) -> Self

Applies an action to the current state, returning a new state as a result of the action.

This method creates a new state by applying the given action to the current state. The original state remains unchanged (immutable transformation).

§Arguments
  • action - The action to apply to the current state
§Returns

A new state representing the position after applying the action

§Examples

let initial_state = MyGameState {
    current_player: PlayerId::ALICE,
    move_count: 0,
    game_over: false
};
let action = MyAction { move_type: "play_tile".to_string() };

let new_state = initial_state.apply(&action);

// State should be updated
assert_eq!(new_state.whose_turn(), PlayerId::BOB as u8);
assert_ne!(new_state.fingerprint(), initial_state.fingerprint());

// Original state unchanged
assert_eq!(initial_state.whose_turn(), PlayerId::ALICE as u8);

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§