extends RefCounted # 用例:核心公式(MultiplierSet / PrestigeModel / OfflineModel) func run(a, _data: BalanceData) -> 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") # W5 新参数(裁定 P-26):削减速 −4%/层封顶 −40%;m07 改 20% a.near(PrestigeModel.wrath_penalty(10, 0.04, 0.4, 0.0), 0.4, 1e-9, "冤气削减封顶 40%") a.near(PrestigeModel.wrath_penalty(10, 0.04, 0.4, 0.20), 0.20, 1e-9, "m07 改 20%") a.near(PrestigeModel.wrath_penalty(5, 0.04, 0.4, 0.0), 0.2, 1e-9, "5 层 = 20%") a.near(PrestigeModel.wrath_penalty(9, 0.04, 0.4, 0.0), 0.36, 1e-9, "9 层 = 36%(未触顶)") 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(1), 0.48, 1e-9, "重开曲线 R2(v1.1 校准值)") a.near(PrestigeModel.restart_target(2), 0.42, 1e-9, "重开曲线 R3(v1.1 校准值)") a.near(PrestigeModel.restart_target(3), 0.40, 1e-9, "重开曲线 R4(v1.1 校准值)") 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 不可") # ---- W5 G-1:wrath_layers.csv 22 行(效果/成本逐行;[B§12] 漏登补登)---- var wl := _data.wrath_layers a.eq(wl.size(), 22, "冤煞层 22 行") var sum_effect := 0.0 var prev_cost := -1 for row in wl: a.eq(row.layer_index, wl.find(row) + 1, "layer_index 从 1 连续(%s)" % row.id) # 成本列 = round(8×n^1.8) 逐行一致(表 = 公式落盘,双源交叉校验) a.eq(row.cost, PrestigeModel.wrath_layer_cost(row.layer_index, 8.0, 1.8), "成本 = 公式(%s)" % row.id) a.true_(row.cost > prev_cost, "成本严格递增(%s)" % row.id) prev_cost = row.cost # effect 剖面:L1-15 = 0.15;L16-22 = 0.00(合计封顶 +225%) if row.layer_index <= 15: a.near(row.effect, 0.15, 1e-9, "L%d effect = 0.15" % row.layer_index) else: a.near(row.effect, 0.0, 1e-9, "L%d effect = 0(归零)" % row.layer_index) sum_effect += row.effect a.near(sum_effect, 2.25, 1e-9, "22 层合计 effect = +225%(15 层封顶)") a.near(_data.wrath_layer_effect_sum(15), 2.25, 1e-9, "effect_sum(15) = +225%") a.near(_data.wrath_layer_effect_sum(10), 1.5, 1e-9, "effect_sum(10) = +150%") a.near(_data.wrath_layer_effect_sum(22), 2.25, 1e-9, "effect_sum(22) 仍 +225%(16-22 归零)") a.near(_data.wrath_layer_effect_sum(0), 0.0, 1e-9, "effect_sum(0) = 0") a.eq(_data.wrath_layer(1).cost, 8, "wrath_layer(1) 成本 8") a.eq(_data.wrath_layer(22).cost, 2087, "wrath_layer(22) 成本 2087") a.true_(_data.wrath_layer(23) == null, "wrath_layer(23) 越界 = null") # W5 新调参(裁定 F-1/F-2):宿慧渐近 + 跳过封顶 a.near(_data.tune_num("tune_suihui_global_max", 0.0), 0.5, 1e-9, "宿慧渐近上限 0.50") a.near(_data.tune_num("tune_suihui_global_scale", 0.0), 420.0, 1e-9, "宿慧衰减尺度 420") a.near(_data.tune_num("tune_skip_level_cap_per_gen", 0.0), 50.0, 1e-9, "跳过每档封顶 50") a.near(_data.tune_num("tune_wrath_penalty", 0.0), 0.04, 1e-9, "削减速 0.04/层") a.near(_data.tune_num("tune_wrath_penalty_cap", 0.0), 0.4, 1e-9, "削减速封顶 0.40") a.false_(_data.has_tune("tune_wrath_bonus"), "tune_wrath_bonus 已迁入表(防双源)") a.false_(_data.has_tune("tune_suihui_global_pct"), "tune_suihui_global_pct 已被渐近公式取代") # ---- 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, "效率硬顶:%s h 离线 加法 +%s ⇒ 等效 %.2f h ≤ %s h" % [ str(dur_h), str(add), float(rr["effective_hours"]), str(dur_h)]) # ---- BigNumber 红线 ---- a.true_(BigNumber.assert_within(1e13, "test"), "1e13 不过红线") a.true_(not BigNumber.assert_within(1e15, "test"), "1e15 触红线")