games-rs 0.5.0

Pre-implemented games written in rust.
Documentation
//! Deck of cards
//!
//! Cards that implement `DefaultCollection` can use Deck::default
//! ```
//! use games::deck::Deck;
//! use games::cards::StandardCard;
//! // Usable with cards that implement games::deck::DefaultCollection
//! let deck: Deck<StandardCard> = Deck::default();
//! ```
//! Otherwise use Deck::new
//! ```
//! use games::deck::{Deck, DefaultCollection};
//! use games::cards::StandardCard;
//! // Cards that don't implement DefaultCollection must use Deck::from
//! let deck: Deck<StandardCard> = Deck::from(StandardCard::default_collection());
//! ```
//! DeckBuilder can also be used to create a deck, with default only being implemented for
//! `DefaultCollection`
//! ```
//! use games::deck::{DeckBuilder, Deck, DefaultCollection};
//! use games::cards::StandardCard;
//! let deck: Deck<StandardCard> = DeckBuilder::default().sets(5).build();
//! // OR
//! let deck: Deck<StandardCard> = DeckBuilder::from(StandardCard::default_collection()).sets(2).build();
//! ```

use crate::cards::StandardCard;
use crate::deck_of_cards::STANDARD_DECK_OF_CARDS;
use crate::errors::{BASE_DECK_ERROR_CODE, ErrorCode};
use core::fmt::{self, Debug, Display};
use rand::RngExt;
use std::{collections::VecDeque, collections::vec_deque::IntoIter as DequeIntoIter};

/// Create a default collection
pub trait DefaultCollection: Copy + Clone + Debug + Ord + Display {
    /// Create a default collection
    fn default_collection() -> VecDeque<Self>;
    /// Create n default collections
    fn multiple_collections(n: usize) -> VecDeque<Self> {
        let c = Self::default_collection();
        let set_len = c.len();
        c.into_iter().cycle().take(set_len * n).collect()
    }
    /// Create a deck of Card from default collection
    fn create_deck() -> Deck<Self> {
        Deck::default()
    }
}

impl DefaultCollection for StandardCard {
    fn default_collection() -> VecDeque<Self> {
        STANDARD_DECK_OF_CARDS.iter().copied().collect()
    }
    fn multiple_collections(n: usize) -> VecDeque<Self> {
        STANDARD_DECK_OF_CARDS
            .iter()
            .copied()
            .cycle()
            .take(52usize * n)
            .collect()
    }
}

/// Standard card deck
#[repr(C)]
#[derive(
    Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq, Ord, PartialOrd, Hash,
)]
pub struct Deck<C: Copy + Clone + Debug + Ord + Display>(pub(crate) VecDeque<C>);

/// Deck error
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub enum DeckError {
    /// No cards left in the deck (6001)
    NoCard,
}

impl Display for DeckError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DeckError::NoCard => f.write_str("No Cards are left in the deck"),
        }
    }
}

impl ErrorCode for DeckError {
    fn error_code(&self) -> i32 {
        BASE_DECK_ERROR_CODE
            + match *self {
                DeckError::NoCard => 1,
            }
    }
}
impl<C: Copy + Clone + Debug + Ord + Display> Deck<C> {
    /// Draw a card from the deck at random
    ///
    /// # Errors
    /// Returns an error if the deck is out of cards
    pub fn draw(&mut self) -> Result<C, DeckError> {
        self.0.pop_front().ok_or(DeckError::NoCard)
    }
    /// Randomly draw a card
    ///
    /// # Errors
    ///
    /// Errors if there are no cards to draw
    pub fn draw_random(&mut self) -> Result<C, DeckError> {
        if self.0.is_empty() {
            return Err(DeckError::NoCard);
        }

        let len = self.0.len();
        if len == 1 {
            self.0.pop_front().ok_or(DeckError::NoCard)
        } else {
            let index = crate::get_rng().random_range(0..len);
            self.0.remove(index).ok_or(DeckError::NoCard)
        }
    }
    /// Randomly draw up to <count> cards, will stop early if out of cards
    /// This only shuffles the selected [count,len) range of cards
    /// For a mores random draw, use .shuffle() then .draw_many()
    pub fn draw_many_random(&mut self, count: usize) -> Vec<C> {
        if self.0.is_empty() || count == 0 {
            return Vec::with_capacity(0);
        }
        let len = self.0.len();
        let mut rng = crate::get_rng();
        let mid = len.saturating_sub(count);
        // Shuffle partialy, not sure if I should fully shuffle here
        for i in (len..mid).rev() {
            let idx = rng.random_range(0..(i + 1));
            // invariant: elements with index > i have been locked in place.
            self.0.swap(i, idx);
        }
        self.0.split_off(mid).into()
    }
    /// Draw up to <count> cards, will stop early if out of cards
    pub fn draw_many(&mut self, count: usize) -> Vec<C> {
        if self.0.is_empty() || count == 0 {
            return Vec::with_capacity(0);
        }
        let len = self.0.len();
        if count >= len {
            self.0.drain(..).collect()
        } else {
            self.0.split_off(len - count).into()
        }
    }
    /// Draw the rest of the cards
    pub fn draw_rest(&mut self) -> Vec<C> {
        self.0.drain(0..).collect()
    }
    /// Randomly draw the rest of the cards
    pub fn draw_rest_random(&mut self) -> Vec<C> {
        self.shuffle();
        self.0.drain(0..).collect()
    }
    /// Insert a card into the deck
    pub fn insert(&mut self, card: C) {
        self.0.push_back(card);
    }
    /// Convert the dec into a vector of cards
    pub fn into_vec(self) -> Vec<C> {
        self.0.into()
    }
    /// Shuffle the deck
    pub fn shuffle(&mut self) {
        let mut rng = crate::get_rng();
        for i in (1..self.len()).rev() {
            let idx = rng.random_range(0..(i + 1));
            // invariant: elements with index > i have been locked in place.
            self.0.swap(i, idx);
        }
    }
    /// Peek at the next card
    pub fn peek(&self) -> Option<&C> {
        self.0.front()
    }
    /// Create a new deck of cards
    pub fn from_cards(cards: Vec<C>) -> Self {
        Self(cards.into())
    }
    /// Check if the deck is empty
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
    /// Length of the cards in the deck
    pub fn len(&self) -> usize {
        self.0.len()
    }
    /// Create an empty deck of cards
    pub fn empty() -> Self {
        Self(VecDeque::new())
    }
}
impl<C: DefaultCollection> Default for Deck<C> {
    fn default() -> Deck<C> {
        Self(C::default_collection())
    }
}

impl<C: Copy + Clone + Debug + Ord + Display> Extend<C> for Deck<C> {
    fn extend<I: IntoIterator<Item = C>>(&mut self, iter: I) {
        self.0.extend(iter)
    }
}

impl<C: Copy + Clone + Debug + Ord + Display> core::iter::FromIterator<C> for Deck<C> {
    fn from_iter<I: IntoIterator<Item = C>>(iter: I) -> Self {
        let mut c = Self::empty();
        c.extend(iter);
        c
    }
}

impl<C: Copy + Clone + Debug + Ord + Display> IntoIterator for Deck<C> {
    type Item = C;
    type IntoIter = DequeIntoIter<C>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

/// Builder for `games::deck::Deck`
/// ```
/// use games::cards::StandardCard;
/// use games::deck::{Deck,DeckBuilder};
/// let deck: Deck<StandardCard> = DeckBuilder::default().sets(5).build();
/// ```
#[derive(Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct DeckBuilder<C: Copy + Clone + Debug + Ord + Display>(Vec<C>);
impl<C: Copy + Clone + Debug + Ord + Display> DeckBuilder<C> {
    /// Increase the sets of cause
    /// NOTE: Using this multiple times will have a multiplicative effect
    /// EX: sets(5).sets(5) will create 25 sets
    pub fn sets(mut self, n: usize) -> Self {
        let set_len = self.0.len();
        self.0 = self.0.into_iter().cycle().take(set_len * n).collect();
        self
    }
    /// Build the deck of cards
    pub fn build(self) -> Deck<C> {
        Deck(self.0.into())
    }
}
impl<C: DefaultCollection> Default for DeckBuilder<C> {
    fn default() -> DeckBuilder<C> {
        Self(C::default_collection().into())
    }
}

impl<C: Copy + Clone + Debug + Ord + Display> From<Vec<C>> for Deck<C> {
    fn from(cards: Vec<C>) -> Self {
        Self(cards.into())
    }
}

impl<C: Copy + Clone + Debug + Ord + Display> From<VecDeque<C>> for Deck<C> {
    fn from(cards: VecDeque<C>) -> Self {
        Self(cards)
    }
}

impl<C: Copy + Clone + Debug + Ord + Display> From<Vec<C>> for DeckBuilder<C> {
    fn from(cards: Vec<C>) -> Self {
        Self(cards)
    }
}
impl<C: Copy + Clone + Debug + Ord + Display> From<VecDeque<C>> for DeckBuilder<C> {
    fn from(cards: VecDeque<C>) -> Self {
        Self(cards.into())
    }
}