|
|
1576253caa
|
fix: 子代理审查26问题修复13个(剩余为编码定义/DSL文档字段)
本次修复(13/26):
- FuFlag传播: PhaseConfig加FuFlag属性+BuildPhases映射
- Excludes/Conflicts引用完整性: 引用的番型名必须存在于fan_types
- WildcardBase常量提取: WildcardRegistry引用MahjongTile.WildcardBase
- 合规验证扩展: max_fan/phase.type/end_condition/action/priority
- FanCalculationPolicy未消费警告
不修复的剩余13个:
- 编码常量(MahjongTile domain定义,非配置项)
- DSL字段仅文档(POCO有但引擎硬编码等效逻辑)
- LOW代码卫生项
--check输出现在会报告: excludes/conflicts引用了不存在的番型(如国标15个)
|
2026-07-04 23:11:29 +08:00 |
|
|
|
b7fb93d4e4
|
refactor: FanValue fallback 集中到 PhaseMachine.DefaultFanValue()
ScoreEngine.FanValue 和 PhaseMachine.GetFanValue 之前各自维护
一份相同的硬编码 fallback 列表。改为 ScoreEngine 调用
PhaseMachine.DefaultFanValue() 单例消除重复。
硬编码审计结论: 所有影响变体适配的硬编码已全部修复,
剩余的是麻将基础规则(碰2/杠3/暗杠4/13/14张)和牌编码定义。
|
2026-07-04 21:51:40 +08:00 |
|
|
|
4e9f06d5cd
|
fix: PhaseMachine硬编码>=8番 → 读DSL win_min_fan
4处修复:
- PhaseMachine构造函数新增 _winMinFan 参数
- GetLegalActions 中 discard win check (line 139): >= 8 → >= _winMinFan
- GetLegalActions 中 self-draw win check (line 165): >= 8 → >= _winMinFan
- CheckCondition 中的 can_win*_and_fan_ge_8 (line 97-98): >= 8 → >= _winMinFan
- MahjongRoom 传参: winMinFan=_rules.WinMinFan
效果: 国标胡牌率 30%→13% (baseFan<8的低番手牌被正确拦截)
58 tests pass, 5 variants 0 errors
|
2026-07-04 21:46:58 +08:00 |
|
|
|
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 |
|