Exemple #1
0
        public static (int, int) Chankan(ProgressiveScoringData data, WindScoringData wind, TileType winningTile)
        {
            var(yaku, fu) = data.YakuAndFu(wind, winningTile, true);
            var han = Han.CalculateScoringField(yaku);

            return(han, fu);
        }
Exemple #2
0
        private static ProgressiveScoringData CreateProgressiveScoringData(ProgressiveScoringData data, int[] groupKinds, int[] base5Hashes, int groupInterpretationIterator)
        {
            data.Reset();

            for (var i = 0; i < 4; i++)
            {
                var meldType = (groupInterpretationIterator >> (2 * i)) & 3;
                if (meldType == 0)
                {
                    continue;
                }

                var kind = groupKinds[i];

                if (kind < 34)
                {
                    var suitId = kind / 9;
                    var index  = kind % 9;
                    if (meldType == 1)
                    {
                        data.Pon(suitId, index);
                    }
                    else if (meldType == 2)
                    {
                        data.Ankan(suitId, index);
                    }
                    else
                    {
                        data.Daiminkan(suitId, index);
                    }
                }
                else
                {
                    var x      = kind - 34;
                    var suitId = x / 7;
                    var meldId = x % 7;
                    data.Chii(suitId, meldId);
                }
            }

            data.Init(base5Hashes);

            return(data);
        }
Exemple #3
0
        public void CompareWithEvaluatedHands()
        {
            const string workingDirectory   = "C:\\tenhou\\scoreDb";
            const int    numberOfGroupKinds = 34 + 21;
            const int    maxGroupsHash      = numberOfGroupKinds * numberOfGroupKinds * numberOfGroupKinds * numberOfGroupKinds;
            var          failureCount       = 0;

            var pairTileTypeIds = new[]
            {
                0, 1, 2,
                //3,  4,  5,  6,  7,  8,
                //18, 19, 20, 21, 22, 23, 24, 25, 26,
                //27, 31, 32
            };

            var        tileCounts  = new int[34];
            var        groupKinds  = new int[4];
            var        base5Hashes = new int[4];
            Span <int> base5Table  = stackalloc int[9];

            Base5.Table.CopyTo(base5Table);
            var scoringData = new ProgressiveScoringData();

            foreach (var pairTileTypeId in pairTileTypeIds)
            {
                var path = Path.Combine(workingDirectory, $"standard{pairTileTypeId}.dat");
                using var fileStream   = File.OpenRead(path);
                using var binaryReader = new BinaryReader(fileStream);

                var windConfigurations = SimpleWindConfiguration;
                if (pairTileTypeId >= 27 && pairTileTypeId < 31)
                {
                    windConfigurations = WindConfigurations[pairTileTypeId - 27];
                }

                for (var groupsHash = 0; groupsHash < maxGroupsHash; groupsHash++)
                {
                    Array.Clear(tileCounts, 0, tileCounts.Length);
                    tileCounts[pairTileTypeId] += 2;

                    var g = groupsHash;
                    groupKinds[0] = g % numberOfGroupKinds;
                    g            /= numberOfGroupKinds;
                    groupKinds[1] = g % numberOfGroupKinds;
                    g            /= numberOfGroupKinds;
                    groupKinds[2] = g % numberOfGroupKinds;
                    g            /= numberOfGroupKinds;
                    groupKinds[3] = g;

                    if (groupKinds[0] > groupKinds[1] || groupKinds[1] > groupKinds[2] || groupKinds[2] > groupKinds[3])
                    {
                        continue;
                    }

                    AddGroup(tileCounts, groupKinds[0]);
                    AddGroup(tileCounts, groupKinds[1]);
                    AddGroup(tileCounts, groupKinds[2]);
                    AddGroup(tileCounts, groupKinds[3]);

                    if (InvalidTileCounts(tileCounts))
                    {
                        continue;
                    }

                    var invalidKanFlags = InvalidKanFlags(groupKinds, tileCounts);

                    for (var groupInterpretationIterator = 0; groupInterpretationIterator < 256; groupInterpretationIterator++)
                    {
                        if ((groupInterpretationIterator & invalidKanFlags) != 0)
                        {
                            continue;
                        }

                        var tilePresences = 1L << pairTileTypeId;
                        base5Hashes[0] = 0;
                        base5Hashes[1] = 0;
                        base5Hashes[2] = 0;
                        base5Hashes[3] = 0;
                        base5Hashes[pairTileTypeId / 9] += base5Table[pairTileTypeId % 9] * 2;

                        for (var i = 0; i < 4; i++)
                        {
                            if (((groupInterpretationIterator >> (2 * i)) & 3) != 0)
                            {
                                continue;
                            }

                            var kind = groupKinds[i];
                            if (kind < 34)
                            {
                                base5Hashes[kind / 9] += base5Table[kind % 9] * 3;

                                tilePresences |= 1L << kind;
                            }
                            else
                            {
                                var x     = kind - 34;
                                var suit  = x / 7;
                                var index = x % 7;
                                base5Hashes[suit] += base5Table[index] * 31;

                                tilePresences |= 0b111L << (9 * suit + index);
                            }
                        }

                        var data = CreateProgressiveScoringData(scoringData, groupKinds, base5Hashes, groupInterpretationIterator);

                        for (var i = 0; i < 34; i++)
                        {
                            if ((tilePresences >> i & 1L) == 0)
                            {
                                continue;
                            }

                            var winningTile = TileType.FromTileTypeId(i);

                            for (var index = 0; index < windConfigurations.Length; index++)
                            {
                                var wind = windConfigurations[index];
                                var(tsumoHan, tsumoFu) = ScoreCalculator.Tsumo(data, wind, winningTile);

                                var expectedTsumoHan = binaryReader.ReadByte();
                                if (expectedTsumoHan != tsumoHan)
                                {
                                    failureCount += 1;
                                }

                                if (expectedTsumoHan < 5)
                                {
                                    int expectedTsumoFu = binaryReader.ReadByte();
                                    if (expectedTsumoFu != tsumoFu)
                                    {
                                        failureCount += 1;
                                    }
                                }

                                var(ronHan, ronFu) = ScoreCalculator.Ron(data, wind, winningTile);

                                var expectedRonHan = binaryReader.ReadByte();
                                if (expectedRonHan != ronHan)
                                {
                                    failureCount += 1;
                                }

                                if (expectedTsumoHan < 5)
                                {
                                    int expectedRonFu = binaryReader.ReadByte();
                                    if (expectedRonFu != ronFu)
                                    {
                                        failureCount += 1;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            Assert.Equal(0, failureCount);
        }
Exemple #4
0
 public static (Yaku, int) TsumoWithYaku(ProgressiveScoringData data, WindScoringData wind, TileType winningTile)
 {
     var(yaku, fu) = data.YakuAndFu(wind, winningTile, false);
     return((Yaku)yaku, fu);
 }