From: Geoffrey Allott Date: Sat, 26 Jun 2021 20:21:19 +0000 (+0100) Subject: add initial cribbage scoring X-Git-Url: https://git.pointlesshacks.com/?a=commitdiff_plain;h=945e9789889f6803bd48470667173eeddb22aaa8;p=pokerwave.git add initial cribbage scoring --- diff --git a/src/card.rs b/src/card.rs index 8ffb0f0..9a26e8c 100644 --- a/src/card.rs +++ b/src/card.rs @@ -20,6 +20,26 @@ pub enum Rank { Ace = 14, } +impl Rank { + pub fn ace_low_rank(self) -> u32 { + match self { + Ace => 1, + Two => 2, + Three => 3, + Four => 4, + Five => 5, + Six => 6, + Seven => 7, + Eight => 8, + Nine => 9, + Ten => 10, + Jack => 11, + Queen => 12, + King => 13, + } + } +} + impl Display for Rank { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.write_str(match *self { diff --git a/src/game/cribbage/mod.rs b/src/game/cribbage/mod.rs new file mode 100644 index 0000000..0d47f79 --- /dev/null +++ b/src/game/cribbage/mod.rs @@ -0,0 +1 @@ +mod score; diff --git a/src/game/cribbage/score.rs b/src/game/cribbage/score.rs new file mode 100644 index 0000000..24c5da9 --- /dev/null +++ b/src/game/cribbage/score.rs @@ -0,0 +1,372 @@ +use std::fmt::{self, Display}; + +use itertools::Itertools; + +use crate::card::{Card, Rank}; +use crate::card::Rank::*; + +#[derive(Copy, Clone, Debug)] +pub struct Score { + nob: u8, + flush: u8, + fifteen: u8, + pair: u8, + run: u8, +} + +impl Score { + pub fn points(&self) -> u8 { + self.nob + self.flush + self.fifteen + self.pair + self.run + } +} + +impl Display for Score { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Score { nob: 0, flush: 0, fifteen: 0, pair: 0, run: 0 } => f.write_str("Nineteen"), + Score { nob: 0, flush: 0, fifteen: 2, pair: 0, run: 0 } => f.write_str("Fifteen two, and the rest won't do"), + Score { nob: 0, flush: 0, fifteen: 4, pair: 0, run: 0 } => f.write_str("Fifteen two, fifteen four, look all day, see no more"), + Score { nob: 0, flush: 0, fifteen: 6, pair: 0, run: 0 } => f.write_str("Fifteen two, fifteen four, fifteen six, pick up sticks"), + Score { nob, flush, fifteen, pair, run } => { + let fifteen = match fifteen { + 0 => "", + 2 => "Fifteen two", + 4 => "Fifteen two, fifteen four", + 6 => "Fifteen two, fifteen four, fifteen six", + 8 => "Fifteen two, fifteen four, fifteen six, fifteen eight", + 10 => "Fifteen two, fifteen four, fifteen six, fifteen eight, fifteen ten", + 12 => "Fifteen two, fifteen four, fifteen six, fifteen eight, fifteen ten, fifteen twelve", + 14 => "Fifteen two, fifteen four, fifteen six, fifteen eight, fifteen ten, fifteen twelve, fifteen fourteen", + 16 => "Fifteen two, fifteen four, fifteen six, fifteen eight, fifteen ten, fifteen twelve, fifteen fourteen, fifteen sixteen", + _ => return write!(f, "[ERROR] {:?}", self), + }; + let pair_and_run = match (fifteen, pair, run) { + (_, 0, 0) => "", + ("", 2, 0) => "Two", + (_, 2, 0) => " and two", + ("", 0, 3) => "Three", + (_, 0, 3) => " and three", + ("", 4, 0) => "Two and two", + (_, 4, 0) => " and two and two", + ("", 0, 4) => "Four", + (_, 0, 4) => " and four", + ("", 2, 3) => "Two and three", + (_, 2, 3) => " and two and three", + ("", 0, 5) => "Five", + (_, 0, 5) => " and five", + ("", 6, 0) => "Six", + (_, 6, 0) => " and six", + ("", 8, 0) => "Six and two", + (_, 8, 0) => " and six and two", + ("", 2, 6) => "Eight", + (_, 2, 6) => " and eight", + ("", 2, 8) => "Ten", + (_, 2, 8) => " and ten", + ("", 12, 0) => "Twelve", + (_, 12, 0) => " and twelve", + ("", 6, 9) => "Fifteen", + (_, 6, 9) => " and fifteen", + ("", 4, 12) => "Sixteen", + (_, 4, 12) => " and sixteen", + _ => return write!(f, "[ERROR] {:?}", self), + }; + let flush = match (fifteen, pair_and_run, flush) { + (_, _, 0) => "", + ("", "", 4) => "Four", + (_, _, 4) => " and four", + ("", "", 5) => "Five", + (_, _, 5) => " and five", + _ => return write!(f, "[ERROR] {:?}", self), + }; + let nob = match (fifteen, pair_and_run, flush, nob) { + (_, _, _, 0) => "", + ("", "", "", 1) => "One for his nob", + (_, _, _, 1) => " and one for his nob", + _ => return write!(f, "[ERROR] {:?}", self), + }; + match (fifteen, pair_and_run, flush, nob) { + (fifteen, "", "", "") => f.write_str(fifteen), + ("", pair_and_run, "", "") => f.write_str(pair_and_run), + ("", "", flush, "") => f.write_str(flush), + ("", "", "", nob) => f.write_str(nob), + (fifteen, pair_and_run, flush, nob) => { + f.write_str(fifteen)?; + f.write_str(pair_and_run)?; + f.write_str(flush)?; + f.write_str(nob)?; + write!(f, " is {}", self.points()) + } + } + } + } + } +} + +#[derive(Copy, Clone, Debug)] +pub struct PeggingScore { + fifteen: u8, + thirty_one: u8, + pair: u8, + run: u8, +} + +impl PeggingScore { + pub fn points(&self) -> u8 { + self.fifteen + self.thirty_one + self.pair + self.run + } +} + +impl Display for PeggingScore { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + PeggingScore { fifteen: 0, thirty_one: 0, pair: 0, run: 0 } => Ok(()), + PeggingScore { fifteen: 2, thirty_one: 0, pair: 0, run: 0 } => f.write_str("Fifteen for two"), + PeggingScore { fifteen: 2, thirty_one: 0, pair: 2, run: 0 } => f.write_str("Fifteen two and two is four"), + PeggingScore { fifteen: 2, thirty_one: 0, pair: 0, run: 3 } => f.write_str("Fifteen two and three is five"), + PeggingScore { fifteen: 2, thirty_one: 0, pair: 0, run: 4 } => f.write_str("Fifteen two and four is six"), + PeggingScore { fifteen: 2, thirty_one: 0, pair: 0, run: 5 } => f.write_str("Fifteen two and five is seven"), + PeggingScore { fifteen: 2, thirty_one: 0, pair: 6, run: 0 } => f.write_str("Fifteen two and six is eight"), + PeggingScore { fifteen: 2, thirty_one: 0, pair: 12, run: 0 } => f.write_str("Fifteen two and twelve is fourteen"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 0, run: 0 } => f.write_str("Thirty-one for two"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 2, run: 0 } => f.write_str("Thirty-one for two and two is four"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 0, run: 3 } => f.write_str("Thirty-one for two and three is five"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 0, run: 4 } => f.write_str("Thirty-one for two and four is six"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 0, run: 5 } => f.write_str("Thirty-one for two and five is seven"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 0, run: 6 } => f.write_str("Thirty-one for two and six is eight"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 6, run: 0 } => f.write_str("Thirty-one for two and six is eight"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 0, run: 7 } => f.write_str("Thirty-one for two and seven is nine"), + PeggingScore { fifteen: 0, thirty_one: 2, pair: 12, run: 0 } => f.write_str("Thirty-one for two and twelve is fourteen"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 2, run: 0 } => f.write_str("Two"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 0, run: 3 } => f.write_str("Three"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 0, run: 4 } => f.write_str("Four"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 0, run: 5 } => f.write_str("Five"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 0, run: 6 } => f.write_str("Six"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 6, run: 0 } => f.write_str("Six"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 0, run: 7 } => f.write_str("Seven"), + PeggingScore { fifteen: 0, thirty_one: 0, pair: 12, run: 0 } => f.write_str("Twelve"), + _ => write!(f, "[ERROR] {:?}", self), + } + } +} + +fn value(rank: Rank) -> u32 { + match rank { + Ace => 1, + Two => 2, + Three => 3, + Four => 4, + Five => 5, + Six => 6, + Seven => 7, + Eight => 8, + Nine => 9, + Ten => 10, + Jack => 10, + Queen => 10, + King => 10, + } +} + +fn sum_value(cards: &[Card]) -> u32 { + cards.iter().map(|card| card.rank).map(value).sum() +} + +fn is_run(cards: &[Card]) -> bool { + cards.iter().map(|card| card.rank.ace_low_rank()).sorted().tuple_windows().all(|(rank1, rank2)| rank2 == rank1 + 1) +} + +pub fn score_pegging(cards: &[Card]) -> PeggingScore { + let mut score = PeggingScore { + fifteen: 0, + thirty_one: 0, + pair: 0, + run: 0, + }; + + if sum_value(cards) == 15 { + score.fifteen += 2; + } + + if sum_value(cards) == 31 { + score.thirty_one += 2; + } + + for start in 0..cards.len() { + let run = &cards[start..]; + if run.len() < 3 { + break; + } + if is_run(run) { + score.run += run.len() as u8; + break; + } + } + + for start in 0..cards.len() { + let cards = &cards[start..]; + if cards.len() < 2 { + break; + } + if cards.iter().all_equal() { + score.pair += (cards.len() * (cards.len() - 1)) as u8; + break; + } + } + + score +} + +pub fn score_4_card_cribbage_hand(cards: [Card; 4], turnup: Card, is_box: bool) -> Score { + let mut score = Score { + nob: 0, + flush: 0, + fifteen: 0, + pair: 0, + run: 0, + }; + + for card in &cards { + if card.rank == Jack && card.suit == turnup.suit { + score.nob += 1; + } + } + + if cards[0].suit == cards[1].suit && cards[1].suit == cards[2].suit && cards[2].suit == cards[3].suit && cards[3].suit == turnup.suit { + score.flush += 5; + } else if !is_box && cards[0].suit == cards[1].suit && cards[1].suit == cards[2].suit && cards[2].suit == cards[3].suit { + score.flush += 4; + } + + let cards = [cards[0], cards[1], cards[2], cards[3], turnup]; + for cards in cards.iter().cloned().powerset() { + if sum_value(&cards) == 15 { + score.fifteen += 2; + } + } + + for cards in cards.iter().cloned().combinations(2) { + if cards[0].rank == cards[1].rank { + score.pair += 2; + } + } + + for &run_length in &[5, 4, 3] { + let runs = cards.iter().cloned().combinations(run_length) + .filter(|cards| is_run(cards)) + .count(); + if runs > 0 { + score.run += (run_length * runs) as u8; + break; + } + } + + score +} + +#[cfg(test)] +mod test { + use super::*; + + use crate::card::*; + + #[test] + fn cribbage_hand_rankings_with_display() { + let score = score_4_card_cribbage_hand([ACE_OF_HEARTS, ACE_OF_SPADES, TWO_OF_CLUBS, TWO_OF_DIAMONDS], THREE_OF_HEARTS, false); + assert_eq!(16, score.points()); + assert_eq!("Sixteen", format!("{}", score)); + + let score = score_4_card_cribbage_hand([ACE_OF_HEARTS, ACE_OF_SPADES, SIX_OF_SPADES, SEVEN_OF_CLUBS], SEVEN_OF_DIAMONDS, false); + assert_eq!(12, score.points()); + assert_eq!("Fifteen two, fifteen four, fifteen six, fifteen eight and two and two is 12", format!("{}", score)); + + let score = score_4_card_cribbage_hand([ACE_OF_HEARTS, SEVEN_OF_SPADES, SEVEN_OF_CLUBS, SEVEN_OF_HEARTS], SEVEN_OF_DIAMONDS, false); + assert_eq!(24, score.points()); + assert_eq!("Fifteen two, fifteen four, fifteen six, fifteen eight, fifteen ten, fifteen twelve and twelve is 24", format!("{}", score)); + + let score = score_4_card_cribbage_hand([FIVE_OF_CLUBS, FIVE_OF_DIAMONDS, FIVE_OF_HEARTS, JACK_OF_SPADES], TEN_OF_SPADES, false); + assert_eq!(21, score.points()); + assert_eq!("Fifteen two, fifteen four, fifteen six, fifteen eight, fifteen ten, fifteen twelve, fifteen fourteen and six and one for his nob is 21", format!("{}", score)); + + let score = score_4_card_cribbage_hand([SIX_OF_CLUBS, SEVEN_OF_DIAMONDS, EIGHT_OF_HEARTS, NINE_OF_SPADES], NINE_OF_CLUBS, false); + assert_eq!(16, score.points()); + assert_eq!("Fifteen two, fifteen four, fifteen six and ten is 16", format!("{}", score)); + + let score = score_4_card_cribbage_hand([NINE_OF_CLUBS, TEN_OF_DIAMONDS, JACK_OF_HEARTS, QUEEN_OF_SPADES], KING_OF_CLUBS, false); + assert_eq!(5, score.points()); + assert_eq!("Five", format!("{}", score)); + } + + #[test] + fn cribbage_hand_rankings() { + assert_eq!(16, score_4_card_cribbage_hand([ACE_OF_CLUBS, ACE_OF_DIAMONDS, TWO_OF_HEARTS, TWO_OF_SPADES], THREE_OF_CLUBS, false).points()); + assert_eq!(12, score_4_card_cribbage_hand([ACE_OF_CLUBS, ACE_OF_DIAMONDS, SIX_OF_HEARTS, SEVEN_OF_SPADES], SEVEN_OF_CLUBS, false).points()); + assert_eq!(13, score_4_card_cribbage_hand([ACE_OF_CLUBS, ACE_OF_DIAMONDS, SIX_OF_HEARTS, SEVEN_OF_SPADES], EIGHT_OF_CLUBS, false).points()); + assert_eq!(12, score_4_card_cribbage_hand([ACE_OF_CLUBS, ACE_OF_DIAMONDS, SEVEN_OF_HEARTS, SEVEN_OF_SPADES], EIGHT_OF_CLUBS, false).points()); + assert_eq!(15, score_4_card_cribbage_hand([ACE_OF_CLUBS, TWO_OF_DIAMONDS, THREE_OF_HEARTS, THREE_OF_SPADES], THREE_OF_CLUBS, false).points()); + assert_eq!(12, score_4_card_cribbage_hand([ACE_OF_CLUBS, FOUR_OF_DIAMONDS, FOUR_OF_HEARTS, FOUR_OF_SPADES], TEN_OF_CLUBS, false).points()); + assert_eq!(13, score_4_card_cribbage_hand([ACE_OF_CLUBS, FOUR_OF_DIAMONDS, FOUR_OF_HEARTS, JACK_OF_SPADES], FOUR_OF_SPADES, false).points()); + assert_eq!(24, score_4_card_cribbage_hand([ACE_OF_CLUBS, SEVEN_OF_DIAMONDS, SEVEN_OF_HEARTS, SEVEN_OF_SPADES], SEVEN_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([TWO_OF_CLUBS, TWO_OF_DIAMONDS, TWO_OF_HEARTS, TWO_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(17, score_4_card_cribbage_hand([TWO_OF_CLUBS, THREE_OF_DIAMONDS, FOUR_OF_HEARTS, FOUR_OF_SPADES], FOUR_OF_CLUBS, false).points()); + assert_eq!(16, score_4_card_cribbage_hand([TWO_OF_CLUBS, TWO_OF_DIAMONDS, THREE_OF_HEARTS, THREE_OF_SPADES], FOUR_OF_CLUBS, false).points()); + assert_eq!(17, score_4_card_cribbage_hand([TWO_OF_CLUBS, THREE_OF_DIAMONDS, THREE_OF_HEARTS, THREE_OF_SPADES], FOUR_OF_CLUBS, false).points()); + assert_eq!(12, score_4_card_cribbage_hand([TWO_OF_CLUBS, SIX_OF_DIAMONDS, SIX_OF_HEARTS, SEVEN_OF_SPADES], SEVEN_OF_CLUBS, false).points()); + assert_eq!(16, score_4_card_cribbage_hand([TWO_OF_CLUBS, SIX_OF_DIAMONDS, SEVEN_OF_HEARTS, SEVEN_OF_SPADES], EIGHT_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, THREE_OF_HEARTS, THREE_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(24, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, THREE_OF_HEARTS, THREE_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(21, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, THREE_OF_HEARTS, FOUR_OF_SPADES], FIVE_OF_CLUBS, false).points()); + assert_eq!(18, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, THREE_OF_HEARTS, SIX_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, FOUR_OF_HEARTS, FOUR_OF_SPADES], FIVE_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, FOUR_OF_HEARTS, FIVE_OF_SPADES], FIVE_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, SIX_OF_HEARTS, SIX_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(14, score_4_card_cribbage_hand([THREE_OF_CLUBS, THREE_OF_DIAMONDS, SIX_OF_HEARTS, SIX_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([THREE_OF_CLUBS, FOUR_OF_DIAMONDS, FOUR_OF_HEARTS, FOUR_OF_SPADES], FOUR_OF_CLUBS, false).points()); + assert_eq!(17, score_4_card_cribbage_hand([THREE_OF_CLUBS, FOUR_OF_DIAMONDS, FOUR_OF_HEARTS, FOUR_OF_SPADES], FIVE_OF_CLUBS, false).points()); + assert_eq!(16, score_4_card_cribbage_hand([THREE_OF_CLUBS, FOUR_OF_DIAMONDS, FOUR_OF_HEARTS, FIVE_OF_SPADES], FIVE_OF_CLUBS, false).points()); + assert_eq!(24, score_4_card_cribbage_hand([THREE_OF_CLUBS, SIX_OF_DIAMONDS, SIX_OF_HEARTS, SIX_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(24, score_4_card_cribbage_hand([FOUR_OF_CLUBS, FOUR_OF_DIAMONDS, FOUR_OF_HEARTS, FOUR_OF_SPADES], SEVEN_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([FOUR_OF_CLUBS, FOUR_OF_DIAMONDS, FOUR_OF_HEARTS, SEVEN_OF_SPADES], SEVEN_OF_CLUBS, false).points()); + assert_eq!(24, score_4_card_cribbage_hand([FOUR_OF_CLUBS, FOUR_OF_DIAMONDS, FIVE_OF_HEARTS, SIX_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(14, score_4_card_cribbage_hand([FOUR_OF_CLUBS, FOUR_OF_DIAMONDS, SEVEN_OF_HEARTS, SEVEN_OF_SPADES], SEVEN_OF_CLUBS, false).points()); + assert_eq!(24, score_4_card_cribbage_hand([FOUR_OF_CLUBS, FIVE_OF_DIAMONDS, FIVE_OF_HEARTS, SIX_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(21, score_4_card_cribbage_hand([FOUR_OF_CLUBS, FIVE_OF_DIAMONDS, SIX_OF_HEARTS, SIX_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(23, score_4_card_cribbage_hand([FIVE_OF_CLUBS, FIVE_OF_DIAMONDS, FIVE_OF_HEARTS, FOUR_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(22, score_4_card_cribbage_hand([FIVE_OF_CLUBS, FIVE_OF_DIAMONDS, FIVE_OF_HEARTS, TEN_OF_SPADES], TEN_OF_CLUBS, false).points()); + assert_eq!(23, score_4_card_cribbage_hand([FIVE_OF_CLUBS, FIVE_OF_DIAMONDS, JACK_OF_HEARTS, JACK_OF_SPADES], FIVE_OF_SPADES, false).points()); + assert_eq!(28, score_4_card_cribbage_hand([FIVE_OF_CLUBS, FIVE_OF_DIAMONDS, FIVE_OF_HEARTS, FIVE_OF_SPADES], TEN_OF_CLUBS, false).points()); + assert_eq!(18, score_4_card_cribbage_hand([FIVE_OF_CLUBS, FIVE_OF_DIAMONDS, TEN_OF_HEARTS, JACK_OF_SPADES], QUEEN_OF_SPADES, false).points()); + assert_eq!(17, score_4_card_cribbage_hand([FIVE_OF_CLUBS, FIVE_OF_DIAMONDS, TEN_OF_HEARTS, JACK_OF_SPADES], QUEEN_OF_CLUBS, false).points()); + assert_eq!(21, score_4_card_cribbage_hand([FIVE_OF_CLUBS, JACK_OF_DIAMONDS, JACK_OF_HEARTS, JACK_OF_SPADES], FIVE_OF_HEARTS, false).points()); + assert_eq!(29, score_4_card_cribbage_hand([FIVE_OF_CLUBS, JACK_OF_DIAMONDS, FIVE_OF_HEARTS, FIVE_OF_SPADES], FIVE_OF_DIAMONDS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([SIX_OF_CLUBS, SIX_OF_DIAMONDS, NINE_OF_HEARTS, NINE_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([SIX_OF_CLUBS, NINE_OF_DIAMONDS, NINE_OF_HEARTS, NINE_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([SIX_OF_CLUBS, SIX_OF_DIAMONDS, SEVEN_OF_HEARTS, SEVEN_OF_SPADES], EIGHT_OF_CLUBS, false).points()); + assert_eq!(16, score_4_card_cribbage_hand([SIX_OF_CLUBS, SEVEN_OF_DIAMONDS, EIGHT_OF_HEARTS, NINE_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([SEVEN_OF_CLUBS, SEVEN_OF_DIAMONDS, SEVEN_OF_HEARTS, ACE_OF_SPADES], ACE_OF_CLUBS, false).points()); + assert_eq!(21, score_4_card_cribbage_hand([SEVEN_OF_CLUBS, SEVEN_OF_DIAMONDS, SEVEN_OF_HEARTS, EIGHT_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(21, score_4_card_cribbage_hand([SEVEN_OF_CLUBS, SEVEN_OF_DIAMONDS, SEVEN_OF_HEARTS, EIGHT_OF_SPADES], SIX_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([SEVEN_OF_CLUBS, SEVEN_OF_DIAMONDS, SEVEN_OF_HEARTS, EIGHT_OF_SPADES], EIGHT_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([SEVEN_OF_CLUBS, EIGHT_OF_DIAMONDS, EIGHT_OF_HEARTS, EIGHT_OF_SPADES], EIGHT_OF_CLUBS, false).points()); + assert_eq!(24, score_4_card_cribbage_hand([SEVEN_OF_CLUBS, SEVEN_OF_DIAMONDS, EIGHT_OF_HEARTS, EIGHT_OF_SPADES], NINE_OF_CLUBS, false).points()); + assert_eq!(20, score_4_card_cribbage_hand([SEVEN_OF_CLUBS, EIGHT_OF_DIAMONDS, EIGHT_OF_HEARTS, NINE_OF_SPADES], NINE_OF_CLUBS, false).points()); + } + + #[test] + fn pegging_scores() { + let score = score_pegging(&[ACE_OF_SPADES, TWO_OF_SPADES, THREE_OF_SPADES, FOUR_OF_SPADES, FIVE_OF_SPADES]); + assert_eq!(7, score.points()); + assert_eq!("Fifteen two and five is seven", format!("{}", score)); + + let score = score_pegging(&[TEN_OF_HEARTS, FIVE_OF_CLUBS]); + assert_eq!(2, score.points()); + assert_eq!("Fifteen for two", format!("{}", score)); + + let score = score_pegging(&[TEN_OF_HEARTS, FIVE_OF_CLUBS, TEN_OF_CLUBS]); + assert_eq!(0, score.points()); + assert_eq!("", format!("{}", score)); + + let score = score_pegging(&[TEN_OF_HEARTS, FIVE_OF_CLUBS, TEN_OF_CLUBS, SIX_OF_DIAMONDS]); + assert_eq!(2, score.points()); + assert_eq!("Thirty-one for two", format!("{}", score)); + } +} diff --git a/src/game/mod.rs b/src/game/mod.rs index 8ec8795..d06ca9d 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,5 +1,6 @@ mod action; mod chatroom; +mod cribbage; mod filter; mod poker; mod whist;