implement discarding dupes and sacrifice discards
This commit is contained in:
parent
43477b1023
commit
8398173939
1 changed files with 68 additions and 18 deletions
|
@ -194,7 +194,7 @@ namespace Hanabi
|
|||
|
||||
_actions_log.emplace(ActionType::play, played_card, index, _num_clues == 8, strike);
|
||||
|
||||
if (is_playable(played_card))
|
||||
if (!strike)
|
||||
{
|
||||
--_stacks[played_card.suit];
|
||||
_score++;
|
||||
|
@ -951,10 +951,62 @@ namespace Hanabi
|
|||
// Check for discards now
|
||||
if (_pace > 0 and _num_clues < max_num_clues)
|
||||
{
|
||||
for (std::uint8_t index = 0; index < hand_size; index++)
|
||||
// This will hold the index of trash to discard
|
||||
std::uint8_t const invalid_index = std::numeric_limits<std::uint8_t>::max();
|
||||
std::uint8_t discard_index = invalid_index;
|
||||
|
||||
for (hand_index_t index = 0; index < hand_size; index++)
|
||||
{
|
||||
if (is_trash(hand[index]))
|
||||
{
|
||||
discard_index = index;
|
||||
|
||||
// All discards are equivalent, do not continue searching for different trash
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no trivial trash found, check for duplicates next
|
||||
if (discard_index == invalid_index) {
|
||||
for (std::uint8_t index = 0; index < hand_size; index++) {
|
||||
Card const card = _hands[_turn][index];
|
||||
auto it = std::find_if(_hands[_turn].begin() + index + 1, _hands[_turn].end(), [&card, this](Card const & card_in_hand) {
|
||||
return card_in_hand == card;
|
||||
});
|
||||
if (it != _hands[_turn].end()) {
|
||||
// found a duplicate to discard
|
||||
discard_index = index;
|
||||
// Since we are discarding essentially trash, we do not have to consider further actions
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Discard if we found trash now
|
||||
if (discard_index != invalid_index) {
|
||||
probability_t sum_of_probabilities = 0;
|
||||
|
||||
do_for_each_potential_draw(discard_index, false, [this, &sum_of_probabilities](const unsigned long multiplicity) {
|
||||
sum_of_probabilities += evaluate_state() * multiplicity;
|
||||
});
|
||||
|
||||
const unsigned long total_weight = std::max(static_cast<unsigned long>(_weighted_draw_pile_size), 1ul);
|
||||
const probability_t probability_discard = sum_of_probabilities / total_weight;
|
||||
best_probability = std::max(best_probability, probability_discard);
|
||||
|
||||
best_probability = std::max(best_probability, probability_discard);
|
||||
if (best_probability == 1)
|
||||
{
|
||||
update_tablebase(id_of_state, best_probability);
|
||||
return best_probability;
|
||||
};
|
||||
} else {
|
||||
// If we reach this state, then there are no dupes in hand, so we need to check if we want to
|
||||
// sacrifice cards in hand
|
||||
for(hand_index_t index = 0; index < hand_size; ++index) {
|
||||
if(!is_critical(hand[index])) {
|
||||
std::cout << "Considered sacrificing card " << hand[index] << "in the following state:\n" << *this << std::endl;
|
||||
// consider discarding this
|
||||
probability_t sum_of_probabilities = 0;
|
||||
|
||||
do_for_each_potential_draw(index, false, [this, &sum_of_probabilities](const unsigned long multiplicity) {
|
||||
|
@ -971,9 +1023,7 @@ namespace Hanabi
|
|||
update_tablebase(id_of_state, best_probability);
|
||||
return best_probability;
|
||||
};
|
||||
|
||||
// All discards are equivalent, do not continue searching for different trash
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue