protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { const YakuEnvironment cmp = YakuEnvironment.自摸 | YakuEnvironment.海底; if ((env & cmp) != cmp) { return(false); } result.Add(YakuValue.FromFanValue(this, "海底摸月", 1)); return(true); }
protected static bool SelfWindEquals(Wind wind, YakuEnvironment env) { if (wind == Wind.None) { throw new ArgumentException($"不可以为{nameof(Wind)}.{nameof(Wind.None)}", nameof(wind)); } int val1 = ((int)env >> 6) & 0xf; int val2 = 1 << ((int)wind - 1); return(val1 == val2); }
protected override bool TestRon(ITiles tiles, YakuEnvironment env) { if (tiles.HandTiles.Count != 14) { return(false); } BaseTile prev = null; for (int i = 0; i < 14; prev = tiles.HandTiles[i].BaseTile, i += 2) { if (prev == tiles.HandTiles[i].BaseTile) { return(false); // 不允许相同的将 } if (tiles.HandTiles[i].BaseTile != tiles.HandTiles[i + 1].BaseTile) { return(false); } } return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { int[] counts = { -3, -1, -1, -1, -1, -1, -1, -1, -3 }; for (int i = 0; i < tiles.Count; i++) { counts[(tiles[i].BaseTile as NumberTile).Number - 1]++; } int val = 0; for (int i = 0; i < 9; i++) { val |= counts[i]; } if (val != 1) { return(false); } int extraNumber = Array.IndexOf(counts, 1) + 1; var extraTile = tiles.Added.BaseTile as NumberTile; if (extraTile.Number == extraNumber) { result.Add(YakuValue.FromFullYaku(this, "纯正九莲宝灯", 1)); } else { result.Add(YakuValue.FromFullYaku(this, "九莲宝灯", 1)); } return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { int dora = tiles.Count(t => t.IsRedDora); if (dora == 0) { return(false); } result.Add(YakuValue.FromFanValue(this, "赤宝牌", 0, dora)); return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { KanjiTile.Kanji GetKanjis(YakuEnvironment e) { int slefWind = ((int)e >> 6) & 0xf; int fieldWind = ((int)e >> 10) & 0xf; return((KanjiTile.Kanji)(slefWind | fieldWind)); } if ((env & YakuEnvironment.门前清) == 0) { return(false); } if (groups.Pair.Type == GroupType.和牌) { return(false); } foreach (var g in groups.JunkoList) { if (g.Type == GroupType.副露) { return(false); } if (g.Type == GroupType.和牌) { var numTile = g.Key as NumberTile; switch (g.AddedIndex) { case 0 when numTile.Number == 7: //边张 case 1: //嵌张 case 2 when numTile.Number == 1: //边张 return(false); } } } if (groups.Pair.Key is KanjiTile t) { var excludeKanji = KanjiTile.Kanji.白 | KanjiTile.Kanji.发 | KanjiTile.Kanji.中 | GetKanjis(env); if ((t.Value & excludeKanji) != 0) { return(false); } } result.Add(YakuValue.FromFanValue(this, "平和", 1)); return(true); }
protected override bool HookCalculateFu(ref int fu, IGroups groups, YakuEnvironment env) { fu = env.HasFlag(YakuEnvironment.自摸) ? 20 : 30; return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { if ((env & YakuEnvironment.抢杠) == 0) { return(false); } result.Add(YakuValue.FromFanValue(this, "抢杠", 1)); return(true); }
protected override bool TestRon(ITiles tiles, YakuEnvironment env) { return Array.TrueForAll(tiles.BaseTiles.Sorted.Tiles, tc => tc == 0 || tc == 2); }
protected override bool HookCalculateFu(ref int fu, IGroups groups, YakuEnvironment env) { fu = 25; return true; }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { if ((env & YakuEnvironment.门前清) == 0) { return(false); } int[,] counts = new int[3, 7]; foreach (var g in groups.JunkoList) { counts[g.Key.SortedLevel, (g.Key as NumberTile).Number - 1]++; } int count = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 7; j++) { if (counts[i, j] % 2 == 0) { count += counts[i, j]; if (count == 4) { result.Add(YakuValue.FromFanValue(this, "二杯口", 3)); return(true); } } } } return(false); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { int[,] counts = new int[3, 7]; foreach (var g in groups.JunkoList) { counts[g.Key.SortedLevel, (g.Key as NumberTile).Number - 1]++; } bool yes = false; for (int i = 0; i < 3; i++) { for (int j = 0; j < 7; j++) { if (counts[i, j] >= 2 && counts[i, j] < 4) { yes = !yes; // 防止二杯口 } } } if (!yes) { return(false); } result.Add(YakuValue.FromFanValue(this, "一杯口", 1)); return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { foreach (var g in groups.PungList) { if (g.Type == GroupType.副露) { return(false); } if (g.Type == GroupType.和牌 && !SelfWindEquals(g.AddedWind, env)) { return(false); } } if (groups.Pair.Type == GroupType.和牌) { result.Add(YakuValue.FromFullYaku(this, "四暗刻单骑", 1)); } else { result.Add(YakuValue.FromFullYaku(this, "四暗刻", 1)); } return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { int[] counts = new int[9]; foreach (var g in groups.PungList) { if (g.Key is NumberTile t) { counts[t.Number]++; } } for (int i = 0; i < 9; i++) { if (counts[i] == 3) { result.Add(YakuValue.FromFanValue(this, "三色同刻", 2)); return(true); } } return(false); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { if (groups.PungList.Any(g => !(g is Gan))) { return(false); } result.Add(YakuValue.FromFullYaku(this, "四杠子", 1)); return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { long flags = 0; for (int i = 0; i < tiles.Count; i++) { flags |= (1L << tiles[i].BaseTile.SortedIndex); } if ((flags | CheckFlags) != CheckFlags) { return(false); } result.Add(YakuValue.FromFullYaku(this, "绿一色", 1)); return(true); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { result.Add(YakuValue.FromFanValue(this, "清一色", (env & YakuEnvironment.门前清) != 0 ? 6 : 5)); return(true); }
protected override bool Test(ICollection<YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { if (!TestRon(tiles, env)) return false; result.Add(YakuValue.FromFanValue(this, "七对子", 2)); return true; }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { Kanji Get自风(YakuEnvironment e) => (Kanji)(((int)e >> 6) & 0xf); Kanji Get场风(YakuEnvironment e) => (Kanji)(((int)e >> 10) & 0xf); Kanji selfWind = Get自风(env), fieldWind = Get场风(env); var cmp = selfWind | fieldWind | Kanji.白 | Kanji.发 | Kanji.中; bool yes = false; foreach (var g in groups.PungList) { if (g.Key is KanjiTile t) { if ((t.Value & cmp) != 0) { yes = true; if (t.Value == selfWind) { result.Add(YakuValue.FromFanValue(this, "自风" + selfWind, 1)); } if (t.Value == fieldWind) { result.Add(YakuValue.FromFanValue(this, "场风" + fieldWind, 1)); } else if (t.Value == Kanji.白) { result.Add(YakuValue.FromFanValue(this, "役牌白", 1)); } else if (t.Value == Kanji.发) { result.Add(YakuValue.FromFanValue(this, "役牌发", 1)); } else { result.Add(YakuValue.FromFanValue(this, "役牌中", 1)); } } } } return(yes); }
protected override bool Test(ICollection <YakuValue> result, ITiles tiles, IGroups groups, YakuEnvironment env) { const KanjiTile.Kanji cmp = KanjiTile.Kanji.白 | KanjiTile.Kanji.发 | KanjiTile.Kanji.中; if (!(groups.Pair.Key is KanjiTile t) || (t.Value & cmp) == 0) { return(false); } int count = groups.PungList.Count(g => g.Key is KanjiTile t2 && (t2.Value & cmp) != 0); if (count < 2) { return(false); } result.Add(YakuValue.FromFanValue(this, "小三元", 2)); return(true); }