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 + β 缓议
80 lines
5.3 KiB
GDScript
80 lines
5.3 KiB
GDScript
extends RefCounted
|
||
|
||
# 用例:核心公式(MultiplierSet / PrestigeModel / OfflineModel)
|
||
|
||
func run(a, _data) -> void:
|
||
# ---- MultiplierSet 三乘区 + 软上限 ----
|
||
var m := MultiplierSet.new(16.0, 8.0, 64.0)
|
||
m.set_click_levels(4, 0.0, 0.01)
|
||
a.near(m.click_mult(), 16.0, 1e-9, "点击区 4 级 = ×16")
|
||
m.set_click_levels(5, 0.0, 0.01)
|
||
a.near(m.click_mult(), 16.0, 1e-9, "点击区 5 级仍钳 ×16")
|
||
m.set_gen_eff("gen_01_youhun", 6)
|
||
a.near(m.gen_mult("gen_01_youhun"), 7.0, 1e-9, "班底区 6 级 = ×7")
|
||
m.set_gen_eff("gen_01_youhun", 99)
|
||
a.near(m.gen_mult("gen_01_youhun"), 8.0, 1e-9, "班底区钳 ×8")
|
||
m.set_global_add(63.0)
|
||
a.near(m.global_mult(), 64.0, 1e-9, "全局区 ×64")
|
||
m.set_global_add(100.0)
|
||
a.near(m.global_mult(), 64.0, 1e-9, "全局区钳 ×64")
|
||
m.set_click_levels(4, 8.0, 0.01)
|
||
a.near(m.click_value(1.0, 1000.0), 96.0, 1e-6, "click_value = 1×16 + 1000×8%")
|
||
|
||
# ---- PrestigeModel ----
|
||
a.eq(PrestigeModel.suihui_gain(1.5e9, 1e6, 5.0, 0.0, 0.0), 193, "宿慧 1.5B → 193")
|
||
a.eq(PrestigeModel.suihui_gain(1.25e7, 1e6, 5.0, 0.0, 0.0), 17, "宿慧 12.5M → 17")
|
||
a.eq(PrestigeModel.suihui_gain(1.5e9, 1e6, 5.0, 0.0, 0.3), 135, "宿慧 30% 削减 → 135")
|
||
a.eq(PrestigeModel.suihui_gain(1.5e9, 1e6, 5.0, 0.45, 0.0), 279, "宿慧 m03×3 → 279")
|
||
a.eq(PrestigeModel.suihui_gain(0.0, 1e6, 5.0, 0.0, 0.0), 0, "零累计 → 0 宿慧")
|
||
a.eq(PrestigeModel.wrath_layer_cost(1, 8.0, 1.8), 8, "怨煞层 1 成本 8")
|
||
a.eq(PrestigeModel.wrath_layer_cost(2, 8.0, 1.8), 28, "怨煞层 2 成本 28")
|
||
a.eq(PrestigeModel.wrath_layer_cost(22, 8.0, 1.8), 2087, "怨煞层 22 成本 2087")
|
||
a.near(PrestigeModel.wrath_penalty(10, 0.03, 0.3, 0.0), 0.3, 1e-9, "冤气削减封顶 30%")
|
||
a.near(PrestigeModel.wrath_penalty(10, 0.03, 0.3, 0.15), 0.15, 1e-9, "m07 改 15%")
|
||
a.near(PrestigeModel.wrath_penalty(5, 0.03, 0.3, 0.0), 0.15, 1e-9, "5 层 = 15%")
|
||
a.eq(PrestigeModel.skip_count(23, 5), 4, "skip 23/5 = 4")
|
||
a.eq(PrestigeModel.skip_count(23, 4), 5, "skip 23/4 = 5(m04)")
|
||
a.near(PrestigeModel.restart_target(0), 1.0, 1e-9, "重开曲线 R1")
|
||
a.near(PrestigeModel.restart_target(3), 0.3, 1e-9, "重开曲线 R4")
|
||
a.near(PrestigeModel.restart_target(4), 0.25, 1e-9, "重开曲线 R5 触底")
|
||
a.true_(PrestigeModel.enthrone_available(2, 2), "敕封:转世 2 可")
|
||
a.true_(not PrestigeModel.enthrone_available(1, 2), "敕封:转世 1 不可")
|
||
|
||
# ---- OfflineModel 分带 + 72h 封顶 + 时钟回拨 + 长明灯加法 + 硬顶 ----
|
||
# W4 契约 v2(systems-spec §2.4/§2.5):第三参数由 offline_mult(乘性)改为
|
||
# offline_add(加法,直接加在各档速率上,各档硬顶 100%)。
|
||
var r1: Dictionary = OfflineModel.settle(3600.0, 10.0, 0.0, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(r1["effective_hours"], 1.0, 1e-9, "离线 1h = 1h 等效")
|
||
a.near(r1["merit"], 36000.0, 1e-6, "离线 1h × 10/s")
|
||
var r8: Dictionary = OfflineModel.settle(8.0 * 3600.0, 10.0, 0.0, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(r8["effective_hours"], 6.2, 1e-9, "离线 8h = 6.2h 等效(契约 v2:77.5%)")
|
||
a.near(r8["merit"], 223200.0, 1e-6, "离线 8h 收益")
|
||
var r24: Dictionary = OfflineModel.settle(24.0 * 3600.0, 10.0, 0.0, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(r24["effective_hours"], 12.6, 1e-9, "离线 24h = 12.6h 等效(契约 v2)")
|
||
var r100: Dictionary = OfflineModel.settle(100.0 * 3600.0, 10.0, 0.0, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(r100["effective_hours"], 17.4, 1e-9, "离线 100h → 72h 封顶 = 17.4h 等效(24.2%)")
|
||
var rneg: Dictionary = OfflineModel.settle(-5.0, 10.0, 0.0, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(rneg["merit"], 0.0, 1e-9, "时钟回拨 → 0")
|
||
a.near(OfflineModel.ratio_8h_over_1h(2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1), 6.2, 1e-9,
|
||
"历史口径比率 6.2(契约 v2 起门 #9 改判等效小时,见 SimGates.gate_offline_v2)")
|
||
# 长明灯加法:+30%(6 级)⇒ 2-8h 档 70%+30% = 100%(硬顶)⇒ 8h = 8.0h(效率 100%)
|
||
var r8l: Dictionary = OfflineModel.settle(8.0 * 3600.0, 10.0, 0.30, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(r8l["effective_hours"], 8.0, 1e-9, "长明灯满级 8h = 8.0h 等效(硬顶 100%)")
|
||
a.near(r8l["merit"], 288000.0, 1e-6, "长明灯满级 8h 收益")
|
||
# 加法不越过硬顶:+55%(6 级 + m05)仍 = 8.0h;8-24h 档 40%+30% = 70%
|
||
var r8m: Dictionary = OfflineModel.settle(8.0 * 3600.0, 10.0, 0.55, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(r8m["effective_hours"], 8.0, 1e-9, "加法 +55% 仍钳 8.0h(0-2h/2-8h 双档顶格)")
|
||
var r24l: Dictionary = OfflineModel.settle(24.0 * 3600.0, 10.0, 0.30, 2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.near(r24l["effective_hours"], 2.0 + 6.0 + 16.0 * 0.7, 1e-9, "长明灯满级 24h = 19.2h(8-24h 档 70%)")
|
||
# 效率硬顶:任意加成下等效 ≤ 实际(离线不得优于在线)
|
||
for dur_h in [1.0, 8.0, 24.0, 72.0]:
|
||
for add in [0.0, 0.30, 0.55, 5.0]:
|
||
var rr: Dictionary = OfflineModel.settle(dur_h * 3600.0, 10.0, add,
|
||
2.0, 1.0, 8.0, 0.7, 24.0, 0.4, 0.1, 72.0)
|
||
a.true_(float(rr["effective_hours"]) <= dur_h + 1e-9,
|
||
"效率硬顶:%gh 离线 加法 +%g ⇒ 等效 %.2fh ≤ %gh" % [dur_h, add, float(rr["effective_hours"]), dur_h])
|
||
|
||
# ---- BigNumber 红线 ----
|
||
a.true_(BigNumber.assert_within(1e13, "test"), "1e13 不过红线")
|
||
a.true_(not BigNumber.assert_within(1e15, "test"), "1e15 触红线")
|