init commit
This commit is contained in:
62
src/util.rs
Normal file
62
src/util.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
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!()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user