--- /dev/null
+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));
+ }
+}