コード例 #1
0
        /// <summary>
        /// Returns an array containing all possible bit masks with active players.
        /// </summary>
        /// <param name="totalCount">Total number of players</param>
        /// <param name="minCount">Inclusive minimal number of active players</param>
        /// <param name="maxCount">Inclusive maximal number of active players</param>
        /// <returns></returns>
        public static UInt16[] Get(int totalCount, int minCount, int maxCount)
        {
            if (totalCount < minCount || totalCount < maxCount)
            {
                throw new ArgumentOutOfRangeException("Total count must be >= than min and max counts");
            }
            int count = 0;

            for (int i = minCount; i <= maxCount; ++i)
            {
                count += (int)EnumAlgos.CountCombin(totalCount, i);
            }

            UInt16[] result = new ushort[count];

            // Use a slow but simple algorithm
            UInt16 maxMask = (UInt16)((1 << totalCount) - 1);

            count = 0;
            for (UInt16 mask = 0; mask <= maxMask; ++mask)
            {
                int bitCount = CountBits.Count(mask);
                if (minCount <= bitCount && bitCount <= maxCount)
                {
                    result[count++] = mask;
                }
            }
            return(result);
        }
コード例 #2
0
 public void Test_CountCombin()
 {
     Assert.AreEqual(1, EnumAlgos.CountCombin(0, 0));
     Assert.AreEqual(1, EnumAlgos.CountCombin(1, 0));
     Assert.AreEqual(2, EnumAlgos.CountCombin(2, 1));
     Assert.AreEqual(1326, EnumAlgos.CountCombin(52, 2));
     Assert.AreEqual(133784560, EnumAlgos.CountCombin(52, 7));
 }
コード例 #3
0
        public void Test_Random()
        {
            int REPETITIONS = 100;

#if DEBUG
            REPETITIONS = 8;
#endif

            int seed = (int)DateTime.Now.Ticks;
            Console.WriteLine("Random seed {0}", seed);
            Random rand = new Random(seed);
            _cardRng = new SequenceRng(seed);
            _cardRng.SetSequence(StdDeck.Descriptor.FullDeckIndexes);
            for (int r = 0; r < REPETITIONS; ++r)
            {
                _enumCount = r % 7;
                int sharedCount = rand.Next(0, StdDeck.Descriptor.Size + 1 - _enumCount);
                int deadCount   = rand.Next(0, StdDeck.Descriptor.Size + 1 - sharedCount - _enumCount);

                _cardRng.Shuffle(sharedCount + deadCount);
                int rc = 0;

                _shared = new CardSet();
                for (int i = 0; i < sharedCount; ++i)
                {
                    _shared |= StdDeck.Descriptor.CardSets[_cardRng.Sequence[rc++]];
                }

                _dead = new CardSet();
                for (int i = 0; i < deadCount; ++i)
                {
                    _dead |= StdDeck.Descriptor.CardSets[_cardRng.Sequence[rc++]];
                }
                Debug.Assert(rc == sharedCount + deadCount);
                Debug.Assert(!_shared.IsIntersectingWith(_dead));

                //Console.WriteLine("B: {0:x16} D:{1:x16}", board, dead);
                _combinationsCount = 0;
                _lastCs            = 0;
                CardEnum.Combin(StdDeck.Descriptor, _enumCount, _shared, _dead, VerifyCombination);
                Assert.AreEqual(EnumAlgos.CountCombin(StdDeck.Descriptor.Size - sharedCount - deadCount, _enumCount), _combinationsCount);

                _combinationsCount1 = 0;
                _lastCs1            = 0;
                CardEnum.Combin(StdDeck.Descriptor, _enumCount, _shared, _dead, VerifyCombinationParam, _combinationsCount);
                Assert.AreEqual(EnumAlgos.CountCombin(StdDeck.Descriptor.Size - sharedCount - deadCount, _enumCount), _combinationsCount1);

                _combinationsCount1 = 0;
                _lastCs1            = 0;
                int[] cards = new int[_enumCount + sharedCount].Fill(-1);
                StdDeck.Descriptor.GetIndexesAscending(_shared).ToArray().CopyTo(cards, 0);
                int[] deadIdx = StdDeck.Descriptor.GetIndexesAscending(_shared | _dead).ToArray();

                CardEnum.Combin(StdDeck.Descriptor, _enumCount, cards, sharedCount, deadIdx, deadIdx.Length, VerifyCombinationParam, _combinationsCount);
                Assert.AreEqual(EnumAlgos.CountCombin(StdDeck.Descriptor.Size - sharedCount - deadCount, _enumCount), _combinationsCount1);
            }
            Console.WriteLine("{0} repetitions done.", REPETITIONS);
        }
コード例 #4
0
ファイル: AHVO.cs プロジェクト: ivan-alles/poker-acpc
        public static float Calculate(CardSet board)
        {
            CalulateParam param     = new CalulateParam();
            int           boardSize = board.CountCards();
            int           toDeal    = 7 - boardSize;

            CardEnum.Combin(StdDeck.Descriptor, toDeal, board, CardSet.Empty, OnDeal, param);
            return((float)(param.Sum / EnumAlgos.CountCombin(52 - boardSize, toDeal)));
        }
コード例 #5
0
        /// <summary>
        /// Returns an array containing enumerated combinations.
        /// </summary>
        public static CardSet[] Combin(DeckDescriptor deckDescr, int count, CardSet sharedCards, CardSet deadCards)
        {
            CardSet           unused    = deadCards | sharedCards;
            int               combCount = (int)EnumAlgos.CountCombin(deckDescr.Size - unused.CountCards(), count);
            CombinArrayParams p         = new CombinArrayParams();

            p.arr = new CardSet[combCount];
            Combin(deckDescr, count, sharedCards, deadCards, OnCombinArray, p);
            return(p.arr);
        }
コード例 #6
0
 public void Test_CountCombinations_Idx()
 {
     int[] cards = new int[7];
     for (int i = 0; i <= 6; ++i)
     {
         _combinationsCount1 = 0;
         CardEnum.Combin(StdDeck.Descriptor, i, cards, 0, null, 0, CountCombinationsParam, 33);
         Assert.AreEqual(EnumAlgos.CountCombin(52, i), _combinationsCount1);
     }
 }
コード例 #7
0
        double CalculateAverageHVO(int[] board)
        {
            CardSet boardCs = StdDeck.Descriptor.GetCardSet(board);
            CalculateAverageHsParam param = new CalculateAverageHsParam();
            int toDealCount = 7 - board.Length;

            CardEnum.Combin(StdDeck.Descriptor, toDealCount, boardCs, CardSet.Empty, OnPocket, param);
            Assert.AreEqual(EnumAlgos.CountCombin(52 - board.Length, toDealCount), param.Count);
            return(param.Sum / param.Count);
        }
コード例 #8
0
        public void Omaha()
        {
            Reset();
            Console.WriteLine("Calculate number of chance nodes from 1 player perspective for Omaha");

            CardEnum.Combin(StdDeck.Descriptor, 4, CardSet.Empty, CardSet.Empty, SuitIsomorphismPreflopOmaha);
            Console.WriteLine("Preflop Chance Nodes: colored: {0}, color-isomorphic: {1} {2:0.##}%",
                              _pocketCount, _normPreflopCount, 100.0 * _normPreflopCount / _pocketCount);
            Assert.AreEqual(EnumAlgos.CountCombin(52, 4), _pocketCount);
            // Value verified in Wiki, etc.
            Assert.AreEqual(16432, _normPreflopCount);
        }
コード例 #9
0
ファイル: DealRecord.cs プロジェクト: ivan-alles/poker-acpc
        public DealRecord(GameRecord cfg, DeckDescriptor deckDescr, SequenceRng randomDealer)
        {
            _cfg          = cfg;
            _deckDescr    = deckDescr;
            _randomDealer = randomDealer;

            // Loop through actions and
            // - find the fixed cards
            // - count random cards
            // - count enumerated cards

            for (int a = 0; a < _cfg.Actions.Count; ++a)
            {
                PokerAction action = _cfg.Actions[a];
                if (!action.IsDealerAction())
                {
                    continue;
                }
                string[] cards = action.Cards.Split(_separator, StringSplitOptions.RemoveEmptyEntries);
                foreach (string card in cards)
                {
                    if (card == "?")
                    {
                        _randomCount++;
                    }
                    else if (card.Length > 0 && card.Substring(0, 1) == "#")
                    {
                        int idx = int.Parse(card.Substring(1));
                        while (_enumCounts.Count <= idx)
                        {
                            _enumCounts.Add(0);
                            _enumCombosCounts.Add(0);
                            _enumCombos.Add(new List <CardSet>());
                        }
                        _enumCounts[idx]++;
                    }
                    else
                    {
                        _fixedCards.UnionWith(_deckDescr.GetCardSet(card));
                    }
                }
            }

            // Count enumerated combinations.
            int deadCards = _fixedCards.CountCards();

            for (int i = 0; i < _enumCounts.Count; ++i)
            {
                _enumCombosCounts[i] = EnumAlgos.CountCombin(_deckDescr.Size - deadCards, _enumCounts[i]);
                deadCards           += _enumCounts[i];
            }
        }
コード例 #10
0
        public void Test_CountCombinations_CardSet()
        {
            for (int i = 0; i <= 6; ++i)
            {
                _combinationsCount = 0;
                CardEnum.Combin(StdDeck.Descriptor, i, CardSet.Empty, CardSet.Empty, CountCombinations);
                Assert.AreEqual(EnumAlgos.CountCombin(52, i), _combinationsCount);

                _combinationsCount1 = 0;
                CardEnum.Combin(StdDeck.Descriptor, i, CardSet.Empty, CardSet.Empty, CountCombinationsParam, _combinationsCount);
                Assert.AreEqual(EnumAlgos.CountCombin(52, i), _combinationsCount1);
            }
        }
コード例 #11
0
        public void GenerateStates(int maxHandSize)
        {
            DateTime startTime = DateTime.Now;

            _maxHandSize = maxHandSize;

            _cardsToState = new CardsToState[_maxHandSize][];
            for (int i = 0; i < _maxHandSize; ++i)
            {
                _cardsToState[i] = new CardsToState[EnumAlgos.CountCombin(52, i)];
            }

            for (int i = 0; i < _maxHandSize; ++i)
            {
                _combinCount = 0;
                GenerateCombin(CardSet.Empty, 51, 0, i, OnCombinCreateStates);
                Debug.Assert(_combinCount == _cardsToState[i].Length);
                Console.WriteLine("{0}-hands generated", i);
            }
            Console.WriteLine("{0:#,#} states created", _states.Count);

            if (_maxHandSize == 7)
            {
                // Print some statistics about 7-hands.
                int max6EquivStatesCount = -1;
                int nonUniqueKeyCount    = 0;
                foreach (List <State> l in _dict6.Values)
                {
                    max6EquivStatesCount = Math.Max(max6EquivStatesCount, l.Count);
                    if (l.Count > 1)
                    {
                        nonUniqueKeyCount++;
                    }
                }
                Console.WriteLine("Number of non-unique 6-hands keys: {0}", nonUniqueKeyCount);
                Console.WriteLine("Max. number of equivalent 6-hands with same key: {0}", max6EquivStatesCount);
            }

            for (int i = 0; i < _maxHandSize; ++i)
            {
                _combinCount = 0;
                GenerateCombin(CardSet.Empty, 51, 0, i, OnCombinLinkStates);
                Debug.Assert(_combinCount == _cardsToState[i].Length);
                Console.WriteLine("{0}-hands linked", i);
            }

            double runTime = (DateTime.Now - startTime).TotalSeconds;

            Console.WriteLine("Generated in {0:0.000} seconds", runTime);
        }
コード例 #12
0
ファイル: NormRank.cs プロジェクト: ivan-alles/poker-acpc
        /// <summary>
        /// Counts number of rank-equivalent hands that are comprised from the same cards
        /// ranks as the given hand, fully ignoring suits.
        /// For example, for AcKc or AsKh returns 16, for 2s2d returns 6.
        /// There must be no dead cards.
        /// </summary>
        /// <remarks>Works even if a deck contains different number of suits (&lt;=4) for different ranks.
        /// </remarks>
        public static int CountEquiv(CardSet hand, DeckDescriptor deck)
        {
            int count = 1;

            for (int r = 0; r < 16; ++r)
            {
                UInt64 handRanks      = hand.bits & _rankMasks[r];
                UInt64 allRanks       = deck.FullDeck.bits & _rankMasks[r];
                int    handRanksCount = CountBits.Count(handRanks);
                int    allRanksCount  = CountBits.Count(allRanks);
                int    rankCount      = (int)EnumAlgos.CountCombin(allRanksCount, handRanksCount);
                count *= rankCount;
            }
            return(count);
        }
コード例 #13
0
        public void Benchmark_Showdown()
        {
            HoldemGameRules gr = new HoldemGameRules();

            int [][] hands = new int[2][];
            UInt32[] ranks = new UInt32[2];
            for (int p = 0; p < 2; ++p)
            {
                hands[p] = new int[7];
            }
            hands[0][0] = 0;
            hands[0][1] = 1;
            hands[1][0] = 2;
            hands[1][1] = 3;
            // Force loading LUT
            UInt32   checksum  = LutEvaluator7.Evaluate(0, 1, 2, 3, 4, 5, 6);
            DateTime startTime = DateTime.Now;
            int      count     = 0;

            for (int b0 = 4; b0 < 52 - 4; ++b0)
            {
                hands[0][2] = hands[1][2] = b0;
                for (int b1 = b0 + 1; b1 < 52 - 3; ++b1)
                {
                    hands[0][3] = hands[1][3] = b1;
                    for (int b2 = b1 + 1; b2 < 52 - 2; ++b2)
                    {
                        hands[0][4] = hands[1][4] = b2;
                        for (int b3 = b2 + 1; b3 < 52 - 1; ++b3)
                        {
                            hands[0][5] = hands[1][5] = b3;
                            for (int b4 = b3 + 1; b4 < 52 - 0; ++b4)
                            {
                                hands[0][6] = hands[1][6] = b4;
                                gr.Showdown(_gd, hands, ranks);
                                checksum += ranks[0] + ranks[1];
                                count++;
                            }
                        }
                    }
                }
            }
            double runTime = (DateTime.Now - startTime).TotalSeconds;

            Assert.AreEqual(EnumAlgos.CountCombin(52 - 4, 5), count);
            Console.WriteLine("Showdown for 2 players, {0:#,#} hands, {1:#,#} h/s, time: {2:0.000} s, checksum: {3}",
                              count, count / runTime, runTime, checksum);
        }
コード例 #14
0
ファイル: HsSd.cs プロジェクト: ivan-alles/poker-acpc
        /// <summary>
        /// Precalculate and store tables. If the output already exists, will not overwrite.
        /// <remarks>Long-running. </remarks>
        /// </summary>
        /// <param name="round">Round (0, 1 or 2).</param>
        public static void Precalculate(int round)
        {
            DateTime startTime = DateTime.Now;

            string lutPath = GetLutPath(round);

            if (File.Exists(lutPath))
            {
                // Do not ovewriting an existing file to save time.
                Console.WriteLine("LUT file {0} already exist, exiting. Delete the file to recalculate.", lutPath);
                return;
            }

            int POCKETS_COUNT = (int)HePocketKind.__Count;
            //POCKETS_COUNT = 1; // Test

            PrecalculationContext context = new PrecalculationContext {
                Round = round
            };

            int[] listSize = new int[] { 169, 1361802, 15111642 };
            context.list = round < 2 ? (object)new List <Entry01>(listSize[round]) : (object)new List <Entry2>(listSize[round]);

            Console.WriteLine("Calculating for round {0}: ", round);

            int boardSize = HeHelper.RoundToHandSize[round] - 2;

            for (int p = 0; p < POCKETS_COUNT; ++p)
            {
                context.pocketKind = (HePocketKind)p;
                context.pocket     = HePocket.KindToCardSet((HePocketKind)p);
                context.pocketSei.Reset();
                context.pocketSei.Convert(context.pocket);
                Console.Write("{0} ", HePocket.KindToString((HePocketKind)p));
                CardEnum.Combin(StdDeck.Descriptor, boardSize, CardSet.Empty, context.pocket, OnPrecalculateBoard, context);
            }
            Console.WriteLine();
            Debug.Assert(EnumAlgos.CountCombin(50, boardSize) * POCKETS_COUNT == context.count);
            if (round < 2)
            {
                WriteTable((List <Entry01>)context.list, lutPath);
            }
            else
            {
                WriteTable((List <Entry2>)context.list, lutPath);
            }
            Console.WriteLine("LUT file {0} written, calculated in {1:0.0} s", lutPath, (DateTime.Now - startTime).TotalSeconds);
        }
コード例 #15
0
        public void Test_CalculateFast_Array()
        {
            HePocketKind[] pockets1 = new HePocketKind[] { HePocketKind._55, HePocketKind._66 };
            HePocketKind[] pockets2 = new HePocketKind[] { HePocketKind._76s, HePocketKind._76o };

            PocketEquity.Result r = PocketEquity.CalculateFast(pockets1, pockets2);
            Assert.AreEqual(0.56058, r.Equity, 0.000005);
            Assert.AreEqual(246571776L / EnumAlgos.CountCombin(48,5), r.Count);

            pockets1 = new HePocketKind[] { HePocketKind._AKs, HePocketKind._AQs };
            pockets2 = new HePocketKind[] { HePocketKind._88, HePocketKind._77 };

            r = PocketEquity.CalculateFast(pockets1, pockets2);
            Assert.AreEqual(0.47681, r.Equity, 0.000005);
            Assert.AreEqual(164381184L / EnumAlgos.CountCombin(48, 5), r.Count);
        }
コード例 #16
0
        public void Holdem()
        {
            Reset();
            Console.WriteLine("Calculate number of chance nodes from 1 player perspective for Holdem");

            CardEnum.Combin(StdDeck.Descriptor, 2, CardSet.Empty, CardSet.Empty, SuitIsomorphismPreflopHoldem);
            Console.WriteLine("Preflop Chance Nodes: colored: {0}, color-isomorphic: {1} {2:0.##}%",
                              _pocketCount, _normPreflopCount, 100.0 * _normPreflopCount / _pocketCount);
            int flopCount = (int)(EnumAlgos.CountCombin(52, 2) * EnumAlgos.CountCombin(50, 3));

            Console.WriteLine("Flop Chance Nodes: colored: {0}, color-isomorphic: {1} {2:0.##}%",
                              flopCount, _normFlopCount, 100.0 * _normFlopCount / flopCount);
            Assert.AreEqual(EnumAlgos.CountCombin(52, 2), _pocketCount);
            Assert.AreEqual(169, _normPreflopCount);
            // Value calculated by this test by many different implementations.
            Assert.AreEqual(1348620, _normFlopCount);
        }
コード例 #17
0
 public void Test_CalculateFast_VerifyAll()
 {
     double totalEquity = 0;
     uint totalCount = 0;
     int matchupsCount = 0;
     for (int pk1 = 0; pk1 < HePocket.Count; pk1++)
     {
         for (int pk2 = 0; pk2 < HePocket.Count; pk2++)
         {
             PocketEquity.Result r = PocketEquity.CalculateFast((HePocketKind)pk1, (HePocketKind)pk2);
             totalEquity += r.Equity;
             totalCount += r.Count;
             matchupsCount++;
         }
     }
     int expTotalCount = (int) (EnumAlgos.CountCombin(52, 2)*EnumAlgos.CountCombin(50, 2));
     Assert.AreEqual(totalCount, expTotalCount);
     Assert.AreEqual((double)169*169/2, totalEquity, 0.00001);
 }
コード例 #18
0
        public void Test_Flop()
        {
            HeHsDeviation dev = new HeHsDeviation();

            // Generate some unlucky flops.
            dev.ProcessHand(StdDeck.Descriptor.GetIndexes("7c 6c Ah 5s 5d"));
            dev.ProcessHand(StdDeck.Descriptor.GetIndexes("7c 6c Ad Kd Qd"));
            Assert.True(dev.AccDeviation[1] < 0);
            Assert.True(dev.AvDeviation[1] < 0);
            Assert.AreEqual(new int[] { 2, 2, 0, 0 }, dev.HandCount);
            dev.Reset();

            // Generate some lucky flops.
            dev.ProcessHand(StdDeck.Descriptor.GetIndexes("7c 6c Ac 5c 4c"));
            dev.ProcessHand(StdDeck.Descriptor.GetIndexes("7c 6c Ah Kc Qc"));
            Assert.True(dev.AccDeviation[1] > 0);
            Assert.True(dev.AvDeviation[1] > 0);
            Assert.AreEqual(new int[] { 2, 2, 0, 0 }, dev.HandCount);
            dev.Reset();

            // Deal all flops for a pocket and make sure the luck is zero.
            dev.Reset();
            int[] hand = new int[5];
            hand[0] = StdDeck.Descriptor.GetIndex("Ac");
            hand[1] = StdDeck.Descriptor.GetIndex("Ad");
            CardEnum.Combin(StdDeck.Descriptor, 3, hand, 2, hand, 2, OnCombinProcessHand, dev);
            Assert.AreEqual(0, dev.AccDeviation[1], 0.002);
            Assert.AreEqual(0, dev.AvDeviation[1], 1e-7);
            int hc = (int)EnumAlgos.CountCombin(50, 3);

            Assert.AreEqual(new int[] { hc, hc, 0, 0 }, dev.HandCount);

            // Deal all pockets and all flops, and make sure the luck is zero.
            // Check only average deviation, the accumulated one is too big because of low precision.
            dev.Reset();
            hand = new int[5];
            CardEnum.Combin(StdDeck.Descriptor, 2, hand, 0, null, 0, OnCombinFlop, dev);
            Assert.AreEqual(0, dev.AvDeviation[0], 0.0001);
            Assert.AreEqual(0, dev.AvDeviation[1], 0.0001);
            hc = (int)EnumAlgos.CountCombin(52, 2) * (int)EnumAlgos.CountCombin(50, 3);
            Assert.AreEqual(new int[] { hc, hc, 0, 0 }, dev.HandCount);
        }
コード例 #19
0
ファイル: HandStrength.cs プロジェクト: ivan-alles/poker-acpc
        static List <Entry> Precalculate(int boardSize)
        {
            int POCKETS_COUNT = (int)HePocketKind.__Count;
            //POCKETS_COUNT = 1; // Test

            PrecalculationContext context = new PrecalculationContext();

            int[] listSize = new int[] { 169, -1, -1, 1361802, 15111642 };
            context.list = new List <Entry>(listSize[boardSize]);

            for (int p = 0; p < POCKETS_COUNT; ++p)
            {
                context.pocketKind = (HePocketKind)p;
                context.pocket     = HePocket.KindToCardSet((HePocketKind)p);
                context.pocketSei.Reset();
                context.pocketSei.Convert(context.pocket);
                Console.WriteLine("Calculating for board size {0}, pocket {1}", boardSize, context.pocket);
                CardEnum.Combin(StdDeck.Descriptor, boardSize, CardSet.Empty, context.pocket, OnPrecalculateBoard, context);
            }

            Debug.Assert(EnumAlgos.CountCombin(50, boardSize) * POCKETS_COUNT == context.count);
            return(context.list);
        }
コード例 #20
0
ファイル: HandStrength.cs プロジェクト: ivan-alles/poker-acpc
        public static float Calculate(int[] hand, int handLength)
        {
            Debug.Assert(handLength >= 2 && handLength <= 7);
            int[] deckCopy = StdDeck.Descriptor.FullDeckIndexes.ShallowCopy();

            for (int i = 0; i < handLength; ++i)
            {
                deckCopy[hand[i]] = -1;
            }

            int[]  restDeck   = RemoveDeadCards(deckCopy, handLength);
            int    boardSize  = handLength - 2;
            UInt32 result     = 0;
            UInt32 boardStart = 0;

            for (int i = 0; i < boardSize; ++i)
            {
                boardStart = LutEvaluator7.pLut[boardStart + hand[2 + i]];
            }
            DealBoard(hand, restDeck, deckCopy, boardStart, 0, restDeck.Length + boardSize - 4, ref result);
            UInt32 count = (UInt32)EnumAlgos.CountCombin(52 - handLength, 5 - boardSize) * (UInt32)EnumAlgos.CountCombin(45, 2);

            return((float)result / count / 2);
        }