12.3 从测试到决策
假设被证伪之后必须二选一:改规格还是改假设。用样本量扫描 N=24/100/500/2000/8000 诊断 H4(结局分布熵)——熵在 N=100 起越过 1500 毫比特、N≥500 稳定在 1718–1747,判定为测试设计缺陷、改假设而非改规格,story_spec.json 一行不改;真人测试标 X。
tag
假设被证伪之后必须二选一:改规格还是改假设。用样本量扫描 N=24/100/500/2000/8000 诊断 H4(结局分布熵)——熵在 N=100 起越过 1500 毫比特、N≥500 稳定在 1718–1747,判定为测试设计缺陷、改假设而非改规格,story_spec.json 一行不改;真人测试标 X。
把规格与内核内联进单文件 HTML,用 Playwright 无头注入 24 条选择序列真玩:逐条断言终局节点、结局与状态摘要与 Python 侧一致,两遍确定性 24/24,覆盖率 982‰,截图与批跑 JSON 落盘。真人玩家测试标 X。
一次可玩性测试如果没有假设,就只是点着玩。本节把《雾港夜航》这次测试要验的东西落成四条可证伪的命题——覆盖率、结局覆盖、跨宿主一致、分布熵,每条都给出可测整数、判据与证伪条件,并算出零假设基线 446‰。真人玩家测试需真实业务环境,命令行不可复现,标 X。
本章的「模拟玩家」是采样器,不是玩家模型:它只做路径选择策略(随机 / 贪心 / 覆盖导向),不建模动因、不做玩家分型。本节把这条分工写成一份可 lint 的 D 层声明表,再用 S 层脚本做硬断言,并与 11.1、11.2 真跑产物交叉核对,证明声明与脚本做的是同一件事。
同一份规格、同一个种子,只换「怎么选」这一条规则:随机、贪心、覆盖导向各跑 5000 条路径,量结局分布、结局分布熵与路径长度分布。实测贪心 5000 条里一次都没走到「真相」,而随机与覆盖导向都到达全部 5 个结局;再把三种策略按 7 档混合比扫描,只有纯贪心丢结局。全部指标都是 proxy。
给采样装上「策略」这个旋钮:随机(可播种 PRNG 选可用选项)、贪心(总是最大化好感度增量)、覆盖导向(优先走尚未覆盖的边)三种模拟玩家策略,在同一份规格下各走 10 与 200 条路径,对照覆盖率、结局数与路径长度区间。全部指标都是 proxy。
把 96 条采样路径在各场景上的经过次数画成 14×96 的矩阵热力图,cell 为整数、颜色按整数档位查表(档位定义在 config/nm_10_3_heatmap.json,全程无浮点调色)。矩阵元素之和 2544 恰等于所有路径的节点数之和;按结局排序后同结局的路径聚成一块。
把 48 个对话节点 / 56 条去重对话边按场景分层画成一张 SVG 分支图,边按是否被一条确定性路径走过着色:走过 25 条(446‰),未走过 31 条;随机采样 200 条即可铺满 56/56。布局坐标由场景序号与场景内序号直接算出,纯 xml.etree 建树、回读校验。
把前几章算出的张力曲线用纯 xml.etree 手写成 SVG:ET.Element / ET.SubElement 建树、ET.tostring 落盘,再用 ET.fromstring 回读校验合法性并断言元素计数。16 个节拍里一条确定性路径命中 11 个、跳过 5 个,全程整数、无浮点、不依赖任何第三方绘图库。
同一条选择序列推进两次,走出的状态必须逐位一致。本节用三条证据钉死这件事:确定性序列回放两次摘要相同、每个前缀从零重放等于全程记录、500 条采样序列各自回放两次逐条一致,并说明「回放无隐藏状态」到底在保证什么、为什么它是本卷所有度量的前提。
同一条路径可以写成三种编码:人可读的规范串、机器可比的紧凑整数元组、以及只对状态算的 FNV-1a 摘要。本节给出三种编码的构造规则,并用 Python 与 TypeScript 两侧对同一条路径算出逐位一致的结果,说明摘要绑定的是编码串而不是文本。
一次通关可以被拆成三种表示:玩家按下的选择序列、引擎走出的节点序列、以及每一步之后的完整状态轨迹。本节用《雾港夜航》的首选项确定性策略走完一条 25 步路径,逐步骤打印好感度、置位 flag、持有物品与 FNV-1a 状态摘要,并给出节点数等于选择数加一的整数不变量。
《叙事策划与叙事工艺》卷三《叙事体验与路径度量》目录:16 章 48 节,把玩家路径变成可度量的对象——路径的表示与采样、分支覆盖率与缺口、结局分布熵、张力曲线与 MAE、后果可见性、节奏密度、好感度曲线形状、一致性残差,以及反推与演化回归。本页给出分工说明、六档可运行性口径与全书 16 章 48 节完整清单。
《叙事策划与叙事工艺》卷三《叙事体验与路径度量》全 50 篇,也是三卷本的收官卷。卷一回答「一个故事能不能先被写成一份规格」,卷二回答「这份规格能不能被一台机器确定性地执行」,卷三回答「执行出来的那些路径能不能被度量,而且度量得诚实」。全书围绕虚构的三夜悬疑叙事《雾港夜航》与工具链 inkwell 展开,只读卷二交付的真源与内核、不新造字段:config/story_spec.json 的 beats(16 个节拍与整数张力)与 metrics(目标张力曲线、覆盖率目标 850‰、结局熵下限 1500 毫比特、两个 MAE 阈值)是本卷两个新的度量输入。第一部分(第 1–4 章)做路径、覆盖与平衡:一次通关的轨迹怎么编码成可回放的路径、随机/贪心/穷举三种采样策略、分支覆盖率的千分比口径与缺口定位、结局分布熵与分支偏斜、结局可达性的回归、后果可见性与假选择检测、选择密度与节奏;第二部分(第 5–9 章)做曲线、张力与一致性:张力从哪里来(叙事节拍而非机制动力学)、张力与释放的节拍计算、情感曲线的构造与目标曲线 MAE、代理指标的口径声明、叙事节奏与密度、节奏冲突检测、好感度随路径的变化与阈值触达分布、关系曲线形状分类、一致性残差与设定-行为对齐回归、失调告警阈值;第三部分(第 10–12 章)做可视化、模拟与测试:纯 xml.etree 出张力曲线、分支图与路径热力图、模拟玩家的路径策略与它对分布的影响、W 层 Playwright 路径批跑与断言、从测试到决策;第四部分(第 13–16 章)做反推、演化与收官:曲线异常点定位、参数到曲线的反推与其稳健性、规格演化的影响面与指标回归、叙事质量代理指标总表与「指标不能声称什么」,最后把三卷装配成一份规格三种消费的完整链路。按章节提供仿真、逻辑内核与原型;当前试点阶段已有复核记录,完整项目的配置、共享模块和交付验收仍在补齐。全书数字均来自本机实跑:单条确定性路径覆盖对话边 446‰、覆盖场景 9/14、覆盖节拍 11/16、只到达 1/5 结局,而 BFS 口径下 115 条对话边全部可达(1000‰),可达状态 9895423 个;全部指标均为 proxy,只做相对比较。
规格演化后(新增 flag、新增物品、新增好感度变量、新增节点),旧存档必须仍能读。本节实跑兼容性矩阵:四种新规格下旧存档全部读入成功并给出补默认值规则;迁移函数三条判据——缺失字段补默认、多余字段丢弃并报告、类型不符拒绝——逐条在本机实跑验证。
《叙事策划与叙事工艺》卷二《叙事引擎与分支系统》附录 A:把全卷 16 章 48 节散落的对话树节点与选项字段、嵌套数组条件文法与四类效果算子汇成索引表,给出本卷 S/P/W/D 四层共 43 个仿真脚本、31 个内核模块与 37 份产物的实盘清点,并附一段可跑的 TypeScript 对话树格式检查器——它连同三个注入负例证明格式约定不是纸面条文。
浏览器里走完同一条确定性策略路径(总是选第一个可用选项,共 25 个事件),读出终局状态,与 Python 侧产物比对 canonical 串与 FNV-1a 摘要。三侧锚点一致:摘要 4162796975、节点 e_lit、结局 灯守。只对整数状态写逐位一致。
给可玩原型挂一套稳定的 data-* 选择器契约:当前节点、每个选择按钮、四个好感度、已置位 flag、持有物品各有一个可寻址的属性。再用 Playwright 无头打开这页单文件 HTML,断言 DOM 已绘制、按钮数等于当前可用选项数、点击后节点推进。
把 config/story_spec.json 与 core/src/inkwell/engine.ts 一起内联进一个单文件 HTML,产出 web/dist/ne09.html。本节实测产物 41641 字节、script src 0、外部 http(s) 链接 0,给出零外部依赖的自检口径与双击即玩的最小交付形态。
四条必须恒为 0 的残差:钳位(可达状态与转移后都在 [0,100] 内)、初值(每个声明角色的 init 落在自身 range 内)、累积口径(新值恒等于 clamp(旧值 + add),set 不写好感度)、门限可达性(15 条门限均可跨过)。四条残差合计 0;lin 与 hai 有 affinity 声明却不在 state.vars,按「声明未用=报告,用了未声明=FAIL」报告。