void CardKnowledge::update()

in csrc/HolmesBot.cc [94:193]


void CardKnowledge::update(const Server &server, const HolmesBot &bot)
{
    int color = this->color_;
    int value = this->value_;

  repeat_loop:

    if (color == -1) {
        for (Color k = RED; k <= BLUE; ++k) {
            if (this->cannotBe(k)) continue;
            else if (color == -1) color = k;
            else { color = -1; break; }
        }
        if (color != -1) this->setMustBe(Color(color));
    }

    if (value == -1) {
        for (int v = 1; v <= 5; ++v) {
            if (this->cannotBe(Value(v))) continue;
            else if (value == -1) value = v;
            else { value = -1; break; }
        }
        if (value != -1) this->setMustBe(Value(value));
    }

    // this is the complicated part

    assert(color == this->color_);
    assert(value == this->value_);

    /* See if we can identify the card based on what we know
     * about its properties. */
    if (value == -1 || color == -1) {
        bool restart = false;
        for (Color k = RED; k <= BLUE; ++k) {
            for (int v = 1; v <= 5; ++v) {
                if (this->cantBe_[k][v]) continue;
                const int total = (v == 1 ? 3 : (v == 5 ? 1 : 2));
                const int played = bot.playedCount_[k][v];
                const int held = bot.locatedCount_[k][v];
                assert(played+held <= total || bot.permissive_);
                if ((played+held >= total) ||
                    (isValuable && !bot.isValuable(server, Card(k,v))) ||
                    (isPlayable && !server.pileOf(k).nextValueIs(v)) ||
                    (isWorthless && !server.pileOf(k).contains(v)))
                {
                    this->cantBe_[k][v] = true;
                    restart = true;
                }
            }
        }
        if (restart) goto repeat_loop;
    }

    /* If the card is worthless, it's not valuable or playable. */
    if (this->isWorthless) return;

    if (!this->isPlayable && !this->isValuable) {
        for (Color k = RED; k <= BLUE; ++k) {
            for (int v = 1; v <= 5; ++v) {
                if (this->cantBe_[k][v]) continue;
                if (!server.pileOf(k).contains(v)) {
                    goto mightBeUseful;
                }
            }
        }
        this->isWorthless = true;
        return;
      mightBeUseful:;
    }

    /* Valuableness and playableness are orthogonal. */
    assert(!this->isWorthless || bot.permissive_);

    if (!this->isValuable) {
        for (Color k = RED; k <= BLUE; ++k) {
            for (int v = 1; v <= 5; ++v) {
                if (this->cantBe_[k][v]) continue;
                if (!bot.isValuable(server, Card(k,v))) {
                    goto mightNotBeValuable;
                }
            }
        }
        this->isValuable = true;
      mightNotBeValuable:;
    }

    if (!this->isPlayable) {
        for (Color k = RED; k <= BLUE; ++k) {
            for (int v = 1; v <= 5; ++v) {
                if (this->cantBe_[k][v]) continue;
                if (!server.pileOf(k).nextValueIs(v)) {
                    goto mightBeUnplayable;
                }
            }
        }
        this->isPlayable = true;
      mightBeUnplayable:;
    }
}