spaceship/tests/test_conquered_planet_clear.gd
Loïc Wisniewski 6e13b6397c Take planets by killing what defends them
#211 conquest is the fight now: a planet registers the garrison its setup
authors, each defender's own death counts against it, and the last one takes
the world. The capture points - stand in a ring, wait out a timer, once per
ring - are gone, along with the editor palette that placed them.
#212 conquest opens a dialog on the surface naming the research points
recovered; the award travels with the signal, after it is banked.
#209 the prologue's charted sectors go with the breach, so the map the
survivors keep is of where they now are - and "chart 30 sectors" is no
longer complete before they have flown anywhere.
#218 enemy variety is gated on the FLEET, not on wave strength: a starting
fleet meets chasers only at any wave number, and each vessel past three
opens one more kind.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
2026-09-05 13:31:25 +02:00

137 lines
5.3 KiB
GDScript

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