games-rs 0.5.0

Pre-implemented games written in rust.
Documentation
use crate::cards::StandardCard as Card;

/// Used to manage BlackJack hands
#[repr(C)]
#[derive(
    Clone,
    Debug,
    Default,
    serde::Serialize,
    serde::Deserialize,
    Eq,
    PartialEq,
    Ord,
    PartialOrd,
    Hash,
)]
pub(crate) struct Hand(Vec<Card>);

impl Hand {
    /// Add a card to hand
    pub(crate) fn add_card(&mut self, card: Card) {
        self.0.push(card)
    }

    /// Calculate the score
    pub(crate) fn score(&self) -> u8 {
        //
        self.0
            .iter()
            .try_fold((0u8, 0u8), |(mut ace_count, mut total), c| {
                // Get the face value of the card
                let val = c.face().value();
                // If the value is 11, its an ace
                if val == 11 {
                    ace_count = ace_count.checked_add(1)?;
                // Not an ace
                } else {
                    // Increase the total by the face value
                    total = total.checked_add(val)?;
                }
                Some((ace_count, total))
            })
            .and_then(|(mut ace_count, mut total)| {
                // If there is more than one ace
                if ace_count >= 1 {
                    // And the total is less than 10
                    if total <= 10 {
                        // The ace is worth 11 points
                        total = total.checked_add(11)?;
                    } else {
                        // Otherwise the ace is worth 1
                        total = total.checked_add(1)?;
                    }
                    // Reduce the ace count by 1
                    ace_count = ace_count.checked_sub(1)?;
                }
                // ace_count is to total of all other aces
                // because the value of the other aces is 1

                // Question: If the sum of aces + the 10 ace push it over 21, should the original ace be set to the value of 1?
                Some(total + ace_count)
            })
            .unwrap_or(0)
    }
    pub(crate) fn into_vec(self) -> Vec<Card> {
        self.0
    }
    pub(crate) fn cards_len(&self) -> usize {
        self.0.len()
    }
    pub(crate) fn cards(&self) -> &[Card] {
        &self.0
    }
}

impl From<Vec<Card>> for Hand {
    fn from(cards: Vec<Card>) -> Self {
        Self(cards)
    }
}

impl Extend<Card> for Hand {
    fn extend<I: IntoIterator<Item = Card>>(&mut self, iter: I) {
        self.0.extend(iter);
    }
}

impl core::iter::FromIterator<Card> for Hand {
    fn from_iter<I: IntoIterator<Item = Card>>(iter: I) -> Self {
        let mut c = Hand::default();
        c.extend(iter);
        c
    }
}