diff --git a/src/game.rs b/src/game.rs index 9ade5c0..6587554 100644 --- a/src/game.rs +++ b/src/game.rs @@ -2,13 +2,17 @@ use rand::{seq::SliceRandom, Rng}; pub trait Player { fn select_card( - &self, + &mut self, hand: &[Card], stack: &[Card], additional_information: &AdditionalInformation, ) -> Card; } +pub trait PlayerBuilder: Sync { + fn build(&self) -> Box; +} + #[derive(Debug)] pub struct AdditionalInformation {} @@ -85,7 +89,16 @@ pub fn playeble(card: Card, hand: &[Card], stack_color: Option) -> bool { } } -pub fn herzen(player: &[Box], starting_player: usize, rng: &mut impl Rng) -> Vec { +pub fn herzen( + player_builders: &[Box], + starting_player: usize, + rng: &mut impl Rng, +) -> Vec { + let mut player = player_builders + .iter() + .map(|p| p.build()) + .collect::>(); + let mut full_deck = (1..=8) .flat_map(|u| { [ diff --git a/src/main.rs b/src/main.rs index 9eae78a..ff87753 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use game::Player; +use game::PlayerBuilder; use rand::{rngs::SmallRng, SeedableRng}; mod game; @@ -122,13 +122,10 @@ mod player; // } fn main() { - let player: Vec> = vec![ + let player: Vec> = vec![ Box::new(player::highest::Highest {}), - Box::new(player::highest::Highest {}), - Box::new(player::highest::Highest {}), - Box::new(player::highest::Highest {}), - Box::new(player::highest::Highest {}), - Box::new(player::cli::Cli {}), + Box::new(player::random::Random { seed: 0 }), + // Box::new(player::cli::Cli {}), ]; let mut rng = SmallRng::from_entropy(); diff --git a/src/player/mod.rs b/src/player/mod.rs index a8201a6..c9fe709 100644 --- a/src/player/mod.rs +++ b/src/player/mod.rs @@ -1,12 +1,18 @@ pub mod cli { - use crate::game::{playeble, Player}; + use crate::game::{playeble, Player, PlayerBuilder}; pub struct Cli {} + impl PlayerBuilder for Cli { + fn build(&self) -> Box { + Box::new(Cli {}) + } + } + impl Player for Cli { fn select_card( - &self, + &mut self, hand: &[crate::game::Card], stack: &[crate::game::Card], additional_information: &crate::game::AdditionalInformation, @@ -36,13 +42,19 @@ pub mod cli { pub mod highest { use std::cmp::Reverse; - use crate::game::{playeble, Player}; + use crate::game::{playeble, Player, PlayerBuilder}; pub struct Highest {} + impl PlayerBuilder for Highest { + fn build(&self) -> Box { + Box::new(Highest {}) + } + } + impl Player for Highest { fn select_card( - &self, + &mut self, hand: &[crate::game::Card], stack: &[crate::game::Card], additional_information: &crate::game::AdditionalInformation, @@ -58,3 +70,43 @@ pub mod highest { } } } + +pub mod random { + use rand::{rngs::SmallRng, seq::SliceRandom, SeedableRng}; + + use crate::game::{playeble, Player, PlayerBuilder}; + + pub struct Random { + pub seed: u64, + } + + impl PlayerBuilder for Random { + fn build(&self) -> Box { + Box::new(RandomPlayer { + rng: SmallRng::seed_from_u64(self.seed), + }) + } + } + + struct RandomPlayer { + rng: SmallRng, + } + + impl Player for RandomPlayer { + fn select_card( + &mut self, + hand: &[crate::game::Card], + stack: &[crate::game::Card], + additional_information: &crate::game::AdditionalInformation, + ) -> crate::game::Card { + let _ = additional_information; + let mut h = hand.to_vec(); + + h.sort(); + + h.retain(|&c| playeble(c, hand, stack.first().map(|d| d.color))); + + *h.choose(&mut self.rng).unwrap() + } + } +}