fix WinGame logic
authorGeoffrey Allott <geoffrey@allott.email>
Sun, 7 Mar 2021 12:35:20 +0000 (12:35 +0000)
committerGeoffrey Allott <geoffrey@allott.email>
Sun, 7 Mar 2021 12:35:20 +0000 (12:35 +0000)
src/game/poker/holdem.rs

index 33cf3347c6239db08661b198fe3dec6dcd46a040..86be4bbaf697938ff45e43f127dd221a120aa6f7 100644 (file)
@@ -203,6 +203,14 @@ impl TexasHoldEm {
             .find(|&(_, &stack)| stack == 0)
             .map(|(&username, _)| username)
     }
+
+    fn only_player_left(&self) -> Option<Username> {
+        self.seats.player_set()
+            .into_iter()
+            .filter(|username| !self.ghosts.contains_key(username))
+            .exactly_one()
+            .ok()
+    }
 }
 
 impl Game for TexasHoldEm {
@@ -497,13 +505,8 @@ impl Game for TexasHoldEm {
                             error!("There is no player to win the pot: {:#?}", self);
                             DealerAction::Leave
                         }
-                    } else if self.seats.players_len() == 1 {
-                        if let Some(&username) = self.seats.player_set().iter().next() {
-                            DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::WinGame }))
-                        } else {
-                            error!("There is no player to win the game {:#?}", self);
-                            DealerAction::Leave
-                        }
+                    } else if let Some(username) = self.only_player_left() {
+                        DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::WinGame }))
                     } else if let Some(username) = self.next_knocked_out_player() {
                         DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::KnockedOut }))
                     } else if let Some(username) = self.dealer.and_then(|dealer| self.seats.player_after(dealer)) {
@@ -539,13 +542,8 @@ impl Game for TexasHoldEm {
             State::Showdown if self.pot == 0 => {
                 if let Some(username) = self.next_knocked_out_player() {
                     DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::KnockedOut }))
-                } else if self.seats.players_len() == 1 {
-                    if let Some(&username) = self.seats.player_set().iter().next() {
-                        DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::WinGame }))
-                    } else {
-                        error!("There was no player to win the game: {:#?}", self);
-                        DealerAction::Leave
-                    }
+                } else if let Some(username) = self.only_player_left() {
+                    DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::WinGame }))
                 } else if let Some(username) = self.dealer.and_then(|dealer| self.seats.player_after(dealer)) {
                     DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }))
                 } else {
@@ -1311,4 +1309,50 @@ mod tests {
 
         test_game(actions, settings, seed);
     }
+
+    #[test]
+    fn three_players_knocked_out_at_once() {
+        let actions = r#"[
+            {"timestamp":1615119954716,"username":"geoff","action":{"action":"Join","seat":0,"chips":1000}},
+            {"timestamp":1615119959371,"username":"kat","action":{"action":"Join","seat":1,"chips":1000}},
+            {"timestamp":1615119966559,"username":"mack","action":{"action":"Join","seat":2,"chips":1000}},
+            {"timestamp":1615119978936,"username":"pete","action":{"action":"Join","seat":3,"chips":1000}},
+            {"timestamp":1615119978938,"username":"pete","action":{"action":"NextToDeal"}},
+            {"timestamp":1615119978941,"username":"geoff","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Spades"}}},
+            {"timestamp":1615119978943,"username":"kat","action":{"action":"ReceiveCard","card":{"rank":"Ace","suit":"Clubs"}}},
+            {"timestamp":1615119978945,"username":"mack","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Hearts"}}},
+            {"timestamp":1615119978946,"username":"pete","action":{"action":"ReceiveCard","card":{"rank":"Ace","suit":"Spades"}}},
+            {"timestamp":1615119978947,"username":"geoff","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Clubs"}}},
+            {"timestamp":1615119978949,"username":"kat","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Spades"}}},
+            {"timestamp":1615119978951,"username":"mack","action":{"action":"ReceiveCard","card":{"rank":"Nine","suit":"Spades"}}},
+            {"timestamp":1615119978952,"username":"pete","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Hearts"}}},
+            {"timestamp":1615119978954,"username":"pete","action":{"action":"EndDeal"}},
+            {"timestamp":1615119978955,"username":"geoff","action":{"action":"PostBlind","chips":25}},
+            {"timestamp":1615119978957,"username":"kat","action":{"action":"PostBlind","chips":50}},
+            {"timestamp":1615119986455,"username":"mack","action":{"action":"Bet","chips":1000}},
+            {"timestamp":1615119988046,"username":"pete","action":{"action":"Bet","chips":1000}},
+            {"timestamp":1615119989208,"username":"geoff","action":{"action":"Bet","chips":975}},
+            {"timestamp":1615119991509,"username":"kat","action":{"action":"Bet","chips":950}},
+            {"timestamp":1615119991512,"username":"pete","action":{"action":"CommunityCard","card":{"rank":"Four","suit":"Hearts"}}},
+            {"timestamp":1615119991514,"username":"pete","action":{"action":"CommunityCard","card":{"rank":"Seven","suit":"Clubs"}}},
+            {"timestamp":1615119991516,"username":"pete","action":{"action":"CommunityCard","card":{"rank":"Jack","suit":"Diamonds"}}},
+            {"timestamp":1615119991517,"username":"pete","action":{"action":"CommunityCard","card":{"rank":"Ten","suit":"Spades"}}},
+            {"timestamp":1615119991520,"username":"pete","action":{"action":"CommunityCard","card":{"rank":"Queen","suit":"Hearts"}}},
+            {"timestamp":1615119991522,"username":"mack","action":{"action":"WinHand","chips":4000,"hand":"Straight, Q High"}},
+            {"timestamp":1615119991525,"username":"geoff","action":{"action":"KnockedOut"}},
+            {"timestamp":1615119991527,"username":"kat","action":{"action":"KnockedOut"}},
+            {"timestamp":1615119991529,"username":"pete","action":{"action":"KnockedOut"}},
+            {"timestamp":1615119991530,"username":"mack","action":{"action":"WinGame"}}
+        ]"#;
+        let actions = serde_json::from_str(actions).unwrap();
+
+        let settings =
+            r#"{"format":"TexasHoldEm","title":"4-Player TexasHoldEm Test","max_players":4,"small_blind":25,"starting_stack":1000,"action_timeout":null}"#;
+        let settings = serde_json::from_str(settings).unwrap();
+
+        let seed = r#"{"rng":"ChaCha20","seed":"092b99f45313fff167029dc7420ed69a92becae492e09b65bc06ddcaae3c9e9c"}"#;
+        let seed = serde_json::from_str(seed).unwrap();
+
+        test_game(actions, settings, seed);
+    }
 }