]> git.scottworley.com Git - pluta-lesnura/blame - src/lib.rs
Deck
[pluta-lesnura] / src / lib.rs
CommitLineData
57f490a0
SW
1use rand::Rng;
2
3pub const NUM_RANKS: u8 = 13;
09822a98
SW
4pub const NUM_SUITS: u8 = 4;
5pub const NUM_CARDS: u8 = NUM_RANKS * NUM_SUITS;
57f490a0
SW
6
7#[derive(Clone, Copy, Eq, PartialEq)]
8pub struct Rank(u8);
9
09822a98
SW
10#[derive(Clone, Copy, Eq, PartialEq)]
11pub struct Suit(u8);
12
13#[derive(Clone, Copy, Eq, PartialEq)]
14pub struct Card(u8);
15impl Card {
16 #[must_use]
17 pub fn rank(&self) -> Rank {
18 Rank(self.0 >> 2)
19 }
20 #[must_use]
21 pub fn suit(&self) -> Suit {
22 Suit(self.0 & 3)
23 }
24}
25
26#[must_use]
27pub fn deck() -> Vec<Card> {
28 (0..NUM_CARDS).map(Card).collect()
29}
30
57f490a0
SW
31#[derive(Clone, Copy)]
32pub struct PathLength(Rank);
33
34#[derive(Clone, Copy, Default)]
35pub struct PathLengthInfo(u16);
36impl PathLengthInfo {
37 #[must_use]
38 pub fn is_showing(&self, i: Rank) -> bool {
39 (self.0 >> i.0) & 1 == 1
40 }
41 fn reveal(&mut self, i: Rank) {
42 self.0 |= 1 << i.0;
43 }
44 pub fn reveal_random(&mut self, true_length: PathLength) -> Option<Rank> {
45 let showing = u8::try_from(self.0.count_ones()).expect("There aren't that many bits");
46 let not_showing = NUM_RANKS - showing;
47 if not_showing <= 1 {
48 return None;
49 }
50
51 let mut show = rand::thread_rng().gen_range(0..not_showing - 1);
52 for i in 0..NUM_RANKS {
53 let r = Rank(i);
54 if !self.is_showing(r) && r != true_length.0 {
55 if show == 0 {
56 self.reveal(r);
57 return Some(r);
58 }
59 show -= 1;
60 }
61 }
62 unreachable!()
63 }
754e9730
SW
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
57f490a0
SW
71 fn path_length_info_random_reveal() {
72 let length = PathLength(Rank(7));
73 let mut pli = PathLengthInfo::default();
74 for _ in 0..12 {
75 let old_pli = PathLengthInfo::clone(&pli);
76 match pli.reveal_random(length) {
77 None => panic!("Nothing revealed?"),
78 Some(r) => {
79 assert!(!old_pli.is_showing(r));
80 assert!(pli.is_showing(r));
81 }
82 }
83 assert_eq!(pli.0.count_ones(), 1 + old_pli.0.count_ones());
84 }
85 assert!(pli.reveal_random(length).is_none());
754e9730 86 }
09822a98
SW
87
88 #[test]
89 fn test_deck() {
90 let _d = deck();
91 }
754e9730 92}