From 958c63e7d0fa5a477b33e597630dc52820ed9927 Mon Sep 17 00:00:00 2001 From: Jeff Wu Date: Wed, 9 Mar 2016 10:27:40 -0800 Subject: [PATCH] implementing display for everything --- src/game.rs | 89 ++++++++++++++++++++++++++++++++++++++++------- src/info.rs | 41 +++++++++++++++++++--- src/strategies.rs | 2 +- 3 files changed, 115 insertions(+), 17 deletions(-) diff --git a/src/game.rs b/src/game.rs index 7940080..dd1cde5 100644 --- a/src/game.rs +++ b/src/game.rs @@ -64,12 +64,12 @@ impl From> for Pile { } impl fmt::Display for Pile where T: fmt::Display { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // surely doing unwraps is improper.. - write!(f, "[").unwrap(); + try!(f.write_str("[")); for item in &self.0 { - write!(f, "{}, ", item).unwrap(); + try!(f.write_str(&format!("{}, ", item))); } - write!(f, "] ") + try!(f.write_str("")); + Ok(()) } } @@ -96,12 +96,15 @@ impl Firework { } } + fn top_value(&self) -> Value { + self.cards.top().unwrap().value + } + fn desired_value(&self) -> Option { - let top_value = self.cards.top().unwrap().value; - if top_value == FINAL_VALUE { + if self.complete() { None } else { - Some(top_value + 1) + Some(self.top_value() + 1) } } @@ -111,7 +114,7 @@ impl Firework { } fn complete(&self) -> bool { - self.desired_value() == None + self.top_value() == FINAL_VALUE } fn place(&mut self, card: Card) { @@ -129,10 +132,10 @@ impl Firework { } impl fmt::Display for Firework { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(value) = self.desired_value() { - write!(f, "{} firework at {}", self.color, value) - } else { + if self.complete() { write!(f, "{} firework complete!", self.color) + } else { + write!(f, "{} firework at {}", self.color, self.top_value()) } } } @@ -189,6 +192,19 @@ pub struct PlayerState { // represents what is common knowledge about the player's hand info: CardsInfo, } +impl fmt::Display for PlayerState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write_str("hand: ")); + + let mut i = 0; + for card in &self.hand.0 { + let info : &CardInfo = &self.info.0[i]; + try!(f.write_str(&format!("{} =? {: <15} ", card, info))); + i += 1; + } + Ok(()) + } +} impl PlayerState { pub fn new(hand: Cards) -> PlayerState { let infos = (0..hand.size()).map(|_| { @@ -275,7 +291,7 @@ pub struct BoardState { // TODO: // pub turn_history: Vec, // only relevant when deck runs out - deckless_turns_remaining: u32, + pub deckless_turns_remaining: u32, } impl BoardState { pub fn new(opts: &GameOptions) -> BoardState { @@ -324,6 +340,10 @@ impl BoardState { score as u32 } + pub fn deck_size(&self) -> usize { + self.deck.size() + } + pub fn player_to_left(&self, player: &Player) -> Player { (player + 1) % self.num_players } @@ -331,6 +351,35 @@ impl BoardState { (player - 1) % self.num_players } } +impl fmt::Display for BoardState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write_str(&format!( + "Turn {} (Player {}'s turn):\n", self.turn, self.player + ))); + let deck_size = self.deck_size(); + try!(f.write_str(&format!( + "{} cards remaining in deck\n", deck_size + ))); + if deck_size == 0 { + try!(f.write_str(&format!( + "Deck is empty. {} turns remaining in game\n", self.deckless_turns_remaining + ))); + } + try!(f.write_str(&format!( + "{}/{} hints remaining\n", self.hints_remaining, self.hints_total + ))); + try!(f.write_str(&format!( + "{}/{} lives remaining\n", self.lives_remaining, self.lives_total + ))); + try!(f.write_str("Fireworks:\n")); + for (_, firework) in &self.fireworks { + try!(f.write_str(&format!(" {}\n", firework))); + } + // discard: Cards::new(), + + Ok(()) + } +} // complete game view of a given player // state will be borrowed GameState @@ -352,6 +401,22 @@ pub struct GameState { pub player_states: HashMap, pub board: BoardState, } +impl fmt::Display for GameState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write_str("==========================\n")); + try!(f.write_str("Hands:\n")); + try!(f.write_str("==========================\n")); + for player in 0..self.board.num_players { + let state = &self.player_states.get(&player).unwrap(); + try!(f.write_str(&format!("player {} {}\n", player, state))); + } + try!(f.write_str("==========================\n")); + try!(f.write_str("Board:\n")); + try!(f.write_str("==========================\n")); + try!(f.write_str(&format!("{}", self.board))); + Ok(()) + } +} pub type Score = u32; diff --git a/src/info.rs b/src/info.rs index c7d2c22..6dea5de 100644 --- a/src/info.rs +++ b/src/info.rs @@ -1,22 +1,39 @@ use std::collections::HashMap; use std::cmp::Eq; use std::hash::Hash; +use std::fmt; use game::*; // Represents a bit of information about T pub trait Info where T: Hash + Eq + Clone { // get all a-priori possibilities - fn get_possibilities() -> Vec; + fn get_all_possibilities() -> Vec; // get map from values to whether it's possible // true means maybe, false means no fn get_possibility_map(&self) -> &HashMap; fn get_mut_possibility_map(&mut self) -> &mut HashMap; + // get what is now possible + fn get_possibilities(&self) -> Vec<&T> { + let mut v = Vec::new(); + let map = self.get_possibility_map(); + for (value, is_possible) in map { + if *is_possible { + v.push(value); + } + } + v + } + + fn is_possible(&self, value: &T) -> bool { + self.get_possibility_map().contains_key(value) + } + fn initialize() -> HashMap { let mut possible_map : HashMap = HashMap::new(); - for value in Self::get_possibilities().iter() { + for value in Self::get_all_possibilities().iter() { possible_map.insert(value.clone(), true); } possible_map @@ -60,7 +77,7 @@ impl ColorInfo { } } impl Info for ColorInfo { - fn get_possibilities() -> Vec { + fn get_all_possibilities() -> Vec { let mut possible : Vec = Vec::new(); for color in COLORS.iter() { possible.push(*color); @@ -83,7 +100,7 @@ impl ValueInfo { } } impl Info for ValueInfo { - fn get_possibilities() -> Vec { + fn get_all_possibilities() -> Vec { let mut possible : Vec = Vec::new(); for value in VALUES.iter() { possible.push(*value); @@ -111,3 +128,19 @@ impl CardInfo { } } } +impl fmt::Display for CardInfo { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut string = String::new(); + for color in &self.color_info.get_possibilities() { + let colorchar = color.chars().next().unwrap(); + string.push(colorchar); + } + // while string.len() < COLORS.len() + 1 { + string.push(' '); + //} + for value in &self.value_info.get_possibilities() { + string.push_str(&format!("{}", value)); + } + f.pad(&string) + } +} diff --git a/src/strategies.rs b/src/strategies.rs index 8201e2b..3bca303 100644 --- a/src/strategies.rs +++ b/src/strategies.rs @@ -44,7 +44,7 @@ pub fn simulate_once(opts: &GameOptions, _: &S) -> Score { } // TODO: do some stuff - debug!("State: {:?}", game); + debug!("State:\n{}", game); } game.score() }