Skip to content

Commit ad1c892

Browse files
committed
Merge fix for #5
2 parents 7d32f26 + c075500 commit ad1c892

File tree

4 files changed

+102
-29
lines changed

4 files changed

+102
-29
lines changed

src/lib.rs

+46
Original file line numberDiff line numberDiff line change
@@ -733,4 +733,50 @@ mod tests {
733733

734734
eprintln!("{}\n{}", r.as_str(), r.roll().unwrap());
735735
}
736+
737+
#[test]
738+
fn caith_minimal() {
739+
// This should deterministically roll a 1
740+
let roller = Roller::new(&"1d1").unwrap();
741+
742+
let result = roller.roll().unwrap();
743+
let numeric = result.as_single().unwrap();
744+
let history = numeric.to_string_history();
745+
let as_string = numeric.to_string(false);
746+
747+
assert_eq!(numeric.get_total(), 1);
748+
assert_eq!(as_string, "[1] = 1");
749+
assert_eq!(history, "[1]");
750+
}
751+
752+
#[test]
753+
fn caith_reroll() {
754+
// This should deterministically roll a 1, then reroll 1
755+
let roller = Roller::new(&"1d1 r1").unwrap();
756+
757+
let result = roller.roll().unwrap();
758+
let numeric = result.as_single().unwrap();
759+
let history = numeric.to_string_history();
760+
let as_string = numeric.to_string(false);
761+
762+
assert_eq!(numeric.get_total(), 1);
763+
assert_eq!(as_string, "[1 -> 1] -> [1] = 1");
764+
// Rerolls are now displayed in the history
765+
assert_eq!(history, "[1 -> 1] -> [1]");
766+
}
767+
768+
#[test]
769+
fn caith_no_reroll() {
770+
// This should deterministically roll a 1, then not reroll anything since 1 > 0
771+
let roller = Roller::new(&"1d1 r0").unwrap();
772+
773+
let result = roller.roll().unwrap();
774+
let numeric = result.as_single().unwrap();
775+
let history = numeric.to_string_history();
776+
let as_string = numeric.to_string(false);
777+
778+
assert_eq!(numeric.get_total(), 1);
779+
assert_eq!(as_string, "[1] = 1");
780+
assert_eq!(history, "[1]");
781+
}
736782
}

src/parser.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub(crate) struct RollParser;
1818

1919
// arbitrary limit to avoid OOM
2020
const MAX_DICE_SIDES: u64 = 5000;
21-
const MAX_NB_DICE: u64 = 5000;
21+
const MAX_NUMBER_OF_DICE: u64 = 5000;
2222

2323
// number represent nb dice to keep/drop
2424
#[derive(Clone, PartialEq)]
@@ -144,22 +144,30 @@ fn compute_reroll<RNG: DiceRollSource>(
144144
) -> (TotalModifier, Vec<DiceResult>) {
145145
let value = extract_option_value(option).unwrap();
146146
let mut has_rerolled = false;
147-
let res: Vec<DiceResult> = res
148-
.into_iter()
147+
let mut rerolls: Vec<Vec<DiceResult>> = vec![];
148+
let res_new: Vec<DiceResult> = res
149+
.iter()
149150
.map(|x| {
150-
if x.res <= value {
151+
let mut inner = vec![*x];
152+
let result = if x.res <= value {
151153
has_rerolled = true;
152-
roll_dice(1, sides, rng)[0]
154+
let rerolled = roll_dice(1, sides, rng)[0];
155+
inner.push(rerolled);
156+
rerolled
153157
} else {
154-
x
155-
}
158+
*x
159+
};
160+
rerolls.push(inner);
161+
result
156162
})
157163
.collect();
158164

159165
if has_rerolled {
160-
rolls.add_history(res.clone(), false);
166+
rolls.add_rerolled_history(rerolls);
161167
}
162-
(TotalModifier::None(Rule::reroll), res)
168+
rolls.add_history(res_new.clone(), false);
169+
170+
(TotalModifier::None(Rule::reroll), res_new)
163171
}
164172

165173
fn compute_i_reroll<RNG: DiceRollSource>(
@@ -301,20 +309,22 @@ fn compute_roll<RNG: DiceRollSource>(
301309
rng: &mut RNG,
302310
) -> Result<SingleRollResult> {
303311
let mut rolls = SingleRollResult::new();
304-
let maybe_nb = dice.next().unwrap();
305-
let nb = match maybe_nb.as_rule() {
312+
let number_of_dice = dice.next().unwrap();
313+
let number_of_dice = match number_of_dice.as_rule() {
306314
Rule::nb_dice => {
307315
dice.next(); // skip `d` token
308-
let n = maybe_nb.as_str().parse::<u64>().unwrap();
309-
if n > MAX_NB_DICE {
310-
return Err(
311-
format!("Exceed maximum allowed number of dices ({})", MAX_NB_DICE).into(),
312-
);
316+
let n = number_of_dice.as_str().parse::<u64>().unwrap();
317+
if n > MAX_NUMBER_OF_DICE {
318+
return Err(format!(
319+
"Exceed maximum allowed number of dices ({})",
320+
MAX_NUMBER_OF_DICE
321+
)
322+
.into());
313323
}
314324
n
315325
}
316326
Rule::roll => 1, // no number before `d`, assume 1 dice
317-
_ => unreachable!("{:?}", maybe_nb),
327+
_ => unreachable!("{:?}", number_of_dice),
318328
};
319329

320330
let pair = dice.next().unwrap();
@@ -330,7 +340,7 @@ fn compute_roll<RNG: DiceRollSource>(
330340
return Err(format!("Dice can't have more than {}", MAX_DICE_SIDES).into());
331341
}
332342

333-
let mut res = roll_dice(nb, sides, rng);
343+
let mut res = roll_dice(number_of_dice, sides, rng);
334344
let mut modifier = TotalModifier::None(Rule::expr);
335345
let mut next_option = dice.next();
336346
if !is_fudge {

src/rollresult/rollhistory.rs

+22-11
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ impl Display for Value {
3939
#[non_exhaustive]
4040
#[derive(Debug, Clone)]
4141
pub enum RollHistory {
42+
/// Rolls which include rerolls.
43+
/// Should be followed by a Roll with the final results.
44+
ReRolls(Vec<Vec<DiceResult>>),
4245
/// A roll with normal dices
4346
Roll(Vec<DiceResult>),
4447
/// A roll with Fudge dices
@@ -56,18 +59,26 @@ pub enum RollHistory {
5659
impl Display for RollHistory {
5760
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5861
let s = match self {
62+
RollHistory::ReRolls(v) => {
63+
let s2 = v
64+
.iter()
65+
.map(|r| {
66+
r.iter()
67+
.map(|r| r.res.to_string())
68+
.collect::<Vec<_>>()
69+
.join(" -> ")
70+
})
71+
.collect::<Vec<_>>()
72+
.join(", ");
73+
format!("[{}] -> ", s2)
74+
}
5975
RollHistory::Roll(v) => {
60-
let mut s = String::new();
61-
s.push('[');
62-
let len = v.len();
63-
v.iter().enumerate().for_each(|(i, r)| {
64-
s.push_str(&r.res.to_string());
65-
if i < len - 1 {
66-
s.push_str(", ");
67-
}
68-
});
69-
s.push(']');
70-
s
76+
let s2 = v
77+
.iter()
78+
.map(|r| r.res.to_string())
79+
.collect::<Vec<_>>()
80+
.join(", ");
81+
format!("[{}]", s2)
7182
}
7283
RollHistory::Fudge(v) => {
7384
let mut s = String::new();

src/rollresult/singlerollresult.rs

+6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ impl SingleRollResult {
7676
});
7777
}
7878

79+
pub(crate) fn add_rerolled_history(&mut self, mut history: Vec<Vec<DiceResult>>) {
80+
self.dirty = true;
81+
history.sort_unstable_by(|a, b| b.cmp(a));
82+
self.history.push(RollHistory::ReRolls(history));
83+
}
84+
7985
pub(crate) fn add_parenthesis(&mut self) {
8086
self.history.insert(0, RollHistory::OpenParenthesis);
8187
self.history.push(RollHistory::CloseParenthesis);

0 commit comments

Comments
 (0)