From cadf76999eda63f339189be75dbd73b44a96ddc2 Mon Sep 17 00:00:00 2001 From: xiaoou Date: Sat, 4 Jul 2026 18:38:15 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20DSL=20total=E5=AD=97=E6=AE=B5=E4=BB=8E?= =?UTF-8?q?=E6=9C=AA=E8=A2=AB=E5=BC=95=E6=93=8E=E6=A0=A1=E9=AA=8C+?= =?UTF-8?q?=E5=B9=BF=E4=B8=9C=E7=89=8C=E5=BA=93=E6=95=B0=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: 1. Deal()完全忽略 _rules.Deck.Total → 牌库大小由 includeFlags 决定 2. Guangdong DSL: total=136 但 include_flowers=true → 实际144张 3. DS与引擎脱节导致广东无限对局(flaky test根因之一) 修复: - Deck构造加 expectedTotal 可选参数,不一致时抛 InvalidOperationException - Deal()传 _rules.Deck.Total → 所有DSL变更牌数时必须引擎一致 - Guangdong DSL: total 136→144(广东麻将含花牌=144张) Breaks: 无(向后兼容,expectedTotal默认null=不校验) --- RuleEngine/Core/Deck.cs | 11 ++++++++++- RuleEngine/MahjongRoom.cs | 3 ++- dsl-examples/guangdong_jipinghu.yaml | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/RuleEngine/Core/Deck.cs b/RuleEngine/Core/Deck.cs index 4e5a3f2..5f183b1 100644 --- a/RuleEngine/Core/Deck.cs +++ b/RuleEngine/Core/Deck.cs @@ -4,7 +4,7 @@ public class MahjongDeck { public List Tiles { get; private set; } = new(); - public MahjongDeck(bool includeHonors = false, bool includeFlowers = false, int wildcardCount = 0) + public MahjongDeck(bool includeHonors = false, bool includeFlowers = false, int wildcardCount = 0, int? expectedTotal = null) { var allTiles = MahjongTile.AllTiles(includeHonors, includeFlowers, wildcardCount); foreach (var t in allTiles) @@ -19,6 +19,15 @@ public class MahjongDeck // Add extra wildcard tiles for (int i = 0; i < wildcardCount; i++) Tiles.Add(MahjongTile.WildcardBase + i); + + // Validate against DSL total if specified + if (expectedTotal.HasValue && Tiles.Count != expectedTotal.Value) + { + throw new InvalidOperationException( + $"牌库大小不匹配: 引擎生成 {Tiles.Count} 张, DSL 声明 {expectedTotal.Value} 张。" + + $" includeHonors={includeHonors} includeFlowers={includeFlowers} wildcardCount={wildcardCount}." + + $" 请检查 DSL deck.total 字段与 include_honors/include_flowers 的一致性。"); + } } public void Shuffle(Random? rng = null) diff --git a/RuleEngine/MahjongRoom.cs b/RuleEngine/MahjongRoom.cs index 8f2429e..e051252 100644 --- a/RuleEngine/MahjongRoom.cs +++ b/RuleEngine/MahjongRoom.cs @@ -685,7 +685,8 @@ public class MahjongRoom } } - var deck = new MahjongDeck(includeHonors, includeFlowers, wildcardCount); + var deck = new MahjongDeck(includeHonors, includeFlowers, wildcardCount, + expectedTotal: _rules.Deck.Total); deck.Shuffle(_rng); State.Deck = deck.Tiles; diff --git a/dsl-examples/guangdong_jipinghu.yaml b/dsl-examples/guangdong_jipinghu.yaml index ac303a8..df041d0 100644 --- a/dsl-examples/guangdong_jipinghu.yaml +++ b/dsl-examples/guangdong_jipinghu.yaml @@ -17,7 +17,7 @@ deck: generator: mahjong include_honors: true include_flowers: true - total: 136 + total: 144 deal: cards_per_player: 13