extends SceneTree const E = preload("res://world/owniverse/math/exact.gd") var checks: int = 0 var failures: int = 0 func _initialize() -> void: call_deferred("run") func check(condition: bool, message: String) -> void: checks = E.add(checks, 1) if (not condition): failures = E.add(failures, 1) push_error(message) func fixture(): var world = load("res://world/owniverse/owniverse.gd").new() var global: Node = root.get_node("Global") for id in global.OwniverseEntities: var entity = load("res://world/owniverse/owniverse_entity.gd").new(global.OwniverseEntities[id]) world.catalog.entities[id] = entity world.state.amount[id] = 0 world.state.stats.total_amount[id] = 0 if E.ne(entity.group_as, ""): world.state.amount[entity.group_as] = 0 world.state.stats.total_amount[entity.group_as] = 0 world.catalog.entities["N"].life_product = {} world.catalog.entities["N"].product_per_year_type = "H" world.catalog.entities["N"].product_per_year_amount = 10 world.catalog.entities["N"].auto = 0 world.state.amount.N = 1 return world func dispose(world) -> void: for entity in world.catalog.entities.values(): entity.free() world.free() func run() -> void: var world = fixture() for id in ["DSN", "SN", "BSN", "HN", "SGRB", "GRB", "LGRB", "HGRB"]: check(E.eq(world.stellar.evolution_products(world.state, world.catalog.entities[id], 3).blast, E.multiply(3, world.catalog.entities[id].blast)), E.add("Entity blast determines power: ", id)) world.catalog.entities.SN.output_and.blast = 999 world.catalog.entities.SN.blast = 4 check(E.eq(world.stellar.evolution_products(world.state, world.catalog.entities.SN, 2).blast, 8), "Imported output cannot override or double blast power") world.catalog.entities.SN.blast = 0 check((not world.stellar.evolution_products(world.state, world.catalog.entities.SN, 2).has("blast")), "Zero entity blast disables external event") world.catalog.entities.SN.output_or = {"positive": "blast:999", "negative": "blast:999", "chance": 50} check((not world.stellar.evolution_products(world.state, world.catalog.entities.SN, 2).has("blast")), "Alternative output cannot restore disabled blast") dispose(world) world = fixture() var rd = world.catalog.entities.RD check(E.eq(rd.planets.HP.chance, E.of("0.01")), "Preserve fractional planet probability") check((E.eq(rd.planets.GG.amount, 2) and E.eq(rd.planets.GG.chance, E.of("0.08"))), "Read count and chance separately") check(E.eq(rd._parse_planet_string("HP:1:0.01"), {"HP": {"amount": 1, "chance": E.of("0.01")}}), "Accept a single planet term") check(rd._parse_planet_string("").is_empty(), "Empty planet definitions stay empty") for id in ["HP", "EON1", "C0.9", "C1.2"]: check(world.catalog.entities[id].blastability, E.add("Blast vulnerable: ", id)) for id in ["RP", "GG", "AB", "C1.3", "C1.4", "C1.5"]: check((not world.catalog.entities[id].blastability), E.add("Blast protected: ", id)) # Actual GI table: HRG -> SN, with 1% GRB; no random rounding. var totals: Dictionary = {} for i in 100: var products: Dictionary = world.stellar.evolution_products(world.state, world.catalog.entities.HRG, 1) for id in products: totals[id] = E.add(totals.get(id, 0), products[id]) check((E.eq(totals.get("SN"), 99) and E.eq(totals.get("GRB"), 1)), "GI rare outcomes accumulate deterministically") var restored = fixture() restored.state = E.decode(bytes_to_var(var_to_bytes(E.encode(world.state)))) check(E.eq(world.stellar.evolution_products(world.state, world.catalog.entities.HRG, 37), restored.stellar.evolution_products(restored.state, restored.catalog.entities.HRG, 37)), "Evolution carry survives serialization") dispose(restored) # Real RD lifespan, four stars spread over the existing lifespan/40 window. world.state.amount.N = 0 world.state.amount.RD = 4 world.batches.append_batch(world.state, "RD", 4, 0, 0) var lifespan: Variant = rd.lifespan var width: Variant = rd.lifespan_delta world.evolution.evolve_batches(world.state, lifespan) check(E.eq(world.state.amount.RD, 4), "Window start does not kill the whole batch") world.evolution.evolve_batches(world.state, E.add(lifespan, E.divide(width, 4))) check((E.eq(world.state.amount.RD, 3) and E.eq(world.state.amount.TWD, 1)), "One quarter of a batch evolves") world.evolution.evolve_batches(world.state, E.add(lifespan, E.divide(width, 2))) check((E.eq(world.state.amount.RD, 2) and E.eq(world.state.amount.TWD, 2)), "Half the batch evolves") world.evolution.evolve_batches(world.state, E.add(lifespan, width)) check((E.eq(world.state.amount.RD, 0) and E.eq(world.state.amount.TWD, 4)), "Window end completes evolution") check(world.state.batches.RD.is_empty(), "Completed batch removed") dispose(world) # Creation accumulates independently for each star/planet pair. world = fixture() world.state.amount.RD = 100 for i in 100: world.stellar.create_planets(world.state, "RD", 1, 0, 0, 1) check(E.eq(world.state.binds.RD.HP, 1), "100 RD at metallicity 1 produce one HP") check(E.eq(world.state.binds.RD.RP, 21), "Rocky planet probability retains fractions") check((E.eq(world.state.binds.RD.GG, 16) and E.eq(world.state.binds.RD.AB, 120)), "Planet multiplicity applied") check((E.eq(world.state.amount.HP, 0) and E.eq(world.state.stats.total_amount.HP, 1)), "Created planets are bound, counted once") var saves: Node = root.get_node("SaveManager") check(E.eq(saves.validate_data({"format_version": 5, "app_version": "", "ui": {"current_page": 0}, "state": world.state}), ""), "Planet carry save validates") restored = fixture() restored.state = E.decode(bytes_to_var(var_to_bytes(E.encode(world.state)))) world.stellar.create_planets(world.state, "RD", 37, 0, 0, E.of("0.7")) restored.stellar.create_planets(restored.state, "RD", 37, 0, 0, E.of("0.7")) check(E.eq(world.state, restored.state), "Planet carry continues after save") dispose(restored) dispose(world) # A partially dying dwarf sterilizes HP; survivors and RP move to its heir. world = fixture() world.state.amount.RD = 4 world.state.binds.RD = {"HP": 8, "RP": 4, "C1.2": 4, "C1.3": 4, "GG": 4} world.batches.append_batch(world.state, "RD", 4, 0, 0) world.evolution.evolve_batches(world.state, E.add(lifespan, E.divide(width, 2))) check((E.eq(world.state.amount.RD, 2) and E.eq(world.state.amount.TWD, 2)), "Partial star transition with planets") check(E.eq(E.add(world.state.binds.RD.HP, world.state.binds.TWD.HP), 4), "Half of HP sterilized") check((E.eq(world.state.binds.RD["C1.3"], 2) and E.eq(world.state.binds.TWD["C1.3"], 2)), "Protected civilization splits between parent and heir") check(E.eq(E.add(world.state.binds.RD.RP, world.state.binds.TWD.RP), 10), "Sterilized planets become RP without loss") check((E.eq(world.state.amount.RP, 0) and E.eq(world.state.amount["C1.3"], 0)), "Inherited planets never become free") world.evolution.evolve_batches(world.state, E.add(lifespan, width)) check((E.eq(world.state.binds.RD["C1.3"], 0) and E.eq(world.state.binds.TWD["C1.3"], 4)), "No planets left at extinct parent type") check(E.eq(saves.validate_data({"format_version": 5, "app_version": "", "ui": {"current_page": 0}, "state": world.state}), ""), "Inherited state validates") dispose(world) world = fixture() world.state.amount.WS = 2 world.state.binds.WS = {"HP": 4, "C1.3": 4, "RP": 4, "GG": 4} world.batches.append_batch(world.state, "WS", 2, 0, 0) world.evolution.evolve_batches(world.state, E.add(world.catalog.entities.WS.lifespan, world.catalog.entities.WS.lifespan_delta)) var physical: Dictionary = world.ledger.physical_amounts(world.state) check((((E.eq(physical.HP, 0) and E.eq(physical["C1.3"], 0)) and E.eq(physical.RP, 0)) and E.eq(physical.GG, 0)), "Level 2 removes all planets, including protected civilization") check(E.eq(world.state.amount.LRG, 2), "Giant evolves after local destruction") dispose(world) world = fixture() world.state.amount.RD = 10 world.state.binds.RD = {"HP": 10, "C1.2": 10, "C1.3": 10, "RP": 0} world.stellar.apply_blast(world.state, 5, {"blast": 1, "density": 1}) check((E.eq(world.state.binds.RD.HP, 5) and E.eq(world.state.binds.RD["C1.2"], 5)), "Blast damages vulnerable worlds proportionally") check((E.eq(world.state.binds.RD["C1.3"], 10) and E.eq(world.state.binds.RD.RP, 10)), "Blast protects C1.3 and creates RP") world.stellar.apply_blast(world.state, 1000000, {"blast": 1, "density": 1}) check((E.eq(world.state.binds.RD.HP, 0) and E.eq(world.state.binds.RD.RP, 20)), "Overwhelming blast is capped at available planets") check((not world.state.amount.has("blast")), "Blast is not a resource") dispose(world) world = fixture() world.state.amount.RD = 1 world.state.binds.RD = {"HP": 1} for i in 10: world.stellar.apply_blast(world.state, 1, {"blast": 1, "density": E.of("0.1")}) check((E.eq(world.state.binds.RD.HP, 0) and E.eq(world.state.binds.RD.RP, 1)), "Small blast effects accumulate across cycles") dispose(world) # Actual supernova output: one SN gives a neutron star, resources, and an event. world = fixture() world.state.amount.SN = 1 world.batches.append_batch(world.state, "SN", 1, 0, 0) world.evolution.evolve_batches(world.state, 2) check((E.eq(world.state.amount.SN, 0) and E.eq(world.state.amount.LNS, 1)), "Supernova produces a remnant") check(((E.eq(world.state.amount.H, 8) and E.eq(world.state.amount.He, 50)) and E.eq(world.state.amount.Met, 11)), "Supernova returns table resources") check((not world.state.amount.has("blast")), "Supernova dispatches blast output") check(E.eq(saves.validate_data({"format_version": 5, "app_version": "", "ui": {"current_page": 0}, "state": world.state}), ""), "Blast state validates") dispose(world) world = fixture() world.state.amount.H = 1000 world.state.amount.Met = 100 check(E.eq(world.production.produce("RD", 100), 100), "Manual star creation succeeds") check(E.ge(world.state.binds.RD.HP, 1), "Manual creation dispatches planet formation") check(E.eq(world.state.amount.H, 900), "Planet creation does not duplicate or spend stellar fuel") dispose(world) world = fixture() world.state.amount.N = 0 world.state.amount.RD = 1 world.state.amount.H = 100 world.state.amount.Met = 100 world.state.auto_resources.H = 100 world.evolute(E.of("0.1")) check((E.eq(world.state.amount.RD, 101) and E.eq(world.state.amount.H, 0)), "Automatic formation uses its resource budget") check(E.ge(world.state.binds.RD.HP, 1), "Automatic formation also creates planets") dispose(world) world = fixture() world.catalog.entities.N.auto = 1 # 1000 newly produced automatic H reserve 1 H, enough for 10 HBD. world.evolute(100) check(E.eq(world.state.amount.HBD, 10), "Brown dwarfs form without existing ordinary stars") check((E.eq(world.state.amount.H, 999) and E.eq(world.state.auto_resources.H, 999)), "Brown dwarfs consume exactly their reserved hydrogen") check((E.eq(world.presentation.amounts(world.state, world.catalog).BD, 10) and E.gt(world.state.batches.HBD.size(), 0)), "Brown dwarfs appear in counter and evolution batches") world.catalog.entities.N.product_per_year_amount = 0 world.evolute(100) check(E.eq(world.state.amount.HBD, 10), "Stored automatic budget is not taxed repeatedly") dispose(world) world = fixture() world.catalog.entities.N.auto = 1 world.state.amount.RD = 1 world.evolute(50) check((E.eq(world.state.amount.HBD, 5) and E.near(world.state.auto_star_deficits.HBD_fuel, E.of("0.5"))), "Individual dwarfs retain prepaid fractional fuel") check(E.eq(world.state.amount.H, 0), "Prepaid fuel is not available to ordinary stars") var resumed = fixture() resumed.catalog.entities.N.auto = 1 resumed.state = E.decode(bytes_to_var(var_to_bytes(E.encode(world.state)))) world.evolute(50) resumed.evolute(50) check(E.eq(world.state.amount.HBD, 10), "Accumulated quota eventually creates a whole batch") check(E.eq(world.state, resumed.state), "Brown dwarf quota survives serialization deterministically") check((E.eq(world.state.amount.RD, 1000) and E.eq(world.state.amount.H, 0)), "Shared automatic hydrogen is spent once") world.state.batches.HBD = [{"amount": 10, "start_year": 101, "end_year": 101}] world.evolution.evolve_batches(world.state, 101) check(((E.eq(world.state.amount.HBD, 0) and E.eq(world.state.amount.CBD, 10)) and E.eq(world.presentation.amounts(world.state, world.catalog).BD, 10)), "Cooling preserves aggregate brown dwarf count") dispose(resumed) dispose(world) world = fixture() var saw_individual: bool = false for i in range(250): world.state.amount.H = E.add(world.state.amount.H, 1) world.state.auto_resources.H = E.add(world.state.auto_resources.get("H", 0), 1) var before: Variant = world.state.amount.HBD world.automatic.produce_brown_dwarfs(world.state, 1, E.of(i), E.of(E.add(i, 1))) var born: Variant = E.subtract(world.state.amount.HBD, before) check((E.eq(born, 0) or E.eq(born, 1)), "Small fuel increments produce individual dwarfs") saw_individual = (saw_individual or E.eq(born, 1)) check(saw_individual, "Random rounding does not wait for ten dwarfs") resumed = fixture() resumed.state = E.decode(bytes_to_var(var_to_bytes(E.encode(world.state)))) for i in range(250, 500): for simulation in [world, resumed]: simulation.state.amount.H = E.add(simulation.state.amount.H, 1) simulation.state.auto_resources.H = E.add(simulation.state.auto_resources.H, 1) simulation.automatic.produce_brown_dwarfs(simulation.state, 1, E.of(i), E.of(E.add(i, 1))) check(E.eq(world.state, resumed.state), "Random sequence and prepaid fuel survive saving") check(E.near(E.add(E.add(world.state.amount.H, E.multiply(world.state.amount.HBD, E.of("0.1"))), world.state.auto_star_deficits.HBD_fuel), 500), "Individual production conserves fuel including prepaid reserve") check(E.near(E.add(world.state.amount.HBD, world.state.auto_star_deficits.HBD), 5), "Signed remainder preserves the 0.1 percent allocation") var paused_count: Variant = world.state.amount.HBD for i in 10: world.automatic.produce_brown_dwarfs(world.state, 0, 500, 501) check(E.eq(world.state.amount.HBD, paused_count), "No repeated random attempts without new fuel") dispose(resumed) dispose(world) # Two simultaneous successors share surviving planets in the same 99:1 ratio. world = fixture() world.catalog.entities.HRG.destroy_level = 0 world.state.amount.HRG = 100 world.state.binds.HRG = {"C1.3": 100} world.state.batches.HRG = [{"start_year": E.of("0.1"), "end_year": E.of("0.1"), "amount": 100}] world.evolution.evolve_batches(world.state, E.of("0.1")) check((E.eq(world.state.binds.SN["C1.3"], 99) and E.eq(world.state.binds.GRB["C1.3"], 1)), "Planets split among actual alternative successors") check(E.eq(world.state.binds.HRG["C1.3"], 0), "Alternative evolution leaves no orphan bindings") dispose(world) world = fixture() world.state.amount.N = 0 world.state.amount.HRG = 1 world.state.batches.HRG = [{"start_year": E.of("0.1"), "end_year": E.of("0.1"), "amount": 1}] world.evolute(3) check((E.eq(world.state.amount.LNS, 1) and E.eq(world.state.amount.SN, 0)), "Long step follows multiple stellar generations") check(E.ge(world.state.amount.S, 99), "Short-lived newborn supernova emits S before disappearing") dispose(world) print(("Stellar rules: %d checks, %d failures" % [checks, failures])) quit((0 if E.eq(failures, 0) else 1))