Make better decisions between hinting and discarding

I think most of the gains of this change come from the fact
that now we don't discard any potentially useful cards if we have more
than 4 hints remaining.
This commit is contained in:
Felix Bauckholt 2019-02-26 14:50:49 +01:00 committed by Jeff Wu
parent b3a8209b74
commit 7ace892f40
2 changed files with 20 additions and 12 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 | |cheat | 24.8600 | 24.9781 | 24.9715 | 24.9570 |
| | 90.52 % | 98.12 % | 97.74 % | 96.57 % | | | 90.52 % | 98.12 % | 97.74 % | 96.57 % |
|info | 20.9745 | 24.6041 | 24.8543 | 24.8942 | |info | 21.9455 | 24.7136 | 24.8868 | 24.8976 |
| | 04.40 % | 75.07 % | 89.59 % | 91.53 % | | | 07.01 % | 79.46 % | 91.26 % | 91.91 % |
To reproduce: To reproduce:

View file

@ -603,6 +603,20 @@ impl InformationPlayerStrategy {
info.update_for_hint(&hint.hinted, matches); info.update_for_hint(&hint.hinted, matches);
} }
fn someone_else_needs_hint(&self) -> bool {
// Does another player have a playable card, but doesn't know it?
let view = &self.last_view;
view.get_other_players().iter().any(|player| {
let has_playable_card = view.get_hand(&player).iter().any(|card| {
view.get_board().is_playable(card)
});
let knows_playable_card = self.get_player_public_info(&player).iter().any(|table| {
table.probability_is_playable(view.get_board()) == 1.0
});
has_playable_card && !knows_playable_card
})
}
fn update_public_info_for_discard_or_play( fn update_public_info_for_discard_or_play(
&mut self, &mut self,
view: &BorrowedGameView, view: &BorrowedGameView,
@ -970,11 +984,6 @@ impl PlayerStrategy for InformationPlayerStrategy {
view.board.total_cards view.board.total_cards
- (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);
let soft_discard_threshold = if view.board.num_players < 5 {
discard_threshold - 5
} else {
discard_threshold
}; // TODO something more principled.
// make a possibly risky play // make a possibly risky play
// TODO: consider removing this, if we improve information transfer // TODO: consider removing this, if we improve information transfer
@ -1007,10 +1016,13 @@ impl PlayerStrategy for InformationPlayerStrategy {
let useless_indices = self.find_useless_cards(view, &private_info); let useless_indices = self.find_useless_cards(view, &private_info);
let will_hint = let will_hint =
if view.board.discard_size() <= soft_discard_threshold && useless_indices.len() > 0 { false } 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 }
// hinting is better than discarding dead cards // hinting is better than discarding dead cards
// (probably because it stalls the deck-drawing). // (probably because it stalls the deck-drawing).
else if view.board.hints_remaining > 0 && view.someone_else_can_play() { true } else if view.board.hints_remaining > 0 && view.someone_else_can_play() { true }
else if view.board.hints_remaining > 4 { true }
// this is the only case in which we discard a potentially useful card.
else { false }; else { false };
if will_hint { if will_hint {
@ -1027,10 +1039,6 @@ impl PlayerStrategy for InformationPlayerStrategy {
return TurnChoice::Discard(useless_indices[0]); return TurnChoice::Discard(useless_indices[0]);
} }
// NOTE: the only conditions under which we would discard a potentially useful card:
// - we have no known useless cards
// - there are no hints remaining OR nobody else can play
// Play the best discardable card // Play the best discardable card
let mut compval = 0.0; let mut compval = 0.0;
let mut index = 0; let mut index = 0;