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.

/// This is the implementation of a Deck of cards.
/// There are two basic kinds:
/// 1. The Game Deck, automatically generated 104 cards.
/// 2. Any Deck-type pile, like the hand of a Player.
/// Descks can be shuffled, cards pushed to bottom and
/// pulled from top. Maybe others, too.
/// 

use std::collections::VecDeque;
use rand::Rng;

/// We reference [`Card`]s
use crate::card::Card;

#[derive(Debug)]
/// A Deck is an ordered two-ended vector (`VecDeque`) of [`Card`]s.
pub(crate) struct Deck {
    content: VecDeque<Card>,
}

impl Deck {
    /// Creates an empty [`Deck`] of undefined size
    pub(crate) fn new_empty() -> Self {
        debug!("Empty deck generated");
        Deck {
            content: VecDeque::new(),
        }
    }

    /// Creates a new full [`Deck`] with 104 cards.
    pub(crate) fn new() -> Self {
        debug!("Full deck generated");
        let content = (1..=104).into_iter().map( |n| Card::new(n) ).collect();
        Deck {
            content,
        }
    }

    /// Shuffles this [`Deck`] (using its default method)
    pub(crate) fn shuffle( &mut self ) {
        let mut rng = rand::thread_rng();
        
        trace!("Deck before shuffle: len {}, {:?}", self.content.len(), self);
        debug!("Deck shuffled");
        // shufflers:
        // * naive: swap cards n times
        // * kgb: half the deck, take 1..4 cards sequentially from each
        // * grin: take 1..6 from front and put at bottom

        // naive shuffle: exchange <n> random cards
        for _ in 1..=500 {
            // Generate two random positions of cards in Deck
            let c1 = rng.gen_range(0 .. self.content.len());
            let c2 = rng.gen_range(0 .. self.content.len());
            // If it's not the same card we swap them in the `content` vector.
            // The `swap()` funtion handles ownership and does not angry 
            // the borrow checker.
            if c1 != c2 {
                self.content.swap(c1, c2);
            }
        }
        trace!("Deck after shuffle: len {}, {:?}", self.content.len(), self);
    }

    /// Returns the top card of this [`Deck`].
    pub(crate) fn pop( &mut self ) -> Option<Card> {
        self.content.pop_front() 
    }

    /// Put a card into the bottom of the [`Deck`]
    pub(crate) fn push( &mut self, c: Card ) {
        self.content.push_back(c);
    }

    /// Push multiple cards to the bottom of the [`Deck`]
    pub(crate) fn push_cards( &mut self, cards: VecDeque<Card> ) {
        trace!("Collecting back, deck len is {}, cards {}", self.content.len(), cards.len());
        cards.into_iter().for_each( |card| self.push(card) );
        trace!("Deck len is {}", self.content.len());
    }

    /// Returns the length of this [`Deck`].
    pub(crate) fn len( &self ) -> usize {
        self.content.len()
    }

    /// Take a card from inside of the Deck.
    /// Using an illegal index will `panic!()`, so don't.
    fn _get_nth( &mut self, n: usize ) -> Card {
        if let Some(c) = self.content.remove(n) {
            c
        } else {
            panic!("get_nth: index {} out of bounds ({})!", n, self.content.len());
        }
    }
}