strategy that cheats, first pass
This commit is contained in:
parent
a16f490c04
commit
2f6dc571c2
4 changed files with 102 additions and 20 deletions
26
src/game.rs
26
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
|
||||
);
|
||||
|
|
19
src/main.rs
19
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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
75
src/strategies/cheating.rs
Normal file
75
src/strategies/cheating.rs
Normal 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) {
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue