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:
parent
7ace892f40
commit
35502541a2
2 changed files with 36 additions and 2 deletions
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue