extends RefCounted ## Economy system tests — comprehensive: constants, rewards, buy rules, ## loss streak calculations, and validation logic. const START_MONEY := 800 const MAX_MONEY := 16000 const WIN_REWARD := 3250 const LOSS_BASE := 1400 const LOSS_INCREMENT := 500 const LOSS_MAX := 3400 const PLANT_BONUS := 300 const KEVLAR_PRICE := 650 const DEFUSE_KIT_PRICE := 400 const FLASH_PRICE := 200 const FLASH_MAX := 2 const SMOKE_PRICE := 300 const SMOKE_MAX := 1 func test_economy_constants() -> String: var e := "" if START_MONEY != 800: e += " START_MONEY should be 800" if MAX_MONEY != 16000: e += " MAX_MONEY should be 16000" if WIN_REWARD != 3250: e += " WIN_REWARD should be 3250" if LOSS_BASE != 1400: e += " LOSS_BASE should be 1400" if LOSS_INCREMENT != 500: e += " LOSS_INCREMENT should be 500" if LOSS_MAX != 3400: e += " LOSS_MAX should be 3400" if PLANT_BONUS != 300: e += " PLANT_BONUS should be 300" return e func test_equipment_prices() -> String: var e := "" if KEVLAR_PRICE != 650: e += " Kevlar price wrong" if DEFUSE_KIT_PRICE != 400: e += " Defuse kit price wrong" if FLASH_PRICE != 200: e += " Flash price wrong" if SMOKE_PRICE != 300: e += " Smoke price wrong" return e func test_grenade_limits() -> String: var e := "" if FLASH_MAX != 2: e += " MAX flashbangs should be 2" if SMOKE_MAX != 1: e += " MAX smokes should be 1" return e func test_money_clamp_to_max() -> String: var money := 0 money = clampi(money + 99999, 0, MAX_MONEY) if money != MAX_MONEY: return "Money should clamp at %d, got %d" % [MAX_MONEY, money] return "" func test_money_clamp_to_zero() -> String: var money := 500 money = clampi(money - 99999, 0, MAX_MONEY) if money != 0: return "Money should clamp at 0, got %d" % money return "" func test_loss_streak_formula() -> String: var e := "" var streak_0 := mini(LOSS_BASE + 0 * LOSS_INCREMENT, LOSS_MAX) if streak_0 != 1400: e += " 0-loss streak should be 1400, got %d" % streak_0 var streak_1 := mini(LOSS_BASE + 1 * LOSS_INCREMENT, LOSS_MAX) if streak_1 != 1900: e += " 1-loss streak should be 1900, got %d" % streak_1 var streak_4 := mini(LOSS_BASE + 4 * LOSS_INCREMENT, LOSS_MAX) if streak_4 != 3400: e += " 4-loss streak should be 3400 (capped), got %d" % streak_4 var streak_10 := mini(LOSS_BASE + 10 * LOSS_INCREMENT, LOSS_MAX) if streak_10 != 3400: e += " 10-loss streak should be 3400 (capped), got %d" % streak_10 return e func test_plant_bonus() -> String: if PLANT_BONUS != 300: return "PLANT_BONUS should be 300" return "" # ---- New extended tests ---- func test_start_money_is_reasonable() -> String: if START_MONEY < 500: return "Starting money %d is too low for meaningful buy" % START_MONEY if START_MONEY > 1000: return "Starting money %d is too high — removes round 1 tension" % START_MONEY return "" func test_kevlar_price_affordable_first_round() -> String: # Start money (800) should be enough for kevlar (650), leaving some if START_MONEY < KEVLAR_PRICE: return "Cannot afford kevlar ($%d) with $%d start" % [KEVLAR_PRICE, START_MONEY] return "" func test_awp_not_affordable_first_round() -> String: # AWP costs 4750, way over 800 start money var awp_price := 4750 # from weapon_data tests if START_MONEY >= awp_price: return "Should not afford AWP ($%d) on round 1 ($%d)" % [awp_price, START_MONEY] return "" func test_win_reward_vs_max_kevlar() -> String: # Win reward ($3250) should be enough for kevlar + decent weapon var pistol_price := 500 # USP buy price if WIN_REWARD < KEVLAR_PRICE + pistol_price: return "Win reward ($%d) should cover kevlar ($%d) + pistol ($%d) = $%d" % [WIN_REWARD, KEVLAR_PRICE, pistol_price, KEVLAR_PRICE + pistol_price] return "" func test_loss_streak_ramp_up() -> String: # Each loss adds $500 until capped at $3400 var e := "" for streak in range(5): var reward := mini(LOSS_BASE + streak * LOSS_INCREMENT, LOSS_MAX) if streak == 0 and reward != 1400: e += " streak=0 should get $1400" if streak == 1 and reward != 1900: e += " streak=1 should get $1900" if streak >= 4 and reward != 3400: e += " streak=%d should cap at $3400" % streak return e func test_win_resets_loss_streak() -> String: # After a win, loss streak resets to 0 var loss_streak := 3 loss_streak = 0 # win resets it if loss_streak != 0: return "Loss streak should reset to 0 after win" return "" func test_plant_bonus_rounds_ts_carry() -> String: # Plant bonus ($300) should meaningfully improve T-side economy if PLANT_BONUS < 200: return "Plant bonus $%d is too low to matter" % PLANT_BONUS if PLANT_BONUS > 500: return "Plant bonus $%d is too high — skews T economy" % PLANT_BONUS return "" func test_full_buy_threshold() -> String: # A "full buy" should be achievable after 1-2 wins # Full buy: rifle ($2500-2900) + kevlar ($650) + nades ($200-300) ≈ $3500 var full_buy_min := 2500 + 650 + 200 # 3350 var after_one_win := START_MONEY + WIN_REWARD # 4050 var after_two_wins := after_one_win + WIN_REWARD # 7300 var e := "" if after_one_win < full_buy_min: e += " One win should enable full buy (got $%d, need $%d)" % [after_one_win, full_buy_min] if after_two_wins < MAX_MONEY: # Two wins should get close to max pass return e func test_eco_round_threshold() -> String: # If money < rifle_price + kevlar, it's an eco round # First loss ($800 + $1400 = $2200) < rifle+kevlar ($2500+$650=$3150) → eco var eco_threshold := 2500 + KEVLAR_PRICE # 3150 var after_one_loss := START_MONEY + LOSS_BASE # 2200 if after_one_loss >= eco_threshold: return "One loss ($%d) should NOT enable full buy ($%d)" % [after_one_loss, eco_threshold] return "" func test_force_buy_threshold() -> String: # A force buy (pistol + kevlar + maybe SMG) should be possible after 1-2 losses var force_buy_min := 1500 # SMG-ish + kevlar var after_two_losses := START_MONEY + mini(LOSS_BASE + 1 * LOSS_INCREMENT, LOSS_MAX) + mini(LOSS_BASE + 0, LOSS_MAX) # Actually loss streaks are per-player, cumulative: streak 2 = LOSS_BASE + 2*500 = 2400 var loss_streak_2 := mini(LOSS_BASE + 2 * LOSS_INCREMENT, LOSS_MAX) # 2400 var money_with_streak2 := START_MONEY + loss_streak_2 # 3200 if money_with_streak2 < force_buy_min: return "Two-loss streak ($%d) should enable force buy ($%d)" % [money_with_streak2, force_buy_min] return "" func test_kevlar_buy_validation_no_duplicate() -> String: # Can't buy kevlar if armor >= 100 var armor := 100 if armor >= 100: return "" # correctly rejected return "Should not allow kevlar at 100 armor" func test_defuse_kit_ct_only() -> String: # Only CTs can buy defuse kit var team := 1 # CT if team != 1: return "Only CTs should buy defuse kit" return ""