1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use super::ratio::{Ratio};
use super::super::{Die, Reroll};
impl Die {
pub fn minimum(&self) -> i32 {
1
}
pub fn maximum(&self) -> i32 {
self.0 as i32
}
pub fn average(&self, reroll: Option<Reroll>) -> Ratio {
if let Some(reroll) = reroll {
let mut numerator = 0;
for result in self.results() {
if reroll.reroll(result as u32, *self) {
numerator += (self.0 + 1) as i128;
} else {
numerator += (result * 2) as i128;
}
}
Ratio::new(numerator, self.0 as i128 * 2)
} else {
Ratio::new(self.0 as i128 + 1, 2)
}
}
pub fn results(&self) -> impl Iterator<Item=i32> {
self.minimum()..(self.maximum() + 1)
}
pub fn probabilities(&self, reroll: Option<Reroll>) -> Vec<(i32, Ratio)> {
if let Some(reroll) = reroll {
let (low, high) = super::numerators(*self, reroll);
let denominator = self.0.pow(2) as i128;
let low = Ratio::new(low, denominator);
let high = Ratio::new(high, denominator);
self.results().map(|r| {
let probability = if reroll.reroll(r as u32, *self) { low } else { high };
(r, probability)
}).collect()
} else {
self.results().map(|r| (r, Ratio::new(1, self.0 as i128))).collect()
}
}
}