예제 #1
0
        static HandCalculatorTests()
        {
            var loadStatics = new HandCalculator();

            loadStatics.Init(Enumerable.Range(0, 13).Select(TileType.FromTileTypeId));
            Console.WriteLine(loadStatics.Shanten);
        }
예제 #2
0
파일: Program.cs 프로젝트: tkitada/mahjong
        private static void Main(string[] args)
        {
            random_ = new Random();
            var wall  = new List <int>(Enumerable.Range(0, 136));
            var count = wall.Count;

            for (var i = 0; i < count; i++)
            {
                var r = random_.Next(i, count);
                (wall[i], wall[r]) = (wall[r], wall[i]);
            }
            var hand     = new TileIds(wall.GetRange(0, 13));
            var discards = new List <int>();

            wall.RemoveRange(0, 13);

            for (var c = wall.Count; c > 0; c--)
            {
                hand.Add(wall[0]);
                wall.RemoveAt(0);

                PrintTiles(hand);

                var res = HandCalculator.EstimateHandValue(hand, hand.Last() /*, config:new HandConfig(isTsumo:true)*/);
                if (res.Error is null)
                {
                    Console.WriteLine("");
                    PrintHandResult(hand, hand.Last(), null, res);
                    break;
                }
                discards.Add(DecideDahai(hand));

                PrintTiles(hand);
            }
        }
예제 #3
0
        public void Tsumo(HandConfig config)
        {
            var tsumo = wall_.Tsumo();

            if (tsumo is null)
            {
                return;
            }

            Hand.Tsumo(tsumo);
            var result = HandCalculator.EstimateHandValue(Hand.AllTiles,
                                                          Hand.TsumoTile,
                                                          doraIndicators: DoraIndicators,
                                                          config: config);

            if (result.Error is null)
            {
                IsAgari = true;
                Result  = result;
            }
            else
            {
                IsAgari = false;
                Result  = null;
            }
        }
예제 #4
0
        public void JustSomeHands(string hand, int expected)
        {
            var parser = new ShorthandParser(hand);
            var c      = new HandCalculator(parser);

            var actual = c.Shanten;

            Assert.Equal(expected, actual);
        }
예제 #5
0
        public void JustSomeHands(string hand, int[] expected)
        {
            var parser = new ShorthandParser(hand);
            var c      = new HandCalculator(parser);

            var actual = c.GetUkeIreFor13();

            Assert.Equal(expected, actual);
        }
예제 #6
0
        public void CompareHandsTest(List <string> hand1, List <string> hand2)
        {
            var cardValues    = new CardValues();
            var handData      = new HandCalculator(cardValues, new HandValues(cardValues));
            var hand1WithData = handData.Calculate(hand1);
            var hand2WithData = handData.Calculate(hand2);

            Assert.True(hand1WithData.Value > hand2WithData.Value);
        }
예제 #7
0
        public void SomeHandByTsumo(string handString, int roundWind, int seatWind, string discardString, Yaku expectedYaku)
        {
            var discard = TileType.FromString(discardString);
            var sp      = new ShorthandParser(handString);
            var hand    = new HandCalculator(sp);
            var wind    = new WindScoringData(roundWind, seatWind);

            var(yaku, fu) = ScoreCalculator.TsumoWithYaku(hand.ScoringData, wind, discard);

            Assert.Equal(expectedYaku, yaku);
        }
예제 #8
0
        public void TotalFuTsumo(string handString, int roundWind, int seatWind, string drawString, int expectedFu)
        {
            var draw = TileType.FromString(drawString);
            var sp   = new ShorthandParser(handString);
            var hand = new HandCalculator(sp);
            var wind = new WindScoringData(roundWind, seatWind);

            var(han, fu) = ScoreCalculator.Tsumo(hand.ScoringData, wind, draw);

            Assert.Equal(expectedFu, fu);
        }
예제 #9
0
        public void BlockingDaiminkan()
        {
            var parser = new ShorthandParser("12223m11222333z");
            var c      = new HandCalculator(parser);
            var m2     = TileType.FromSuitAndIndex(Suit.Manzu, 1);

            c.Daiminkan(m2);

            var actual = c.Shanten;

            Assert.Equal(1, actual);
        }
예제 #10
0
        public static void Main()
        {
            HandCalculator handHandCalculator = new HandCalculator();

            int sum        = handHandCalculator.Add(1, 2);
            int difference = handHandCalculator.Subtract(5, 4);
            int product    = handHandCalculator.Multiply(5, 4);
            int quotient   = handHandCalculator.Divide(10, 2);

            Console.WriteLine("Done");
            Console.ReadKey();
        }
예제 #11
0
        public void AdditionTest()
        {
            // Arrange
            HandCalculator handCalculator = new HandCalculator();
            const int      expectedResult = 6;

            // Act
            int result = handCalculator.Add(2, 4);

            // Assert
            Assert.AreEqual(expectedResult, result);
            Assert.That(result, Is.EqualTo(expectedResult));
        }
예제 #12
0
        public void ChiitoiDiscard()
        {
            var parser = new ShorthandParser("114477m114477p11s");
            var c      = new HandCalculator(parser);

            c.Discard(TileType.FromSuitAndIndex(Suit.Manzu, 0));
            c.Draw(TileType.FromSuitAndIndex(Suit.Jihai, 6));
            c.Discard(TileType.FromSuitAndIndex(Suit.Manzu, 3));

            var actual = c.Shanten;

            Assert.Equal(1, actual);
        }
예제 #13
0
        public void StoresTheBestHand()
        {
            var deck   = Card.Deck.ToList();
            var player = new Player {
                Hand = "2H 3D 9C KD 5S", Name = "Alice"
            };
            var calculator      = new HandCalculator();
            var outcomeDeck     = Card.Deck.ToList();
            var playedCards     = Card.ConvertToHandOfCards(player.Hand, ref outcomeDeck).ToList();
            var expectedOutcome = calculator.BestHand(playedCards);

            var playerHand = new PlayerHand(player, ref deck);

            playerHand.Best.Should().BeEquivalentTo(expectedOutcome);
        }
예제 #14
0
        public void BlockingPon()
        {
            var parser = new ShorthandParser("1223m112223z123M");
            var c      = new HandCalculator(parser);
            var m2     = TileType.FromSuitAndIndex(Suit.Manzu, 1);

            c.Pon(m2);
            var shaa = TileType.FromSuitAndIndex(Suit.Jihai, 2);

            c.Discard(shaa);

            var actual = c.Shanten;

            Assert.Equal(1, actual);
        }
예제 #15
0
        public void BlockingShouminkan()
        {
            var parser = new ShorthandParser("1223m112223337z");
            var c      = new HandCalculator(parser);
            var m2     = TileType.FromSuitAndIndex(Suit.Manzu, 1);
            var z7     = TileType.FromSuitAndIndex(Suit.Jihai, 6);

            c.Pon(m2);
            c.Discard(z7);
            c.Draw(m2);
            c.Shouminkan(m2);

            var actual = c.Shanten;

            Assert.Equal(1, actual);
        }
예제 #16
0
        public ViewModel()
        {
            appService_ = new PlayerApplicationService("yamada");

            appService_.RequestJoin();

            appService_.JoinEvent += (_, e) =>
            {
                System.Console.WriteLine($"id: {e.JoinRes.Id}");
                appService_.RequestHand();
            };
            appService_.HandEvent += (_, e) =>
            {
                Hand = e.HandRes.Hand;
                System.Console.WriteLine($"hand: {Hand.ToOneLineString()}");
                appService_.RequestTsumo();
            };
            appService_.TsumoEvent += (_, e) =>
            {
                var tsumo = e.TsumoRes.Tsumo;
                System.Console.WriteLine($"tsumo: {tsumo.ToOneLineString()}");
                Hand.Add(tsumo);
                System.Console.WriteLine($"shanten: {Shanten.CalculateShanten(Hand)}");
                var result = HandCalculator.EstimateHandValue(Hand, tsumo, config: new HandConfig(isTsumo: true));
                if (result.Error is null)
                {
                    appService_.RequestAgari();
                    return;
                }
                var index = DecideDahai();
                Hand.RemoveAt(index);
                appService_.RequestDahai(index);
            };
            appService_.DahaiEvent += (_, e) => appService_.RequestTsumo();
            appService_.AgariEvent += (_, e) =>
            {
                var res = e.AgariRes;
                PrintHandResult(res.Tiles, res.WinTile, res.Melds, res.Result);
            };
        }
예제 #17
0
        public static bool IsTenpai(IHandAnalysis hand, IReadOnlyList <Tile> concealedTiles, int meldCount)
        {
            if (hand.Shanten <= 0)
            {
                return(true);
            }

            if (meldCount == 0)
            {
                return(false);
            }

            var usedTileTypeIds = new bool[34];
            var initialTiles    = new Stack <TileType>();

            foreach (var tile in concealedTiles)
            {
                usedTileTypeIds[tile.TileType.TileTypeId] = true;
                initialTiles.Push(tile.TileType);
            }

            TileType?draw = null;

            if (initialTiles.Count % 3 == 2)
            {
                draw = initialTiles.Pop();
            }

            var remainingMelds = meldCount;
            var toPon          = new List <TileType>();

            for (var i = 27; i < 34 && remainingMelds > 0; i++)
            {
                if (usedTileTypeIds[i])
                {
                    continue;
                }

                remainingMelds -= 1;
                var tileType = TileType.FromTileTypeId(i);
                initialTiles.Push(tileType);
                initialTiles.Push(tileType);
                initialTiles.Push(tileType);
                toPon.Add(tileType);
            }

            if (remainingMelds > 0)
            {
                return(false);
            }

            var tempHand = new HandCalculator();

            tempHand.Init(initialTiles);
            foreach (var tileType in toPon)
            {
                tempHand.Pon(tileType);
                tempHand.Discard(tileType);
            }

            if (draw != null)
            {
                tempHand.Draw(draw);
            }

            return(tempHand.Shanten <= 0);
        }
 public void SetUp()
 {
     var converter = new Converter();
     scorer = new HandCalculator(converter);
 }
예제 #19
0
        public void CanCalculateCorrectValueOfHand(List <Card> hand, int expected)
        {
            var actual = HandCalculator.Calculate(hand);

            Assert.Equal(expected, actual);
        }
예제 #20
0
        private async Task computeHandWithAgari(CommandContext ctx, string hand, string agari)
        {
            var    basicHand  = HandParser.GetSimpleHand(hand);
            var    basicAgari = HandParser.GetSimpleHand(agari);
            var    handEmoji  = HandParser.GetHandEmojiCodes(hand, ctx.Client);
            string suitOrder  = U.getSuitOrder(basicHand);

            var hand136  = C.one_line_string_to_136_array(basicHand);
            var agari136 = C.one_line_string_to_136_array(basicAgari)[0];

            StringBuilder sb = new();

            sb.AppendLine($"<@!{ctx.User.Id}>: {GetHandMessage(handEmoji)}\n");
            var config = new HandConfig();

            // TSUMO

            config.is_tsumo = true;
            var calculator   = new HandCalculator();
            var result       = calculator.estimate_hand_value(hand136.ToList(), agari136, config: config);
            var handShape136 = C.from_34_indices_to_136_arrays(result.hand);
            var setsStr      = handShape136.Select(set => C.to_one_line_string(set));
            IEnumerable <string> orderedSetStr = new List <string>();

            foreach (var chr in suitOrder)
            {
                orderedSetStr = orderedSetStr.Concat(setsStr.Where(x => x.Contains(chr)));
            }
            sb.AppendLine($"Tsumo:{string.Join(",", orderedSetStr.Select(x => $"{GetHandMessage(HandParser.GetHandEmojiCodes(x, ctx.Client))}"))}");

            sb.AppendLine($"{result.han}han {result.fu}fu");
            foreach (var yaku in result.yaku)
            {
                sb.AppendLine($"{yaku}");
            }
            if (result.cost != null)
            {
                foreach (var yaku in result.cost.Keys)
                {
                    sb.AppendLine($"{yaku}: {result.cost[yaku]}");
                }

                foreach (var detail in result.fu_details)
                {
                    sb.AppendLine($"{detail.Item2}: +{detail.Item1}fu");
                }
            }

            //RON

            config.is_tsumo = false;
            calculator      = new HandCalculator();
            result          = calculator.estimate_hand_value(hand136.ToList(), agari136, config: config);
            handShape136    = C.from_34_indices_to_136_arrays(result.hand);
            setsStr         = handShape136.Select(set => C.to_one_line_string(set));
            orderedSetStr   = new List <string>();
            foreach (var chr in suitOrder)
            {
                orderedSetStr = orderedSetStr.Concat(setsStr.Where(x => x.Contains(chr)));
            }
            sb.AppendLine();
            sb.AppendLine($"Ron:{string.Join(",", orderedSetStr.Select(x => $"{GetHandMessage(HandParser.GetHandEmojiCodes(x, ctx.Client))}"))}");

            sb.AppendLine($"{result.han}han {result.fu}fu");
            foreach (var yaku in result.yaku)
            {
                sb.AppendLine($"{yaku}");
            }

            if (result.cost != null)
            {
                foreach (var cost in result.cost.Keys)
                {
                    sb.AppendLine($"{cost}: {result.cost[cost]}");
                }
            }

            foreach (var detail in result.fu_details)
            {
                sb.AppendLine($"{detail.Item2}: +{detail.Item1}fu");
            }
            var message = await ctx.Channel.SendMessageAsync(sb.ToString());
        }
 public HandCalculatorTests()
 {
     _calculator = new HandCalculator();
 }
        public void SetUp()
        {
            var converter = new Converter();

            scorer = new HandCalculator(converter);
        }
예제 #23
0
파일: Example.cs 프로젝트: tkitada/mahjong
        private static void Main(string[] args)
        {
            /***********************************************************************/
            /* タンヤオ ロン                                                       */
            /***********************************************************************/
            var tiles   = TileIds.Parse(man: "22444", pin: "333567", sou: "444");
            var winTile = TileId.Parse(sou: "4");
            var result  = HandCalculator.EstimateHandValue(tiles, winTile);

            PrintHandResult(tiles, winTile, null, result);

            /***********************************************************************/
            /* タンヤオ ツモ                                                       */
            /***********************************************************************/
            result = HandCalculator.EstimateHandValue(tiles, winTile, config: new HandConfig(isTsumo: true));
            PrintHandResult(tiles, winTile, null, result);

            /***********************************************************************/
            /* 副露追加                                                             */
            /***********************************************************************/
            var melds = new List <Meld>
            {
                new Meld(MeldType.PON, tiles: TileIds.Parse(man: "444"))
            };
            var config = new HandConfig(options: new OptionalRules(hasOpenTanyao: true));

            result = HandCalculator.EstimateHandValue(tiles, winTile, melds, config: config);
            PrintHandResult(tiles, winTile, melds, result);

            /***********************************************************************/
            /* シャンテン数計算                                                             */
            /***********************************************************************/
            tiles = TileIds.Parse(man: "13569", pin: "123459", sou: "443");
            var shanten = Shanten.CalculateShanten(tiles);

            Console.WriteLine(tiles.ToOneLineString());
            Console.WriteLine($"{shanten}シャンテン");
            Console.WriteLine("");

            /***********************************************************************/
            /* 数え役満                                                             */
            /***********************************************************************/
            //13翻打ち止め
            tiles   = TileIds.Parse(man: "22244466677788");
            winTile = TileId.Parse(man: "7");
            melds   = new List <Meld>
            {
                new Meld(MeldType.KAN, TileIds.Parse(man: "2222"), opened: false)
            };
            var doraIndicators = TileIds.Parse(man: "1111"); //ドラ表示牌

            config = new HandConfig(isRiichi: true, options: new OptionalRules(kazoeLimit: Kazoe.Limited));
            result = HandCalculator.EstimateHandValue(tiles, winTile, melds, doraIndicators, config);
            PrintHandResult(tiles, winTile, melds, result);

            //三倍満扱い
            config = new HandConfig(isRiichi: true, options: new OptionalRules(kazoeLimit: Kazoe.Sanbaiman));
            result = HandCalculator.EstimateHandValue(tiles, winTile, melds, doraIndicators, config);
            PrintHandResult(tiles, winTile, melds, result);

            //13翻ごとに役満を重ねる(26翻でダブル役満)
            config = new HandConfig(isRiichi: true, options: new OptionalRules(kazoeLimit: Kazoe.Nolimit));
            result = HandCalculator.EstimateHandValue(tiles, winTile, melds, doraIndicators, config);
            PrintHandResult(tiles, winTile, melds, result);
        }