88 lines
5.5 KiB
GDScript
88 lines
5.5 KiB
GDScript
# tests/unit/battle_settlement/damage_math_test.gd — 战斗结算·伤害公式族纯函数单元测试
|
||
# 运行:godot --headless --path game --script res://tests/unit/battle_settlement/damage_math_test.gd
|
||
# 协议:DamageMath = 零状态纯算术宿主(headless 可跑);掷点档位参数全读 settlement 表(零玩法数值字面量)。
|
||
# 注:0/100 等出现在断言中的数值 = 语义常量(中性池/百分比满额),非玩法行值。
|
||
extends SceneTree
|
||
|
||
const DamageMathScript := preload("res://core/damage_math.gd")
|
||
const ConfigDBScript := preload("res://core/config_db.gd")
|
||
const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:_check/汇总退出样板单点
|
||
|
||
var db
|
||
|
||
|
||
func _init() -> void:
|
||
db = ConfigDBScript.new()
|
||
var load_ok: bool = db.load_tables("res://data/tables", true)
|
||
Kit.check("前置:settlement 表加载零 error", load_ok and db.diagnostics_count("error") == 0)
|
||
if load_ok:
|
||
_test_pool_damage()
|
||
_test_counter_component()
|
||
_test_roll_discount_percent()
|
||
_test_rolled_component()
|
||
quit(Kit.finish("damage_math_test"))
|
||
|
||
|
||
func _floor_val() -> int:
|
||
return int(db.settlement.damage_roll.damage_floor)
|
||
|
||
|
||
# ---- F2 乘区:池内加算 → 池间乘算 → floor(单一取整规则)----
|
||
|
||
func _test_pool_damage() -> void:
|
||
var d := _floor_val() + 9 # 表值推导的任意正探针量(非玩法行值)
|
||
Kit.check("中性双池 (0,0) 原样透传", DamageMathScript.pool_damage(d, 0, 0) == d)
|
||
Kit.check("负敌方池压低不增高", DamageMathScript.pool_damage(d, 0, int(db.settlement.core.pool_clamp_lo)) <= d)
|
||
Kit.check("正·主角池抬升不低于原值", DamageMathScript.pool_damage(d, int(db.settlement.core.pool_clamp_hi), 0) >= d)
|
||
Kit.check("主角池单调不减(+50% vs +49% 探针档)", DamageMathScript.pool_damage(d, 50, 0) >= DamageMathScript.pool_damage(d, 49, 0))
|
||
Kit.check("对称性:池值互换结果不变(乘算交换)", DamageMathScript.pool_damage(d, 30, -20) == DamageMathScript.pool_damage(d, -20, 30))
|
||
Kit.check("输出非负(maxi(0,·) 封底)", DamageMathScript.pool_damage(d, int(db.settlement.core.pool_clamp_lo), int(db.settlement.core.pool_clamp_lo)) >= 0)
|
||
|
||
|
||
# ---- 克制分量:空桶不吃修正恒 0;落地下限保底([1,+∞) 全来源)----
|
||
|
||
func _test_counter_component() -> void:
|
||
var floor_v := _floor_val()
|
||
Kit.check("空桶(点数≤0)恒 0 不吃修正", DamageMathScript.counter_component(0, floor_v, floor_v) == 0
|
||
and DamageMathScript.counter_component(-1, 5, floor_v) == 0)
|
||
Kit.check("正向修正直加", DamageMathScript.counter_component(floor_v, floor_v, floor_v) == floor_v * 2)
|
||
Kit.check("负修正触底保落地伤害下限", DamageMathScript.counter_component(floor_v, -floor_v * 10, floor_v) == floor_v)
|
||
Kit.check("下限参数缺省 = 0(无下限语义面)", DamageMathScript.counter_component(floor_v, -floor_v * 10) == 0)
|
||
|
||
|
||
# ---- 掷点折扣查档(纯函数):满阈值恒全额;档位边界/末档语义与表数组一致 ----
|
||
|
||
func _test_roll_discount_percent() -> void:
|
||
var threshold := 10 # 查档探针阈值(夹具值——档位参数本身全部来自表)
|
||
var bounds: Array = db.settlement.damage_roll.roll_tier_bounds
|
||
var discounts: Array = db.settlement.damage_roll.roll_tier_discounts
|
||
Kit.check("前置:档位数 = 边界数 + 1(查档契约——档数 = 边界数 + 1)", discounts.size() == bounds.size() + 1 and discounts.size() > 0)
|
||
Kit.check("掷点 ≥ 阈值恒全额 100", DamageMathScript.roll_discount_percent(threshold, threshold, bounds, discounts) == 100
|
||
and DamageMathScript.roll_discount_percent(threshold + 5, threshold, bounds, discounts) == 100)
|
||
# 缺口 = 1:落首档(缺口 ∈ [1, bounds[0]] → discounts[0])
|
||
var tier0_expected: int = int(discounts[0])
|
||
if int(bounds[0]) >= 1:
|
||
Kit.check("缺口 1 落首档", DamageMathScript.roll_discount_percent(threshold - 1, threshold, bounds, discounts) == tier0_expected)
|
||
# 缺口超末边界:落末档
|
||
var last_expected: int = int(discounts[-1])
|
||
Kit.check("缺口超末边界落末档", DamageMathScript.roll_discount_percent(threshold - int(bounds[-1]) - 1, threshold, bounds, discounts) == last_expected)
|
||
# 档位值降序(重档折扣更深)——表自检
|
||
var descending := true
|
||
for i in range(discounts.size() - 1):
|
||
if int(discounts[i]) < int(discounts[i + 1]):
|
||
descending = false
|
||
Kit.check("档位值随档位加深不升(折扣单调)", descending)
|
||
|
||
|
||
# ---- 吃掷点分量算术:折扣→(暴击)→floor→+克制修正(单一取整链)----
|
||
|
||
func _test_rolled_component() -> void:
|
||
var base := float(_floor_val() + 7) # 表值推导探针基线
|
||
var crit_mult: int = int(db.settlement.damage_roll.crit_multiplier)
|
||
Kit.check("满额折扣无暴击 = floor(基线) + 修正 0", DamageMathScript.rolled_component(base, 100, false, crit_mult, 0) == int(floor(base)))
|
||
Kit.check("满额折扣暴击按表倍率放大", DamageMathScript.rolled_component(base, 100, true, crit_mult, 0) == int(floor(base * float(crit_mult) / 100.0)))
|
||
Kit.check("折扣降低不高于满额", DamageMathScript.rolled_component(base, 50, false, crit_mult, 0) <= DamageMathScript.rolled_component(base, 100, false, crit_mult, 0))
|
||
Kit.check("克制修正加在 floor 之后(加法核)", DamageMathScript.rolled_component(base, 100, false, crit_mult, _floor_val()) == int(floor(base)) + _floor_val())
|
||
Kit.check("复合序 = 基线×折扣%×暴击%(floor 只在链末)",
|
||
DamageMathScript.rolled_component(base, 50, true, crit_mult, 0) == int(floor(base * 50.0 / 100.0 * float(crit_mult) / 100.0)))
|