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

16 KiB
Raw Blame History

验收读数重测批——判读报告(初稿,真人位留空)

  • 日期: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 个连续种子 × 每局只消费头部 1740 个 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 本体无恙。

影响面评估(修正后)

  • 玩家单局体验:≈无。一局只有 1740 次掷点,即使种子头部窗口有偏,也与普通骰子运气无法区分(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 已随批删除,不留残留。