81 lines
7.4 KiB
Markdown
81 lines
7.4 KiB
Markdown
# ADR-0007: 全游戏随机流统一评估(RNG Single Stream Evaluation)
|
||
|
||
## Status
|
||
|
||
**已裁决:方案丙(并流 + 全事件日志)——2026-09-27 用户裁决,随批落地**。推荐案甲未被采纳,评估书正文保留原样作决策记录;丙的实施 = 统一随机流批(rng_service.gd 重写 + 七消费点迁移 + 单盐黄金向量重登记 + 事件日志会话制),验证与工单清单见文末「落地记录」。
|
||
|
||
背景:2026-09-27 用户在[关卡节点图生成](../../gdd/systems/冒险循环/关卡节点图生成.md)拍板点②两轮复裁终选「随机数统一用一个流」(全面执行),并拍板执行路径 = **先出本评估书再动手**、节点图特性实施排队其后。本评估书按用户要求如实给出:现行机制事实、统一流的真实改动面、三个备选与推荐。裁决本 ADR 后按裁决执行。
|
||
|
||
## Date
|
||
|
||
2026-09-27
|
||
|
||
## Context
|
||
|
||
### 用户动因(如实记录)
|
||
|
||
用户质疑链全程:①问「增流是什么、文档没说明」→ ②质疑「借流复现口径变含糊」论断:「如果所有的随机数获取都是有完整记录的,那不是都可以一一复现吗?我觉得你的理论不对」→ ③收到机制澄清(复现=主种子+计数器按位重推导、非日志回放)与两条代价说明后,仍两轮终裁「统一用一个流」。动因解读:用户重视**单一随机源的心智简洁**,对"七条流"的分栏结构存疑(直觉=繁琐),并认为完整记录即可复现一切。
|
||
|
||
### 现行机制事实(全部带代码锚)
|
||
|
||
| 事实 | 锚点 |
|
||
|---|---|
|
||
| 唯一主种子:冒险开始恰一次注入,禁中途重播种(全零断言) | `game/core/rng_service.gd:80-105` |
|
||
| 唯一派生公式族:derive(stream, scope) = mix64(SALT_s XOR (master + scope×GOLDEN)) | `game/core/rng_service.gd:61-77` |
|
||
| 七条流 = 七个盐值常量(同一公式、同一主种子) | `game/core/rng_service.gd:14-24` |
|
||
| 零旁路随机:randomize()/自建 RNG 硬性红线 | CLAUDE.md 硬性红线;`rng_service.gd:4` |
|
||
| 每流独立计数器;快照观测面 counter() | `rng_service.gd:36,140-142` |
|
||
| 复现 = 按(流,号位)重新推导,非日志回放 | registry `rng_service`/`stream_seed_derivation` 条目 |
|
||
| 计数器实际持久化:**现行存档未写各流计数器**(adventure_runner 摘要只落 master_seed) | `game/core/adventure_runner.gd:59,83,217` |
|
||
| 黄金向量断言(R3 8 常量) | `game/smoke/smoke_all.gd:34-36,3121+` |
|
||
| MC 逐局独立种子 | `game/smoke/adventure_monte_carlo.gd:15,52` |
|
||
|
||
**核心发现**:字面目标「全游戏随机数派生自同一个源、可逐位复现、没有多套随机」——**现行架构已经满足**。七条流不是七个随机源,是同一主种子的七个盐值分栏(分栏只改派生种子,不改源)。真正剩下的唯一改动 = **把七条分栏计数器并为一个全局计数器**(物理并流)。
|
||
|
||
### 七流消费点清单(并流迁移面)
|
||
|
||
| 流 | 消费点 | 取号时机 |
|
||
|---|---|---|
|
||
| board_gen | `board_generator.gd:16`、`battle_orchestrator.gd:141` | 每张棋盘 |
|
||
| reward_roll | `reward_economy.gd:61` | 每次装板批 |
|
||
| encounter | `battle_orchestrator.gd:116` | 每次战斗实例化(数量骰) |
|
||
| armor_roll | `damage_controller.gd:286`(流名走配置 `db.settlement.armor_roll_stream`) | 每次命中掷点 |
|
||
| behavior_roll | 战斗结算开轮摇号(SkillLottery;子流 scope = spawn_index×1000000+序) | 每敌每轮 |
|
||
| variant_place | `battle_orchestrator.gd:198` | 每板变异布置 |
|
||
| gp_drop | `battle_orchestrator.gd:737` | 每战末掉落掷定 |
|
||
|
||
## Alternatives Considered
|
||
|
||
### 方案甲:字面达成·维持分栏(node_map 作第八栏)
|
||
|
||
承认字面目标已满足(核心发现);节点图抽签按既有增流纪律接入第八栏。零迁移、位置语义(号位=第 N 次某类事件)完整保留、黄金向量与对拍口径不动。
|
||
|
||
### 方案乙:物理并流(用户终裁方向,如实评估)
|
||
|
||
单盐单全局计数器:derive(scope) = mix64(SALT_0 XOR (master + scope×GOLDEN)),scope = 全局顺序号。三个后果(均已向用户两轮呈报,此处落档):
|
||
|
||
1. **号位失去事件语义**——第 N 号只回答"全局第 N 次取数",不再回答"第 N 次什么"。玩家换条路(战斗次数变化)后,同一 N 号对应的事件种类漂移。
|
||
2. **路线依赖**——任何一处随机事件数量/顺序变化平移其后全部骰子;对拍工具"行数恒等纯次序位移"性质失效;"这局 Boss 为什么没中"类单点归因需全序重放。
|
||
3. **连带改动面**——七消费点迁移(上表 6 文件);armor_roll 流名配置语义失效(`db.settlement.armor_roll_stream` 并流后无意义);behavior_roll 子流位(spawn_index×STRIDE)重设计;快照契约登记面变更(7 计数器→1,实际存档未持久化计数器故代码迁移面小);R3 黄金向量 8 常量全量重生成;MC/对拍读数与旧基线断档(全部历史基线作废重测)。
|
||
|
||
### 方案丙:并流 + 全事件日志(用户的「完整记录」模型落地)
|
||
|
||
乙 + 每次取数落盘(流名/号位/用途/返回值),以此恢复单点定位能力。代价 = 乙全部代价 + 每次取数的写盘开销与日志体积;且日志回放与按位重推导并存 = 两套复现机制并存。
|
||
|
||
## Recommendation
|
||
|
||
**推荐甲**:用户的核心诉求(单一随机源、完整可复现、无多套随机)现行架构字面满足;乙/丙是为一个已满足的目标支付真实的分析能力与一次性迁移成本。本 ADR 按用户裁决路径交付评估,**若用户裁决维持乙,上表「连带改动面」即实施批工单,按乙执行,本特性排队其后**——两个方向都已备好,裁决即动。
|
||
|
||
## Consequences
|
||
|
||
- 裁决甲:节点图生成实施批按第八栏增流推进(改代码+金向量+冒烟断言三件套),本评估书归档为架构记录。
|
||
- 裁决乙:先开 rng 架构批(迁移工单如上),全量回归后节点图生成实施批接续;历史 MC 基线全部作废重测归曲线调参批。
|
||
- 裁决丙:同乙,另加日志面设计与写盘性能验收。
|
||
|
||
## 落地记录(统一随机流批 2026-09-27)
|
||
|
||
- 代码:rng_service.gd 重写(单盐 SINGLE_SALT=原 board_gen 盐 / 全局计数器 / 用途标签 open_stream(purpose) / derive_at(scope) 单参 / open_scope 与 BEHAVIOR_SUBSTREAM_STRIDE 退役 / 事件日志会话制 user://logs/rng_log_<主种子>.jsonl);消费点七处迁移(board_generator/reward_economy/battle_orchestrator×4/damage_probe/skill_rhythm_probe/smoke_all 向量与计数断言);behavior_roll 子流派生向量退役(逐敌顺序取号替代,单敌轨迹独立复放面随之退役——冒烟 ③ 测试同批退役,同种子全战斗对拍由 ② 承载)。
|
||
- 向量:统一流 8 常量重登记(scope 0-3 与旧 board_gen 向量逐位连续——单盐沿用其盐);registry stream_seed_derivation 全量改版。
|
||
- 测试:冒烟 557/0 三闸全过(nat20/极性路由/L2 max 三处种子硬编码测试改行为面扫描——并流后随机值面漂移的测试面重锚);四场景探针全绿(ui_input_probe 加「移位扩边」前置——板面种子漂移下前沿不足两格时沿已开区点击移位);MC 20 局逐局独立跑通,事件日志逐冒险落盘实证。
|
||
- 行为面基线:并流后全部历史 MC/verifier 基线作废,重测归曲线调参批(测量对账条款既有口径)。
|