diff options
Diffstat (limited to 'src/dice.rs')
| -rw-r--r-- | src/dice.rs | 135 |
1 files changed, 91 insertions, 44 deletions
diff --git a/src/dice.rs b/src/dice.rs index c89c4c9..68b6ecf 100644 --- a/src/dice.rs +++ b/src/dice.rs @@ -3,16 +3,26 @@ use std::ops::Add; use rand::rngs::ThreadRng; use rand::Rng; -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub struct RiskDie(u8); pub const NUM_DIE_LEVELS: usize = 6; -pub const RISK_DIE_VALUES: [u8; NUM_DIE_LEVELS] = [4, 6, 8, 10, 12, 20]; -pub const DELTA_4: RiskDie = RiskDie(0); -pub const DELTA_6: RiskDie = RiskDie(1); -pub const DELTA_8: RiskDie = RiskDie(2); -pub const DELTA_10: RiskDie = RiskDie(3); -pub const DELTA_12: RiskDie = RiskDie(4); -pub const DELTA_20: RiskDie = RiskDie(5); +pub const DIE_VALUES: [u8; NUM_DIE_LEVELS] = [4, 6, 8, 10, 12, 20]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct Die(u8); +pub const D_4: Die = Die(0); +pub const D_6: Die = Die(1); +pub const D_8: Die = Die(2); +pub const D_10: Die = Die(3); +pub const D_12: Die = Die(4); +pub const D_20: Die = Die(5); + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct RiskDie(Die); +pub const DELTA_4: RiskDie = RiskDie(Die(0)); +pub const DELTA_6: RiskDie = RiskDie(Die(1)); +pub const DELTA_8: RiskDie = RiskDie(Die(2)); +pub const DELTA_10: RiskDie = RiskDie(Die(3)); +pub const DELTA_12: RiskDie = RiskDie(Die(4)); +pub const DELTA_20: RiskDie = RiskDie(Die(5)); #[derive(Debug, PartialEq, Eq)] pub enum Error @@ -21,11 +31,11 @@ pub enum Error InvalidValue, } -impl RiskDie +impl Die { pub fn from_level(level: u8) -> Result<Self, Error> { - if (level as usize) < RISK_DIE_VALUES.len() { + if (level as usize) < DIE_VALUES.len() { Ok(Self(level)) } else { @@ -35,7 +45,7 @@ impl RiskDie pub fn from_value(value: u8) -> Result<Self, Error> { - for (i, val) in RISK_DIE_VALUES.iter().enumerate() { + for (i, val) in DIE_VALUES.iter().enumerate() { if *val == value { return Ok(Self(i as u8)); } @@ -46,27 +56,15 @@ impl RiskDie pub fn level(&self) -> u8 { self.0 } - pub fn value(&self) -> u8 { RISK_DIE_VALUES[self.0 as usize] } + pub fn value(&self) -> u8 { DIE_VALUES[self.0 as usize] } - /// Roll the die. If the die shows 3 or less, it returns the next lower die. - /// If it is more, it returns itself. If it was already the lowest die value - /// and it would be stepped down it returns `None`. - pub fn roll(self) -> Option<Self> + pub fn roll(&self) -> u8 { let mut rng = rand::thread_rng(); self.roll_with_rng(&mut rng) } - pub fn roll_with_rng(self, rng: &mut ThreadRng) -> Option<Self> - { - let rolled = rng.gen_range(1..=self.value()); - if rolled > 3 { - Some(self) - } - else { - self.level_down() - } - } + pub fn roll_with_rng(&self, rng: &mut ThreadRng) -> u8 { rng.gen_range(1..=self.value()) } pub fn can_be_lowered(&self) -> bool { self.0 > 0 } @@ -94,6 +92,53 @@ impl RiskDie } } +impl RiskDie +{ + pub fn from_level(level: u8) -> Result<Self, Error> + { + Ok(Self { + 0: Die::from_level(level)?, + }) + } + + pub fn from_value(value: u8) -> Result<Self, Error> + { + Ok(Self { + 0: Die::from_value(value)?, + }) + } + + pub fn level(&self) -> u8 { self.0.level() } + + pub fn value(&self) -> u8 { self.0.value() } + + /// Roll the die. If the die shows 3 or less, it returns the next lower die. + /// If it is more, it returns itself. If it was already the lowest die value + /// and it would be stepped down it returns `None`. + pub fn roll(self) -> Option<Self> + { + let mut rng = rand::thread_rng(); + self.roll_with_rng(&mut rng) + } + + pub fn roll_with_rng(self, rng: &mut ThreadRng) -> Option<Self> + { + let rolled = self.0.roll_with_rng(rng); + if rolled > 3 { + Some(self) + } + else { + self.level_down() + } + } + + pub fn can_be_lowered(&self) -> bool { self.0.can_be_lowered() } + pub fn level_down(self) -> Option<Self> { self.0.level_down().map(|d| RiskDie(d)) } + + pub fn can_be_upped(&self) -> bool { self.0.can_be_upped() } + pub fn level_up(self) -> Self { RiskDie(self.0.level_up()) } +} + #[rustfmt::skip] const DELTA_ADDITION_TABLE: [[u8; NUM_DIE_LEVELS]; NUM_DIE_LEVELS] = [ /* ------------------- with d4 d6 d8 d10 d12 d20 */ @@ -110,7 +155,9 @@ impl Add for RiskDie fn add(self, other: Self) -> Self::Output { - RiskDie(DELTA_ADDITION_TABLE[self.0 as usize][other.0 as usize]) + RiskDie(Die( + DELTA_ADDITION_TABLE[self.0.level() as usize][other.0.level() as usize] + )) } } @@ -120,7 +167,7 @@ mod tests use super::*; #[test] - fn create_die_from_level() + fn create_risk_die_from_level() { let die = RiskDie::from_level(0).expect("Unable to create die for correct level"); assert_eq!(die.value(), 4); @@ -137,7 +184,7 @@ mod tests } #[test] - fn create_die_from_invalid_level() + fn create_risk_die_from_invalid_level() { assert_eq!( RiskDie::from_level(6).expect_err("Should not be able to create die from level"), @@ -146,7 +193,7 @@ mod tests } #[test] - fn create_from_value() + fn create_risk_die_from_value() { let die = RiskDie::from_value(4).expect("Unable to create die from correct value"); assert_eq!(die.level(), 0); @@ -163,25 +210,25 @@ mod tests } #[test] - fn level_down() + fn risk_die_level_down() { assert_eq!(DELTA_4.level_down(), None); - assert_eq!(DELTA_6.level_down(), Some(RiskDie(0))); - assert_eq!(DELTA_8.level_down(), Some(RiskDie(1))); - assert_eq!(DELTA_10.level_down(), Some(RiskDie(2))); - assert_eq!(DELTA_12.level_down(), Some(RiskDie(3))); - assert_eq!(DELTA_20.level_down(), Some(RiskDie(4))); + assert_eq!(DELTA_6.level_down(), Some(DELTA_4)); + assert_eq!(DELTA_8.level_down(), Some(DELTA_6)); + assert_eq!(DELTA_10.level_down(), Some(DELTA_8)); + assert_eq!(DELTA_12.level_down(), Some(DELTA_10)); + assert_eq!(DELTA_20.level_down(), Some(DELTA_12)); } #[test] - fn level_up() + fn risk_die_level_up() { - assert_eq!(DELTA_4.level_up(), RiskDie(1)); - assert_eq!(DELTA_6.level_up(), RiskDie(2)); - assert_eq!(DELTA_8.level_up(), RiskDie(3)); - assert_eq!(DELTA_10.level_up(), RiskDie(4)); - assert_eq!(DELTA_12.level_up(), RiskDie(5)); - assert_eq!(DELTA_20.level_up(), RiskDie(5)); + assert_eq!(DELTA_4.level_up(), DELTA_6); + assert_eq!(DELTA_6.level_up(), DELTA_8); + assert_eq!(DELTA_8.level_up(), DELTA_10); + assert_eq!(DELTA_10.level_up(), DELTA_12); + assert_eq!(DELTA_12.level_up(), DELTA_20); + assert_eq!(DELTA_20.level_up(), DELTA_20); } #[test] |
