18 KiB
D2 数据配置与数值表 设计推演
状态:concluded(未闭合项见文末「开放问题」)· 本文只装"为什么"——
design/gdd/d2-data-config.md只收本文的结论。 修订时新增问题节,不删旧节(历史即依据)。
问题 1:为什么要有 D2——数值集中一处、schema 先行、单点发放?
广度分析
- 候选 A:参数随各系统代码硬编码——收益:少一层间接;代价:调一次难度要改五处代码、战斗无法用固定种子复现、headless 自动化测试无从谈起。
- 候选 B:集中数值表但允许多入口读取——代价:副本绕过校验,热重载换新值时副本不知情,单一事实源名存实亡。
- 候选 C(采纳):数值表单一事实源 + ConfigDB 单点类型化读取 + schema 先行、数值回填。
深度分析
schema 先行使 D2 能在设计顺序第 1 位交付而不阻塞下游:结构(自定义 Resource 类,字段带类型/范围/默认/注释)由 D2 定死,数值由 owner 系统 GDD 按设计顺序回填——先有格子、后填数字。本 GDD 只定数据结构、注册表与校验模式,不替任何系统定平衡。
综合判断
design 件设计目的、系统范围与规则 1/2/3 即本结论:玩法数值零代码字面量、取数只经 ConfigDB、全部表两件套交付。
问题 2:为什么 fail-fast 无软回退、唯一软着陆只给 debug 热重载?
广度分析
- 候选 A:软回退(出错用默认值或上一好值带病运行)——代价:错误数值上线比崩溃更伤(P1/P2 信任底线),且放行带病数值会使 CI 冒烟失去意义。
- 候选 B(采纳):加载期与运行期一律致命中止;唯一例外 = debug 热重载校验失败时保留旧表停留 Ready——不杀运行中的调试会话。
- 校验通道候选:单通道(测试侧无法断言致命路径——Godot 无进程内拦截 push_error/push_warning 的 API)vs 校验双通道 collect_only(采纳:游戏通道致命、测试通道收集不升级,诊断收集器承载冒烟断言与四元组去重状态)。
深度分析
release 构建的致命表现(引擎默认错误路径的实际行为)尚未验证,显式 deferred 到首次 release 导出 checklist——设计顺序第 1 位时无导出模板可依赖。headless 下走 --script 协议独立进程非 0 退出,因为同阶段无主场景可依赖,脚本须 extends SceneTree 以获得 quit(code)、autoload 须由脚本显式实例化。
综合判断
规则 6、校验双通道表、状态机 Failed 两路径与 EC16 即本结论;校验严格度不设 knob(fatal 写死)。
问题 3:难度行解析为什么 floor + warning、无兜底无外推?
广度分析
- 候选 A:default 行兜底——代价:配置缺口被静默吃掉,难度断档不可见。
- 候选 B:clamp / 线性外推——代价:超表成长语义是 C3 owner 公式的职责,D2 越权定义成长。
- 候选 C(采纳):floor 到不超过请求坐标的最近已有行 + 非精确命中记 warning(四元组去重);实体键精确匹配不近似;越域请求由前置守卫致命拦截。
深度分析
核心判据:进度坐标可以就近近似,"是哪种敌人"不能近似——身份近似会静默改变遭遇构成、损害 P2 归因。warning 定位是开发期异常信号而非审计工具(防刷屏去重是刻意的);难度审计由离线曲线导出工具承担(headless 导出 resolve(level 1..N × depth 0..M) 矩阵供 diff,C3 期交付——排期倒挂见开放问题 #5)。depth 分量永不 ceil 的保证来自 EC15 锚行校验:防"入口天灾"(入口请求静默 floor 到深行造成难度突刺),写死开、非 knob,重议须走本 GDD 显式修订流程。
综合判断
design 件「难度行解析」的 R1 结论与表达式、missing_type 枚举(base_ceil 恒记规则由本分类推导)与 EC4/EC5/EC14/EC15 即本结论。
问题 4:流种子派生为什么是纯函数、为什么不用运行时 hash()?
广度分析
- 候选 A:运行时
hash()混合流名——代价:Godot 不承诺 hash 跨版本稳定,黄金向量与跨版本复现失去意义。 - 候选 B:scope 自增值直接作种子——代价:同 master_seed 下不同流的同序号 scope 互相碰撞。
- 候选 C(采纳):
( SALT_s XOR wrap64(master_seed + scope × GOLDEN_RATIO) ) AND 0x7FFFFFFFFFFFFFFF——每流互异奇盐、黄金比例乘数、wrap64 自然回绕、掩码收尾。
深度分析
中间积本就越界(乘数 0x9E3779B97F4A7C15 > 2^63,scope=1 即回绕)——这是设计依赖的语义而非缺陷,故禁止 float 中间量(53 位尾数必丢精度)、禁止对中间量用 %(带符号取余语义易误用)、禁止"主动修复溢出";三个常量均 ≥2^63,GDScript 十六进制字面量按二补数解析为负,故统一用分段表达式书写。跨 master_seed 的全局单射由鸽笼原理数学排除,不做声明。INT64_MIN 致命而非归一化:abs 在 int64 对 INT64_MIN 恒等回绕,输出掩码抹掉 bit 63 使其与 0 静默别名(实测与 0 在全流种子逐一相等——掩码本身是规约的一部分);负 scope 同理会与 scope+2^63 经掩码别名,故 debug 断言中止。计数器永不重置、不随关卡/图序重置——否则不同关卡的同序号图会得到相同种子;set_master_seed 仅许全流计数器全零时调用——冒险中途重播种会静默清零计数器,击穿同冒险无碰撞前提与 D3 快照语义。
综合判断
design 件 R2 结论、公式、实现级规约三行、黄金向量表(AC-3 常量依据,经独立复算验证)即本结论;状态线独立不变式(reload 不触碰 RNG——若按状态机对称性在 reload 时重置 RNG 将击穿 AC-4)同理成立:派生只依赖盐/master_seed/scope,与表数据无关。
问题 5:RNG 为什么封闭三流、增流为什么要过 P1 评审?
广度分析
- 候选 A:各系统自建 RandomNumberGenerator /
randomize()——代价:不可复现,回放/审计/自动化测试全废。 - 候选 B:流自由注册——代价:流复用破坏可复现隔离,未知名流静默产生。
- 候选 C(采纳):封闭具名流(board_gen / reward_roll / encounter),增流 = 改代码 + P1 支柱评审(随机须有界、可见或可推理)——有意设卡。
深度分析
三流的 scope 事件绑定是各自消费者契约的一部分:board_gen = 每次生成新扫雷图(A1 换图时);reward_roll = 每次 board install 批(格奖励批 + 清图奖励批,B4 AC-1 为契约源);encounter = 每场战斗实例化恰一 scope(begin_battle 实例化期、扫雷开始前——unit_count 区间均匀骰在挖掘决策域之外,P1 合规;C3 遭遇随机化批增流,registry 已登记)。derive_at 纯函数不推计数器——预览取数不污染正式序列,杜绝预览类取数的平衡 Heisenbug。同帧多系统请求同一流允许(EC13):Godot 主线程玩法逻辑单线程假设成立,open_stream 各自取号按调用顺序串行生效,不引入锁。玩法随机(如结算浮动)D2 不预置——任何系统若需要,自带方案走增流通道并通过 P1 评审(原 R4 显式排除裁决:玩法平衡公式与玩法随机都不在 D2,归 owner 系统 GDD)。
综合判断
规则 5、封闭流表、取数入口表与 EC12/EC13 即本结论;combat_var 类玩法随机预置流不设基础设施。
问题 6:debug override 链为什么是这五条边界?
广度分析
- 覆盖位置候选:各系统自读 override 源——代价:gameplay 可见 override 来源、多点校验漂移;采纳 = 覆盖判定与存储内聚 ConfigDB(规则 2 单点)。
- key 空间候选:任意路径含进度表行寻址(如
difficulty.(2,0).hp)——v1 收窄为仅单行全局表字段,行寻址语法登记为后续扩展。 - release 形态候选:运行时碰巧不生效——采纳 = 结构性不存在(不加载、不注册任何 override 源,恒等是结构保证)。
深度分析
override 值类型与范围复用 schema 校验逻辑——防止 debug 会话注入越界值污染平衡基线(EC11);未知 key 同样 warning + 忽略。debug 谓词做成可注入形式(OS.is_debug_build() 之外引入 feature 标签闸,例 sim_release),AC-8 的模拟以此为基础;"release 不加载 override 源"的结构保证验证本身 deferred 到首次 release 导出 checklist(AC-18)。override 仅为运行时状态,永不回写 .tres。
综合判断
design 件 R3 结论与边界五条即本结论。
问题 7:体验锚点论证——"玩家永远不该注意到的地基"凭什么撑 P1/P2?
广度分析
- D2 无专属玩家幻想:P1"我算对了"的掌控感来自 A1/A2 可推理设计,P2 的延迟兑现感来自 B1 可见结算;D2 只提供三种消极保障。
- 手感稳定("改数字不改代码"):全部影响手感的数字集中一处可调 + 热重载即改即验——"测试数据驱动平衡"的开发方式,任何"这轮玩起来不对劲"都能快速修正且不引入新毛刺。
- 公平可信("同决策必同结果"):可复现是开发侧信任底线(回放/审计/自动化测试),不等于玩家侧可推理;玩法随机零预置(走增流通道 + P1 评审)。
- 难度可信(P4,"越下越险由结构保证"):数值表天生带(关卡序号, 节点深度)两维——难度曲线可审计、可回溯,而非散落各处的魔法数字。
深度分析
难度第三轴"精英/Boss 修饰"已定稿难度 = f(关卡序号, 节点深度, 精英/Boss 修饰)(game-concept),但修饰语义归 C1/C3——D2 只做 DifficultyTable 的 elite_/boss_ 前缀命名空间预留与 Boss=Dmax 行约定,不定义任何修饰数值、不预写修饰枚举;两键定不了精英性的节点形态(如分支地图同深度并存精英与普通节点)允许改键,按接口漂移修订规则回写(与 MetaTable 同等豁免待遇);A1 OQ6 是 C1 定稿时的强制重审门。DifficultyTable 乘数域 [0.1,10] 已 registry 预登记;越域 clamp+warning 是 registry 登记的显式例外——组合事故非配置事故,非 fail-fast 场景。
综合判断
design 件设计目的四条承诺、规则 4 轴归宿表与 DifficultyTable 占位行即本结论。
问题 8:已裁决争议与数值锚定论证汇总
广度分析
- 单行全局表先例链:ActionEconomyTable 立先例 → HeroTable / RewardConfigTable / SettlementTable 沿用(无成长语义的表允许只放一行);MetaTable 为元进度轴豁免,C4 可改键。
- weaken = −65(值域 [60,85]——B1 F0 裁决,条款 2 锚闭合);defense_up = −30(减伤墙批 C3 投值,叠满两层 −60 帽——B3/registry 同批)。
- HeroTable atk = 6 原型锚(provisional 归 C3);atk = 0 加载拒绝——"0 基线 × 百分比增益恒零"死锁自 schema 层杜绝(基础攻击恒存在,消费面 = 主角战斗段先手攻击)。
- RewardConfigTable 标定:active_p0 = 0.4(供给控制器注入概率初值,首件之后每张新板——E[战斗获取] ≈ 1 标定目标,归 C3);active_decay = 0.5 指数递减 0.4→0.2→0.1→…(加难杠杆候选 0.6 随 C3 OQ7 扫描);p_min = 8(默认根最低刀 power——K≥1 供给闸刀力下界 floor_supply_missing);k_dmg = 0 = F5 断言关闭——刀保底语义由供给控制器战斗首件保证取代,no_damage_row 后闸托底。
深度分析
两处溯源缺口在案:EnemyTable MVP 行值(goblin 18HP / 4ATK 等)出自原型 REPORT、出处待查(义务 #5);HeroTable max_hp MVP 值出处待查(义务 #6)。provisional 值在 owner 定稿前不视为平衡事实;定稿后删除调参表清单对应条目,值的事实登记归 owner GDD 与 registry——已定稿占位参考值(标中旗 / 清图奖励 / 状态四行 / 奖励池等)已随各 owner 定稿清退。
综合判断
数值事实留 design 调参表与 registry,锚定论证收于本节;胜场成长机制去留(+25% HP / +1 ATK——反雪球问题)仍待 C3 裁决(义务 #7,在案未闭合)。
附录 A:评审与审计元数据
- 评审:lean 门禁 systems-designer / qa-lead;full 评审 + 同日 re-review 含 game-designer / creative-director,CD-GDD-ALIGN 终裁 Approved——评审日志
design/gdd/reviews/d2-data-config-review-log.md。 - 双向一致性核对明细(与 systems-index 依赖分层表核对一致):A1←A4,D2 · B2←D2 · B4←D2 · B1←A3,B2,B3,B4,D2 · C2←C3,D2 · C4←D3,C2,D2 · C3←D2,B2 · Foundation 含 D2;C2 / B1 / B4 / C4 ← D2 四条边已补入索引依赖分层表;B4←D2 边已按 B4 定稿收窄——A2 事实经 B1 转化零直接接口、B3 为验收锚关系非运行时边。
已闭环对账义务(历史审计,design 不再列):
| 编号 | 内容 | 对侧 | 状态 |
|---|---|---|---|
| 1 | ActionEconomyTable 跨字段校验(任一动作成本 ≤ ap_per_round)条件性夹具登记 | A3 | 已登记(schema 类别承载,随 A3 冒烟) |
| 2 | VariationTable 跨字段校验 hide_numbers⇒safe_nonzero 夹具 variation_mask_constraint | A4 | 已激活 |
| 3 | StatusEffectTable effect_id 悬空引用校验(条件性夹具——首个含引用字段的 owner 回填时补) | B3 / B4 | 已激活(B4 defense_up 首引,夹具 b4_dangling_effect) |
| 12 | 双向一致性四条边补入索引依赖分层表(C2 / B1 / B4 / C4 ← D2) | systems-index | 已完成 |
开放问题
| # | 问题 | owner |
|---|---|---|
| 1 | headless 测试载体终稿:MVP 用 --headless --script 冒烟(本 GDD 决策);gdUnit4 是否在 Technical Setup 引入并迁移冒烟用例 |
Technical Setup 阶段(systems-index 门禁增补记录项) |
| 2 | 编辑器内表文件热重载自动化(当前仅 debug 键触发;低优先) | 未指派 |
| 3 | 数值表显示名的本地化 | D6 |
| 4 | C4 MetaTable 并入 ConfigDB 还是独立 autoload(倾向并入) | C4 GDD |
| 5 | 难度曲线导出工具(R1 审计的离线载体):headless 导出 resolve 矩阵脚本,C3 期交付——排期倒挂:BoardGenTable 可推理率曲线自 A1(第 5 位)起回填,A1 定稿前须有临时抽查载体(入 systems-index 门禁记录) | C3 GDD 登记排期 |
| 6 | systems-index 树形概要行仍写"九张表单一事实源",与本 GDD 现行十张表 schema 目录(AuxItemTable 转正后)不一致——索引行归 systems-index 维护批修订,本件不代改 | systems-index 维护批 |
去向映射(零丢失可审计证据)
| 原文章节 / 表 | 落点 |
|---|---|
| 头部块(状态/版本/支柱/层级/一句话) | design 头部块;评审行 → analysis 附录 A |
| 速览表(定位/拥有/不拥有/上游/下游/硬约束) | design 设计目的 / 系统范围(含硬约束行)/ 依赖与输出 |
| 存在理由·策略·定位三行 | design 设计目的 + analysis 问题 1、7 |
| 体验锚点表 | design 设计目的四条承诺;论证 → analysis 问题 7 |
| 全局流程(三链路字符画 + 出口分发表) | design 核心循环 |
| 核心规则 1 / 2 | design「统一取数与调试覆盖」规则 1 / 2 |
| 核心规则 3 / 4 + 表形状 / 轴归宿两表 | design「表结构与回填」 |
| 核心规则 5 + 流表 / 取数入口表 | design「随机数服务」 |
| 核心规则 6 / 7 / 8 + 错误两类表 | design「加载·校验·热重载」 |
| 规则 6 实现参照——校验双通道表 | design「加载·校验·热重载·校验双通道」 |
| 枚举·十张表目录 / 未回填占位表 / MVP 内容行 | design「表结构与回填」三个子节 |
| 枚举·RNG 流 | design「随机数服务·封闭流与取数入口」(与规则 5 流表去重合并,内容一致) |
| 枚举·missing_type | design「难度行解析·missing_type」 |
| 枚举·致命错误类别 | 并入 design 规则 6 错误两类表(段序违例/池映射悬空/p_perfect 越域三覆盖项并入加载期行) |
| 枚举·override key 空间 | 并入 design R3 边界②(key 形态与支持域内容完全重合) |
| 数值结论与推导 R1(结论/推导/变量/Example/去重键) | design「难度行解析」(结论 + 表达式 + 变量 + 验算);取舍与审计论证 → analysis 问题 3 |
| 数值结论与推导 R2(结论/公式/实现级规约/变量/黄金向量) | design「随机数服务·R2 流种子派生」;机理与候选论证 → analysis 问题 4 |
| 数值结论与推导 R3(结论 + 边界五条) | design「统一取数与调试覆盖·调试覆盖链」;候选取舍 → analysis 问题 6 |
| 数值结论与推导 R4 显式排除 | design 系统范围不负责清单 + 规则 5 增流通道;论证 → analysis 问题 5 |
| 状态(状态机表 + 不变式) | design「加载·校验·热重载·状态机」 |
| 状态·RNG 生命周期 / 快照三行 | design「随机数服务·RNG 生命周期与快照」 |
| 边界情况 EC1–EC16 | design「加载·校验·热重载·边界情况」(编号不变) |
| 依赖表 + 三行注记 | design 依赖与输出;双向一致性核对明细 → analysis 附录 A |
| 登记与对账义务 #4–#11(在案) | design 依赖与输出·登记与对账义务表 |
| 登记与对账义务 #1 / #2 / #3 / #12(已闭环) | analysis 附录 A |
| 呈现与 UI 面 | design「呈现与 UI 面」 |
| Tuning Knobs·D2 自身 knobs + 交互 / 清退注记 | design 调参表·D2 自身 knobs |
| Tuning Knobs·九张表逐表字段行 | design 调参表·表 schema 逐表字段行 |
| 验收标准·测试口径 + AC-1–AC-18 | design 验收标准(编号不变) |
| 开放问题 1–5 | analysis 开放问题(编号不变);#6 为本次迁移新登记的跨文档不一致 |
| 数值锚定论证(weaken/defense_up/atk/active_p0/p_min/k_dmg 等) | analysis 问题 8(数值事实本身留 design 调参表与 MVP 内容行表) |
| 版本历史全部行 | design 版本历史(原行全保留,追加 v2 迁移行) |