feat(balance): 关间大奖励 10→5 + L2 五处血量收紧——双合格线扫描收敛(用户拍板 2026-09-23)

- adventure.tres: level_clear_hp_bonus 10→5(刀一:关间补给收窄)
- enemy.tres L2: 群行 22→26×3 / 24→28、蛛化卓尔精灵 112→130(刀二=B包第7轮留档收紧候选L2部分;L3 未动)
- smoke_all.gd: 满配锚 (400,200)→(900,400)——L2 抬血后旧档不再满通,先例式抬锚(B包 200/100→400/200 同款)
- 读数:零强化过第二关率 普通 15→2% / 完美 40→15%;营地循环爬升形态成立(第4局0%→第37局100%)
- 冒烟 553 项 0 失败三闸过;verifier 双轮扫描报告 production/qa/balance-verifier-20260923-043341/050222.md(worktree)
This commit is contained in:
DKChan committed 2026-09-23 05:37:50 +08:00
1 parent 3309aae2a3
commit a4edb1e7f8
3 files changed
+23 -23

No files matched your search

@@ -4,7 +4,7 @@
[resource]
script = ExtResource("1")
level_clear_hp_bonus = 10
level_clear_hp_bonus = 5
keystone_per_level = 10
; 冒险结构实现批(2026-09-21 建表——registry adventure_table 条目同批注记更新):
@@ -140,7 +140,7 @@ rows = [{
"display_name": "熊地精猎群",
"unit_count": 2,
"unit_count_max": 3,
"hp": 22,
"hp": 26,
"atk": 2,
"atk_min": 1,
"atk_max": 3,
@@ -162,7 +162,7 @@ rows = [{
"enemy_id": "giant_spider",
"display_name": "巨蜘蛛",
"unit_count": 2,
"hp": 24,
"hp": 28,
"atk": 2,
"atk_min": 1,
"atk_max": 3,
@@ -205,10 +205,10 @@ rows = [{
"node_depth": 6,
"enemy_id": "giant_spider",
"display_name": "巨蜘蛛巢群",
"unit_count": 2,
"unit_count_max": 3,
"hp": 22,
"atk": 1,
"unit_count": 2,
"unit_count_max": 3,
"hp": 26,
"atk": 1,
"atk_min": 1,
"atk_max": 2,
"pool": [{
@@ -228,10 +228,10 @@ rows = [{
"node_depth": 7,
"enemy_id": "giant_spider",
"display_name": "巨蜘蛛巢群",
"unit_count": 2,
"unit_count_max": 3,
"hp": 22,
"atk": 2,
"unit_count": 2,
"unit_count_max": 3,
"hp": 26,
"atk": 2,
"atk_min": 1,
"atk_max": 3,
"pool": [{
@@ -252,7 +252,7 @@ rows = [{
"enemy_id": "drider",
"display_name": "蛛化卓尔精灵",
"unit_count": 1,
"hp": 112,
"hp": 130,
"atk": 3,
"atk_min": 2,
"atk_max": 4,
@@ -124,7 +124,7 @@ func _smoke_adventure_table() -> void:
func _smoke_adventure_api() -> void:
print("--- 冒险结构 API 闸(重复开始拒绝 · 放弃两态受理)---")
var adr = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(42))
adr.set_hero_override(400, 200) # 首战速胜档(放弃的非战斗受理要走到选路态)
adr.set_hero_override(900, 400) # 首战速胜档(放弃的非战斗受理要走到选路态)
check(adr.start_adventure(42), "冒险启动受理(主种子注入恰一次——state=running)")
check(not adr.start_adventure(43), "进行中重复 start_adventure 拒绝(重开须待结算完毕)")
check(adr.runner().current_battle() != null, "首战在飞(接口①开始关卡直达战斗节点)")
@@ -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, 400, 200)
var st: Dictionary = autoplay.run_adventure(_db, 42, 900, 400)
var sum: Dictionary = st["summary"]
check(String(st["result"]) == "completed" and bool(sum.get("cleared", false)),
"满配通关(42 / atk+400 / hp+200——cleared=true;v2 怪阶梯后旧 200/100 档不再满配)")
"满配通关(42 / atk+900 / hp+400——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 := 3.0 # hp+200 ⇒ TunePanel 百分比后乘 ×3(加算先加、百分比后乘——生效次序口径)
var k := 5.0 # hp+400 ⇒ TunePanel 百分比后乘 ×5(加算先加、百分比后乘——生效次序口径)
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, 400, 200)
var st2: Dictionary = autoplay.run_adventure(_db, 42, 900, 400)
check(st2["summary"] == sum and st2["encounter_max_hp_seq"] == seq
and st2["visited_ids"] == st["visited_ids"],
"同种子两局逐位可复现(summary/上限序列/行进序列——主种子单点派生)")
@@ -242,7 +242,7 @@ func _smoke_adventure() -> void:
"L2 败北败退明细:层号=2 · 节点在案(数值验证取数面 2026-09-22)")
# ⑥ 重复宣布拒绝(settle 后再调 _on_level_finished——摘要零变化)
var adr6 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(7))
adr6.set_hero_override(400, 200)
adr6.set_hero_override(900, 400)
check(adr6.start_adventure(7), "重复拒绝场景:冒险启动(seed 7)")
var b6 = adr6.runner().current_battle()
var st6 := _adv_st()
@@ -273,7 +273,7 @@ func _smoke_adventure() -> void:
var same := {}
for s in range(42, 92):
var a8 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(s))
a8.set_hero_override(400, 200)
a8.set_hero_override(900, 400)
if not a8.start_adventure(s):
continue
if _adv_drive_to_shop(a8, _adv_st(), autoplay):
@@ -313,7 +313,7 @@ func _smoke_adventure() -> void:
"同一公式两个落点逐位一致(LevelRunner.rest_heal_amount 内置默认)")
# ⑩ 放弃(战斗中拒绝 · 非战斗期受理同失败型结算)
var a10 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(15))
a10.set_hero_override(400, 200)
a10.set_hero_override(900, 400)
check(a10.start_adventure(15), "放弃场景:冒险启动(seed 15——首战在飞)")
check(not a10.abandon(), "战斗中 abandon 拒绝(战斗域单事务在飞)")
var b10 = a10.runner().current_battle()
@@ -2907,7 +2907,7 @@ func _smoke_shop_room() -> void:
var shop_run := {}
for s in range(42, 92):
var runner = load("res://core/level_runner.gd").new(_db, _fresh_rng(s))
runner.set_hero_override(400, 200) # 行进段快速通关档(购买断言与百分比轴正交——加算区单独断言)
runner.set_hero_override(900, 400) # 行进段快速通关档(购买断言与百分比轴正交——加算区单独断言)
runner.start_level(2, s)
var st := {"result": "", "rounds": 0, "refreshes": 0, "mine_hits": 0, "hero_dmg": 0, "policy": "normal"}
var guard := 40
@@ -3481,7 +3481,7 @@ func _smoke_save() -> void:
# ⑨ 摘要集成(冒险结构批产物驱动):run_adventure 真局摘要 → apply 原语 → 域读数 → 写盘读回保持
var autoplay = load("res://smoke/level_autoplay.gd")
var st9: Dictionary = autoplay.run_adventure(_db, 42, 400, 200)
var st9: Dictionary = autoplay.run_adventure(_db, 42, 900, 400)
var f9 = sm_script.new(paths[8])
f9.apply_adventure_summary(st9.get("summary", {}))
var kpl := int(_db.adventure.keystone_per_level)
@@ -3492,7 +3492,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, 400, 200)
var st9b: Dictionary = autoplay.run_adventure(_db, 42, 900, 400)
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)")