Skip to content

交互案例 · 规则级复盘

当规则书与引擎各说各话 ​

未通过·《罪恶摇摆:白垩与黑铁》v2.0.0·证据截止日 2026-10-21

TL;DR ​

一款四人社交推理游戏可以在引擎层完全自洽,却依然不具备上线条件。在 v2.0.0 的这次复核里,引擎回归是绿的——11/11 条断言全部通过——但玩家看到的 规则书、操作控件和引擎实际执行的是三套不同的游戏。两处错位是玩家可见的阻断 项,一处是精度问题,一处是尚未定论的措辞问题。真正值得记录的不是崩溃,而是 静默的信息差:每一层单独看都合理,所以当玩家围绕一个引擎永远不会支付的 数字做规划时,系统不会抛出任何异常。

背景 ​

《罪恶摇摆:白垩与黑铁》是一款 H5 社交推理游戏:1 名真人 + 3 名 AI,四张面具 无放回分配,五轮“公开发言 + 暗中行动”,黑白天平随每次选择摇摆。嫌疑值 clamp 在 [0, 100],达到 100 即被处刑;只有存活者参与最终排名。

上线材料包含四份文档:

文档它定义的真相层
01_角色与规则设定.md玩家在角色揭示、规则教学和商店页读到的内容
02_核心数值与结算引擎.md引擎实际计算的内容
03_三剧本回归测试记录.md自动回归覆盖了什么,以及明确不覆盖什么
04_发行说明.mdv2.0.0 改了什么,以及哪些事项被声明为就绪

src/App.jsx 里还有一份引擎与玩家可见角色文案的内联副本。回归记录明确写了: 这份内联副本不与 src/gameEngine.js 做一致性比较。这个缺口后面会变成关键证据。

信息差 ​

玩家和引擎对同四条规则持有不同模型。四处差异都不会产生错误提示。

规则玩家可见文案引擎 / 源码后果
告密修女隐藏胜利刺杀得分 +500assassinationBonus = 50;回归断言也是 50玩家把一次处刑的价值高估了 10 倍
无面公爵伪装可选勾选框;不勾选就不伪装首次 EXECUTE_BLACK 自动伪装;context.disguiseRequests 从不被读取玩家无法选择“不伪装”
摄政王背叛加成“背叛动作 +75%”+75% 绑定 EXECUTE_BLACK,而非 SABOTAGE_BOTH;术语表却把“背叛”定义为 SABOTAGE_BOTH按字面推演 0 × 1.75 = 0;意图需要设计确认
公爵平衡加成“差值 ≤10 达到上限 +50”max(0, round(50 − diff));差值 10 → 40在文案宣称的上限边界上出现 10 分预期差

前两项是阻断项,因为玩家能看见或操作错误的东西。第三项是未决项,因为两种读法 都成立,材料没有说明设计意图。第四项是精度缺陷:它改变了玩家看到的收益,但在 本次审计的剧本里不改变“完美平衡”评级,也不改变冠军归属。

五轮复盘 ​

这是一次规则级复盘,不是录制下来的玩家对局。下表中的每个数字都能从上述材料 复现;重点在于展示这些缺口如何在多轮中叠加。

轮次玩家如何规划引擎实际做什么玩家观察到什么
1抽到告密修女;因为隐藏条件写着 +500,主动推动一次处刑结算 +50一个看起来合理、实际错误的得分明细;没有警告
2抽到无面公爵;选择 EXECUTE_BLACK,且不勾选伪装首次黑王座行动自动伪装,并把 dukeDisguiseUsed 置为 true桌面被告知这是白圣堂行动;“不伪装”的计划被静默覆盖
3抽到摄政王;按“背叛动作”期待 +75%只对 EXECUTE_BLACK 加成;SABOTAGE_BOTH 的信用收益为 0,无法被放大取决于实际选择,可能没有加成,也可能出现意料之外的加成
4用公爵把信用差控制在 10,期待吃到 +50 上限计算 max(0, round(50 − 10)) = 40在文案宣称的边界上少了 10 分
5按规则书重建最终排名只对存活者按引擎值排名叙事与记分板不一致,但两者都“合法”

真正的问题是叠加效应。单处错位可以被当成显示 bug;五轮里出现四处错位,玩家就 无法建立可靠的心智模型——而每个子系统都在报告自己成功。

为什么 11/11 没抓到 ​

回归记录对自己的边界是诚实的:

本次回归仅覆盖 src/gameEngine.js 的引擎数值与台词生成,不覆盖玩家可见文案、 UI 控件到引擎入参的传递,也不覆盖两份引擎副本之间的一致性。

而发布失败恰好就住在这三层里。断言 #5 检查的是 assassinationBonus = 50——引擎 常量——所以它会通过,而玩家可见的隐藏条件仍然写着 +500。这套回归从未打开角色 揭示弹窗,从未点击伪装勾选框,也从未把 App.jsx 的内联副本与 gameEngine.js 做 diff。

对发布包逐条审计得到 20 个检查项:

处置数量例子
通过15四动作基础表、clamp 范围、天平阈值、处刑顺序、存活者排名
阻断2修女 +500 vs +50;伪装勾选框未接线
非阻断1差值 10 时公爵上限 +50 vs +40
未决1摄政王“背叛”措辞与实现不一致
待核1契约测试、文案快照、双副本 diff 均未编写

测试设计 ​

  1. 冻结证据截止日,并按受众列出每个来源:玩家可见、引擎实现、测试证据、 发行说明、UI 源码。
  2. 在读任何结论之前先建规则矩阵。每一行记录文案值、实现值、测试证据和 玩家可见后果。
  3. 独立复算边界值。不要用一个绿色断言去验证玩家读到的那行文案。
  4. 按可达性与暴露面分类:
    • 玩家能看见或操作 → 阻断;
    • 当前版本不可达 → 待核;
    • 措辞歧义 → 未决,不能静默算“通过”。
  5. 补三条缺失的契约测试:
    • 勾选伪装 → 触发伪装;
    • 不勾选 → 不伪装;
    • 同一局第二次请求 → 不生效。
  6. 为每个角色揭示和每条规则文案增加快照测试。
  7. 在 CI 中 diff App.jsx 内联引擎与 src/gameEngine.js。在被证明完全一致之前, 重复引擎就是第二个真相源。

证据 ​

检查项结果
2026-10-22 重跑 npm run sim11/11 PASS
发布包检查项20
玩家可见阻断2
非阻断精度缺陷1
未决措辞问题1
伪装勾选框契约测试0
文案快照测试0
双引擎 diff 测试0
无来源支撑的结论0

内联 UI 副本不是假设:App.jsx 自带一份 HIDDEN_WIN_CONDITIONS.NUN 字符串, 里面仍是 +500;它的 processTurn 也会在未读取 useDisguise 状态的情况下 自动把 dukeDisguiseUsed 置为 true。引擎文件和 UI 文件都可以相对自己的测试 “正确”,却依然互相矛盾。

结论 ​

未通过。 引擎足以通过它自己的回归,但发布不够。两个玩家可见的阻断项仍未 关闭:修女隐藏条件写错了支付数字,公爵伪装控件并没有控制任何东西。摄政王措辞 仍需要设计决策,公爵上限需要修文案。

绿色回归只证明它覆盖的那一层,不是发布证书。可复用的规则是: 测试层与层之间的契约,而不只是碰巧有测试的那一层。

整改 ​

事项责任角色关闭条件
修女隐藏条件 +500 → +50(或改引擎为 500 并重新平衡)玩法/逻辑工程师角色弹窗截图显示 +50;回归仍通过
把勾选状态写入 context.disguiseRequests;引擎只在请求时伪装客户端 + 玩法工程师勾选/不勾选/重复请求三条契约测试通过
澄清摄政王“背叛”或改绑加成设计 + 玩法工程师设计确认单 + 最终文案
修正公爵上限文案(差值 0 → +50,每增加 1 点减 1)玩法工程师文案快照通过
增加文案快照与双引擎 diffQA未来任何漂移都会让 CI 失败

相关 ​

Crystaria (with Paw and Kyle)