Files
gplan-2/design/qa/acceptance-rerun-20260919.md
T

151 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 验收读数重测批——判读报告(初稿,真人位留空)
- **日期**:2026-09-19
- **口径依据**:`docs/acceptance-ap6-ac.md` v1.0(定稿判读规则全文照搬执行)
- **被测构建**:master @ d236d9f(技能池新效应词汇批后;乘区接线+削弱续时+甲效换装+充能退役+rider 五次数值行为变更叠加后的首次全量重测)
- **执行环境**:独立 worktree `D:\code\g-plan2-acceptance-rerun`(分支 `acceptance-rerun-20260919`)——绕开主工作区并行会话未提交改动
- **数据源状态**:① 模拟批 ✅ 完成(两关 × N=30 × 种子 4200+30 × 策略 both,共 1200 局)② 日志批 ✅ 完成 ③ **真人批 ⬜ 缺位**(3–5 局基线档待用户补跑,k 系数待并入)——按口径「三数据源全部跑完再判读」,本报告全部结论为**初稿**,终稿待真人批合入
- **前置验证**:worktree 冒烟 317 项 0 失败(run_smoke 三闸全过)✅
---
## ⚠️ 核心发现:窄种子窗 × 复用放大——掷点统计失真(本批最重要产出;2026-09-19 深勘后根因已修正定稿)
**一句话**:d20 掷点流的派生公式本身是均匀的,但「30 个连续种子 × 每局只消费头部 ~17~40 个 scope × 每种子被复用 ~40 局」的组合,把头部窗口自身的面值彩票放大 ~40 倍灌进全部聚合统计——验收的档位分布/EV gate 读数因此失真。**修正记录**:本报告首稿曾定性为"派生种子首输出缺陷、真实玩家体验受损",经 2000 种子全局对照与跨步种子对照推翻——公式无恙、玩家单局影响≈机会涨落水平,真实受害者是测量有效性。
### 证据链(可复现,探针脚本形态见附录)
1. **逐位比对**:种子 4227 首局前 23 个日志掷点与 `rng.open_stream("armor_roll")` 逐 scope 首输出序列**完全一致**——日志掷点 = 派生种子首输出,无其他变换。
2. **逐种子失真**:真实日志按种子聚合 18 点数 0→131(种子 4211 = 0、4227 = 120);二项分布下 n≈700 的 σ≈6,此散布远超抽样涨落——复用放大实锤(每局重吃同一种子的头部窗口,窗口彩票 ×40)。
3. **全局均匀对照**:2000 个跨步种子 × 头部 31 scope 等权聚合,χ²=22.8(19df 95% 临界 30.1)——**派生公式全局无偏**;splitmix 混淆版同样干净(χ²=23.5),混淆不解决本问题(问题不在公式)。
4. **窗口彩票对照**:MC 实际窗口(连续 30 种子 × 头部 41 scope)18 点 +35% 集中在高权重头部;同规模跨步种子窗口 χ²=26 正常——特定窗口运气 × 复用 = 失真。
5. **真实消费模式复现**:按「30 种子 × 40 局 × 每局 8~31 掷」聚合,复现 18 点 +57%(1876/23822)的日志签名。
6. **排除项**:纯随机种子首输出均匀(4 万次最大偏差 2.7σ)——引擎 PCG 本体无恙。
### 影响面评估(修正后)
- **玩家单局体验:≈无**。一局只有 ~17~40 次掷点,即使种子头部窗口有偏,也与普通骰子运气无法区分(17 次均匀掷点本身就有 ±10pp 级涨落)。**首稿"玩家体验随种子漂移"的说法降级为理论可能性**(只有在单局掷点数大幅增长的未来内容里才可能被感知)。
- **测量有效性:实害**。验收掷点面(档位分布/EV/nat20)与任何基于这 30 个种子的聚合统计,都被窗口彩票 ×40 放大污染——本批阶段一两个 gate FAIL 由此归因,不能算到机制或数值头上。**同构隐患**:五条流(board_gen/reward_roll/encounter/armor_roll/behavior_roll)共享此消费模式,窄种子窗 + 短消费窗 + 复用的分析面都会中招。
- **潜在陷阱(非现行故障)**:若未来种子外露(种子分享玩法)或单局掷点数大增,窄窗彩票从测量问题升级为体验问题。
### 修复方向(三案,均已评估;探针级验证见附录)
- **方案 A(推荐,零游戏代码)**:掷点统计面改用宽种子带——如 4200 起步长 7919 取 ≥100 个种子(保留 4200–4229 子段则历史坐标仍可比),窗口彩票按 1/√种子数摊平;实现 = MC 工具加一档「掷点扫描批」参数。承伤/通关率等压力读数同理受益。
- **方案 B(可选加固,一处小改)**:`rng_service.gd` 派生前对 master 做一次非线性混淆(如 splitmix64 finalizer)——任何窄种子窗表现如随机抽样,根治"连续小整数种子"陷阱。逐 scope 回放语义不变;代价 = 黄金向量重登记 + 冒烟回归。全局均匀性已被证明,此案是防御性投资,不紧急。
- **方案 C(用户提案:真随机 + 逐次记录)**:技术上可行但代价不成比例——存档序列化快照契约(master_seed)、反事实重算工具(analyze_playtest 依赖确定性重模拟)、逐次可回放语义全部重做,记录文件随局数无限增长;而它解决的问题 A/B 已以小得多的代价覆盖。不推荐,除非未来设计转向"非确定性掷点"价值观。
- **共性注记**:无论何案,单局 17~40 掷的"运气窗"本身(某局恰好 18 点多)是骰子本性,修复对象是"系统性放大"而非"运气存在"。
### B 案落地结果(2026-09-19 用户拍板 B 案,同日实施收口)
- **实现**:`rng_service.gd` R2→R3——derive = mix64(SALT XOR wrap64(master + scope×GOLDEN)),splitmix64 finalizer 变体(乘数 0xBF58476D1CE4E5B9 / 0x94D049BB133111EB、加数同 GOLDEN_RATIO);**全程 63 位掩码**(有符号 int64 算术移位在正值域与逻辑移位逐位一致——与 Python 参考实现对齐的关键)。逐 scope 复放语义/计数器契约/存档快照契约不变。
- **黄金向量**:8 常量全量重登记(冒烟 R3 向量断言 + registry stream_seed_derivation 条目 + Formulas-R3 指向),Python 参考实现与 GDScript 实现逐位交叉验证一致;R2 旧向量作废。
- **冒烟**:316 项 0 失败三闸全过(317→316 = 一条"探针首掷恰好暴击才触发"的条件断言在新序列下不触发,良性)。
- **R3 版模拟批重跑(1200 局)验证**:
- 18 点异常**消失**(1740→846,期望 1010,残差回落到 30 种子窗口彩票的理论噪声带 ≈2σ_eff);
- nat20 暴击率 5.92%(带内 PASS);主角→敌全额率 100% PASS;
- **敌→主角 EV 减免 25.6% 仍高于理论 21.25%——但现在是干净读数**:档位分布 ×0.25 档 16.6%(理论 10%)、全额 50.0%(理论 55%),指向主角有效 AC 被护甲强化(ac_up)供给抬高 ~1.2 点。这是 B 案清除 RNG 噪声后**首次可见的真实设计信号**,归调参批处置(护甲强化供给是合法杠杆位);
- 压力面结论对 RNG 改版稳健:L1 完美档基线格 87% 通关/承伤均 17.0/p90 24,与改版前同方向同量级——阶段二"压力不足"判定不变,仍顺延调参批;
- 同种子历史坐标随 R3 改版整体作废(预期内,已登记 registry 批注)。
- **遗留提示**:B 案消除的是"窄窗彩票被系统性放大",30 种子的窗口彩票噪声本身仍在(档位分布 gate 若按 ±2σ 独立样本口径判读仍会误报)——**建议阶段一正式重跑时叠加 A 案**(掷点统计面用宽种子带,如 4200+i×7919 × ≥100 种子),两案正交不冲突。
### A 案叠加落地结果(2026-09-19 用户拍板 A/B 叠加,同日实施收口)
- **实现**:`level_monte_carlo.gd` 增第 5 参种子模式 `shared|unique`(缺省 shared = 旧行为零变更,保留同种子 A/B 对照用法;unique = 逐局独立种子 seed0+全局序号)。unique 模式下每个 (种子, scope) 恰消费一次 → 聚合掷点统计回归标准二项分布,±2σ gate 口径重新有效——这是 A 案的本质:消除复用权重,而非换种子段。
- **A+B 版模拟批重跑(两关 1200 局,逐局独立种子)验证**:
- d20 直方图**全面干净**:20 面值全部落在期望 1011 的 ±2.3σ 内(对照:R2 版 18 点 +57%≈20σ);
- nat20 暴击率 5.12%(带内 PASS);主角→敌 / 敌→主角暴击率 5.13%/5.09% 双向对齐理论;
- **敌→主角档位分布失真仍在但已是干净设计信号**:全额 50.9%(理论 55%,-7.6σ)、×0.25 档 15.0%(理论 10%,+15σ)——指向主角有效 AC 被护甲强化(ac_up +1×2 层)供给抬高 ~1.5 点,EV 减免 24.59% 同源。此偏差**真实且显著**,归调参批裁决(重新校准 gate 把 AC 增益期计入理论模型,或调护甲供给);
- 压力面第三次复测稳如磐石:L1 完美档基线格 87% 通关/承伤 16.8/p90 24——R2/R3/A+B 三批同向同量级,"压力不足"判定与 RNG 无关焊死;L2 完美档 87%/13.9·21;
- 弃图率读数稳定(完美档 0.02-0.10 次/局,normal 0)。
- **A+B 叠加后的验收口径状态**:掷点面 gate 判读从此有效;阶段一正式重跑数据 = 本批(T220949/T221847 两文件);同种子历史坐标已三重作废(R3 改版 + unique 模式),坐标可比性锚改为「本批 A+B 数据」。
---
## 阶段一:机制验收(日志批,gate 判读——全部受发现①污染,仅记录现状)
数据:两份 MC 日志共 318,626 行、1200 局、20,945 次掷点。
| 指标 | 读数 | 期望带 | 判读 | 注记 |
|---|---|---|---|---|
| 零承伤轮(窄口径) | 0 / 8076 攻击落地轮 | 0 | ✅ PASS | 伤害下限 1 生效 |
| 零掉血轮(宽口径) | 6706 / 13364 敌战轮(50.2%) | observe | 记录 | 与真人旧读数对照待真人批 |
| nat20 暴击率 | 4.53% | 5%±2pp | ✅ PASS(带污染注记) | 种子头部偏置使逐种子暴击率漂移大 |
| 档位分布(敌→主角) | 全额 50.8%/×0.75 15.0%/×0.5 21.6%/×0.25 12.6% | 55/15/20/10 各±2σ | ❌ FAIL | 归因=RNG 偏置为主 + 护甲强化增益抬 AC 混入(全额缺口方向与增益一致,但幅度超增益可解释范围) |
| 玩家侧全额率 | 主角→敌 EV 减免 0.00% | 100% 全额 | ✅ PASS | 敌 AC 关内 0 生效 |
| EV 减免(敌→主角) | 23.98% | 21.25%±2pp | ❌ FAIL | 同上归因 |
| Boss 血量锚 | 表值 hp=58(蛛化卓尔精灵) | r_boss=150÷153.5≈0.98 | ⚠️ 锚过期 | 口径写于压缩批与卓尔加血前(150→÷3→58);锚值重校准归调参批,本批记录现状 |
| 增益战斗期复原 | 三类可复原(attack_up/weaken/减伤族) | observe | ✅ 记录 | 复原面工作正常 |
| 快照 buffs 非空 | **8790/14402** | 恒空(盲区口径=0) | ⚠️ 盲区口径已破 | rider/状态批后快照开始携带 buffs(疑 duration-2 状态使衰减段后仍有存留)——**好消息**(盲区闭合),口径文档需改写该节 |
| 数据质量·解析失败 | 0 | 0 | ✅ PASS | |
| 数据质量·未配对 battle_end | **1200(系统性 1/局)** | 0 | ⚠️ 行序伪影 | 每局恰 1 条 battle_end 落到 run 行切分点之后(level_end 先于 battle_end 落盘);不影响核心统计(分析器不依赖 battle_end),行序归因待核 |
## 阶段二:压力验收(模拟批基线格,初稿判读——顺延至掷点修复后终判)
### 第一关(生死带主判据格:MC perfect 基线格 atk+0%/hp+0%,n=30)
| 指标 | 读数 | gate | 判读 |
|---|---|---|---|
| 整关承伤分布 | p10=13.0 / p50=18 / p90=25.0 / max=28 | p10∈[35,45] 且 p90∈[55,65] | ❌ FAIL(远低于带下沿——压力不足方向) |
| 通关率 | 87% | [35%, 65%] | ❌ FAIL(越上界) |
| 通关余量 | 胜局剩余 HP 均 7.4 | p90≤13 且 p10≥3(收敛后 gate) | observe(未收敛) |
| 平均轮数 | 16.4 | observe | 记录 |
| 盲挖档(normal 基线格)通关率 | 73% | observe(生死带下 0% 为预期态) | 记录——73% 与生死带预期相悖,同证压力不足 |
### 第二关(对照面,无独立 gate)
| 指标 | 读数 |
|---|---|
| 完美档基线格通关率 / 承伤 p50/p90 | 87% / 15.5 / 21.2 |
| 盲挖档基线格通关率 | 83% |
| 台阶倒挂 | L1 87% vs L2 87%——倒挂消失(旧读数 65vs90→65vs80→本批持平),方向性好转 |
### F4 满配格(gate:普通场 ≤20% / Boss 场 ≤50% 生效 max_hp)
| 关卡 | 普通场 | Boss 场 | 判读 |
|---|---|---|---|
| L1 | 6.5% | 15.7% | ✅ PASS |
| L2 | 5.9% | 22.8% | ✅ PASS |
### 战斗级承伤带(普通 ≤20% / Boss ≤50%,全网格聚合)
全部 9 个(关×类型×深度)分组 ✓ PASS;Boss 战单独出列读数:L1 Boss 场均承伤 26.7% max_hp / 5.9 轮,L2 Boss 35.7% / 5.0 轮——Boss 承伤占比显著高于普通场(设计方向:Boss 是主要伤害来源),无不可控死法迹象(败北节点全部集中于 Boss 位,普通位败北为 0)。
### 阶段二初稿结论
双 gate(承伤带 + 通关率)双败,方向一致=**压力不足**(完美档太容易通关、承伤远低于生死带)。按归因规则本应走 §4e 阶梯(敌方输出侧),但发现①属实现缺陷且优先级在前(§4e 边界 1)——**建议顺序:掷点修复批 → 阶段一重跑 → 阶段二调参批**。附带提醒:修复掷点会轻微改变承伤/通关读数(掷点分布变了),调参批应在修复后的重测读数上工作。
---
## 07⑦ 刷新经济监控——基线读数(本批搭车项,2026-09-19 首批基线)
分析器已新增两读数(`log_analysis.py` 关卡级统计:弃图率=每局受理刷新次数,与 MC 刷新/局同口径;每轮刷新率=刷新次数÷结算轮数)。**首批基线**:
| 数据面 | 弃图率(次/局) | 每轮刷新率 | 样本 |
|---|---|---|---|
| MC L1 完美档基线格 | 0.23 | — | 30 局 |
| MC L2 完美档基线格 | 0.03 | — | 30 局 |
| MC 全网格 L1 完美档 | 0.08 | 0.006 | 300 局 |
| MC 全网格 L2 完美档 | 0.01 | 0.001 | 300 局 |
| MC 全网格 normal 档(两关) | 0.00 | 0.000 | 600 局 |
| 真人日志参照(并行会话今日 600 局模拟,非本批数据) | 完美档 0.12 | 0.008 | 供交叉参照 |
解读起点(供调参批参考,非结论):完美档低频弃图(~0.1 次/局量级)、normal 档零弃图——与「完美档卡死才刷新」的口径一致(auto_player 刷新=卡死解除手段);normal 档零使用提示 1 RAP 定价对普通玩家可能偏贵或无感知,真人批数据将回答。**阈值数字仍归调参批**(口径不变:现在定是拍脑袋)。
**顺带核查项**:07⑥ 速杀退化预警的读数(战斗结束未开资格格占比)经核对**现役日志不可推导**——battle_end 行仅含 result+hero_hp,无格面开格状态面。采集义务需等埋点(board 状态入结算快照或独立行),本批不硬做,注记后延。
---
## 待办与回流
1. **真人批**(用户):基线档 3–5 局 → k 系数 + 零掉血轮宽口径真人对照 → 本报告终稿。
2. **掷点测量修复**(待拍板选案):方案 A(宽种子带,零代码)/方案 B(master 混淆加固,黄金向量重登记)/方案 C(真随机+记录,不推荐);选 A 则登记 06 待办为「验收掷点扫描种子带改造」,选 B 则为 rng_service 加固批;阶段一在修复后重跑。
3. **口径文档连带修订**(归合并批):`docs/acceptance-ap6-ac.md` 快照 buffs 盲区节改写、Boss 血量锚参照值重校准(58 现值)、§2 消费读数行补刷新两读数;`06-待办清单`「刷新经济性监控」条目保留至调参批定阈值。
4. **曲线调参批门**:确认改为「掷点测量修复 + 阶段一重跑后」起跑(原门=验收读数)。
## 附录:探针脚本(复现用)
本批全部 RNG 探针为一次性 `/tmp` 脚本(rng_probe*.gd),核心复现路径:
① 从日志抽种子 4227 首局前 23 掷与 `open_stream("armor_roll")` 逐 scope 首输出逐位比对;
② `SALT_ARMOR_ROLL ^ (seed + scope×GOLDEN) & 0x7FFF…` 直喂 `RandomNumberGenerator.randi_range(1,20)` 画头部直方图;
③ 按 30 种子×40 局×8~31 掷聚合复现失真签名。诊断用工程内探针 `smoke/rng_face_probe.gd` 已随批删除,不留残留。