bridge_deck/
lib.rs

1#![deny(missing_docs)]
2//! This crate defines a type [`Card`] for an individual card ([`Card`]) and
3//! another type [`Cards`] for a deck or hand of cards.
4
5/// A single card
6#[derive(Copy, Clone, PartialEq, Eq)]
7pub struct Card {
8    offset: u8,
9}
10
11impl std::fmt::Debug for Card {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        let rank = self.rank();
14        match rank {
15            11 => write!(f, "J{:?}", self.suit()),
16            12 => write!(f, "Q{:?}", self.suit()),
17            13 => write!(f, "K{:?}", self.suit()),
18            14 => write!(f, "A{:?}", self.suit()),
19            _ => write!(f, "{}{:?}", rank, self.suit()),
20        }
21    }
22}
23impl std::fmt::Debug for Suit {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        match self {
26            Suit::Clubs => write!(f, "C"),
27            Suit::Diamonds => write!(f, "D"),
28            Suit::Hearts => write!(f, "H"),
29            Suit::Spades => write!(f, "S"),
30        }
31    }
32}
33
34#[test]
35fn debug() {
36    assert_eq!(&format!("{:?}", Card::new(Suit::Hearts, 4)), "4H");
37    assert_eq!(&format!("{:?}", Card::SA), "AS");
38}
39
40/// This module defines card constants
41impl Card {
42    /// Create a new card with given rank and suit.
43    pub const fn new(suit: Suit, rank: u8) -> Card {
44        // debug_assert!(rank < 15);
45        // debug_assert!(rank > 1);
46        Card {
47            offset: rank + 16 * suit as u8,
48        }
49    }
50    /// What is the Suit?
51    pub const fn suit(self) -> Suit {
52        match self.offset >> 4 {
53            0 => Suit::Clubs,
54            1 => Suit::Diamonds,
55            2 => Suit::Hearts,
56            _ => Suit::Spades,
57        }
58    }
59    /// What is my rank?
60    pub const fn rank(self) -> u8 {
61        self.offset % 16
62    }
63    /// 2 of Clubs
64    pub const C2: Card = Card::new(Suit::Clubs, 2);
65    /// 3 of Clubs
66    pub const C3: Card = Card::new(Suit::Clubs, 3);
67    /// 4 of Clubs
68    pub const C4: Card = Card::new(Suit::Clubs, 4);
69    /// 5 of Clubs
70    pub const C5: Card = Card::new(Suit::Clubs, 5);
71    /// 6 of Clubs
72    pub const C6: Card = Card::new(Suit::Clubs, 6);
73    /// 7 of Clubs
74    pub const C7: Card = Card::new(Suit::Clubs, 7);
75    /// 8 of Clubs
76    pub const C8: Card = Card::new(Suit::Clubs, 8);
77    /// 9 of Clubs
78    pub const C9: Card = Card::new(Suit::Clubs, 9);
79    /// 10 of Clubs
80    pub const C10: Card = Card::new(Suit::Clubs, 10);
81    /// Jack of Clubs
82    pub const CJ: Card = Card::new(Suit::Clubs, 11);
83    /// Queen of Clubs
84    pub const CQ: Card = Card::new(Suit::Clubs, 12);
85    /// King of Clubs
86    pub const CK: Card = Card::new(Suit::Clubs, 13);
87    /// Ace of Clubs
88    pub const CA: Card = Card::new(Suit::Clubs, 14);
89
90    /// 2 of Diamonds
91    pub const D2: Card = Card::new(Suit::Diamonds, 2);
92    /// 3 of Diamonds
93    pub const D3: Card = Card::new(Suit::Diamonds, 3);
94    /// 4 of Diamonds
95    pub const D4: Card = Card::new(Suit::Diamonds, 4);
96    /// 5 of Diamonds
97    pub const D5: Card = Card::new(Suit::Diamonds, 5);
98    /// 6 of Diamonds
99    pub const D6: Card = Card::new(Suit::Diamonds, 6);
100    /// 7 of Diamonds
101    pub const D7: Card = Card::new(Suit::Diamonds, 7);
102    /// 8 of Diamonds
103    pub const D8: Card = Card::new(Suit::Diamonds, 8);
104    /// 9 of Diamonds
105    pub const D9: Card = Card::new(Suit::Diamonds, 9);
106    /// 10 of Diamonds
107    pub const D10: Card = Card::new(Suit::Diamonds, 10);
108    /// Jack of Diamonds
109    pub const DJ: Card = Card::new(Suit::Diamonds, 11);
110    /// Queen of Diamonds
111    pub const DQ: Card = Card::new(Suit::Diamonds, 12);
112    /// King of Diamonds
113    pub const DK: Card = Card::new(Suit::Diamonds, 13);
114    /// Ace of Diamonds
115    pub const DA: Card = Card::new(Suit::Diamonds, 14);
116
117    /// 2 of Hearts
118    pub const H2: Card = Card::new(Suit::Hearts, 2);
119    /// 3 of Hearts
120    pub const H3: Card = Card::new(Suit::Hearts, 3);
121    /// 4 of Hearts
122    pub const H4: Card = Card::new(Suit::Hearts, 4);
123    /// 5 of Hearts
124    pub const H5: Card = Card::new(Suit::Hearts, 5);
125    /// 6 of Hearts
126    pub const H6: Card = Card::new(Suit::Hearts, 6);
127    /// 7 of Hearts
128    pub const H7: Card = Card::new(Suit::Hearts, 7);
129    /// 8 of Hearts
130    pub const H8: Card = Card::new(Suit::Hearts, 8);
131    /// 9 of Hearts
132    pub const H9: Card = Card::new(Suit::Hearts, 9);
133    /// 10 of Hearts
134    pub const H10: Card = Card::new(Suit::Hearts, 10);
135    /// Jack of Hearts
136    pub const HJ: Card = Card::new(Suit::Hearts, 11);
137    /// Queen of Hearts
138    pub const HQ: Card = Card::new(Suit::Hearts, 12);
139    /// King of Hearts
140    pub const HK: Card = Card::new(Suit::Hearts, 13);
141    /// Ace of Hearts
142    pub const HA: Card = Card::new(Suit::Hearts, 14);
143
144    /// 2 of Spades
145    pub const S2: Card = Card::new(Suit::Spades, 2);
146    /// 3 of Spades
147    pub const S3: Card = Card::new(Suit::Spades, 3);
148    /// 4 of Spades
149    pub const S4: Card = Card::new(Suit::Spades, 4);
150    /// 5 of Spades
151    pub const S5: Card = Card::new(Suit::Spades, 5);
152    /// 6 of Spades
153    pub const S6: Card = Card::new(Suit::Spades, 6);
154    /// 7 of Spades
155    pub const S7: Card = Card::new(Suit::Spades, 7);
156    /// 8 of Spades
157    pub const S8: Card = Card::new(Suit::Spades, 8);
158    /// 9 of Spades
159    pub const S9: Card = Card::new(Suit::Spades, 9);
160    /// 10 of Spades
161    pub const S10: Card = Card::new(Suit::Spades, 10);
162    /// Jack of Spades
163    pub const SJ: Card = Card::new(Suit::Spades, 11);
164    /// Queen of Spades
165    pub const SQ: Card = Card::new(Suit::Spades, 12);
166    /// King of Spades
167    pub const SK: Card = Card::new(Suit::Spades, 13);
168    /// Ace of Spades
169    pub const SA: Card = Card::new(Suit::Spades, 14);
170}
171
172/// The four suits
173#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
174pub enum Suit {
175    /// Clubs
176    Clubs = 0,
177    /// Diamonds
178    Diamonds = 1,
179    /// Hearts
180    Hearts = 2,
181    /// Spades
182    Spades = 3,
183}
184
185/// A deck or hand of cards
186///
187/// This data structure assumes that each card can appear only once, as in the
188/// game bridge.  If you want to allow more than one deck mixed together you
189/// want a different crate.  Because each card can only appear once, `Cards` is
190/// `Copy` and only takes 64 bits.  This makes it fast and memory efficient.
191#[derive(Copy, Clone, PartialEq, Eq, Debug)]
192pub struct Cards {
193    bits: u64,
194}
195
196impl Cards {
197    /// How many cards are there?
198    pub const fn len(&self) -> usize {
199        self.bits.count_ones() as usize
200    }
201
202    /// insert a card to the deck or hand
203    pub fn insert(&mut self, card: Card) {
204        self.bits = self.bits | (1 << card.offset)
205    }
206
207    /// Check if we contain a card
208    pub fn contains(&self, card: Card) -> bool {
209        self.bits & (1 << card.offset) != 0
210    }
211
212    /// Join two stacks of cards together
213    pub fn union(&self, cards: Cards) -> Cards {
214        Cards {
215            bits: self.bits | cards.bits,
216        }
217    }
218
219    /// Randomly pick `num` cards to remove from the deck.
220    /// Returns `None` only if there aren't enough cards.
221    pub fn pick(&mut self, mut num: usize) -> Option<Cards> {
222        let mut bits = self.bits;
223        let mut n_left = self.len();
224        if num > n_left {
225            return None;
226        }
227        let mut kept = 0;
228        let mut given = 0;
229        let mut rng = rand::thread_rng();
230        while n_left > 0 {
231            if n_left == num {
232                given |= bits;
233                break;
234            } else if num == 0 {
235                kept |= bits;
236                break;
237            }
238            use rand::Rng;
239            let chosen = rng.gen::<u64>() & bits;
240            if chosen != 0 {
241                let num_chosen = chosen.count_ones() as usize;
242                if num_chosen <= num {
243                    bits &= !chosen;
244                    given |= chosen;
245                    n_left -= num_chosen;
246                    num -= num_chosen;
247                } else if num_chosen + num < n_left {
248                    bits &= !chosen;
249                    kept |= chosen;
250                    n_left -= num_chosen;
251                }
252            }
253        }
254        self.bits = kept;
255        Some(Cards { bits: given })
256    }
257
258    /// All 52 cards.
259    pub const ALL: Cards = Cards {
260        bits: 0x7ffc + (0x7ffc << 16) + (0x7ffc << 32) + (0x7ffc << 48),
261    };
262    /// A deck or hand with no cards in it.
263    pub const EMPTY: Cards = Cards { bits: 0 };
264}
265
266impl Iterator for Cards {
267    type Item = Card;
268
269    fn next(&mut self) -> Option<Self::Item> {
270        if self.bits == 0 {
271            None
272        } else {
273            let next = self.bits.trailing_zeros();
274            self.bits = self.bits & !(1 << next);
275            Some(Card { offset: next as u8 })
276        }
277    }
278}
279
280#[test]
281fn all_cards() {
282    for c in Cards::ALL {
283        println!("c: {:?}", c);
284    }
285    assert_eq!(Cards::ALL.len(), 52);
286}
287#[test]
288fn iterate() {
289    let mut cards = Cards::EMPTY;
290    assert_eq!(cards.next(), None);
291    assert_eq!(cards.len(), 0);
292    cards.insert(Card::C2);
293    assert_eq!(cards.len(), 1);
294    cards.insert(Card::C4);
295    assert_eq!(cards.len(), 2);
296    assert!(cards.contains(Card::C4));
297    assert!(!cards.contains(Card::C3));
298    assert!(cards.contains(Card::C2));
299    assert_eq!(cards.next(), Some(Card::C2));
300    assert_eq!(cards.next(), Some(Card::C4));
301    assert_eq!(cards.next(), None);
302
303    assert_eq!(cards.len(), 0);
304    cards.insert(Card::C2);
305    assert_eq!(cards.len(), 1);
306    cards.insert(Card::C4);
307    assert_eq!(cards.len(), 2);
308
309    let two_cards = cards;
310
311    let mut hand = cards.pick(2).unwrap();
312    assert_eq!(cards.len(), 0);
313    assert_eq!(hand.len(), 2);
314    assert_eq!(hand, two_cards);
315
316    let other = hand.pick(1).unwrap();
317    assert_eq!(other.union(hand), two_cards);
318}