#74: RESEARCH_LAB_CHANCE raised from 0.08 to 0.16 - research points gate mid/late skill-tree nodes and vessel/lab research now (#63), so 0.08 was too scarce for how central they'd become to progression. #75: an extractor placed on a research_lab planet would sit on an empty resource id forever, since it yields nothing by design. Refused in BuildController's placement confirm, with the same "explain the refusal" idiom every other build gate uses. register_capture_points() gained an optional definition_id parameter so the refusal/reward logic can tell a research_lab planet apart without threading an extra argument through every existing caller. #76: conquering a research_lab awarded a research point with no on-screen acknowledgement beyond a HUD number the player has no reason to be watching at that exact moment. CaptureLabel's existing "CONQUERED" flash now names the reward directly on a research_lab. test_extractor_building.gd and test_planet_conquest_gate.gd both use a "first planet chunk found" scan with no regard for definition_id; in this world's fixed seed that chunk happens to be a research_lab, so #75's new gate started refusing their otherwise-unrelated extractor placement checks. Both now skip a research_lab chunk when picking their target, same as test_research_lab_extractor_gate.gd does on purpose for its own dedicated coverage of that refusal.
This commit is contained in:
parent
d68aac6444
commit
63d0d6a496
5 changed files with 146 additions and 7 deletions
|
|
@ -27,7 +27,12 @@ func _initialize() -> void:
|
|||
for x in range(-15, 15):
|
||||
for y in range(-15, 15):
|
||||
var chunk: Vector2i = Vector2i(x, y)
|
||||
if WorldGen.has_planet_at_chunk(chunk):
|
||||
# #75: this test is about the planet-proximity/duplicate rules,
|
||||
# not resource type - skip a research_lab specifically, since it
|
||||
# yields nothing and is correctly refused (see
|
||||
# test_research_lab_extractor_gate.gd for that behaviour).
|
||||
if WorldGen.has_planet_at_chunk(chunk) \
|
||||
and WorldGen.planet_data_at_chunk(chunk).definition_id != "research_lab":
|
||||
target_chunk = chunk
|
||||
found = true
|
||||
break
|
||||
|
|
|
|||
|
|
@ -29,7 +29,12 @@ func _initialize() -> void:
|
|||
for x in range(-15, 15):
|
||||
for y in range(-15, 15):
|
||||
var chunk: Vector2i = Vector2i(x, y)
|
||||
if WorldGen.has_planet_at_chunk(chunk):
|
||||
# #75: this test is about the conquest gate, not resource type -
|
||||
# skip a research_lab specifically, since it yields nothing and
|
||||
# is correctly refused regardless of conquest (see
|
||||
# test_research_lab_extractor_gate.gd for that behaviour).
|
||||
if WorldGen.has_planet_at_chunk(chunk) \
|
||||
and WorldGen.planet_data_at_chunk(chunk).definition_id != "research_lab":
|
||||
target_chunk = chunk
|
||||
found = true
|
||||
break
|
||||
|
|
|
|||
114
tests/test_research_lab_extractor_gate.gd
Normal file
114
tests/test_research_lab_extractor_gate.gd
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
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://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_status.text):
|
||||
return _fail("refusal did not explain itself, status was '%s'" % controller.build_status.text)
|
||||
print("extractor refused on a research_lab planet, explained: '%s'" % controller.build_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
|
||||
Loading…
Reference in a new issue