Esempio n. 1
0
        /// <summary>
        /// 1. Selects a starting suit
        /// 2. Converts a pattern of one suite 4 times, setting the pattern first to the starting suite,
        ///    then to next suit, etc.
        /// </summary>
        /// <param name="pattern"></param>
        private void TestConvertOneSuite(UInt32 pattern)
        {
            NormSuit sn = new NormSuit();

            for (int s1 = 0; s1 < 4; ++s1)
            {
                // Console.WriteLine("Starting suite {0}", s1);
                CardSet orig = new CardSet();
                orig.bits = (ulong)pattern << 16 * (s1 % 4);
                Assert.AreEqual(FromSuits(0, 0, 0, pattern), sn.Convert(orig));
                orig.bits = (ulong)pattern << 16 * ((s1 + 1) % 4);
                Assert.AreEqual(FromSuits(0, 0, pattern, 0), sn.Convert(orig));

                // Test copy constructor.
                NormSuit sn2 = new NormSuit(sn);

                orig.bits = (ulong)pattern << 16 * ((s1 + 2) % 4);
                Assert.AreEqual(FromSuits(0, pattern, 0, 0), sn2.Convert(orig));
                orig.bits = (ulong)pattern << 16 * ((s1 + 3) % 4);
                Assert.AreEqual(FromSuits(pattern, 0, 0, 0), sn2.Convert(orig));

                // Test both reset and recreate.
                if (s1 % 2 == 0)
                {
                    sn.Reset();
                }
                else
                {
                    sn = new NormSuit();
                }
            }
        }
Esempio n. 2
0
        static void OnPrecalculateBoard(ref CardSet board, PrecalculationContext d)
        {
            NormSuit sei      = new NormSuit(d.pocketSei);
            CardSet  seBoard  = sei.Convert(board);
            Entry    keyEntry = new Entry(d.pocketKind, seBoard);
            // Actually there is no BinarySearch necessary, because a key will be either present in the table
            // or go to the end (greater than the rest).
            // It's left here just to verify the algorithm.
            int idx = d.list.BinarySearch(keyEntry);

            if (idx < 0)
            {
                if (d.list.Count > 0 && d.list[d.list.Count - 1].key >= keyEntry.key)
                {
                    throw new ApplicationException(
                              "Algorithm error, new value must be greater than all existing values.");
                }
                List <int> pocketIdxs = StdDeck.Descriptor.GetIndexesAscending(d.pocket);
                List <int> boardIdxs  = StdDeck.Descriptor.GetIndexesAscending(seBoard);
                int[]      hand       = new int[pocketIdxs.Count + boardIdxs.Count];
                int        h          = 0;
                for (int i = 0; i < pocketIdxs.Count; ++i)
                {
                    hand[h++] = pocketIdxs[i];
                }
                for (int i = 0; i < boardIdxs.Count; ++i)
                {
                    hand[h++] = boardIdxs[i];
                }
                keyEntry.value = Calculate(hand);
                d.list.Add(keyEntry);
            }
            d.count++;
        }
Esempio n. 3
0
        // Create ranges for each pocket kind.
        // Also puts non-se pockets to _cardSetToKind
        private static void AddPocket(ref CardSet pocket, int [] rangePos)
        {
            NormSuit ns       = new NormSuit();
            CardSet  snPocket = ns.Convert(pocket);
            // The suit-normalized pocket is already added, we can use its kind.
            int kindIndex = (int)_cardSetToKind[snPocket];

            if (!_cardSetToKind.ContainsKey(pocket))
            {
                _cardSetToKind.Add(pocket, (HePocketKind)kindIndex);
            }
            _kindToRange[kindIndex][rangePos[kindIndex]] = pocket;
            rangePos[kindIndex]++;
        }
Esempio n. 4
0
        public void Benchmark_Convert()
        {
            int repetitions = 40000000;

            CardSet cs1 = FromSuits(0, 0x1, 0, 0);
            CardSet cs2 = FromSuits(0x1, 0, 0, 0);
            CardSet cs3 = FromSuits(0, 0, 0x1, 0);
            CardSet cs4 = FromSuits(0, 0, 0, 0x1);

            NormSuit sn = new NormSuit();

            DateTime startTime = DateTime.Now;

            for (int i = 0; i < repetitions; ++i)
            {
                CardSet result;
                result = sn.Convert(cs1);
                result = sn.Convert(cs2);
                result = sn.Convert(cs3);
                result = sn.Convert(cs4);
            }

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

            Console.WriteLine("Single card: conversions {0:###,###,###}, time {1} s, {2:###,###,###} conv/s",
                              repetitions * 4, time, repetitions * 4 / time);

            cs1 = FromSuits(0, 0xFFFF, 0, 0);
            cs2 = FromSuits(0xFFFF, 0, 0, 0);
            cs3 = FromSuits(0, 0, 0xFFFF, 0);
            cs4 = FromSuits(0, 0, 0, 0xFFFF);

            sn = new NormSuit();

            startTime = DateTime.Now;

            for (int i = 0; i < repetitions; ++i)
            {
                CardSet result;
                result = sn.Convert(cs1);
                result = sn.Convert(cs2);
                result = sn.Convert(cs3);
                result = sn.Convert(cs4);
            }

            time = (DateTime.Now - startTime).TotalSeconds;

            Console.WriteLine("Full suite: conversions {0:###,###,###}, time {1} s, {2:###,###,###} conv/s",
                              repetitions * 4, time, repetitions * 4 / time);
        }
Esempio n. 5
0
        public static float[] CalculateFast(int[] hand, int handLength, SdKind sdKind)
        {
            Debug.Assert(handLength >= 0 && handLength <= 7);
            if (handLength == 7)
            {
                // SdKind.SdPlus1 will throw an exception, this is exactly what we want.
                return(Calculate(hand, handLength, sdKind == SdKind.SdPlus1 ? 4 : 3));
            }

            if (_lut2 == null)
            {
                LoadLuts();
            }

            float[] hssd = new float[2];

            int      round    = HeHelper.HandSizeToRound[handLength];
            CardSet  pocket   = StdDeck.Descriptor.GetCardSet(hand, 0, 2);
            CardSet  board    = StdDeck.Descriptor.GetCardSet(hand, 2, handLength - 2);
            NormSuit se       = new NormSuit();
            CardSet  sePocket = se.Convert(pocket);
            CardSet  seBoard  = se.Convert(board);

            if (round == 2)
            {
                Entry2 keyEntry = new Entry2(HePocket.CardSetToKind(sePocket), seBoard);
                int    idx      = Array.BinarySearch(_lut2, keyEntry);
                if (idx < 0)
                {
                    ThrowNoEntryException(sePocket, seBoard);
                }
                hssd[0] = _lut2[idx].Hs;
                // For turn, there is no difference between SD kinds.
                hssd[1] = _lut2[idx].SdPlus1;
            }
            else
            {
                Entry01 keyEntry = new Entry01(HePocket.CardSetToKind(sePocket), seBoard);
                int     idx      = Array.BinarySearch(_lut01[round], keyEntry);
                if (idx < 0)
                {
                    ThrowNoEntryException(sePocket, seBoard);
                }
                // For turn, there is no difference between SD kinds.
                hssd[0] = _lut01[round][idx].Hs;
                hssd[1] = sdKind == SdKind.SdPlus1 ? _lut01[round][idx].SdPlus1 : _lut01[round][idx].Sd3;
            }
            return(hssd);
        }
Esempio n. 6
0
        public static float CalculateFast(CardSet board)
        {
            NormSuit ns          = new NormSuit();
            Entry    searchEntry = new Entry();

            searchEntry.CardSet = ns.Convert(board).bits;
            int round = HeHelper.HandSizeToRound[board.CountCards() + 2];

            Entry [] lut = _luts[round - 1];
            int      idx = Array.BinarySearch(lut, searchEntry);

            if (idx < 0)
            {
                throw new ApplicationException(string.Format("Cannot find LUT entry for board: '{0}'", StdDeck.Descriptor.GetCardNames(board)));
            }
            return(lut[idx].Ahvo);
        }
Esempio n. 7
0
        public void Benchmark_CardSetToKind()
        {
            CardSet[] pockets     = CardEnum.Combin(StdDeck.Descriptor, 2, CardSet.Empty, CardSet.Empty);
            int       repetitions = 100;
            DateTime  startTime   = DateTime.Now;

            int checksum = 0;

            for (int r = 0; r < repetitions; ++r)
            {
                for (int p = 0; p < pockets.Length; ++p)
                {
                    checksum += (int)HePocket.CardSetToKind(pockets[p]);
                }
            }

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

            Console.WriteLine("Cardset to kind: count: {0:#,#}, {1:#,#} r/s, checksum: {2}",
                              repetitions * pockets.Length, repetitions * pockets.Length / runTime, checksum);

            startTime = DateTime.Now;

            CardSet checksum1 = CardSet.Empty;

            NormSuit ns = new NormSuit();

            for (int r = 0; r < repetitions; ++r)
            {
                for (int p = 0; p < pockets.Length; ++p)
                {
                    checksum1 |= ns.Convert(pockets[p]);
                    ns.Reset();
                }
            }

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

            Console.WriteLine("To compare performance:");

            Console.WriteLine("Normalize suit : count: {0:#,#}, {1:#,#} r/s, checksum: {2}",
                              repetitions * pockets.Length, repetitions * pockets.Length / runTime, checksum1.bits);
        }
Esempio n. 8
0
        public void Benchmark_CopyFrom()
        {
            int repetitions = 40000000;

            NormSuit sn  = new NormSuit();
            NormSuit sn1 = new NormSuit();

            DateTime startTime = DateTime.Now;

            for (int i = 0; i < repetitions; ++i)
            {
                sn1.CopyFrom(sn);
            }

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

            Console.WriteLine("Repetitions {0:###.###.###}, time {1} s, {2:###,###,###,###} copy/s",
                              repetitions, time, repetitions / time);
        }
Esempio n. 9
0
 public void Test_CountSuits()
 {
     // Total 16 combinations
     Assert.AreEqual(0, NormSuit.CountSuits(FromSuits(0, 0, 0, 0)));
     Assert.AreEqual(1, NormSuit.CountSuits(FromSuits(0, 0, 0, 1)));
     Assert.AreEqual(1, NormSuit.CountSuits(FromSuits(0, 0, 1, 0)));
     Assert.AreEqual(1, NormSuit.CountSuits(FromSuits(0, 1, 0, 0)));
     Assert.AreEqual(1, NormSuit.CountSuits(FromSuits(1, 0, 0, 0)));
     Assert.AreEqual(2, NormSuit.CountSuits(FromSuits(0, 0, 1, 1)));
     Assert.AreEqual(2, NormSuit.CountSuits(FromSuits(0, 1, 0, 1)));
     Assert.AreEqual(2, NormSuit.CountSuits(FromSuits(1, 0, 0, 1)));
     Assert.AreEqual(2, NormSuit.CountSuits(FromSuits(0, 1, 1, 0)));
     Assert.AreEqual(2, NormSuit.CountSuits(FromSuits(1, 0, 1, 0)));
     Assert.AreEqual(2, NormSuit.CountSuits(FromSuits(1, 1, 0, 0)));
     Assert.AreEqual(3, NormSuit.CountSuits(FromSuits(0, 1, 1, 1)));
     Assert.AreEqual(3, NormSuit.CountSuits(FromSuits(1, 0, 1, 1)));
     Assert.AreEqual(3, NormSuit.CountSuits(FromSuits(1, 1, 0, 1)));
     Assert.AreEqual(3, NormSuit.CountSuits(FromSuits(1, 1, 1, 0)));
     Assert.AreEqual(4, NormSuit.CountSuits(FromSuits(1, 1, 1, 1)));
 }
Esempio n. 10
0
        public void Test_KindToRange_CardSetToKind_KindToSuiteNormalizedCardSet()
        {
            HashSet <CardSet> uniquePockets = new HashSet <CardSet>();

            for (int p = 0; p < (int)HePocketKind.__Count; ++p)
            {
                HePocketKind kind   = (HePocketKind)p;
                CardSet[]    range  = HePocket.KindToRange(kind);
                CardSet      ncsExp = HePocket.KindToCardSet(kind);
                foreach (CardSet cs in range)
                {
                    Assert.AreEqual(kind, HePocket.CardSetToKind(cs), "Each pocket from range must be of the expected kind.");
                    NormSuit ns  = new NormSuit();
                    CardSet  ncs = ns.Convert(cs);
                    Assert.AreEqual(ncsExp, ncs, "Card set from ranges must transform to same normalized card set");

                    // This will throw an exception if some pockets were duplicated.
                    uniquePockets.Add(cs);
                }
            }
            Assert.AreEqual(1326, uniquePockets.Count);
        }
Esempio n. 11
0
        public static Result CalculateNoVerify(CardSet[] csRange1, CardSet[] csRange2)
        {
            UInt64   totalValue = 0;
            uint     count      = 0;
            NormSuit ns         = new NormSuit();
            Dictionary <CardSet, UInt32> knonwValues = new Dictionary <CardSet, UInt32>();

            foreach (CardSet cs1 in csRange1)
            {
                foreach (CardSet cs2 in csRange2)
                {
                    if (cs1.IsIntersectingWith(cs2))
                    {
                        continue;
                    }
                    CardSet union = ns.Convert(cs1);
                    union.UnionWith(ns.Convert(cs2));
                    ns.Reset();
                    Debug.Assert(union.CountCards() == 4);
                    UInt32 knownValue;
                    if (!knonwValues.TryGetValue(union, out knownValue))
                    {
                        int[] h1 = StdDeck.Descriptor.GetIndexesAscending(cs1).ToArray();
                        int[] h2 = StdDeck.Descriptor.GetIndexesAscending(cs2).ToArray();
                        knownValue = CalculateMatchupValue(h1, h2);
                        knonwValues.Add(union, knownValue);
                    }
                    totalValue += knownValue;
                    count++;
                }
            }
            Result r = new Result();

            r.Equity = (float)totalValue / count / _boardsCount / 2;
            r.Count  = count;
            return(r);
        }
Esempio n. 12
0
        private static float CalculateFast(CardSet pocket, CardSet board, int handLength)
        {
            if (_luts[1] == null)
            {
                LoadPrecalculationTables();
            }

            int round = HeHelper.HandSizeToRound[handLength];

            Entry[] lookup = _luts[round];

            NormSuit se       = new NormSuit();
            CardSet  sePocket = se.Convert(pocket);
            CardSet  seBoard  = se.Convert(board);
            Entry    keyEntry = new Entry(HePocket.CardSetToKind(sePocket), seBoard);
            int      idx      = Array.BinarySearch <Entry>(lookup, keyEntry);

            if (idx < 0)
            {
                throw new ApplicationException(String.Format("No entry in lookup table for pocket {{{0}}} board {{{1}}}",
                                                             sePocket, seBoard));
            }
            return(lookup[idx].value);
        }
Esempio n. 13
0
        /// <summary>
        /// Generates all possible hands containing given suites,
        /// normalizes and verifies them.
        /// </summary>
        private void TestPermutations(uint s3, uint s2, uint s1, uint s0)
        {
            uint[] arr = new uint[] { s0, s1, s2, s3 };
            Array.Sort(arr);
            CardSet            expected = FromSuits(arr[0], arr[1], arr[2], arr[3]);
            List <List <int> > perms    = EnumAlgos.GetPermut(4);

            for (int i = 0; i < perms.Count; ++i)
            {
                // Console.WriteLine("Permutation: {0}", i);
                NormSuit sn        = new NormSuit();
                CardSet  orig      = FromSuits(arr[perms[i][0]], arr[perms[i][1]], arr[perms[i][2]], arr[perms[i][3]]);
                CardSet  converted = sn.Convert(orig);
                Assert.AreEqual(expected, converted);
                // Make sure result is consistent.
                converted = sn.Convert(orig);
                Assert.AreEqual(expected, converted);
                // Make sure self is converted to self with a new normalizers
                // (because it is already sorted).
                NormSuit sn2 = new NormSuit();
                converted = sn2.Convert(converted);
                Assert.AreEqual(expected, converted);
            }
        }
Esempio n. 14
0
        public void Test_Convert()
        {
            // Do generic testing with 1 suit in card set.
            TestConvertOneSuite(0xFFFF);
            TestConvertOneSuite(0x8001);

            // Do some more complex testing manually.
            NormSuit sn = new NormSuit();

            Assert.AreEqual(FromSuits(0, 0, 0x8001, 0x8001), sn.Convert(FromSuits(0x8001, 0, 0, 0x8001)));
            sn = new NormSuit();
            Assert.AreEqual(FromSuits(0, 0, 0x7001, 0xFFFF), sn.Convert(FromSuits(0, 0xFFFF, 0, 0x7001)));
            sn.Reset();
            Assert.AreEqual(FromSuits(0, 0, 0x8001, 0xFFFF), sn.Convert(FromSuits(0, 0xFFFF, 0, 0x8001)));
            sn.Reset();
            Assert.AreEqual(FromSuits(0, 0x8001, 0xF00F, 0xFFFF), sn.Convert(FromSuits(0xF00F, 0x8001, 0, 0xFFFF)));
            sn.Reset();
            Assert.AreEqual(FromSuits(0x8001, 0xDEAD, 0xF00F, 0xFFFF), sn.Convert(FromSuits(0xFFFF, 0xF00F, 0x8001, 0xDEAD)));

            // Make sure equal suites keep order for 2 suits
            for (int s1 = 0; s1 < 4; ++s1)
            {
                for (int s2 = s1 + 1; s2 < 4; ++s2)
                {
                    sn.Reset();
                    uint[] s = new uint[4];
                    s[s1] = 1;
                    s[s2] = 1;
                    // Convert once with equal suit ranks.
                    sn.Convert(FromSuits(s));
                    // Change ranks, make sure they are ordered as suite indexes.
                    s[s1] = 1;
                    s[s2] = 2;
                    Assert.AreEqual(FromSuits(0, 0, 2, 1), sn.Convert(FromSuits(s)));
                }
            }

            // Make sure equal suites keep order for 3 suits
            for (int s1 = 0; s1 < 4; ++s1)
            {
                for (int s2 = s1 + 1; s2 < 4; ++s2)
                {
                    for (int s3 = s2 + 1; s3 < 4; ++s3)
                    {
                        sn.Reset();
                        uint[] s = new uint[4];
                        s[s1] = 1;
                        s[s2] = 1;
                        s[s3] = 1;
                        // Convert once with equal suit ranks.
                        sn.Convert(FromSuits(s));
                        // Change ranks, make sure they are ordered as suite indexes.
                        s[s1] = 1;
                        s[s2] = 2;
                        s[s3] = 3;
                        Assert.AreEqual(FromSuits(0, 3, 2, 1), sn.Convert(FromSuits(s)));
                    }
                }
            }

            // Make sure equal suites keep order for 4 suits - only one combination is possible
            sn.Reset();
            sn.Convert(FromSuits(1, 1, 1, 1));
            Assert.AreEqual(FromSuits(4, 3, 2, 1), sn.Convert(FromSuits(4, 3, 2, 1)));


            // Test all permutations of some suits combinations.
            TestPermutations(0x1, 0x2, 0x3, 0x4);
            TestPermutations(0x8001, 0xFFFF, 0xF0F0, 0x0F0F);
            TestPermutations(0x0, 0x0, 0x0, 0x0);
            TestPermutations(0x0, 0x0, 0x0, 0x1);
            TestPermutations(0x0, 0x0, 0x1, 0x1);
            TestPermutations(0x0, 0x0, 0x2, 0x1);
            TestPermutations(0x0, 0x1, 0x1, 0x1);
            TestPermutations(0x0, 0x2, 0x1, 0x1);
            TestPermutations(0x0, 0x3, 0x2, 0x1);
            TestPermutations(0x1, 0x1, 0x1, 0x1);
            TestPermutations(0x2, 0x1, 0x1, 0x1);
            TestPermutations(0x2, 0x2, 0x1, 0x1);
            TestPermutations(0x3, 0x2, 0x1, 0x1);
        }
Esempio n. 15
0
        static void OnPrecalculateBoard(ref CardSet board, PrecalculationContext d)
        {
            NormSuit       sei     = new NormSuit(d.pocketSei);
            CardSet        seBoard = sei.Convert(board);
            List <Entry01> list01  = null;
            List <Entry2>  list2   = null;
            UInt32         key     = GetKey((int)d.pocketKind, seBoard);
            bool           addNew  = false;

            // A key will be either present in the table or go to the end (greater than the rest).
            // This is due to the order of dealt boards in CardEnum
            if (d.Round < 2)
            {
                list01 = (List <Entry01>)d.list;
                addNew = list01.Count == 0 || list01[list01.Count - 1].Key < key;
            }
            else
            {
                list2  = (List <Entry2>)d.list;
                addNew = list2.Count == 0 || list2[list2.Count - 1].Key < key;
            }

            if (addNew)
            {
                List <int> pocketIdxs = StdDeck.Descriptor.GetIndexesAscending(d.pocket);
                List <int> boardIdxs  = StdDeck.Descriptor.GetIndexesAscending(seBoard);
                int[]      hand       = new int[pocketIdxs.Count + boardIdxs.Count];
                int        h          = 0;
                for (int i = 0; i < pocketIdxs.Count; ++i)
                {
                    hand[h++] = pocketIdxs[i];
                }
                for (int i = 0; i < boardIdxs.Count; ++i)
                {
                    hand[h++] = boardIdxs[i];
                }
                float[] sdhs;
                if (d.Round < 2)
                {
                    Entry01 newEntry = new Entry01 {
                        Key = key
                    };
                    sdhs             = Calculate(hand, d.Round + 1);
                    newEntry.Hs      = sdhs[0];
                    newEntry.SdPlus1 = sdhs[1];
                    sdhs             = Calculate(hand, 3);
                    newEntry.Sd3     = sdhs[1];
                    list01.Add(newEntry);
                }
                else
                {
                    Entry2 newEntry = new Entry2 {
                        Key = key
                    };
                    sdhs             = Calculate(hand, d.Round + 1);
                    newEntry.Hs      = sdhs[0];
                    newEntry.SdPlus1 = sdhs[1];
                    list2.Add(newEntry);
                }
            }
            d.count++;
        }