use crate::Error;
use crate::Game;
use crate::game::{GameOutcome, GameState};
use crate::prelude::MatchRules;
use crate::rules::prelude::*;
use crate::rules::{Cube, Rules};
#[derive(Debug, Clone, Default)]
pub struct Match {
points: (u64, u64),
rules: Rules,
cube: Cube,
state: MatchState,
crawford_game: bool,
since_crawford: u8,
murphy_count: u8,
game: Game,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub enum MatchState {
#[default]
Start,
OfferCube(Player),
AwaitOfferAcceptance(Player),
AwaitBeaverAcceptance(Player),
PlayGame(Player),
End(Player),
}
impl Match {
pub fn new() -> Self {
Match::default()
}
pub fn offer_double(&mut self, player: Player) -> Result<(), Error> {
match self.state {
MatchState::Start
| MatchState::End(_)
| MatchState::AwaitOfferAcceptance(_)
| MatchState::AwaitBeaverAcceptance(_)
| MatchState::PlayGame(_) => Err(Error::CubeNotPermitted),
MatchState::OfferCube(p) => {
if p != player || !self.rules.get_cube_play()? {
return Err(Error::CubeNotPermitted);
}
if self.rules.get_crawford()? && self.crawford_game {
return Err(Error::CubeNotPermitted);
}
if self.rules.get_holland()? && self.since_crawford < 5 {
return Err(Error::CubeNotPermitted);
}
self.state = MatchState::AwaitOfferAcceptance(p);
Ok(())
}
}
}
pub fn accept_double(&mut self, player: Player) -> Result<(), Error> {
match self.state {
MatchState::AwaitOfferAcceptance(p) => {
let next_value = self.cube.offer(player)?;
self.cube.set(next_value)?;
self.cube.set_owner(player);
self.state = MatchState::PlayGame(p);
Ok(())
}
_ => Err(Error::NotYourTurn),
}
}
pub fn reject_double(&mut self, player: Player) -> Result<(), Error> {
match self.state {
MatchState::AwaitOfferAcceptance(p) | MatchState::AwaitBeaverAcceptance(p) => {
if player == p {
return Err(Error::NotYourTurn);
}
self.state = MatchState::PlayGame(p);
Ok(())
}
_ => Err(Error::NotYourTurn),
}
}
pub fn get_match_state(&self) -> Result<&MatchState, Error> {
Ok(&self.state)
}
pub fn get_game_state(&self) -> Result<&GameState, Error> {
Ok(self.game.get_state())
}
pub fn get_player(&self) -> Result<Player, Error> {
match self.state {
MatchState::Start => Ok(Player::Nobody),
MatchState::PlayGame(p) => Ok(p),
MatchState::AwaitOfferAcceptance(p) => Ok(p.other()),
MatchState::AwaitBeaverAcceptance(p) => Ok(p.other()),
MatchState::End(_) => Err(Error::MatchEnded),
MatchState::OfferCube(p) => Ok(p),
}
}
pub fn get_score(&self) -> Result<(u64, u64), Error> {
Ok((self.points.0, self.points.1))
}
pub fn get_cube_value(&self) -> Result<u64, Error> {
Ok(self.cube.get())
}
pub fn get_cube_owner(&self) -> Result<Player, Error> {
Ok(self.cube.owner())
}
pub fn set_match_state(&mut self, s: MatchState) {
self.state = s
}
}
impl MatchRules for Match {
fn set_points(&mut self, points: u64) -> Result<(), Error> {
self.rules.set_points(points)
}
fn get_points(&self) -> Result<u64, Error> {
self.rules.get_points()
}
fn set_cube_play(&mut self, cube: bool) -> Result<(), Error> {
self.rules.set_cube_play(cube)
}
fn get_cube_play(&self) -> Result<bool, Error> {
self.rules.get_cube_play()
}
fn set_crawford(&mut self, state: bool) -> Result<(), Error> {
self.rules.set_crawford(state)
}
fn get_crawford(&self) -> Result<bool, Error> {
self.rules.get_crawford()
}
fn set_beaver(&mut self, state: bool) -> Result<(), Error> {
self.rules.set_beaver(state)
}
fn get_beaver(&self) -> Result<bool, Error> {
self.rules.get_beaver()
}
fn set_raccoon(&mut self, state: bool) -> Result<(), Error> {
self.rules.set_raccoon(state)
}
fn get_raccoon(&self) -> Result<bool, Error> {
self.rules.get_raccoon()
}
fn set_murphy(&mut self, state: bool, limit: u8) -> Result<(), Error> {
self.rules.set_murphy(state, limit)
}
fn get_murphy(&self) -> Result<(bool, u8), Error> {
self.rules.get_murphy()
}
fn set_jacobi(&mut self, state: bool) -> Result<(), Error> {
self.rules.set_jacobi(state)
}
fn get_jacobi(&self) -> Result<bool, Error> {
self.rules.get_jacobi()
}
fn set_holland(&mut self, state: bool) -> Result<(), Error> {
self.rules.set_holland(state)
}
fn get_holland(&self) -> Result<bool, Error> {
self.rules.get_holland()
}
}
impl Roll for Match {
fn roll(&mut self, player: Player) -> Result<(), Error> {
match self.state {
MatchState::Start => {
self.state = MatchState::PlayGame(Player::Nobody);
}
MatchState::OfferCube(player_state) => {
if player_state == player {
self.state = MatchState::PlayGame(player);
} else {
return Err(Error::NotYourTurn);
}
}
MatchState::AwaitOfferAcceptance(_) | MatchState::AwaitBeaverAcceptance(_) => {
return Err(Error::CubeAwaitReaction);
}
MatchState::PlayGame(p) => {
if p != Player::Nobody {
return Err(Error::MoveFirst);
}
}
MatchState::End(_) => return Err(Error::MatchEnded),
}
self.game.roll(player)?;
if self.state == MatchState::PlayGame(Player::Nobody)
&& let GameState::Moving(p) = self.game.get_state()
{
self.state = MatchState::PlayGame(*p);
}
let murphy = self.rules.get_murphy()?;
let murphy_ok = if murphy.1 == 0 {
true
} else {
self.murphy_count < murphy.1
};
if murphy.0 && murphy_ok && self.state == MatchState::PlayGame(Player::Nobody) {
self.cube.set(self.cube.offer(Player::Nobody)?)?;
self.murphy_count += 1;
}
Ok(())
}
fn get_dice(&self) -> (u8, u8) {
self.game.get_dice()
}
fn set_dice(&mut self, player: Player, v: (u8, u8)) -> Result<(), Error> {
self.game.set_dice(player, v)
}
fn dice_available(&self) -> &Vec<u8> {
self.game.dice_available()
}
fn dice_consumed(&self) -> bool {
self.game.dice_consumed()
}
}
impl Move for Match {
fn get_board(&self) -> BoardDisplay {
self.game.get_board()
}
fn move_checkers(
&mut self,
player: Player,
moves: Vec<(Position, Position)>,
) -> Result<(), Error> {
match self.state {
MatchState::Start => Err(Error::RollFirst),
MatchState::OfferCube(player_state) => {
if player_state == player {
Err(Error::RollFirst)
} else {
Err(Error::NotYourTurn)
}
}
MatchState::AwaitOfferAcceptance(_) | MatchState::AwaitBeaverAcceptance(_) => {
Err(Error::CubeAwaitReaction)
}
MatchState::PlayGame(player_state) => {
if player_state == player {
self.game.move_checkers(player, moves)?;
match self.game.get_state() {
GameState::Moving(_) => {
Ok(())
}
GameState::Rolling(p) => {
self.state = MatchState::OfferCube(*p);
Ok(())
}
GameState::GameEnd(outcome) => {
let jacobi_outcome = if self.rules.get_cube_play()?
&& self.rules.get_jacobi()?
&& self.cube.owner() == Player::Nobody
{
(1, 1, 1)
} else {
(self.cube.get(), 2 * self.cube.get(), 3 * self.cube.get())
};
match outcome {
GameOutcome::Regular(winner) => match winner {
Player::Player0 => self.points.0 += jacobi_outcome.0,
Player::Player1 => self.points.1 += jacobi_outcome.0,
Player::Nobody => unreachable!("Should never happen!"),
},
GameOutcome::Gammon(winner) => match winner {
Player::Player0 => self.points.0 += jacobi_outcome.1,
Player::Player1 => self.points.1 += jacobi_outcome.1,
Player::Nobody => unreachable!("Should never happen!"),
},
GameOutcome::Backgammon(winner) => match winner {
Player::Player0 => self.points.0 += jacobi_outcome.2,
Player::Player1 => self.points.1 += jacobi_outcome.2,
Player::Nobody => unreachable!("Should never happen!"),
},
}
if self.points.0 >= self.rules.get_points()? {
self.state = MatchState::End(Player::Player0);
};
if self.points.1 >= self.rules.get_points()? {
self.state = MatchState::End(Player::Player1);
};
if self.points.0 < self.rules.get_points()?
&& self.points.1 < self.rules.get_points()?
{
self.state = MatchState::Start;
if self.rules.get_crawford()?
&& (self.crawford_game || self.since_crawford > 0)
{
self.since_crawford += 1;
self.crawford_game = false;
}
if (self.rules.get_points()? - self.points.0 == 1
|| self.rules.get_points()? - self.points.1 == 1)
&& self.since_crawford == 0
&& !self.crawford_game
&& self.rules.get_crawford()?
{
self.crawford_game = true;
}
}
Ok(())
}
}
} else {
Err(Error::NotYourTurn)
}
}
MatchState::End(_) => Err(Error::MatchEnded),
}
}
fn set_checkers(&mut self, player: Player, to: Position, amount: i8) -> Result<(), Error> {
self.game.set_checkers(player, to, amount)
}
fn empty_board(&mut self) -> Result<(), Error> {
self.game.empty_board()
}
fn available_moves(&self, player: Player) -> Result<Vec<Vec<(Position, Position)>>, Error> {
self.game.available_moves(player)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_match() {
let m = Match::new();
assert_eq!(m.points, (0, 0));
assert_eq!(m.rules, Rules::default());
assert_eq!(m.cube, Cube::default());
assert_eq!(m.state, MatchState::Start);
assert!(!m.crawford_game);
assert_eq!(m.since_crawford, 0);
assert_eq!(m.game, Game::default());
}
#[test]
fn test_double_from_offer_cube_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player1);
m.offer_double(Player::Player1)?;
assert_eq!(m.state, MatchState::AwaitOfferAcceptance(Player::Player1));
m.state = MatchState::PlayGame(Player::Player1);
let result = m.offer_double(Player::Player0);
assert_eq!(result, Err(Error::CubeNotPermitted));
m.state = MatchState::AwaitOfferAcceptance(Player::Player1);
let result = m.offer_double(Player::Player1);
assert_eq!(result, Err(Error::CubeNotPermitted));
m.state = MatchState::End(Player::Player1);
let result = m.offer_double(Player::Player1);
assert_eq!(result, Err(Error::CubeNotPermitted));
m.state = MatchState::Start;
let result = m.offer_double(Player::Player1);
assert_eq!(result, Err(Error::CubeNotPermitted));
Ok(())
}
#[test]
fn test_set_and_get_points() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(13)?;
assert_eq!(m.get_points()?, 13);
m.set_points(25)?;
assert_eq!(m.get_points()?, 25);
Ok(())
}
#[test]
fn test_set_and_get_crawford() -> Result<(), Error> {
let mut m = Match::new();
assert!(m.get_crawford()?);
m.set_crawford(false)?;
assert!(!m.get_crawford()?);
m.set_crawford(true)?;
assert!(m.get_crawford()?);
Ok(())
}
#[test]
fn test_set_and_get_beaver() -> Result<(), Error> {
let mut m = Match::new();
assert!(!m.get_beaver()?);
m.set_beaver(true)?;
assert!(m.get_beaver()?);
m.set_beaver(false)?;
assert!(!m.get_beaver()?);
Ok(())
}
#[test]
fn test_set_and_get_raccoon() -> Result<(), Error> {
let mut m = Match::new();
assert!(!m.get_raccoon()?);
m.set_raccoon(true)?;
assert!(m.get_raccoon()?);
m.set_raccoon(false)?;
assert!(!m.get_raccoon()?);
Ok(())
}
#[test]
fn test_set_and_get_murphy() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.get_murphy()?, (false, 0));
m.set_murphy(true, 5)?;
assert_eq!(m.get_murphy()?, (true, 5));
m.set_murphy(false, 10)?;
assert_eq!(m.get_murphy()?, (false, 0));
Ok(())
}
#[test]
fn test_set_and_get_jacobi() -> Result<(), Error> {
let mut m = Match::new();
assert!(!m.get_jacobi()?);
m.set_jacobi(true)?;
assert!(m.get_jacobi()?);
m.set_jacobi(false)?;
assert!(!m.get_jacobi()?);
Ok(())
}
#[test]
fn test_set_and_get_holland() -> Result<(), Error> {
let mut m = Match::new();
assert!(!m.get_holland()?);
m.set_holland(true)?;
assert!(m.get_holland()?);
m.set_holland(false)?;
assert!(!m.get_holland()?);
Ok(())
}
#[test]
fn test_roll_from_start() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.state, MatchState::Start);
while m.state == MatchState::Start || m.state == MatchState::PlayGame(Player::Nobody) {
m.roll(Player::Nobody)?;
}
assert!(matches!(
m.state,
MatchState::PlayGame(Player::Player0) | MatchState::PlayGame(Player::Player1)
));
Ok(())
}
#[test]
fn test_roll_from_offer_cube_correct_player() -> Result<(), Error> {
let mut m = Match::new();
m.game = Game::new();
m.state = MatchState::AwaitOfferAcceptance(Player::Player1);
let result = m.roll(Player::Player1);
assert_eq!(result, Err(Error::CubeAwaitReaction));
Ok(())
}
#[test]
fn test_roll_from_offer_cube_wrong_player() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player0);
let result = m.roll(Player::Player1);
assert_eq!(result, Err(Error::NotYourTurn));
Ok(())
}
#[test]
fn test_roll_from_await_offer_acceptance() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::AwaitOfferAcceptance(Player::Player1);
let result = m.roll(Player::Player1);
assert_eq!(result, Err(Error::CubeAwaitReaction));
Ok(())
}
#[test]
fn test_roll_from_play_game() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::PlayGame(Player::Player1);
let result = m.roll(Player::Player1);
assert_eq!(result, Err(Error::MoveFirst));
Ok(())
}
#[test]
fn test_roll_from_end() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::End(Player::Player1);
let result = m.roll(Player::Player1);
assert_eq!(result, Err(Error::MatchEnded));
Ok(())
}
#[test]
fn test_roll_offer_cube() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player1);
m.game.set_player(Player::Player1)?;
let result = m.roll(Player::Player1);
assert_eq!(result, Ok(()));
Ok(())
}
#[test]
fn test_get_dice() {
let m = Match::new();
let dice = m.get_dice();
assert_eq!(dice, (0, 0));
}
#[test]
fn test_set_dice() -> Result<(), Error> {
let mut m = Match::new();
m.game.set_player(Player::Player0)?;
m.set_dice(Player::Player0, (3, 5))?;
assert_eq!(m.get_dice(), (3, 5));
Ok(())
}
#[test]
fn test_dice_available() {
let m = Match::new();
let available = m.dice_available();
assert_eq!(available.len(), 0);
}
#[test]
fn test_dice_consumed() {
let m = Match::new();
assert!(m.dice_consumed());
}
#[test]
fn test_accept_double() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::AwaitOfferAcceptance(Player::Player0);
m.accept_double(Player::Player1)?;
assert_eq!(m.state, MatchState::PlayGame(Player::Player0));
assert_eq!(m.cube.get(), 2);
m.state = MatchState::Start;
let result = m.accept_double(Player::Player0);
assert_eq!(result, Err(Error::NotYourTurn));
Ok(())
}
#[test]
fn test_double_no_cube() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player1);
m.rules.set_cube_play(false)?;
let result = m.offer_double(Player::Player1);
assert_eq!(result, Err(Error::CubeNotPermitted));
Ok(())
}
#[test]
fn test_double_crawford() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player1);
m.rules.set_crawford(true)?;
m.crawford_game = true;
let result = m.offer_double(Player::Player1);
assert_eq!(result, Err(Error::CubeNotPermitted));
Ok(())
}
#[test]
fn test_double_holland() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player1);
m.rules.set_crawford(false)?;
m.rules.set_holland(true)?;
m.since_crawford = 2;
let result = m.offer_double(Player::Player1);
assert_eq!(result, Err(Error::CubeNotPermitted));
m.since_crawford = 4;
let result = m.offer_double(Player::Player1);
assert_eq!(result, Err(Error::CubeNotPermitted));
m.since_crawford = 5;
let result = m.offer_double(Player::Player1);
assert_eq!(result, Ok(()));
Ok(())
}
#[test]
fn test_reject_double() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::AwaitOfferAcceptance(Player::Player0);
m.reject_double(Player::Player1)?;
assert_eq!(m.state, MatchState::PlayGame(Player::Player0));
m.state = MatchState::AwaitOfferAcceptance(Player::Player1);
let result = m.reject_double(Player::Player1);
assert_eq!(result, Err(Error::NotYourTurn));
m.state = MatchState::Start;
let result = m.reject_double(Player::Player0);
assert_eq!(result, Err(Error::NotYourTurn));
Ok(())
}
#[test]
fn test_set_rules() -> Result<(), Error> {
let mut m = Match::new();
m.set_cube_play(true)?;
m.set_crawford(true)?;
m.set_beaver(true)?;
m.set_raccoon(true)?;
m.set_murphy(true, 10)?;
m.set_jacobi(true)?;
m.set_holland(true)?;
let result = m.get_cube_play();
assert_eq!(result, Ok(true));
let result = m.get_crawford();
assert_eq!(result, Ok(true));
let result = m.get_beaver();
assert_eq!(result, Ok(true));
let result = m.get_raccoon();
assert_eq!(result, Ok(true));
let result = m.get_murphy();
assert_eq!(result, Ok((true, 10)));
let result = m.get_jacobi();
assert_eq!(result, Ok(true));
let result = m.get_holland();
assert_eq!(result, Ok(true));
Ok(())
}
#[test]
fn test_double_murphy() -> Result<(), Error> {
let mut m: Match;
loop {
m = Match::new();
m.rules.set_murphy(true, 0)?;
m.roll(Player::Nobody)?;
if m.state == MatchState::PlayGame(Player::Nobody) {
break;
}
}
assert_eq!(m.cube.get(), 2);
Ok(())
}
#[test]
fn test_double_murphy_with_limit() -> Result<(), Error> {
let mut m: Match;
loop {
m = Match::new();
m.rules.set_murphy(true, 4)?;
m.roll(Player::Nobody)?;
if m.state == MatchState::PlayGame(Player::Nobody) {
break;
}
}
assert_eq!(m.cube.get(), 2);
Ok(())
}
#[test]
fn test_move_checkers_from_start_state() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.state, MatchState::Start);
let result = m.move_checkers(
Player::Player0,
vec![(Position::Board(24), Position::Board(23))],
);
assert_eq!(result, Err(Error::RollFirst));
Ok(())
}
#[test]
fn test_move_checkers_from_offer_cube_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player0);
let result = m.move_checkers(
Player::Player0,
vec![(Position::Board(24), Position::Board(23))],
);
assert_eq!(result, Err(Error::RollFirst));
m.state = MatchState::OfferCube(Player::Player0);
let result = m.move_checkers(
Player::Player1,
vec![(Position::Board(1), Position::Board(2))],
);
assert_eq!(result, Err(Error::NotYourTurn));
Ok(())
}
#[test]
fn test_move_checkers_from_await_offer_acceptance_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::AwaitOfferAcceptance(Player::Player0);
let result = m.move_checkers(
Player::Player0,
vec![(Position::Board(24), Position::Board(23))],
);
assert_eq!(result, Err(Error::CubeAwaitReaction));
Ok(())
}
#[test]
fn test_move_checkers_play_game_state_not_your_turn() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::PlayGame(Player::Player0);
let result = m.move_checkers(
Player::Player1,
vec![(Position::Board(1), Position::Board(2))],
);
assert_eq!(result, Err(Error::NotYourTurn));
Ok(())
}
#[test]
fn test_move_checkers_match_end_with_points() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(false)?;
m.points = (4, 0);
m.state = MatchState::PlayGame(Player::Player0);
m.game.set_player(Player::Player0)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player0, Position::Board(6), 1)?;
m.game
.set_checkers(Player::Player1, Position::Board(1), 1)?;
m.game.set_checkers(Player::Player0, Position::Off, 14)?;
m.game.set_checkers(Player::Player1, Position::Off, 14)?;
m.game.set_dice(Player::Player0, (6, 5))?;
m.move_checkers(Player::Player0, vec![(Position::Board(6), Position::Off)])?;
assert!(m.points.0 >= 5);
assert_eq!(m.state, MatchState::End(Player::Player0));
Ok(())
}
#[test]
fn test_move_checkers_partial() -> Result<(), Error> {
let mut m = Match::new();
m.set_cube_play(false)?;
m.state = MatchState::PlayGame(Player::Player0);
m.game.set_player(Player::Player0)?;
m.game.set_dice(Player::Player0, (6, 1))?;
m.move_checkers(
Player::Player0,
vec![(Position::Board(24), Position::Board(18))],
)?;
assert_eq!(m.state, MatchState::PlayGame(Player::Player0));
assert_eq!(m.dice_available(), &vec![1]);
m.move_checkers(
Player::Player0,
vec![(Position::Board(24), Position::Board(23))],
)?;
assert_eq!(m.state, MatchState::OfferCube(Player::Player1));
Ok(())
}
#[test]
fn test_move_checkers_match_end_with_points_and_jacobi0() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(true)?;
m.set_jacobi(true)?;
m.points = (4, 0);
m.state = MatchState::PlayGame(Player::Player0);
m.game.set_player(Player::Player0)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player0, Position::Board(6), 1)?;
m.game
.set_checkers(Player::Player1, Position::Board(23), 15)?;
m.game.set_checkers(Player::Player0, Position::Off, 14)?;
m.game.set_dice(Player::Player0, (6, 5))?;
m.move_checkers(Player::Player0, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points.0, 5);
assert_eq!(m.state, MatchState::End(Player::Player0));
Ok(())
}
#[test]
fn test_move_checkers_match_end_with_points_and_jacobi1() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(true)?;
m.set_jacobi(true)?;
m.points = (2, 4);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.game
.set_checkers(Player::Player0, Position::Board(1), 1)?;
m.game.set_checkers(Player::Player1, Position::Off, 14)?;
m.game.set_checkers(Player::Player0, Position::Off, 14)?;
m.game.set_dice(Player::Player1, (6, 5))?;
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points.1, 5);
assert_eq!(m.state, MatchState::End(Player::Player1));
Ok(())
}
#[test]
fn test_move_checkers_match_end_with_points_and_jacobi2() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(true)?;
m.set_jacobi(true)?;
m.points = (2, 4);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.game
.set_checkers(Player::Player0, Position::Board(1), 15)?;
m.game.set_checkers(Player::Player1, Position::Off, 14)?;
m.game.set_dice(Player::Player1, (6, 5))?;
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points.1, 5);
assert_eq!(m.state, MatchState::End(Player::Player1));
Ok(())
}
#[test]
fn test_move_checkers_match_end_with_points_and_jacobi3() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(true)?;
m.set_jacobi(true)?;
m.points = (4, 2);
m.state = MatchState::PlayGame(Player::Player0);
m.game.set_player(Player::Player0)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player0, Position::Board(6), 1)?;
m.game
.set_checkers(Player::Player1, Position::Board(1), 15)?;
m.game.set_checkers(Player::Player0, Position::Off, 14)?;
m.game.set_dice(Player::Player0, (6, 5))?;
m.move_checkers(Player::Player0, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points.0, 5);
assert_eq!(m.state, MatchState::End(Player::Player0));
Ok(())
}
#[test]
fn test_move_checkers_match_end_with_points_and_jacobi4() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(true)?;
m.set_jacobi(true)?;
m.points = (2, 4);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.game
.set_checkers(Player::Player0, Position::Board(1), 14)?;
m.game.set_checkers(Player::Player0, Position::Off, 1)?;
m.game.set_checkers(Player::Player1, Position::Off, 14)?;
m.game.set_dice(Player::Player1, (6, 5))?;
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points.1, 5);
assert_eq!(m.state, MatchState::End(Player::Player1));
Ok(())
}
#[test]
fn test_move_checkers_match_end_with_backgammon1() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(false)?;
m.points = (2, 4);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.game
.set_checkers(Player::Player0, Position::Board(23), 15)?;
m.game.set_checkers(Player::Player1, Position::Off, 14)?;
m.game.set_dice(Player::Player1, (6, 5))?;
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points.1, 7);
assert_eq!(m.state, MatchState::End(Player::Player1));
Ok(())
}
#[test]
fn test_move_checkers_match_ongoing() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(false)?;
m.points = (2, 0);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.game
.set_checkers(Player::Player1, Position::Board(6), 2)?;
m.game
.set_checkers(Player::Player0, Position::Board(23), 15)?;
m.game.set_checkers(Player::Player1, Position::Off, 13)?;
m.game.set_dice(Player::Player1, (6, 5))?;
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
m.move_checkers(
Player::Player1,
vec![(Position::Board(6), Position::Board(1))],
)?;
assert_eq!(m.points.1, 0);
assert_eq!(m.state, MatchState::OfferCube(Player::Player0));
Ok(())
}
#[test]
fn test_move_checkers_match_ended() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::End(Player::Player1);
m.game.set_player(Player::Player1)?;
m.game.set_dice(Player::Player1, (6, 5))?;
m.empty_board()?;
m.game
.set_checkers(Player::Player1, Position::Board(6), 2)?;
m.game
.set_checkers(Player::Player0, Position::Board(23), 15)?;
m.game.set_checkers(Player::Player1, Position::Off, 13)?;
let result = m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)]);
assert_eq!(result, Err(Error::MatchEnded));
Ok(())
}
#[test]
fn test_move_checkers_game_end() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(false)?;
m.points = (2, 0);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.set_checkers(Player::Player0, Position::Board(23), 15)?;
m.set_checkers(Player::Player1, Position::Off, 14)?;
m.game.set_dice(Player::Player1, (6, 5))?;
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points.1, 3);
assert_eq!(m.state, MatchState::Start);
Ok(())
}
#[test]
fn test_match_available_moves() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.set_checkers(Player::Player0, Position::Board(23), 15)?;
m.set_checkers(Player::Player1, Position::Off, 14)?;
m.game.set_dice(Player::Player1, (6, 5))?;
let result = m.available_moves(Player::Player1)?;
assert_eq!(
result,
vec![
vec![(Position::Board(6), Position::Off)],
vec![
(Position::Board(6), Position::Board(1)),
(Position::Board(1), Position::Off)
]
]
);
Ok(())
}
#[test]
fn test_match_crawford_game() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(true)?;
m.set_crawford(true)?;
m.points = (0, 3);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.set_checkers(Player::Player0, Position::Board(23), 14)?;
m.set_checkers(Player::Player1, Position::Off, 14)?;
m.set_checkers(Player::Player0, Position::Off, 1)?;
m.game.set_dice(Player::Player1, (6, 5))?;
assert!(!m.crawford_game);
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points, (0, 4));
assert_eq!(m.state, MatchState::Start);
assert!(m.crawford_game);
assert_eq!(m.since_crawford, 0);
Ok(())
}
#[test]
fn test_match_since_crawford_game() -> Result<(), Error> {
let mut m = Match::new();
m.set_points(5)?;
m.set_cube_play(true)?;
m.set_crawford(true)?;
m.crawford_game = true;
m.points = (3, 0);
m.state = MatchState::PlayGame(Player::Player1);
m.game.set_player(Player::Player1)?;
m.empty_board()?;
m.set_checkers(Player::Player1, Position::Board(6), 1)?;
m.set_checkers(Player::Player0, Position::Board(23), 14)?;
m.set_checkers(Player::Player1, Position::Off, 14)?;
m.set_checkers(Player::Player0, Position::Off, 1)?;
m.game.set_dice(Player::Player1, (6, 5))?;
assert_eq!(m.since_crawford, 0);
m.move_checkers(Player::Player1, vec![(Position::Board(6), Position::Off)])?;
assert_eq!(m.points, (3, 1));
assert_eq!(m.state, MatchState::Start);
assert!(!m.crawford_game);
assert_eq!(m.since_crawford, 1);
Ok(())
}
#[test]
fn test_match_get_state() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.get_match_state(), Ok(&MatchState::Start));
m.state = MatchState::OfferCube(Player::Player0);
assert_eq!(
m.get_match_state(),
Ok(&MatchState::OfferCube(Player::Player0))
);
Ok(())
}
#[test]
fn get_player_from_start_state() -> Result<(), Error> {
let m = Match::new();
assert_eq!(m.get_player(), Ok(Player::Nobody));
Ok(())
}
#[test]
fn get_player_from_play_game_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::PlayGame(Player::Player0);
assert_eq!(m.get_player(), Ok(Player::Player0));
m.state = MatchState::PlayGame(Player::Player1);
assert_eq!(m.get_player(), Ok(Player::Player1));
Ok(())
}
#[test]
fn get_player_from_await_offer_acceptance_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::AwaitOfferAcceptance(Player::Player0);
assert_eq!(m.get_player(), Ok(Player::Player1));
m.state = MatchState::AwaitOfferAcceptance(Player::Player1);
assert_eq!(m.get_player(), Ok(Player::Player0));
Ok(())
}
#[test]
fn get_player_from_await_beaver_acceptance_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::AwaitBeaverAcceptance(Player::Player0);
assert_eq!(m.get_player(), Ok(Player::Player1));
m.state = MatchState::AwaitBeaverAcceptance(Player::Player1);
assert_eq!(m.get_player(), Ok(Player::Player0));
Ok(())
}
#[test]
fn get_player_from_end_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::End(Player::Player0);
assert_eq!(m.get_player(), Err(Error::MatchEnded));
m.state = MatchState::End(Player::Player1);
assert_eq!(m.get_player(), Err(Error::MatchEnded));
Ok(())
}
#[test]
fn get_player_from_offer_cube_state() -> Result<(), Error> {
let mut m = Match::new();
m.state = MatchState::OfferCube(Player::Player0);
assert_eq!(m.get_player(), Ok(Player::Player0));
m.state = MatchState::OfferCube(Player::Player1);
assert_eq!(m.get_player(), Ok(Player::Player1));
Ok(())
}
#[test]
fn get_board_returns_correct_board_display() {
let m = Match::new();
let board_display = m.get_board();
assert_eq!(board_display, m.game.get_board());
}
#[test]
fn test_get_score() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.get_score()?, (0, 0));
m.points = (3, 5);
assert_eq!(m.get_score()?, (3, 5));
m.points = (7, 2);
assert_eq!(m.get_score()?, (7, 2));
Ok(())
}
#[test]
fn test_get_cube_value() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.get_cube_value()?, 1);
m.cube.set(2)?;
assert_eq!(m.get_cube_value()?, 2);
m.cube.set(4)?;
assert_eq!(m.get_cube_value()?, 4);
Ok(())
}
#[test]
fn test_get_cube_owner() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.get_cube_owner()?, Player::Nobody);
m.cube.set_owner(Player::Player0);
assert_eq!(m.get_cube_owner()?, Player::Player0);
m.cube.set_owner(Player::Player1);
assert_eq!(m.get_cube_owner()?, Player::Player1);
m.cube.set_owner(Player::Nobody);
assert_eq!(m.get_cube_owner()?, Player::Nobody);
Ok(())
}
#[test]
fn test_get_game_state() -> Result<(), Error> {
let mut m = Match::new();
assert_eq!(m.get_game_state()?, &GameState::Rolling(Player::Nobody));
m.game.set_player(Player::Player0)?;
m.game.set_dice(Player::Player0, (3, 5))?;
assert_eq!(m.get_game_state()?, &GameState::Moving(Player::Player0));
Ok(())
}
}