feat(acceptance): 验收读数重测批·初稿——模拟批1200局+日志批+掷点流种子偏置核心发现(2026-09-19,独立 worktree 分支;真人位留空)——①执行面:worktree 检出 d236d9f 冒烟 317 项 0 失败,MC 两关×N=30×种子4200+30×both 共 1200 局,log_analysis.py+专项脚本判读;②核心发现=掷点流结构性种子偏置:日志掷点与 armor_roll 流逐 scope 首输出逐位一致,派生种子头部面值聚类(4227 头部 30 scope 4 个 18 点 vs 4211 零个),短局×种子复用放大 40 倍,真实消费模式复现 18 点 +57%≈20σ,纯随机种子对照均匀排除引擎本体——单局 d20 体验随种子漂移(0%→20% 18点率),AC 档位设计地基受损;预热无效/splitmix 未达标,建议立项掷点修复批(黄金向量重登记+阶段一重跑义务,五流连带核查);③阶段一=零承伤轮 PASS/nat20 PASS(污染注记)/档位分布与 EV FAIL(归因 RNG)/Boss 血量锚过期(58 现值)/快照 buffs 非空盲区口径已破/battle_end 行序伪影 1 局一条;④阶段二初稿=L1 完美档 87% 越 gate 上界+承伤 p10=13/p90=25 远低于带(压力不足),F4 两关全 PASS,台阶倒挂消失,判定顺延掷点修复后(§4e 边界1 先查实现缺陷);⑤07⑦ 刷新经济基线已采(弃图率完美档 ~0.1 次/局、normal 0、每轮刷新率 ≤0.6%)——log_analysis.py 新增弃图率/每轮刷新率两读数列,阈值仍归调参批;07⑥ 速杀占比不可推导注记后延;⑥判读报告 production/qa/acceptance-rerun-20260919.md(真人 3–5 局缺位,k 系数待补后终稿);active.md 快照节+台账 84(分支内,主工作区合并时人工对账)

This commit is contained in:
DKChan committed 2026-09-19 22:50:28 +08:00
1 parent 87fec0278a
commit 8178394489
4 files changed
+154 -9

No files matched your search

@@ -111,6 +111,7 @@ class RunAcc:
self.snapshot_buffs_total = 0
self.round_ledger = [] # --rounds 逐轮流水
self.roll_rows = [] # 命中掷点候选字段的 step 行
self.refresh_count = 0 # 受理的弃图刷新次数(action 行 op=refresh accepted=True)
self._prev_hp = None # 上一结算快照的主角 HP(宽口径逐轮差分用)
self._last_enemy_present = False
@@ -164,6 +165,11 @@ class RunAcc:
self.result = e.get("result", "")
self.end_hp = int(e.get("hp", 0))
def on_action(self, e):
# 刷新经济监控(07 清单⑦):只计受理成功的弃图刷新——被拒尝试不构成弃图。
if e.get("op") == "refresh" and e.get("accepted"):
self.refresh_count += 1
# -- 轮窗口收口(核心口径都在这里)------------------------------------
def _finalize_round(self, snap, battle, hp, enemy_present):
@@ -326,7 +332,9 @@ def _feed(run, res, kind, e):
run.on_battle_end(e)
elif kind == "level_end":
run.on_level_end(e)
# action / ux / diagnosis 等其余 kind:本工具当前无消费面,静默跳过
elif kind == "action":
run.on_action(e)
# ux / diagnosis 等其余 kind:本工具当前无消费面,静默跳过
def resolve_inputs(arg):
@@ -355,6 +363,8 @@ def aggregate_levels(runs):
wins = sum(1 for r in rs if r.result == "victory")
boss_rs = [r for r in rs if r.boss_enter_hp() is not None]
win_rs = [r for r in rs if r.result == "victory"]
total_rounds = sum(r.rounds_total for r in rs)
total_refresh = sum(r.refresh_count for r in rs)
rows.append({
"level": lvl, "policy": policy or "—", "runs": n,
"clear_rate": wins / n if n else None,
@@ -362,6 +372,8 @@ def aggregate_levels(runs):
"avg_boss_hp": (sum(r.boss_enter_hp() for r in boss_rs) / len(boss_rs)) if boss_rs else None,
"avg_end_hp": (sum(r.end_hp for r in win_rs) / len(win_rs)) if win_rs else None,
"avg_dmg": sum(r.damage_total for r in rs) / n if n else None,
"refresh_per_run": total_refresh / n if n else None, # 弃图率(与 MC 刷新/局同口径)
"refresh_per_round": total_refresh / total_rounds if total_rounds else None, # 每轮刷新率
})
return rows
@@ -502,13 +514,17 @@ def render(res_files, args, out):
print("== 关卡级统计 ==", file=out)
print(" 口径:局=run 行切分(无 run 行的旧日志整文件一局);通关=result=victory;", file=out)
print(" 进BossHP=Boss首结算快照HP+首轮承伤−首轮治疗(精确反推);平均轮数=每局settlement数。", file=out)
hdr = f" {'关卡':>6} {'档位':>8} {'局数':>5} {'通关率':>7} {'平均轮数':>8} {'进BossHP均':>10} {'通关剩余HP均':>12} {'整局承伤均':>10}"
print(" 弃图率=每局受理刷新次数(07⑦ 基线读数,与 MC 刷新/局同口径);", file=out)
print(" 每轮刷新率=刷新次数÷结算轮数(组内加权)。阈值数字归调参批,本表只出基线。", file=out)
hdr = (f" {'关卡':>6} {'档位':>8} {'局数':>5} {'通关率':>7} {'平均轮数':>8} {'进BossHP均':>10} "
f"{'通关剩余HP均':>12} {'整局承伤均':>10} {'弃图率':>7} {'每轮刷新率':>9}")
print(hdr, file=out)
for row in aggregate_levels(all_runs):
print(f" {str(row['level']):>6} {row['policy']:>8} {row['runs']:>5} "
f"{fmt(row['clear_rate'] * 100 if row['clear_rate'] is not None else None):>6}% "
f"{fmt(row['avg_rounds']):>8} {fmt(row['avg_boss_hp']):>10} "
f"{fmt(row['avg_end_hp']):>12} {fmt(row['avg_dmg']):>10}", file=out)
f"{fmt(row['avg_end_hp']):>12} {fmt(row['avg_dmg']):>10} "
f"{fmt(row['refresh_per_run'], 2):>7} {fmt(row['refresh_per_round'], 3):>9}", file=out)
print(file=out)
print("== 战斗级统计(按 关卡/节点类型/深度 分组;对照承伤带 普通≤20%、Boss≤50% max_hp)==", file=out)
@@ -553,11 +569,11 @@ def render(res_files, args, out):
if args.per_run:
print("== 逐局明细(--per-run)==", file=out)
print(f" {'文件':<28} {'种子':>6} {'档位':>8} {'结果':>8} {'轮数':>4} {'承伤':>5} {'零承伤轮':>8} {'进BossHP':>8} {'终局HP':>6}", file=out)
print(f" {'文件':<28} {'种子':>6} {'档位':>8} {'结果':>8} {'轮数':>4} {'承伤':>5} {'零承伤轮':>8} {'进BossHP':>8} {'终局HP':>6} {'刷新':>4}", file=out)
for run in all_runs:
print(f" {run.src_file:<28} {str(run.seed):>6} {run.policy or '—':>8} "
f"{run.result or '—':>8} {run.rounds_total:>4} {run.damage_total:>5} "
f"{run.zero_narrow:>8} {fmt(run.boss_enter_hp(), 0):>8} {str(run.end_hp):>6}", file=out)
f"{run.zero_narrow:>8} {fmt(run.boss_enter_hp(), 0):>8} {str(run.end_hp):>6} {run.refresh_count:>4}", file=out)
print(file=out)
if args.rounds: