spaceship/tests/test_workshop_staffing.gd

139 lines
5.2 KiB
GDScript3
Raw Normal View History

extends SceneTree
# Forgejo #216, the workshop half. A spacial workshop used to conjure its own
# repair drones, free and permanent. They are built at a ship crafter now,
# flown out from the mothership hangar to whichever workshop asked for them,
# and spent by the repairs they make.
#
# test_transporter_supply.gd covers the same rules on the hub side. The two
# share a model but not their wear paths - a transporter spends a run getting
# home, a drone spends a repair getting home - so the drone's own path is
# exercised here rather than assumed from the transporter's.
#
# Covers:
# A. a new workshop stands empty, and takes nothing until it is asked to
# B. the crafter accepts a repair drone order, which it used to refuse
# C. an assigned workshop is sent one from the hangar
# D. it repairs a damaged structure and is worn by doing so
# E. its last repair uses it up, and the workshop is short again
var state: Node
var workshop_id: int
var damaged_id: int
var elapsed: float = 0.0
var stage: int = 0
func _initialize() -> void:
state = root.get_node("GameState")
state.buildings.clear()
state.extractors.clear()
state.transporters.clear()
state.repair_drones.clear()
state.stored_vessels.clear()
state.vessel_deliveries.clear()
state.reset_progression()
state.rocks = 600
state.unlocked = ["shipyards", "logistics"]
state.add_building(state.BUILDING_MOTHERSHIP, Vector2.ZERO)
workshop_id = state.add_building(GameState.BUILDING_WORKSHOP, Vector2(700.0, 0.0))
damaged_id = state.add_building(state.BUILDING_SHIP_CRAFTER, Vector2(900.0, 200.0))
state.deposit_resource_to_building(workshop_id, GameState.RESOURCE_ORE, 400)
func _drones() -> int:
return state.station_crew(workshop_id)
func _process(delta: float) -> bool:
elapsed += delta
match stage:
0:
# --- A. nothing comes with the structure ---------------------
if not state.repair_drones.is_empty():
return _fail("a new workshop arrived with %d drones" % state.repair_drones.size())
state.stored_vessels.append(GameState.REPAIR_DRONE)
state._advance_station_dispatch()
if _drones() != 0:
return _fail("a workshop that asked for nothing took a drone anyway")
print("a new workshop stands empty, and takes nothing unasked")
# --- B. the crafter takes the order --------------------------
var crafter_id: int = state.add_building(state.BUILDING_SHIP_CRAFTER, Vector2(-900.0, 0.0))
if not state.queue_order(crafter_id, GameState.REPAIR_DRONE):
return _fail("the crafter refused a repair drone order")
state.find_building(crafter_id).orders.clear()
# --- C. assigned, then sent ----------------------------------
if state.set_station_desired(workshop_id, 1) != 1:
return _fail("the workshop refused an order for one drone")
state._advance_station_dispatch()
if state.vessel_deliveries.is_empty():
return _fail("nothing was sent to the workshop")
elapsed = 0.0
stage = 1
return false
1:
if _drones() < 1:
if elapsed > 25.0:
return _fail("the drone never reached the workshop")
return false
var fresh: Array = state.station_condition(workshop_id)
if fresh.size() != 1 or int(fresh[0]) != GameState.DRONE_REPAIRS:
return _fail("the arrived drone reports %s, expected [%d]" \
% [fresh, GameState.DRONE_REPAIRS])
print("ordered and flown out: 1 drone with %d repairs in it" % GameState.DRONE_REPAIRS)
# --- D. it does the work, and is worn by it ------------------
state.damage_building(damaged_id, state.building_max_hp(state.BUILDING_SHIP_CRAFTER) / 2)
elapsed = 0.0
stage = 2
return false
2:
if state.building_health_fraction(damaged_id) >= 0.999:
print("the workshop's own drone repaired the structure")
elapsed = 0.0
stage = 3
return false
if elapsed > 40.0:
return _fail("the drone never repaired the damaged structure")
return false
3:
# Spent on getting HOME, so this waits for it to be idle again.
if state.repair_drones.is_empty():
return _fail("the drone vanished mid-run")
if String(state.repair_drones[0].state) != GameState.DRONE_IDLE:
if elapsed > 25.0:
return _fail("the drone never got home")
return false
var worn: Array = state.station_condition(workshop_id)
if worn.is_empty() or int(worn[0]) >= GameState.DRONE_REPAIRS:
return _fail("a drone that ran a repair is still unworn (%s)" % [worn])
print("a completed repair wore it to %d" % int(worn[0]))
# --- E. and its last one uses it up --------------------------
state.repair_drones[0].repairs_left = 1
state.damage_building(damaged_id, state.building_max_hp(state.BUILDING_SHIP_CRAFTER) / 2)
elapsed = 0.0
stage = 4
return false
4:
if not state.repair_drones.is_empty():
if elapsed > 40.0:
return _fail("a drone on its last repair was never retired")
return false
if state.stored_vessels.has(GameState.REPAIR_DRONE):
return _fail("a spent drone went back to the hangar instead of being used up")
if _drones() != 0:
return _fail("the workshop still counts a retired drone")
print("spent after its last repair: gone, and the workshop is short again")
print("TEST_WORKSHOP_STAFFING: PASS")
quit(0)
return true
return false
func _fail(message: String) -> bool:
print("TEST_WORKSHOP_STAFFING: FAIL (%s)" % message)
quit(1)
return true