seed deck in simulator, use iterators more

This commit is contained in:
Jeff Wu 2016-04-02 15:14:05 -07:00
parent b19e6ff615
commit 678a8f26a7
5 changed files with 103 additions and 135 deletions

View file

@ -1,8 +1,8 @@
use rand::{self, Rng, SeedableRng};
use std::collections::HashMap;
use std::fmt;
use std::iter;
use std::slice::IterMut;
use std::ops::Range;
pub use info::*;
pub use cards::*;
@ -134,24 +134,6 @@ impl PlayerState {
}
}
fn new_deck(seed: u32) -> Cards {
let mut deck: Cards = Cards::new();
for &color in COLORS.iter() {
for &value in VALUES.iter() {
let count = get_count_for_value(value);
for _ in 0..count {
deck.push(Card::new(color, value));
}
}
};
rand::ChaChaRng::from_seed(&[seed]).shuffle(&mut deck[..]);
trace!("Created deck: {:?}", deck);
deck
}
// State of everything except the player's hands
// Is all completely common knowledge
#[derive(Debug,Clone)]
@ -179,12 +161,11 @@ pub struct BoardState {
pub deckless_turns_remaining: u32,
}
impl BoardState {
pub fn new(opts: &GameOptions, seed: u32) -> BoardState {
let mut fireworks : HashMap<Color, Firework> = HashMap::new();
for &color in COLORS.iter() {
fireworks.insert(color, Firework::new(color));
}
let deck = new_deck(seed);
pub fn new(opts: &GameOptions, deck: Cards) -> BoardState {
let fireworks = COLORS.iter().map(|&color| {
(color, Firework::new(color))
}).collect::<HashMap<_, _>>();
let total_cards = deck.len() as u32;
BoardState {
@ -283,16 +264,12 @@ impl BoardState {
}
}
pub fn get_players(&self) -> Vec<Player> {
(0..self.num_players).collect::<Vec<_>>()
pub fn get_players(&self) -> Range<Player> {
(0..self.num_players)
}
pub fn score(&self) -> Score {
let mut score = 0;
for (_, firework) in &self.fireworks {
score += firework.score();
}
score as u32
self.fireworks.iter().map(|(_, firework)| firework.score()).fold(0, |a, b| a + b)
}
pub fn deck_size(&self) -> u32 {
@ -373,37 +350,27 @@ pub trait GameView {
}
fn has_card(&self, player: &Player, card: &Card) -> bool {
for other_card in self.get_hand(player) {
if *card == *other_card {
return true;
}
}
false
self.get_hand(player).iter().position(|other_card| {
card == other_card
}).is_some()
}
fn can_see(&self, card: &Card) -> bool {
for other_player in self.get_board().get_players() {
if self.me() == other_player {
continue
}
if self.has_card(&other_player, card) {
return true;
}
}
false
self.get_board().get_players().filter(|&player| {
player != self.me()
}).any(|player| {
self.has_card(&player, card)
})
}
fn someone_else_can_play(&self) -> bool {
for player in self.get_board().get_players() {
if player != self.me() {
for card in self.get_hand(&player) {
if self.get_board().is_playable(card) {
return true;
}
}
}
}
false
self.get_board().get_players().filter(|&player| {
player != self.me()
}).any(|player| {
self.get_hand(&player).iter().any(|card| {
self.get_board().is_playable(card)
})
})
}
}
@ -449,14 +416,13 @@ pub struct OwnedGameView {
}
impl OwnedGameView {
pub fn clone_from(borrowed_view: &BorrowedGameView) -> OwnedGameView {
let mut info : Vec<SimpleCardInfo> = Vec::new();
for card_info in borrowed_view.info.iter() {
info.push((*card_info).clone());
}
let mut other_player_states : HashMap<Player, PlayerState> = HashMap::new();
for (other_player, player_state) in &borrowed_view.other_player_states {
other_player_states.insert(*other_player, (*player_state).clone());
}
let info = borrowed_view.info.iter()
.map(|card_info| card_info.clone()).collect::<Vec<_>>();
let other_player_states = borrowed_view.other_player_states.iter()
.map(|(&other_player, &player_state)| {
(other_player, player_state.clone())
}).collect::<HashMap<_, _>>();
OwnedGameView {
player: borrowed_view.player.clone(),
@ -508,19 +474,17 @@ impl fmt::Display for GameState {
}
impl GameState {
pub fn new(opts: &GameOptions, seed: u32) -> GameState {
let mut board = BoardState::new(opts, seed);
pub fn new(opts: &GameOptions, deck: Cards) -> GameState {
let mut board = BoardState::new(opts, deck);
let mut player_states : HashMap<Player, PlayerState> = HashMap::new();
for i in 0..opts.num_players {
let player_states =
(0..opts.num_players).map(|player| {
let hand = (0..opts.hand_size).map(|_| {
// we can assume the deck is big enough to draw initial hands
board.deck.pop().unwrap()
}).collect::<Vec<_>>();
player_states.insert(
i, PlayerState::new(hand),
);
}
(player, PlayerState::new(hand))
}).collect::<HashMap<_, _>>();
GameState {
player_states: player_states,
@ -528,7 +492,7 @@ impl GameState {
}
}
pub fn get_players(&self) -> Vec<Player> {
pub fn get_players(&self) -> Range<Player> {
self.board.get_players()
}
@ -543,9 +507,9 @@ impl GameState {
// get the game state view of a particular player
pub fn get_view(&self, player: Player) -> BorrowedGameView {
let mut other_player_states = HashMap::new();
for (other_player, state) in &self.player_states {
if player != *other_player {
other_player_states.insert(*other_player, state);
for (&other_player, state) in &self.player_states {
if player != other_player {
other_player_states.insert(other_player, state);
}
}
BorrowedGameView {

View file

@ -142,11 +142,8 @@ pub trait Info<T> where T: Hash + Eq + Clone + Copy {
}
fn initialize() -> HashSet<T> {
let mut possible_map : HashSet<T> = HashSet::new();
for value in Self::get_all_possibilities().iter() {
possible_map.insert(value.clone());
}
possible_map
Self::get_all_possibilities().iter()
.map(|val| val.clone()).collect::<HashSet<_>>()
}
fn mark_true(&mut self, value: T) {
@ -160,11 +157,7 @@ pub trait Info<T> where T: Hash + Eq + Clone + Copy {
}
fn mark(&mut self, value: T, info: bool) {
if info {
self.mark_true(value);
} else {
self.mark_false(value);
}
if info { self.mark_true(value); } else { self.mark_false(value); }
}
}

View file

@ -1,4 +1,4 @@
use rand::{self, Rng};
use rand::{self, Rng, SeedableRng};
use std::collections::HashMap;
use std::fmt;
use crossbeam;
@ -29,6 +29,24 @@ pub trait GameStrategyConfig {
fn initialize(&self, &GameOptions) -> Box<GameStrategy>;
}
fn new_deck(seed: u32) -> Cards {
let mut deck: Cards = Cards::new();
for &color in COLORS.iter() {
for &value in VALUES.iter() {
let count = get_count_for_value(value);
for _ in 0..count {
deck.push(Card::new(color, value));
}
}
};
rand::ChaChaRng::from_seed(&[seed]).shuffle(&mut deck[..]);
trace!("Created deck: {:?}", deck);
deck
}
pub fn simulate_once(
opts: &GameOptions,
game_strategy: Box<GameStrategy>,
@ -36,16 +54,13 @@ pub fn simulate_once(
) -> GameState {
let seed = seed_opt.unwrap_or(rand::thread_rng().next_u32());
let deck = new_deck(seed);
let mut game = GameState::new(opts, seed);
let mut game = GameState::new(opts, deck);
let mut strategies : HashMap<Player, Box<PlayerStrategy>> = HashMap::new();
for player in game.get_players() {
strategies.insert(
player,
game_strategy.initialize(player.clone(), &game.get_view(player)),
);
}
let mut strategies = game.get_players().map(|player| {
(player, game_strategy.initialize(player.clone(), &game.get_view(player)))
}).collect::<HashMap<Player, Box<PlayerStrategy>>>();
while !game.is_over() {
let player = game.board.player;
@ -110,8 +125,8 @@ impl Histogram {
(self.sum as f32) / (self.total_count as f32)
}
pub fn merge(&mut self, other: Histogram) {
for (val, count) in other.hist.iter() {
self.insert_many(*val, *count);
for (val, count) in other.hist.into_iter() {
self.insert_many(val, count);
}
}
}

View file

@ -44,9 +44,9 @@ impl CheatingStrategy {
}
impl GameStrategy for CheatingStrategy {
fn initialize(&self, player: Player, view: &BorrowedGameView) -> Box<PlayerStrategy> {
for (player, state) in &view.other_player_states {
for (&player, state) in &view.other_player_states {
self.player_states_cheat.borrow_mut().insert(
*player, state.hand.clone()
player, state.hand.clone()
);
}
Box::new(CheatingPlayerStrategy {
@ -141,28 +141,23 @@ impl PlayerStrategy for CheatingPlayerStrategy {
let states = self.player_states_cheat.borrow();
let my_cards = states.get(&self.me).unwrap();
let playable_cards = my_cards.iter().filter(|card| {
let playable_cards = my_cards.iter().enumerate().filter(|&(_, card)| {
view.board.is_playable(card)
}).collect::<Vec<_>>();
if playable_cards.len() > 0 {
// play the best playable card
// the higher the play_score, the better to play
let mut play_card = None;
let mut index = 0;
let mut play_score = -1;
for card in playable_cards {
for &(i, card) in playable_cards.iter() {
let score = self.get_play_score(view, card);
if score > play_score {
play_card = Some(card);
index = i;
play_score = score;
}
}
let index = my_cards.iter().position(|card| {
card == play_card.unwrap()
}).unwrap();
return TurnChoice::Play(index)
}

View file

@ -220,11 +220,12 @@ impl InformationStrategy {
}
impl GameStrategy for InformationStrategy {
fn initialize(&self, player: Player, view: &BorrowedGameView) -> Box<PlayerStrategy> {
let mut public_info = HashMap::new();
for player in view.board.get_players() {
let public_info =
view.board.get_players().map(|player| {
let hand_info = (0..view.board.hand_size).map(|_| { CardPossibilityTable::new() }).collect::<Vec<_>>();
public_info.insert(player, hand_info);
}
(player, hand_info)
}).collect::<HashMap<_,_>>();
Box::new(InformationPlayerStrategy {
me: player,
public_info: public_info,
@ -316,12 +317,14 @@ impl InformationPlayerStrategy {
fn answer_questions(
questions: &Vec<Box<Question>>, hand: &Cards, view: &OwnedGameView
) -> ModulusInformation {
let mut info = ModulusInformation::none();
for question in questions {
let answer_info = question.answer_info(hand, view);
info.combine(answer_info);
}
info
questions.iter()
.fold(
ModulusInformation::none(),
|mut answer_info, question| {
let new_answer_info = question.answer_info(hand, view);
answer_info.combine(new_answer_info);
answer_info
})
}
fn get_hint_info_for_player(
@ -338,19 +341,18 @@ impl InformationPlayerStrategy {
}
fn get_hint_sum_info(&self, total_info: u32, view: &OwnedGameView) -> ModulusInformation {
let mut sum = ModulusInformation::new(total_info, 0);
for player in view.get_board().get_players() {
if player != self.me {
view.get_board().get_players().filter(|&player| {
player != self.me
}).fold(
ModulusInformation::new(total_info, 0),
|mut sum_info, player| {
let answer = self.get_hint_info_for_player(&player, total_info, view);
sum.add(&answer);
}
}
trace!("Summed answer {:?}\n", sum);
sum
sum_info.add(&answer);
sum_info
})
}
fn infer_own_from_hint_sum(&mut self, hint: ModulusInformation) {
let mut hint = hint;
fn infer_own_from_hint_sum(&mut self, mut hint: ModulusInformation) {
let questions = {
let view = &self.last_view;
let hand_info = self.get_my_public_info();
@ -375,14 +377,13 @@ impl InformationPlayerStrategy {
self.return_public_info(&me, hand_info);
}
fn update_from_hint_sum(&mut self, hint: ModulusInformation) {
fn update_from_hint_sum(&mut self, mut hint: ModulusInformation) {
let hinter = self.last_view.board.player;
let players = {
let view = &self.last_view;
view.board.get_players()
};
trace!("{}: inferring for myself, starting with {:?}", self.me, hint);
let mut hint = hint;
for player in players {
if (player != hinter) && (player != self.me) {
{
@ -725,8 +726,8 @@ impl PlayerStrategy for InformationPlayerStrategy {
// we already stored the view
let view = &self.last_view;
for player in view.board.get_players().iter() {
let hand_info = self.get_player_public_info(player);
for player in view.board.get_players() {
let hand_info = self.get_player_public_info(&player);
debug!("Current state of hand_info for {}:", player);
for (i, card_table) in hand_info.iter().enumerate() {
debug!(" Card {}: {}", i, card_table);