public void TestHasTane() { var list = Yakus.GetHasTane(); var actual = list.GetYakus(MonthEnum.Ayame); Assert.IsTrue(actual.Count() == 1); Assert.IsTrue(actual.Any(x => x == YakuEnum.Tane)); }
public void TestHasTsukiFuda() { var list = Yakus.GetHasTsukiFuda(); var actual = list.GetYakus(MonthEnum.Matsu); Assert.IsTrue(actual.Count() == 1); Assert.IsTrue(actual.Any(x => x == YakuEnum.TsukiFuda)); }
public void TestHasInoShikaCho() { var list = Yakus.GetHasInoShikaCho(); var actual = list.GetYakus(MonthEnum.Ayame); Assert.IsTrue(actual.Count() == 1); Assert.IsTrue(actual.Any(x => x == YakuEnum.Inoshikacho)); }
public void TestHasAkatanAotan() { var list = Yakus.GetHasAkatanAotan(); var actual = list.GetYakus(MonthEnum.Ayame); Assert.IsTrue(actual.Count() == 4); Assert.IsTrue(actual.Any(x => x == YakuEnum.AkatanAotanNoChofuku || x == YakuEnum.Akatan || x == YakuEnum.Aotan || x == YakuEnum.Tan)); }
public void TestHasTeshi() { var list = Yakus.GetHasTeshi(); var actual = list.HasTeshi(MonthEnum.Ayame); var actualNot = list.HasTeshi(MonthEnum.Botan); Assert.IsTrue(actual); Assert.IsFalse(actualNot); }
public void TestHasKuttsuki() { var list = Yakus.GetHasKuttsuki(); var listNot = Yakus.GetNotHasKuttsuki(); var actual = list.HasKuttsuki(); var actualNot = listNot.HasKuttsuki(); Assert.IsTrue(actual); Assert.IsFalse(actualNot); }
public void TestHasAmeShiko() { var list = Yakus.GetHasAmeShiko(); var listNot = Yakus.GetNotHasAmeShiko(); var actual = list.GetYakus(MonthEnum.Ayame); var actualNot = listNot.GetYakus(MonthEnum.Ayame); Assert.IsTrue(actual.Count() == 1); Assert.IsTrue(actual.Any(x => x == YakuEnum.AmeShiko)); Assert.IsTrue(actualNot.All(x => x != YakuEnum.AmeShiko)); }
/// <summary> /// Checks if this instance is equal to another one. /// </summary> /// <param name="other">Second instance of <see cref="HandYakuListPivot"/>.</param> /// <returns><c>True</c> if equal; <c>False</c> otherwise.</returns> public bool Equals(HandYakuListPivot other) { return(other?.ConcealedHand == ConcealedHand && other.Yakus.Count == Yakus.Count && other.Yakus.All(y => Yakus.Contains(y))); }
/// <summary> /// Computes the list of yakus available with this sequence of combinations. /// If the list contains one or several yakumans, it can't contain any regular yakus. /// Two <see cref="YakuPivot"/> are not computed : /// <list type="bullet"> /// <item><see cref="KokushiMusou"/></item> /// <item><see cref="NagashiMangan"/></item> /// </list> /// </summary> /// <param name="combinationsSequence">Sequence of combinations.</param> /// <param name="context">Context.</param> /// <returns>List of yakus with this sequence of combinations.</returns> /// <exception cref="ArgumentNullException"><paramref name="combinationsSequence"/> is <c>Null</c>.</exception> /// <exception cref="ArgumentNullException"><paramref name="context"/> is <c>Null</c>.</exception> /// <exception cref="NotImplementedException">The <see cref="YakuPivot"/> to check is not implemented.</exception> public static List <YakuPivot> GetYakus(List <TileComboPivot> combinationsSequence, WinContextPivot context) { if (combinationsSequence == null) { throw new ArgumentNullException(nameof(combinationsSequence)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var yakus = new List <YakuPivot>(); foreach (YakuPivot yaku in Yakus.Where(y => y.IsYakuman)) { bool addYaku = false; if (yaku == Daisangen) { addYaku = combinationsSequence.Count(c => c.IsBrelanOrSquare && c.Family == FamilyPivot.Dragon) == 3; } else if (yaku == Suuankou) { addYaku = combinationsSequence.Count(c => c.IsBrelanOrSquare && c.IsConcealed && (!c.Tiles.Contains(context.LatestTile) || context.DrawType.IsSelfDraw())) == 4; } else if (yaku == Shousuushii) { addYaku = combinationsSequence.Count(c => c.IsBrelanOrSquare && c.Family == FamilyPivot.Wind) == 3 && combinationsSequence.Any(c => c.IsPair && c.Family == FamilyPivot.Wind); } else if (yaku == Daisuushii) { addYaku = combinationsSequence.Count(c => c.IsBrelanOrSquare && c.Family == FamilyPivot.Wind) == 4; } else if (yaku == Tsuuiisou) { addYaku = combinationsSequence.All(c => c.IsHonor); } else if (yaku == Ryuuiisou) { addYaku = combinationsSequence.All(c => (c.Family == FamilyPivot.Bamboo && c.Tiles.All(t => new[] { 2, 3, 4, 6, 8 }.Contains(t.Number))) || (c.Family == FamilyPivot.Dragon && c.Tiles.First().Dragon == DragonPivot.Green) ); } else if (yaku == Chinroutou) { addYaku = combinationsSequence.All(c => c.IsTerminal); } else if (yaku == ChuurenPoutou) { if (combinationsSequence.All(c => c.IsConcealed) && combinationsSequence.Select(c => c.Family).Distinct().Count() == 1) { string numberPattern = string.Join(string.Empty, combinationsSequence.SelectMany(c => c.Tiles).Select(t => t.Number).OrderBy(i => i)); addYaku = new[] { "11112345678999", "11122345678999", "11123345678999", "11123445678999", "11123455678999", "11123456678999", "11123456778999", "11123456788999", "11123456789999" }.Contains(numberPattern); } } else if (yaku == Suukantsu) { addYaku = combinationsSequence.Count(c => c.IsSquare) == 4; } else if (yaku == Tenhou) { addYaku = context.IsTenhou(); } else if (yaku == Chiihou) { addYaku = context.IsChiihou(); } else if (yaku == Renhou) { addYaku = context.IsRenhou(); } else if (yaku == KokushiMusou) { // Do nothing here, but prevents the exception below. } else { throw new NotImplementedException(); } if (addYaku) { yakus.Add(yaku); } } // Remove yakumans with existant upgrade (it's an overkill as the only known case is "Shousuushii" vs. "Daisuushii"). yakus.RemoveAll(y => y.Upgrades.Any(yu => yakus.Contains(yu))); // Only return yakumans if any. if (yakus.Count >= 1) { return(yakus); } foreach (YakuPivot yaku in Yakus.Where(y => !y.IsYakuman)) { bool addYaku = false; int occurences = 1; if (yaku == Chiniisou) { addYaku = combinationsSequence.Select(c => c.Family).Distinct().Count() == 1 && !combinationsSequence.Any(c => c.IsHonor); } else if (yaku == Haitei) { addYaku = context.IsRoundLastTile; } else if (yaku == RinshanKaihou) { addYaku = context.DrawType == DrawTypePivot.Compensation; } else if (yaku == Chankan) { addYaku = context.DrawType == DrawTypePivot.OpponentKanCallOpen; } else if (yaku == Tanyao) { addYaku = combinationsSequence.All(c => !c.HasTerminalOrHonor); } else if (yaku == Yakuhai) { occurences = combinationsSequence.Count(c => c.IsBrelanOrSquare && ( c.Family == FamilyPivot.Dragon || ( c.Family == FamilyPivot.Wind && ( c.Tiles.First().Wind == context.DominantWind || c.Tiles.First().Wind == context.PlayerWind ) ) ) ); addYaku = occurences > 0; } else if (yaku == Riichi) { addYaku = context.IsRiichi; } else if (yaku == Ippatsu) { addYaku = context.IsIppatsu; } else if (yaku == MenzenTsumo) { addYaku = context.DrawType.IsSelfDraw() && combinationsSequence.All(c => c.IsConcealed); } else if (yaku == Honiisou) { addYaku = combinationsSequence.Where(c => !c.IsHonor).Select(c => c.Family).Distinct().Count() == 1; } else if (yaku == Pinfu) { addYaku = combinationsSequence.Count(c => c.IsSequence && c.IsConcealed) == 4 && !HandPivot.HandWithValuablePair(combinationsSequence, context.DominantWind, context.PlayerWind) && combinationsSequence.Any(c => c.IsSequence && c.Tiles.Contains(context.LatestTile) && !context.LatestTile.TileIsEdgeWait(c) && !context.LatestTile.TileIsMiddleWait(c)); } else if (yaku == Iipeikou) { int sequencesCount = combinationsSequence.Count(c => c.IsSequence); addYaku = combinationsSequence.All(c => c.IsConcealed) && sequencesCount >= 2 && combinationsSequence.Where(c => c.IsSequence).Distinct().Count() < sequencesCount; } else if (yaku == Shousangen) { addYaku = combinationsSequence.Count(c => c.IsBrelanOrSquare && c.Family == FamilyPivot.Dragon) == 2 && combinationsSequence.Any(c => c.IsPair && c.Family == FamilyPivot.Dragon); } else if (yaku == Honroutou) { addYaku = combinationsSequence.All(c => c.IsTerminal || c.IsHonor); } else if (yaku == Chiitoitsu) { addYaku = combinationsSequence.All(c => c.IsPair); } else if (yaku == Sankantsu) { addYaku = combinationsSequence.Count(c => c.IsSquare) == 3; } else if (yaku == SanshokuDoukou) { addYaku = combinationsSequence .Where(c => c.IsBrelanOrSquare && !c.IsHonor) .GroupBy(c => c.Tiles.First().Number) .FirstOrDefault(b => b.Count() >= 3)? .Select(b => b.Family)? .Distinct()? .Count() == 3; } else if (yaku == Sanankou) { addYaku = combinationsSequence.Count(c => c.IsBrelanOrSquare && c.IsConcealed && (!c.Tiles.Contains(context.LatestTile) || context.DrawType.IsSelfDraw())) == 3; } else if (yaku == Toitoi) { addYaku = combinationsSequence.Count(c => c.IsBrelanOrSquare) == 4; } else if (yaku == Ittsu) { List <TileComboPivot> ittsuFamilyCombos = combinationsSequence .Where(c => c.IsSequence) .GroupBy(c => c.Family) .FirstOrDefault(b => b.Count() >= 3)? .ToList(); addYaku = ittsuFamilyCombos != null && ittsuFamilyCombos.Any(c => c.SequenceFirstNumber == 1) && ittsuFamilyCombos.Any(c => c.SequenceFirstNumber == 4) && ittsuFamilyCombos.Any(c => c.SequenceFirstNumber == 7); } else if (yaku == SanshokuDoujun) { addYaku = combinationsSequence .Where(c => c.IsSequence) .GroupBy(c => c.SequenceFirstNumber) .FirstOrDefault(b => b.Count() >= 3)? .Select(b => b.Family)? .Distinct()? .Count() == 3; } else if (yaku == Chanta) { addYaku = combinationsSequence.All(c => c.HasTerminalOrHonor); } else if (yaku == DaburuRiichi) { addYaku = context.IsRiichi && context.IsFirstTurnRiichi; } else if (yaku == Ryanpeikou) { addYaku = combinationsSequence.All(c => c.IsConcealed) && combinationsSequence.Count(c => c.IsSequence) == 4 && combinationsSequence.Where(c => c.IsSequence).Distinct().Count() <= 2; } else if (yaku == Junchan) { addYaku = combinationsSequence.All(c => c.HasTerminal); } else if (yaku == NagashiMangan) { // Do nothing here, but prevents the exception below. } else { throw new NotImplementedException(); } if (addYaku) { for (int i = 0; i < occurences; i++) { yakus.Add(yaku); } } } // Remove yakus with existant upgrade. // It works because Upgrades is not recursive. yakus.RemoveAll(y => y.Upgrades.Any(yu => yakus.Contains(yu))); // On a concealed chanka, only Kokushi is allowed. if (context.DrawType == DrawTypePivot.OpponentKanCallConcealed && !yakus.Contains(KokushiMusou)) { yakus.Clear(); } return(yakus); }