diff --git a/src/game.rs b/src/game.rs index 0e1d22b..805a886 100644 --- a/src/game.rs +++ b/src/game.rs @@ -30,7 +30,7 @@ pub fn get_count_for_value(value: &Value) -> usize { pub type Player = u32; -#[derive(Debug)] +#[derive(Debug,Clone,PartialEq)] pub struct Card { pub color: Color, pub value: Value, @@ -227,9 +227,9 @@ pub struct GameOptions { #[derive(Debug)] pub struct PlayerState { // the player's actual hand - hand: Cards, + pub hand: Cards, // represents what is common knowledge about the player's hand - info: CardsInfo, + pub info: CardsInfo, } impl fmt::Display for PlayerState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -305,7 +305,7 @@ fn new_deck() -> Cards { } }; shuffle(&mut deck); - debug!("Created deck: {:?}", deck); + trace!("Created deck: {:?}", deck); deck } @@ -542,7 +542,7 @@ impl GameState { let mut other_player_states = HashMap::new(); for (other_player, state) in &self.player_states { if player != *other_player { - other_player_states.insert(player, state); + other_player_states.insert(*other_player, state); } } GameStateView { @@ -558,20 +558,20 @@ impl GameState { let ref mut state = self.player_states.get_mut(&self.board.player).unwrap(); let (card, _) = state.take(index); if let Some(new_card) = self.board.deck.pop() { - info!("Drew new card, {}", new_card); + debug!("Drew new card, {}", new_card); state.place(new_card); } card } pub fn process_choice(&mut self, choice: &TurnChoice) { - info!("Player {}'s move", self.board.player); + debug!("Player {}'s move", self.board.player); match choice { &TurnChoice::Hint(ref hint) => { assert!(self.board.hints_remaining > 0, "Tried to hint with no hints remaining"); self.board.hints_remaining -= 1; - info!("Hint to player {}, about {}", hint.player, hint.hinted); + debug!("Hint to player {}, about {}", hint.player, hint.hinted); assert!(self.board.player != hint.player, format!("Player {} gave a hint to himself", hint.player)); @@ -581,7 +581,7 @@ impl GameState { } &TurnChoice::Discard(index) => { let card = self.take_from_hand(index); - info!("Discard card in position {}, which is {}", index, card); + debug!("Discard card in position {}, which is {}", index, card); self.board.discard.place(card); self.board.try_add_hint(); @@ -589,7 +589,7 @@ impl GameState { &TurnChoice::Play(index) => { let card = self.take_from_hand(index); - info!( + debug!( "Playing card at position {}, which is {}", index, card ); @@ -599,15 +599,15 @@ impl GameState { if self.board.is_playable(&card) { let ref mut firework = self.board.fireworks.get_mut(&card.color).unwrap(); firework_made = card.value == FINAL_VALUE; - info!("Successfully played {}!", card); + debug!("Successfully played {}!", card); if firework_made { - info!("Firework complete for {}!", card.color); + debug!("Firework complete for {}!", card.color); } firework.place(card); } else { self.board.discard.place(card); self.board.lives_remaining -= 1; - info!( + debug!( "Removing a life! Lives remaining: {}", self.board.lives_remaining ); diff --git a/src/main.rs b/src/main.rs index 3b87b44..e845b7d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod game; mod simulator; mod strategies { pub mod examples; + pub mod cheating; } mod info; @@ -27,7 +28,8 @@ impl log::Log for SimpleLogger { fn main() { log::set_logger(|max_log_level| { - max_log_level.set(log::LogLevelFilter::Trace); + //max_log_level.set(log::LogLevelFilter::Trace); + max_log_level.set(log::LogLevelFilter::Info); Box::new(SimpleLogger) }).unwrap(); @@ -37,7 +39,7 @@ fn main() { num_hints: 8, num_lives: 3, }; - let n = 1; + let n = 1000; // simulator::simulate(&opts, &strategies::examples::AlwaysDiscard, n); // simulator::simulate_symmetric(&opts, strategies::examples::AlwaysPlayConfig, n); // simulator::simulate( @@ -49,12 +51,17 @@ fn main() { // Box::new(strategies::examples::AlwaysPlayConfig), // ], // n); + // simulator::simulate_symmetric( + // &opts, + // strategies::examples::RandomStrategyConfig { + // hint_probability: 0.4, + // play_probability: 0.2, + // }, + // n + // ); simulator::simulate_symmetric( &opts, - strategies::examples::RandomStrategyConfig { - hint_probability: 0.4, - play_probability: 0.2, - }, + strategies::cheating::CheatingStrategyConfig::new(), n ); } diff --git a/src/simulator.rs b/src/simulator.rs index 43e4810..7aaa47c 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -56,7 +56,7 @@ pub fn simulate<'a>(opts: &GameOptions, strat_configs: &Vec>>, +} + +impl CheatingStrategyConfig { + pub fn new() -> CheatingStrategyConfig { + CheatingStrategyConfig { + player_states_cheat: Rc::new(RefCell::new(HashMap::new())), + } + } +} +impl <'a> StrategyConfig for CheatingStrategyConfig { + fn initialize(&self, _: &Player, _: &GameStateView) -> Box { + Box::new(CheatingStrategy { + player_states_cheat: self.player_states_cheat.clone(), + }) + } +} +pub struct CheatingStrategy { + player_states_cheat: Rc>>, +} +impl Strategy for CheatingStrategy { + fn decide(&mut self, me: &Player, view: &GameStateView) -> TurnChoice { + let next = view.board.player_to_left(&me); + self.player_states_cheat.borrow_mut().insert( + next, view.other_player_states.get(&next).unwrap().hand.clone() + ); + if view.board.turn == 1 { + TurnChoice::Hint(Hint { + player: next, + hinted: Hinted::Value(1) + }) + } else { + let states = self.player_states_cheat.borrow(); + let my_cards = states.get(me).unwrap(); + let mut playable_cards = my_cards.iter().filter(|card| { + view.board.is_playable(card) + }).peekable(); + if playable_cards.peek() == None { + TurnChoice::Discard(0) + } else { + let mut play_card = playable_cards.next().unwrap(); + + let mut next_card_opt = playable_cards.next(); + while let Some(next_card) = next_card_opt { + if next_card.value < play_card.value { + play_card = next_card; + } + next_card_opt = playable_cards.next(); + } + + let index = my_cards.iter().position(|card| { + card == play_card + }).unwrap(); + TurnChoice::Play(index) + } + } + } + fn update(&mut self, _: &Turn, _: &GameStateView) { + } +}