fix: 4个HIGH severity DSL规则bug(子代理审查发现)
子代理审查(对照4个DSL)发现27个bug,本轮修复HIGH级别4个: 1. PhaseMachine wildcard计数用Core.MahjongTile.IsWildcard(静态)→ 不检查配置的红中(35)→_wildcards.CountWildcards(实例) 2. 番型名不匹配:引擎生成 对对胡/暗七对,但DSL定义 碰碰胡/碰碰和/七对→FanName()动态匹配_fanConfig 3. 十三幺/七对/全不靠/一色双龙会不识别自身番型→ CheckWin各路径返回前注入番型名+IdentifyFans追加 4. 258将: 七对路径缺检查+IsValid258Pair OR→AND逻辑 (一张癞子+非258牌应拒绝,不是通过) 此前已修:chi越权(d95eab8)+花牌计分+BEFORE_GAME_START(9b9e4c3) 剩余17个MED/LOW→下一轮评估
This commit is contained in:
@ -45,7 +45,23 @@ public class MeldsSolver
|
||||
var sevenPairs = TrySevenPairs(tiles, wildcardCount);
|
||||
if (sevenPairs != null)
|
||||
{
|
||||
sevenPairs.Fans = ApplyFanExclusions(IdentifyFans(sevenPairs));
|
||||
// 258将检查: 武汉七对每对都需258
|
||||
if (require258Pair)
|
||||
{
|
||||
foreach (var m in sevenPairs.Melds)
|
||||
{
|
||||
if (m.Type == "pair" && m.Tiles.Count >= 2)
|
||||
{
|
||||
int a = m.Tiles[0], b = m.Tiles[1];
|
||||
// Both tiles must be 258 or wildcard
|
||||
if (!Is258OrWildcard(a) && !Is258OrWildcard(b))
|
||||
return new MeldsResult { IsWin = false };
|
||||
}
|
||||
}
|
||||
}
|
||||
sevenPairs.Fans = new List<string> { FanName("暗七对", "七对") };
|
||||
sevenPairs.Fans = ApplyFanExclusions(
|
||||
sevenPairs.Fans.Concat(IdentifyFans(sevenPairs)).Distinct().ToList());
|
||||
return sevenPairs;
|
||||
}
|
||||
|
||||
@ -53,7 +69,9 @@ public class MeldsSolver
|
||||
var thirteen = TryThirteenOrphans(tiles, wildcardCount);
|
||||
if (thirteen != null)
|
||||
{
|
||||
thirteen.Fans = ApplyFanExclusions(IdentifyFans(thirteen));
|
||||
thirteen.Fans = new List<string> { "十三幺" };
|
||||
thirteen.Fans = ApplyFanExclusions(
|
||||
thirteen.Fans.Concat(IdentifyFans(thirteen)).Distinct().ToList());
|
||||
return thirteen;
|
||||
}
|
||||
|
||||
@ -61,7 +79,9 @@ public class MeldsSolver
|
||||
var allOrphans = TryAllOrphans(tiles, wildcardCount);
|
||||
if (allOrphans != null)
|
||||
{
|
||||
allOrphans.Fans = ApplyFanExclusions(IdentifyFans(allOrphans));
|
||||
allOrphans.Fans = new List<string> { "全不靠" };
|
||||
allOrphans.Fans = ApplyFanExclusions(
|
||||
allOrphans.Fans.Concat(IdentifyFans(allOrphans)).Distinct().ToList());
|
||||
return allOrphans;
|
||||
}
|
||||
|
||||
@ -69,7 +89,9 @@ public class MeldsSolver
|
||||
var doubleDragon = TryDoubleDragon(tiles, wildcardCount);
|
||||
if (doubleDragon != null)
|
||||
{
|
||||
doubleDragon.Fans = ApplyFanExclusions(IdentifyFans(doubleDragon));
|
||||
doubleDragon.Fans = new List<string> { "一色双龙会" };
|
||||
doubleDragon.Fans = ApplyFanExclusions(
|
||||
doubleDragon.Fans.Concat(IdentifyFans(doubleDragon)).Distinct().ToList());
|
||||
return doubleDragon;
|
||||
}
|
||||
|
||||
@ -538,13 +560,27 @@ public class MeldsSolver
|
||||
// === 258将检查 ===
|
||||
private bool IsValid258Pair(int tileA, int tileB)
|
||||
{
|
||||
bool Check(int t)
|
||||
{
|
||||
if (t == -1) return true; // wildcard
|
||||
int r = MahjongTile.Rank(t);
|
||||
return r == 2 || r == 5 || r == 8;
|
||||
}
|
||||
return Check(tileA) || Check(tileB);
|
||||
// Both wildcards → OK. One wildcard → check the other. Both real → both must be 258.
|
||||
if (tileA == -1 && tileB == -1) return true;
|
||||
if (tileA == -1) return Is258Tile(tileB);
|
||||
if (tileB == -1) return Is258Tile(tileA);
|
||||
return Is258Tile(tileA) && Is258Tile(tileB);
|
||||
}
|
||||
|
||||
private bool Is258OrWildcard(int tile) => tile == -1 || Is258Tile(tile);
|
||||
|
||||
private bool Is258Tile(int tile)
|
||||
{
|
||||
int r = MahjongTile.Rank(tile);
|
||||
return r == 2 || r == 5 || r == 8;
|
||||
}
|
||||
|
||||
/// <summary>Resolve canonical fan name to DSL fan name (e.g. 对对胡→碰碰胡/碰碰和).</summary>
|
||||
private string FanName(params string[] candidates)
|
||||
{
|
||||
foreach (var c in candidates)
|
||||
if (_fanConfig.ContainsKey(c)) return c;
|
||||
return candidates[0];
|
||||
}
|
||||
|
||||
// === 番型识别 (DSL-driven: structural patterns auto-detected) ===
|
||||
@ -581,11 +617,11 @@ public class MeldsSolver
|
||||
|
||||
// 对对胡: all melds are kezi
|
||||
if (melds.Count > 0 && melds.All(m => m.Type == "kezi"))
|
||||
fans.Add("对对胡");
|
||||
fans.Add(FanName("对对胡", "碰碰胡", "碰碰和"));
|
||||
|
||||
// 暗七对 (all melds are pairs — from seven-pairs path)
|
||||
if (melds.Count > 0 && melds.All(m => m.Type == "pair"))
|
||||
fans.Add("暗七对");
|
||||
fans.Add(FanName("暗七对", "七对"));
|
||||
|
||||
// 带幺九: all melds contain 1/9/honor
|
||||
if (melds.Count > 0 && pair.Count >= 1)
|
||||
@ -594,7 +630,7 @@ public class MeldsSolver
|
||||
m.Tiles.Where(t => t != -1).All(MahjongTile.IsTerminal));
|
||||
bool pairTerminal = pair.All(t => t == -1 || MahjongTile.IsTerminal(t));
|
||||
if (allMeldsTerminal && pairTerminal)
|
||||
fans.Add("带幺九");
|
||||
fans.Add(FanName("带幺九", "全带幺"));
|
||||
}
|
||||
|
||||
// 混幺九: all tiles are terminals or honors, includes at least one honor and one numbered
|
||||
@ -660,10 +696,6 @@ public class MeldsSolver
|
||||
if (allEven && allTiles.All(t => MahjongTile.IsNumbered(t) || MahjongTile.IsHonor(t)))
|
||||
fans.Add("全双");
|
||||
|
||||
// 碰碰和 (same as 对对胡, guobiao name)
|
||||
if (melds.Count > 0 && melds.All(m => m.Type == "kezi") && !fans.Contains("对对胡"))
|
||||
fans.Add("碰碰和");
|
||||
|
||||
// Filter: only keep fans that exist in DSL config or are well-known
|
||||
return fans.Where(f => _fanConfig.ContainsKey(f) ||
|
||||
f is "清一色" or "混一色" or "对对胡" or "碰碰和" or "暗七对" or "七对"
|
||||
|
||||
Reference in New Issue
Block a user