make whist deterministic based on seed
authorGeoffrey Allott <geoffrey@allott.email>
Mon, 1 Mar 2021 22:13:26 +0000 (22:13 +0000)
committerGeoffrey Allott <geoffrey@allott.email>
Mon, 1 Mar 2021 22:13:26 +0000 (22:13 +0000)
src/game/mod.rs
src/game/whist.rs

index 6e459354b46fbab6557bfe3c8914bda3d83c3732..2ab9e1c14386cd284ea358c165130c85e3316c91 100644 (file)
@@ -44,7 +44,7 @@ impl dyn Game {
     pub fn new(GameSummary{id, settings}: GameSummary, seed: Seed) -> Box<Self> {
         match settings {
             GameSettings::Chatroom(settings) => Box::new(Chatroom::new(id, settings)),
-            GameSettings::KnockOutWhist(settings) => Box::new(KnockOutWhist::new(id, settings)),
+            GameSettings::KnockOutWhist(settings) => Box::new(KnockOutWhist::new(id, settings, seed)),
             GameSettings::TexasHoldEm(settings) => Box::new(TexasHoldEm::new(id, settings, seed)),
         }
     }
index b2d11a368f2c89185d780fa7d32e9fcef88f09b0..8d59f58dcc74efd8587918571067b007dce84e58 100644 (file)
@@ -1,9 +1,7 @@
 use std::collections::{HashMap, HashSet};
 
-use rand::seq::IteratorRandom;
-use rand::thread_rng;
-
 use crate::card::{Card, Suit, FIFTY_TWO_CARD_DECK};
+use crate::rng::{Seed, WaveRng};
 use crate::seats::Seats;
 use crate::username::Username;
 use crate::util::max::IteratorMaxItems;
@@ -31,6 +29,7 @@ pub struct KnockOutWhistSettings {
 pub struct KnockOutWhist {
     id: i64,
     settings: KnockOutWhistSettings,
+    rng: WaveRng,
     actions_len: usize,
     state: State,
     seats: Seats,
@@ -50,10 +49,11 @@ pub struct KnockOutWhist {
 }
 
 impl KnockOutWhist {
-    pub fn new(id: i64, settings: KnockOutWhistSettings) -> Self {
+    pub fn new(id: i64, settings: KnockOutWhistSettings, seed: Seed) -> Self {
         Self {
             id,
             settings,
+            rng: seed.into_rng(),
             actions_len: 0,
             state: State::NotStarted,
             seats: Seats::new(),
@@ -167,6 +167,7 @@ impl Game for KnockOutWhist {
 
     fn take_action(&mut self, ValidatedUserAction(UserAction{username, action}): ValidatedUserAction) -> Result<(), ActionError> {
         self.actions_len += 1;
+        self.rng.advance();
         match (self.state, action) {
             (_, Action::AddOn{..}) | (_, Action::Fold) | (_, Action::Bet{..}) => {
                 Err(ActionError::InvalidActionForGameType)
@@ -302,11 +303,11 @@ impl Game for KnockOutWhist {
     }
 
     fn next_dealer_action(&self) -> Option<ValidatedUserAction> {
-        let mut rng = thread_rng();
+        let mut rng = self.rng.clone();
         match self.state {
             State::NotStarted => {
                 if self.seats.players_len() == self.settings.max_players as usize { // TODO
-                    if let Some(username) = self.seats.player_set().into_iter().choose(&mut rng) {
+                    if let Some(username) = rng.choose_from(self.seats.player_set()) {
                         return Some(ValidatedUserAction(UserAction{username, action: Action::NextToDeal}));
                     }
                 }
@@ -314,12 +315,12 @@ impl Game for KnockOutWhist {
             }
             State::Dealing => {
                 if let Some(username) = self.receiver {
-                    let card = self.deck.iter().choose(&mut rng).cloned();
+                    let card = rng.choose_from(&self.deck).cloned();
                     Some(ValidatedUserAction(UserAction{username, action: Action::ReceiveCard{card}}))
                 } else if let Some(username) = self.dealer {
                     match (self.call, self.trump_card) {
                         (None, None) => {
-                            if let Some(&card) = self.deck.iter().choose(&mut rng) {
+                            if let Some(&card) = rng.choose_from(&self.deck) {
                                 Some(ValidatedUserAction(UserAction{username, action: Action::CommunityCard{card}}))
                             } else {
                                 None
@@ -358,7 +359,7 @@ impl Game for KnockOutWhist {
             }
             State::CutForCall => {
                 if let Some(username) = self.receiver {
-                    if let Some(card) = self.deck.iter().choose(&mut rng).cloned() {
+                    if let Some(card) = rng.choose_from(&self.deck).cloned() {
                         Some(ValidatedUserAction(UserAction{username, action: Action::RevealCard{card}}))
                     } else {
                         None