80 lines
2.3 KiB
Rust
80 lines
2.3 KiB
Rust
|
|
use crate::Error;
|
||
|
|
use rand::distributions::{Distribution, Uniform};
|
||
|
|
use serde::{Deserialize, Serialize};
|
||
|
|
|
||
|
|
/// Represents the two dices
|
||
|
|
///
|
||
|
|
/// Backgammon is always played with two dices.
|
||
|
|
#[derive(Debug, Clone, Copy, Serialize, PartialEq, Deserialize, Default)]
|
||
|
|
pub struct Dices {
|
||
|
|
/// The two dice values
|
||
|
|
pub values: (u8, u8),
|
||
|
|
/// Boolean indicating whether the dices have been consumed already. We use a tuple
|
||
|
|
/// of four booleans in case the dices are equal, in which case we have four dices
|
||
|
|
/// to play.
|
||
|
|
pub consumed: (bool, bool, bool, bool),
|
||
|
|
}
|
||
|
|
impl Dices {
|
||
|
|
/// Roll the dices which generates two random numbers between 1 and 6, replicating a perfect
|
||
|
|
/// dice. We use the operating system's random number generator.
|
||
|
|
pub fn roll(self) -> Self {
|
||
|
|
let between = Uniform::new_inclusive(1, 6);
|
||
|
|
let mut rng = rand::thread_rng();
|
||
|
|
|
||
|
|
let v = (between.sample(&mut rng), between.sample(&mut rng));
|
||
|
|
|
||
|
|
// if both dices are equal, we have four dices to play
|
||
|
|
if v.0 == v.1 {
|
||
|
|
Dices {
|
||
|
|
values: (v.0, v.1),
|
||
|
|
consumed: (false, false, false, false),
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Dices {
|
||
|
|
values: (v.0, v.1),
|
||
|
|
consumed: (false, false, true, true),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Trait to roll the dices
|
||
|
|
pub trait Roll {
|
||
|
|
/// Roll the dices
|
||
|
|
fn roll(&mut self) -> Result<&mut Self, Error>;
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_roll() {
|
||
|
|
let dices = Dices::default().roll();
|
||
|
|
assert!(dices.values.0 >= 1 && dices.values.0 <= 6);
|
||
|
|
assert!(dices.values.1 >= 1 && dices.values.1 <= 6);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_roll_consumed() {
|
||
|
|
let dices = Dices::default().roll();
|
||
|
|
if dices.values.0 == dices.values.1 {
|
||
|
|
assert_eq!(dices.consumed, (false, false, false, false));
|
||
|
|
} else {
|
||
|
|
assert_eq!(dices.consumed, (false, false, true, true));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_roll_consumed1() {
|
||
|
|
for _i in 0..100 {
|
||
|
|
let dices = Dices::default().roll();
|
||
|
|
if dices.values.0 == dices.values.1 {
|
||
|
|
assert_eq!(dices.consumed, (false, false, false, false));
|
||
|
|
} else {
|
||
|
|
assert_eq!(dices.consumed, (false, false, true, true));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|