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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
extern crate rand;
#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;
use rand::{Rng, SeedableRng};
use rand::distributions::Uniform;
use rand::rngs::SmallRng;
use std::num::NonZeroU32;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct Die {
faces: NonZeroU32,
}
impl Default for Die {
fn default() -> Self {
Die { faces: NonZeroU32::new(20).unwrap() }
}
}
impl Die {
pub fn new(faces: NonZeroU32) -> Die {
Die { faces }
}
pub fn roll(&self) -> u32 {
let mut rng = SmallRng::from_entropy();
rng.sample(Uniform::new_inclusive(1, self.faces().get()))
}
pub fn faces(&self) -> NonZeroU32 {
self.faces
}
}
pub fn roll(amount: u32, faces: NonZeroU32) -> Vec<u32> {
let die = Die::new(faces);
let mut results = Vec::with_capacity(amount as usize);
for _ in 0..amount {
results.push(die.roll());
}
results
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn die_roll_d6() {
let faces = NonZeroU32::new(6).unwrap();
let d6 = Die::new(faces);
for _ in 0..99 {
let roll = d6.roll();
assert!(roll > 0 && roll <= faces.get());
}
}
#[test]
fn die_roll_d1() {
let d1 = Die::new(NonZeroU32::new(1).unwrap());
assert_eq!(d1.roll(), 1);
}
#[test]
fn die_faces() {
let d6 = Die::new(NonZeroU32::new(6).unwrap());
assert_eq!(d6.faces().get(), 6)
}
#[test]
fn roll_vector_length_equals_number_of_dice() {
let length = roll(3, NonZeroU32::new(6).unwrap()).len();
assert_eq!(length, 3);
}
#[test]
fn roll_vector_contains_numbers_from_valid_range() {
let amount = 3;
let faces = NonZeroU32::new(6).unwrap();
for _ in 0..99 {
let vec = roll(amount, faces);
assert!(vec.iter().all(|v| v <= &faces.get() && v > &0));
}
}
#[test]
fn roll_zero_dice() {
let amount = 0;
let faces = NonZeroU32::new(6).unwrap();
assert_eq!(roll(amount, faces).len(), 0)
}
}