3 pub const NUM_RANKS: usize = 13;
4 pub const NUM_SUITS: usize = 4;
5 pub const NUM_JOKERS: usize = 2;
6 pub const NUM_CARDS: usize = NUM_RANKS * NUM_SUITS + NUM_JOKERS;
8 #[derive(Clone, Copy, Eq, PartialEq)]
12 pub fn value(&self) -> u8 {
17 #[derive(Clone, Copy, Eq, PartialEq)]
20 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
24 pub fn is_joker(&self) -> bool {
25 usize::from(self.0) >= NUM_RANKS * NUM_SUITS
28 pub fn rank(&self) -> Option<Rank> {
29 (!self.is_joker()).then_some(Rank(self.0 >> 2))
32 pub fn suit(&self) -> Option<Suit> {
33 (!self.is_joker()).then_some(Suit(self.0 & 3))
37 #[derive(Clone, Copy)]
38 pub enum WithOrWithoutJokers {
44 pub fn deck(j: WithOrWithoutJokers) -> Vec<Card> {
45 let limit = u8::try_from(match j {
46 WithOrWithoutJokers::WithJokers => NUM_CARDS,
47 WithOrWithoutJokers::WithoutJokers => NUM_SUITS * NUM_RANKS,
49 .expect("Too many cards?");
50 (0..limit).map(Card).collect()
53 #[derive(Clone, Copy)]
54 pub struct PathLength(Rank);
56 #[derive(Clone, Copy, Default)]
57 pub struct PathLengthInfo(u16);
60 pub fn is_showing(&self, i: Rank) -> bool {
61 (self.0 >> i.0) & 1 == 1
63 fn reveal(&mut self, i: Rank) {
66 pub fn reveal_random(&mut self, true_length: PathLength) -> Option<Rank> {
67 let showing = usize::try_from(self.0.count_ones()).expect("There aren't that many bits");
68 let not_showing = NUM_RANKS - showing;
73 let mut show = rand::thread_rng().gen_range(0..not_showing - 1);
74 for i in 0..NUM_RANKS {
75 let r = Rank(u8::try_from(i).expect("Too many cards?"));
76 if !self.is_showing(r) && r != true_length.0 {
93 pub fn discard(&mut self, card: Card) {
94 self.cards.push(card);
103 pub fn new(cards: Vec<Card>) -> Self {
106 pub fn draw(&mut self, discard: &mut Discard) -> Option<Card> {
107 if self.cards.is_empty() {
108 if let Some(top_discard) = discard.cards.pop() {
109 std::mem::swap(&mut self.cards, &mut discard.cards);
110 discard.discard(top_discard);
123 fn path_length_info_random_reveal() {
124 let length = PathLength(Rank(7));
125 let mut pli = PathLengthInfo::default();
127 let old_pli = PathLengthInfo::clone(&pli);
128 match pli.reveal_random(length) {
129 None => panic!("Nothing revealed?"),
131 assert!(!old_pli.is_showing(r));
132 assert!(pli.is_showing(r));
135 assert_eq!(pli.0.count_ones(), 1 + old_pli.0.count_ones());
137 assert!(pli.reveal_random(length).is_none());
142 use WithOrWithoutJokers::*;
143 let d = deck(WithoutJokers);
144 let rank_sum: u32 = d
148 .map(|r| u32::from(r.value()))
150 assert_eq!(rank_sum, 364);
151 let _dj = deck(WithJokers);
156 let mut lib = Library::new(vec![Card(7)]);
157 let mut dis = Discard::default();
158 dis.discard(Card(8));
159 dis.discard(Card(9));
160 assert_eq!(lib.draw(&mut dis), Some(Card(7)));
161 assert_eq!(lib.draw(&mut dis), Some(Card(8)));
162 assert_eq!(lib.draw(&mut dis), None);