src/deck.rs
author Peter Gervai <grin@grin.hu>
Sat, 04 Feb 2023 22:46:13 +0100
changeset 5 0dd7f2c9fd81
parent 4 a2f0cb2b5c13
permissions -rw-r--r--
Comments. Lot of Comments.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     1
/// This is the implementation of a Deck of cards.
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     2
/// There are two basic kinds:
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     3
/// 1. The Game Deck, automatically generated 104 cards.
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     4
/// 2. Any Deck-type pile, like the hand of a Player.
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     5
/// Descks can be shuffled, cards pushed to bottom and
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     6
/// pulled from top. Maybe others, too.
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     7
/// 
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
     8
4
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
     9
use std::collections::VecDeque;
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    10
use rand::Rng;
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    11
5
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    12
/// We reference [`Card`]s
4
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    13
use crate::card::Card;
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    14
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    15
#[derive(Debug)]
5
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    16
/// A Deck is an ordered two-ended vector (`VecDeque`) of [`Card`]s.
4
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    17
pub(crate) struct Deck {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    18
    content: VecDeque<Card>,
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    19
}
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    20
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    21
impl Deck {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    22
    /// Creates an empty [`Deck`] of undefined size
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    23
    pub(crate) fn new_empty() -> Self {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    24
        debug!("Empty deck generated");
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    25
        Deck {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    26
            content: VecDeque::new(),
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    27
        }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    28
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    29
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    30
    /// Creates a new full [`Deck`] with 104 cards.
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    31
    pub(crate) fn new() -> Self {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    32
        debug!("Full deck generated");
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    33
        let content = (1..=104).into_iter().map( |n| Card::new(n) ).collect();
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    34
        Deck {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    35
            content,
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    36
        }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    37
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    38
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    39
    /// Shuffles this [`Deck`] (using its default method)
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    40
    pub(crate) fn shuffle( &mut self ) {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    41
        let mut rng = rand::thread_rng();
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    42
        
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    43
        trace!("Deck before shuffle: len {}, {:?}", self.content.len(), self);
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    44
        debug!("Deck shuffled");
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    45
        // shufflers:
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    46
        // * naive: swap cards n times
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    47
        // * kgb: half the deck, take 1..4 cards sequentially from each
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    48
        // * grin: take 1..6 from front and put at bottom
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    49
5
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    50
        // naive shuffle: exchange <n> random cards
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    51
        for _ in 1..=500 {
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    52
            // Generate two random positions of cards in Deck
4
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    53
            let c1 = rng.gen_range(0 .. self.content.len());
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    54
            let c2 = rng.gen_range(0 .. self.content.len());
5
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    55
            // If it's not the same card we swap them in the `content` vector.
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    56
            // The `swap()` funtion handles ownership and does not angry 
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    57
            // the borrow checker.
4
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    58
            if c1 != c2 {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    59
                self.content.swap(c1, c2);
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    60
            }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    61
        }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    62
        trace!("Deck after shuffle: len {}, {:?}", self.content.len(), self);
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    63
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    64
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    65
    /// Returns the top card of this [`Deck`].
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    66
    pub(crate) fn pop( &mut self ) -> Option<Card> {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    67
        self.content.pop_front() 
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    68
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    69
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    70
    /// Put a card into the bottom of the [`Deck`]
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    71
    pub(crate) fn push( &mut self, c: Card ) {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    72
        self.content.push_back(c);
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    73
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    74
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    75
    /// Push multiple cards to the bottom of the [`Deck`]
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    76
    pub(crate) fn push_cards( &mut self, cards: VecDeque<Card> ) {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    77
        trace!("Collecting back, deck len is {}, cards {}", self.content.len(), cards.len());
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    78
        cards.into_iter().for_each( |card| self.push(card) );
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    79
        trace!("Deck len is {}", self.content.len());
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    80
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    81
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    82
    /// Returns the length of this [`Deck`].
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    83
    pub(crate) fn len( &self ) -> usize {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    84
        self.content.len()
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    85
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    86
5
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    87
    /// Take a card from inside of the Deck.
0dd7f2c9fd81 Comments. Lot of Comments.
Peter Gervai <grin@grin.hu>
parents: 4
diff changeset
    88
    /// Using an illegal index will `panic!()`, so don't.
4
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    89
    fn _get_nth( &mut self, n: usize ) -> Card {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    90
        if let Some(c) = self.content.remove(n) {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    91
            c
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    92
        } else {
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    93
            panic!("get_nth: index {} out of bounds ({})!", n, self.content.len());
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    94
        }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    95
    }
a2f0cb2b5c13 Split main into module files.
Peter Gervai <grin@grin.hu>
parents:
diff changeset
    96
}