extends SceneTree # Headless gameplay test: run with # godot --headless -s res://tests/test_conquered_planet_clear.gd # A planet's garrison was destroyed to take it, so it must not be standing # there again the next time the player lands. # # #211 made the garrison the whole of conquest: killing the last defender # takes the planet, and there are no capture points beside them any more. # # Covers: # A. an unconquered planet lays out its authored enemies, as before # B. killing the last of them conquers it, and re-landing places none # C. a setup with NO enemies counts as vacuously conquered - there is # nothing there to beat # D. a half-cleared planet the player left comes back whole, and its count # with it, rather than falling to a single kill on the next visit const PLANET_KEY: String = "test_conquered_planet_clear" const OPEN_PLANET_KEY: String = "test_conquered_planet_clear_open" const LEFT_PLANET_KEY: String = "test_conquered_planet_clear_left" var game_state: Node var host_scene: PackedScene var stage: int = 0 var elapsed: float = 0.0 func _initialize() -> void: game_state = root.get_node("GameState") game_state.planet_capture.clear() host_scene = load("res://surface/PlanetSetupHost.tscn") func _process(delta: float) -> bool: elapsed += delta if stage == 0: # One frame of grace so the autoload is fully up, same as the other # scene-driven tests. if elapsed < 0.1: return false # --- A. unconquered: the garrison is there --------------------------- game_state.planet_id = PLANET_KEY game_state.planet_definition_id = "rocky" var setup: Resource = _make_setup(3) var enemies: int = _apply_and_count_enemies(setup) if enemies != 3: return _fail("an unconquered planet placed %d of its 3 authored enemies" % enemies) if game_state.is_planet_conquered(PLANET_KEY): return _fail("a planet with 3 defenders standing reported itself conquered") print("unconquered planet: 3 enemies placed") # --- B. the last kill takes it, and it stays taken ------------------- game_state.mark_garrison_enemy_destroyed(PLANET_KEY) game_state.mark_garrison_enemy_destroyed(PLANET_KEY) if game_state.is_planet_conquered(PLANET_KEY): return _fail("the planet fell with a defender still standing") game_state.mark_garrison_enemy_destroyed(PLANET_KEY) if not game_state.is_planet_conquered(PLANET_KEY): return _fail("killing the whole garrison did not conquer the planet") var remaining: int = _apply_and_count_enemies(setup) if remaining != 0: return _fail("re-landing on a conquered planet placed %d enemies" % remaining) print("conquered planet: last kill took it, re-landing places nobody") # --- C. nothing to fight is nothing to take -------------------------- game_state.planet_id = OPEN_PLANET_KEY var open_setup: Resource = _make_setup(0) var open_enemies: int = _apply_and_count_enemies(open_setup) if not game_state.is_planet_conquered(OPEN_PLANET_KEY): return _fail("a setup with no enemies was expected to be vacuously conquered") if open_enemies != 0: return _fail("a setup authoring no enemies placed %d" % open_enemies) print("setup with no garrison: vacuously conquered, nobody placed") # --- D. leaving mid-fight does not bank the kills -------------------- # The garrison is re-placed in full on the next landing, so its count # has to start again with it - otherwise a planet left at one-from- # clear would fall to a single kill against three fresh defenders. game_state.planet_id = LEFT_PLANET_KEY var left_setup: Resource = _make_setup(3) _apply_and_count_enemies(left_setup) game_state.mark_garrison_enemy_destroyed(LEFT_PLANET_KEY) game_state.mark_garrison_enemy_destroyed(LEFT_PLANET_KEY) var returned: int = _apply_and_count_enemies(left_setup) if returned != 3: return _fail("returning to a half-cleared planet placed %d of 3 defenders" % returned) game_state.mark_garrison_enemy_destroyed(LEFT_PLANET_KEY) if game_state.is_planet_conquered(LEFT_PLANET_KEY): return _fail("one kill took a planet defended by three - the count did not reset with the garrison") print("returning mid-fight: the garrison and its count both start again") print("TEST_CONQUERED_PLANET_CLEAR: PASS") quit(0) return true return false func _make_setup(enemy_count: int) -> Resource: var setup: Resource = load("res://surface/PlanetSetup.gd").new() setup.setup_id = "in_memory" setup.surface_profile_id = "rocky" var spawn_script: Script = load("res://surface/PlanetSetupSpawn.gd") for i in range(enemy_count): var spawn: Resource = spawn_script.new() spawn.enemy_id = "chaser" spawn.position = Vector2(0.0, 200.0 * float(i + 1)) setup.enemy_spawns.append(spawn) return setup func _apply_and_count_enemies(setup: Resource) -> int: var host: Node = host_scene.instantiate() root.add_child(host) host.apply_setup(setup) var count: int = _count_enemies(host) host.free() return count # Counted by group rather than by script or node name: that is how everything # else in the game finds enemies, so this cannot pass while the real hunters # see something different. func _count_enemies(host: Node) -> int: var count: int = 0 for child in host.get_children(): if child.is_in_group("enemies"): count += 1 return count func _fail(message: String) -> bool: print("TEST_CONQUERED_PLANET_CLEAR: FAIL (%s)" % message) quit(1) return true