extends Node const REWARDS := preload("res://scripts/planets/planet_rewards.gd") const EVENTS := preload("res://scripts/planets/surface_events.gd") const PROFILES := preload("res://scripts/planets/planet_profiles.gd") func offer(event: Dictionary, captain: Resource, state: Resource, id: String) -> Dictionary: for option in EVENTS.options(event,captain,state): if option.id == id: return option return {} func _ready() -> void: GameState.system_level = 32 var captain: Resource = preload("res://scripts/captain/captain_progress.gd").new() captain.credits = 100000 captain.parts = 1000 for key in ["iron","sulfur","uranium","copper","nickel"]: captain.minerals[key] = 1000 var state: Resource = captain.expedition var samples: Array[Dictionary] = [] for index in 3: var d := float(index)*0.5 var profile := PROFILES.generate(777,1,"Biom testowy") profile.difficulty = d profile.oxygen = roundi(80*(1.0-d)) profile.temperature = roundi(40+60*d) profile.flora = roundi(50*d) profile.landing_damage = 5 var expected_bounds: Vector2i = [Vector2i(0,2),Vector2i(1,6),Vector2i(2,10)][index] assert(REWARDS.module_bonus_range(profile) == expected_bounds) var rng := RandomNumberGenerator.new() rng.seed = 348838 var histogram := {} for sample_index in 10000: var bonus := REWARDS.roll_module_bonus(rng,profile) assert(bonus >= expected_bounds.x and bonus <= expected_bounds.y) histogram[bonus] = int(histogram.get(bonus,0))+1 for bonus in range(expected_bounds.x,expected_bounds.y): assert(int(histogram[bonus]) > int(histogram[bonus+1])) assert(histogram.has(expected_bounds.y)) assert(REWARDS.material_multiplier(profile) == 1.0+index) # Explicitly exclude all ammunition, rockets, credits and consumables. var scaled := REWARDS.scale_materials({"parts":6,"copper":8,"silicon":8,"missile":4,"ammunition":10,"irradiated_ammunition":10,"energy_bank":1,"credits":50},profile) assert(scaled.parts == 6*(1+index) and scaled.copper == 8*(1+index)) assert(scaled.missile == 4 and scaled.ammunition == 10 and scaled.irradiated_ammunition == 10 and scaled.energy_bank == 1 and scaled.credits == 50) state.lander_hp = 100 assert(state.begin_visit(profile)) var trader := {"kind":"trader","seed":1234,"complete":false} var goods := offer(trader,captain,state,"materials") assert(goods.reward.copper == 8*(1+index) and goods.reward.silicon == 8*(1+index)) var missiles := offer(trader,captain,state,"missiles") var barter := {"kind":"barter","seed":1234,"complete":false} var barter_missiles := offer(barter,captain,state,"missiles") assert(barter_missiles.reward.missile == 3) assert(trader.module.item_level >= 32+expected_bounds.x and trader.module.item_level <= 32+expected_bounds.y) var safe := {"kind":"safe_bet","seed":1234,"complete":false} var guaranteed := offer(safe,captain,state,"safe") assert(guaranteed.reward.parts == 6*(1+index)) assert(EVENTS.resolve(safe,"safe",captain,state).success) assert(state.cargo_parts == 6*(1+index),"A reward must be scaled exactly once") # Hidden outcomes retain their category and ammo counts for a shared seed. var hidden := [] for seed_value in 200: var chest_rng := RandomNumberGenerator.new() chest_rng.seed = seed_value var prize := EVENTS._mystery(chest_rng,32,profile) hidden.append(prize) # One visit grants loot; gear and effective hazards scale its quantity. var modules := 0 for attempt in 1200: state.lander_hp = 100 var poi := {"kind":"deposit","complete":false} var result: Dictionary = state.resolve_poi(captain,poi,rng) if result.success: for key in result.materials: var yield_factor: float = PROFILES.poi_loot_report(profile,captain).multiplier var minimum := maxi(1,roundi(18*(1+index)*yield_factor)) var maximum := maxi(1,roundi(28*(1+index)*yield_factor)) assert(int(result.materials[key]) >= minimum and int(result.materials[key]) <= maximum) assert(result.module == null) var structure := {"kind":"ruins","complete":false} var structure_result: Dictionary = state.resolve_poi(captain,structure,rng) if structure_result.module != null: modules += 1 assert(structure.complete and structure_result.module.item_level >= 32 and structure_result.module.item_level <= 44) state.cargo_modules.clear() assert(modules > 5) samples.append({"profile":profile,"missile_count":missiles.reward.missile,"missile_price":missiles.cost.credits,"ammo_barter_cost":barter_missiles.cost.iron,"goods_cost":goods.cost.credits,"hidden":hidden}) state.finish_visit(captain,true) print("BIOME ",d,": module range +",expected_bounds.x,"..+",expected_bounds.y,"; materials x",1+index,"; rockets=",missiles.reward.missile,"; price=",missiles.cost.credits,"; barter cost=",barter_missiles.cost.iron,"; tested POI modules=",modules) for index in range(1,3): assert(samples[index].missile_count == samples[0].missile_count) assert(samples[index].missile_price < samples[index-1].missile_price) assert(samples[index].ammo_barter_cost < samples[index-1].ammo_barter_cost) assert(samples[index].goods_cost == samples[0].goods_cost) for seed_value in 200: var easy_prize: Dictionary = samples[0].hidden[seed_value] var prize: Dictionary = samples[index].hidden[seed_value] assert(prize.keys() == easy_prize.keys()) for key in prize: if key in REWARDS.MATERIAL_KEYS: assert(int(prize[key]) == int(easy_prize[key])*(1+index)) elif key == "missile": assert(prize[key] == easy_prize[key]) elif key == "module": var bounds := REWARDS.module_bonus_range(samples[index].profile) assert(prize[key].item_level >= 32+bounds.x and prize[key].item_level <= 32+bounds.y) var cap_rng := RandomNumberGenerator.new() for level in [995,999,1000]: for index in 50: assert(REWARDS.generate_module(cap_rng,{"difficulty":1.0},level).item_level <= 1000) print("BIOME REWARD SCALING PASS: 30000 bonus rolls, 3600 POI attempts, 600 mystery outcomes; materials grow, ammo counts stable, rocket offers cheaper, no duplicate scaling, level cap respected") get_tree().quit()