4.3 关系的不对称与变化
关系有两副面孔:一副是矩阵里静态的不对称,一副是沿路径动态的变化。本节用自实现 MINSTD 采样 20000 条路径,输出 4 个好感度变量的「初始值 → 终局值」分布表,断言整数不变量残差为 0,并统计出 15 对关系里 13 对不对称、2 对差距达到 20。
tag
关系有两副面孔:一副是矩阵里静态的不对称,一副是沿路径动态的变化。本节用自实现 MINSTD 采样 20000 条路径,输出 4 个好感度变量的「初始值 → 终局值」分布表,断言整数不变量残差为 0,并统计出 15 对关系里 13 对不对称、2 对差距达到 20。
故事里谁对谁是什么态度,规格里只有派系立场这一层。本节把 6 个角色之间的关系写成 6×6 整数矩阵,校验形状、值域与对角线,再用派系立场推出先验做一致性交叉检查:30 个非对角格里 2 个偏离先验,15 对里有 13 对不对称,而派系立场本身却完全对称。
把卷一的三处消费——穷举、执行、度量——在同一份规格上串成一次预演:穷举给出覆盖率与结局可达性,执行把 seed 采样的第一条路径推进到底并算出整数 digest,度量给出张力 MAE 与结局分布熵。S 层与 P 层对同一路径复算,digest 逐位相同。
从改规格到产物核对是一条五环流水线:结构校验与语义校验、规格解析、跨语言摘要、内核门禁、产物核对。本节给出逐条本机真跑过的命令,用一个 S 层驱动把五环串成一次执行,再用一个 P 层门禁断言这份报告不是过期快照,并给出各环的时间账与取舍口径。
把一致性写成一个整数:残差 = 规则失配 R + 立场失配 S + 秘密失配 K + 对齐缺口 A,本案例基线为 7。本节是 B 层:对门有效阈值、好感度初值、节拍密度做扰动,观察残差与覆盖率的相变——残差在阈值越过 60 时阶跃(7→9),覆盖率随初值连续下滑(−10 时 895‰),输出 3 条软告警但 exit 0。
「叙事失调」通常是主观说法:故事说一套、玩法做一套。本节把它形式化为可判定的失配——设定声明的规则、立场与秘密,与规格实际允许玩家做的事之间的差集,给出 R / S / K 三类判定口径,并在《雾港夜航》上实跑得到残差 6。这是代理指标,只做相对比较,不声称「更协调」。
一致性 = 声明域与使用域的差集。S 层脚本输出一张一致性报告表:14 项逐项给出声明数、使用数、两个方向的差集与判定。实测「使用未声明」为 0;真实发现是 lin/hai 声明了 affinity 却不在 state.vars、d_lt_2 有 line_when 无 line_else,以及 7 个 flag 与 fog_glass 被写却从未被读。
死条件 = 条件引用的状态量在到达该节点前不可能取到所需值。判定用对话图上的可达区间前向不动点:区间过近似、不按条件剪枝,故「过近似都说够不着」才是真死条件。S 层复跑显示当前 0 个死条件;正文如实交代曾经有过的 4 个、各自的成因与修法。
结构校验只问图的形状:孤儿(无人指向且非起点)、断链(goto 指向不存在的节点)、死路(无选项且无结局标记)。S 层脚本对对话图与场景图逐类检测,实测三类缺陷均为 0;P 层用人为注入的三个负例断言检测器真的会开火,而不是只会返回空列表,起点则是唯一的豁免。
把全部 48 条台词与 115 个选项渲染成一张 163 行的文本表,每行一个键,内联进单文件 HTML,再用 Playwright 无头打开,断言台词条数、选项条数、空文本行数与键指纹,截图到 out/shots/,并验两遍渲染确定性。末尾重申本章的做 / 不做边界:本套只做文本的结构,不评价文本质量。
同一条台词记录在不同状态下渲染出不同变体,这是条件文本的全部含义。本节枚举两个条件节点的整个定义域:d_tc_2 两分支两条文本;d_lt_2 声明了 line_when 却没写 line_else,101 个状态枚举下来只得到一条文本——结构分流了,文本没分流。变体退化因此成了一个可数的缺口,修法是在规格里补声明,而不是改台词。
台词里出现的角色名与地点名,在规格里其实是一次变量查找。本节给出文本模板的唯一文法(占位、转义与未知占位回落),由规格三段拼出 24 个绑定的命名实体表,并渲染全部 48 条 line 与 115 条选项文本统计占位出现次数:行内占位 0 处、字段级占位 48 处、可模板化点 33 处。只做文本的结构,不评价文本质量。
把 48 个对话节点当成一张有向图,环、不可达节点、死路三类缺陷就都成了可判定的性质。本节用 DFS 三色标记找环、BFS 从起点算可达性与层号,实测三类缺陷均为 0:115 条选项去重后只有 56 条唯一跳转,5 个无出口节点全是结局,与 na_00 的 BFS 状态空间穷举口径互证。
对话节点是字段化的记录:节点层八个字段、选项层五个字段,其中 goto 是选项的独立字段而非效果算子。本节给出两张字段表,用 S 层脚本校验 115 条跳转全部命中已声明节点并输出节点度数表,再用 P 层测试断言未知选项被拒绝、推进是纯函数。
把好感度沿采样路径画成曲线后,「形状」也成了一个可分类的量:单调上升 / 先升后平 / 单调下降 / 波动 / 全程不变,五类互斥。S 层统计 2000 条路径的形状占比并用纯 xml.etree 出图,B 层把初始值整体上下扰动 ±10,观察门限跨越率的相变——−10 档新增 9 条死门,全程只软告警不硬失败。
阈值门就是条件里的 ['aff', 名, '>=', 整数]:它可能长在选项的 when、节点的 line_when 或结局的 when 上。S 层把全规格 15 条门限抽成一张表,在 20000 条采样路径上给出每条门限的跨越率、最高到达与缺口,基线 0 条死门;P 层断言门限未达时选项不可选、恰好达到时可选的边界行为。
好感度只有两个动作:从 characters[].affinity.init 起一个整数,之后每次写入都走 add 再夹回 [0,100]。S 层静态清点出 4 个变量共 66 次写入、8 种增量,并点出声明了却从不推进的 lin 与 hai;P 层用 300 条采样路径断言值域恒定,并以「把某个 add 放大到百万级仍被夹回」的负例证明 clamp 不是冗余算子。
本套的核心主张:台词文本不是规格的输入端,而是规格的一种渲染产物。同一条 dialogue 记录(line 加 line_when 加 line_else)在不同状态下渲染出不同台词。本节给出四分支渲染规则、用 d_tc_2 做最小演示、反向断言文本不进状态,并写死边界——只做文本的结构,不评价文本质量。
《叙事策划与叙事工艺》卷一《叙事结构与可执行规格》目录:16 章 48 节,把一个故事写成可执行规格 story_spec.json,让同一份规格被 S 层穷举、P 层确定性内核与 B 层参数扰动三处消费,产出逐位一致的状态摘要。本页给出七处分工说明、六档可运行性口径、《雾港夜航》规格总览与全书 16 章 48 节完整清单。
《叙事策划与叙事工艺》卷一《叙事结构与可执行规格》全 50 篇。它回答一个问题:一个故事能不能先被写成一份规格,再让台词文本成为这份规格的渲染产物?全书围绕虚构的三夜悬疑叙事《雾港夜航》与工具链 inkwell 展开,唯一真源是 config/story_spec.json 的十段字段:meta(三幕)、world(4 派系 stance 矩阵、14 个地点的解锁条件、6 条 lore 的揭示旗标)、characters(6 个角色的目标/恐惧/秘密/好感度/弧光)、beats(16 个节拍与整数张力)、scene_graph(14 个节点与 16 条边,其中 5 条带条件)、dialogue(48 个对话节点、115 个选项、5 个结局)、conditions(嵌套数组文法,6 种形式)、state(18 个 flag、4 个好感度、9 个物品)、endings 与 metrics。第一部分(第 1–4 章)把故事还原成结构:四个最小构成、九段骨架、文本是渲染的分工、字段全表与版本迁移、世界观与角色的形式化;第二部分(第 5–8 章)把结构还原成图与曲线:弧光的可达性、节拍与三种结构模型、场景图的可达性与解锁、分支拓扑与假选择判定;第三部分(第 9–12 章)把条件与数值写透:条件文法与写入域、状态变量的闭包检验、好感度阈值门与曲线形状、对话树的遍历与校验、文本模板与条件变体;第四部分(第 13–16 章)做校验与装配:结构/语义/一致性三层校验、叙事失调的形式化、工具链的目录分工与流水线,最后装配成一份规格三处消费的完整链路并交付卷二。按章节提供仿真、逻辑内核与原型;当前试点阶段已有复核记录,完整项目的配置、共享模块和交付验收仍在补齐。全书数字均来自本机实跑:可达状态 9895423 个,分支覆盖率 1000‰,不可达节点与不可达选项均为 0。