From ea2857a9cd626309f044696b1b42a05f3054dc70 Mon Sep 17 00:00:00 2001 From: Jeff Wu Date: Wed, 30 Mar 2016 01:00:04 -0700 Subject: [PATCH] make use of dead card discard info --- README.md | 2 +- src/strategies/information.rs | 69 +++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 34d47ac..10fb769 100644 --- a/README.md +++ b/README.md @@ -53,5 +53,5 @@ Currently, on seeds 0-9999, we have: | 2p | 3p | 4p | 5p | ----------|---------|---------|---------|---------| cheating | 24.8600 | 24.9781 | 24.9715 | 24.9583 | -info | 14.981 | 22.526 | 24.516 | 24.742 | +info | 15.15 | 22.79 | 24.604 | 24.778 | diff --git a/src/strategies/information.rs b/src/strategies/information.rs index 34b2fe4..82ea54b 100644 --- a/src/strategies/information.rs +++ b/src/strategies/information.rs @@ -343,7 +343,7 @@ impl InformationPlayerStrategy { answer } - fn get_hint_sum(&self, total_info: u32, view: &T) -> ModulusInformation + fn get_hint_sum_info(&self, total_info: u32, view: &T) -> ModulusInformation where T: GameView { let mut sum = ModulusInformation::new(total_info, 0); @@ -442,29 +442,33 @@ impl InformationPlayerStrategy { } } } - if view.board.is_playable(card) { - 5 + (5 - (card.value as i32)) - } else { - 0 - } + 5 + (5 - (card.value as i32)) } - fn find_useless_card(&self, view: &BorrowedGameView, hand: &Vec) -> Option { - let mut set: HashSet = HashSet::new(); + fn find_useless_cards(&self, view: &T, hand: &Vec) -> Vec + where T: GameView + { + let mut useless: HashSet = HashSet::new(); + let mut seen: HashMap = HashMap::new(); for (i, card_table) in hand.iter().enumerate() { - if card_table.probability_is_dead(view.board) == 1.0 { - return Some(i); - } - if let Some(card) = card_table.get_card() { - if set.contains(&card) { - // found a duplicate card - return Some(i); + if card_table.probability_is_dead(view.get_board()) == 1.0 { + useless.insert(i); + } else { + if let Some(card) = card_table.get_card() { + if seen.contains_key(&card) { + // found a duplicate card + useless.insert(i); + useless.insert(*seen.get(&card).unwrap()); + } else { + seen.insert(card, i); + } } - set.insert(card); } } - return None + let mut useless_vec : Vec = useless.into_iter().collect(); + useless_vec.sort(); + return useless_vec; } fn someone_else_can_play(&self, view: &BorrowedGameView) -> bool { @@ -564,7 +568,7 @@ impl InformationPlayerStrategy { fn get_hint(&self, view: &BorrowedGameView) -> TurnChoice { let total_info = 3 * (view.board.num_players - 1); - let hint_info = self.get_hint_sum(total_info, view); + let hint_info = self.get_hint_sum_info(total_info, view); let hint_type = hint_info.value % 3; let player_amt = (hint_info.value - hint_type) / 3; @@ -699,12 +703,16 @@ impl PlayerStrategy for InformationPlayerStrategy { - (COLORS.len() * VALUES.len()) as u32 - (view.board.num_players * view.board.hand_size); - // TODO: use the useless card discard as information! + let public_useless_indices = self.find_useless_cards(view, &self.get_my_public_info()); + let useless_indices = self.find_useless_cards(view, &private_info); if view.board.discard_size() <= discard_threshold { // if anything is totally useless, discard it - if let Some(i) = self.find_useless_card(view, &private_info) { - return TurnChoice::Discard(i); + if public_useless_indices.len() > 1 { + let info = self.get_hint_sum_info(public_useless_indices.len() as u32, view); + return TurnChoice::Discard(public_useless_indices[info.value as usize]); + } else if useless_indices.len() > 0 { + return TurnChoice::Discard(useless_indices[0]); } } @@ -714,7 +722,7 @@ impl PlayerStrategy for InformationPlayerStrategy { if self.someone_else_can_play(view) { return self.get_hint(view); } else { - print!("This actually happened"); + // print!("This actually happens"); } } @@ -722,8 +730,11 @@ impl PlayerStrategy for InformationPlayerStrategy { // infer that we have no playable cards // if anything is totally useless, discard it - if let Some(i) = self.find_useless_card(view, &private_info) { - return TurnChoice::Discard(i); + if public_useless_indices.len() > 1 { + let info = self.get_hint_sum_info(public_useless_indices.len() as u32, view); + return TurnChoice::Discard(public_useless_indices[info.value as usize]); + } else if useless_indices.len() > 0 { + return TurnChoice::Discard(useless_indices[0]); } // Play the best discardable card @@ -759,6 +770,16 @@ impl PlayerStrategy for InformationPlayerStrategy { } TurnChoice::Discard(index) => { if let &TurnResult::Discard(ref card) = &turn.result { + let public_useless_indices = self.find_useless_cards( + &self.last_view, &self.get_player_public_info(&turn.player)); + if public_useless_indices.len() > 1 { + // unwrap is safe because *if* a discard happened, and there were known + // dead cards, it must be a dead card + let value = public_useless_indices.iter().position(|&i| i == index).unwrap(); + self.update_from_hint_sum(ModulusInformation::new( + public_useless_indices.len() as u32, value as u32 + )); + } self.update_public_info_for_discard_or_play(view, &turn.player, index, card); } else { panic!("Got turn choice {:?}, but turn result {:?}",