11.3 数值的可复现
可复现分两层。机制层的 digest 是纯整数与布尔的规范化 JSON,跨语言必须逐字相等;表现层的像素位移由宿主浮点算出,浮点加法不满足结合律,换个求和顺序末位就变,只能按声明容差断言。本节给出两侧逐字相同的 digest 字符串,并演示为什么禁写「逐位相等」。
category
可复现分两层。机制层的 digest 是纯整数与布尔的规范化 JSON,跨语言必须逐字相等;表现层的像素位移由宿主浮点算出,浮点加法不满足结合律,换个求和顺序末位就变,只能按声明容差断言。本节给出两侧逐字相同的 digest 字符串,并演示为什么禁写「逐位相等」。
增长与衰减曲线在整数域上必须闭式与递推逐项一致,否则同一份规格在不同宿主会跑出两条曲线。本节用有理数 115/100 与 90/100 各跑 11 项,证明保分子的递推与闭式逐项恒等,而逐步地板除的朴素递推会累积漂移:十级之后差 8,幂运算必须走 BigInt 才不丢位。
浮点让同一份规格在两个宿主上算出不同的末位,跨语言一致就无从谈起。本节给出三条跨语言纪律——预算与阈值一律整数、随机一律自实现可播种 PRNG、config 禁浮点——并把暴击判定、倍率、千分比、向上取整、整数幂逐条改写成整数写法,用一张对照表列出两语言的同一结果。
「卡住」有四种形态:无合法动作的死锁、有动作却不改变状态的停滞、资源不可达目标的不可解、以及撞上上限的截断。本节把 4.3 的搜索器包成一张判据表,用四个夹具各命中一类,并钉死结论的可靠性边界——solvable=true 有证据恒可靠,false 只在 exhausted=true 时才是证明。
第 1、3、4 章各散落着一部分不变量:资源边界、守恒、状态封闭。本节把它们收成一张 8 条的可执行清单,逐条给出整数判据与一个故意造违反的负例。清单在真实轨迹的 26 个状态上全 true,8 条负例全被判 false——把「机制自洽」从零散断言变成可回归的验收面。
状态空间不是「所有可能的状态」,而是「从开局真的能走到的状态」。本节用广度优先展开动作序列的前缀树、以 digest 去重,把《灰烬牌库》12 步内的可达集真的枚举出来:7637 个状态,只占粗粒度上界的十亿分之 250;再拿 8 类「永远不该出现」的状态去扫,命中数全为 0。
机制每回合产生十几次状态变化,玩家只看见其中一部分——「哪些分量被呈现」这份名单,就是机制与玩家的接口。本节把《灰烬牌库》的状态按呈现与否分成 8/12 两堆,从轨迹里抽出 17 条反馈事件与逐回合的净位移/总位移:最强回合 29、最弱回合只有 6,还有 4 条指令的反馈是「什么都没发生」。
上一节的三张表里,状态分量按「会不会被花掉」再分一次,就得到四种资源:能量、手牌、生命、格挡;而目标就是这四种资源的期末余额。本节给一张每回合的收入-支出表,用《灰烬牌库》跑一局账:能量入 12 出 10 余 2、格挡产 10 只吸收 6、伤害 50 有 5 点被溢出截断,账本末态与引擎摘要逐字对拍一致。
机制不是一段文字描述,而是三张能逐字段核对的小表:动词(玩家能做什么)、规则(动词受什么约束、状态怎么变)、状态(规则作用在什么上)。本节用《灰烬牌库》的 play_spec.json 把三张表从规格里解析出来——2 个动词、6 个动作符号、13 条规则、12 个状态分量,并查出 0 个孤儿分量与 2 个没人消费的参数。
《游戏设计》卷一《玩法机制与可执行规格》目录:16 章 48 节,把玩法设计文档写成可执行规格 play_spec.json,让同一份规格被 S 层仿真、P 层确定性内核、W 层可玩原型与 B 层相变扫描四处消费,产出逐字一致的摘要。本页给出七处分工说明、六档可运行性口径、《灰烬牌库》机制总览与全书 16 章 48 节完整清单。