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_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) *self.get_possibility_map().get(value).unwrap() } fn initialize() -> HashMap { let mut possible_map : HashMap = HashMap::new(); for value in Self::get_all_possibilities().iter() { possible_map.insert(value.clone(), true); } possible_map } fn merge(&mut self, other: &Self) { for (value, possible) in self.get_mut_possibility_map().iter_mut() { *possible = *possible && *other.get_possibility_map().get(value).unwrap(); } } fn mark_true(&mut self, value: &T) { // mark everything else as definitively impossible for (other_value, possible) in self.get_mut_possibility_map().iter_mut() { if other_value != value { *possible = false; } else { assert_eq!(*possible, true); } } } fn mark_false(&mut self, value: &T) { self.get_mut_possibility_map().insert(value.clone(), false); } fn mark(&mut self, value: &T, info: bool) { if info { self.mark_true(value); } else { self.mark_false(value); } } } #[derive(Debug)] pub struct ColorInfo(HashMap); impl ColorInfo { pub fn new() -> ColorInfo { ColorInfo(ColorInfo::initialize()) } } impl Info for ColorInfo { fn get_all_possibilities() -> Vec { let mut possible : Vec = Vec::new(); for color in COLORS.iter() { possible.push(*color); } possible } fn get_possibility_map(&self) -> &HashMap { &self.0 } fn get_mut_possibility_map(&mut self) -> &mut HashMap { &mut self.0 } } #[derive(Debug)] pub struct ValueInfo(HashMap); impl ValueInfo { pub fn new() -> ValueInfo { ValueInfo(ValueInfo::initialize()) } } impl Info for ValueInfo { fn get_all_possibilities() -> Vec { let mut possible : Vec = Vec::new(); for value in VALUES.iter() { possible.push(*value); } possible } fn get_possibility_map(&self) -> &HashMap { &self.0 } fn get_mut_possibility_map(&mut self) -> &mut HashMap { &mut self.0 } } #[derive(Debug)] pub struct CardInfo { pub color_info: ColorInfo, pub value_info: ValueInfo, } impl CardInfo { pub fn new() -> CardInfo { CardInfo { color_info: ColorInfo::new(), value_info: ValueInfo::new(), } } } impl fmt::Display for CardInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut string = String::new(); for color in &COLORS { if self.color_info.is_possible(color) { let colorchar = color.chars().next().unwrap(); string.push(colorchar); } } // while string.len() < COLORS.len() + 1 { string.push(' '); //} for value in &VALUES { if self.value_info.is_possible(value) { string.push_str(&format!("{}", value)); } } f.pad(&string) } }