Commit Graph

14 Commits

Author SHA1 Message Date
a94e68fee2 fix: 鸡胡 FanValue=0 导致武汉麻将赢家得0分
根因: IdentifyFans 生成的无字/平胡/断幺九等标记番型(base_fan=0)
→ fans.Count>0 → 鸡胡不添加 → FanValue只有0值番型 → baseFan=0

修复(2处):
1. ScoreEngine.FanValue + PhaseMachine.GetFanValue: 鸡胡硬编码 fallback=1
2. IdentifyFans allZeroValue: 当所有番型都是0值(不在_fanConfig且不在硬编码列表)
   时强制添加鸡胡。0值判断依据: 在_fanConfig中base_fan≤0,
   或不在9个硬编码fallback番型中(清一色/混一色/对对胡/碰碰和/暗七对/七对/带幺九/十三幺/鸡胡)

验证: 武汉麻将赢家分数从0变成非零(3/6/9分), 58 tests pass, 5 variants 0 errors
2026-07-04 21:24:46 +08:00
b038d5e2da fix: GetLegalActions从硬编码改为读DSL+条件求值+wildcard计数修正
子代理审查MED级bug修复:

1. GetLegalActions硬编码忽略DSL action列表
   →从play phase的SelfActions/OthersReactions读取允许的action
   →DSL可禁用an_kong/bu_kong/pung等操作

2. action condition字符串完全未求值
   →CheckCondition()支持:can_win/can_chi/has_two_same等10种条件
   →国标can_win_tumo_and_fan_ge_8条件被评估

3. wildcard bonus仅计缺口填充
   →改为统计赢家手牌+副露中全部癞子(per_wildcard_in_win语义)

4. PhaseMachine两处wildcard计数从静态IsWildcard改为_wildcards实例

6个文件:PhaseMachine+ScoreEngine(核心)+MahjongRoom(WildcardRegistry引用)
2026-07-04 20:37:13 +08:00
d5973fd2bc 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→下一轮评估
2026-07-04 20:32:39 +08:00
d95eab84f0 fix: chi在四川血战等无吃变体中仍然可用
Root cause: HandleDiscardReactions始终调用CanChiCheck,不检查
DSL的others_reaction是否包含chi action

修复:
- PhaseMachine: 构造时读取phases→检查是否有chi→_chiAllowed
- MahjongRoom: HandleDiscardReactions用_phaseMachine.ChiAllowed门控
- 人类/AI均在无chi变体中不再看到/执行chi

Impact: xuezhandaodi(无chi)和wuhan/guobiao/guangdong(有chi)行为正确隔离
2026-07-04 20:22:04 +08:00
c2b5136085 refactor: _wildcards static→实例级 WildcardRegistry
Root cause: static HashSet跨测试/跨变体污染+硬编码名→编码映射

Changes:
- WildcardRegistry: 实例级wildcard管理(IsWildcard/CountWildcards/Clone)
- GameState: 新增Wildcards属性(含Clone)
- MahjongTile: 移除static_wildcards,IsWildcard仅查编码50-59
  +ToString(tile,wildcards)重载用于游戏上下文显示
- MeldsSolver: _wildcards字段→构造函数注入(WildcardRegistry?)
- PhaseMachine: _wildcards字段+构造注入
- Deal(): State.Wildcards.Clear()+AddRange替代static ConfigureWildcards
  +NameToEncoding查表替代switch硬编码
- RandomMahjongAI/HumanMahjongPlayer: state.Wildcards替代static调用
- HumanMahjongPlayer.CheckTing: 补wildcardCount参数(之前遗漏)
- ExecuteWinClaim: IsFinished=true→Settle()(之前Phase漏设)

Test: CoreTests清理ConfigureWildcards()→WildcardRegistry测试
Impact: 零static state→不同变体/测试完全隔离,未来支持随机宝牌
2026-07-04 20:05:26 +08:00
978fcd87dd fix: 国标fan_types缺常见番型→0%胡牌率(补全28种)
Root cause: guobiao.yaml只列了11个高番型(≥24番),缺少Level 1-6的常见番型。
add_max每level只取最大值→缺中低番型拼不出8番门槛。

修复:
- DSL补全:全大/全中/全小(12番),大于五/小于五(8番),碰碰和/混一色/五门齐/全求人(6番),
  全带幺(4番),断幺九/平和/门前清(2番),缺一门/无字(1番)
- ScoreEngine/PhaseMachine fallback加'碰碰和'(国标名称)
- 随机AI 国标胡牌率: 0%→30%(纯运气,合理)

注: 完整国标有81种番型,Demo阶段补到28种够覆盖常见组合
2026-07-04 19:16:16 +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
a06f40bd2d fix: 番型互斥从未应用 + FanValue兜底乱给分 + 白名单过滤
Root cause:
1. ApplyFanExclusions定义但从未被调用 → 互斥(清一色⊃缺一门)形同虚设
2. FanValue中 _=>1 兜底 → '缺一门''平胡'等不在DSL的番型也被+1分
3. IdentifyFans返回所有结构模式 → 与DSL配置不一致

修复:
- CheckWin五处IdentifyFans调用后加ApplyFanExclusions
- FanValue去掉_=>1,改为只认DSL配置+硬编码知名番型
- IdentifyFans末尾白名单过滤:只返回DSL或知名番型
- PhaseMachine.GetFanValue同步更新
- ScoreEngine: 不在DSL的番型→0分
2026-07-04 18:12:06 +08:00
cbbe503117 fix: Code Review完整修复 — AI chi/暗杠/加杠/chi位置
发现的6个缺口:
1. HandleDiscardReactions AI分支缺chi → 新增ExecuteAiChi
2. StepTurn不处理an_kong/bu_kong → 新增ExecuteAnKong/ExecuteBuKong
3. PhaseMachine.GetLegalActions chi误在自回合 → 移除(chi只能反应)
4. ScoreEngine.CheckFinish死代码 → 保留(无影响)
5. ExecutePungKong用Random.Shared → 改用_rng
6. HumanMahjongPlayer残留chiOpt → 移除
2026-07-04 17:56:14 +08:00
b6bdf064ff feat: 吃(chi)反应支持 — HandleDiscardReactions + 人类/AI
- CanChi→CanChiCheck公开给MahjongRoom调用
- HandleDiscardReactions: offset=1(上家)且非字牌时检查chi
- 人类HUD: c(吃)选项
- ExecuteChi: 找到配对的两张牌→创建chi副露→出牌
- ExecutePungKongHuman: 抽取碰/杠人类交互逻辑
2026-07-04 17:51:58 +08:00
bf041b7e50 fix: CheckWin守卫!=14拒绝副露后手牌 + FullHand合并副露
根因: CheckWin要求tiles.Count==14,碰/杠后手牌只有11/8/5/2张
修复:
- CheckWin守卫: !=14 → total%3!=2 (接受2,5,8,11,14)
- FullHand(): 合并手牌+Exposed副露→虚拟完整手牌
- 所有CheckWin调用点改用FullHand (MahjongRoom+PhaseMachine+HumanMahjongPlayer)
- 新增集成测试: 副露后11张手牌自摸
2026-07-04 17:31:31 +08:00
d416450e56 fix: CanAnKong硬编码false + 人类HUD显示听牌/杠/对手状态
修复:
- CanAnKong: 硬编码false → 检查手牌中4张相同(暗杠)
- HumanMahjongPlayer: 添加MeldsSolver依赖,实时检测听牌
- 人类HUD: 显示牌墙/副露/听牌🀄/杠类型(暗/明/加)
- 交互模式人类: 对手显示'X张手牌 | 已pung[..]'不暴露手牌
2026-07-04 17:24:05 +08:00
bb43ed7c89 fix: CheckWin缺少wildcard/258参数导致武汉麻将0%胡牌 + 庄家第一轮跳过摸牌
Root cause 1: 所有CheckWin调用未传wildcardCount/require258Pair
- StepTurn自摸: 5处遗漏 → 癞子在手牌中被当废牌
- HandleDiscardReactions: 2处遗漏
- PhaseMachine: 2处遗漏
→ 武汉麻将永远不能胡牌

Root cause 2: 庄家开局14张+摸牌=15张, CheckWin守卫≠14拒绝
→ 庄家永远不能自摸 → 修复: 庄家第一轮跳过摸牌

额外修复:
- RandomMahjongAI: 永远不出癞子(预留wildcard)
- ScoreEngine.FanValue: 从DSL _fanConfig读取番值
- HandleDiscardReactions: 同优先级座位顺序
- 新增GetWinParams/CountWildcardsInHand辅助方法

验证: 47/47测试, Wuhan 1.6%胡牌(500局), Sichuan 0.4%
2026-07-04 11:39:00 +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