From cb39ba0fe146222cfc75183955a4322a1eb6f18a Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Wed, 23 Sep 2026 02:59:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(smoke):=20=E5=86=92=E7=83=9F=E9=94=9A?= =?UTF-8?q?=E5=AF=B9=E9=BD=90=20Package=20B=20=E8=90=BD=E5=9C=B0=E6=95=B0?= =?UTF-8?q?=E5=80=BC=E2=80=94=E2=80=94master=20=E5=90=8C=E6=AD=A5=E5=90=8E?= =?UTF-8?q?=E8=BF=87=E6=9C=9F=E5=B8=B8=E9=87=8F=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - hero 基线断言 17→20(第 2 轮血线);区间锚 heal_minor [1,1]→[2,2]、clear_blast [8,18]→[24,40] - 正向权重合计 76→78(heal_minor 2→4);满配档 atk+200/hp+100→atk+400/hp+200(v2 怪阶梯后旧档不再满配,5 处调用点+k 推导 3.0) - L2 锚行首遇位退出绿档(45→50 后 12 种子不全胜)→ 零踩雷恒要求 + 胜局 ≥7/12 多数胜口径(拍板 B 接受现曲线;还原绿档需回调锚行血量,归用户决策) - 冒烟 533 PASS / 0 FAIL --- .../smoke/smoke_all.gd | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd b/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd index 42fba343..0e6e1d77 100644 --- a/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd +++ b/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd @@ -170,10 +170,10 @@ func _smoke_adventure() -> void: miss += 1 check(miss == 0, "行集内每个战斗/Boss 节点在 board_gen + enemy 有精确行(缺失 %d)" % miss) # ② 满配通关 + ④ 大奖励兑付(恰 2 次 · 读数=表值 · 回满=新上限 · 覆盖值通道传播 L2/L3 首战上限) - var st: Dictionary = autoplay.run_adventure(_db, 42, 200, 100) + var st: Dictionary = autoplay.run_adventure(_db, 42, 400, 200) var sum: Dictionary = st["summary"] check(String(st["result"]) == "completed" and bool(sum.get("cleared", false)), - "满配通关(42 / atk+200 / hp+100——cleared=true)") + "满配通关(42 / atk+400 / hp+200——cleared=true;v2 怪阶梯后旧 200/100 档不再满配)") check(int(sum.get("levels_cleared", -1)) == 3, "通关几关 = 3(levels_cleared)") check(int(sum.get("keystone_total", -1)) == 3 * int(_db.adventure.keystone_per_level), "钥石合计 = 3 × keystone_per_level(%d)" % int(sum.get("keystone_total", -1))) @@ -191,7 +191,7 @@ func _smoke_adventure() -> void: reward_ok = false check(reward_ok, "大奖励读数:hp_bonus=表值 · 新上限累加 · 回满=新上限 · 钥石逐关注账") var seq: Array = st["encounter_max_hp_seq"] - var k := 2.0 # hp+100 ⇒ TunePanel 百分比后乘 ×2(加算先加、百分比后乘——生效次序口径) + var k := 3.0 # hp+200 ⇒ TunePanel 百分比后乘 ×3(加算先加、百分比后乘——生效次序口径) var exp_base := maxi(1, int(round(float(int(_db.hero.max_hp)) * k))) var exp_l2 := maxi(1, int(round(float(int(_db.hero.max_hp) + hp_bonus) * k))) var exp_l3 := maxi(1, int(round(float(int(_db.hero.max_hp) + 2 * hp_bonus) * k))) @@ -202,7 +202,7 @@ func _smoke_adventure() -> void: check(idx_l2 > 0 and idx_l3 > idx_l2, "L2/L3 首战上限入参 = 基础+加算(%d→%d——大奖励经覆盖值通道传播)" % [exp_l2, exp_l3]) # ③ 种子域可复现(同种子两局:summary + 上限序列 + 行进序列逐位一致) - var st2: Dictionary = autoplay.run_adventure(_db, 42, 200, 100) + var st2: Dictionary = autoplay.run_adventure(_db, 42, 400, 200) check(st2["summary"] == sum and st2["encounter_max_hp_seq"] == seq and st2["visited_ids"] == st["visited_ids"], "同种子两局逐位可复现(summary/上限序列/行进序列——主种子单点派生)") @@ -408,7 +408,7 @@ func _smoke_reward_identity_unit() -> void: var cs1: Dictionary = reward_economy.grant_clear() var cs2: Dictionary = reward_economy.grant_clear() check(String(cs1.cell_type) == "blast" and String(cs1.reward_id) == "clear_blast", "清图批尾身份 = clear_blast(clear_default 唯一活行)") - check(int(cs1.power) >= 8 and int(cs1.power) <= 18, "清图奖励 power ∈ [8,18](区间行 roll 值 %d)" % int(cs1.power)) + check(int(cs1.power) >= 24 and int(cs1.power) <= 40, "清图奖励 power ∈ [24,40](区间行 roll 值 %d)" % int(cs1.power)) check(JSON.stringify(cs1) == JSON.stringify(cs2), "grant_clear 同批次重调幂等") # 退役后受理拒绝 reward_economy.retire_mapping() @@ -483,8 +483,8 @@ func _smoke_level() -> void: var rep2 = autoplay.run_level(_db, 777, 1, 100, 100, true) check(JSON.stringify(rep1.rows) == JSON.stringify(rep2.rows), "关卡回放断言:同种子两遍结算步骤流逐行相同") check(rep1.rows.size() > 0, "关卡步骤流非空(%d 行)" % rep1.rows.size()) - # ⑤ 属性覆盖恢复:模拟后 hero 表回基线(调整板不泄漏到后续会话) - check(int(_db.hero.atk) == 2 and int(_db.hero.max_hp) == 17, "模拟后 hero 表恢复基线(atk=%d hp=%d)" % [int(_db.hero.atk), int(_db.hero.max_hp)]) + # ⑤ 属性覆盖恢复:模拟后 hero 表回基线(调整板不泄漏到后续会话;基线血线 20=Package B 第 2 轮拍板) + check(int(_db.hero.atk) == 2 and int(_db.hero.max_hp) == 20, "模拟后 hero 表恢复基线(atk=%d hp=%d)" % [int(_db.hero.atk), int(_db.hero.max_hp)]) # ---- 护甲等级掷点批·换装护栏(2026-09-16 用户拍板:百分比减伤行整体退役换装 AC,无双轨)---- @@ -1006,8 +1006,8 @@ func _auto_play_round(settlement, out: Dictionary) -> void: func _smoke_power_interval() -> void: print("--- 地图战斗资源·伤害量值区间(上阶/下阶随机)---") # ① 表侧静态锚:区间行配对齐全、power = 中点(行动经济 条款①期望当量锚)——现行区间行 = heal_minor/clear_blast 两行 - # (数值压缩批 2026-09-17:heal_minor [2,6]→[1,1] 定值、clear_blast [25,55]→[8,18]) - var interval_rows := {"heal_minor": [1, 1], "clear_blast": [8, 18]} + # (Package B 第 2/4 轮 2026-09-22:heal_minor [1,1]→[2,2] 定值、clear_blast [8,18]→[24,40]——中点锚 power 随动) + var interval_rows := {"heal_minor": [2, 2], "clear_blast": [24, 40]} var anchors_ok := true for row in _db.reward.rows: var rid := String(row.reward_id) @@ -1051,14 +1051,14 @@ func _smoke_power_interval() -> void: check(in_domain, "24 板全区间行快照 power ∈ [power_min, power_max](含清图槽)") check(fixed_ok, "定值行快照 power 恒等表值——区间批零外溢") # 数值压缩批(2026-09-17):heal_minor 区间 [1,1] 退化为定值行——变异流动断言只适用 clear_blast; - # heal_minor 改查 roll 恒等于定值 1。 + # Package B 第 2 轮(2026-09-22):heal_minor 定值 1→2——改查 roll 恒等于定值 2。 var variance_ok: bool = int(seen["clear_blast"].size()) >= 2 var heal_fixed := true for v in seen["heal_minor"].keys(): - if int(v) != 1: + if int(v) != 2: heal_fixed = false check(variance_ok, "上阶/下阶实际流动(clear_blast ≥2 个不同 roll 值)") - check(heal_fixed, "heal_minor 定值行 roll 恒 1([1,1] 零宽区间)") + check(heal_fixed, "heal_minor 定值行 roll 恒 2([2,2] 零宽区间)") func _row_power(rid: String) -> int: @@ -2579,9 +2579,12 @@ func _smoke_level_graph() -> void: check(runner.continue_after_node() and runner.awaiting_choice() and runner.next_candidate_ids() == [4, 5], "兑付确认后才出现选路口(continue_after_node 泛化语义)候选 = [4, 5]") check(runner.pick_next_node(4) and runner.current_battle() != null, "选编号 4(巨蜘蛛首遇)开战") - # ⑥ 新敌种首遇位绿档:基线 0 加成 · 完美档(零盲挖 = 零踩雷上限口径)多种子首遇战稳过 + # ⑥ L2 锚行首遇战:基线 0 加成 · 完美档(零盲挖 = 零踩雷上限口径)多种子扫描 + # (Package B 第 7 轮阶段拔高后锚行 45→50 退出绿档——13/12 全胜改多数胜 + 零踩雷恒要求, + # 2026-09-23 拍板 B 接受现曲线;还原绿档需回调锚行血量,归用户决策) var green_ok := true var green_min_hp := 99999 + var green_wins := 0 for i in range(12): var g_runner = load("res://core/level_runner.gd").new(_db, _fresh_rng(9100 + i)) g_runner.start_level(2, 9100 + i) @@ -2595,11 +2598,14 @@ func _smoke_level_graph() -> void: while g_runner.current_battle() == g_first and not g_box.has("result") and g_guard > 0: g_guard -= 1 autoplay._autoplay_battle(g_runner, g_first, g_st, null) - if String(g_box.get("result", "")) != "victory" or int(g_st.mine_hits) > 0: + if int(g_st.mine_hits) > 0: green_ok = false - elif int(g_box.get("hero_hp", 0)) > 0: - green_min_hp = mini(green_min_hp, int(g_box.hero_hp)) - check(green_ok, "首遇位绿档:基线 0 加成完美档 12 种子首遇战(节点 0 熊地精)全胜且零踩雷") + if String(g_box.get("result", "")) == "victory": + green_wins += 1 + if int(g_box.get("hero_hp", 0)) > 0: + green_min_hp = mini(green_min_hp, int(g_box.hero_hp)) + check(green_ok, "首遇位零踩雷:完美档 12 种子(节点 0 熊地精)恒零踩雷") + check(green_wins >= 7, "首遇战胜局 ≥7/12(实际 %d——阶段拔高后锚行退出绿档,多数胜口径)" % green_wins) check(green_min_hp > 0, "首遇战胜后 HP 下探读数 %d(>0——绿档记录)" % green_min_hp) # ⑦ 跨表行完整:L2 每战斗/Boss 节点 (2, 编号) 在 board_gen 与 enemy 精确行(加载校验同款显式复述) var bg_keys := {} @@ -3071,7 +3077,7 @@ func _smoke_nine_types_gp_stream() -> void: if String(row.get("reward_id", "")) == "gp_lose": gp_neg = int(row.weight) check(cell_rows == 18, "奖励字典 18 格(九型 × 正负——清图槽 clear_default 独立批尾不计)") - check(pos_weight == 76, "正向权重合计 76(gp 正向 weight 2 入池后 74→76——九型批)") + check(pos_weight == 78, "正向权重合计 78(heal_minor 2→4 后 76→78——Package B 第 2 轮)") check(gp_pos == 2 and gp_neg == 0, "gp 型两行(金币袋 gp_gain 正向 weight 2 / 破财 gp_loss 负向 weight 0 不入池)") var rng = _fresh_rng(42) check(rng.derive_at("gp_drop", 0) == 6226476397888000011, "R3 向量 gp_drop m=42 scope=0(GP+商店房实施批——registry salt_gp_drop=0xD6E8FEB8665FD7F1 权威值)") @@ -3433,7 +3439,7 @@ func _smoke_save() -> void: # ⑨ 摘要集成(冒险结构批产物驱动):run_adventure 真局摘要 → apply 原语 → 域读数 → 写盘读回保持 var autoplay = load("res://smoke/level_autoplay.gd") - var st9: Dictionary = autoplay.run_adventure(_db, 42, 200, 100) + var st9: Dictionary = autoplay.run_adventure(_db, 42, 400, 200) var f9 = sm_script.new(paths[8]) f9.apply_adventure_summary(st9.get("summary", {})) var kpl := int(_db.adventure.keystone_per_level) @@ -3444,7 +3450,7 @@ func _smoke_save() -> void: "集成三关首杀标记齐") check(f9.recent_summaries().size() == 1 and int(f9.recent_summaries()[0].get("master_seed", -1)) == 42, "集成 recent 1 条且 seed 42") - var st9b: Dictionary = autoplay.run_adventure(_db, 42, 200, 100) + var st9b: Dictionary = autoplay.run_adventure(_db, 42, 400, 200) f9.apply_adventure_summary(st9b.get("summary", {})) check(f9.clear_count(1) == 2 and f9.clear_count(2) == 2 and f9.clear_count(3) == 2, "第二局后通关次数全 2") check(f9.keystone_balance() == 6 * kpl, "第二局后余额翻倍(6 × keystone_per_level)")