strategy that cheats, first pass

This commit is contained in:
Jeff Wu 2016-03-13 01:05:05 -08:00
parent a16f490c04
commit 2f6dc571c2
4 changed files with 102 additions and 20 deletions

View file

@ -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
);

View file

@ -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
);
}

View file

@ -56,7 +56,7 @@ pub fn simulate<'a>(opts: &GameOptions, strat_configs: &Vec<Box<StrategyConfig +
let mut total_score = 0;
for _ in 0..n_trials {
let score = simulate_once(&opts, strat_configs);
info!("Scored: {:?}", score);
debug!("Scored: {:?}", score);
total_score += score;
}
let average: f32 = (total_score as f32) / (n_trials as f32);

View file

@ -0,0 +1,75 @@
use std::rc::Rc;
use std::cell::{RefCell};
use std::collections::HashMap;
use simulator::*;
use game::*;
// strategy that cheats by using Cell
// Plays according to the following rules:
// - if any card is playable,
// play the card with the lowest
// - if a card is
#[allow(dead_code)]
#[derive(Clone)]
pub struct CheatingStrategyConfig {
player_states_cheat: Rc<RefCell<HashMap<Player, Cards>>>,
}
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<Strategy> {
Box::new(CheatingStrategy {
player_states_cheat: self.player_states_cheat.clone(),
})
}
}
pub struct CheatingStrategy {
player_states_cheat: Rc<RefCell<HashMap<Player, Cards>>>,
}
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) {
}
}