Adding calculations for keep, and adding validation on keep input

This commit is contained in:
Matthew Sparks 2021-09-07 20:43:08 -04:00
parent 1860eaf378
commit 15163ac11d
2 changed files with 26 additions and 8 deletions

View File

@ -41,7 +41,12 @@ fn parse_dice(input: &str) -> IResult<&str, Dice> {
// if ok, keep expression is present // if ok, keep expression is present
Ok(r) => { Ok(r) => {
input = r.0; input = r.0;
// don't allow keep greater than number of dice, and don't allow keep zero
if r.1.1 <= count && r.1.1 != "0" {
keep = r.1.1; keep = r.1.1;
} else {
keep = count;
}
} }
// otherwise absent and keep all dice // otherwise absent and keep all dice
Err(_) => keep = count, Err(_) => keep = count,

View File

@ -19,15 +19,21 @@ pub trait Rolled {
} }
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct DiceRoll(pub Vec<u32>); // array of rolls in order, and how many dice to keep
pub struct DiceRoll (pub Vec<u32>, usize);
impl DiceRoll { impl DiceRoll {
pub fn rolls(&self) -> &[u32] { pub fn rolls(&self) -> &[u32] {
&self.0 &self.0
} }
pub fn keep(&self) -> usize {
self.1
}
// only count kept dice in total
pub fn total(&self) -> u32 { pub fn total(&self) -> u32 {
self.0.iter().sum() self.0[..=(self.1-1)].iter().sum()
} }
} }
@ -41,11 +47,16 @@ impl fmt::Display for DiceRoll {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.rolled_value())?; write!(f, "{}", self.rolled_value())?;
let rolls = self.rolls(); let rolls = self.rolls();
let mut iter = rolls.iter(); let keep = self.keep();
let mut iter = rolls.iter().enumerate();
if let Some(first) = iter.next() { if let Some(first) = iter.next() {
write!(f, " ({}", first)?; write!(f, " ({}", first.1)?;
for roll in iter { for roll in iter {
write!(f, " + {}", roll)?; if roll.0 < keep {
write!(f, " + {}", roll.1)?;
} else {
write!(f, " + [{}]", roll.1)?;
}
} }
write!(f, ")")?; write!(f, ")")?;
} }
@ -58,11 +69,13 @@ impl Roll for dice::Dice {
fn roll(&self) -> DiceRoll { fn roll(&self) -> DiceRoll {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let rolls: Vec<_> = (0..self.count) let mut rolls: Vec<_> = (0..self.count)
.map(|_| rng.gen_range(1..=self.sides)) .map(|_| rng.gen_range(1..=self.sides))
.collect(); .collect();
// sort rolls in descending order
rolls.sort_by(|a, b| b.cmp(a));
DiceRoll(rolls) DiceRoll(rolls,self.keep as usize)
} }
} }