1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 00:27:35 +00:00

Hearts: Let the AI prefer lead cards for which other cards are in play

When picking a lead card the AI should avoid playing cards where it
knows that no other player has a lower value card of the same type.
This commit is contained in:
Gunnar Beutner 2021-05-23 14:49:58 +02:00 committed by Andreas Kling
parent 647d0f9f8a
commit 2dfced2501
3 changed files with 19 additions and 5 deletions

View file

@ -210,7 +210,10 @@ size_t Game::pick_card(Player& player)
auto prefer_card = [this, &player](Card& card) { auto prefer_card = [this, &player](Card& card) {
return !other_player_has_lower_value_card(player, card) && other_player_has_higher_value_card(player, card); return !other_player_has_lower_value_card(player, card) && other_player_has_higher_value_card(player, card);
}; };
return player.pick_lead_card(move(valid_card), move(prefer_card)); auto lower_value_card_in_play = [this, &player](Card& card) {
return other_player_has_lower_value_card(player, card);
};
return player.pick_lead_card(move(valid_card), move(prefer_card), move(lower_value_card_in_play));
} }
} }
auto* high_card = &m_trick[0]; auto* high_card = &m_trick[0];

View file

@ -11,7 +11,8 @@
namespace Hearts { namespace Hearts {
size_t Player::pick_lead_card(Function<bool(Card&)> valid_play, Function<bool(Card&)> prefer_card) size_t Player::pick_lead_card(Function<bool(Card&)> valid_play, Function<bool(Card&)> prefer_card,
Function<bool(Card&)> lower_value_card_in_play)
{ {
struct CardWithIndex { struct CardWithIndex {
RefPtr<Card> card; RefPtr<Card> card;
@ -38,17 +39,27 @@ size_t Player::pick_lead_card(Function<bool(Card&)> valid_play, Function<bool(Ca
dbgln("----"); dbgln("----");
} }
size_t last_index = -1; ssize_t fallback_index = -1;
ssize_t last_index = -1;
for (auto& cwi : sorted_hand) { for (auto& cwi : sorted_hand) {
if (!valid_play(*cwi.card)) if (!valid_play(*cwi.card))
continue; continue;
if (lower_value_card_in_play(*cwi.card)) {
// Allow falling back to this card if no other suitable card is in play.
fallback_index = cwi.index;
continue;
}
if (prefer_card(*cwi.card)) { if (prefer_card(*cwi.card)) {
dbgln_if(HEARTS_DEBUG, "Preferring card {}", *cwi.card); dbgln_if(HEARTS_DEBUG, "Preferring card {}", *cwi.card);
return cwi.index; return cwi.index;
} }
last_index = cwi.index; last_index = cwi.index;
} }
return last_index; if (last_index == -1) {
dbgln_if(HEARTS_DEBUG, "Falling back to card {}", *hand[fallback_index]);
return fallback_index;
} else
return last_index;
} }
Optional<size_t> Player::pick_low_points_high_value_card(Optional<Card::Type> type) Optional<size_t> Player::pick_low_points_high_value_card(Optional<Card::Type> type)

View file

@ -21,7 +21,7 @@ public:
{ {
} }
size_t pick_lead_card(Function<bool(Card&)>, Function<bool(Card&)>); size_t pick_lead_card(Function<bool(Card&)>, Function<bool(Card&)>, Function<bool(Card&)>);
Optional<size_t> pick_low_points_high_value_card(Optional<Card::Type> type = {}); Optional<size_t> pick_low_points_high_value_card(Optional<Card::Type> type = {});
Optional<size_t> pick_lower_value_card(Card& other_card); Optional<size_t> pick_lower_value_card(Card& other_card);
Optional<size_t> pick_slightly_higher_value_card(Card& other_card); Optional<size_t> pick_slightly_higher_value_card(Card& other_card);