fix(smoke): 冒烟锚对齐 Package B 落地数值——master 同步后过期常量修复
- 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
This commit is contained in:
1 parent
54f2da34af
commit
cb39ba0fe1
1 file changed
+26
-20
@@ -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)")
|
||||
|
||||
Reference in new issue
Block a user