make use of dead card discard info

This commit is contained in:
Jeff Wu 2016-03-30 01:00:04 -07:00
parent 9494d549ae
commit ea2857a9cd
2 changed files with 46 additions and 25 deletions

View file

@ -53,5 +53,5 @@ Currently, on seeds 0-9999, we have:
| 2p | 3p | 4p | 5p | | 2p | 3p | 4p | 5p |
----------|---------|---------|---------|---------| ----------|---------|---------|---------|---------|
cheating | 24.8600 | 24.9781 | 24.9715 | 24.9583 | 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 |

View file

@ -343,7 +343,7 @@ impl InformationPlayerStrategy {
answer answer
} }
fn get_hint_sum<T>(&self, total_info: u32, view: &T) -> ModulusInformation fn get_hint_sum_info<T>(&self, total_info: u32, view: &T) -> ModulusInformation
where T: GameView where T: GameView
{ {
let mut sum = ModulusInformation::new(total_info, 0); 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)) 5 + (5 - (card.value as i32))
} else {
0
}
} }
fn find_useless_card(&self, view: &BorrowedGameView, hand: &Vec<CardPossibilityTable>) -> Option<usize> { fn find_useless_cards<T>(&self, view: &T, hand: &Vec<CardPossibilityTable>) -> Vec<usize>
let mut set: HashSet<Card> = HashSet::new(); where T: GameView
{
let mut useless: HashSet<usize> = HashSet::new();
let mut seen: HashMap<Card, usize> = HashMap::new();
for (i, card_table) in hand.iter().enumerate() { for (i, card_table) in hand.iter().enumerate() {
if card_table.probability_is_dead(view.board) == 1.0 { if card_table.probability_is_dead(view.get_board()) == 1.0 {
return Some(i); useless.insert(i);
} } else {
if let Some(card) = card_table.get_card() { if let Some(card) = card_table.get_card() {
if set.contains(&card) { if seen.contains_key(&card) {
// found a duplicate card // found a duplicate card
return Some(i); useless.insert(i);
} useless.insert(*seen.get(&card).unwrap());
set.insert(card); } else {
seen.insert(card, i);
} }
} }
return None }
}
let mut useless_vec : Vec<usize> = useless.into_iter().collect();
useless_vec.sort();
return useless_vec;
} }
fn someone_else_can_play(&self, view: &BorrowedGameView) -> bool { fn someone_else_can_play(&self, view: &BorrowedGameView) -> bool {
@ -564,7 +568,7 @@ impl InformationPlayerStrategy {
fn get_hint(&self, view: &BorrowedGameView) -> TurnChoice { fn get_hint(&self, view: &BorrowedGameView) -> TurnChoice {
let total_info = 3 * (view.board.num_players - 1); 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 hint_type = hint_info.value % 3;
let player_amt = (hint_info.value - hint_type) / 3; let player_amt = (hint_info.value - hint_type) / 3;
@ -699,12 +703,16 @@ impl PlayerStrategy for InformationPlayerStrategy {
- (COLORS.len() * VALUES.len()) as u32 - (COLORS.len() * VALUES.len()) as u32
- (view.board.num_players * view.board.hand_size); - (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 view.board.discard_size() <= discard_threshold {
// if anything is totally useless, discard it // if anything is totally useless, discard it
if let Some(i) = self.find_useless_card(view, &private_info) { if public_useless_indices.len() > 1 {
return TurnChoice::Discard(i); 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) { if self.someone_else_can_play(view) {
return self.get_hint(view); return self.get_hint(view);
} else { } else {
print!("This actually happened"); // print!("This actually happens");
} }
} }
@ -722,8 +730,11 @@ impl PlayerStrategy for InformationPlayerStrategy {
// infer that we have no playable cards // infer that we have no playable cards
// if anything is totally useless, discard it // if anything is totally useless, discard it
if let Some(i) = self.find_useless_card(view, &private_info) { if public_useless_indices.len() > 1 {
return TurnChoice::Discard(i); 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 // Play the best discardable card
@ -759,6 +770,16 @@ impl PlayerStrategy for InformationPlayerStrategy {
} }
TurnChoice::Discard(index) => { TurnChoice::Discard(index) => {
if let &TurnResult::Discard(ref card) = &turn.result { 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); self.update_public_info_for_discard_or_play(view, &turn.player, index, card);
} else { } else {
panic!("Got turn choice {:?}, but turn result {:?}", panic!("Got turn choice {:?}, but turn result {:?}",