extends SceneTree # Headless gameplay test: run with # godot --headless -s res://tests/test_research_lab_extractor_gate.gd # Forgejo #75: a research_lab planet yields no resources at all (#63) - an # extractor placed there would sit on an empty resource id forever. The # build menu must refuse the placement and explain why, the same "explain # the refusal" idiom used for every other build gate. Mirrors # test_extractor_building.gd's own chunk-discovery/settle/confirm shape. var main_scene: Node var fleet: Node var game_state: Node var controller: Node var target_chunk: Vector2i var target_planet_id: String var stage: int = 0 var elapsed: float = 0.0 func _initialize() -> void: var found: bool = false for x in range(-40, 40): for y in range(-40, 40): var chunk: Vector2i = Vector2i(x, y) if not WorldGen.has_planet_at_chunk(chunk): continue if WorldGen.planet_data_at_chunk(chunk).definition_id == "research_lab": target_chunk = chunk found = true break if found: break if not found: print("TEST_RESEARCH_LAB_EXTRACTOR_GATE: FAIL (no research_lab chunk found to test with)") quit(1) return game_state = root.get_node("GameState") game_state.rocks = 200 game_state.buildings.clear() game_state.extractors.clear() game_state.planet_capture.clear() target_planet_id = "chunk:%d:%d" % [target_chunk.x, target_chunk.y] # This test is about the resource-id gate, not conquest itself (see # test_planet_conquest_gate) - pre-conquer the target directly. game_state.register_capture_points(target_planet_id, 1, "research_lab") game_state.mark_point_captured(target_planet_id, 0) game_state.reset_progression() for node in GameState.SKILL_TREE: game_state.unlocked.append(node.id) main_scene = load("res://world/Main.tscn").instantiate() root.add_child(main_scene) fleet = main_scene.get_node("Fleet") controller = main_scene.get_node("BuildController") func _process(delta: float) -> bool: elapsed += delta match stage: 0: main_scene.get_node("AsteroidField").set_process(false) main_scene.get_node("EnemySpawner").set_process(false) var near: Vector2 = WorldGen.chunk_origin(target_chunk) + Vector2.ONE * WorldGen.CHUNK_SIZE * 0.5 for ship in fleet.ships: ship.position = near fleet.move_to(near) elapsed = 0.0 stage = 1 return false 1: var planet_field: Node = main_scene.get_node("PlanetField") if elapsed < planet_field.check_interval + 0.2: return false if not planet_field.populated_chunks.has(target_chunk): return _fail("the research_lab planet never spawned") var planet: Node2D = planet_field.populated_chunks[target_chunk][0] if String(planet.resource_type) != "": return _fail("test setup error: chosen planet's resource_type is '%s', expected empty" \ % planet.resource_type) for ship in fleet.ships: ship.position = planet.position fleet.move_to(planet.position) elapsed = 0.0 stage = 2 return false 2: if elapsed < 0.3: return false controller._on_build_pressed() if not controller.build_menu.visible: return _fail("the build menu did not open over the planet") var before: int = game_state.extractors.size() controller._show_building_info(GameState.BUILDING_EXTRACTOR) controller._confirm_build() if game_state.extractors.size() != before: return _fail("an extractor was built on a research_lab planet") if not ("nothing to extract" in controller.build_menu.status.text): return _fail("refusal did not explain itself, status was '%s'" % controller.build_menu.status.text) print("extractor refused on a research_lab planet, explained: '%s'" % controller.build_menu.status.text) print("TEST_RESEARCH_LAB_EXTRACTOR_GATE: PASS") quit(0) return true return false func _fail(message: String) -> bool: print("TEST_RESEARCH_LAB_EXTRACTOR_GATE: FAIL (%s)" % message) quit(1) return true