Rule JSON 格式说明¶
本文说明后端当前支持的规则 JSON 结构。对应 Rust 类型定义位于 src/domain/rule_engine.rs。
1. 顶层结构¶
规则文件顶层是一个 JSON object,包含 5 个主要字段:
字段含义:
classes:系统运行时对象类型定义,目前固定需要包含player、card、tablecardsets:牌型定义cardset_comparisons:跨牌型比较规则match_flow:对局主流程end_flow:结算流程
后端校验要求:
classes必须包含player、card、tablecardsets至少有 1 个- 所有名字不能重复,且不能为空
2. classes¶
2.1 结构¶
每个 class 结构如下:
{
"default_properties": {
"属性名": {
"type": "int | enum",
"default": 0,
"config": []
}
},
"user_properties": {},
"methods": {}
}
说明:
default_properties:内置属性user_properties:规则作者自定义属性methods:对象方法
当前后端支持的属性类型只有:
intenum
其中:
int只需要type和defaultenum除了type和default外,通常还需要config
2.2 enum 属性格式¶
{
"point": {
"type": "enum",
"default": 1,
"config": [
{ "id": "enum-point-1", "display": "A", "value": 1 },
{ "id": "enum-point-2", "display": "2", "value": 2 }
]
}
}
后端实际使用的是:
defaultconfig[*].value
display 主要给前端显示用。
3. methods¶
对象方法结构:
说明:
parameters:参数定义returns:返回类型,可以是int、enum或nullflow:方法流程图
方法流程中会用到:
25:方法开始26:返回
4. cardsets¶
牌型定义格式:
{
"1": {
"name": "Single",
"properties": {},
"build_flow": {},
"compare_flow": {},
"successors": []
}
}
字段含义:
name:牌型名称properties:牌型识别结果上可附带的整型属性build_flow:判断一组牌是否匹配该牌型compare_flow:同牌型比较逻辑successors:当当前牌型可压过哪些其他牌型时,填对方牌型的id
4.1 build_flow¶
用途:识别当前选牌是否属于该牌型。
常见结构:
27开始- 若干取值/比较节点
16条件分支28返回匹配结果
28 节点格式:
说明:
result = 1表示匹配成功result = 0表示匹配失败properties中目前只会提取整型字段
4.2 compare_flow¶
用途:同牌型比较,判断 A 和 B 谁赢。
常见结构:
29开始- 若干计算节点
16条件分支30返回比较结果
30 节点格式:
说明:
result = 0表示 A 胜result = 1表示 B 胜
这里的 A / B 在运行时分别对应:
- A:当前出牌
- B:上一手成功出牌
5. cardset_comparisons¶
用于跨牌型比较。
格式:
匹配方式基于牌型 name,不是 id。
后端逻辑:
- 如果当前出牌与上一手牌型不同
- 优先查
cardset_comparisons - 如果没查到,再看
successors
6. FlowGraph 格式¶
所有流程图字段都使用同一种结构:FlowGraph
{
"1": {
"type": 17,
"content": {
"next": "2"
}
},
"2": {
"type": 21,
"content": {
"timer": 30,
"next": "3"
}
}
}
每个节点的基础结构:
字段说明:
type:组件类型编号content:组件配置count:主要给发牌组件用next:直接后继节点
后端还会从 content 里读取:
nextnext_truenext_false
因此很多旧规则会把跳转写在 content 里,这也是兼容的。
6.1 节点编号约定¶
- 流程入口必须存在编号
"1" - 所有跳转目标必须存在
- 分支缺失
next_true或next_false会报错
7. 当前后端支持的组件类型¶
当前支持:
1方法调用2排序4赋值5取集合第 N 个元素6属性访问7集合长度8/9常量整数10四则运算11集合逻辑12二元逻辑13非14比较15牌型判断16条件分支17对局开始18进入结算19洗牌20发牌21等待玩家出牌22等待玩家做选择23结算开始24写入单个玩家结算结果25方法开始26返回27牌型构建开始28牌型构建返回29牌型比较开始30牌型比较返回
8. 常用引用值¶
后端在求值时支持一些保留引用。
8.1 对象引用¶
table_0:牌桌对象player_0、player_1...:按运行时座位顺序访问玩家玩家:当前玩家
注意:
- 当前玩家不是按用户真实 ID 决定,而是按运行时座位顺序决定
8.2 牌组/牌型引用¶
cardscard_setselectedCardsselected_cards
以上都表示“当前传入牌组”。
牌型比较流程中:
A/a/cardsetA/currentRound:当前出牌B/b/cardsetB/previousRound:上一手成功出牌
8.3 表属性¶
后端会额外维护一些运行时表属性,例如:
player_indexsettlement_indexcur_max
规则里也可以自己定义额外的 table.user_properties。
9. 属性访问规则¶
type = 6 的 content 结构:
operator 含义:
0:对象属性访问1:组件结果属性访问2:集合映射属性访问
示例:
表示读取节点 2 结果的 point 属性。
10. 比较运算符¶
type = 14 时,operator 当前含义为:
0:等于1:大于2:小于3:大于等于4:小于等于
11. 最小可运行样例¶
当前仓库内有两个样例文件:
test.json:历史规则样例test2.json:当前极简可手测样例
建议以后排查规则问题时优先从 test2.json 开始,因为它结构最小、链路更短。
12. 编写建议¶
- 优先使用 ASCII 属性名,如
point、suit、winner_index - 不要依赖前端导出时的乱码中文键名
- 分支节点
condition不要留空 - 组件结果取属性时,确认
type = 6的operator是否应为1 - 牌型比较返回值里,
0是 A 赢,不是“false” - 如果规则需要版本化,建议直接把 JSON 放进仓库,而不是只放在工作区根目录