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(value: bool, message: String) -> void: checks = E.add(checks, 1) if (not value): failures = E.add(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, "EON2": 4, "C0.0": 3} world.state.amount.EON1 = 2 world.state.stats.total_amount.EON1 = 12 world.state.stats.total_amount.EON2 = 4 world.state.stats.total_amount["C0.0"] = 3 var before: Dictionary = world.state.duplicate(true) stage._refresh_universe_ui() var counts: Dictionary = world.presentation.amounts(world.state, world.catalog) check(((E.eq(counts.EON1, 12) and E.eq(counts.EON2, 4)) and E.eq(counts.LP, 16)), "Individual eons and their total include bound planets") check(((E.eq(counts["C0.0"], 3) and E.eq(counts.C0, 3)) and E.eq(counts.Planet, 19)), "Civilization detail does not double the planetary total") check((E.eq(world.presentation.amounts(world.state, world.catalog, true).EON1, 12) and E.eq(world.presentation.amounts(world.state, world.catalog, true).LP, 16)), "Historical counts retain individual and aggregate values") check(E.eq(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(E.eq(decision.remaining, ["EON3"]), "Only unmet requirements remain pending") for id in ["EON1", "EON2", "LP", "C0.0", "C0"]: check(decision.visible.has(id), E.add("Unlock projection includes detail and alias: ", id)) check((E.eq(pending, pending_before) and E.eq(world.state, before)), "Unlock evaluation leaves inputs untouched") var snapshot: Dictionary = world.presentation.pending_amounts.duplicate() world.presentation.deferred_updates = true world.state.amount.EON1 = E.add(world.state.amount.EON1, 1) world.presentation.refresh(world.state, world.catalog) check((world.presentation.dirty and E.eq(world.presentation.pending_amounts, snapshot)), "Deferred refresh retains pending snapshot") world.presentation.refresh(world.state, world.catalog, true) check(((not world.presentation.dirty) and E.eq(world.presentation.pending_amounts.EON1, 13)), "Forced refresh publishes latest amounts") world.state.amount.EON1 = E.subtract(world.state.amount.EON1, 1) world.presentation.deferred_updates = false world.presentation.refresh(world.state, world.catalog) for id in ["EON1", "EON2", "LP", "C0.0", "C0"]: check(stage.owniverse_items[id].visible, E.add("Unlock both levels: ", id)) check(E.ne(stage.owniverse_items[id].description.text, ""), E.add("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 stage._refresh_universe_ui() check((stage.owniverse_items.EON2.visible and E.eq(stage.owniverse_items.EON2.description.text, "")), "Previously reached stage stays unlocked after extinction with no stale count") for entity in world.catalog.entities.values(): entity.free() world.free() scene.free() print(("Life icons: %d checks, %d failures" % [checks, failures])) quit((0 if E.eq(failures, 0) else 1))