implement two for his heels
authorGeoffrey Allott <geoffrey@allott.email>
Thu, 1 Jun 2023 22:39:11 +0000 (23:39 +0100)
committerGeoffrey Allott <geoffrey@allott.email>
Thu, 1 Jun 2023 22:39:11 +0000 (23:39 +0100)
src/game/cribbage/mod.rs

index ebf172481100b5a5f24f159cd795251c490c34b1..66e01fa4d965050fa3ed26ad61103257042fc671 100644 (file)
@@ -1,6 +1,6 @@
 use std::collections::{HashMap, HashSet};
 
-use crate::card::{Card, FIFTY_TWO_CARD_DECK};
+use crate::card::{Card, FIFTY_TWO_CARD_DECK, Rank};
 use crate::rng::{Seed, WaveRng};
 use crate::seats::Seats;
 use crate::username::Username;
@@ -18,6 +18,7 @@ enum State {
     Dealing,
     Choosing,
     TurnUp,
+    ScoringTurnUp,
     Pegging,
     ScoringPegging,
     Scoring,
@@ -237,6 +238,7 @@ impl Game for Cribbage {
                 }
             }
             (State::TurnUp, _) => Err(ActionError::Dealing),
+            (State::ScoringTurnUp, _) => Err(ActionError::Dealing),
             (State::Scoring, _) => Err(ActionError::Dealing),
             (State::ScoringBox, _) => Err(ActionError::Dealing),
             (State::Completed, _) => Err(ActionError::GameHasEnded),
@@ -298,11 +300,16 @@ impl Game for Cribbage {
             }
             (State::TurnUp, Action::CommunityCard { card }) => {
                 self.turn_up = Some(card);
-                self.state = State::Pegging;
+                self.state = if card.rank == Rank::Jack { State::ScoringTurnUp } else { State::Pegging };
                 self.active = self.dealer.and_then(|dealer| self.seats.player_after(dealer));
                 self.players_still_in = self.players();
                 Ok(())
             }
+            (State::ScoringTurnUp, Action::Score { points, .. }) => {
+                *self.points.entry(username).or_default() += points as u32;
+                self.state = State::Pegging;
+                Ok(())
+            }
             (State::Pegging, Action::PlayCard { card }) => {
                 if Some(username) != self.active {
                     error!("Username taking action must be active");
@@ -443,6 +450,14 @@ impl Game for Cribbage {
                     DealerAction::Leave
                 }
             }
+            State::ScoringTurnUp => {
+                if let Some(username) = self.dealer {
+                    DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::Score { points: 2, reason: "Two for his heels".to_string() } }))
+                } else {
+                    error!("Expected to score the turn-up but there was no dealer");
+                    DealerAction::Leave
+                }
+            }
             State::Pegging => DealerAction::WaitForPlayer,
             State::ScoringPegging => {
                 if let Some(username) = self.winner() {
@@ -634,4 +649,73 @@ mod tests {
 
         test_game(actions, settings, seed);
     }
+
+    #[test]
+    fn two_for_his_heels() {
+        let actions = r#"[
+            {"timestamp":1685220615999,"username":"Geoff","action":{"action":"Join","seat":0,"chips":0}},
+            {"timestamp":1685220772960,"username":"Aga","action":{"action":"Join","seat":1,"chips":0}},
+            {"timestamp":1685308376245,"username":"Geoff","action":{"action":"NextToDeal"}},
+            {"timestamp":1685308376245,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Diamonds"}}},
+            {"timestamp":1685308376246,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Diamonds"}}},
+            {"timestamp":1685308376246,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Spades"}}},
+            {"timestamp":1685308376246,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Five","suit":"Spades"}}},
+            {"timestamp":1685308376246,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Seven","suit":"Spades"}}},
+            {"timestamp":1685308376246,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Spades"}}},
+            {"timestamp":1685308376247,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Diamonds"}}},
+            {"timestamp":1685308376247,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Clubs"}}},
+            {"timestamp":1685308376247,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Six","suit":"Spades"}}},
+            {"timestamp":1685308376247,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Clubs"}}},
+            {"timestamp":1685308376248,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Five","suit":"Diamonds"}}},
+            {"timestamp":1685308376248,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Spades"}}},
+            {"timestamp":1685308376248,"username":"Geoff","action":{"action":"EndDeal"}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"PutInBox","card":{"rank":"Two","suit":"Clubs"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"PutInBox","card":{"rank":"Two","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"PutInBox","card":{"rank":"Two","suit":"Diamonds"}}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"PutInBox","card":{"rank":"Three","suit":"Diamonds"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"CommunityCard","card":{"rank":"Jack","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"Score","points":2,"reason":"Two for his heels"}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Eight","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Five","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Five","suit":"Diamonds"}}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"Score","points":2,"reason":"Two"}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"King","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"Pass"}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"Pass"}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"Score","points":1,"reason":"One for a go"}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Seven","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"King","suit":"Clubs"}}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Six","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"Pass"}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"Score","points":1,"reason":"One for a go"}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"King","suit":"Diamonds"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"Score","points":1,"reason":"One for a go"}},
+            {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Five","suit":"Diamonds"}}},
+            {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Six","suit":"Spades"}}},
+            {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Seven","suit":"Spades"}}},
+            {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Eight","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Aga","action":{"action":"Score","points":8,"reason":"Fifteen two, fifteen four and four is 8"}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Five","suit":"Spades"}}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"King","suit":"Clubs"}}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"King","suit":"Diamonds"}}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"King","suit":"Spades"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"Score","points":14,"reason":"Fifteen two, fifteen four, fifteen six, fifteen eight and six is 14"}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Two","suit":"Clubs"}}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Two","suit":"Diamonds"}}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Two","suit":"Spades"}}},
+            {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Three","suit":"Diamonds"}}},
+            {"timestamp":1685308376249,"username":"Geoff","action":{"action":"Score","points":12,"reason":"Fifteen two, fifteen four, fifteen six and six is 12"}},
+            {"timestamp":1685308376248,"username":"Geoff","action":{"action":"WinGame"}}
+        ]"#;
+
+        let actions = serde_json::from_str(actions).unwrap();
+
+        let settings = r#"{"format":"Cribbage","title":"Cribbage Testing","max_players":2,"target_score":21,"start_time":null}"#;
+        let settings = serde_json::from_str(settings).unwrap();
+
+        let seed = r#"{"rng":"ChaCha20","seed":"9f71c78e1b6218813b88b82d636cd34015fea43aabd6901f45736de4f9005b15"}"#;
+        let seed = serde_json::from_str(seed).unwrap();
+
+        test_game(actions, settings, seed);
+    }
 }