From 7ace892f40b740a11be2dccfd9529a5515f54e6e Mon Sep 17 00:00:00 2001 From: Felix Bauckholt Date: Tue, 26 Feb 2019 14:50:49 +0100 Subject: [PATCH] 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. --- README.md | 4 ++-- src/strategies/information.rs | 28 ++++++++++++++++++---------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 05f0b25..45507c0 100644 --- a/README.md +++ b/README.md @@ -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 | 20.9745 | 24.6041 | 24.8543 | 24.8942 | -| | 04.40 % | 75.07 % | 89.59 % | 91.53 % | +|info | 21.9455 | 24.7136 | 24.8868 | 24.8976 | +| | 07.01 % | 79.46 % | 91.26 % | 91.91 % | To reproduce: diff --git a/src/strategies/information.rs b/src/strategies/information.rs index 57a24ef..d3d1ec4 100644 --- a/src/strategies/information.rs +++ b/src/strategies/information.rs @@ -603,6 +603,20 @@ impl InformationPlayerStrategy { 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( &mut self, view: &BorrowedGameView, @@ -970,11 +984,6 @@ impl PlayerStrategy for InformationPlayerStrategy { view.board.total_cards - (COLORS.len() * VALUES.len()) as u32 - (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 // 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 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 // (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 > 4 { true } + // this is the only case in which we discard a potentially useful card. else { false }; if will_hint { @@ -1027,10 +1039,6 @@ impl PlayerStrategy for InformationPlayerStrategy { 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 let mut compval = 0.0; let mut index = 0;