From 8a654ccece0483c7268766ddd125dc70117d9798 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 8 Oct 2026 05:07:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20=E5=8D=A1=E2=93=AA?= =?UTF-8?q?=E2=91=A3=E2=80=94=E2=80=94=E5=88=A0=20adventure=5Frunner.gd=20?= =?UTF-8?q?start=5Fadventure=20=E4=B8=89=E8=A1=8C=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E8=B5=8B=E5=80=BC=EF=BC=88=E9=80=90=E5=AD=97=E9=87=8D=E5=A4=8D?= =?UTF-8?q?+=E4=B8=AD=E9=97=B4=E9=9B=B6=E8=AF=AD=E5=8F=A5+=5Fseed=5Fattune?= =?UTF-8?q?=5Fcharges=20=E7=BA=AF=E9=87=8D=E7=BD=AE=E5=B9=82=E7=AD=89=3D?= =?UTF-8?q?=E9=9B=B6=E8=A1=8C=E4=B8=BA=E5=8F=98=E5=8C=96=EF=BC=8C=E8=AF=81?= =?UTF-8?q?=E6=8D=AE=E4=B8=8E=E5=9B=9B=E4=BB=B6=E5=AF=B9=E7=85=A7=E8=A7=81?= =?UTF-8?q?=E5=87=BA=E5=8F=A3=E6=8A=A5=E5=91=8A=EF=BC=89=EF=BC=9B=E5=85=A5?= =?UTF-8?q?=E5=8F=A3=E6=8A=A5=E5=91=8A=E9=9A=8F=E6=89=B9=E8=90=BD=E7=B1=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qa/iter19-card0-exit-report-2026-10-08.md | 96 +++++++++++++++++++ game/core/adventure_runner.gd | 3 - 2 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 design/qa/iter19-card0-exit-report-2026-10-08.md diff --git a/design/qa/iter19-card0-exit-report-2026-10-08.md b/design/qa/iter19-card0-exit-report-2026-10-08.md new file mode 100644 index 00000000..5c23571a --- /dev/null +++ b/design/qa/iter19-card0-exit-report-2026-10-08.md @@ -0,0 +1,96 @@ +# 迭代 19 卡⓪「主菜单开局缺陷修复批」出口报告(2026-10-08) + +- worktree:`D:\code\g-plan2-iter19-card0`(分支 `iter19-card0-20261008`,基点 b0a73df = master 顶部) +- 台账号:**398**(记账前以 `git -C D:/code/g-plan2 show master:active.md` 查撞——master 无 398;397 条预配「卡⓪398」与本卡一致,未撞未顺延) +- MC/verifier:零跑(本卡 MC=静态论证,见 §5) + +--- + +## 1. 四件逐件改动对照(file:line 改前 → 改后) + +### ① 主菜单两入口补传同调三键 + +T0 实查:行号与任务书一致(新冒险入口 main.gd:510、继续上局入口 main.gd:470);接收面确认 start_adventure :129-130+138 三键齐、resume_adventure :215-216 仅两键(见 §7 披露项)。三键来源复用既有营地投影口径,零新读取逻辑: + +| 键 | 来源(既有访问器) | 与营地投影同源依据 | +|---|---|---| +| attunement | `save_manager.attunement_equipped()`(save_manager.gd:314-316) | `meta.attune_camp_status()["equipped"]` 同一读数源(meta_progression.gd:368) | +| attune_refresh_y | `meta.attune_refresh_charges()`(meta_progression.gd:394-395,当前等级行表值) | `attune_camp_status()["refresh"]["charges"]` 同一读数源(:386) | +| tree_rules | `meta.tree_rule_keys()`(meta_progression.gd:241-253,Fork 激活侧 effects) | 树 rule 键集唯一既有取值口 | + +改动(均 `game/presentation/main.gd`): + +- **新增 static 构造函数 `build_adventure_params`**(改前 :493 空、改后 :496-513)——两入口共用参数面构造;hero_override 沿用既有 `meta.hero_override() if meta != null else {}` 口径原样搬入;static 形态=冒烟直呼单测(③),免实例化整菜单场景。 +- **继续上局入口**(`_resume_from_menu`,改前 :470 内联 2 键 dict `{"hero_override", "treasure_unlocked"}` → 改后 :470-471 `build_adventure_params(save_manager, meta, {"treasure_unlocked": ...})`,产出 5 键)。 +- **开新冒险入口**(`_start_adventure`,改前 :510 内联 4 键 dict → 改后 :528-530 `build_adventure_params(save_manager, meta, {"first_script", "treasure_unlocked", "shop_mode"})`,产出 7 键)。 + +runner 侧受理零改动(任务书明令「无需改 runner 侧受理」)。 + +### ② 关卡开场行攻血改传当前生效值 + 后缀认局外加成 + +改动(`game/presentation/main.gd` `_on_adventure_level_started`,改前 :517-521 → 改后 :539-549): + +- 攻/血:改前传初始表值 `int(db.hero.atk)` / `int(db.hero.max_hp)` → 改后传 `runner.effective_atk()` / `runner.effective_max_hp()`——与战斗面板同源(battle_orchestrator begin_battle enc 的 `hero_atk`/`hero_max_hp` 即 LevelRunner.effective_*,level_runner.gd:479-480)。回调时点 runner 已带全部加成:`level_started` 在 `_runner.start_level_external(...)` 之后 emit(adventure_runner.gd:946,改后 :943),base_override/加算区/调试 pct 均已注入。 +- 「含面板加成」后缀判断:改前只认 `debug_overlay.atk_pct() > 0 or debug_overlay.hp_pct() > 0` → 改后追加认局外加成 `meta.hero_override()` 的 atk/max_hp 两轴 flat 任一 >0(调试 pct 条件保留)。白板局(无局外 flat、无面板 pct)不带后缀。后缀文案本身零改。 +- 依据:06-待办清单「关卡开场行攻血显示初始表值」条——「战斗面板用 level_runner.gd:480 生效值……两处数字对不上;后缀只认调试浮窗 pct,局外加成不触发注记」,用户 2026-10-07 确认缺陷成立。 + +`battle_narrator.gd:38-40`(level_open_line)零改——签名与拼装能力本就够用。 + +### ③ 冒烟补主菜单入口传参断言 + +改动(`game/smoke/smoke_all.gd`,新增 :4661-4687,⑫同调段之后、`_meta_smoke_cleanup()` 之前): + +- 形态:直呼 `load("res://presentation/main.gd").build_adventure_params(...)` 单测统一构造面(static 免实例化整菜单场景,对既有冒烟夹具零侵入——level_autoplay 直呼 runner 的旧口径原样不动)。 +- 夹具(隔离档 `_META_SMOKE_PATHS[8]`=smoke_meta_tree.json,随段尾既有 cleanup 清理):装配 `["luck_coin"]` + Y 升 2 档 + Fork `fg_posture` 取 a 侧;前置断言防空转(rule 键非空 + Y=Lv2 行表值 2)。 +- 断言 6 项(大白话文案): + 1. 前置:Fork 侧 a 激活 rule 键非空 + Y=Lv2 行表值 2; + 2. 开新冒险:同调装配 = 存档装配集(营地装了什么开局就带什么); + 3. 开新冒险:Y 刷新池 = 当前等级行表值(营地升几档开局就给几次); + 4. 开新冒险:树 rule 键集 = Fork 激活侧 effects(点哪侧带哪侧); + 5. 开新冒险:入口特有键(first_script/shop_mode)随 extra 原样并入; + 6. 继续上局:三键与开新冒险同源同值(续玩不吃白板开局)。 +- 两入口覆盖说明:真实两入口共用 `build_adventure_params`(①的落法),开新/续玩两组断言即两路径的传参面;构造函数被两入口弃用回归时第 2-6 项即转红。 + +### ④ 删 adventure_runner.gd 三行重复赋值 + +改动(`game/core/adventure_runner.gd`,改前 :132-134 三行 → 删;现 :129-131 单组赋值收尾): + +零行为变化证据: + +1. **逐字重复**:被删 :132-134 与保留 :129-131 三行逐 token 相同(`_attunement = params.get(...)`、`_attune_refresh_y = maxi(0, int(params.get(...)))`、`_seed_attune_charges()`),同一 params 实参下二次赋值结果逐位相等。 +2. **中间无扰动**::131 与被删 :132 之间零语句——两次 `_seed_attune_charges()` 连续背靠背调用。 +3. **`_seed_attune_charges` 幂等**(:635-640,改后 :632-637):函数体 = `attune_charges = {}` 整体重置后按 `_attunement`+表行重灌——纯函数(读 params 已落地的 `_attunement` 与 db 表行,零 RNG、零信号、零 db 写),连续两次调用终态与一次相同。 +4. **闸实证**:删后 run_smoke 840/0、run_all 17 套件全绿(含 breakpoint_resume/curio_refresh_paid 等直呼 start_adventure 参数面的套件)——充能账本/刷新双源行为断言零漂移。 + +## 2. 闸数字(改前基线 / 改后) + +| 闸 | 改前(主区 b0a73df 实测基线) | 改后(本 worktree 批末) | +|---|---|---| +| run_smoke | 834 项 0 失败,三闸过 | **840 项 0 失败,三闸过**(+6=③新增断言,失败数持平 0) | +| probe_gate 默认段 | input/struct/contrast 三探针全绿 | 三探针全绿 | +| probe_gate --click | 全绿 | 全绿(click 走查真跑主菜单开局一场冒险,问题=0) | +| run_all | 17 套件全绿 | 17 套件全绿 | +| 残留 Godot | 0 | **0**(probe_gate 批末闸「本闸残留 Godot=0 · 全局 Godot=0」) | + +中间轮次:改动落齐后即跑轻闸(probe_gate 默认段全绿 + run_smoke 840/0),批末重闸三件全跑如上。 + +## 3. MC 零跑静态论证(一句话) + +本卡 MC=静态论证:MC 取数面不经主菜单入口(adventure_monte_carlo/level_autoplay 直呼 AdventureRunner 参数面,在册夹具口径不动),故 ①② 的呈现层改动对 MC 路径零触及,MC 零跑零风险。 + +## 4. 范围外三件未触碰声明 + +- X/Y 刷新双源语义倒置(adventure_runner.gd 原 :658-659/:706-709,删重后 :655-656/:703-706):**零触碰**(④删除的三行在其上方,纯行号平移,内容未动——待用户裁定甲/乙)。 +- 被动同调件呈现:**零触碰**。 +- Fork 规则归因行(呈现层):**零触碰**。 +- 主区其余脏文件:**零触碰**(全程只在本 worktree 改动三文件+出口报告+active.md;主区仅 `git -C` 只读查询)。 + +## 5. 遗留与移交项 + +1. **runner 侧 resume_adventure 受理面无 tree_rules 键**(:215-217 仅收 attunement/attune_refresh_y;任务书「接收面 :215-217 现成」对 tree_rules 不成立)。本卡按「无需改 runner 侧受理」执行:两入口三键均已传出,续玩局 tree_rules 暂不被消费(=续玩局 Fork 规则键暂不生效,与修复前同态、无回归)。移交:runner 侧补一行受理(`_tree_rules = params.get("tree_rules", ...)` 同 :138 款)即可闭环,归用户裁定后随任一后续批落。 +2. X/Y 双源语义倒置仍待用户裁定(范围外,登记 06)。 +3. 开场行后缀在「局内有加算区 flat 但无局外加成」时无注记(数字含加算区但 suffix 不带)——按任务书「局外加成存在才带」字面口径执行,如需扩展认加算区归设计批裁定。 + +## 6. 提交清单 + +(本节随提交落定,见 git log——分四笔:修复①② / 断言③ / 清理④+出口报告 / 台账 398 记账。) diff --git a/game/core/adventure_runner.gd b/game/core/adventure_runner.gd index 6f214914..b3b8cd2a 100644 --- a/game/core/adventure_runner.gd +++ b/game/core/adventure_runner.gd @@ -128,9 +128,6 @@ func start_adventure(seed_val: int, params: Dictionary = {}) -> bool: _treasure_unlocked = params.get("treasure_unlocked", {}) if params.get("treasure_unlocked", {}) is Dictionary else {} _attunement = params.get("attunement", []) if params.get("attunement", []) is Array else [] # additive(迭代 11 第①批 T5) _attune_refresh_y = maxi(0, int(params.get("attune_refresh_y", 0))) # additive(迭代 11 第①批 T5b——Y 冒险周期池) - _seed_attune_charges() # 迭代 11 第①批 T6——冒险开始充能账本按装备主动件重置(每冒险充能语义) # additive(迭代 7 T5) - _attunement = params.get("attunement", []) if params.get("attunement", []) is Array else [] # additive(迭代 11 第①批 T5) - _attune_refresh_y = maxi(0, int(params.get("attune_refresh_y", 0))) # additive(迭代 11 第①批 T5b——Y 冒险周期池) _seed_attune_charges() # 迭代 11 第①批 T6——冒险开始充能账本按装备主动件重置(每冒险充能语义) # 特性开局注入(迭代 12 T7——MC 成型画像载体:params.relics_seed 非空=开局持有集〔七流派 # 各 2 件档一成型——测量面专用;真实局规则改写型特性只走局内随机渠道,红线②层级纪律不破〕)