From 8dbcb8038df62151d5e6dbdb8b9fbe7ed24b4482 Mon Sep 17 00:00:00 2001 From: Geoffrey Allott Date: Sat, 17 Jun 2023 22:15:51 +0100 Subject: [PATCH] knock out players correctly upon cut for call; make sure order of players knocked out is deterministic by knocking out the lowest username first --- src/game/whist.rs | 142 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/src/game/whist.rs b/src/game/whist.rs index 6d0d39e..131070b 100644 --- a/src/game/whist.rs +++ b/src/game/whist.rs @@ -262,7 +262,7 @@ impl Game for KnockOutWhist { } Ok(()) } - (State::Playing, Action::KnockedOut) => { + (State::Playing | State::CutForCall, Action::KnockedOut) => { if self.dealer == Some(username) { self.dealer = self.seats.player_before(username); } @@ -357,10 +357,12 @@ impl Game for KnockOutWhist { State::ChoosingTrumps => DealerAction::WaitForPlayer, State::Playing => { if !self.winners.is_empty() { - for username in self.seats.player_set() { - if matches!(self.tricks_won.get(&username), Some(0) | None) { - return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::KnockedOut })); - } + let knocked_out_player = self.seats.player_set() + .into_iter() + .filter(|username| matches!(self.tricks_won.get(username), Some(0) | None)) + .min(); + if let Some(username) = knocked_out_player { + return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::KnockedOut })); } if self.seats.players_len() == 1 { if let Some(&username) = self.winners.iter().next() { @@ -378,6 +380,13 @@ impl Game for KnockOutWhist { } } State::CutForCall => { + let knocked_out_player = self.seats.player_set() + .into_iter() + .filter(|username| matches!(self.tricks_won.get(username), Some(0) | None)) + .min(); + if let Some(username) = knocked_out_player { + return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::KnockedOut })); + } if let Some(username) = self.receiver { if let Some(card) = rng.choose_from(self.deck) { DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::CutCard { card } })) @@ -1178,4 +1187,127 @@ mod tests { test_game(actions, settings, seed); } + + #[test] + fn players_knocked_out_on_tie_for_first() { + let actions = r#"[ + {"timestamp":1687025531200,"username":"Steve","action":{"action":"Join","seat":0,"chips":0}}, + {"timestamp":1687025539806,"username":"Aga","action":{"action":"Join","seat":1,"chips":0}}, + {"timestamp":1687025544327,"username":"Geoff","action":{"action":"Join","seat":2,"chips":0}}, + {"timestamp":1687025544328,"username":"Aga","action":{"action":"NextToDeal"}}, + {"timestamp":1687025544329,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Seven","suit":"Clubs"}}}, + {"timestamp":1687025544332,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Five","suit":"Clubs"}}}, + {"timestamp":1687025544334,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Queen","suit":"Hearts"}}}, + {"timestamp":1687025544335,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Ten","suit":"Spades"}}}, + {"timestamp":1687025544336,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Nine","suit":"Hearts"}}}, + {"timestamp":1687025544338,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Ten","suit":"Hearts"}}}, + {"timestamp":1687025544338,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Ace","suit":"Hearts"}}}, + {"timestamp":1687025544339,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Nine","suit":"Diamonds"}}}, + {"timestamp":1687025544339,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Diamonds"}}}, + {"timestamp":1687025544339,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Spades"}}}, + {"timestamp":1687025544340,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Queen","suit":"Diamonds"}}}, + {"timestamp":1687025544340,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Hearts"}}}, + {"timestamp":1687025544341,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Jack","suit":"Clubs"}}}, + {"timestamp":1687025544341,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Ten","suit":"Clubs"}}}, + {"timestamp":1687025544342,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Diamonds"}}}, + {"timestamp":1687025544343,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Spades"}}}, + {"timestamp":1687025544343,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Six","suit":"Spades"}}}, + {"timestamp":1687025544344,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Ace","suit":"Clubs"}}}, + {"timestamp":1687025544344,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Hearts"}}}, + {"timestamp":1687025544345,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Nine","suit":"Clubs"}}}, + {"timestamp":1687025544345,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Clubs"}}}, + {"timestamp":1687025544345,"username":"Aga","action":{"action":"CommunityCard","card":{"rank":"Three","suit":"Hearts"}}}, + {"timestamp":1687025544346,"username":"Aga","action":{"action":"EndDeal"}}, + {"timestamp":1687025567895,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Jack","suit":"Clubs"}}}, + {"timestamp":1687025575145,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Five","suit":"Clubs"}}}, + {"timestamp":1687025577395,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Ace","suit":"Clubs"}}}, + {"timestamp":1687025577396,"username":"Aga","action":{"action":"WinTrick"}}, + {"timestamp":1687025579295,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"King","suit":"Hearts"}}}, + {"timestamp":1687025584278,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Ace","suit":"Hearts"}}}, + {"timestamp":1687025585580,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Nine","suit":"Hearts"}}}, + {"timestamp":1687025585581,"username":"Geoff","action":{"action":"WinTrick"}}, + {"timestamp":1687025589478,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Ten","suit":"Spades"}}}, + {"timestamp":1687025593261,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Six","suit":"Spades"}}}, + {"timestamp":1687025598728,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Queen","suit":"Hearts"}}}, + {"timestamp":1687025598731,"username":"Aga","action":{"action":"WinTrick"}}, + {"timestamp":1687025602929,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Two","suit":"Clubs"}}}, + {"timestamp":1687025605361,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Seven","suit":"Clubs"}}}, + {"timestamp":1687025607462,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Ten","suit":"Clubs"}}}, + {"timestamp":1687025607470,"username":"Steve","action":{"action":"WinTrick"}}, + {"timestamp":1687025610129,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Queen","suit":"Diamonds"}}}, + {"timestamp":1687025613629,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Two","suit":"Diamonds"}}}, + {"timestamp":1687025615128,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Eight","suit":"Hearts"}}}, + {"timestamp":1687025615129,"username":"Geoff","action":{"action":"WinTrick"}}, + {"timestamp":1687025616079,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Two","suit":"Spades"}}}, + {"timestamp":1687025620212,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Nine","suit":"Diamonds"}}}, + {"timestamp":1687025716180,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Ten","suit":"Hearts"}}}, + {"timestamp":1687025716181,"username":"Aga","action":{"action":"WinTrick"}}, + {"timestamp":1687025717565,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Diamonds"}}}, + {"timestamp":1687025721250,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Spades"}}}, + {"timestamp":1687025723213,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Nine","suit":"Clubs"}}}, + {"timestamp":1687025723214,"username":"Aga","action":{"action":"WinTrick"}}, + {"timestamp":1687025723214,"username":"Aga","action":{"action":"WinCall"}}, + {"timestamp":1687025723215,"username":"Geoff","action":{"action":"NextToDeal"}}, + {"timestamp":1687025723216,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Ace","suit":"Diamonds"}}}, + {"timestamp":1687025723219,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Diamonds"}}}, + {"timestamp":1687025723221,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Four","suit":"Clubs"}}}, + {"timestamp":1687025723224,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Ten","suit":"Diamonds"}}}, + {"timestamp":1687025723227,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Spades"}}}, + {"timestamp":1687025723229,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Six","suit":"Clubs"}}}, + {"timestamp":1687025723232,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Jack","suit":"Clubs"}}}, + {"timestamp":1687025723234,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Hearts"}}}, + {"timestamp":1687025723235,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Hearts"}}}, + {"timestamp":1687025723236,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Nine","suit":"Clubs"}}}, + {"timestamp":1687025723236,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Diamonds"}}}, + {"timestamp":1687025723237,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Hearts"}}}, + {"timestamp":1687025723237,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Queen","suit":"Hearts"}}}, + {"timestamp":1687025723238,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Seven","suit":"Diamonds"}}}, + {"timestamp":1687025723238,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Nine","suit":"Hearts"}}}, + {"timestamp":1687025723238,"username":"Steve","action":{"action":"ReceiveCard","card":{"rank":"Two","suit":"Spades"}}}, + {"timestamp":1687025723239,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Clubs"}}}, + {"timestamp":1687025723239,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Diamonds"}}}, + {"timestamp":1687025723240,"username":"Geoff","action":{"action":"EndDeal"}}, + {"timestamp":1687025742414,"username":"Aga","action":{"action":"ChooseTrumps","suit":"Spades"}}, + {"timestamp":1687025937234,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Jack","suit":"Clubs"}}}, + {"timestamp":1687025944502,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"King","suit":"Clubs"}}}, + {"timestamp":1687025945935,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Six","suit":"Clubs"}}}, + {"timestamp":1687025945936,"username":"Aga","action":{"action":"WinTrick"}}, + {"timestamp":1687025948351,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"King","suit":"Hearts"}}}, + {"timestamp":1687025950851,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Nine","suit":"Hearts"}}}, + {"timestamp":1687025953734,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Queen","suit":"Hearts"}}}, + {"timestamp":1687025953738,"username":"Aga","action":{"action":"WinTrick"}}, + {"timestamp":1687025961402,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Eight","suit":"Spades"}}}, + {"timestamp":1687025965318,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Hearts"}}}, + {"timestamp":1687025967985,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Two","suit":"Spades"}}}, + {"timestamp":1687025967990,"username":"Aga","action":{"action":"WinTrick"}}, + {"timestamp":1687025970585,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Eight","suit":"Diamonds"}}}, + {"timestamp":1687025972251,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Diamonds"}}}, + {"timestamp":1687025974868,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Ace","suit":"Diamonds"}}}, + {"timestamp":1687025974878,"username":"Steve","action":{"action":"WinTrick"}}, + {"timestamp":1687025976019,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Ten","suit":"Diamonds"}}}, + {"timestamp":1687025979902,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Two","suit":"Diamonds"}}}, + {"timestamp":1687025981968,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Four","suit":"Clubs"}}}, + {"timestamp":1687025981971,"username":"Steve","action":{"action":"WinTrick"}}, + {"timestamp":1687025983469,"username":"Steve","action":{"action":"PlayCard","card":{"rank":"Nine","suit":"Clubs"}}}, + {"timestamp":1687025986068,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Seven","suit":"Diamonds"}}}, + {"timestamp":1687025987784,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Eight","suit":"Hearts"}}}, + {"timestamp":1687025987787,"username":"Steve","action":{"action":"WinTrick"}}, + {"timestamp":1687025987787,"username":"Geoff","action":{"action":"KnockedOut"}}, + {"timestamp":1687025987790,"username":"Steve","action":{"action":"CutCard","card":{"rank":"Three","suit":"Hearts"}}}, + {"timestamp":1687025987790,"username":"Aga","action":{"action":"CutCard","card":{"rank":"Three","suit":"Spades"}}}, + {"timestamp":1687025987790,"username":"Steve","action":{"action":"CutCard","card":{"rank":"Three","suit":"Diamonds"}}}, + {"timestamp":1687025987790,"username":"Aga","action":{"action":"CutCard","card":{"rank":"Five","suit":"Hearts"}}}, + {"timestamp":1687025987791,"username":"Aga","action":{"action":"WinCall"}}, + {"timestamp":1687025987792,"username":"Steve","action":{"action":"NextToDeal"}} + ]"#; + let actions = serde_json::from_str(actions).unwrap(); + + let settings = r#"{"format":"KnockOutWhist","title":"Kingly Juncture","max_players":3,"start_time":null}"#; + let settings = serde_json::from_str(settings).unwrap(); + + let seed = r#"{"rng":"ChaCha8","seed":"689b3ec1462a1a11a403680f26909f3539f702bc16d074911bb16788e07dfe58"}"#; + let seed = serde_json::from_str(seed).unwrap(); + + test_game(actions, settings, seed); + } } -- 2.34.1