docs: AI-readable DSL规范+番型识别器清单
dsl-specification.md: 新玩法生成指南 - 全部支持的DSL字段+有效值+约束 - 39种引擎识别番型名 - 支持的条件字符串/action/pre_hook - 已知限制清单 - 创建新DSL的完整流程+检查清单 fan-recognizer-inventory.md: 番型识别器清单 - 每种番型的检测条件 - 事件番型的标志位映射 - 未实现的番型列表(使用将得分为0) 验证: AI按规范生成的南昌麻将(fixed wildcard发财) → 100%合规零警告,正常运行
This commit is contained in:
286
docs/dsl-specification.md
Normal file
286
docs/dsl-specification.md
Normal file
@ -0,0 +1,286 @@
|
||||
# 麻将引擎 DSL 生成规范 (AI-readable)
|
||||
|
||||
## 概述
|
||||
|
||||
此文档描述 Card Game Engine 麻将规则引擎支持的所有 DSL 字段及其有效值。AI 代理在创建新玩法 YAML 文件时,**只能使用本文档列出的字段和值**。未列出的字段/值将被引擎拒绝或忽略,导致规则无法正确执行。
|
||||
|
||||
引擎通过双层检查确保合规:
|
||||
1. **能力注册检查** (`CapabilityRegistry.Check`):`requires` 列表中的每个能力必须已注册,否则拒绝加载
|
||||
2. **规则合规检查** (`ValidateRuleCompliance`):逐条检查番型名/条件/hook/模式是否被引擎支持,列出具体 gap
|
||||
|
||||
---
|
||||
|
||||
## 字段索引 (所有支持的 DSL 字段)
|
||||
|
||||
### game (必需)
|
||||
```yaml
|
||||
game:
|
||||
name: "玩法名称" # string, 任意
|
||||
type: mahjong # 固定值
|
||||
engine_type: mahjong # 固定值
|
||||
players: { min: 4, max: 4 } # 当前仅支持4人
|
||||
```
|
||||
|
||||
### requires (必需)
|
||||
```yaml
|
||||
requires:
|
||||
- deck.generator_mahjong
|
||||
- meldsolver.standard_win
|
||||
- meldsolver.seven_pairs
|
||||
- meldsolver.thirteen_orphans # 可选,需要十三幺时加
|
||||
- meldsolver.all_orphans # 可选,需要全不靠时加
|
||||
- meldsolver.double_dragon # 可选,需要一色双龙会时加
|
||||
- meldsolver.wildcard # 可选,有癞子时加
|
||||
- deck.flower_cards # 可选,有花牌时加
|
||||
- phase.mahjong_turn
|
||||
- phase.parallel_elimination # 可选,血战模式时加
|
||||
- phase.priority_arbitration
|
||||
- scoring.fan_exclusion
|
||||
- scoring.pre_hooks # 可选,需要结算前hook时加
|
||||
```
|
||||
|
||||
### deck (必需)
|
||||
```yaml
|
||||
deck:
|
||||
generator: mahjong # 固定值
|
||||
include_honors: true # bool, 是否含字牌(东南西北中发白)
|
||||
include_flowers: true # bool, 是否含花牌(春夏秋冬梅兰竹菊)
|
||||
total: 136 # 牌库总张数。108=无字无花, 136=有字无花, 144=有字有花
|
||||
```
|
||||
**注意**:`total` 必须匹配 `include_honors` + `include_flowers` 组合,否则引擎加载时抛异常。
|
||||
- `include_honors: false, include_flowers: false` → `total: 108`
|
||||
- `include_honors: true, include_flowers: false` → `total: 136`
|
||||
- `include_honors: true, include_flowers: true` → `total: 144`
|
||||
- wildcardCount>0 时额外加对应张数
|
||||
|
||||
### deal (必需)
|
||||
```yaml
|
||||
deal:
|
||||
cards_per_player: 13 # 固定值
|
||||
dealer_extra: 1 # 固定值
|
||||
```
|
||||
|
||||
### wildcard_rules (可选,有癞子时必填)
|
||||
```yaml
|
||||
wildcard_rules:
|
||||
type: fixed # "fixed"=指定牌当癞子 或 留空=编码50+的独立癞子牌
|
||||
tiles: [红中] # 当type=fixed时,b必须使用这些名称
|
||||
wildcard_encoding: 50 # 独立癞子牌的起始编码,默认50(范围50-59)
|
||||
behavior: substitute # 当前仅支持"substitute"
|
||||
fan_calculation_policy: optimal # 当前仅支持"optimal"
|
||||
scoring:
|
||||
per_wildcard_in_win: 1 # 每张癞子额外加番,0=不加
|
||||
```
|
||||
**固定癞子牌名映射** (tiles 字段可用值):
|
||||
| YAML 名称 | 引擎编码 |
|
||||
|-----------|---------|
|
||||
| 红中 | 35 |
|
||||
| 发财 | 36 |
|
||||
| 白板 | 37 |
|
||||
|
||||
**限制**:`behavior` 仅支持 `substitute`,`fan_calculation_policy` 仅支持 `optimal`。其他值会在合规检查中警告。
|
||||
|
||||
### win_condition (可选)
|
||||
```yaml
|
||||
win_condition:
|
||||
pair_must_be_258: true # bool, 是否要求将牌必须是2/5/8
|
||||
```
|
||||
|
||||
### fan_types (必需)
|
||||
```yaml
|
||||
fan_types:
|
||||
- name: 清一色 # 番型名(见下方"引擎识别的番型名")
|
||||
base_fan: 8 # 基础番数
|
||||
level: 8 # 等级(用于add_max/max_level策略)
|
||||
excludes: [缺一门, 无字] # 互斥番型(有此番型时不计算被排除的)
|
||||
conflicts: [暗七对] # 冲突番型(取番数高的)
|
||||
condition: "" # 条件(见下方"支持的条件字符串")
|
||||
```
|
||||
**注意**:`name` 必须是引擎能识别的番型名(见下方列表),否则得分为0。`condition` 必须是引擎支持的条件字符串。
|
||||
|
||||
### fan_stacking (必需)
|
||||
```yaml
|
||||
fan_stacking: add # "add"=所有番型相加, "max_level"=仅最高level, "add_max"=每level取最大后相加
|
||||
```
|
||||
|
||||
### max_fan (可选)
|
||||
```yaml
|
||||
max_fan: 100 # 单局最高番数上限,默认无限
|
||||
```
|
||||
|
||||
### win_min_fan (可选)
|
||||
```yaml
|
||||
win_min_fan: 8 # 最低胡牌番数要求(如国标8番起胡), 0=无限制
|
||||
```
|
||||
|
||||
### win_rule (可选)
|
||||
```yaml
|
||||
win_rule:
|
||||
ji_hu_self_draw_only: true # 鸡胡只能自摸(广东鸡平胡)
|
||||
```
|
||||
|
||||
### phases (必需)
|
||||
```yaml
|
||||
phases:
|
||||
- name: deal
|
||||
type: auto
|
||||
action: deal_cards # 标准发牌。有花牌+开局换花用 deal_cards_with_flowers
|
||||
next: play
|
||||
|
||||
- name: play
|
||||
type: mahjong_turn
|
||||
turn_order: counter_clockwise
|
||||
parallel_elimination: false # true=血战到底模式
|
||||
sub_phases:
|
||||
draw:
|
||||
type: auto
|
||||
action: draw_card
|
||||
on_draw_flower: replace # 摸到花牌时补牌(有花牌的变体)
|
||||
on_empty_deck: exhausted # 牌墙耗尽行为
|
||||
self_action:
|
||||
options:
|
||||
- { action: discard }
|
||||
- { action: an_kong } # 可选,有暗杠时加
|
||||
- { action: bu_kong, condition: has_punged_pair } # 可选,有加杠时加
|
||||
- { action: win, condition: can_win_tumo } # 可选,可自摸时加
|
||||
others_reaction:
|
||||
options:
|
||||
- { action: chi, priority: 1, condition: can_chi } # 可选,有吃时加
|
||||
- { action: pung, priority: 2, condition: has_two_same }
|
||||
- { action: ming_kong, priority: 3, condition: has_three_same }
|
||||
- { action: win, priority: 4, condition: can_win }
|
||||
- { action: pass, priority: 0 }
|
||||
priority_policy: highest_wins
|
||||
on_win: game_over
|
||||
end_conditions:
|
||||
- { type: player_wins, action: settle }
|
||||
- { type: deck_exhausted, action: draw_game }
|
||||
|
||||
- name: settle
|
||||
type: auto
|
||||
action: calculate_scores
|
||||
next: null
|
||||
```
|
||||
**action 选项**:可用的 self_action:discard/an_kong/bu_kong/win。可用的 others_reaction:chi/pung/ming_kong/win/pass。**不列出的 action 将不可用**。
|
||||
|
||||
**支持的条件字符串**:
|
||||
| 条件 | 含义 |
|
||||
|------|------|
|
||||
| `can_win_tumo` | 可以自摸胡 |
|
||||
| `can_win_tumo_and_fan_ge_8` | 自摸+番数≥8 |
|
||||
| `can_win` | 可以吃胡 |
|
||||
| `can_win_and_fan_ge_8` | 吃胡+番数≥8 |
|
||||
| `has_punged_pair` | 有碰过的对子(加杠) |
|
||||
| `has_two_same` | 手中有2张相同 |
|
||||
| `has_three_same` | 手中有3张相同 |
|
||||
| `can_chi` | 可以吃 |
|
||||
|
||||
### scoring (必需)
|
||||
```yaml
|
||||
scoring:
|
||||
mode: fan_table # 当前仅支持"fan_table"
|
||||
max_cap: 100 # 番数上限
|
||||
pre_hooks: # 可选,结算前执行的hook
|
||||
- name: check_hua_zhu # 检查花猪(仅血战)
|
||||
condition: deck_exhausted
|
||||
- name: check_ting # 检查听牌(仅血战)
|
||||
condition: deck_exhausted AND not hua_zhu
|
||||
```
|
||||
|
||||
### pre_hooks (可选)
|
||||
```yaml
|
||||
pre_hooks:
|
||||
- name: wildcard_count # 统计癞子数量
|
||||
description: "描述文字"
|
||||
```
|
||||
**支持的 pre_hook 名**:`wildcard_count`, `check_hua_zhu`, `check_ting`
|
||||
|
||||
### flower_rules (可选,有花牌时)
|
||||
```yaml
|
||||
flower_rules:
|
||||
on_draw: replace_and_draw # 摸花牌时补牌
|
||||
replace_tiles: BEFORE_GAME_START # 开局前换花牌(广东) 或留空=游戏中换花牌(国标)
|
||||
scoring:
|
||||
normal: 1 # 每张花牌基础分
|
||||
matching:
|
||||
value: 1 # 配对花牌额外分
|
||||
mapping:
|
||||
1: [春, 梅]
|
||||
2: [夏, 兰]
|
||||
3: [秋, 竹]
|
||||
4: [冬, 菊]
|
||||
```
|
||||
|
||||
### fu_flag (可选,过水机制,仅血战到底)
|
||||
```yaml
|
||||
# 在 phases.play 下:
|
||||
fu_flag:
|
||||
type: dirty_flag
|
||||
set_on: can_win_but_pass
|
||||
clear_on: next_discard_self
|
||||
effect: block_win_on_current_tile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 引擎识别的番型名 (39种)
|
||||
|
||||
以下番型名可以被引擎的结构识别器检测到。**使用这些名称时引擎会正确识别并计分,使用其他名称则得分为0。**
|
||||
|
||||
### 结构性番型 (始终可识别)
|
||||
清一色, 混一色, 字一色, 对对胡, 碰碰胡, 碰碰和, 暗七对, 七对,
|
||||
将一色, 带幺九, 全带幺, 混幺九, 缺一门, 无字, 平胡, 平和, 断幺九,
|
||||
全大, 全中, 全小, 全双, 大于五, 小于五,
|
||||
大四喜, 大三元, 小四喜, 小三元, 一色四同顺, 五门齐
|
||||
|
||||
### 特殊牌型 (在 CheckWin 特定路径中识别)
|
||||
十三幺, 全不靠, 一色双龙会, 连七对
|
||||
|
||||
### 状态相关 (需要游戏上下文)
|
||||
全求人, 门前清
|
||||
|
||||
### 事件番型 (需要引擎设置对应标志位)
|
||||
杠上开花, 海底捞月, 抢杠胡, 天胡, 地胡
|
||||
|
||||
### 条件番型
|
||||
癞子胡 (条件: hand_contains_wildcard)
|
||||
|
||||
### 兜底番型
|
||||
鸡胡 (当没有其他番型被识别时自动添加)
|
||||
|
||||
---
|
||||
|
||||
## 已知限制 (不会在合规检查中警告,但确实不可用)
|
||||
|
||||
1. **behavior**: 仅支持 `substitute`。不支持 `universal`/`multiplier` 等其他行为。
|
||||
2. **fan_calculation_policy**: 仅支持 `optimal`(单次回溯找可行解)。不支持 `average`/`fixed`。
|
||||
3. **scoring.mode**: 仅支持 `fan_table`。不支持 `multiply_score`。
|
||||
4. **牌库生成器**: 仅支持 `generator: mahjong`。不支持其他牌库类型。
|
||||
5. **玩家数**: 仅支持 4 人。不支持 2 人/3 人。
|
||||
6. **花牌计分**: `flower_rules.scoring` 的各字段都支持,但 `replace_tiles` 仅在广东鸡平胡(BEFORE_GAME_START)和国标(留空=on_draw replace)下正确。
|
||||
7. **pre_hooks**: 仅 `wildcard_count`/`check_hua_zhu`/`check_ting` 被引擎识别。其他名称会在合规检查中警告。
|
||||
8. **特殊花色**: 不区分风圈/箭刻/门风。番型 `圈风刻`/`门风刻`/`箭刻` 不在识别列表中。
|
||||
9. **番型组合: 一色三同顺/一色三节高/三色三同顺/花龙/组合龙/推不倒/无番和**: 不在识别列表中。
|
||||
|
||||
---
|
||||
|
||||
## 创建新 DSL 的完整流程
|
||||
|
||||
1. 从现有示例复制模板(推荐 `dsl-examples/wuhan.yaml`)
|
||||
2. 修改 `game.name`
|
||||
3. 选择 `deck` (牌数) 和 `requires` (能力)
|
||||
4. 选择 `fan_types` (仅使用上表格中的番型名,其他名称得分为0)
|
||||
5. 选择 `fan_stacking` 策略
|
||||
6. 选择 `phases` 中的 actions (不列出=不可用)
|
||||
7. 如果需要 wildcard/花牌/fu_flag,添加对应段
|
||||
8. 运行 `dotnet run --project Demo -- --dsl your_file --count 5` 验证
|
||||
|
||||
### 快速检查清单
|
||||
- [ ] `deck.total` 与 `include_honors/include_flowers` 匹配
|
||||
- [ ] `fan_types` 所有 `name` 在引擎识别列表中
|
||||
- [ ] `fan_types` 的 `condition` 在支持列表中(或为空)
|
||||
- [ ] `phases` 的 actions 在支持列表中
|
||||
- [ ] `wildcard_rules.behavior` = "substitute"
|
||||
- [ ] `scoring.mode` = "fan_table"
|
||||
- [ ] `pre_hooks` 仅含 known hooks
|
||||
- [ ] 加载时合规检查零警告
|
||||
82
docs/fan-recognizer-inventory.md
Normal file
82
docs/fan-recognizer-inventory.md
Normal file
@ -0,0 +1,82 @@
|
||||
# 番型识别器清单 (39种)
|
||||
|
||||
此文档列出引擎 `IdentifyFans(result, state?)` 能识别的全部番型名及其检测条件。
|
||||
|
||||
## 结构性番型 (基于手牌 melds/pair 结构检测)
|
||||
|
||||
| 番型名 | 检测条件 | 别名 |
|
||||
|--------|---------|------|
|
||||
| 清一色 | 全部数牌同花色,无字牌 | - |
|
||||
| 混一色 | 全部数牌同花色+含字牌 | - |
|
||||
| 字一色 | 全部为字牌 | - |
|
||||
| 对对胡 | 全部面子为刻子 | 碰碰胡, 碰碰和 |
|
||||
| 暗七对 | 全部面子为对子(来自七对路径) | 七对 |
|
||||
| 将一色 | 全部为2/5/8数牌 | - |
|
||||
| 带幺九 | 全部面子含幺九牌,将对为幺九 | 全带幺 |
|
||||
| 混幺九 | 全部为幺九或字牌,且两者都有 | - |
|
||||
| 缺一门 | 数牌最多2种花色 | - |
|
||||
| 无字 | 全部为数牌,无字牌 | - |
|
||||
| 平胡 | 全部面子为顺子 | 平和 |
|
||||
| 断幺九 | 全部为中张数牌(2-8,无幺九无字) | - |
|
||||
| 全大 | 全部数牌rank≥7 | - |
|
||||
| 全中 | 全部数牌rank 4-6 | - |
|
||||
| 全小 | 全部数牌rank≤3 | - |
|
||||
| 全双 | 全部数牌rank为偶数 | - |
|
||||
| 大于五 | 全部数牌rank>5 | - |
|
||||
| 小于五 | 全部数牌rank<5 | - |
|
||||
| 大四喜 | 4个风刻(东南西北) | - |
|
||||
| 大三元 | 3个箭刻(中发白) | - |
|
||||
| 小四喜 | 3个风刻+风将 | - |
|
||||
| 小三元 | 2个箭刻+箭将 | - |
|
||||
| 一色四同顺 | 4个完全相同的顺子 | - |
|
||||
| 五门齐 | 3种数牌+字牌共计4类 | - |
|
||||
|
||||
## 特殊牌型 (在 CheckWin 特定路径中,不经过标准面子提取)
|
||||
|
||||
| 番型名 | 检测路径 | 说明 |
|
||||
|--------|---------|------|
|
||||
| 十三幺 | TryThirteenOrphans | 13种幺九+1对 |
|
||||
| 全不靠 | TryAllOrphans | 147/258/369+字牌 |
|
||||
| 一色双龙会 | TryDoubleDragon | 同花色1-9各2张 |
|
||||
| 连七对 | TrySevenPairs(同色连7对) | 同花色的连续7对(未单独实现,由七对路径检测后通过DSL名匹配) |
|
||||
|
||||
## 状态相关番型 (需要传入 state 参数)
|
||||
|
||||
| 番型名 | 检测条件 |
|
||||
|--------|---------|
|
||||
| 全求人 | melds=0 且 allTiles≤2 (即全部副露) |
|
||||
| 门前清 | state.Exposed 全部为空(无碰/杠/吃) |
|
||||
|
||||
## 事件番型 (需要 state 中的事件标志位)
|
||||
|
||||
| 番型名 | 标志位 | 设置时机 |
|
||||
|--------|--------|---------|
|
||||
| 杠上开花 | state.IsKongDraw | 杠后摸牌时 |
|
||||
| 海底捞月 | state.IsLastTile | 摸牌前deck只剩1张 |
|
||||
| 抢杠胡 | state.IsRobbedKong | 加杠时 |
|
||||
| 天胡 | state.IsFirstTurn && state.DealerOnFirstTurn | 庄家首轮 |
|
||||
| 地胡 | state.IsFirstTurn && !state.DealerOnFirstTurn | 非庄家首轮 |
|
||||
|
||||
## 条件番型
|
||||
|
||||
| 番型名 | 条件 | 检测方式 |
|
||||
|--------|------|---------|
|
||||
| 癞子胡 | hand_contains_wildcard | state.Wildcards.CountWildcards(allTiles) > 0 |
|
||||
|
||||
## 兜底番型
|
||||
|
||||
| 番型名 | 触发条件 |
|
||||
|--------|---------|
|
||||
| 鸡胡 | 上述所有番型都未识别时自动添加 |
|
||||
|
||||
---
|
||||
|
||||
## 未实现的番型 (使用这些名称将得分为0)
|
||||
|
||||
以下番型引擎无法识别,在合规检查中会列出警告:
|
||||
|
||||
**结构类**: 绿一色, 九莲宝灯, 四杠子, 一色三同顺, 一色三节高, 三色三同顺, 三色三节高, 一色三步高, 三色三步高, 花龙, 组合龙, 推不倒, 无番和, 清龙, 三色双龙会, 全带五, 一色三高, 一色四高, 三风刻, 三杠, 四归一, 双暗刻, 双同刻, 双暗杠, 双明杠, 老少副, 连六, 喜相逢, 一般高, 幺九刻
|
||||
|
||||
**事件类**: 圈风刻, 门风刻, 箭刻, 不求人, 自摸(作为独立番型)
|
||||
|
||||
**条件类**: 边张, 坎张, 单钓将
|
||||
Reference in New Issue
Block a user