奥马哈嗨手评估员

时间:2009-08-20 11:14:57

标签: iteration lookup-tables poker

目前我正试图将Keith Rule的德州扑克手评估员移植到奥马哈嗨:

在仔细考虑算法之后,我找到了一个解决方案,它给了我正确的手百分比,一切都很好..

但它真的很慢。我怎样才能加快速度?

我现在唯一要做的就是查找正常的五张牌,LUT可能适合我。有人在之前整合了一个吗?

static void Main(string[] args)
    {
        long count = 0;
        double player1win = 0.0, player2win=0.0;
        ulong player1 = Hand.ParseHand("Ad Kd As Ks");
        ulong player2 = Hand.ParseHand("Th 5c 2c 7d");
        foreach (ulong board in Hand.Hands(0, player1 | player2, 5))
        {
            uint maxplayer1value = 0, maxplayer2value = 0;
            foreach (ulong boardcards in Hand.Hands(0, ulong.MaxValue ^ board, 3))
            {
                foreach (ulong player1hand in Hand.Hands(0Ul, ulong.MaxValue ^ player1, 2))
                {
                    uint player1value = Hand.Evaluate(player1hand | boardcards, 5);
                    if (player1value > maxplayer1value) maxplayer1value = player1value;

                }
            }
            foreach (ulong boardcards in Hand.Hands(0, ulong.MaxValue ^ board, 3))
            {
                foreach (ulong player2hand in Hand.Hands(0UL, ulong.MaxValue ^ player2, 2))
                {
                    uint player2value = Hand.Evaluate(player2hand | boardcards, 5);
                    if (player2value > maxplayer2value) maxplayer2value = player2value;

                }
            }

            if (maxplayer1value > maxplayer2value)
            {
                player1win += 1.0;
            }
            else if (maxplayer2value > maxplayer1value)
            {
                player2win += 1.0;
            }
            else
            {
                player1win += 0.5;
                player2win += 0.5;
            }
            count++;
        }
        Console.WriteLine("Player1: {0:0.0000} Player2: {1:0.0000} Count: {2}", player1win / count * 100, player2win / count * 100, count);
        Console.ReadLine();       
    }

2 个答案:

答案 0 :(得分:3)

看起来你正在尝试创建权益计算器。我也是这样做的,但不是奥马哈(德州扑克代替)。随后玩家将进行评估,我每秒约有200K手,这足以在短时间内提供准确的结果。如果只有两名球员 评估,我每秒最多可以获得400万次评估。

我用手拿着位掩码。一个64位整数表示卡,手或整板。显然,你只需要52个。通过使用按位运算符,事情变得相当快。这是我项目的快速示例(在C ++中)。它使用2 + 2评估器 快速查找:


        while (trial < trials) {
                /** I use here a linked list over the hand-distributions (players).
                  * This is kind of natural as well, as circle is the basic
                  * shape of poker.
                  */
                pDist = pFirstDist;

                unsigned __int64 usedCards = _deadCards;
                bool collision;

                /** Here, we choose random distributions for the comparison.
                  * There is a chance, that two separate distributions has
                  * the same card being picked-up. In that case, we have a collision,
                  * so do the choosing again.
                  */
                do {
                        pDist->Choose(usedCards, collision);

                        /** If there is only one hand in the distribution (unary),
                          * there is no need to check over collision, since it's been
                          * already done in the phase building them (distributions).
                          */
                        if (pDist->_isUnary)
                                collision = false;

                        pDist = pDist->_pNext;
                } while (pDist != pFirstDist && !collision);

                if (collision) {
                        /** Oops! Collision occurred! Take the next player (hand-
                          * distribution and do this all over again.
                          *
                          */
                        pFirstDist = pDist->_pNext;

                        continue;
                }

                unsigned __int64 board = 0;

                /** Pick a board from the hashed ones, until it's unique compared to
                  * the distributions.
                  *
                  */
                do {
                        if (count == 1) {
                                board = boards[0];
                                collision = false;
                        } else {
                                board = boards[Random()];
                                collision = (board & usedCards) != 0;
                        }
                } while (collision);

                board |= _boardCards;

                int best = 0, s = 1;

                do {
                        pDist->_currentHand |= board;

                        unsigned long i, l = static_cast<unsigned long>(pDist->_currentHand >> 32);
                        int p;
                        bool f = false;

                        /** My solution to find out the set bits.
                          * Since I'm working on a 32-bit environment, the "64-bit"
                          * variable needs to be split in to parts.
                          */
                        if (_BitScanForward(&i, l)) {
                                p = _evaluator->_handRanks[53 + i + 32]; // Initial entry to the 2 + 2 evaluator hash.
                                l &= ~(static_cast<unsigned long>(1) << i);
                                f = true;
                        }

                        if (f)
                                while (_BitScanForward(&i, l)) {
                                        l &= ~(static_cast<unsigned long>(1) << i);
                                        p = _evaluator->_handRanks[p + i + 32];
                                }

                        l = static_cast<unsigned long>(pDist->_currentHand & 0xffffffff);

                        if (!f) {
                                _BitScanForward(&i, l);

                                p = _evaluator->_handRanks[53 + i];
                                l &= ~(static_cast<unsigned long>(1) << i);
                        }

                        while (_BitScanForward(&i, l)) {
                                l &= ~(static_cast<unsigned long>(1) <<_handRanks[p + i];
                        }

                        pDist->_rank = p;

                        /** Keep the statistics up. Please do remember, that
                          * equity consist of ties as well, so it's not a percentual
                          * chance of winning.
                          */
                        if (p > best) {
                                pWinner = pDist;
                                s = 1;
                                best = p;
                        } else if (p == best)
                                ++s;

                        pDist = pDist->_pNext;
                } while (pDist != pFirstDist);

                if (s > 1) {
                        for (unsigned int i = 0; i _rank == best) {
                                        _handDistributions[i]->_ties += 1.0f / s;
                                        _handDistributions[i]->_equity += 1.0f / s;
                                }
                } else {
                        ++pWinner->_wins;
                        ++pWinner->_equity;
                }

                ++trial;

                pFirstDist = pDist->_pNext;
        }

请参考2 + 2评估员,这很容易适应您自己的需要。

答案 1 :(得分:1)

这可能会有所帮助:

可以找到现成的Objective-C(和Java)德州扑克7和5卡评估员的示例here并进一步解释here。它“添加”手来生成一个足以表征手牌以确定排名的指数。

所有反馈都欢迎来自其中的电子邮件地址