Prioritize queued logistics deliveries

This commit is contained in:
Loïc Wisniewski 2026-08-15 10:41:18 +02:00
commit f5c60f8805
2 changed files with 46 additions and 29 deletions

View file

@ -1155,6 +1155,40 @@ func _dispatch_transporters() -> void:
var mothership: Variant = get_mothership_position() var mothership: Variant = get_mothership_position()
if mothership == null: if mothership == null:
return # nowhere to load from return # nowhere to load from
# Supply already-queued production and research before collecting passive
# extractor output. Extractors can refill forever, so servicing them first
# can otherwise consume every transporter each time one becomes idle and
# permanently starve a partly supplied order.
for b in buildings:
var needed_resource := ""
for resource_type in resource_types():
if outstanding_resource_cost(int(b.id), resource_type) > 0 \
and bank_inventory.amount(resource_type) > 0:
needed_resource = resource_type
break
if needed_resource == "":
continue
# One at a time per building: without this every idle transporter
# would be sent after the same shortfall and they would all arrive
# carrying resources nobody needs any more.
if _transporter_inbound_to(int(b.id)):
continue
var chosen: Dictionary = {}
var best_d: float = INF
for t in transporters:
if t.state != TRANSPORTER_IDLE:
continue
var here: Vector2 = transporter_position(t)
var d: float = here.distance_squared_to(b.position)
if d < best_d:
best_d = d
chosen = t
if chosen.is_empty():
return # every transporter is busy
chosen.target_id = int(b.id)
chosen.resource_type = needed_resource
_begin_leg(chosen, transporter_position(chosen), mothership, TRANSPORTER_TO_MOTHERSHIP)
# A distant extractor is worth visiting only once it has a full hold ready. # A distant extractor is worth visiting only once it has a full hold ready.
# This keeps the transporter system meaningful: mining is local until a # This keeps the transporter system meaningful: mining is local until a
# vessel physically carries a researched-sized load home. # vessel physically carries a researched-sized load home.
@ -1180,35 +1214,6 @@ func _dispatch_transporters() -> void:
chosen_extractor.target_id = 0 chosen_extractor.target_id = 0
_begin_leg(chosen_extractor, transporter_position(chosen_extractor), extractor.position, _begin_leg(chosen_extractor, transporter_position(chosen_extractor), extractor.position,
TRANSPORTER_TO_EXTRACTOR) TRANSPORTER_TO_EXTRACTOR)
for b in buildings:
var needed_resource := ""
for resource_type in resource_types():
if outstanding_resource_cost(int(b.id), resource_type) > 0 \
and bank_inventory.amount(resource_type) > 0:
needed_resource = resource_type
break
if needed_resource == "":
continue
# One at a time per building: without this every idle transporter
# would be sent after the same shortfall and they would all arrive
# carrying ore nobody needs any more.
if _transporter_inbound_to(int(b.id)):
continue
var chosen: Dictionary = {}
var best_d: float = INF
for t in transporters:
if t.state != TRANSPORTER_IDLE:
continue
var here: Vector2 = transporter_position(t)
var d: float = here.distance_squared_to(b.position)
if d < best_d:
best_d = d
chosen = t
if chosen.is_empty():
return # every transporter is busy
chosen.target_id = int(b.id)
chosen.resource_type = needed_resource
_begin_leg(chosen, transporter_position(chosen), mothership, TRANSPORTER_TO_MOTHERSHIP)
func _advance_transporters(delta: float) -> void: func _advance_transporters(delta: float) -> void:

View file

@ -9,7 +9,7 @@ func _initialize() -> void:
state.stored_vessels.clear() state.stored_vessels.clear()
state.reset_progression() state.reset_progression()
state.rocks = 0 state.rocks = 0
state.gas = 30 state.gas = 10
state.build_time_scale = 0.01 state.build_time_scale = 0.01
state.add_building(GameState.BUILDING_MOTHERSHIP, Vector2.ZERO) state.add_building(GameState.BUILDING_MOTHERSHIP, Vector2.ZERO)
@ -18,8 +18,20 @@ func _initialize() -> void:
if not state.queue_lab_research(lab_id, "unlock_gas_bomber"): if not state.queue_lab_research(lab_id, "unlock_gas_bomber"):
_fail("could not queue gas research") _fail("could not queue gas research")
return return
if state.outstanding_resource_cost(lab_id, GameState.RESOURCE_GAS) != 30: # Reproduce a first 20-unit delivery followed by the remaining 10 being
_fail("lab did not request 30 gas") # available at the mothership. Full extractors must not take priority over
# completing this already-partly-supplied research order.
state.deposit_resource_to_building(lab_id, GameState.RESOURCE_GAS, 20)
state.add_extractor("Ore A", Vector2(240, 0), GameState.RESOURCE_ORE)
state.add_extractor("Ore B", Vector2(360, 0), GameState.RESOURCE_ORE)
for extractor in state.extractors:
extractor.inventory.deposit(GameState.RESOURCE_ORE, state.transporter_load_limit())
if state.outstanding_resource_cost(lab_id, GameState.RESOURCE_GAS) != 10:
_fail("partly supplied lab did not request its remaining 10 gas")
return
state._dispatch_transporters()
if not state._transporter_inbound_to(lab_id):
_fail("extractor collection took priority over waiting research")
return return
# Large steps make each physical leg complete in one call; multiple calls # Large steps make each physical leg complete in one call; multiple calls