extends SceneTree # Headless gameplay test: run with # godot --headless -s res://tests/test_resource_readout.gd # Verifies ResourceReadout.gd (#49) generalizes ResourceCounter/GasCounter/ # CargoCounter/GasCargoCounter into one row per GameState.resource_types() # entry, in both Main.tscn and PlanetSurface.tscn, with no per-resource # code: # 1. exactly one banked + one fleet NeonNumber per current resource type, # each correctly reading its own resource's amount # 2. fleet rows hide at zero and show once carried, banked rows always show # 3. banked and fleet rows are visually distinct (colour, position) # 4. the script itself contains no hardcoded resource id - the row count # and mapping come entirely from GameState.resource_types() # 5. PlanetSurface.tscn's instance renders too, with its own bright- # background contrast # # A -s entry-point script can only reach the GameState autoload's CONSTANTS # through the bare "GameState" identifier (GameState.RESOURCE_ORE etc.) - # calling any of its METHODS that way fails to compile with "Identifier not # found: GameState", even from _initialize(). Every other test in this suite # already routes method calls through the actual instance # (root.get_node("GameState")) instead, and this file follows the same rule. var game_state: Node var main: Node var readout: Node var stage: int = 0 var elapsed: float = 0.0 func _initialize() -> void: game_state = root.get_node("GameState") game_state.bank_inventory.set_amount(GameState.RESOURCE_ORE, 11) game_state.bank_inventory.set_amount(GameState.RESOURCE_GAS, 4) game_state.fleet_inventory.set_amount(GameState.RESOURCE_ORE, 6) # Gas left at 0 in the fleet hold deliberately, to check the hide-at-zero # rule holds per-resource, not just per-readout. # --- 4. no hardcoded resource id in the generalized script --- var source: String = FileAccess.get_file_as_string("res://ResourceReadout.gd") for literal in ['"ore"', '"gas"', 'RESOURCE_ORE', 'RESOURCE_GAS']: if literal in source: return _fail("ResourceReadout.gd hardcodes %s - it must read GameState.resource_types() only" % literal) main = load("res://Main.tscn").instantiate() root.add_child(main) readout = main.get_node("UI/ResourceReadout") func _process(delta: float) -> bool: elapsed += delta match stage: 0: if elapsed < 0.2: return false # --- 1. one row per resource type, correctly mapped --- var types: PackedStringArray = game_state.resource_types() for resource_type in types: var banked: Node = readout.banked_number(resource_type) var fleet: Node = readout.fleet_number(resource_type) if banked == null or fleet == null: return _fail("no readout row for resource '%s'" % resource_type) if banked.amount != game_state.banked_resource(resource_type): return _fail("banked row for '%s' shows %d, bank has %d" % [ resource_type, banked.amount, game_state.banked_resource(resource_type) ]) # --- 2. hide-at-zero is per resource --- var ore_fleet: Node = readout.fleet_number(GameState.RESOURCE_ORE) var gas_fleet: Node = readout.fleet_number(GameState.RESOURCE_GAS) if not ore_fleet.visible: return _fail("fleet ore is 6 but its row is hidden") if gas_fleet.visible: return _fail("fleet gas is 0 but its row is showing") if ore_fleet.amount != 6: return _fail("fleet ore row shows %d, hold has 6" % ore_fleet.amount) # --- 3. banked and fleet are visually distinct --- var ore_banked: Node = readout.banked_number(GameState.RESOURCE_ORE) if ore_banked.glow_color == ore_fleet.glow_color: return _fail("banked and fleet rows share a colour") if ore_banked.position == ore_fleet.position: return _fail("banked and fleet rows share a position") # Depositing gas into the fleet hold should reveal its row live. game_state.fleet_inventory.deposit(GameState.RESOURCE_GAS, 3) elapsed = 0.0 stage = 1 return false 1: if elapsed < 0.2: return false var gas_fleet: Node = readout.fleet_number(GameState.RESOURCE_GAS) if not gas_fleet.visible or gas_fleet.amount != 3: return _fail("fleet gas row did not update live after a deposit (visible=%s amount=%d)" % [ gas_fleet.visible, gas_fleet.amount ]) # --- 5. the surface scene's instance also works, bright-background --- main.free() var surface: Node = load("res://PlanetSurface.tscn").instantiate() root.add_child(surface) var surface_readout: Node = surface.get_node("UI/ResourceReadout") if not surface_readout.bright_background: surface.free() return _fail("PlanetSurface's ResourceReadout instance is not set to bright_background") elapsed = 0.0 stage = 2 return false 2: if elapsed < 0.2: return false print("TEST_RESOURCE_READOUT: PASS") quit(0) return true return false func _fail(message: String) -> bool: print("TEST_RESOURCE_READOUT: FAIL (%s)" % message) quit(1) return true