Files
minibaldur-bevy/src/util.rs
2023-10-15 23:41:11 -05:00

63 lines
1.1 KiB
Rust

use rand::prelude::*;
enum Tok {
Roll(u32),
Flat(u32),
}
use Tok::*;
/// Rolls dice corresponding to a ttrpg dice specifier
/// ```
/// assert_eq!(roll("4d6 + 1d4 + 1").1.len(), 2)
/// ```
pub fn roll(spec: &str) -> (u32, Vec<u32>) {
let mut toks = spec.split_whitespace();
let mut rolls = vec![];
let mut total = 0;
let first = toks.next().unwrap();
match parse_tok(first) {
Roll(v) => {
total += v;
rolls.push(v);
}
Flat(v) => total += v,
};
let toks : Vec<&str> = toks.collect();
let mut toks = toks.chunks(2);
while let Some(&[op, tok]) = toks.next() {
let val = match parse_tok(tok) {
Roll(v) => {
rolls.push(v);
v
}
Flat(v) => v,
};
if op == "-" {
total -= val;
} else {
total += val;
}
}
(total, rolls)
}
fn parse_tok(tok: &str) -> Tok {
let mut rng = thread_rng();
match *tok.split('d')
.map(|x| x.parse().unwrap())
.collect::<Vec<_>>()
.as_slice() {
[v] => Flat(v),
[n, d] => {
let mut total = 0;
for _ in 0..n {
total += rng.gen_range(1..=d)
}
Roll(total)
}
_ => panic!()
}
}