Gas burner building and the energy resource (#54)
A new building that consumes gas to produce energy, a new resource
stored and moved exactly like ore and gas.
The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own
warm yellow-green ResourceDefinition, registered in
ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY.
Inventory/ResourceBar/ResourceTransferList needed no changes - #49
already made them resource-agnostic, confirmed structurally in the
test rather than touched.
The building: GasBurnerBuildingVisual (a hexagonal chamber with intake
vents in gas's colour and output ports in energy's, so the silhouette
itself reads "gas in, energy out"), GasBurnerBuildingDefinition
(capabilities=["gas_burner"], its own build-menu icon appended to
IconButton.Icon rather than inserted, per the ticket's own warning
about renumbering stored scene values), and the matching
UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new
"Power Systems" skill-tree node, mirroring how "freight" unlocks the
transport hub.
Conversion: _advance_gas_burners(), simulated in GameState alongside
_advance_production/extractor mining so it keeps running while the
player is elsewhere. Withdraws gas and deposits energy in the
building's OWN inventory only - never the bank - so it stalls with no
local gas exactly like a lab waiting on materials.
Logistics: a gas burner's ongoing gas deficit is folded into the
existing queued-building-supply dispatch path (same "needs resource X"
loop production/research orders already use, extended with
gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/
TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy
to the bank, mirroring the extractor pickup path per the ticket. The
existing f5c60f8 priority (queued deliveries outrank collection) holds:
the pickup dispatch loop runs last.
Tests: new tests/test_gas_burner.gd (resource genericity, stall
semantics, research gate, and full delivery+pickup logistics via a
real hub), run_tests transporter/resource regressions, and screenshots
of the build menu (all 7 buildings) and transfer menu (all 3
resources). Full suite: 81/81.
Two real bugs found and fixed along the way, neither gas-burner-
specific:
- _transporter_inbound_to() matched ANY non-idle transporter with a
matching target_id, regardless of purpose. Once pickup states shared
target_id with delivery states (both address a building, not an
extractor), a transporter delivering gas made the SAME building look
"busy" to the unrelated energy-pickup dispatch, starving it even
with a second, genuinely free transporter sitting idle at the hub.
Split into _transporter_inbound_to() (delivery states only) and a
new _transporter_inbound_for_pickup() (pickup states only).
- The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content
sizing) had no room for a 7th building - despite the ticket's own
note that no layout changes should be needed. A naive 4th row ran
off the bottom of a 720x1280 viewport; fitting one meant both adding
a 4th row top AND shrinking the shared button/label/cost sizing so
each row's content no longer taller than the compressed row spacing.
Caught only by actually screenshotting it - a real build menu, not
headless, since --headless renders nothing.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
|
|
|
extends SceneTree
|
|
|
|
|
|
|
|
|
|
# Headless gameplay test: run with
|
|
|
|
|
# godot --headless -s res://tests/test_gas_burner.gd
|
|
|
|
|
# Forgejo #54: gas burner building + the energy resource, stored/moved
|
|
|
|
|
# exactly like ore and gas.
|
|
|
|
|
#
|
|
|
|
|
# Modeled on tests/test_extractor_income.gd's shape: pure GameState state,
|
|
|
|
|
# no scene loaded, poking buildings/inventories directly and waiting out
|
|
|
|
|
# real production/transporter timing with generous margins rather than
|
|
|
|
|
# fixed frame counts (SceneTree physics can run ahead of _process(), trap 5
|
|
|
|
|
# in the repo notes).
|
|
|
|
|
#
|
|
|
|
|
# Covers:
|
|
|
|
|
# A. energy is fully generic - in resource_types(), has its own
|
|
|
|
|
# ResourceDefinition/glyph/colour - with no per-resource code anywhere
|
|
|
|
|
# (ResourceBar/ResourceTransferList already iterate resource_types())
|
|
|
|
|
# B. a burner with local gas converts it to energy, into its OWN
|
|
|
|
|
# inventory, at the configured rate; with no gas it stalls and never
|
|
|
|
|
# touches the bank
|
|
|
|
|
# C. the building is gated behind its own research node
|
|
|
|
|
# D. a hub transporter both delivers gas to a burner and collects its
|
|
|
|
|
# energy, following the existing supply/pickup dispatch paths
|
|
|
|
|
|
|
|
|
|
var game_state: Node
|
|
|
|
|
var stage: int = 0
|
|
|
|
|
var elapsed: float = 0.0
|
|
|
|
|
var mothership_id: int = 0
|
|
|
|
|
var hub_id: int = 0
|
|
|
|
|
var burner_id: int = 0
|
|
|
|
|
var load_limit: int = 0
|
|
|
|
|
var energy_before_stall: int = 0
|
2026-08-16 21:38:07 +02:00
|
|
|
var conversion_rate: float = 0.0
|
|
|
|
|
var conversion_yield: int = 0
|
Gas burner building and the energy resource (#54)
A new building that consumes gas to produce energy, a new resource
stored and moved exactly like ore and gas.
The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own
warm yellow-green ResourceDefinition, registered in
ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY.
Inventory/ResourceBar/ResourceTransferList needed no changes - #49
already made them resource-agnostic, confirmed structurally in the
test rather than touched.
The building: GasBurnerBuildingVisual (a hexagonal chamber with intake
vents in gas's colour and output ports in energy's, so the silhouette
itself reads "gas in, energy out"), GasBurnerBuildingDefinition
(capabilities=["gas_burner"], its own build-menu icon appended to
IconButton.Icon rather than inserted, per the ticket's own warning
about renumbering stored scene values), and the matching
UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new
"Power Systems" skill-tree node, mirroring how "freight" unlocks the
transport hub.
Conversion: _advance_gas_burners(), simulated in GameState alongside
_advance_production/extractor mining so it keeps running while the
player is elsewhere. Withdraws gas and deposits energy in the
building's OWN inventory only - never the bank - so it stalls with no
local gas exactly like a lab waiting on materials.
Logistics: a gas burner's ongoing gas deficit is folded into the
existing queued-building-supply dispatch path (same "needs resource X"
loop production/research orders already use, extended with
gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/
TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy
to the bank, mirroring the extractor pickup path per the ticket. The
existing f5c60f8 priority (queued deliveries outrank collection) holds:
the pickup dispatch loop runs last.
Tests: new tests/test_gas_burner.gd (resource genericity, stall
semantics, research gate, and full delivery+pickup logistics via a
real hub), run_tests transporter/resource regressions, and screenshots
of the build menu (all 7 buildings) and transfer menu (all 3
resources). Full suite: 81/81.
Two real bugs found and fixed along the way, neither gas-burner-
specific:
- _transporter_inbound_to() matched ANY non-idle transporter with a
matching target_id, regardless of purpose. Once pickup states shared
target_id with delivery states (both address a building, not an
extractor), a transporter delivering gas made the SAME building look
"busy" to the unrelated energy-pickup dispatch, starving it even
with a second, genuinely free transporter sitting idle at the hub.
Split into _transporter_inbound_to() (delivery states only) and a
new _transporter_inbound_for_pickup() (pickup states only).
- The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content
sizing) had no room for a 7th building - despite the ticket's own
note that no layout changes should be needed. A naive 4th row ran
off the bottom of a 720x1280 viewport; fitting one meant both adding
a 4th row top AND shrinking the shared button/label/cost sizing so
each row's content no longer taller than the compressed row spacing.
Caught only by actually screenshotting it - a real build menu, not
headless, since --headless renders nothing.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
|
|
|
|
|
|
|
|
const MOTHERSHIP_AT := Vector2.ZERO
|
|
|
|
|
const HUB_AT := Vector2(150.0, 0.0)
|
|
|
|
|
const BURNER_AT := Vector2(400.0, 0.0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _initialize() -> void:
|
|
|
|
|
game_state = root.get_node("GameState")
|
|
|
|
|
game_state.rocks = 0
|
|
|
|
|
game_state.gas = 0
|
|
|
|
|
game_state.buildings.clear()
|
|
|
|
|
game_state.extractors.clear()
|
|
|
|
|
game_state.transporters.clear()
|
|
|
|
|
game_state.reset_progression()
|
|
|
|
|
|
|
|
|
|
mothership_id = game_state.add_building(GameState.BUILDING_MOTHERSHIP, MOTHERSHIP_AT)
|
|
|
|
|
burner_id = game_state.add_building(GameState.BUILDING_GAS_BURNER, BURNER_AT)
|
|
|
|
|
game_state.deposit_resource_to_building(burner_id, GameState.RESOURCE_GAS, 20)
|
2026-08-16 21:38:07 +02:00
|
|
|
var logistics: Resource = game_state.building_logistics_profile(game_state.find_building(burner_id))
|
|
|
|
|
conversion_rate = logistics.conversion_rate
|
|
|
|
|
conversion_yield = logistics.conversion_yield
|
2026-09-03 00:12:08 +02:00
|
|
|
if not is_equal_approx(conversion_rate, 0.2):
|
|
|
|
|
_fail("burner conversion rate is %.2f/s, expected the reduced 0.20/s" % conversion_rate)
|
Gas burner building and the energy resource (#54)
A new building that consumes gas to produce energy, a new resource
stored and moved exactly like ore and gas.
The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own
warm yellow-green ResourceDefinition, registered in
ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY.
Inventory/ResourceBar/ResourceTransferList needed no changes - #49
already made them resource-agnostic, confirmed structurally in the
test rather than touched.
The building: GasBurnerBuildingVisual (a hexagonal chamber with intake
vents in gas's colour and output ports in energy's, so the silhouette
itself reads "gas in, energy out"), GasBurnerBuildingDefinition
(capabilities=["gas_burner"], its own build-menu icon appended to
IconButton.Icon rather than inserted, per the ticket's own warning
about renumbering stored scene values), and the matching
UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new
"Power Systems" skill-tree node, mirroring how "freight" unlocks the
transport hub.
Conversion: _advance_gas_burners(), simulated in GameState alongside
_advance_production/extractor mining so it keeps running while the
player is elsewhere. Withdraws gas and deposits energy in the
building's OWN inventory only - never the bank - so it stalls with no
local gas exactly like a lab waiting on materials.
Logistics: a gas burner's ongoing gas deficit is folded into the
existing queued-building-supply dispatch path (same "needs resource X"
loop production/research orders already use, extended with
gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/
TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy
to the bank, mirroring the extractor pickup path per the ticket. The
existing f5c60f8 priority (queued deliveries outrank collection) holds:
the pickup dispatch loop runs last.
Tests: new tests/test_gas_burner.gd (resource genericity, stall
semantics, research gate, and full delivery+pickup logistics via a
real hub), run_tests transporter/resource regressions, and screenshots
of the build menu (all 7 buildings) and transfer menu (all 3
resources). Full suite: 81/81.
Two real bugs found and fixed along the way, neither gas-burner-
specific:
- _transporter_inbound_to() matched ANY non-idle transporter with a
matching target_id, regardless of purpose. Once pickup states shared
target_id with delivery states (both address a building, not an
extractor), a transporter delivering gas made the SAME building look
"busy" to the unrelated energy-pickup dispatch, starving it even
with a second, genuinely free transporter sitting idle at the hub.
Split into _transporter_inbound_to() (delivery states only) and a
new _transporter_inbound_for_pickup() (pickup states only).
- The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content
sizing) had no room for a 7th building - despite the ticket's own
note that no layout changes should be needed. A naive 4th row ran
off the bottom of a 720x1280 viewport; fitting one meant both adding
a 4th row top AND shrinking the shared button/label/cost sizing so
each row's content no longer taller than the compressed row spacing.
Caught only by actually screenshotting it - a real build menu, not
headless, since --headless renders nothing.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func _process(delta: float) -> bool:
|
|
|
|
|
elapsed += delta
|
|
|
|
|
match stage:
|
|
|
|
|
0:
|
|
|
|
|
# --- A. energy is fully generic -------------------------------
|
|
|
|
|
if not game_state.resource_types().has(GameState.RESOURCE_ENERGY):
|
|
|
|
|
return _fail("energy is not in resource_types() - the HUD/transfer list would never show it")
|
|
|
|
|
var definition: Resource = game_state.resource_definition(GameState.RESOURCE_ENERGY)
|
|
|
|
|
if definition == null or definition.glyph_scene == null:
|
|
|
|
|
return _fail("energy has no ResourceDefinition or glyph_scene")
|
|
|
|
|
var energy_color: Color = game_state.resource_color(GameState.RESOURCE_ENERGY)
|
|
|
|
|
if energy_color == game_state.resource_color(GameState.RESOURCE_ORE) \
|
|
|
|
|
or energy_color == game_state.resource_color(GameState.RESOURCE_GAS):
|
|
|
|
|
return _fail("energy shares a colour with ore or gas")
|
|
|
|
|
print("energy is generic: in resource_types(), own definition, own colour %s" % energy_color)
|
|
|
|
|
|
|
|
|
|
# --- B. produces energy from local gas at the configured rate -
|
2026-09-03 00:12:08 +02:00
|
|
|
if elapsed < 5.5:
|
Gas burner building and the energy resource (#54)
A new building that consumes gas to produce energy, a new resource
stored and moved exactly like ore and gas.
The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own
warm yellow-green ResourceDefinition, registered in
ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY.
Inventory/ResourceBar/ResourceTransferList needed no changes - #49
already made them resource-agnostic, confirmed structurally in the
test rather than touched.
The building: GasBurnerBuildingVisual (a hexagonal chamber with intake
vents in gas's colour and output ports in energy's, so the silhouette
itself reads "gas in, energy out"), GasBurnerBuildingDefinition
(capabilities=["gas_burner"], its own build-menu icon appended to
IconButton.Icon rather than inserted, per the ticket's own warning
about renumbering stored scene values), and the matching
UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new
"Power Systems" skill-tree node, mirroring how "freight" unlocks the
transport hub.
Conversion: _advance_gas_burners(), simulated in GameState alongside
_advance_production/extractor mining so it keeps running while the
player is elsewhere. Withdraws gas and deposits energy in the
building's OWN inventory only - never the bank - so it stalls with no
local gas exactly like a lab waiting on materials.
Logistics: a gas burner's ongoing gas deficit is folded into the
existing queued-building-supply dispatch path (same "needs resource X"
loop production/research orders already use, extended with
gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/
TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy
to the bank, mirroring the extractor pickup path per the ticket. The
existing f5c60f8 priority (queued deliveries outrank collection) holds:
the pickup dispatch loop runs last.
Tests: new tests/test_gas_burner.gd (resource genericity, stall
semantics, research gate, and full delivery+pickup logistics via a
real hub), run_tests transporter/resource regressions, and screenshots
of the build menu (all 7 buildings) and transfer menu (all 3
resources). Full suite: 81/81.
Two real bugs found and fixed along the way, neither gas-burner-
specific:
- _transporter_inbound_to() matched ANY non-idle transporter with a
matching target_id, regardless of purpose. Once pickup states shared
target_id with delivery states (both address a building, not an
extractor), a transporter delivering gas made the SAME building look
"busy" to the unrelated energy-pickup dispatch, starving it even
with a second, genuinely free transporter sitting idle at the hub.
Split into _transporter_inbound_to() (delivery states only) and a
new _transporter_inbound_for_pickup() (pickup states only).
- The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content
sizing) had no room for a 7th building - despite the ticket's own
note that no layout changes should be needed. A naive 4th row ran
off the bottom of a 720x1280 viewport; fitting one meant both adding
a 4th row top AND shrinking the shared button/label/cost sizing so
each row's content no longer taller than the compressed row spacing.
Caught only by actually screenshotting it - a real build menu, not
headless, since --headless renders nothing.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
|
|
|
return false
|
|
|
|
|
var gas_left: int = game_state.building_resource(burner_id, GameState.RESOURCE_GAS)
|
|
|
|
|
var energy_made: int = game_state.building_resource(burner_id, GameState.RESOURCE_ENERGY)
|
|
|
|
|
var gas_burned: int = 20 - gas_left
|
2026-09-03 00:12:08 +02:00
|
|
|
if gas_burned < 1:
|
|
|
|
|
return _fail("burner burned no gas in 5.5s at rate %.2f/s" % conversion_rate)
|
2026-08-16 21:38:07 +02:00
|
|
|
if energy_made != gas_burned * conversion_yield:
|
Gas burner building and the energy resource (#54)
A new building that consumes gas to produce energy, a new resource
stored and moved exactly like ore and gas.
The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own
warm yellow-green ResourceDefinition, registered in
ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY.
Inventory/ResourceBar/ResourceTransferList needed no changes - #49
already made them resource-agnostic, confirmed structurally in the
test rather than touched.
The building: GasBurnerBuildingVisual (a hexagonal chamber with intake
vents in gas's colour and output ports in energy's, so the silhouette
itself reads "gas in, energy out"), GasBurnerBuildingDefinition
(capabilities=["gas_burner"], its own build-menu icon appended to
IconButton.Icon rather than inserted, per the ticket's own warning
about renumbering stored scene values), and the matching
UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new
"Power Systems" skill-tree node, mirroring how "freight" unlocks the
transport hub.
Conversion: _advance_gas_burners(), simulated in GameState alongside
_advance_production/extractor mining so it keeps running while the
player is elsewhere. Withdraws gas and deposits energy in the
building's OWN inventory only - never the bank - so it stalls with no
local gas exactly like a lab waiting on materials.
Logistics: a gas burner's ongoing gas deficit is folded into the
existing queued-building-supply dispatch path (same "needs resource X"
loop production/research orders already use, extended with
gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/
TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy
to the bank, mirroring the extractor pickup path per the ticket. The
existing f5c60f8 priority (queued deliveries outrank collection) holds:
the pickup dispatch loop runs last.
Tests: new tests/test_gas_burner.gd (resource genericity, stall
semantics, research gate, and full delivery+pickup logistics via a
real hub), run_tests transporter/resource regressions, and screenshots
of the build menu (all 7 buildings) and transfer menu (all 3
resources). Full suite: 81/81.
Two real bugs found and fixed along the way, neither gas-burner-
specific:
- _transporter_inbound_to() matched ANY non-idle transporter with a
matching target_id, regardless of purpose. Once pickup states shared
target_id with delivery states (both address a building, not an
extractor), a transporter delivering gas made the SAME building look
"busy" to the unrelated energy-pickup dispatch, starving it even
with a second, genuinely free transporter sitting idle at the hub.
Split into _transporter_inbound_to() (delivery states only) and a
new _transporter_inbound_for_pickup() (pickup states only).
- The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content
sizing) had no room for a 7th building - despite the ticket's own
note that no layout changes should be needed. A naive 4th row ran
off the bottom of a 720x1280 viewport; fitting one meant both adding
a 4th row top AND shrinking the shared button/label/cost sizing so
each row's content no longer taller than the compressed row spacing.
Caught only by actually screenshotting it - a real build menu, not
headless, since --headless renders nothing.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
|
|
|
return _fail("burner made %d energy for %d gas burned, expected %dx" % [
|
2026-08-16 21:38:07 +02:00
|
|
|
energy_made, gas_burned, conversion_yield
|
Gas burner building and the energy resource (#54)
A new building that consumes gas to produce energy, a new resource
stored and moved exactly like ore and gas.
The resource: EnergyResourceGlyph (a cell/bolt mark) + energy's own
warm yellow-green ResourceDefinition, registered in
ResourceDefinitions.ORDER/DEFINITIONS and GameState.RESOURCE_ENERGY.
Inventory/ResourceBar/ResourceTransferList needed no changes - #49
already made them resource-agnostic, confirmed structurally in the
test rather than touched.
The building: GasBurnerBuildingVisual (a hexagonal chamber with intake
vents in gas's colour and output ports in energy's, so the silhouette
itself reads "gas in, energy out"), GasBurnerBuildingDefinition
(capabilities=["gas_burner"], its own build-menu icon appended to
IconButton.Icon rather than inserted, per the ticket's own warning
about renumbering stored scene values), and the matching
UI/BuildMenu/GasBurner* nodes in Main.tscn. Gated behind a new
"Power Systems" skill-tree node, mirroring how "freight" unlocks the
transport hub.
Conversion: _advance_gas_burners(), simulated in GameState alongside
_advance_production/extractor mining so it keeps running while the
player is elsewhere. Withdraws gas and deposits energy in the
building's OWN inventory only - never the bank - so it stalls with no
local gas exactly like a lab waiting on materials.
Logistics: a gas burner's ongoing gas deficit is folded into the
existing queued-building-supply dispatch path (same "needs resource X"
loop production/research orders already use, extended with
gas_burner_gas_deficit()), and a new TO_BUILDING_PICKUP/
TO_MOTHERSHIP_FROM_BUILDING transporter state pair collects its energy
to the bank, mirroring the extractor pickup path per the ticket. The
existing f5c60f8 priority (queued deliveries outrank collection) holds:
the pickup dispatch loop runs last.
Tests: new tests/test_gas_burner.gd (resource genericity, stall
semantics, research gate, and full delivery+pickup logistics via a
real hub), run_tests transporter/resource regressions, and screenshots
of the build menu (all 7 buildings) and transfer menu (all 3
resources). Full suite: 81/81.
Two real bugs found and fixed along the way, neither gas-burner-
specific:
- _transporter_inbound_to() matched ANY non-idle transporter with a
matching target_id, regardless of purpose. Once pickup states shared
target_id with delivery states (both address a building, not an
extractor), a transporter delivering gas made the SAME building look
"busy" to the unrelated energy-pickup dispatch, starving it even
with a second, genuinely free transporter sitting idle at the hub.
Split into _transporter_inbound_to() (delivery states only) and a
new _transporter_inbound_for_pickup() (pickup states only).
- The build menu's 3-row/6-slot layout (MENU_ROW_TOPS + row content
sizing) had no room for a 7th building - despite the ticket's own
note that no layout changes should be needed. A naive 4th row ran
off the bottom of a 720x1280 viewport; fitting one meant both adding
a 4th row top AND shrinking the shared button/label/cost sizing so
each row's content no longer taller than the compressed row spacing.
Caught only by actually screenshotting it - a real build menu, not
headless, since --headless renders nothing.
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 12:10:31 +02:00
|
|
|
])
|
|
|
|
|
if game_state.rocks != 0 or game_state.gas != 0:
|
|
|
|
|
return _fail("conversion touched the bank (rocks=%d gas=%d) - it must only use local stock" % [
|
|
|
|
|
game_state.rocks, game_state.gas
|
|
|
|
|
])
|
|
|
|
|
print("burner converted %d gas -> %d energy locally, bank untouched" % [gas_burned, energy_made])
|
|
|
|
|
|
|
|
|
|
# --- stall with no gas -----------------------------------------
|
|
|
|
|
var burner_inventory: RefCounted = game_state.building_inventory(burner_id)
|
|
|
|
|
burner_inventory.withdraw(GameState.RESOURCE_GAS, burner_inventory.amount(GameState.RESOURCE_GAS))
|
|
|
|
|
energy_before_stall = game_state.building_resource(burner_id, GameState.RESOURCE_ENERGY)
|
|
|
|
|
elapsed = 0.0
|
|
|
|
|
stage = 1
|
|
|
|
|
return false
|
|
|
|
|
1:
|
|
|
|
|
if elapsed < 1.5:
|
|
|
|
|
return false
|
|
|
|
|
var energy_now: int = game_state.building_resource(burner_id, GameState.RESOURCE_ENERGY)
|
|
|
|
|
if energy_now != energy_before_stall:
|
|
|
|
|
return _fail("burner made energy with no local gas (energy %d -> %d) - it must stall" % [
|
|
|
|
|
energy_before_stall, energy_now
|
|
|
|
|
])
|
|
|
|
|
print("stalled with no gas: energy held at %d" % energy_now)
|
|
|
|
|
|
|
|
|
|
# --- C. gated behind research -----------------------------------
|
|
|
|
|
if game_state.is_building_unlocked(GameState.BUILDING_GAS_BURNER):
|
|
|
|
|
return _fail("gas_burner is buildable with no research at all")
|
|
|
|
|
var gate: String = game_state.research_for_building(GameState.BUILDING_GAS_BURNER)
|
|
|
|
|
if gate == "":
|
|
|
|
|
return _fail("no research node gates gas_burner")
|
|
|
|
|
game_state.unlocked = ["shipyards", "logistics", "freight", "power_systems"]
|
|
|
|
|
if not game_state.is_building_unlocked(GameState.BUILDING_GAS_BURNER):
|
|
|
|
|
return _fail("still locked after researching '%s'" % gate)
|
|
|
|
|
print("locked behind research '%s', unlockable" % gate)
|
|
|
|
|
|
|
|
|
|
# --- D. logistics: reset for a fresh delivery/pickup test -----
|
|
|
|
|
game_state.buildings.clear()
|
|
|
|
|
game_state.transporters.clear()
|
|
|
|
|
game_state.gas = 200
|
|
|
|
|
mothership_id = game_state.add_building(GameState.BUILDING_MOTHERSHIP, MOTHERSHIP_AT)
|
|
|
|
|
hub_id = game_state.add_building(GameState.BUILDING_TRANSPORT_HUB, HUB_AT)
|
|
|
|
|
burner_id = game_state.add_building(GameState.BUILDING_GAS_BURNER, BURNER_AT)
|
|
|
|
|
if game_state.transporters.size() != game_state.hub_capacity():
|
|
|
|
|
return _fail("hub did not provision its transporters")
|
|
|
|
|
load_limit = game_state.transporter_load_limit()
|
|
|
|
|
elapsed = 0.0
|
|
|
|
|
stage = 2
|
|
|
|
|
return false
|
|
|
|
|
2:
|
|
|
|
|
# --- a transporter delivers gas to the burner ------------------
|
|
|
|
|
if game_state.building_resource(burner_id, GameState.RESOURCE_GAS) > 0:
|
|
|
|
|
print("transporter delivered gas to the burner: %d" % [
|
|
|
|
|
game_state.building_resource(burner_id, GameState.RESOURCE_GAS)
|
|
|
|
|
])
|
|
|
|
|
# Force the burner's local energy up to a full load so pickup
|
|
|
|
|
# dispatch fires immediately, rather than waiting out the
|
|
|
|
|
# genuinely slow conversion rate for a second, separate check.
|
|
|
|
|
game_state.building_inventory(burner_id).set_amount(GameState.RESOURCE_ENERGY, load_limit)
|
|
|
|
|
elapsed = 0.0
|
|
|
|
|
stage = 3
|
|
|
|
|
return false
|
|
|
|
|
if elapsed > 10.0:
|
|
|
|
|
return _fail("no gas was ever delivered to the burner")
|
|
|
|
|
return false
|
|
|
|
|
3:
|
|
|
|
|
# --- a transporter collects the burner's energy to the bank ---
|
|
|
|
|
if game_state.banked_resource(GameState.RESOURCE_ENERGY) >= load_limit:
|
|
|
|
|
print("transporter collected %d energy to the bank" % game_state.banked_resource(GameState.RESOURCE_ENERGY))
|
|
|
|
|
print("TEST_GAS_BURNER: PASS")
|
|
|
|
|
quit(0)
|
|
|
|
|
return true
|
|
|
|
|
if elapsed > 10.0:
|
|
|
|
|
return _fail("burner's energy was never collected (bank=%d burner=%d)" % [
|
|
|
|
|
game_state.banked_resource(GameState.RESOURCE_ENERGY),
|
|
|
|
|
game_state.building_resource(burner_id, GameState.RESOURCE_ENERGY),
|
|
|
|
|
])
|
|
|
|
|
return false
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _fail(message: String) -> bool:
|
|
|
|
|
print("TEST_GAS_BURNER: FAIL (%s)" % message)
|
|
|
|
|
quit(1)
|
|
|
|
|
return true
|