zhongchuyi commited on
Commit
683852a
·
1 Parent(s): 7644a65

feature: Prompt更新

Browse files
Files changed (3) hide show
  1. README.md +154 -63
  2. app.py +1 -0
  3. m_prompt.txt +20 -20
README.md CHANGED
@@ -9,88 +9,179 @@ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
13
 
14
- ## 这是什么
15
 
16
- MahjongGameDesigner 是一个“麻将玩法生成与迭代”工具,输出三类交付物:
17
- - **自然语言规则说明**(可直接给策划/制作/评审)
18
- - **mGDL v1.3**(结构化规则描述,用于规范化与落地)
19
- - **思维日志(设计日志)**(融合清单、冲突桥接、推演摘要、落地映射,便于人工复核)
20
 
21
- 工具提供两种关键能力:
22
- - **Analyse 模式(单问题迭代)**:通过多轮问答把需求场景收敛到可生成状态(不生成 mGDL)
23
- - **可控迭代(DesignState 驱动)**:基于上轮 DesignState 做最小修改,并限制本轮允许修改范围,减少漂移
 
 
 
 
 
 
 
 
 
24
 
25
- ## 快速开始(推荐流程)
 
 
26
 
27
- ### 1) 先Analyse 模式把需求收敛
28
- 1. 勾选:`Analyse 模式:单问题迭代完善需求(不生成mGDL)`
29
- 2. 在聊天框描述你的目标(例:想做“血战类 + 扎鸟机制 + 更强互动”的新玩法)
30
- 3. 模型每轮只会问你 1 个最关键问题,并输出:
31
- - 本轮增量思维日志(≤200字)
32
- - DesignState(JSON)
33
- - `READY_TO_GENERATE: true/false`
34
- 4. 当 READY 为 true(或你认为信息已经足够),进入第2步
35
 
36
- ### 2) 一键生成完整玩法交付物
37
- 点击按钮:`基于当前 DesignState 生成完整玩法`
 
 
 
 
 
38
 
39
- 生成完成后可下载:
40
- - `gdl_output.txt`(mGDL)
41
- - `narrative_output.txt`(自然语言规则)
42
- - `design_log_output.txt`(思维日志 / 设计日志)
43
 
44
- ### 3) 继续可控迭代(局部优化而不重写)
45
- 1. 取消勾选 Analyse 模式
46
- 2. 勾选:`启用可控迭代:基于上轮 DesignState 做最小修改`
47
- 3. 选择“本轮允许修改范围”(例如:仅优化创新机制)
48
- 4. 输入你的改动诉求(例:把主机制触发从“胡牌后”改成“听牌后”,并降低随机性)
49
 
50
- 系统会在输出后做次“范围越界”提示(软提示,不会中断生成),帮助你保持“最小修改、低漂移”的多轮迭代。
51
 
52
- ## 出与导出
 
 
 
 
 
53
 
54
- - 自然语言与 mGDL 会自动从模型输出中提取并保存到 `exports/` 下
55
- - 思维日志会从 `### 设计日志(创新推演摘要)` 段落提取并保存到 `exports/design_log_output.txt`
56
- - 在 Analyse 模式下不会导出上述文件(因为 Analyse 模式不生成完整交付物)
57
 
58
- ## 当前阶段的规则准确性重点(必读)
 
 
 
 
59
 
60
- 现阶段主要聚焦“既有机制组合”,但必须保证麻将底层物理逻辑准确(手牌守恒、吃碰杠轮次、牌墙转移等)。因此生成模式下请重点检查输出是否包含并一致:
61
- - 《动作—手牌变化—轮次影响表》
62
- - 3段《最小回合推演》(普通/碰/杠,每行标注手牌张数变化)
63
- - mGDL 的 `(invariants ...)` 中包含牌数守恒与“回合结束手牌恒为13”的约束
 
 
 
 
 
 
 
64
 
65
- ## 生成质量增强(默认开启)
66
 
67
- 为提升“玩法理解”与“创新落地”,系统默认会自动注入:
68
- - `m_prompt.txt`:系统提示词规范(含自检、最小修复、输出格式)
69
- - `麻将游戏mGDL通用语法_v1.3.txt`:mGDL v1.3 语法约束(用于保证输出形式)
70
- - 与用户输入最相关的少量参考玩法 `.md`(规则真理,RAG 语义参考)
71
- - `麻将机制说明.md`:机制词典(用于创新机制选型)
72
 
73
- ## 环境变量(可
 
 
 
 
74
 
75
- ### API / 模型
76
- - `DEEPSEEK_API_KEY`:API Key
77
- - `DEEPSEEK_BASE_URL`:OpenAI 兼容 Base URL
78
- - `MODEL_NAME`:模型名
79
 
80
- ### RAG / 参考注入
81
- - `ENABLE_REFERENCE_RETRIEVAL=1|0`:是否启用参考玩法检索注入(默认 1)
82
- - `REFERENCE_MAX_VARIANTS=3`:最多注入多少个参考玩法(默认 3)
83
- - `INJECT_REFERENCE_MGDL=1|0`:是否注入参考玩法 mGDL(默认 0;通常不建议,语参考以 .md 为主)
84
- - `INJECT_ALL_EXAMPLE_GDL=1|0`:是否额外注入全量示例 mGDL(默认 0,推荐)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- ### 校验与修复
87
- - `ENABLE_OUTPUT_VALIDATION=1|0`:是否对生成结果做静态校验提示(默认 1)
88
- - `ENABLE_AUTO_REPAIR=1|0`:非流式路径下是否自动触发一次“最小修改修复”(默认 0)
89
 
90
- ## 常见问题
 
91
 
92
- ### 为什么 Analyse 模式输出 mGDL?
93
- Analyse 模式的目标是“收敛需求”,每轮只问 1 个关键问题并更新 DesignState,避免边问边生成导致漂移。READY 后请用“一键生成”得到完整交付物。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- ### 为什么会看到“静态校验”提示?
96
- 生成模式下,系统会对输出做轻量检查(例如缺少 mGDL、缺少核心模块、缺少设计日志等)。这只是提示,不会阻断;你也可以在环境变量中关闭校验提示。
 
9
  pinned: false
10
  ---
11
 
12
+ # 🀄️ 麻将玩法创意工坊
13
 
14
+ > AI 驱动的麻将玩法设计与迭代工具
15
 
16
+ [![HuggingFace Space](https://img.shields.io/badge/🤗-HuggingFace%20Space-blue)](https://huggingface.co/spaces/Estazz/MahjongGameDesigner_work_v1)
 
 
 
17
 
18
+ ---
19
+
20
+ ## 功能亮点
21
+
22
+ | 功能 | 说明 |
23
+ |------|------|
24
+ | 🎯 **多阶段引导** | Analyse 模式逐步收敛需求,避免一次性生成偏差 |
25
+ | 🔄 **可控迭代** | 基于 DesignState 做最小修改,支持范围锁定 |
26
+ | 📊 **差异可视化** | 每轮修改自动对比,清晰展示变更点 |
27
+ | 🕐 **版本历史** | 支持回滚到任意历史版本 |
28
+ | 💡 **方案发散** | AI 给出多个候选方案供选择 |
29
+ | ✅ **输出校验** | 自动检测 mGDL 完整性和逻辑守恒 |
30
 
31
+ ---
32
+
33
+ ## 📖 完整使用指南
34
 
35
+ 👉 **[点击查看完整使指南 (USER_GUIDE.md)](./USER_GUIDE.md)**
 
 
 
 
 
 
 
36
 
37
+ 指南包含:
38
+ - 界面各部分详细说明
39
+ - 每个选项的作用和使用场景
40
+ - 推荐工作流程
41
+ - 高级功能教程
42
+ - 系统架构说明
43
+ - 常见问题解答
44
 
45
+ ---
 
 
 
46
 
47
+ ## 🚀 30秒快速开始
 
 
 
 
48
 
49
+ ### 方式:需求明确时
50
 
51
+ 直接在入框描述你的想法:
52
+ ```
53
+ 设计一个"血战+扎鸟"的麻将玩法,底座是四川血战,
54
+ 融入贵州捉鸡的扎鸟机制,胡牌后扎鸟独立计分
55
+ ```
56
+ 点击发送,等待 AI 生成完整玩法。
57
 
58
+ ### 方式二:需求不明确时
 
 
59
 
60
+ 1. ☑️ 勾选 **Analyse 模式**
61
+ 2. 输入初步想法:"想做一个有扎鸟的血战麻将"
62
+ 3. AI 会逐轮问你关键问题,帮你收敛需求
63
+ 4. 当显示 `READY_TO_GENERATE: true` 时
64
+ 5. 点击 **"基于当前 DesignState 生成完整玩法"**
65
 
66
+ ---
67
+
68
+ ## 📦 输出物
69
+
70
+ | 文件 | 内容 | 用途 |
71
+ |------|------|------|
72
+ | `gdl_output.txt` | mGDL v1.3 结构化描述 | 程序落地、规则引擎 |
73
+ | `narrative_output.txt` | 自然语言规则说明 | 策划评审、人工阅读 |
74
+ | `design_log_output.txt` | 设计日志 | 复核融合决策、追溯推演 |
75
+
76
+ ---
77
 
78
+ ## 🎮 核心控制选项说明
79
 
80
+ ### 可控迭代控制区
 
 
 
 
81
 
82
+ |项 | 说明 |
83
+ |------|------|
84
+ | **启用可控迭代** | 基于上轮 DesignState 做最小修改(推荐开启) |
85
+ | **Analyse 模式** | 单问题迭代收敛需求,不生成 mGDL |
86
+ | **修改范围** | 限制 AI 本轮可修改的内容范围 |
87
 
88
+ ### 细粒度范围控制
 
 
 
89
 
90
+ | 选项 | 说明 |
91
+ |------|------|
92
+ | **预设模式** | 使用预设的修改范围 |
93
+ | **自定模式** | 手动锁定特定字段或机制 |
94
+ | **软约束** | 越界时提示但阻断 |
95
+ | **硬约束** | 越界时阻断生成 |
96
+
97
+ ### 版本与方案
98
+
99
+ | 功能 | 说明 |
100
+ |------|------|
101
+ | **版本历史** | 查看和回滚到历史版本 |
102
+ | **方案选择** | 从 AI 给出的多个方案中选择 |
103
+ | **重新发散** | 让 AI 给出更多不同方向的方案 |
104
+
105
+ ---
106
+
107
+ ## ⚙️ 环境变量配置
108
+
109
+ 自部署时可通过环境变量调整:
110
+
111
+ ```bash
112
+ # API 配置
113
+ DEEPSEEK_API_KEY=your-api-key
114
+ DEEPSEEK_BASE_URL=https://api.deepseek.com
115
+ MODEL_NAME=deepseek-chat
116
+
117
+ # 功能开关
118
+ ENABLE_REFERENCE_RETRIEVAL=1 # 参考玩法检索
119
+ REFERENCE_MAX_VARIANTS=3 # 最多注入几个参考
120
+ ENABLE_OUTPUT_VALIDATION=1 # 输出校验
121
+ ```
122
+
123
+ ---
124
 
125
+ ## 🤔 常见问题
 
 
126
 
127
+ <details>
128
+ <summary><b>为什么 Analyse 模式不输出 mGDL?</b></summary>
129
 
130
+ Analyse 模式专注于"收敛需求",通过逐轮问答明确设计方向。当 `READY_TO_GENERATE: true` 时,使用"一键生成"按钮获取完整输出
131
+ </details>
132
+
133
+ <details>
134
+ <summary><b>为什么 AI 修改了我没要求改的部分?</b></summary>
135
+
136
+ 1. 确保开启"可控迭代"
137
+ 2. 选择更严格的"修改范围"
138
+ 3. 使用"细粒度范围控制"锁定关键字段
139
+ 4. 必要时回滚到之前的版本
140
+ </details>
141
+
142
+ <details>
143
+ <summary><b>如何保证规则逻辑正确?</b></summary>
144
+
145
+ 1. 检查输出中的"动作—手牌变化表"
146
+ 2. 验证"最小回合推演"是否闭环
147
+ 3. 确认 mGDL 的 invariants 包含守恒约束
148
+ 4. 参考设计日志中的推演记录
149
+ </details>
150
+
151
+ ---
152
+
153
+ ## 📚 内置参考资源
154
+
155
+ 工具已预加载以下资源:
156
+
157
+ - **mGDL v1.3 语法规范**
158
+ - **麻将机制说明词典**(50+ 常见机制)
159
+ - **参考玩法库**:
160
+ - 四川血战/血流
161
+ - 红中麻将
162
+ - 长沙麻将
163
+ - 贵州捉鸡
164
+ - 广东100张/鸡平胡
165
+ - 武汉麻将
166
+ - 卡五星
167
+ - 等等...
168
+
169
+ 系统会根据你的输入自动检索最相关的参考玩法。
170
+
171
+ ---
172
+
173
+ ## 🛠️ 技术栈
174
+
175
+ - **前端**:Gradio 5.x
176
+ - **AI**:DeepSeek V3 / OpenAI 兼容 API
177
+ - **语言**:Python 3.10+
178
+
179
+ ---
180
+
181
+ ## 📝 License
182
+
183
+ MIT License
184
+
185
+ ---
186
 
187
+ *Made with ❤️ for Mahjong enthusiasts*
 
app.py CHANGED
@@ -575,6 +575,7 @@ with gr.Blocks(
575
  stop_info = gr.Markdown("", visible=False)
576
 
577
  # ====== 核心:流式提交回调(生成器) ======
 
578
  def on_submit(
579
  user_text,
580
  history_msgs,
 
575
  stop_info = gr.Markdown("", visible=False)
576
 
577
  # ====== 核心:流式提交回调(生成器) ======
578
+ #此函数为工具核心,处理用户发送消息的完整流程(模式判断-模型调用-解析与更新)
579
  def on_submit(
580
  user_text,
581
  history_msgs,
m_prompt.txt CHANGED
@@ -39,41 +39,41 @@
39
  **手牌定义**(引用 `<MECHANISM_LIBRARY>` 1.1 节):
40
  - **暗牌**:手中未公开的牌
41
  - **明牌组**:通过吃/碰/杠形成的公开牌组
42
- - **位置**:玩家"占用"的牌,**回合结束时恒为 13 个位置**
43
 
44
- **守恒公式**(按位置计算):
45
  ```
46
- 回合结束位置 = 暗牌 + 吃组×3 + 碰组×3 + 杠组×3 + 暗杠组×4 = 13
47
  ```
48
 
49
- **说明**:(直杠/补杠)第 4 张来自他人弃牌或补摸,只占 3 位置;暗杠 4全来自手牌 4 位置
50
 
51
  1. 默认节奏(来自 `<MECHANISM_LIBRARY>`,除非底座玩法A明确覆写):
52
  - 标准起手牌为 13 张;庄家开局可为 14(必须明确"仅首轮首家多1张")
53
- - 默认行牌节奏为 "摸 1 → 打 1",并在回合结束回到稳定牌数(通常为 13)
54
  2. 允许的例外(必须显式写入规则与表格,并保持闭环):
55
  - 吃/碰后:默认"只打不摸"(除非规则明确允许补摸/补牌)
56
  - 杠后:必须补牌(补摸/补花)后再打 1 张
57
- - 若引入"连续摸牌/摸三打三"等机制:必须明确本回合"摸 N → 打 N(或等价闭环)",并确保回合结束回到稳定牌数
58
  3. 禁止出现(硬性 FAIL):
59
  - 出了一张牌但手牌数量不变(未说明牌去向与替代来源)
60
- - 回合动作序列结束后手牌无法回到稳定值(例如 13→14→13 是最常见闭环;特殊机制也必须闭环
61
  - 摸/打/吃/碰/杠导致手牌或牌墙流转"凭空增减",无法在 transfer 与手牌净变化中解释
62
 
63
- **各动作位置变化速查**(引用 `<MECHANISM_LIBRARY>` 第节):
64
 
65
- | 动作 | 位置变化 | 回合结束位置 |
66
  | --- | --- | --- |
67
  | 摸牌→打牌 | 13→14→13 | 13 |
68
  | 吃/碰→打牌 | 13→14→13 | 13 |
69
- | 明杠→补摸→打牌 | 13→13→14→13 | 13 |
70
- | 暗杠→补摸→打牌 | 1313→14→13 | 13 |
71
- | 补杠→补摸→打牌 | 14→13→14→13(补杠发生在摸牌后)| 13 |
72
 
73
  ### B) 吃碰杠与轮次影响必须显式
74
 
75
  必须对齐 `<MECHANISM_LIBRARY>` 的基础逻辑(除非底座玩法A明确覆写且不破坏守恒):
76
- - 同一轮优先级:胡牌 > 碰牌杠牌 > 吃牌
77
  - 吃:仅能吃上家牌;碰/杠:可对任意玩家
78
  - 胡牌触发方式:以“自摸/点炮”为基础;若引入“抢杠胡/一炮多响”等,必须说明其如何归类到自摸/点炮以及对应结算与轮次处理
79
  - 行牌顺序:庄家 → 下家 → 对家 → 上家;若发生碰/吃,则由吃/碰者继续出牌;若发生杠,则由杠者补牌后继续出牌(出牌顺序不变,只改变“当前出牌权”)
@@ -134,10 +134,10 @@
134
  | 杠后碰 | 杠者补摸后打出的牌可被他人碰;碰成功则出牌权转移给碰者 |
135
  | 连续杠 | 允许补摸后选择再杠而非打牌;每次杠都需补摸,连续杠时只有最后一次打牌 |
136
 
137
- **连续场景位置守恒公式**:
138
- - 连续 N 次碰:最终位置 = 13(每次碰+3明牌,打1张,净增2位置×N,但暗牌相应减少)
139
- - 连续 N 次明杠:最终位置 = 13(明杠不额外占位置)
140
- - 连续 N 次暗杠:最终位置 = 13 + N(每次暗杠额外占1位置)
141
 
142
  #### 抢杠胡完整流程
143
 
@@ -191,13 +191,13 @@
191
  - 剩余玩家继续按原顺序行牌
192
  - 牌墙摸完或仅剩一人时结束
193
 
194
- 若引入上述复杂场景,必须在《最小回合推演》中额外提供对应场景的推演段落(≤8 行),标注每步的位置数与出牌权归属。
195
 
196
  ### D) mGDL invariants(硬性)
197
 
198
  `(invariants ...)` 至少包含:
199
  - `tile_conservation`:总牌数守恒(与 tileset.total 一致)
200
- - `hand_size_stable`(或等价表达):声明行牌阶段“回合动作序列结束后手牌回到稳定值(通常 13;首轮庄家 14 仅在首次打出前成立)”
201
 
202
  ---
203
 
@@ -311,7 +311,7 @@ Analyse 模式输出格式固定为(必须严格遵守):
311
  "players": 4,
312
  "scoring_mode": "multiplier|fan_system|hybrid",
313
  "tileset": {"suits":["wan","tong","tiao"],"honors":0,"special_tiles":[],"total":108},
314
- "core_constraints": ["手牌守恒:回合结束回到13","牌数守恒:所有区域之和=TotalTiles"],
315
  "mechanics": [
316
  {"name":"机制名","type":"core|aux","phase":"setup|play|settle|global","trigger":"...","cost":"...","reward_or_penalty":"...","counterplay":"...","mgdl_path":"extensions.special_mechanics.mechanic_cards.<ID>","transfer_path":"from: X to: Y|none"}
317
  ],
 
39
  **手牌定义**(引用 `<MECHANISM_LIBRARY>` 1.1 节):
40
  - **暗牌**:手中未公开的牌
41
  - **明牌组**:通过吃/碰/杠形成的公开牌组
42
+ - **回合结束**:玩家持有牌数(暗牌 + 明牌组),**无杠时恒为 13 张,每有 1 杠则 +1 张(首轮庄家首次出牌前为 14 张)**
43
 
44
+ **守恒公式**(按实际牌数计算):
45
  ```
46
+ 回合结束牌 = 暗牌 + 吃组×3 + 碰组×3 + 杠组×4 = 13 + 杠组数
47
  ```
48
 
49
+ **说明**:杠组为 4 张;杠后补摸 1 张再打 1 张,使回合结束牌数比无杠多 1
50
 
51
  1. 默认节奏(来自 `<MECHANISM_LIBRARY>`,除非底座玩法A明确覆写):
52
  - 标准起手牌为 13 张;庄家开局可为 14(必须明确"仅首轮首家多1张")
53
+ - 默认行牌节奏为 "摸 1 → 打 1",并在回合结束回到稳定牌数(无杠为 13;每有 1 个杠 +1
54
  2. 允许的例外(必须显式写入规则与表格,并保持闭环):
55
  - 吃/碰后:默认"只打不摸"(除非规则明确允许补摸/补牌)
56
  - 杠后:必须补牌(补摸/补花)后再打 1 张
57
+ - 若引入"连续摸牌/摸三打三"等机制:必须明确本回合"摸 N → 打 N(或等价闭环)",并确保回合结束回到稳定牌数(13 + 杠组数)
58
  3. 禁止出现(硬性 FAIL):
59
  - 出了一张牌但手牌数量不变(未说明牌去向与替代来源)
60
+ - 回合动作序列结束后手牌无法回到稳定值(无杠 13;有杠 13 + 杠组数
61
  - 摸/打/吃/碰/杠导致手牌或牌墙流转"凭空增减",无法在 transfer 与手牌净变化中解释
62
 
63
+ **各动作牌数变化速查**(引用 `<MECHANISM_LIBRARY>` 第 1.2 节):
64
 
65
+ | 动作 | 牌数变化 | 回合结束牌数 |
66
  | --- | --- | --- |
67
  | 摸牌→打牌 | 13→14→13 | 13 |
68
  | 吃/碰→打牌 | 13→14→13 | 13 |
69
+ | 明杠→补摸→打牌 | 13→14→15→14 | 14 |
70
+ | 暗杠→补摸→打牌 | 14→14→15→14 | 14 |
71
+ | 补杠→补摸→打牌 | 14→14→15→14(补杠发生在摸牌后)| 14 |
72
 
73
  ### B) 吃碰杠与轮次影响必须显式
74
 
75
  必须对齐 `<MECHANISM_LIBRARY>` 的基础逻辑(除非底座玩法A明确覆写且不破坏守恒):
76
+ - 同一轮优先级:胡牌 > 碰牌/杠牌(同级,除非规则另设优先) > 吃牌
77
  - 吃:仅能吃上家牌;碰/杠:可对任意玩家
78
  - 胡牌触发方式:以“自摸/点炮”为基础;若引入“抢杠胡/一炮多响”等,必须说明其如何归类到自摸/点炮以及对应结算与轮次处理
79
  - 行牌顺序:庄家 → 下家 → 对家 → 上家;若发生碰/吃,则由吃/碰者继续出牌;若发生杠,则由杠者补牌后继续出牌(出牌顺序不变,只改变“当前出牌权”)
 
134
  | 杠后碰 | 杠者补摸后打出的牌可被他人碰;碰成功则出牌权转移给碰者 |
135
  | 连续杠 | 允许补摸后选择再杠而非打牌;每次杠都需补摸,连续杠时只有最后一次打牌 |
136
 
137
+ **连续场景牌数守恒公式**:
138
+ - 连续 N 次碰:最终牌数 = 13
139
+ - 连续 N 次明杠:最终牌数 = 13 + N
140
+ - 连续 N 次暗杠:最终牌数 = 13 + N
141
 
142
  #### 抢杠胡完整流程
143
 
 
191
  - 剩余玩家继续按原顺序行牌
192
  - 牌墙摸完或仅剩一人时结束
193
 
194
+ 若引入上述复杂场景,必须在《最小回合推演》中额外提供对应场景的推演段落(≤8 行),标注每步的��数与出牌权归属。
195
 
196
  ### D) mGDL invariants(硬性)
197
 
198
  `(invariants ...)` 至少包含:
199
  - `tile_conservation`:总牌数守恒(与 tileset.total 一致)
200
+ - `hand_size_stable`(或等价表达):声明行牌阶段“回合动作序列结束后手牌回到稳定值(无杠 13;每有 1 杠 +1;首轮庄家 14 仅在首次打出前成立)”
201
 
202
  ---
203
 
 
311
  "players": 4,
312
  "scoring_mode": "multiplier|fan_system|hybrid",
313
  "tileset": {"suits":["wan","tong","tiao"],"honors":0,"special_tiles":[],"total":108},
314
+ "core_constraints": ["手牌守恒:回合结束回到13+杠组数","牌数守恒:所有区域之和=TotalTiles"],
315
  "mechanics": [
316
  {"name":"机制名","type":"core|aux","phase":"setup|play|settle|global","trigger":"...","cost":"...","reward_or_penalty":"...","counterplay":"...","mgdl_path":"extensions.special_mechanics.mechanic_cards.<ID>","transfer_path":"from: X to: Y|none"}
317
  ],