118 lines
3.6 KiB
Markdown
118 lines
3.6 KiB
Markdown
# ADR-002: Roll 结果先转组合事实,再匹配规则
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Date
|
|
|
|
2026-06-22
|
|
|
|
## Context
|
|
|
|
Lucky Dice 第一版普通 Roll 默认使用 2 颗骰子,但 PRD 明确要求骰子数量必须来自配置,并保留后续扩展到 3 颗、4 颗或特殊关卡自定义骰子数量的能力。
|
|
|
|
普通 Roll 的规则也不只包含精确组合。首批规则需要覆盖:
|
|
|
|
- 双 Clover 触发 Lucky Dice。
|
|
- 单 Clover 加数字发放普通奖励并提供 bonus。
|
|
- 纯数字结果发放普通奖励。
|
|
|
|
后续还需要支持对子、N 连、指定面数量、点数和区间、骰子数量约束等统计型规则。
|
|
|
|
如果规则匹配直接读取固定位置,例如左骰和右骰,就会把第一版默认值 `2` 固化到系统里。后续扩展 3 骰时,规则、测试和日志都要大范围修改。
|
|
|
|
## Decision
|
|
|
|
普通 Roll 结果必须先转换成结构化 `ComboFacts`,再进入规则匹配。
|
|
|
|
`ComboFacts` 至少包含:
|
|
|
|
- `DiceSetType`
|
|
- `DiceCount`
|
|
- 原始 `Faces`
|
|
- `FaceCounts`
|
|
- `NumberValues`
|
|
- `NumberSum`
|
|
- `CloverCount`
|
|
- `HasClover`
|
|
- `NormalizedKey`
|
|
- `OrderedKey`
|
|
|
|
普通规则默认使用无序事实。`2 + clover` 与 `clover + 2` 必须归一为同一个 `NormalizedKey`。只有规则明确声明需要顺序语义时,才允许读取 `OrderedKey`。
|
|
|
|
matcher 必须基于 `ComboFacts` 中的统计信息判断,不能依赖固定的左骰、右骰字段。
|
|
|
|
## Alternatives Considered
|
|
|
|
### 在规则里直接读取骰子数组位置
|
|
|
|
示例:`faces[0] == clover && faces[1] == clover`。
|
|
|
|
优点:
|
|
|
|
- 第一版双骰场景写起来最快。
|
|
- 不需要单独的事实构建层。
|
|
|
|
缺点:
|
|
|
|
- 默认写死 2 骰。
|
|
- 顺序和无序语义容易混乱。
|
|
- 后续 3 骰、4 骰会导致规则分支爆炸。
|
|
- 测试会绑定实现细节,而不是外部行为。
|
|
|
|
结论:拒绝。它与可配置骰子数量的核心要求冲突。
|
|
|
|
### 只生成字符串组合 key
|
|
|
|
示例:直接生成 `2_clover`、`clover_clover`,规则只匹配 key。
|
|
|
|
优点:
|
|
|
|
- 对精确组合匹配足够简单。
|
|
- 配置和日志易读。
|
|
|
|
缺点:
|
|
|
|
- 难以表达统计型规则,例如至少 2 个 Clover、三连、点数和区间。
|
|
- matcher 会被迫解析字符串,或者需要维护大量派生 key。
|
|
- 原始骰子和统计信息缺失,不利于调试。
|
|
|
|
结论:拒绝作为唯一事实来源。`NormalizedKey` 可以作为 `ComboFacts` 的一个字段,但不能替代完整事实。
|
|
|
|
### 由每个 matcher 自己计算统计信息
|
|
|
|
优点:
|
|
|
|
- 不需要统一事实模型。
|
|
- matcher 内部可以自由处理自己的需求。
|
|
|
|
缺点:
|
|
|
|
- 多个 matcher 重复遍历和统计。
|
|
- 不同 matcher 对 key、顺序、数字值的理解可能不一致。
|
|
- 日志难以记录统一的匹配输入。
|
|
|
|
结论:拒绝。统一事实模型更利于一致性和测试。
|
|
|
|
## Consequences
|
|
|
|
正向影响:
|
|
|
|
- 后续扩展骰子数量时,核心规则仍基于统计事实工作。
|
|
- 规则匹配器可以用少量通用 matcher 覆盖多种组合语义。
|
|
- 日志能记录原始结果、统计结果、无序 key 和有序 key。
|
|
- 测试可以直接验证外部行为和事实结构。
|
|
|
|
代价和约束:
|
|
|
|
- 第一版需要实现并测试 `ComboFactBuilder`。
|
|
- `ComboFacts` 字段需要保持稳定,不能随意为某个规则塞临时字段。
|
|
- Lucky Dice 特殊结果不能进入普通 `ComboFactBuilder`。
|
|
|
|
## Related Documents
|
|
|
|
- [Lucky Dice 核心流程需求](../Requirements/lucky-dice-core-flow-requirements.md)
|
|
- [Lucky Dice 核心流程规格](../Specs/lucky-dice-core-flow-spec.md)
|
|
- [ADR-001](adr-001-separate-normal-and-lucky-dice-sets.md)
|