Files
game-code-4/tests/unit/cases/test_balance_data.gd
T
程基岩(engineering-lead) 08dc5020c3 W4 批次:三项设计裁定落地(Boss 战 Plan B / 离线契约 v2 / 长明灯加法化)
Boss 战修复(Plan B,用户拍板):
- HP 公式 15xPxhall_factor -> HP = P x boss_army_seconds_n(S=23.0→28.0 递增,
  每场军列约 23-28 秒清空,战斗时长成为可直接书写的设计旋钮,结构性消除
  高殿 P 抵消导致不可胜的旧 bug);hall_factor 降级为纯叙事/视觉参数
- 新增 souls_par 列(0→90000):开场冲锋 intro_dmg = HP x 10% x clamp(souls/souls_par,0,1),
  上限 20%->10%;删 hp_factor/intro_dmg_souls_factor/intro_dmg_cap_ratio 三列
- 点击伤害 P x κ x combo_mult,κ = (0.010 + 0.052 x click_ratio) x (1 + 0.30 x m06_owned),
  click_ratio = 已购点击升级 / 12(κ 0.010→0.0806,满配点击占比约 20.5%±3pp)
- 防双重计入:L5-12 点击升级 +1% output/s 留全局区(抬 P 同时抬军列 DPS 与点击
  伤害,可接受),不得再计入 κ 分子(recompute 注释固化)

离线契约 v2(P-8,改契约不改表):
- OfflineModel.settle 第三参 offline_mult -> offline_add(加法);各档效率
  min(rate+add, 1.0) 硬顶 100%,离线永不超在线
- 长明灯 x1.15 乘性 -> +5%/级 加法(满级 +30%,各档封顶 100%)
- 0-2h 100% 保持;8h = 6.2 等效小时(77.5% 效率)
- Gate #9 拆 9a/9b/9c:9a FAIL->PASS(0-2h 全额 + 8h∈[5.5,6.5]),
  9b 长明灯满级 8h∈[7.5,8.0] 且 ≤100%,9c 任意配置效率 ≤100%

数据与工具:
- gen_balance_sheets.py 补登 W3 遗留 7 行 tune(防重跑静默丢失),self_check 更新
- boss_battles/upgrades schema 同步(offline_mult->offline_add enum,漏改会违反导入)

测试(runner 7->8 用例,Node 交叉验证 145 断言全过):
- 可胜性哨兵重写为「十殿全可胜」:每殿 S_n<30、军列+点击≥HP、余时∈[2,8]、
  满配余时差≥4、点击占比∈[15,25]、H10≈20.5%±3pp
- κ 四档断言(0.010/0.036/0.062/0.0806,分母 12)
- 新增 test_offline_contract.gd:契约 v2 数值面 + 9a/9b/9c 全 PASS + β 缓议
2026-10-20 17:01:25 +08:00

46 lines
2.7 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends RefCounted
# 用例:BalanceData 载入 + 跨表引用 + CSV/Bible 关键值(数据门)
func run(a, data) -> void:
a.true_(data.load_errors.is_empty(), "load_errors 为空(%s)" % str(data.load_errors))
a.eq(data.generators.size(), 12, "12 班底")
a.eq(data.upgrades.size(), 108, "108 升级")
a.eq(data.meta_upgrades.size(), 12, "12 宿慧商品")
a.eq(data.halls.size(), 10, "10 殿")
a.eq(data.palettes.size(), 10, "10 色板")
a.eq(data.bosses.size(), 10, "10 殿王战")
a.eq(data.events.size(), 4, "4 事件")
# 关键数值(Balance Bible v1.0 逐值一致)
a.near(data.generators[11].base_rate, 1073741824.0, 0.5, "gen12 rate = 8^10")
a.near(data.generators[1].payback_seconds(), 120.0, 0.5, "gen2 回本 120s")
a.near(data.generators[5].payback_seconds(), 293.0, 0.5, "gen6 回本 293s")
a.near(data.generators[11].payback_seconds(), 1118.0, 0.5, "gen12 回本 1118s")
a.near(data.hall_by_no(1).gate_merit, 2000.0, 0.5, "H1 门 2K")
a.near(data.hall_by_no(10).gate_merit, 1.5e9, 0.5, "H10 门 1.5B")
a.true_(data.hall_by_no(10).is_prestige_gate, "H10 = prestige 门")
a.near(data.boss_for_hall("hall_01_qinguang").boss_army_seconds, 23.0, 1e-9,
"H1 殿王军列单推秒数 S_1 = 23(方案 B;旧 HP 系数 15 已废止)")
a.near(data.boss_for_hall("hall_10_zhuanlun").boss_army_seconds, 28.0, 1e-9,
"H10 殿王军列单推秒数 S_10 = 28")
a.eq(data.boss_for_hall("hall_01_qinguang").souls_par, 0, "H1 超度基准 0(无开场加成)")
a.eq(data.boss_for_hall("hall_10_zhuanlun").souls_par, 90000, "H10 超度基准 90000")
# 敕封诏书(P-12:requires = enthrone_ready)
var edict := data.upgrade("up_gate_tianzi")
a.true_(edict != null, "敕封诏书存在")
a.eq(edict.requires, "enthrone_ready", "诏书 requires = enthrone_ready")
a.eq(edict.cost, 800000000000, "诏书成本 800B")
# 调参数(balance_tuning)
a.near(data.tune_num("tune_souls_div", 0.0), 10000.0, 1e-9, "超度除数 10000")
a.near(data.tune_num("tune_enthrone_suihui_req", 0.0), 60.0, 1e-9, "敕封宿慧门槛 60")
a.near(data.tune_num("tune_enthrone_rebirths", 0.0), 2.0, 1e-9, "敕封转世门槛 2")
a.eq(data.tune_text("tune_restart_curve", ""), "1:0.6:0.4:0.3", "重开曲线文本")
a.near(data.tune_num("tune_wrath_layers", 0.0), 22.0, 1e-9, "冤煞 22 层")
a.near(data.tune_num("tune_click_base", 0.0), 1.0, 1e-9, "点击基础值 1")
# 跨表引用完整性(schema 管单表;这里查跨表)
a.true_(data.check_references().is_empty(), "跨表引用无悬挂(%s)" % str(data.check_references()))
# 每殿恰一场殿王战 + 色板
for h in data.halls:
a.true_(data.boss_for_hall(h.id) != null, "%s 有 boss 行" % h.id)
a.true_(data.palette_for_hall(h.id) != null, "%s 有色板行" % h.id)