diff --git a/design/gdd/systems/战斗循环/敌人系统.md b/design/gdd/systems/战斗循环/敌人系统.md index 85fc1878..82c1badb 100644 --- a/design/gdd/systems/战斗循环/敌人系统.md +++ b/design/gdd/systems/战斗循环/敌人系统.md @@ -145,7 +145,7 @@ 死亡即不动手(保留):摇定后、兑现前死亡(主角先手 / 更早兑现的敌方伤害技),本拍技能作废——不动手、不进冷却、不进保底计数;其余存活敌人照常。拍结构保留:**每结算每存活敌恰行动一次、按行序、先作用后推进**——变的只是"轮到什么",由固定剧本改为摇号。同种敌人不再锁步:各自实例池独立摇号、独立冷却,怪物 1 的重击在冷却里不影响怪物 2,轨迹分歧是涌现,不设开战分配机制。 -蓄力语义(2026-09-16 纠偏定稿):蓄力不是重击前奏——它是一行增益技:0 伤害动作,施加 empower 状态(幅度读 `status_effects.tres`),持续 1 个有效结算(provisional)。旧环"蓄力→猛击"的固定配对是哥布林弹珠的拷贝(给玩家输出窗口用的),随行为环一并退役;蓄力与重击之间**没有任何组合语义**——增益与技能倍率恰好同拍只是增益倍率 × 技能倍率的两层乘法共存(增益幅度 × 增益幅度 = 两层乘法读表可得),蓄力后摇中普通攻击则是增益倍率的加成平砍,两者同为平常事,不是设计的连招。技能冷却(几拍内不能再摇中,技能行属性)与增益持续(状态挂几回合,状态行属性)是两个计时器,互不相干。施放行 = 0 伤害动作,不掷不折(原"零兑付、不读伏击"的读怪奖励语义随伏击退役作废——2026-09-20 八型批)。 +蓄力语义(2026-09-16 纠偏定稿):蓄力不是重击前奏——它是一行增益技:0 伤害动作,施加 empower 状态(幅度读 `status_effects.tres`),持续 1 个有效结算(provisional)。旧环"蓄力→猛击"的固定配对是地精弹珠的拷贝(给玩家输出窗口用的),随行为环一并退役;蓄力与重击之间**没有任何组合语义**——增益与技能倍率恰好同拍只是增益倍率 × 技能倍率的两层乘法共存(增益幅度 × 增益幅度 = 两层乘法读表可得),蓄力后摇中普通攻击则是增益倍率的加成平砍,两者同为平常事,不是设计的连招。技能冷却(几拍内不能再摇中,技能行属性)与增益持续(状态挂几回合,状态行属性)是两个计时器,互不相干。施放行 = 0 伤害动作,不掷不折(原"零兑付、不读伏击"的读怪奖励语义随伏击退役作废——2026-09-20 八型批)。 Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**技能错峰两轨口径,2026-10-05 技能池执行批立 Boss 轨、2026-10-13 迭代 24 N2 补普通敌轨**:**Boss 轨** = L1 酋长池含独占增益技"硬化"〔敌方防御池词汇载体〕+ 半血解锁伤害技"震地怒击";L2 卓尔池独占妨害技"蛛网束缚"+伤害技"毒爆"+ 半血解锁"遏毒";L3 石君王池独占妨害技"大地脉动"+ 半血解锁"岩崩"——独占技随关错峰投放,三行解锁技=每 Boss 一行新独占伤害技〔用户裁案甲,2026-10-04〕;**普通敌轨** = L2/L3 普通敌种技能随关错峰投放(2026-10-13 N2:巨蜘蛛族+毒吐〔(2,5)/(2,6)/(2,7),首遇教学位 (2,4) 不投〕、灰矮人族+盾击〔(3,0)/(3,5)/(3,7)〕,`skills.tres` 12→14 行)——第一关不见的招式第二/三关普通战可见;旧"专属四拍环且含蓄力拍"约定顺带退役,增益 ≤1 纪律下旧蓄力拍不进 Boss 池)。 diff --git a/game/data/tables/enemy.tres b/game/data/tables/enemy.tres index 2e549a1b..ad679a65 100644 --- a/game/data/tables/enemy.tres +++ b/game/data/tables/enemy.tres @@ -788,6 +788,9 @@ rows = [{ ; 后半场 6/2/2/2+震地怒击 2=每拍 4.33;含闸长期速率抽样实测 1.1948,smoke EV 抽样带重锚 [1.10, 1.30]; ; 卓尔遏毒/石君王岩崩同批入池——读数判读归 T7 节奏重测〔后置挂 07,跑批待用户批准〕) ; 含闸长期速率(冷却/保底)EV 锚按实施批 EV 抽样复核登记(proposal §2.5)。 +; 地精 EV 重锚(2026-10-28——触发条件批孤注守势入池(w1,血量 ≤35% 情境入池):池 9/1/1; +; EV 抽样模拟器取无情境口径(trigger 行不过滤、每拍可摇)实测 0.9148,smoke EV 抽样带重锚 [0.82, 1.02]; +; 旧带 [1.00, 1.20] 系触发器前唯一特殊技=突刺的池结构下登记,随池构成换代作废)。 ; ; 分支节点图批(2026-09-17——L2 幽暗地域内容批,行值全部 provisional,投值归 难度曲线与Boss): ; 每战斗/Boss 节点 (2, node_depth) 精确行(跨表校验强制,违例加载致命——ConfigDB ④);锚行 (2,0) 保留。 diff --git a/game/tests/.gates/baseline.json b/game/tests/.gates/baseline.json index 9ad33901..dc18ff4c 100644 --- a/game/tests/.gates/baseline.json +++ b/game/tests/.gates/baseline.json @@ -1,5 +1,5 @@ { - "note": "存量基线·首次自动生成;闸况变化时本脚本会判红,需人工确认后重生成;2026-10-17 人工确认重生成 06 条目:af94ce97 把 gdd_lint 记为存量红(01 篇 R5),该红已由 fcb8c3f8 补流程图消除,实测 --docs 域 06 exit=0,故基线改回绿。2026-10-18 新增闸件 08c 流水线闸(tools/pipeline_gate.py 注册上电),手工加入绿记录(roadmap 压缩批实测 --docs 域 exit=0),其余条目原样保留。2026-10-22 测试术语与层级重构批 A 改键:01 冒烟全量→01 系统测试(同一断言面 smoke_all.gd,运行器换 tools/run_system_test.py,过渡期判定口径不变)、02 单元套件→02 单元与集成测试(同一 run_all.gd 入口,名从实)、新增 00 冒烟测试(tools/run_smoke.py+game/tests/smoke_boot.tscn,重写后单跑实测 17 项 0 失败 PASS);09 静态扫描基线 exit=1(fp=4354b2aa72a7)系滞后红,本批单跑实测 exit=0(与 2026-10-22 16:20 回执一致),基线改回绿;其余条目原样保留。;2026-10-23 主会话记 07 doc_link 为存量红(用户令忽略:锻造工坊.md 死链的修复在另一会话未合入,合回闸豁免;外部修复合入后应重生成基线归绿);2026-10-26 用户特批带红合并(迭代 38 收口):09 静态扫描记存量红——gdstyle 恶化 2 条(battle_orchestrator.gd max-file-length 1314>1302=卡④头注必载内容、level_map_screen.gd max-class-variables 22>21=卡①缓存成员,均为卡片义务的记账漂移非缺陷,压缩还债经计算不可行),用户裁「不管引入的恶化直接提交、特许免测试重跑」;后续批次若触及两文件可顺带还债或经批准重生成基线归绿;2026-10-27 用户裁「标准是尺、不以现状为尺」:09 存量红照实记(exit=1+现行红项指纹,两条恶化各自点名可核),gdstyle 基线登记值回退 1302/21(波 0 的 18 条陈旧键清理保留),gdstyle_gate 逐条违规行加 FAIL 前缀并加「refresh 禁抬高登记值」守卫——存量红期间任何新增违规或进一步恶化都会改指纹被拦;阈值口径不变=gdstyle 默认值(文件 1000 行/类变量 15 等),还债归迭代 40 卡①(battle_orchestrator 1314→≤1000)与迭代 41 卡③(level_map_screen 22→≤15),还清后重新生成基线归绿;2026-10-27 用户特批带红合并(迭代39 拆件批):02 记存量红(fp f74b9a48ef4a=round_flow EV 锚 goblin 0.9148∉[1.00,1.20],触发器批有意行为改动,旧带宽锚触发器前设计,重锚归后续数值批待用户发起);08d 记存量红(red-nokeys=生涯.md:55 引 adventure_runner.gd:814 行号漂移,B1 拆分后 660 行,另 :50/:60 与 元进度.md:70 建议级,修复归合并后文档批,反哺点在册);07 doc_link 基线红→现绿改善随下次基线重生成记账;09 指纹经 S9 注解修复(f96632de)回归登记值 91d45583cf6d", + "note": "存量基线·首次自动生成;闸况变化时本脚本会判红,需人工确认后重生成;2026-10-17 人工确认重生成 06 条目:af94ce97 把 gdd_lint 记为存量红(01 篇 R5),该红已由 fcb8c3f8 补流程图消除,实测 --docs 域 06 exit=0,故基线改回绿。2026-10-18 新增闸件 08c 流水线闸(tools/pipeline_gate.py 注册上电),手工加入绿记录(roadmap 压缩批实测 --docs 域 exit=0),其余条目原样保留。2026-10-22 测试术语与层级重构批 A 改键:01 冒烟全量→01 系统测试(同一断言面 smoke_all.gd,运行器换 tools/run_system_test.py,过渡期判定口径不变)、02 单元套件→02 单元与集成测试(同一 run_all.gd 入口,名从实)、新增 00 冒烟测试(tools/run_smoke.py+game/tests/smoke_boot.tscn,重写后单跑实测 17 项 0 失败 PASS);09 静态扫描基线 exit=1(fp=4354b2aa72a7)系滞后红,本批单跑实测 exit=0(与 2026-10-22 16:20 回执一致),基线改回绿;其余条目原样保留。;2026-10-23 主会话记 07 doc_link 为存量红(用户令忽略:锻造工坊.md 死链的修复在另一会话未合入,合回闸豁免;外部修复合入后应重生成基线归绿);2026-10-26 用户特批带红合并(迭代 38 收口):09 静态扫描记存量红——gdstyle 恶化 2 条(battle_orchestrator.gd max-file-length 1314>1302=卡④头注必载内容、level_map_screen.gd max-class-variables 22>21=卡①缓存成员,均为卡片义务的记账漂移非缺陷,压缩还债经计算不可行),用户裁「不管引入的恶化直接提交、特许免测试重跑」;后续批次若触及两文件可顺带还债或经批准重生成基线归绿;2026-10-27 用户裁「标准是尺、不以现状为尺」:09 存量红照实记(exit=1+现行红项指纹,两条恶化各自点名可核),gdstyle 基线登记值回退 1302/21(波 0 的 18 条陈旧键清理保留),gdstyle_gate 逐条违规行加 FAIL 前缀并加「refresh 禁抬高登记值」守卫——存量红期间任何新增违规或进一步恶化都会改指纹被拦;阈值口径不变=gdstyle 默认值(文件 1000 行/类变量 15 等),还债归迭代 40 卡①(battle_orchestrator 1314→≤1000)与迭代 41 卡③(level_map_screen 22→≤15),还清后重新生成基线归绿;2026-10-27 用户特批带红合并(迭代39 拆件批):02 记存量红(fp f74b9a48ef4a=round_flow EV 锚 goblin 0.9148∉[1.00,1.20],触发器批有意行为改动,旧带宽锚触发器前设计,重锚归后续数值批待用户发起);08d 记存量红(red-nokeys=生涯.md:55 引 adventure_runner.gd:814 行号漂移,B1 拆分后 660 行,另 :50/:60 与 元进度.md:70 建议级,修复归合并后文档批,反哺点在册);07 doc_link 基线红→现绿改善随下次基线重生成记账;09 指纹经 S9 注解修复(f96632de)回归登记值 91d45583cf6d;2026-10-28 EV 锚重锚批(工程改动·worktree ev-anchor-remeasure-20261028,用户特许会话内执行):02 基线红→现绿归绿——round_flow EV 锚 goblin 带宽按无情境口径(模拟器不过滤 trigger 行)重锚 [0.82,1.02](迭代39触发器批孤注守势入池稀释,实测 0.9148,重锚注记 enemy.tres 与测试注释;旧带 [1.00,1.20] 随池构成换代作废),撤销证明=带宽回退 [1.00,1.20] 断言复红;08d 存量红不变(生涯.md:55 行号漂移,修复归文档批)", "gates": { "00 冒烟测试": { "exit": "0", @@ -10,8 +10,8 @@ "fp": "green" }, "02 单元与集成测试": { - "exit": "1", - "fp": "f74b9a48ef4a" + "exit": "0", + "fp": "green" }, "03 探针 --click": { "exit": "0", diff --git a/game/tests/unit/battle_settlement/damage_controller_test.gd b/game/tests/unit/battle_settlement/damage_controller_test.gd index af439ce0..d2a58b9d 100644 --- a/game/tests/unit/battle_settlement/damage_controller_test.gd +++ b/game/tests/unit/battle_settlement/damage_controller_test.gd @@ -220,7 +220,7 @@ func _test_source_death_void(db) -> void: func _unit_fixture() -> Dictionary: return { "enemy_id": "fixture_enemy", - "display_name": "哥布林", + "display_name": "地精", "hp": 5, "max_hp": 5, "atk": 1, "pool": [], "pending_skill": "", "roll_seq": 0, "basic_streak": 0, "armor_type": "light", "armor_class": 0, "attack_type": "normal", diff --git a/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd b/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd index cc6a260f..17c78e42 100644 --- a/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd +++ b/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd @@ -746,14 +746,20 @@ func _record_pool_trajectories(seed_val: int, rounds: int) -> Dictionary: # ④ EV 抽样对锚(含闸长期速率 vs 静态锚——proposal §2.5;精确重锚归 难度曲线与Boss)。 # 带宽口径:熊地精/酋长 EV 结构性恒 1(普攻 1 + 重击 2 与蓄力/硬化 0 加权守恒)→ 窄带; -# 地精突刺池受保底闸抬升(唯一特殊技 w=1/10,保底 M=4 把突刺率从自然 10% 抬到 ~20%+)→ 宽带登记。 +# 地精池 {attack:9, lunge:1, desperate_guard:1}(触发条件批入池)——孤注守势是情境触发行(血量 ≤35% 才入真实可摇集合), +# 本模拟器取无情境口径(trigger 行不过滤、每拍可摇,把最坏情形当长期速率)→ 实测 0.9148; +# 2026-10-28 重锚 [0.82, 1.02](照酋长先例 ±0.10 绝对幅度,中值取理论稳态 0.92;旧带 [1.00,1.20] 系触发器前 +# 唯一特殊技=突刺的池结构下登记,随池构成换代作废;撤销证明=带宽回退旧值本断言复红)→ 宽带登记。 # ④ EV 抽样对锚(含闸长期速率 vs 静态锚——proposal §2.5;精确重锚归 难度曲线与Boss)。 # 带宽口径:熊地精/酋长 EV 结构性恒 1(普攻 1 + 重击 2 与蓄力/硬化 0 加权守恒)→ 窄带; -# 地精突刺池受保底闸抬升(唯一特殊技 w=1/10,保底 M=4 把突刺率从自然 10% 抬到 ~20%+)→ 宽带登记。 +# 地精池 {attack:9, lunge:1, desperate_guard:1}(触发条件批入池)——孤注守势是情境触发行(血量 ≤35% 才入真实可摇集合), +# 本模拟器取无情境口径(trigger 行不过滤、每拍可摇,把最坏情形当长期速率)→ 实测 0.9148; +# 2026-10-28 重锚 [0.82, 1.02](照酋长先例 ±0.10 绝对幅度,中值取理论稳态 0.92;旧带 [1.00,1.20] 系触发器前 +# 唯一特殊技=突刺的池结构下登记,随池构成换代作废;撤销证明=带宽回退旧值本断言复红)→ 宽带登记。 func _smoke_skill_pool_ev_anchor() -> void: - var bands := {"goblin": [1.00, 1.20], "bugbear": [0.97, 1.03], "ogre_chief": [1.10, 1.30]} # 酋长重锚(震地怒击半血解锁入池,含闸长期速率上移:实测 1.1948;EV 锚注 enemy.tres) + var bands := {"goblin": [0.82, 1.02], "bugbear": [0.97, 1.03], "ogre_chief": [1.10, 1.30]} # 地精重锚 2026-10-28(触发条件批孤注守势入池稀释,无情境口径实测 0.9148;EV 锚注 enemy.tres)· 酋长重锚(震地怒击半血解锁入池,含闸长期速率上移:实测 1.1948;EV 锚注 enemy.tres) var species := ["goblin", "bugbear", "ogre_chief"] var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(20260921) diff --git a/game/tests/unit/presentation/pacing_queue_test.gd b/game/tests/unit/presentation/pacing_queue_test.gd index 25178807..0b4fbdff 100644 --- a/game/tests/unit/presentation/pacing_queue_test.gd +++ b/game/tests/unit/presentation/pacing_queue_test.gd @@ -131,11 +131,11 @@ func _init() -> void: rp.stage = fstage rp.board_view = main.board_view rp.settlement_fx = ffx - rp._play_settlement_mark({"type": "damage", "target": "哥布林", "target_id": "goblin_b", "value": 3}) - check(fstage.calls.size() == 1 and fstage.calls[0] == ["goblin_b", "哥布林"], + rp._play_settlement_mark({"type": "damage", "target": "地精", "target_id": "goblin_b", "value": 3}) + check(fstage.calls.size() == 1 and fstage.calls[0] == ["goblin_b", "地精"], "结算标出按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕") - rp._play_cross_zone_fx({"type": "damage", "target": "哥布林", "target_id": "goblin_b", "value": 3}) - check(fstage.calls.size() == 2 and fstage.calls[1] == ["goblin_b", "哥布林"], + rp._play_cross_zone_fx({"type": "damage", "target": "地精", "target_id": "goblin_b", "value": 3}) + check(fstage.calls.size() == 2 and fstage.calls[1] == ["goblin_b", "地精"], "跨区弹道按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕") check(ffx.calls.size() == 2, "两路解析成功后演出层各接一拍(记参面非空)〔wd12〕") rp.free() diff --git a/game/tests/unit/presentation/standee_fx_sweep_test.gd b/game/tests/unit/presentation/standee_fx_sweep_test.gd index b533a59b..f7496895 100644 --- a/game/tests/unit/presentation/standee_fx_sweep_test.gd +++ b/game/tests/unit/presentation/standee_fx_sweep_test.gd @@ -65,8 +65,8 @@ func _init() -> void: var s2 = StandeeBodyScript.new("enemy") stage.world.add_child(s1) stage.world.add_child(s2) - s1.set_data({"display_name": "哥布林", "enemy_id": "goblin_a", "hp": 3, "max_hp": 3, "order": 1}) - s2.set_data({"display_name": "哥布林", "enemy_id": "goblin_b", "hp": 3, "max_hp": 3, "order": 2}) + s1.set_data({"display_name": "地精", "enemy_id": "goblin_a", "hp": 3, "max_hp": 3, "order": 1}) + s2.set_data({"display_name": "地精", "enemy_id": "goblin_b", "hp": 3, "max_hp": 3, "order": 2}) s1.position = Vector2(10, 20) s2.position = Vector2(200, 20) stage._cards.clear() @@ -78,15 +78,15 @@ func _init() -> void: Kit.check("空 id / 未登记 id 恒不命中(名兜底归调用点)〔wd12〕", stage._card_by_id("") == null and stage._card_by_id("no_such") == null) # 口一:on_step_row_fx —— 伤害行携 target_id,闪白落点须在 id 指向的站桩 - stage.on_step_row_fx({"type": "damage", "target": "哥布林", "target_id": "goblin_b"}) + stage.on_step_row_fx({"type": "damage", "target": "地精", "target_id": "goblin_b"}) await create_timer(0.6).timeout # 弹道到达拍 0.33s + 余量 Kit.check("伤害行按 target_id 命中正确站桩(闪白落点)〔wd12〕", s2._flash_count == 1 and s1._flash_count == 0) # 口二:enemy_standee_center —— id 先、display_name 兜底 - var c_b = stage.enemy_standee_center("goblin_b", "哥布林") + var c_b = stage.enemy_standee_center("goblin_b", "地精") var c_b_expect: Vector2 = stage.world_to_shell(s2.position + s2.box * 0.5) Kit.check("弹道落点按 target_id 取站桩中心〔wd12〕", c_b != null and c_b == c_b_expect) - var c_fallback = stage.enemy_standee_center("", "哥布林") + var c_fallback = stage.enemy_standee_center("", "地精") var c_fallback_expect: Vector2 = stage.world_to_shell(s1.position + s1.box * 0.5) Kit.check("无 target_id 时按名兜底同旧行为(首命中)〔wd12〕", c_fallback != null and c_fallback == c_fallback_expect) diff --git a/game/tests/验证集清单.md b/game/tests/验证集清单.md index f6d574c0..0dbc51ed 100644 --- a/game/tests/验证集清单.md +++ b/game/tests/验证集清单.md @@ -1,6 +1,6 @@ # 验证集清单(断言快照·冻结) -> 生成日期:2026-10-27 · 基点 commit:`eb7b6b39f269a35ae5d24b1f2e38b9e5b9e7d419` · 源:cross_system_flow_test.gd、node_map_determinism_test.gd、save_rng_roundtrip_test.gd、system_test.gd、damage_controller_test.gd、damage_math_test.gd、extended_row_violation_test.gd、roll_multiplier_test.gd、round_flow_skill_pool_test.gd、seal_polarity_test.gd、skill_unlock_test.gd、trigger_cond_test.gd、variant_placement_test.gd、source_guard_test.gd、system_contracts_test.gd、adventure_feats_test.gd、board_gen_reward_test.gd、board_generator_test.gd、breakpoint_resume_test.gd、config_db_cross_validator_test.gd、config_db_resolver_test.gd、curio_refresh_paid_test.gd、effect_words_t1_test.gd、feat_vouchers_test.gd、hero_ledger_test.gd、level_map_type_vis_test.gd、level_shop_economy_test.gd、level_table_validate_test.gd、meta_progression_forge_test.gd、minesweeper_rules_test.gd、node_map_generator_test.gd、node_map_growth_test.gd、pool_case_d_test.gd、run_time_fatal_test.gd、save_boot_no_activate_test.gd、save_manager_domain_test.gd、save_slot_isolation_test.gd、save_slot_summary_test.gd、settle_segments_test.gd、treasure_effects_test.gd、treasure_items_test.gd、tree_requires_level_test.gd、tree_rules_v11_test.gd、config_db_fatal_oob_test.gd、config_db_test.gd、counter_prefix_fatal_test.gd、forge_table_test.gd、level_gen_params_test.gd、reward_dangling_treasure_test.gd、rng_service_test.gd、rng_stream_boot_test.gd、table_structure_guard_test.gd、treasure_target_violation_test.gd、example_test.gd、battle_narrator_test.gd、forge_workbench_test.gd、hud_presenter_test.gd、level_map_info_fog_test.gd、modal_flow_test.gd、pacing_queue_test.gd、player_copy_sweep_test.gd、reward_overlay_test.gd、standee_fx_sweep_test.gd、terrain_tile_sets_test.gd、theme_projection_test.gd、type_glow_test.gd、ui_font_asset_test.gd、test_kit.gd +> 生成日期:2026-10-28 · 基点 commit:`8a31936958b7422cfc726827cfe655a902dd882a` · 源:cross_system_flow_test.gd、node_map_determinism_test.gd、save_rng_roundtrip_test.gd、system_test.gd、damage_controller_test.gd、damage_math_test.gd、extended_row_violation_test.gd、roll_multiplier_test.gd、round_flow_skill_pool_test.gd、seal_polarity_test.gd、skill_unlock_test.gd、trigger_cond_test.gd、variant_placement_test.gd、source_guard_test.gd、system_contracts_test.gd、adventure_feats_test.gd、board_gen_reward_test.gd、board_generator_test.gd、breakpoint_resume_test.gd、config_db_cross_validator_test.gd、config_db_resolver_test.gd、curio_refresh_paid_test.gd、effect_words_t1_test.gd、feat_vouchers_test.gd、hero_ledger_test.gd、level_map_type_vis_test.gd、level_shop_economy_test.gd、level_table_validate_test.gd、meta_progression_forge_test.gd、minesweeper_rules_test.gd、node_map_generator_test.gd、node_map_growth_test.gd、pool_case_d_test.gd、run_time_fatal_test.gd、save_boot_no_activate_test.gd、save_manager_domain_test.gd、save_slot_isolation_test.gd、save_slot_summary_test.gd、settle_segments_test.gd、treasure_effects_test.gd、treasure_items_test.gd、tree_requires_level_test.gd、tree_rules_v11_test.gd、config_db_fatal_oob_test.gd、config_db_test.gd、counter_prefix_fatal_test.gd、forge_table_test.gd、level_gen_params_test.gd、reward_dangling_treasure_test.gd、rng_service_test.gd、rng_stream_boot_test.gd、table_structure_guard_test.gd、treasure_target_violation_test.gd、example_test.gd、battle_narrator_test.gd、forge_workbench_test.gd、hud_presenter_test.gd、level_map_info_fog_test.gd、modal_flow_test.gd、pacing_queue_test.gd、player_copy_sweep_test.gd、reward_overlay_test.gd、standee_fx_sweep_test.gd、terrain_tile_sets_test.gd、theme_projection_test.gd、type_glow_test.gd、ui_font_asset_test.gd、test_kit.gd > 提取口径:静态 `check(` 调用点,括号配平归集(可跨行);缺省源=三宿主遍历 > (unit/**+integration/**+system_test.gd)。本基点实测 1604 个静态调用点;行级 > `grep -c "check("` 是另一口径(含 `func check(` 定义行与注释行),两口径各自浮动, @@ -489,66 +489,66 @@ | 264 | 715 | "多实例种子可达(seed=%d——D3 遭遇 ≥2 实例)" ↩ % seed_val | seed_val > 0 | (待填) | | | | 265 | 721 | "同种子回放:各实例摇定动作序列逐位相同(×%d 轮 × %d 实例——子流独立复放面随并流退役)" ↩ % [rounds, int(run1.count)] | not run1.is_empty() and JSON.stringify(run1.seqs) == JSON.stringify(run2.seqs) | (待填) | | | -## S43 _smoke_skill_pool_ev_anchor(行 803–803 · 1 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) +## S43 _smoke_skill_pool_ev_anchor(行 809–809 · 1 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 266 | 803 | "EV 抽样对锚 %s(实测 %.4f ∈ [%.2f, %.2f] 含闸长期速率,×%d 拍)" ↩ % [eid, measured, float(band[0]), float(band[1]), n_beats] | in_band | (待填) | | | +| 266 | 809 | "EV 抽样对锚 %s(实测 %.4f ∈ [%.2f, %.2f] 含闸长期速率,×%d 拍)" ↩ % [eid, measured, float(band[0]), float(band[1]), n_beats] | in_band | (待填) | | | -## S44 _smoke_skill_pool_death_void(行 823–842 · 5 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) +## S44 _smoke_skill_pool_death_void(行 829–848 · 5 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 267 | 823 | "死亡打断种子可达(seed=%d——D2 首拍摇中特殊技)" ↩ % void_seed | void_seed > 0 | (待填) | | | -| 268 | 829 | "死亡打断战斗启动(hero_atk 999——先手必杀 40HP 熊地精)" | settlement.begin_battle({"level_index": 1, "node_depth": 2, "hero_hp": int(_db.hero.max_hp), "hero_atk": 999}) | (待填) | | | -| 269 | 832 | "开轮已摇定本拍动作(待发 = %s)" ↩ % pending | pending != "" | (待填) | | | -| 270 | 838 | "先手击杀 → 摇定技能作废(第 1 轮零敌方行动行——死亡即不动手)" | enemy_rows == 0 | (待填) | | | -| 271 | 842 | "作废不进账(全池冷却 0 · 保底计数 0——执行上报未发生)" | cd_sum == 0 and int(u.basic_streak) == 0 | (待填) | | | +| 267 | 829 | "死亡打断种子可达(seed=%d——D2 首拍摇中特殊技)" ↩ % void_seed | void_seed > 0 | (待填) | | | +| 268 | 835 | "死亡打断战斗启动(hero_atk 999——先手必杀 40HP 熊地精)" | settlement.begin_battle({"level_index": 1, "node_depth": 2, "hero_hp": int(_db.hero.max_hp), "hero_atk": 999}) | (待填) | | | +| 269 | 838 | "开轮已摇定本拍动作(待发 = %s)" ↩ % pending | pending != "" | (待填) | | | +| 270 | 844 | "先手击杀 → 摇定技能作废(第 1 轮零敌方行动行——死亡即不动手)" | enemy_rows == 0 | (待填) | | | +| 271 | 848 | "作废不进账(全池冷却 0 · 保底计数 0——执行上报未发生)" | cd_sum == 0 and int(u.basic_streak) == 0 | (待填) | | | -## S45 _smoke_skill_pool_validation_reject(行 853–889 · 13 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) +## S45 _smoke_skill_pool_validation_reject(行 859–895 · 13 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 272 | 853 | "加载校验拒绝:池条目 skill_id 悬空致命" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "dangling_skill") | (待填) | | | -| 273 | 855 | "加载校验拒绝:池普攻行数 ≠ 1(空池不可能前提)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "pool_composition") | (待填) | | | -| 274 | 860 | "加载校验拒绝:池增益技 > 1(每池增益 ≤1 纪律)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "pool_composition") | (待填) | | | -| 275 | 862 | "加载校验拒绝:普攻配倍率 ≠ 1(域校验锁死)" | not skill_table.validate().is_empty() | (待填) | | | -| 276 | 864 | "加载校验拒绝:普攻配冷却 ≠ 0(域校验锁死)" | not skill_table.validate().is_empty() | (待填) | | | -| 277 | 866 | "加载校验拒绝:damage_mult 越域 [1.1,16]" | not skill_table.validate().is_empty() | (待填) | | | -| 278 | 869 | "加载校验拒绝:池权重 ≤ 0" | not et2.validate().is_empty() | (待填) | | | -| 279 | 871 | "加载校验拒绝:空池(禁)" | not et2.validate().is_empty() | (待填) | | | -| 280 | 877 | "加载校验拒绝:池妨害技 > 1(每池妨害 ≤1 纪律)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "pool_composition") | (待填) | | | -| 281 | 879 | "加载校验拒绝:妨害技缺 buff_ref(效果引用)" | not skill_table.validate().is_empty() | (待填) | | | -| 282 | 881 | "加载校验拒绝:rider_mult 越域 (0,1]" | not skill_table.validate().is_empty() | (待填) | | | -| 283 | 883 | "加载校验拒绝:非伤害技带必中附加分量" | not skill_table.validate().is_empty() | (待填) | | | -| 284 | 889 | "加载校验拒绝:妨害技引用敌方侧状态(施放类 side 守卫)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table, _db.status_effects), "cast_side") | (待填) | | | +| 272 | 859 | "加载校验拒绝:池条目 skill_id 悬空致命" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "dangling_skill") | (待填) | | | +| 273 | 861 | "加载校验拒绝:池普攻行数 ≠ 1(空池不可能前提)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "pool_composition") | (待填) | | | +| 274 | 866 | "加载校验拒绝:池增益技 > 1(每池增益 ≤1 纪律)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "pool_composition") | (待填) | | | +| 275 | 868 | "加载校验拒绝:普攻配倍率 ≠ 1(域校验锁死)" | not skill_table.validate().is_empty() | (待填) | | | +| 276 | 870 | "加载校验拒绝:普攻配冷却 ≠ 0(域校验锁死)" | not skill_table.validate().is_empty() | (待填) | | | +| 277 | 872 | "加载校验拒绝:damage_mult 越域 [1.1,16]" | not skill_table.validate().is_empty() | (待填) | | | +| 278 | 875 | "加载校验拒绝:池权重 ≤ 0" | not et2.validate().is_empty() | (待填) | | | +| 279 | 877 | "加载校验拒绝:空池(禁)" | not et2.validate().is_empty() | (待填) | | | +| 280 | 883 | "加载校验拒绝:池妨害技 > 1(每池妨害 ≤1 纪律)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table), "pool_composition") | (待填) | | | +| 281 | 885 | "加载校验拒绝:妨害技缺 buff_ref(效果引用)" | not skill_table.validate().is_empty() | (待填) | | | +| 282 | 887 | "加载校验拒绝:rider_mult 越域 (0,1]" | not skill_table.validate().is_empty() | (待填) | | | +| 283 | 889 | "加载校验拒绝:非伤害技带必中附加分量" | not skill_table.validate().is_empty() | (待填) | | | +| 284 | 895 | "加载校验拒绝:妨害技引用敌方侧状态(施放类 side 守卫)" | _has_err_category(_db.validate_skill_pool_links(skill_table, enemy_table, _db.status_effects), "cast_side") | (待填) | | | -## S46 _smoke_debuff_rider(行 967–969 · 3 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) +## S46 _smoke_debuff_rider(行 973–975 · 3 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 285 | 967 | "毒爆必中附加分量种子可达(seed=%d,毒爆伤害行 ×%d)" ↩ % [venom_seed, venom_rows_seen] | venom_seed > 0 and venom_rows_seen >= 1 | (待填) | | | -| 286 | 968 | "毒爆伤害行逐拍精确复算:终值 = max(1, 掷点档位主分量) + 必中附加(rider 只随 rider_mult 行出现)" | venom_check_ok | (待填) | | | -| 287 | 969 | "蛛网束缚落主角:施放后掷点阈值 = 基准 AC + 失衡幅度(off_guard ac 轴端到端,seed=%d)" ↩ % snare_seed | snare_seed > 0 | (待填) | | | +| 285 | 973 | "毒爆必中附加分量种子可达(seed=%d,毒爆伤害行 ×%d)" ↩ % [venom_seed, venom_rows_seen] | venom_seed > 0 and venom_rows_seen >= 1 | (待填) | | | +| 286 | 974 | "毒爆伤害行逐拍精确复算:终值 = max(1, 掷点档位主分量) + 必中附加(rider 只随 rider_mult 行出现)" | venom_check_ok | (待填) | | | +| 287 | 975 | "蛛网束缚落主角:施放后掷点阈值 = 基准 AC + 失衡幅度(off_guard ac 轴端到端,seed=%d)" ↩ % snare_seed | snare_seed > 0 | (待填) | | | -## S47 _smoke_counter_buckets(行 992–1031 · 7 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) +## S47 _smoke_counter_buckets(行 998–1037 · 7 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 288 | 992 | "V1 第1战真实 request_dig 受理(begin_battle 后 ACTIVE 相位)〔无状态化 V1〕" | dig1 | (待填) | | | -| 289 | 993 | "V1 第1战付费挖格经 ctx 就地写 adventure 桶=1(无 export 搬运时点)〔无状态化 V1〕" | int(led.get("adv_twin_digs", 0)) == 1 | (待填) | | | -| 290 | 999 | "V1 第2战 begin_battle 经 ctx 读到上一战持久值=1(读路径走宿主字典引用,非副本种子回灌)〔无状态化 V1〕" | EffectEngine.counter(o2.fx_host().counters_ctx, "adv_twin_digs") == 1 | (待填) | | | -| 291 | 1001 | "V1 第2战挖后 adventure 桶跨战累积=2(共享账判空早退缺陷消解的回归钉面——旧副本态恒 1)〔无状态化 V1〕" | int(led.get("adv_twin_digs", 0)) == 2 | (待填) | | | -| 292 | 1018 | "V6 第1战标错落 battle 桶 insurance_used=1(_apply_counter_hit 静态写口经 ctx)〔无状态化 V6〕" | EffectEngine.counter(oA.fx_host().counters_ctx, "insurance_used") == 1 | (待填) | | | -| 293 | 1024 | "卡④ wr2①:完美保险标错行 type=extended 且 effect_id=insurance_used(effect_id 必载)〔明细收敛 V2〕" | not v6_ins.is_empty() and String(v6_ins.get("type", "")) == "extended" and String(v6_ins.get("source_class", "")) == "seal_miss" and bool(v6_ins.get("forgiven", 0)) | (待填) | | | -| 294 | 1031 | "V6 battle 桶随宿主销毁:次战新编排器 fx_counters_battle 天然空,读 insurance_used=0〔无状态化 V6〕" | EffectEngine.counter(oB.fx_host().counters_ctx, "insurance_used") == 0 | (待填) | | | +| 288 | 998 | "V1 第1战真实 request_dig 受理(begin_battle 后 ACTIVE 相位)〔无状态化 V1〕" | dig1 | (待填) | | | +| 289 | 999 | "V1 第1战付费挖格经 ctx 就地写 adventure 桶=1(无 export 搬运时点)〔无状态化 V1〕" | int(led.get("adv_twin_digs", 0)) == 1 | (待填) | | | +| 290 | 1005 | "V1 第2战 begin_battle 经 ctx 读到上一战持久值=1(读路径走宿主字典引用,非副本种子回灌)〔无状态化 V1〕" | EffectEngine.counter(o2.fx_host().counters_ctx, "adv_twin_digs") == 1 | (待填) | | | +| 291 | 1007 | "V1 第2战挖后 adventure 桶跨战累积=2(共享账判空早退缺陷消解的回归钉面——旧副本态恒 1)〔无状态化 V1〕" | int(led.get("adv_twin_digs", 0)) == 2 | (待填) | | | +| 292 | 1024 | "V6 第1战标错落 battle 桶 insurance_used=1(_apply_counter_hit 静态写口经 ctx)〔无状态化 V6〕" | EffectEngine.counter(oA.fx_host().counters_ctx, "insurance_used") == 1 | (待填) | | | +| 293 | 1030 | "卡④ wr2①:完美保险标错行 type=extended 且 effect_id=insurance_used(effect_id 必载)〔明细收敛 V2〕" | not v6_ins.is_empty() and String(v6_ins.get("type", "")) == "extended" and String(v6_ins.get("source_class", "")) == "seal_miss" and bool(v6_ins.get("forgiven", 0)) | (待填) | | | +| 294 | 1037 | "V6 battle 桶随宿主销毁:次战新编排器 fx_counters_battle 天然空,读 insurance_used=0〔无状态化 V6〕" | EffectEngine.counter(oB.fx_host().counters_ctx, "insurance_used") == 0 | (待填) | | | -## S48 _smoke_extended_rows(行 1058–1077 · 2 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) +## S48 _smoke_extended_rows(行 1064–1083 · 2 条 · 源 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 295 | 1058 | "卡④ wr2②:专长揭示兑付行 type=extended 且 effect_id=fx_reveal 且来源格真实〔明细收敛 V2〕" | not paid.is_empty() and String(paid.get("type", "")) == "extended" and Vector2i(paid["origin_cell"][0], paid["origin_cell"][1]).x >= 0 | (待填) | | | -| 296 | 1075 | "卡④ wr2③:揭示落空行 type=extended 且 effect_id=fx_reveal 且 origin_cell=越界哨值〔明细收敛 V2〕" | not missed.is_empty() and String(missed.get("type", "")) == "extended" and Vector2i(missed["origin_cell"][0], missed["origin_cell"][1]).x == -1 | (待填) | | | +| 295 | 1064 | "卡④ wr2②:专长揭示兑付行 type=extended 且 effect_id=fx_reveal 且来源格真实〔明细收敛 V2〕" | not paid.is_empty() and String(paid.get("type", "")) == "extended" and Vector2i(paid["origin_cell"][0], paid["origin_cell"][1]).x >= 0 | (待填) | | | +| 296 | 1081 | "卡④ wr2③:揭示落空行 type=extended 且 effect_id=fx_reveal 且 origin_cell=越界哨值〔明细收敛 V2〕" | not missed.is_empty() and String(missed.get("type", "")) == "extended" and Vector2i(missed["origin_cell"][0], missed["origin_cell"][1]).x == -1 | (待填) | | | ## S49 _smoke_seal_ap_exhausted(行 54–80 · 5 条 · 源 game/tests/unit/battle_settlement/seal_polarity_test.gd · 去向:待分类回填) @@ -2311,8 +2311,8 @@ | 1381 | 117 | "末信号行原文在明细带(排空不吞行:『%s』)" ↩ % last_text | last_text != "" and main.log_view.parsed_text().contains(last_text) | (待填) | | | | 1382 | 123 | "常态段间延迟 >0 且 ≥ 段内(%f/%f)" ↩ % [d_on, d_same] | d_on > 0.0 and d_on >= d_same | (待填) | | | | 1383 | 125 | "减动效段间延迟归零(行不跳过——同帧直落快路)" | main.pace_delay_for("damage", "heal") == 0.0 | (待填) | | | -| 1384 | 135 | "结算标出按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 1 and fstage.calls[0] == ["goblin_b", "哥布林"] | (待填) | | | -| 1385 | 138 | "跨区弹道按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 2 and fstage.calls[1] == ["goblin_b", "哥布林"] | (待填) | | | +| 1384 | 135 | "结算标出按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 1 and fstage.calls[0] == ["goblin_b", "地精"] | (待填) | | | +| 1385 | 138 | "跨区弹道按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 2 and fstage.calls[1] == ["goblin_b", "地精"] | (待填) | | | | 1386 | 140 | "两路解析成功后演出层各接一拍(记参面非空)〔wd12〕" | ffx.calls.size() == 2 | (待填) | | | | 1387 | 147 | "会话更替夹具已入队(前提:%d 行)〔wr4〕" ↩ % main._row_queue.size() | main._row_queue.size() == 2 | (待填) | | | | 1388 | 149 | "会话更替后待播队列清零(_begin_session 内机制 flush)〔wr4〕" | main._row_queue.is_empty() | (待填) | | | diff --git a/reports/iter39-实现报告-2026-10-27.md b/reports/iter39-实现报告-2026-10-27.md index 489b101b..49490ab6 100644 --- a/reports/iter39-实现报告-2026-10-27.md +++ b/reports/iter39-实现报告-2026-10-27.md @@ -45,3 +45,19 @@ ## 五、中间产物退役清单(批末执行) game/tests/bp_baseline_dump.gd(bp1 载体)+reports/iter39-素材/ 六份 JSON(对拍凭据,审计后随本报告退役)。 + +## 六、领域拆分批(v1.3)补记与收口遗留清单(2026-10-27 合并前补) + +§一–§五 写于三卡收口时点;其后用户裁「不满足结构指标也是缺陷、按领域做分割」,三卡以 v1.3 在批内追加领域拆分并二次实现。本节补记拆分批事实与收口遗留,收口以本节为唯一口径。 + +**拆分批提交**:B1 主角账三件 fde14f1c(hero_ledger 整件退役→hero_stats/gp_wallet/gain_journal);修复A 4ca4ddbc(trigger_cond_test 旧成员读换代+adventure_runner:170 残留删除);B2 停点刷新账 012883f3(refresh_bank 新件);B3 私有助手抽取 45faa92b(含 cross_validator 入循环重复追加缺陷修复);B4 战斗指标面 741b6bd7;修复B f96632de(S9 返回类型注解);闸基线 3530144e(02/08d 特批存量红登记)。合并 master=ffb0ac15(用户特批带红合并)。 + +**§三 存量红面已被拆分清偿,建议案作废**:NEW 5 条(curio_stop 4/hero_ledger 1)随 B1/B2 拆分归零;WORSENED 4 条中 battle_orchestrator 类变量与 begin_battle 函数长经 B4 修复、文件长回注册值 1314。终局读数=gdstyle 基线外新违规 0、恶化恰 2 条(battle_orchestrator max-file-length 1314〔登记 1302〕、level_map_screen max-class-variables 22〔登记 21〕——存量债归迭代 40 卡①与迭代 41 卡③,与 iter38 账目一致)。§三「建议案:refresh 9 键」作废(2026-10-27 用户裁「标准是尺、不以现状为尺」后基线只降不升)。 + +**收口遗留清单(全在案,按处置去向分组)**: +1. **EV 锚**:round_flow goblin(地精)场景实测 0.9148 ∉ [1.00,1.20]——触发器批有意行为改动,非缺陷。已按用户特批(2026-10-27)随 02 闸记存量红(fp f74b9a48ef4a)合并;参考区间更新归后续数值批,待用户发起。 +2. **生涯.md:55 引 adventure_runner.gd:814 行号漂移**(拆分后该文件 660 行)——08d 记存量红(red-nokeys)合并;修复归合并后文档批(反哺点在册);建议级同行:生涯.md :50/:60、元进度.md:70。 +3. **第 8 份对拍凭据 bp_baseline_after_split_B1.json 未入库**——08d 存量红期间纯文档提交被钩子拦(无代码改动可随行),已置主仓 reports/iter39-素材/(未跟踪),随文档批一并入库。 +4. **本报告与验收审计报告停在 v1.2 口径**(§一–§五 未反映拆分)——实际落地以 v1.3 卡片与上列提交为准,文档批换代;本节即补记。 +5. **批后收尾未执行**(待办清单/roadmap 账面换代、§五 退役清单执行——退役凭据实为八份 JSON,§五 笔数按拆分前口径写的六份)——待用户另令 batch-closure。 +6. **交接注记**:迭代 40 卡①(gdstyle 波 1)卡面接口块仍引用已退役的 RunLedger——该批 T0 须按现态改写。