#223: an office declared a flat buffer - 60 ore, 30 gas, 30 energy - whatever was in its berth, so one keeping an interceptor had transporters haul it gas and energy it can never spend, and the figure bore no relation to what it was actually charged. Since #220 that charge depends on the berth's occupant and on how far down the fleet the berth sits, neither of which a definition can state. It asks for what its own berth costs, four charges deep: enough that the tax is payable whenever the bank has anything - a transporter round trip fits inside four intervals - and no more, so an office is not a hoard. Same idiom outposts and workshops already use for world-dependent demand. A small floor stays in the definition on purpose: an empty berth asks for nothing dynamic, so without it a newly crewed berth would start from zero and could starve before its first delivery landed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
103 lines
4.8 KiB
GDScript
103 lines
4.8 KiB
GDScript
extends SceneTree
|
|
|
|
# Forgejo #223: a Fleet Office is stocked to a bounded amount - enough that
|
|
# its charge is always payable while the bank has anything, and no more.
|
|
#
|
|
# It used to declare a flat buffer (60 ore, 30 gas, 30 energy) whatever was
|
|
# in its berth, so an office keeping an interceptor had transporters haul it
|
|
# gas and energy it could never spend, and the amount had no relation to what
|
|
# it was actually charged. Since #220 the charge also depends on how far down
|
|
# the fleet the berth sits, which no definition can state.
|
|
#
|
|
# Covers:
|
|
# A. an office asks for what its OWN berth is charged, not a flat figure
|
|
# B. it asks for nothing of a resource that berth never spends
|
|
# C. what it asks for covers at least one charge, so the tax is payable
|
|
# D. the request is bounded - a stocked office stops asking
|
|
# E. and a deeper berth, which #220 charges more, asks for more
|
|
|
|
var state: Node
|
|
|
|
|
|
func _initialize() -> void:
|
|
state = root.get_node("GameState")
|
|
state.buildings.clear()
|
|
state.transporters.clear()
|
|
state.reset_progression()
|
|
state.reset_new_game()
|
|
state.intro_active = false
|
|
state.fleet_vessel_types = PackedStringArray()
|
|
|
|
|
|
func _process(_delta: float) -> bool:
|
|
var offices: Array = []
|
|
for i in range(4):
|
|
offices.append(state.add_building(GameState.BUILDING_FLEET_OFFICE,
|
|
Vector2(600.0 * float(i + 1), 0.0)))
|
|
# Berth 2 keeps an interceptor (ore only); berth 5 keeps a laser, which
|
|
# is dearer both in kind and in depth.
|
|
state.fleet_vessel_types = PackedStringArray([
|
|
GameState.VESSEL_INTERCEPTOR, GameState.VESSEL_INTERCEPTOR,
|
|
GameState.VESSEL_LASER, GameState.VESSEL_LASER, GameState.VESSEL_LASER])
|
|
|
|
var first: int = int(offices[0])
|
|
var charge: Dictionary = state.fleet_office_upkeep(
|
|
GameState.VESSEL_INTERCEPTOR, GameState.BASE_FLEET_SIZE)
|
|
var ore_charge: int = int(charge.get(GameState.RESOURCE_ORE, 0))
|
|
if ore_charge <= 0:
|
|
return _fail("an interceptor berth is charged no ore, so this proves nothing")
|
|
|
|
# --- A + C. it asks for its own charge, several times over ---------
|
|
var ore_wanted: int = state.building_requested_resource(first, GameState.RESOURCE_ORE)
|
|
if ore_wanted < ore_charge:
|
|
return _fail("an empty office asks for %d ore against a %d charge - it can starve with ore banked" \
|
|
% [ore_wanted, ore_charge])
|
|
if ore_wanted < ore_charge * GameState.FLEET_OFFICE_STOCK_CHARGES:
|
|
return _fail("asks for %d ore, under the %d charges it is meant to hold" \
|
|
% [ore_wanted, GameState.FLEET_OFFICE_STOCK_CHARGES])
|
|
# A cheap hull's charges come to less than the small floor the definition
|
|
# declares, and the floor wins - that floor is what keeps a berth payable
|
|
# before its first delivery lands. The dynamic term is what matters for a
|
|
# dear one, which is checked at berth 5 below.
|
|
|
|
# --- B. and nothing it cannot spend --------------------------------
|
|
# An interceptor costs ore alone, so the gas request is the definition's
|
|
# small floor rather than a buffer's worth of cargo it will never burn.
|
|
var gas_wanted: int = state.building_requested_resource(first, GameState.RESOURCE_GAS)
|
|
if gas_wanted >= ore_wanted:
|
|
return _fail("an ore-only berth asks for %d gas against %d ore" % [gas_wanted, ore_wanted])
|
|
print("berth 2 (interceptor): %d ore wanted for a %d charge, %d gas" \
|
|
% [ore_wanted, ore_charge, gas_wanted])
|
|
|
|
# --- D. bounded: stocked, it stops asking ---------------------------
|
|
state.deposit_resource_to_building(first, GameState.RESOURCE_ORE, ore_wanted)
|
|
if state.building_requested_resource(first, GameState.RESOURCE_ORE) != 0:
|
|
return _fail("a stocked office is still asking for ore - the fill is unbounded")
|
|
state.deposit_resource_to_building(first, GameState.RESOURCE_ORE, 500)
|
|
if state.building_requested_resource(first, GameState.RESOURCE_ORE) != 0:
|
|
return _fail("an over-stocked office asks for still more")
|
|
print("stocked, it asks for nothing further")
|
|
|
|
# --- E. a deeper berth costs more, and asks for more ----------------
|
|
var deep: int = int(offices[3])
|
|
var deep_ore: int = state.building_requested_resource(deep, GameState.RESOURCE_ORE)
|
|
var shallow_laser: Dictionary = state.fleet_office_upkeep(
|
|
GameState.VESSEL_LASER, GameState.BASE_FLEET_SIZE)
|
|
if deep_ore <= int(shallow_laser.get(GameState.RESOURCE_ORE, 0)) * GameState.FLEET_OFFICE_STOCK_CHARGES - 1:
|
|
return _fail("berth 5 asks for %d ore, no more than the same hull would at berth 2" % deep_ore)
|
|
# A laser burns energy too, so that berth asks for energy where the
|
|
# interceptor's did not.
|
|
if state.building_requested_resource(deep, GameState.RESOURCE_ENERGY) \
|
|
<= state.building_requested_resource(first, GameState.RESOURCE_ENERGY):
|
|
return _fail("a laser berth asks for no more energy than an interceptor berth")
|
|
print("berth 5 (laser, deeper): %d ore and energy on top" % deep_ore)
|
|
|
|
print("TEST_FLEET_OFFICE_STOCK: PASS")
|
|
quit(0)
|
|
return true
|
|
|
|
|
|
func _fail(message: String) -> bool:
|
|
print("TEST_FLEET_OFFICE_STOCK: FAIL (%s)" % message)
|
|
quit(1)
|
|
return true
|