use crate::tree::node::RewardVal; use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hash; /// Trait for the game state used in MCTS /// /// When leveraging MCTS for your game, you must implement this trait to provide /// the specifics for your game. pub trait GameState: Clone + Debug { /// The type of actions that can be taken in the game type Action: Action; /// The type of players in the game type Player: Player; /// Returns if the game state is terminal, i.e. the game is over /// /// A game state is terminal when no other actions are possible. This can be /// the result of a player winning, a draw, or because some other conditions /// have been met leading to a game with no further possible states. /// /// The default implementation returns True if `get_legal_actions()` returns /// an empty list. It is recommended to override this for a more efficient /// implementation if possible. fn is_terminal(&self) -> bool { let actions = self.get_legal_actions(); actions.len() == 0 } /// Returns the list of legal actions for the game state /// /// This method must return all possible actions that can be made from the /// current game state. fn get_legal_actions(&self) -> Vec; /// Returns the game state resulting from applying the action to the state /// /// This function should not modify the current state directly, and /// instead should modify a copy of the state and return that. fn state_after_action(&self, action: &Self::Action) -> Self; /// Returns the reward from the perspective of the given player for the game state /// /// This evaluates the current state from the perspective of the given player, and /// returns the reward indicating how good of a result the given state is for the /// player. /// /// This is used in the MCTS backpropagation and simulation phases to evaluate /// the value of a given node in the search tree. /// /// A general rule of thumb for values are: /// - 1.0 => a win for the player /// - 0.5 => a draw /// - 0.0 => a loss for the player /// /// Other values can be used for relative wins or losses fn reward_for_player(&self, player: &Self::Player) -> RewardVal; /// Returns the rewards for all players at the current state fn rewards_for_players(&self) -> HashMap; /// Returns the player whose turn it is for the game state /// /// This is used for evaluating the state, so for simultaneous games /// consider the "current player" as the one from whose perspective we are /// evaluating the game state from fn get_current_player(&self) -> &Self::Player; } /// Trait used for actions that can be taken in a game /// /// An action is dependent upon the specific game being defined, and includes /// things like moves, attacks, and other decisions. pub trait Action: Clone + Debug {} /// Trait used for players participating in a game pub trait Player: Clone + Debug + PartialEq + Eq + Hash {} /// Convenience implemnentation of a Player for usize impl Player for usize {} /// Convenience implemnentation of a Player for char impl Player for char {} /// Convenience implemnentation of a Player for String impl Player for String {}