server (from tic-tac example)
This commit is contained in:
parent
7c4d0a19a4
commit
e9d4f04044
8 changed files with 234 additions and 203 deletions
|
|
@ -1,12 +1,10 @@
|
|||
use crate::Player;
|
||||
use crate::player::{Player, Color};
|
||||
use crate::Error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Represents the Backgammon board
|
||||
///
|
||||
/// A Backgammon board consists of 24 fields, each of which can hold 0 or more checkers. In
|
||||
/// addition there is a bar to hold checkers that have been hit and an off area to hold checkers
|
||||
/// that have been removed from the board.
|
||||
/// A Tric-Trac board consists of 24 fields, each of which can hold 0 or more checkers.
|
||||
///
|
||||
/// ```
|
||||
/// # fn foo() {}
|
||||
|
|
@ -16,7 +14,7 @@ use serde::{Deserialize, Serialize};
|
|||
/// // | X O | | O | +-------+
|
||||
/// // | X | | O |
|
||||
/// // | X | | O |
|
||||
/// // | |BAR| |
|
||||
/// // | | | |
|
||||
/// // | O | | X |
|
||||
/// // | O | | X |
|
||||
/// // | O X | | X | +-------+
|
||||
|
|
@ -64,7 +62,6 @@ impl Board {
|
|||
|
||||
BoardDisplay {
|
||||
board,
|
||||
bar: self.get_bar(),
|
||||
off: self.get_off(),
|
||||
}
|
||||
}
|
||||
|
|
@ -92,32 +89,25 @@ impl Board {
|
|||
return Err(Error::FieldBlocked);
|
||||
}
|
||||
|
||||
match player {
|
||||
Player::Player0 => {
|
||||
match player.color {
|
||||
Color::White => {
|
||||
let new = self.raw_board.0.board[field] as i8 + amount;
|
||||
if new < 0 {
|
||||
return Err(Error::MoveInvalid);
|
||||
}
|
||||
self.raw_board.0.board[field] = new as u8;
|
||||
|
||||
// in case one opponent's checker is hit, move it to the bar
|
||||
self.raw_board.1.bar += self.raw_board.1.board[23 - field];
|
||||
self.raw_board.1.board[23 - field] = 0;
|
||||
Ok(())
|
||||
}
|
||||
Player::Player1 => {
|
||||
Color::Black => {
|
||||
let new = self.raw_board.1.board[field] as i8 + amount;
|
||||
if new < 0 {
|
||||
return Err(Error::MoveInvalid);
|
||||
}
|
||||
self.raw_board.1.board[field] = new as u8;
|
||||
|
||||
// in case one opponent's checker is hit, move it to the bar
|
||||
self.raw_board.0.bar += self.raw_board.0.board[23 - field];
|
||||
self.raw_board.0.board[23 - field] = 0;
|
||||
Ok(())
|
||||
}
|
||||
Player::Nobody => Err(Error::PlayerInvalid),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,64 +117,38 @@ impl Board {
|
|||
return Err(Error::FieldInvalid);
|
||||
}
|
||||
|
||||
match player {
|
||||
Player::Player0 => {
|
||||
match player.color {
|
||||
Color::White => {
|
||||
if self.raw_board.1.board[23 - field] > 1 {
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
Player::Player1 => {
|
||||
Color::Black => {
|
||||
if self.raw_board.0.board[23 - field] > 1 {
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
Player::Nobody => Err(Error::PlayerInvalid),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set checkers for a player on the bar. This method adds amount to the already existing
|
||||
/// checkers there.
|
||||
pub fn set_bar(&mut self, player: Player, amount: i8) -> Result<(), Error> {
|
||||
match player {
|
||||
Player::Player0 => {
|
||||
let new = self.raw_board.0.bar as i8 + amount;
|
||||
if new < 0 {
|
||||
return Err(Error::MoveInvalid);
|
||||
}
|
||||
self.raw_board.0.bar = new as u8;
|
||||
Ok(())
|
||||
}
|
||||
Player::Player1 => {
|
||||
let new = self.raw_board.1.bar as i8 + amount;
|
||||
if new < 0 {
|
||||
return Err(Error::MoveInvalid);
|
||||
}
|
||||
self.raw_board.1.bar = new as u8;
|
||||
Ok(())
|
||||
}
|
||||
Player::Nobody => Err(Error::PlayerInvalid),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set checkers for a player off the board. This method adds amount to the already existing
|
||||
/// checkers there.
|
||||
pub fn set_off(&mut self, player: Player, amount: u8) -> Result<(), Error> {
|
||||
match player {
|
||||
Player::Player0 => {
|
||||
match player.color {
|
||||
Color::White => {
|
||||
let new = self.raw_board.0.off + amount;
|
||||
self.raw_board.0.off = new;
|
||||
Ok(())
|
||||
}
|
||||
Player::Player1 => {
|
||||
Color::Black => {
|
||||
let new = self.raw_board.1.off + amount;
|
||||
self.raw_board.1.off = new;
|
||||
Ok(())
|
||||
}
|
||||
Player::Nobody => Err(Error::PlayerInvalid),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -193,7 +157,6 @@ impl Board {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
struct PlayerBoard {
|
||||
board: [u8; 24],
|
||||
bar: u8,
|
||||
off: u8,
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +166,6 @@ impl Default for PlayerBoard {
|
|||
board: [
|
||||
0, 0, 0, 0, 0, 5, 0, 3, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
|
||||
],
|
||||
bar: 0,
|
||||
off: 0,
|
||||
}
|
||||
}
|
||||
|
|
@ -216,11 +178,6 @@ pub trait Move {
|
|||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Move a checker from bar
|
||||
fn move_checker_from_bar(&mut self, player: Player, dice: u8) -> Result<&mut Self, Error>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Move permitted
|
||||
fn move_permitted(&mut self, player: Player, dice: u8) -> Result<&mut Self, Error>
|
||||
where
|
||||
|
|
@ -243,7 +200,6 @@ mod tests {
|
|||
PlayerBoard::default(),
|
||||
PlayerBoard {
|
||||
board: [0, 0, 0, 0, 0, 5, 0, 3, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,],
|
||||
bar: 0,
|
||||
off: 0
|
||||
}
|
||||
);
|
||||
|
|
@ -258,18 +214,11 @@ mod tests {
|
|||
board: [
|
||||
-2, 0, 0, 0, 0, 5, 0, 3, 0, 0, 0, -5, 5, 0, 0, 0, -3, 0, -5, 0, 0, 0, 0, 2,
|
||||
],
|
||||
bar: (0, 0),
|
||||
off: (0, 0)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_bar() {
|
||||
let board = Board::new();
|
||||
assert_eq!(board.get_bar(), (0, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_off() {
|
||||
let board = Board::new();
|
||||
|
|
@ -279,7 +228,8 @@ mod tests {
|
|||
#[test]
|
||||
fn set_player0() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player0, 1, 1)?;
|
||||
let player = Player {name: "".into(), color: Color::White};
|
||||
board.set(player, 1, 1)?;
|
||||
assert_eq!(board.get().board[1], 1);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -287,31 +237,17 @@ mod tests {
|
|||
#[test]
|
||||
fn set_player1() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player1, 2, 1)?;
|
||||
let player = Player {name: "".into(), color: Color::Black};
|
||||
board.set(player, 2, 1)?;
|
||||
assert_eq!(board.get().board[21], -1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_player0_bar() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set_bar(Player::Player0, 1)?;
|
||||
assert_eq!(board.get().bar.0, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_player1_bar() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set_bar(Player::Player1, 1)?;
|
||||
assert_eq!(board.get().bar.1, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_player0_off() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set_off(Player::Player0, 1)?;
|
||||
let player = Player {name: "".into(), color: Color::White};
|
||||
board.set_off(player, 1)?;
|
||||
assert_eq!(board.get().off.0, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -319,7 +255,8 @@ mod tests {
|
|||
#[test]
|
||||
fn set_player1_off() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set_off(Player::Player1, 1)?;
|
||||
let player = Player {name: "".into(), color: Color::Black};
|
||||
board.set_off(player, 1)?;
|
||||
assert_eq!(board.get().off.1, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -327,108 +264,89 @@ mod tests {
|
|||
#[test]
|
||||
fn set_player1_off1() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set_off(Player::Player1, 1)?;
|
||||
board.set_off(Player::Player1, 1)?;
|
||||
let player = Player {name: "".into(), color: Color::Black};
|
||||
board.set_off(player, 1)?;
|
||||
board.set_off(player, 1)?;
|
||||
assert_eq!(board.get().off.1, 2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_invalid_player() {
|
||||
let mut board = Board::new();
|
||||
assert!(board.set(Player::Nobody, 0, 1).is_err());
|
||||
assert!(board.set_bar(Player::Nobody, 1).is_err());
|
||||
assert!(board.set_off(Player::Nobody, 1).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocked_player0() -> Result<(), Error> {
|
||||
let board = Board::new();
|
||||
assert!(board.blocked(Player::Player0, 0)?);
|
||||
assert!(board.blocked(Player { name:"".into(), color: Color::White }, 0)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocked_player1() -> Result<(), Error> {
|
||||
let board = Board::new();
|
||||
assert!(board.blocked(Player::Player1, 0)?);
|
||||
assert!(board.blocked(Player { name:"".into(), color: Color::Black }, 0)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocked_player0_a() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player1, 1, 2)?;
|
||||
assert!(board.blocked(Player::Player0, 22)?);
|
||||
board.set(Player { name:"".into(), color: Color::Black }, 1, 2)?;
|
||||
assert!(board.blocked(Player { name:"".into(), color: Color::White }, 22)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocked_player1_a() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player0, 1, 2)?;
|
||||
assert!(board.blocked(Player::Player1, 22)?);
|
||||
board.set(Player { name:"".into(), color: Color::White }, 1, 2)?;
|
||||
assert!(board.blocked(Player { name:"".into(), color: Color::Black }, 22)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocked_invalid_player() {
|
||||
let board = Board::new();
|
||||
assert!(board.blocked(Player::Nobody, 0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocked_invalid_field() {
|
||||
let board = Board::new();
|
||||
assert!(board.blocked(Player::Player0, 24).is_err());
|
||||
assert!(board.blocked(Player { name:"".into(), color: Color::White }, 24).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_field_with_1_checker_player0_a() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player0, 1, 1)?;
|
||||
board.set(Player::Player1, 22, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::White }, 1, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::Black }, 22, 1)?;
|
||||
assert_eq!(board.get().board[1], -1);
|
||||
assert_eq!(board.get().bar.0, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_field_with_1_checker_player0_b() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player0, 1, 1)?;
|
||||
board.set_bar(Player::Player0, 5)?;
|
||||
board.set(Player::Player1, 22, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::White }, 1, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::Black }, 22, 1)?;
|
||||
assert_eq!(board.get().board[1], -1);
|
||||
assert_eq!(board.get().bar.0, 6);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_field_with_1_checker_player1_a() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player1, 1, 1)?;
|
||||
board.set(Player::Player0, 22, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::Black }, 1, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::White }, 22, 1)?;
|
||||
assert_eq!(board.get().board[22], 1);
|
||||
assert_eq!(board.get().bar.1, 1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_field_with_1_checker_player1_b() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player1, 1, 1)?;
|
||||
board.set_bar(Player::Player1, 5)?;
|
||||
board.set(Player::Player0, 22, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::Black }, 1, 1)?;
|
||||
board.set(Player { name:"".into(), color: Color::White }, 22, 1)?;
|
||||
assert_eq!(board.get().board[22], 1);
|
||||
assert_eq!(board.get().bar.1, 6);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_field_with_2_checkers_player0_a() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player0, 23, 2)?;
|
||||
board.set(Player { name:"".into(), color: Color::White }, 23, 2)?;
|
||||
assert_eq!(board.get().board[23], 4);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -436,7 +354,7 @@ mod tests {
|
|||
#[test]
|
||||
fn set_field_with_2_checkers_player0_b() -> Result<(), Error> {
|
||||
let mut board = Board::new();
|
||||
board.set(Player::Player0, 23, -1)?;
|
||||
board.set(Player { name:"".into(), color: Color::White }, 23, -1)?;
|
||||
assert_eq!(board.get().board[23], 1);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -444,24 +362,24 @@ mod tests {
|
|||
#[test]
|
||||
fn set_field_blocked() {
|
||||
let mut board = Board::new();
|
||||
assert!(board.set(Player::Player0, 0, 2).is_err());
|
||||
assert!(board.set(Player { name:"".into(), color: Color::White }, 0, 2).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_wrong_field1() {
|
||||
let mut board = Board::new();
|
||||
assert!(board.set(Player::Player0, 50, 2).is_err());
|
||||
assert!(board.set(Player { name:"".into(), color: Color::White }, 50, 2).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_wrong_amount0() {
|
||||
let mut board = Board::new();
|
||||
assert!(board.set(Player::Player0, 23, -3).is_err());
|
||||
assert!(board.set(Player { name:"".into(), color: Color::White }, 23, -3).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_wrong_amount1() {
|
||||
let mut board = Board::new();
|
||||
assert!(board.set(Player::Player1, 23, -3).is_err());
|
||||
assert!(board.set(Player { name:"".into(), color: Color::Black }, 23, -3).is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue