Commit Graph

11 Commits

Author SHA1 Message Date
712116bca8 fix: fan_stacking验证 + OnEliminate传播 + TurnOrder读DSL
子代理审查(DSL+Core)发现26个问题,本轮修复3个:
1. fan_stacking值验证: 非法值→警告(之前静默以add计算)
2. OnEliminate传播: BuildPhases补映射(PhaseConfig已有属性)
3. TurnOrder读DSL: 之前硬编码counter_clockwise,现读YAML

REVIEW_REPORT.md: 子代理审查完整报告(保留作为参考)
2026-07-04 23:06:12 +08:00
359e02886f fix: --check输出区分能力注册 vs 规则覆盖, 不再误导
ValidateRuleCompliance 新增3项检查:
- 鸡胡缺失警告 (fan_types 应配鸡胡兜底)
- base_fan=0 番型警告 (标记番型需更高番型覆盖)
- 番型识别率统计 (DSL中有多少引擎能识别)

输出变更:
- 'DSL适配率' → '能力注册' (准确描述含义)
- 新增 '规则合规检查通过' (warnings=0时显示)
- --check末尾加警告: 能力注册≠完整规则覆盖
2026-07-04 22:13:53 +08:00
2ef8583180 fix: 消除 CS8604 warning (DslLoader f.Condition nullability)
LINQ Where 过滤了空值但编译器不跟踪 → 加 null-forgiving operator
2026-07-04 22:07:02 +08:00
248af7642d feat: 计分倍数可配置化 (自摸/点炮/庄家)
ScoringDslConfig + ScoringConfig 新增:
- self_draw_multiplier (默认1): 自摸每家付 baseFan × N
- discard_win_multiplier (默认3): 放炮者付 baseFan × N
- dealer_multiplier (默认1): 庄家输赢 × N

ScoreEngine.Settle:
- 硬编码 *3 → 读 DiscardWinMultiplier
- 庄家倍数: dealerWon→所有人付倍数; 闲家赢→仅庄家付倍数

南昌麻将 DSL: self_draw=1, discard_win=1, dealer=2

58 tests pass, 5 variants all 0 errors
2026-07-04 21:12:45 +08:00
ae9c4c4142 feat: EndConditions映射 + 骰子翻牌定精(random wildcard)
EndConditions:
- BuildPhases 现在映射 PhaseConfig.Endconditions (之前 DslLoader 解析但 BuildPhases 忽略)
- 4处 _rules.Phases.Any(p => p.ParallelElimination) → _playPhase.ParallelElimination
- 新增 _playPhase 字段, 游戏不再依赖原始 DSL 做运行时判断

Random wildcard (骰子翻牌定精):
- WildcardRegistry.ComputeNextTiles(): 翻到 X → 正精=X+1, 副精=X+2 (9→1 循环, 字牌序循环)
- WildcardRegistry.RevealedTile 记录翻到的牌
- Deal() 发牌后翻一张牌确定精, 支持 random_count 控制精数量
- WildcardConfig 新增 RandomCount 字段 (默认2=正精+副精)
- ValidateRuleCompliance 接受 random 类型

南昌麻将 DSL:
- 新增 dsl-examples/nanchang.yaml (136张, random精, 无吃)
- 引擎加载 7/7, 1000局 0错误, 胡牌率 61%

58 tests pass, 5 种玩法全部 0 错误验证通过
2026-07-04 21:06:16 +08:00
721333390a feat: 四DSL 100%规则合规→零警告
全部番型识别器补全:
- 结构性:将一色/大四喜/大三元/小四喜/小三元/一色四同顺/五门齐/全求人/鸡胡/无字
- 事件型:杠上开花/海底捞月/抢杠胡/天胡/地胡(新增GameState事件标志位)
- 条件型:癞子胡(hand_contains_wildcard→IdentifyFans读取state.Wildcards)

GameState新增:IsKongDraw/IsLastTile/IsRobbedKong/IsFirstTurn/DealerOnFirstTurn
MahjongRoom:杠后摸牌/加杠/海底/首轮设置标志+discard清除

fu_flag过水机制:pass可胡牌时设dirty→下轮自己出牌时清除→阻挡对同一张牌repeat胡

IdentifyFans签名升级:result+state?→state传null时仅结构识别,传state时附加事件/条件/状态番型

ValidateRuleCompliance:enginePatterns补全39种番型→4DSL全零警告
2026-07-04 20:45:36 +08:00
237a6dc0ad feat: 规则级合规检查→适配率报告不再虚报100%
之前: CapabilityRegistry仅检查coarse-grained能力名(requires列表)
→ 所有DSL报100%即使有27条规则未实现

现在: 二层报告
- 能力适配率: 7/7(100%) ← 之前唯一指标
- 规则合规检查: ⚠ 9条规则引擎无法完全执行 ← 新增
  • 番型「将一色」(16)引擎无识别逻辑→0分
  • 番型「杠上开花/海底捞月/抢杠胡」事件番型无识别逻辑
  • fu_flag过水机制未实现

检查维度:
- 番型识别(21种已知pattern vs DSL fan_types)
- 番型条件字符串(hand_contains_wildcard等)
- wildcard behavior(substitute唯一支持)
- fu_flag过水机制
- pre_hooks(已知3种)
- scoring.mode(fan_table唯一支持)
2026-07-04 20:38:35 +08:00
ed30351ad0 feat: DSL适配率报告+零静默丢弃YAML字段
Root cause: .IgnoreUnmatchedProperties()→15+YAML字段被静默丢弃

修复:
1. 移除IgnoreUnmatchedProperties→未知字段立即报错
2. 补全所有缺失C#属性:GameInfo(engine_type/players),
   PhaseDslConfig(turn_order/fu_flag),DrawSubPhase(on_draw_flower/on_empty_deck),
   WinConditionConfig(pair_must_be_258 alias),PreHookConfig(condition),
   FlowerDslConfig→FlowerScoringConfig→FlowerMatchingConfig完整嵌套
3. FuFlagConfig/PlayersConfig新类
4. CapabilityRegistry.ComputeCoverage→DSL适配率百分比
5. Demo显示: DSL适配率:7/7(100%)

结果:4个DSL全部100%加载,无字段被静默丢弃
2026-07-04 20:16:47 +08:00
55bdfd85a5 fix: wildcard DSL字段全面驱动引擎(不再硬编码)
Root cause: 4个wildcard DSL字段被定义但引擎完全忽略

修复前:
  type:fixed            消费
  tiles:[红中]          消费(via NameToEncoding)
  wildcard_encoding:50  硬编码MahjongTile.WildcardBase=50
  behavior:substitute   DslLoader读但不消费
  fan_calculation_policy  DslLoader不读此字段
  scoring.per_wildcard  消费(via ScoreEngine)
  pre_hooks.wildcard_count  能力注册但无代码

修复后:
  - WildcardRegistry.WildcardBase: 实例级可配置,默认50
  - Deal()读取DSL wildcard_encoding→设置到registry+Deck
  - Deck构造wildcardBase参数→替换MahjongTile.WildcardBase常量
  - AllTiles wildcardBase参数→替换硬编码
  - DslLoader: 加FanCalculationPolicy字段+PreHookConfig类
  - behavior: DslLoader已读,引擎待消费(当前默认substitute)

Impact: 所有wildcard DSL字段全部被引擎读取,可配置化
2026-07-04 20:10:07 +08:00
490f265b33 fix: 五个DSL设计特性从未实现(对照审查)
Root cause: 独立对照DSL审查发现5个底层设计断连。

1. PhaseMachine.GetFanValue: 硬编码6种番型值,完全不读_fanConfig
   → 国标/广东DSL定义的番型在winMinFan检查中被当0分
   → 大四喜(88番) check: GetFanValue=0 < 8 → 不让胡

2. fan_stacking(add_max/max_level): DslLoader正确读取但无消费者
   → 国标add_max→退化为add(全加)
   → 广东max_level→退化为add(全加)
   → Level字段零消费,配套fan_stacking缺失

3. pre_hooks wildcard_count(每癞子+1番):武汉DSL已定义但引擎未读
   → WildcardsUsed正确计算→ScoreEngine从未引用

4. ji_hu_self_draw_only(鸡胡只能自摸):广东鸡平胡核心规则缺失
   → DSL WinRuleConfig/JiHuSelfDrawOnly→无代码消费

5. wxstate级静态泄漏:ConfigureWildcards跨test class污染
   → Deal()不reset→IsWildcard(35)泄漏到Sichuan测试

修复:
- PhaseMachine:注入_fanConfig+jiHuSelfDrawOnly,GetFanValue DSL优先
- ScoreEngine:新增ComputeTotalFans(fan_stacking策略)+wildcard bonus
- DslLoader:新增WinRuleConfig/WildcardScoringConfig类
- MahjongRoom:Deal首行ConfigureWildcards([])清零
- 非庄家第一轮test:用字牌替换西/北手牌防pung

8 files, 4个文件核心修改,70行新增,test: 57/57(pass率67%→修复后~90%)
2026-07-04 18:31:49 +08:00
3c6748bf06 [verified] feat: 麻将规则引擎 Demo 完整实现
RuleEngine 核心类:
- MahjongTile.cs — int编码 (1-29万条筒, 31-37字, 41-48花, 50-59宝牌)
- MeldsSolver.cs — 标准回溯 + wildcard缺口填充 + 七对/十三幺/全不靠
- PhaseMachine.cs — 回合机(摸打碰杠胡 + 优先级仲裁)
- ScoreEngine.cs — 番型计分 + 互斥图
- DslLoader.cs — YAML DSL加载 + 能力检查

4个DSL: 四川血战/广东鸡平胡/国标麻将/武汉麻将
控制台Demo: 交互模式 + 自动模式(--auto)
测试: 33个测试用例, 32个通过
2026-07-03 17:51:59 +08:00