Example #1
0
        /// <summary>
        /// 各TileKindsが取りうる順列を列挙します。
        /// </summary>
        /// <param name="source"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static IList <TileKinds> Permutations(this TileKinds source, int count)
        {
            var result = new List <TileKinds>();

            PermutationsInnner(source, count, new TileKinds(), result);
            return(result);
        }
Example #2
0
	public void Init(float length, int x, int y, TileKinds initialTileKind, GameObject parentGO) {
		column = x;
		row = y;
		tileKind = initialTileKind;

		this.gameObject.transform.SetParent(parentGO.transform);
		this.SetSize(length);
		Vector2 screenScale = this.GetComponent<RectTransform>().localScale;

		this.gameObject.transform.localPosition = new Vector3(x+0.5f, -y-0.5f, 1f) * length * screenScale.x;
		this.SetTileKind();
	}
Example #3
0
        public override bool IsConditionMet(IList <TileKinds> hand, object[] args = null)
        {
            var chiSets = hand.Where(x => x.IsChi);

            if (chiSets.Count() < 3)
            {
                return(false);
            }

            var manChi = new List <TileKinds>();
            var pinChi = new List <TileKinds>();
            var souChi = new List <TileKinds>();

            foreach (var item in chiSets)
            {
                if (item[0].IsMan)
                {
                    manChi.Add(item);
                }
                if (item[0].IsPin)
                {
                    pinChi.Add(item);
                }
                if (item[0].IsSou)
                {
                    souChi.Add(item);
                }
            }
            foreach (var manItem in manChi)
            {
                foreach (var pinItem in pinChi)
                {
                    foreach (var souItem in souChi)
                    {
                        var manNum = new TileKinds(manItem.Select(x => x.Simplify));
                        var pinNum = new TileKinds(pinItem.Select(x => x.Simplify));
                        var souNum = new TileKinds(souItem.Select(x => x.Simplify));
                        if (manNum.Equals(pinNum) && pinNum.Equals(souNum))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
Example #4
0
 private static void PermutationsInnner(TileKinds stock, int depth, TileKinds current, IList <TileKinds> result)
 {
     if (depth == 0)
     {
         result.Add(current);
         return;
     }
     for (var i = 0; i < stock.Count(); i++)
     {
         var copyOfStock   = new TileKinds(stock);
         var copyOfCurrent = new TileKinds(current)
         {
             copyOfStock[i]
         };
         copyOfStock.RemoveAt(i);
         PermutationsInnner(copyOfStock, depth - 1, copyOfCurrent, result);
     }
 }
Example #5
0
        private static TileKinds FindPairs(Tiles34 tiles34,
                                           int firstIndex  = 0,
                                           int secondIndex = 33)
        {
            var pairIndices = new TileKinds();

            for (var x = firstIndex; x <= secondIndex; x++)
            {
                //字牌の刻子は無視する(途中で分断して対子にはできない)
                if (HONOR_INDICES.Contains(x) && tiles34[x] != 2)
                {
                    continue;
                }

                if (tiles34[x] >= 2)
                {
                    pairIndices.Add(new TileKind(x));
                }
            }
            return(pairIndices);
        }
Example #6
0
        private static IEnumerable <IEnumerable <TileKinds> > FindValidCombinations(Tiles34 tiles34,
                                                                                    int firstIndex,
                                                                                    int secondIndex,
                                                                                    bool handNotCompleted = false)
        {
            //Tiles34[0,1,1,1,2,...]=>TileKinds[1,2,3,4,4,...]
            var indices = new TileKinds();

            for (var x = firstIndex; x <= secondIndex; x++)
            {
                if (tiles34[x] > 0)
                {
                    var l = indices.ToList();
                    l.AddRange(Enumerable.Repeat(new TileKind(x), tiles34[x]));
                    indices = new TileKinds(l);
                }
            }
            if (indices.Count == 0)
            {
                return(new List <IEnumerable <TileKinds> >());
            }

            //TileKindsのnP3全順列を列挙
            //[1,2,3,4,4]=>[[1,2,3],[1,2,4],[1,3,2],[1,3,4],[1,4,2],[1,4,3],[1,4,4],...]
            var t = indices.Permutations(3);
            var allPossibleCombinations = t.Select(x => new TileKinds(x));

            //刻子、順子の形をしている順列を抜きだす
            var validCombinations = new List <TileKinds>();

            foreach (var combination in allPossibleCombinations)
            {
                if (combination.IsChi || combination.IsPon)
                {
                    validCombinations.Add(combination);
                }
            }
            if (validCombinations.Count == 0)
            {
                return(new List <IEnumerable <TileKinds> >());
            }

            var countOfNeededCombinations = indices.Count / 3;

            //有り得る順列のセットが一通りしかないとき
            if (countOfNeededCombinations == validCombinations.Count &&
                indices.Equals(validCombinations.Aggregate(
                                   (x, y) => new TileKinds(Enumerable.Concat(x, y)))))
            {
                return new List <IEnumerable <TileKinds> > {
                           validCombinations
                }
            }
            ;

            var validCombinationsCopy = new List <TileKinds>(validCombinations);

            foreach (var item in validCombinations)
            {
                if (!item.IsPon)
                {
                    continue;
                }
                var countOfSets = 1;

                var countOfTiles = 0;
                while (countOfSets > countOfTiles)
                {
                    countOfTiles = indices.Count(x => item[0].Equals(x)) / 3;
                    countOfSets  = validCombinationsCopy.Count(x => item[0].Equals(x[0]) &&
                                                               item[1].Equals(x[1]) &&
                                                               item[2].Equals(x[2]));
                    if (countOfSets > countOfTiles)
                    {
                        validCombinationsCopy.Remove(item);
                    }
                }
            }
            validCombinations     = validCombinationsCopy;
            validCombinationsCopy = new List <TileKinds>(validCombinations);
            foreach (var item in validCombinations)
            {
                if (!item.IsChi)
                {
                    continue;
                }
                var countOfSets         = 5;
                var countOfPossibleSets = 4;
                while (countOfSets > countOfPossibleSets)
                {
                    countOfSets = validCombinationsCopy.Count(x => item[0].Equals(x[0]) &&
                                                              item[1].Equals(x[1]) &&
                                                              item[2].Equals(x[2]));
                    if (countOfSets > countOfPossibleSets)
                    {
                        validCombinationsCopy.Remove(item);
                    }
                }
            }
            validCombinations = validCombinationsCopy;

            if (handNotCompleted)
            {
                return new List <IEnumerable <TileKinds> >()
                       {
                           validCombinations
                       }
            }
            ;

            var possibleCombinations =
                new TileKinds(Enumerable.Range(0, validCombinations.Count))
                .Permutations(countOfNeededCombinations);

            var combinationsResults = new List <IEnumerable <TileKinds> >();

            foreach (var combination in possibleCombinations)
            {
                var result = new List <TileKind>();

                foreach (var item in combination)
                {
                    result.AddRange(validCombinations[item.Value]);
                }
                result.Sort((x, y) => x.CompareTo(y));

                if (!indices.Equals(new TileKinds(result)))
                {
                    continue;
                }

                var results = new List <TileKinds>();
                foreach (var item in combination)
                {
                    results.Add(validCombinations[item.Value]);
                }
                results.Sort((x, y) => x[0].CompareTo(y[0]));
                if (!combinationsResults.Contains_(results))
                {
                    combinationsResults.Add(results);
                }
            }
            return(combinationsResults);
        }
Example #7
0
        public static (List <FuDetail>, int) CalculateFu(IList <TileKinds> hand,
                                                         TileId winTile,
                                                         TileKinds winGroup,
                                                         HandConfig config,
                                                         IList <int> valuedTiles = null,
                                                         IList <Meld> melds      = null)
        {
            var winTileKind = winTile.ToTileKind();

            if (valuedTiles is null)
            {
                valuedTiles = new List <int>();
            }
            if (melds is null)
            {
                melds = new List <Meld>();
            }
            var fuDetails = new List <FuDetail>();

            if (hand.Count == 7)
            {
                fuDetails = new List <FuDetail>
                {
                    new FuDetail(25, BASE)
                };
                return(fuDetails, 25);
            }
            var pair = hand.Where(x => x.IsPair)
                       .ToList()[0];
            var ponSets = hand.Where(x => x.IsPon);

            var copiedOpenedMelds = melds.Where(x => x.Type == MeldType.CHI)
                                    .Select(x => x.TileKinds)
                                    .ToList();
            var closedChiSets = new List <TileKinds>();

            foreach (var x in hand)
            {
                if (!copiedOpenedMelds.Contains(x))
                {
                    closedChiSets.Add(x);
                }
                else
                {
                    copiedOpenedMelds.Remove(x);
                }
            }
            var IsOpenHand = melds.Any(x => x.Opened);

            if (closedChiSets.Contains(winGroup))
            {
                var tileIndex = winTileKind.Simplify;
                //ペンチャン
                if (winGroup.ContainsTerminal())
                {
                    //ペン12
                    if (tileIndex == 2 && winGroup.IndexOf(winTileKind) == 2)
                    {
                        fuDetails.Add(new FuDetail(2, PENCHAN));
                    }
                    //ペン89
                    else if (tileIndex == 6 && winGroup.IndexOf(winTileKind) == 0)
                    {
                        fuDetails.Add(new FuDetail(2, PENCHAN));
                    }
                }
                //カン57
                if (winGroup.IndexOf(winTileKind) == 1)
                {
                    fuDetails.Add(new FuDetail(2, KANCHAN));
                }
            }

            //符あり雀頭
            var countOfValuedPairs = valuedTiles.Count(x => x == pair[0].Value);

            if (countOfValuedPairs == 1)
            {
                fuDetails.Add(new FuDetail(2, VALUED_PAIR));
            }

            //雀頭ダブ東南4符
            if (countOfValuedPairs == 2)
            {
                fuDetails.Add(new FuDetail(2, VALUED_PAIR));
                fuDetails.Add(new FuDetail(2, VALUED_PAIR));
            }

            //シャンポン待ち
            if (winGroup.IsPair)
            {
                fuDetails.Add(new FuDetail(2, PAIR_WAIT));
            }

            foreach (var setItem in ponSets)
            {
                var openMelds = melds.Where(x => setItem.Equals(x.TileKinds))
                                .ToList();
                var openMeld   = openMelds.Count == 0 ? null : openMelds[0];
                var setWasOpen = !(openMeld is null) && openMeld.Opened;
                var isKan      = !(openMeld is null) &&
                                 (openMeld.Type == MeldType.KAN || openMeld.Type == MeldType.CHANKAN);
                var isYaochu = YAOCHU_INDICES.Contains(setItem[0].Value);

                if (!config.IsTsumo && setItem.Equals(winGroup))
                {
                    setWasOpen = true;
                }
                if (isYaochu)
                {
                    if (isKan)
                    {
                        if (setWasOpen)
                        {
                            fuDetails.Add(new FuDetail(16, OPEN_TERMINAL_KAN));
                        }
                        else
                        {
                            fuDetails.Add(new FuDetail(32, CLOSED_TERMINAL_KAN));
                        }
                    }
                    else
                    {
                        if (setWasOpen)
                        {
                            fuDetails.Add(new FuDetail(4, OPEN_TERMINAL_PON));
                        }
                        else
                        {
                            fuDetails.Add(new FuDetail(8, CLOSED_TERMINAL_PON));
                        }
                    }
                }
                else
                {
                    if (isKan)
                    {
                        if (setWasOpen)
                        {
                            fuDetails.Add(new FuDetail(8, OPEN_KAN));
                        }
                        else
                        {
                            fuDetails.Add(new FuDetail(16, CLOSED_KAN));
                        }
                    }
                    else
                    {
                        if (setWasOpen)
                        {
                            fuDetails.Add(new FuDetail(2, OPEN_PON));
                        }
                        else
                        {
                            fuDetails.Add(new FuDetail(4, CLOSED_PON));
                        }
                    }
                }
            }
            var addTsumoFu = fuDetails.Count > 0 || config.Options.FuForPinfuTsumo;

            if (config.IsTsumo && addTsumoFu)
            {
                fuDetails.Add(new FuDetail(2, TSUMO));
            }
            if (IsOpenHand && fuDetails.Count == 0 && config.Options.FuForOpenPinfu)
            {
                fuDetails.Add(new FuDetail(2, HAND_WITHOUT_FU));
            }
            if (IsOpenHand || config.IsTsumo)
            {
                fuDetails.Add(new FuDetail(20, BASE));
            }
            else
            {
                fuDetails.Add(new FuDetail(30, BASE));
            }
            return(fuDetails, RoundFu(fuDetails));
        }