]> git.scottworley.com Git - pluta-lesnura/commitdiff
Start adding smarter play: Try for momentum
authorScott Worley <scottworley@scottworley.com>
Tue, 18 Jul 2023 19:21:47 +0000 (12:21 -0700)
committerScott Worley <scottworley@scottworley.com>
Tue, 18 Jul 2023 19:21:47 +0000 (12:21 -0700)
src/lib.rs
src/main.rs

index 09bd5fbc2599bf7725b486a183b667bd84c3aa6c..444b3fef59d08d930f7e8ef19e8924f831d96a7e 100644 (file)
@@ -181,6 +181,17 @@ impl Hand {
     fn random(&self) -> Option<&Card> {
         self.cards.choose(&mut rand::thread_rng())
     }
+    /// Make a new Hand that contains only cards of the requested suit
+    fn filter_by_suit(&self, suit: Suit) -> Self {
+        Self {
+            cards: self
+                .cards
+                .iter()
+                .filter(|c| c.suit().expect("I shouldn't have jokers in my hand") == suit)
+                .copied()
+                .collect(),
+        }
+    }
 }
 
 #[derive(Copy, Clone)]
@@ -428,6 +439,22 @@ pub fn random_player(draw_chance: f64) -> impl FnMut(&Game) -> Play {
     }
 }
 
+/// When available, make plays that grant momentum.  Otherwise, play randomly.
+pub fn momentum_player(draw_chance: f64) -> impl FnMut(&Game) -> Play {
+    let mut fallback = random_player(draw_chance);
+    move |game: &Game| -> Play {
+        match (&game.phase, game.discard.top().and_then(Card::suit)) {
+            (Phase::Play, Some(suit)) => {
+                match game.current_player_hand().filter_by_suit(suit).random() {
+                    Some(card) => Play::Play(*card),
+                    _ => fallback(game),
+                }
+            }
+            _ => fallback(game),
+        }
+    }
+}
+
 /// # Errors
 ///
 /// Will return `Err` on invalid plays, like trying to draw during Play phase,
index c7c1c9268a055a1ffcd71cf0f2e93095aa49d352..b2924eec6dc917eb32c016843f6a0d590912ad6b 100644 (file)
@@ -1,5 +1,5 @@
-use clap::{Parser, Subcommand};
-use pluta_lesnura::{play, random_player, Game, Player};
+use clap::{Parser, Subcommand, ValueEnum};
+use pluta_lesnura::{momentum_player, play, random_player, Game, Player};
 
 #[derive(Parser)]
 #[command(author, version, about, long_about = None, arg_required_else_help = true)]
@@ -8,6 +8,12 @@ struct Cli {
     command: Option<Commands>,
 }
 
+#[derive(Clone, Debug, ValueEnum)]
+enum Strategy {
+    Random,
+    Momentum,
+}
+
 #[derive(Subcommand)]
 enum Commands {
     /// Runs simulations
@@ -21,6 +27,9 @@ enum Commands {
         /// How many players?
         #[arg(short = 'p', long)]
         num_players: usize,
+        /// What strategy should players use?
+        #[arg(short = 's', long, value_enum)]
+        strategy: Strategy,
     },
 }
 
@@ -32,12 +41,16 @@ fn main() -> Result<(), &'static str> {
             draw_chance,
             num_games,
             num_players,
+            strategy,
         }) => {
+            let player = || match strategy {
+                Strategy::Random => Player::new(random_player(*draw_chance)),
+                Strategy::Momentum => Player::new(momentum_player(*draw_chance)),
+            };
             for _ in 0..*num_games {
-                let players: Vec<_> =
-                    std::iter::from_fn(|| Some(Player::new(random_player(*draw_chance))))
-                        .take(*num_players)
-                        .collect();
+                let players: Vec<_> = std::iter::from_fn(|| Some(player()))
+                    .take(*num_players)
+                    .collect();
                 let mut game = Game::default();
                 for _ in 0..*num_players {
                     game.add_player();