pub trait Game: Clone {
type Move: Clone;
type Iter<'a>: Iterator<Item = Self::Move> + 'a
where Self: 'a;
type MoveError;
type Player: Player;
const STATE_TYPE: Option<StateType>;
// Required methods
fn move_count(&self) -> usize;
fn max_moves(&self) -> Option<usize>;
fn make_move(&mut self, m: &Self::Move) -> Result<(), Self::MoveError>;
fn possible_moves(&self) -> Self::Iter<'_>;
fn state(&self) -> GameState<Self::Player>;
fn player(&self) -> Self::Player;
// Provided method
fn find_immediately_resolvable_game(
&self,
) -> Result<Option<Self>, Self::MoveError> { ... }
}
Expand description
Represents a combinatorial game.
A game has three distinct variants per game:
- Game play type: Normal, Misere, Other
- Game partiality type: Impartial, Partizan
- Game player count: >0
Required Associated Constants§
const STATE_TYPE: Option<StateType>
Required Associated Types§
sourcetype Iter<'a>: Iterator<Item = Self::Move> + 'a
where
Self: 'a
type Iter<'a>: Iterator<Item = Self::Move> + 'a where Self: 'a
The iterator type for possible moves.
type MoveError
type Player: Player
Required Methods§
sourcefn move_count(&self) -> usize
fn move_count(&self) -> usize
Returns the amount of moves that have been played
sourcefn possible_moves(&self) -> Self::Iter<'_>
fn possible_moves(&self) -> Self::Iter<'_>
Returns an iterator of all possible moves.
If possible, this function should “guess” what the best moves are first. For example, if this is for tic tac toe, it should give the middle move first. Since “better” moves would be found first, this permits more alpha/beta cutoffs.
sourcefn state(&self) -> GameState<Self::Player>
fn state(&self) -> GameState<Self::Player>
Returns the current state of the game. Used for verifying initialization and is commonly called.
If Self::STATE_TYPE
isn’t None,
the following implementation can be used:
fn state(&self) -> GameState<Self::Player> {
Self::STATE_TYPE.unwrap().state(self)
}
sourcefn player(&self) -> Self::Player
fn player(&self) -> Self::Player
Returns the player whose turn it is. The implementation of this should be similar to either
use game_solver::game::ZeroSumPlayer;
fn player(&self) -> Self::Player {
if game.move_count % 2 == 0 {
ZeroSumPlayer::One
} else {
ZeroSumPlayer::Two
}
}
or
use game_solver::game::NPlayer;
fn player(&self) -> Self::Player {
NPlayer(game.move_count % game.num_players)
}
depending on the type of game.
However, no implementation is provided because this does not keep track of the move count.
Provided Methods§
sourcefn find_immediately_resolvable_game(
&self,
) -> Result<Option<Self>, Self::MoveError>
fn find_immediately_resolvable_game( &self, ) -> Result<Option<Self>, Self::MoveError>
Returns a reachable game in one move.
Rather, this function asks if there exists some game in the possible games set which has a resolvable, positive or negative, outcome.
This function must act in the Next player’s best interest. Positive games should have highest priority, then tied games, then lost games. Exact order of what game is returned doesn’t matter past its outcome equivalency, as the score is dependent on move count.
(If this function returns a losing game when a positive game exists in the set of immediately resolvable games, that is a violation of this function’s contract).
This function’s default implementation is quite slow, and it’s encouraged to use a custom implementation.