If a player discards because nobody needed a hint, make that common knowledge

"Needing a hint" is defined as having a playable card, but not knowing
any specific card is playable. Thus, if a player doesn't know any
playable cards and someone else discards, the player (publicly)
concludes that all their cards are unplayable.
This commit is contained in:
Felix Bauckholt 2019-02-26 18:47:07 +01:00 committed by Jeff Wu
parent 7ace892f40
commit 35502541a2
2 changed files with 36 additions and 2 deletions

View file

@ -63,8 +63,8 @@ On seeds 0-9999, we have these average scores and win rates:
|-------|---------|---------|---------|---------|
|cheat | 24.8600 | 24.9781 | 24.9715 | 24.9570 |
| | 90.52 % | 98.12 % | 97.74 % | 96.57 % |
|info | 21.9455 | 24.7136 | 24.8868 | 24.8976 |
| | 07.01 % | 79.46 % | 91.26 % | 91.91 % |
|info | 22.3360 | 24.7279 | 24.8889 | 24.8991 |
| | 09.98 % | 80.48 % | 91.37 % | 92.10 % |
To reproduce:

View file

@ -617,6 +617,33 @@ impl InformationPlayerStrategy {
})
}
fn update_noone_else_needs_hint(&mut self) {
// If it becomes public knowledge that someone_else_needs_hint() returns false,
// update accordingly.
for player in self.last_view.board.get_players() {
if player != self.last_view.board.player {
let knows_playable_card = self.get_player_public_info(&player).iter().any(|table| {
table.probability_is_playable(self.last_view.get_board()) == 1.0
});
if !knows_playable_card {
// If player doesn't know any playable cards, player doesn't have any playable
// cards.
let mut hand_info = self.take_public_info(&player);
for ref mut card_table in hand_info.iter_mut() {
let view = &self.last_view;
let possible = card_table.get_possibilities();
for card in &possible {
if view.get_board().is_playable(card) {
card_table.mark_false(card);
}
}
}
self.return_public_info(&player, hand_info);
}
}
}
}
fn update_public_info_for_discard_or_play(
&mut self,
view: &BorrowedGameView,
@ -1015,6 +1042,7 @@ impl PlayerStrategy for InformationPlayerStrategy {
let public_useless_indices = self.find_useless_cards(view, &self.get_my_public_info());
let useless_indices = self.find_useless_cards(view, &private_info);
// NOTE When changing this, make sure to keep the "discard" branch of update() up to date!
let will_hint =
if view.board.hints_remaining > 0 && self.someone_else_needs_hint() { true }
else if view.board.discard_size() <= discard_threshold && useless_indices.len() > 0 { false }
@ -1083,6 +1111,12 @@ impl PlayerStrategy for InformationPlayerStrategy {
known_useless_indices.len() as u32, value as u32
));
}
if self.last_view.board.hints_remaining > 0 {
// TODO It would be more information-efficient to do this before the call to
// update_from_hint_sum(). To do that, we would have to restructure decide()
// as well.
self.update_noone_else_needs_hint();
}
if let &TurnResult::Discard(ref card) = &turn_record.result {
self.update_public_info_for_discard_or_play(view, &turn_record.player, index, card);