Exemple #1
0
int main(int argc, char *argv[])
{
    // Setup deck of cards
    CardSet deck;
    for (Rank r = RANK_BEGIN; r != RANK_END; ++r) {
        for (Suit s = SUIT_BEGIN; s != SUIT_END; ++s) {
            Card card(r, s);
            deck.insert(card);
        }
    }

    unsigned long long count = 0;

    // Test each starting hand
    for (CardSet::const_iterator i = deck.begin(); i != deck.end(); ++i) {
        CardSet::const_iterator j = i;
        for (++j; j != deck.end(); ++j) {
            string hole = Card::pairString(*i, *j);
            CardSet test(deck);
            Hand hand;
            test.erase(*i); hand.append(*i);
            test.erase(*j); hand.append(*j);
            count++;
            board(hole, test, hand);
        }
    }

    cout << "TOTAL: " << count << endl;
    printStats();

    return 0;
}
Exemple #2
0
void Observer::cardsPickedUp(const PlayerId *playerId, const CardSet &cardSet)
{
    mPlayersCards[playerId] += cardSet.size();
    CardSet& set = mCurrentRoundData->mPickedUpCards[playerId];
    unsigned int oldSize = set.size();
    set.insert(cardSet.begin(), cardSet.end());
    assert(oldSize + cardSet.size() == set.size());
}
Exemple #3
0
bool Engine::findByPtr(const CardSet& cards, const Card* card)
{
    for (CardSet::const_iterator it = cards.begin(); it != cards.end(); ++it) {
        if (&*it == card) {
            return true;
        }
    }
    return false;
}
Exemple #4
0
void Observer::cardsDropped(const PlayerId *playerId, const CardSet &cardSet)
{
    mPlayersCards[playerId] -= cardSet.size();
    if (mCurrentRoundData->mDroppedCards.find(playerId) == mCurrentRoundData->mDroppedCards.end()) {
        mCurrentRoundData->mDroppedCards[playerId] = CardSet();
    }
    CardSet& set = mCurrentRoundData->mDroppedCards[playerId];
    unsigned int oldSize = set.size();
    set.insert(cardSet.begin(), cardSet.end());
    assert(oldSize + cardSet.size() == set.size());
}
Exemple #5
0
void board(const string& hole, const CardSet& deck, const Hand& hand)
{
    HandStats s = stats[hole];
    for (CardSet::const_iterator i = deck.begin(); i != deck.end(); ++i) {
        CardSet::const_iterator j = i;
        for (++j; j != deck.end(); ++j) {
            CardSet::const_iterator k = j;
            for (++k; k != deck.end(); ++k) {                
                s.count++;
                s.outs[ board_rank(hand, *i, *j, *k) ]++;
            }
        }
    }
    stats[hole] = s;
}
Exemple #6
0
bool Engine::playCurrentRound()
{
#define CHECK_QUIT \
if (mQuit.get()) { \
    return false; \
}

    lock();
    if (!mCurrentRoundIndex) {
        mCurrentRoundIndex = &mRoundIndex;
        // prepare round data
        // pick current player as first attacker
        mAttackers.push_back(mCurrentPlayer);
        // if there was no deal yet (very first round) - do not consider cards while picking next players
        std::map<const PlayerId*, CardSet>* cards = *mCurrentRoundIndex ? &mPlayersCards : NULL;
        // pick next player as defender
        mDefender = Rules::pickNext(mGeneratedIds, mCurrentPlayer, cards);
        // gather rest players as additional attackers
        const PlayerId* attacker = mDefender;
        while((attacker = Rules::pickNext(mGeneratedIds, attacker, cards)) != mCurrentPlayer) {
            if (attacker) {
                mAttackers.push_back(attacker);
            }
        }
        unlock();
        std::for_each(mGameObservers.begin(), mGameObservers.end(), RoundStartNotification(mAttackers, mDefender, mRoundIndex));
        // deal cards
        dealCards();
        lock();
        mMaxAttackCards = Rules::maxAttackCards(mPlayersCards[mDefender].size());
        assert(mMaxAttackCards);
    }

    CardSet& defenderCards = mPlayersCards[mDefender];

    if (!mCurrentRoundAttackerId) {
        mCurrentRoundAttackerId = mAttackers[0];
        mPassedCounter = 0;
    }

    Player& defender = *mPlayers[mDefender];

    unlock();

    for (;;) {

        if (mTableCards.attackCards().size() == mMaxAttackCards) {
            // defender has no more cards - defend succeeded
            break;
        }

        const Card* attackCardPtr;

        if (mPickAttackCardFromTable) {
            assert(!mTableCards.attackCards().empty());
            attackCardPtr = &*(mTableCards.attackCards().end() - 1);
        } else {
            CardSet attackCards = Rules::getAttackCards(mTableCards.all(), mPlayersCards[mCurrentRoundAttackerId]);

            Player& currentAttacker = *mPlayers[mCurrentRoundAttackerId];

            if (mTableCards.empty()) {
                attackCardPtr = attackCards.empty() ? NULL : &currentAttacker.attack(mDefender, attackCards);
            } else {
                // ask for pitch even with empty attackCards - expected NULL attack card pointer
                attackCardPtr = currentAttacker.pitch(mDefender, attackCards);
            }

            // check if quit requested and only after that transfer move to defender
            CHECK_QUIT;

            if (attackCards.empty() || !attackCardPtr) {
                lock();
                // player skipped the move - pick next attacker
                mCurrentRoundAttackerId = Rules::pickNext(mAttackers, mCurrentRoundAttackerId, &mPlayersCards);
                // if more than one attacker and we have first attacker again - reset pass counter
                if (mAttackers.size() > 1 && mCurrentRoundAttackerId == mAttackers[0]) {
                    mPassedCounter = 0;
                }
                mPassedCounter++;
                unlock();

                if (mPassedCounter == mAttackers.size()) {
                    // all attackers "passed" - round ended
                    break;
                }
                continue;
            }

            assert(attackCardPtr);

            if(!findByPtr(attackCards, attackCardPtr)) {
                // invalid card returned - the card is not from attackCards
                assert(!attackCards.empty());
                // take any card
                attackCardPtr = &*attackCards.begin();
            }

            Card attackCard = *attackCardPtr;

            lock();
            mTableCards.addAttackCard(attackCard);
            mPlayersCards[mCurrentRoundAttackerId].erase(attackCard);
            unlock();
            CHECK_QUIT;
            std::for_each(mGameObservers.begin(), mGameObservers.end(), CardsDroppedNotification(mCurrentRoundAttackerId, attackCard));
            // the card is removed from the `attackCards` and is added to `mTableCards`, so update its pointer
            attackCardPtr = &*std::find(mTableCards.attackCards().begin(), mTableCards.attackCards().end(), attackCard);
        }

        if (mDefendFailed) {
            continue;
        }

        CardSet defendCards = Rules::getDefendCards(*attackCardPtr, defenderCards, mDeck->trumpSuit());

        const Card* defendCardPtr = defender.defend(mCurrentRoundAttackerId, *attackCardPtr, defendCards);

        bool noCardsToDefend = defendCards.empty();
        bool userGrabbedCards = !defendCardPtr;
        bool invalidDefendCard = !findByPtr(defendCards, defendCardPtr);

        lock();
        mPickAttackCardFromTable = false;
        unlock();

        if(noCardsToDefend || userGrabbedCards || invalidDefendCard) {
            // defend failed
            lock();
            mDefendFailed = true;
            unlock();
        } else {
            lock();
            mTableCards.addDefendCard(*defendCardPtr);
            defenderCards.erase(*defendCardPtr);
            unlock();
            CHECK_QUIT;
            std::for_each(mGameObservers.begin(), mGameObservers.end(), CardsDroppedNotification(mDefender, *defendCardPtr));
        }
    }

    if (mDefendFailed) {
        lock();
        defenderCards.insert(mTableCards.all().begin(), mTableCards.all().end());
        defender.cardsUpdated(defenderCards);
        unlock();
        CHECK_QUIT;
        std::for_each(mGameObservers.begin(), mGameObservers.end(), CardsReceivedNotification(mDefender, mTableCards.all()));
    } else {
        std::for_each(mGameObservers.begin(), mGameObservers.end(), CardsGoneNotification(mTableCards.all()));
    }

    // cleanup
    lock();
    mCurrentRoundAttackerId = NULL;
    mMaxAttackCards = 0;
    mCurrentRoundIndex = NULL;
    unlock();
    CHECK_QUIT;

    std::for_each(mGameObservers.begin(), mGameObservers.end(), RoundEndNotification(mRoundIndex));

    return !mDefendFailed;
}