void HolmesBot::pleaseObserveValueHint()

in csrc/HolmesBot.cc [390:440]


void HolmesBot::pleaseObserveValueHint(const Hanabi::Server &server, int from, int to, Value value, CardIndices card_indices)
{
    assert(server.whoAmI() == me_);

    /* Someone has given Bob a value hint. If the named cards
     * include the one Bob would normally be discarding next,
     * then this must be a warning that that card is valuable.
     * Otherwise, all the named cards are playable. */

    const int discardIndex = this->nextDiscardIndex(server, to);
    const bool isPointless = (value < lowestPlayableValue_);
    const bool isWarning =
        card_indices.contains(discardIndex) &&
        couldBeValuable(server, handKnowledge_[to][discardIndex], value);
    const bool isHintStoneReclaim =
        (!server.discardingIsAllowed()) &&
        (from == (to+1) % server.numPlayers()) &&
        card_indices.contains(0);

    if (isHintStoneReclaim) {
        return;
    }

    assert(!isPointless || permissive_);

    if (isWarning) {
        assert(discardIndex != -1);
        handKnowledge_[to][discardIndex].isValuable = true;
        if (value == lowestPlayableValue_) {
            /* This card is valuable, i.e., not worthless; therefore it
             * must be playable sometime in the future. And since it's
             * the lowest playable value already, it must in fact be
             * playable right now! But we can't say the same thing for
             * any of the other named cards. */
            handKnowledge_[to][discardIndex].isPlayable = true;
        }
    }

    const int numCards = server.sizeOfHandOfPlayer(to);
    for (int i=0; i < numCards; ++i) {
        CardKnowledge &knol = handKnowledge_[to][i];
        if (card_indices.contains(i)) {
            knol.setMustBe(value);
            if (knol.color() == -1 && !isWarning && !knol.isWorthless) {
                knol.isPlayable = true;
            }
        } else {
            knol.setCannotBe(value);
        }
    }
}