extends SceneTree var checks: int = 0 var failures: int = 0 func _initialize() -> void: call_deferred("run") func check(value: bool, message: String) -> void: checks += 1 if not value: failures += 1 push_error(message) func run() -> void: var scene = load("res://world/world.tscn").instantiate() var stage = scene.get_node("Stage") stage.owniverse.free() stage.set_script(load("res://tests/fixtures/ui_stage.gd")) root.add_child(scene) await process_frame await process_frame var world = stage.owniverse world.state.binds.RD = {"EON1": 10.0, "EON2": 4.0, "C0.0": 3.0} world.state.amount.EON1 = 2.0 world.state.stats.total_amount.EON1 = 12.0 world.state.stats.total_amount.EON2 = 4.0 world.state.stats.total_amount["C0.0"] = 3.0 var before: Dictionary = world.state.duplicate(true) stage._refresh_universe_ui() var counts: Dictionary = world.get_item_amounts() check(counts.EON1 == 12.0 and counts.EON2 == 4.0 and counts.LP == 16.0, "Individual eons and their total include bound planets") check(counts["C0.0"] == 3.0 and counts.C0 == 3.0 and counts.Planet == 19.0, "Civilization detail does not double the planetary total") check(world.get_item_amounts(true).EON1 == 12.0 and world.get_item_amounts(true).LP == 16.0, "Historical counts retain individual and aggregate values") check(world.state == before, "Presentation does not modify simulation state") var pending: Array = ["EON1", "EON2", "EON3", "C0.0"] var pending_before: Array = pending.duplicate() var decision: Dictionary = world.presentation.unlocks(world.state, world.catalog, pending) check(decision.remaining == ["EON3"], "Only unmet requirements remain pending") for id in ["EON1", "EON2", "LP", "C0.0", "C0"]: check(decision.visible.has(id), "Unlock projection includes detail and alias: " + id) check(pending == pending_before and world.state == before, "Unlock evaluation leaves inputs untouched") var snapshot: Dictionary = world.items_to_update.duplicate() world.defer_item_updates = true world.state.amount.EON1 += 1.0 world.refresh_item_amounts() check(world.item_amounts_dirty and world.items_to_update == snapshot, "Deferred refresh retains pending snapshot") world.refresh_item_amounts(true) check(not world.item_amounts_dirty and world.items_to_update.EON1 == 13.0, "Forced refresh publishes latest amounts") world.state.amount.EON1 -= 1.0 world.defer_item_updates = false world.refresh_item_amounts() for id in ["EON1", "EON2", "LP", "C0.0", "C0"]: check(stage.owniverse_items[id].visible, "Unlock both levels: " + id) check(stage.owniverse_items[id].description.text != "", "Populate the icon counter: " + id) check(not stage.owniverse_items.EON3.visible, "Unreached eon remains locked") stage.item_activated(stage.owniverse_items.LP) check(stage.owniverse_items.EON1.is_visible_in_tree(), "Selecting LP shows its unlocked eons") stage.item_activated(stage.owniverse_items.C0) check(stage.owniverse_items["C0.0"].is_visible_in_tree() and not stage.owniverse_items.EON1.is_visible_in_tree(), "Selecting C0 switches the detail panel") world.state.binds.RD.EON2 = 0.0 stage._refresh_universe_ui() check(stage.owniverse_items.EON2.visible and stage.owniverse_items.EON2.description.text == "", "Previously reached stage stays unlocked after extinction with no stale count") for entity in world.entities.values(): entity.free() world.free() scene.free() print("Life icons: %d checks, %d failures" % [checks, failures]) quit(0 if failures == 0 else 1)