Skip to main content

Game

Struct Game 

Source
pub struct Game { /* private fields */ }
Expand description

Represents the state of a Second Best game.

This struct maintains the complete game state including the board, player turns, action history, and legal moves.

§Examples

use secondbest::prelude::*;

// Create a new game
let mut game = Game::new();

// Apply some actions
game.apply_action(Action::Put(Position::N, Color::B)).unwrap();
game.apply_action(Action::Put(Position::S, Color::W)).unwrap();

// Check if second best can be declared
if game.can_declare_second_best() {
    game.declare_second_best().unwrap();
}

// Check the game result
match game.result() {
    GameResult::Finished { winner } => println!("Winner: {:?}", winner),
    GameResult::InProgress => println!("Game still in progress"),
}

Implementations§

Source§

impl Game

Source

pub fn new() -> Self

Creates a new game with the default initial state.

The game starts with an empty board and Black as the first player.

§Examples
use secondbest::prelude::*;

let game = Game::new();
assert!(matches!(game.result(), GameResult::InProgress));
Source

pub fn board(&self) -> &Board

Returns a reference to the current game board.

§Examples
use secondbest::prelude::*;

let game = Game::new();
let board = game.board();
assert_eq!(board.count_pieces(Color::B), 0);
assert_eq!(board.count_pieces(Color::W), 0);
Source

pub fn current_player(&self) -> Color

Returns the current player.

§Examples
use secondbest::prelude::*;

let game = Game::new();
assert_eq!(game.current_player(), Color::B);

Checks if a given action is legal in the current game state.

§Examples
use secondbest::prelude::*;

let game = Game::new();
// In a new game, placing a black piece at any position is legal
assert!(game.is_legal_action(Action::Put(Position::N, Color::B)));
// But placing a white piece is not (it's not white's turn)
assert!(!game.is_legal_action(Action::Put(Position::N, Color::W)));
Source

pub fn legal_actions(&self) -> &[Action]

Returns a slice of all legal actions for the current player.

§Examples
use secondbest::prelude::*;

let game = Game::new();
let legal_actions = game.legal_actions();
// In a new game, there are 8 legal actions (placing a black piece at any position)
assert_eq!(legal_actions.len(), 8);
Source

pub fn apply_action(&mut self, action: Action) -> Result<(), GameError>

Applies an action to the game state.

This method updates the board, switches the current player, and recalculates legal actions for the next player.

§Errors

Returns GameError::GameAlreadyOver if the game has already finished. Returns GameError::IllegalAction if the action is not legal in the current state.

§Examples
use secondbest::prelude::*;

let mut game = Game::new();
// Apply a legal action
assert!(game.apply_action(Action::Put(Position::N, Color::B)).is_ok());

// Trying to apply an illegal action (not white's turn)
let current_player = game.current_player();
assert_eq!(current_player, Color::W);
assert!(game.apply_action(Action::Put(Position::S, Color::B)).is_err());
Source

pub fn can_declare_second_best(&self) -> bool

Checks if the current player can declare “second best”.

A player can declare “second best” only after their opponent’s first move in a turn (not after a second move following a previous “second best” declaration).

§Examples
use secondbest::prelude::*;

let mut game = Game::new();
// Initially, second best cannot be declared
assert!(!game.can_declare_second_best());

// After an action, the next player can declare second best
game.apply_action(Action::Put(Position::N, Color::B)).unwrap();
assert!(game.can_declare_second_best());
assert_eq!(game.current_player(), Color::W);
Source

pub fn declare_second_best(&mut self) -> Result<(), GameError>

Declares “second best”, forcing the opponent to choose a different action.

This method reverts the board to its previous state, switches back to the previous player, and marks the previous action as forbidden.

§Errors

Returns GameError::CannotDeclareSecondBest if “second best” cannot be declared in the current state.

§Examples
use secondbest::prelude::*;

let mut game = Game::new();
// Apply an action
game.apply_action(Action::Put(Position::N, Color::B)).unwrap();
assert_eq!(game.current_player(), Color::W);

// Declare second best
assert!(game.declare_second_best().is_ok());

// The turn goes back to the previous player
assert_eq!(game.current_player(), Color::B);
// The previous action is now forbidden
assert!(!game.is_legal_action(Action::Put(Position::N, Color::B)));
Source

pub fn result(&self) -> GameResult

Determines the current result of the game.

The game is considered finished when:

  • A player has achieved a winning condition (3 pieces in a stack or 4 consecutive top pieces)
  • If both players achieve a winning condition simultaneously, the player who made the last move wins
  • If a player has no legal moves available, they lose

Note: Winning conditions are only checked after all “second best” declarations have been used.

§Examples
use secondbest::prelude::*;

let mut game = Game::new();
// Initially, the game is in progress
assert!(matches!(game.result(), GameResult::InProgress));

// Create a sequence of moves
game.apply_action(Action::Put(Position::N, Color::B)).unwrap();
game.apply_action(Action::Put(Position::S, Color::W)).unwrap();
// Game is still in progress at this intermediate stage
assert!(matches!(game.result(), GameResult::InProgress));

game.apply_action(Action::Put(Position::N, Color::B)).unwrap();
game.apply_action(Action::Put(Position::S, Color::W)).unwrap();
game.apply_action(Action::Put(Position::E, Color::B)).unwrap();

// White declares "second best"
assert_eq!(game.current_player(), Color::W);
game.declare_second_best().unwrap();

// Black makes a winning move by stacking 3 pieces at North
assert_eq!(game.current_player(), Color::B);
game.apply_action(Action::Put(Position::N, Color::B)).unwrap();

// Game is finished with Black as the winner
assert_eq!(game.result().winner(), Some(Color::B));
Source

pub fn is_finished(&self) -> bool

Checks if the game has finished.

This is a convenience method that checks the result of result(). It returns the same result as calling game.result().is_finished().

§Examples
use secondbest::prelude::*;

let game = Game::new();
assert!(!game.is_finished());

// After a winning move, the game would be finished
// let mut game = create_winning_game();
// assert!(game.is_finished());
Source

pub fn is_in_progress(&self) -> bool

Checks if the game is still in progress.

This is a convenience method that checks the result of result(). It returns the same result as calling game.result().is_in_progress().

§Examples
use secondbest::prelude::*;

let game = Game::new();
assert!(game.is_in_progress());

// After a winning move, the game would no longer be in progress
// let mut game = create_winning_game();
// assert!(!game.is_in_progress());

Trait Implementations§

Source§

impl Clone for Game

Source§

fn clone(&self) -> Game

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Game

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Game

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Display for Game

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Game

§

impl RefUnwindSafe for Game

§

impl Send for Game

§

impl Sync for Game

§

impl Unpin for Game

§

impl UnsafeUnpin for Game

§

impl UnwindSafe for Game

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.