Hint SmartBot::bestHintForPlayer()

in csrc/SmartBot.cc [930:984]


Hint SmartBot::bestHintForPlayer(int partner) const
{
    assert(partner != me_);
    const std::vector<Card> partners_hand = server_->handOfPlayer(partner);

    bool is_really_playable[5];
    for (int c=0; c < partners_hand.size(); ++c) {
        is_really_playable[c] =
            server_->pileOf(partners_hand[c].color).nextValueIs(partners_hand[c].value);
    }

    /* Avoid giving hints that could be misinterpreted as warnings. */
    int valueToAvoid = -1;
    if (partner == (me_ + 1) % handKnowledge_.size()) {
        const int discardIndex = nextDiscardIndex(partner);
        if (discardIndex != -1) {
            const CardKnowledge &knol = handKnowledge_[partner][discardIndex];
            valueToAvoid = partners_hand[discardIndex].value;
            if (!knol.couldBeValuableWithValue(valueToAvoid)) valueToAvoid = -1;
        }
    }

    return bestHintForPlayerGivenConstraint(partner, [&](Hint hint, const std::vector<CardKnowledge>& oldKnols, const std::vector<CardKnowledge>& newKnols) {
        if (hint.value != -1 && hint.value == valueToAvoid) {
            // This hint would be misinterpreted as a valuable warning.
            return false;
        }
        // If this hint identified a new playable card, then it is a good hint.
        // If this hint did not unambiguously identify a new playable card,
        // but the newest card it touched *is* playable in reality, then it is
        // a good hint.
        // If this hint did not unambiguously identify a new playable card
        // and the newest card it touched is *not* playable in reality, then
        // it is misleading and MUST not be given.
        bool reveals_a_playable_card = false;
        trivalue is_misleading = MAYBE;
        for (int c = partners_hand.size()-1; c >= 0; --c) {
            if (oldKnols[c].playable() != MAYBE) continue;
            if (newKnols[c].playable() == YES) {
                reveals_a_playable_card = true;
            } else if (newKnols[c].playable() == MAYBE && hint.includes(partners_hand[c])) {
                if (is_misleading == MAYBE) {
                    is_misleading = (is_really_playable[c] ? NO : YES);
                }
            }
        }
        if (reveals_a_playable_card || (is_misleading == NO)) {
            // This is a good hint that will reveal a playable card.
            return true;
        } else {
            // This is a misleading or worthless hint.
            return false;
        }
    });
}