Write the v2 production tree into the config files
recipes.toml: full v2 rewrite - iron/copper/quartz mining, smelting incl. the value-losing scrap sink, reprocessing (4 scrap / 4 s, voidsteel at 20% of the full pool), tiered intermediates, hulls, module prefabs, and the three drop-only shortcut recipes. modules.toml: lasers renamed to railguns (implementation unchanged), prefab materials and numbers-pass production times; combat stats stay placeholders for the arena pass. ships.toml: hull-item materials, numbers-pass base production times, and geometry-validated default_modules loadouts for every ship (waves now spawn armed). visuals.toml: item entries for the new palette (quartz, silicon, copper_coil, control_chip, capacitor_bank, hardened_steel, ceramic_plate, voidsteel, voidsteel_plate, railgun modules); retired titanium/alloy/laser items removed. world.toml: scrap_per_threat = 0.25 per the numbers pass. threat_report.py: commit an item's threat only once every eligible recipe is computable - the previous first-resolved-wins behavior let shortcut recipes underprice items (same flaw exists in ThreatCostCalculator, recorded as action item 9). Verified: all default_modules placements valid, verify_recipes and verify_layouts pass, and the report reproduces the numbers-pass tables exactly (fitted: 10.5/47/99/233.5/354.5/722.5/1491.5/1436.5). Doc tables updated for the three geometry-corrected loadouts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DyCu8vwChKMbLJQ3xosYEN
This commit is contained in:
@@ -1,26 +1,29 @@
|
|||||||
# modules.toml
|
# modules.toml
|
||||||
#
|
#
|
||||||
# First real-content iteration: module ids and surface masks are the designed
|
# Production tree v2: all weapons are railguns for now — the implementation
|
||||||
# content; stats, materials, and threat costs are placeholders until the
|
# (instant damage, no projectile, no ammunition) stays as-is and the beam
|
||||||
# recipe and balancing passes.
|
# visual reads as a tracer round. Lasers are reserved for a future distinct
|
||||||
|
# weapon type (see docs/content_design.md, "Production tree v2 — Weapons").
|
||||||
|
# Combat stats are placeholders until the arena balancing pass;
|
||||||
|
# production_time_seconds values come from the numbers pass.
|
||||||
#
|
#
|
||||||
# Unlock progression is mostly disabled (unlock_at_station_level = -1) pending
|
# Unlock progression is mostly disabled (unlock_at_station_level = -1) pending
|
||||||
# the balancing pass. The laser cannons are the exception: laser_cannon_m is
|
# the pacing pass. The railguns are the exception: railgun_m is gated to
|
||||||
# gated to station level 1, and laser_cannon_l requires laser_cannon_m to be
|
# station level 1, and railgun_l requires railgun_m to be unlocked first
|
||||||
# unlocked first (unlock_requires) — a demonstration of the prerequisite chain.
|
# (unlock_requires) — a demonstration of the prerequisite chain.
|
||||||
#
|
#
|
||||||
# Surface mask footprint ladder — footprints gate which hulls can mount a
|
# Surface mask footprint ladder — footprints gate which hulls can mount a
|
||||||
# module, purely through geometry (see ships.toml for the matching hull
|
# module, purely through geometry (see ships.toml for the matching hull
|
||||||
# grids):
|
# grids):
|
||||||
#
|
#
|
||||||
# 1x1 laser_cannon_s, salvager, repair_tool fits every hull, incl. drones
|
# 1x1 railgun_s, salvager, repair_tool fits every hull, incl. drones
|
||||||
# 1x2 maneuvering_thrusters, sensor_booster,
|
# 1x2 maneuvering_thrusters, sensor_booster,
|
||||||
# armor_plates frigate and up
|
# armor_plates frigate and up
|
||||||
# 1x3 afterburner frigate and up (eats most of a frigate)
|
# 1x3 afterburner frigate and up (eats most of a frigate)
|
||||||
# L-shape weapon_stabilizer, weapon_primer,
|
# L-shape weapon_stabilizer, weapon_primer,
|
||||||
# weapon_upgrade frigate and up
|
# weapon_upgrade frigate and up
|
||||||
# 2x2 laser_cannon_m, drone_bay cruiser and up (no 2x2 area on s hulls)
|
# 2x2 railgun_m, drone_bay cruiser and up (no 2x2 area on s hulls)
|
||||||
# 3x3 laser_cannon_l battleship and up (no 3x3 area on m hulls)
|
# 3x3 railgun_l battleship and up (no 3x3 area on m hulls)
|
||||||
# 2x6 drone_hangar carrier only
|
# 2x6 drone_hangar carrier only
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@@ -28,13 +31,13 @@
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[[module]]
|
[[module]]
|
||||||
id = "laser_cannon_s"
|
id = "railgun_s"
|
||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
surface_mask = ["O"]
|
surface_mask = ["O"]
|
||||||
materials = [{item = "laser_cannon_s_module", amount = 1}]
|
materials = [{item = "railgun_s_module", amount = 1}]
|
||||||
production_time_seconds = 0.5
|
production_time_seconds = 1
|
||||||
fill_color = "#FF8040"
|
fill_color = "#FF8040"
|
||||||
glyph = "Ls"
|
glyph = "Rs"
|
||||||
|
|
||||||
[module.weapon]
|
[module.weapon]
|
||||||
damage = 2
|
damage = 2
|
||||||
@@ -43,15 +46,15 @@ attack_rate_hz = 2.0
|
|||||||
|
|
||||||
|
|
||||||
[[module]]
|
[[module]]
|
||||||
id = "laser_cannon_m"
|
id = "railgun_m"
|
||||||
unlock_at_station_level = 1
|
unlock_at_station_level = 1
|
||||||
surface_mask = [
|
surface_mask = [
|
||||||
"OO",
|
"OO",
|
||||||
"OO"]
|
"OO"]
|
||||||
materials = [{item = "laser_cannon_m_module", amount = 1}]
|
materials = [{item = "railgun_m_module", amount = 1}]
|
||||||
production_time_seconds = 2
|
production_time_seconds = 3
|
||||||
fill_color = "#FF8040"
|
fill_color = "#FF8040"
|
||||||
glyph = "Lm"
|
glyph = "Rm"
|
||||||
|
|
||||||
[module.weapon]
|
[module.weapon]
|
||||||
damage = 10
|
damage = 10
|
||||||
@@ -60,17 +63,17 @@ attack_rate_hz = 1.5
|
|||||||
|
|
||||||
|
|
||||||
[[module]]
|
[[module]]
|
||||||
id = "laser_cannon_l"
|
id = "railgun_l"
|
||||||
unlock_at_station_level = 1
|
unlock_at_station_level = 1
|
||||||
unlock_requires = ["laser_cannon_m"]
|
unlock_requires = ["railgun_m"]
|
||||||
surface_mask = [
|
surface_mask = [
|
||||||
"OOO",
|
"OOO",
|
||||||
"OOO",
|
"OOO",
|
||||||
"OOO"]
|
"OOO"]
|
||||||
materials = [{item = "laser_cannon_l_module", amount = 1}]
|
materials = [{item = "railgun_l_module", amount = 1}]
|
||||||
production_time_seconds = 8
|
production_time_seconds = 4
|
||||||
fill_color = "#FF8040"
|
fill_color = "#FF8040"
|
||||||
glyph = "Ll"
|
glyph = "Rl"
|
||||||
|
|
||||||
[module.weapon]
|
[module.weapon]
|
||||||
damage = 40
|
damage = 40
|
||||||
@@ -86,7 +89,7 @@ id = "salvager"
|
|||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
surface_mask = ["O"]
|
surface_mask = ["O"]
|
||||||
materials = [{item = "salvager_module", amount = 1}]
|
materials = [{item = "salvager_module", amount = 1}]
|
||||||
production_time_seconds = 2
|
production_time_seconds = 1
|
||||||
fill_color = "#AACC44"
|
fill_color = "#AACC44"
|
||||||
glyph = "Sv"
|
glyph = "Sv"
|
||||||
|
|
||||||
@@ -101,7 +104,7 @@ id = "repair_tool"
|
|||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
surface_mask = ["O"]
|
surface_mask = ["O"]
|
||||||
materials = [{item = "repair_tool_module", amount = 1}]
|
materials = [{item = "repair_tool_module", amount = 1}]
|
||||||
production_time_seconds = 2
|
production_time_seconds = 1
|
||||||
fill_color = "#66CCFF"
|
fill_color = "#66CCFF"
|
||||||
glyph = "Rp"
|
glyph = "Rp"
|
||||||
|
|
||||||
@@ -119,7 +122,7 @@ id = "afterburner"
|
|||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
surface_mask = ["OOO"]
|
surface_mask = ["OOO"]
|
||||||
materials = [{item = "afterburner_module", amount = 1}]
|
materials = [{item = "afterburner_module", amount = 1}]
|
||||||
production_time_seconds = 2
|
production_time_seconds = 1
|
||||||
fill_color = "#40A0FF"
|
fill_color = "#40A0FF"
|
||||||
glyph = "Ab"
|
glyph = "Ab"
|
||||||
|
|
||||||
@@ -133,7 +136,7 @@ id = "maneuvering_thrusters"
|
|||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
surface_mask = ["OO"]
|
surface_mask = ["OO"]
|
||||||
materials = [{item = "maneuvering_thrusters_module", amount = 1}]
|
materials = [{item = "maneuvering_thrusters_module", amount = 1}]
|
||||||
production_time_seconds = 2
|
production_time_seconds = 1
|
||||||
fill_color = "#40A0FF"
|
fill_color = "#40A0FF"
|
||||||
glyph = "Mt"
|
glyph = "Mt"
|
||||||
|
|
||||||
@@ -150,7 +153,7 @@ id = "armor_plates"
|
|||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
surface_mask = ["OO"]
|
surface_mask = ["OO"]
|
||||||
materials = [{item = "armor_plates_module", amount = 1}]
|
materials = [{item = "armor_plates_module", amount = 1}]
|
||||||
production_time_seconds = 3
|
production_time_seconds = 1
|
||||||
fill_color = "#808080"
|
fill_color = "#808080"
|
||||||
glyph = "A"
|
glyph = "A"
|
||||||
|
|
||||||
@@ -163,7 +166,7 @@ id = "sensor_booster"
|
|||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
surface_mask = ["OO"]
|
surface_mask = ["OO"]
|
||||||
materials = [{item = "sensor_booster_module", amount = 1}]
|
materials = [{item = "sensor_booster_module", amount = 1}]
|
||||||
production_time_seconds = 2
|
production_time_seconds = 1
|
||||||
fill_color = "#40A0FF"
|
fill_color = "#40A0FF"
|
||||||
glyph = "S"
|
glyph = "S"
|
||||||
|
|
||||||
@@ -182,7 +185,7 @@ surface_mask = [
|
|||||||
"OX",
|
"OX",
|
||||||
]
|
]
|
||||||
materials = [{item = "weapon_upgrade_module", amount = 1}]
|
materials = [{item = "weapon_upgrade_module", amount = 1}]
|
||||||
production_time_seconds = 4
|
production_time_seconds = 2
|
||||||
fill_color = "#FF4040"
|
fill_color = "#FF4040"
|
||||||
glyph = "Wu"
|
glyph = "Wu"
|
||||||
|
|
||||||
@@ -198,7 +201,7 @@ surface_mask = [
|
|||||||
"OX",
|
"OX",
|
||||||
]
|
]
|
||||||
materials = [{item = "weapon_primer_module", amount = 1}]
|
materials = [{item = "weapon_primer_module", amount = 1}]
|
||||||
production_time_seconds = 4
|
production_time_seconds = 2
|
||||||
fill_color = "#FF4040"
|
fill_color = "#FF4040"
|
||||||
glyph = "Wp"
|
glyph = "Wp"
|
||||||
|
|
||||||
@@ -214,7 +217,7 @@ surface_mask = [
|
|||||||
"OX",
|
"OX",
|
||||||
]
|
]
|
||||||
materials = [{item = "weapon_stabilizer_module", amount = 1}]
|
materials = [{item = "weapon_stabilizer_module", amount = 1}]
|
||||||
production_time_seconds = 4
|
production_time_seconds = 1
|
||||||
fill_color = "#FF4040"
|
fill_color = "#FF4040"
|
||||||
glyph = "Ws"
|
glyph = "Ws"
|
||||||
|
|
||||||
@@ -236,7 +239,7 @@ surface_mask = [
|
|||||||
"OO",
|
"OO",
|
||||||
"OO"]
|
"OO"]
|
||||||
materials = [{item = "drone_bay_module", amount = 1}]
|
materials = [{item = "drone_bay_module", amount = 1}]
|
||||||
production_time_seconds = 5
|
production_time_seconds = 3
|
||||||
fill_color = "#CC66FF"
|
fill_color = "#CC66FF"
|
||||||
glyph = "Db"
|
glyph = "Db"
|
||||||
|
|
||||||
@@ -248,6 +251,6 @@ surface_mask = [
|
|||||||
"OOOOOO",
|
"OOOOOO",
|
||||||
"OOOOOO"]
|
"OOOOOO"]
|
||||||
materials = [{item = "drone_hangar_module", amount = 1}]
|
materials = [{item = "drone_hangar_module", amount = 1}]
|
||||||
production_time_seconds = 20
|
production_time_seconds = 6
|
||||||
fill_color = "#9933CC"
|
fill_color = "#9933CC"
|
||||||
glyph = "Dh"
|
glyph = "Dh"
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
# recipes.toml
|
# recipes.toml
|
||||||
#
|
#
|
||||||
# First real-content iteration of the production tree. Quantities and
|
# Production tree v2 (see docs/content_design.md, "Production tree v2" and
|
||||||
# durations are a first guess; the balancing pass will tune them and assign
|
# "Numbers — first pass"). Quantities and durations are tuned so that every
|
||||||
# real unlock_at_station_level values. Almost everything is unlocked for now so
|
# fitted ship lands on the threat-cost ladder and the ratio curve is
|
||||||
# the full tree is testable; the only gated recipe schematics are the medium and
|
# realized: tier 1 ratios are 1:1, tier 2 ratios are 2:3, tier 3+ ratios
|
||||||
# large laser-cannon item recipes, which demonstrate the unlock_requires
|
# are deliberately strange.
|
||||||
# prerequisite chain (large requires medium — see modules.toml / ships.toml).
|
|
||||||
#
|
#
|
||||||
# Input chain per game phase — each phase adds exactly one new base input:
|
# Input chain per game phase — each phase transition adds exactly one new
|
||||||
|
# base input:
|
||||||
#
|
#
|
||||||
# early iron_ore + copper_ore -> ingots -> copper_wire, steel_plate,
|
# early iron_ore + copper_ore minable on every asteroid tile (the
|
||||||
# circuit_board
|
# asteroid is an M-type body — its bulk
|
||||||
# mid + titanium_ore -> titanium_frame; assembler-made
|
# rock IS ore)
|
||||||
# mechanical_parts, targeting_unit,
|
# mid + quartz geode deposits in expansion territory
|
||||||
# drive_unit
|
# (deposit gating pending — see action
|
||||||
# late + advanced_alloy -> reinforced_plating, capital_core.
|
# item 5 in docs/progression_design.md;
|
||||||
# advanced_alloy CANNOT be mined; it only
|
# until then quartz mines anywhere)
|
||||||
# comes from reprocessing salvaged scrap,
|
# late + voidsteel battle-forged: ONLY from reprocessing
|
||||||
# so capital production requires combat.
|
# salvaged scrap, so capital production
|
||||||
|
# requires combat
|
||||||
#
|
#
|
||||||
# Run tools/verify_recipes.py after editing to check that every consumed
|
# Run tools/verify_recipes.py and tools/threat_report.py after editing.
|
||||||
# item has a producer and every item has a visuals.toml entry.
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Mining (tier 0)
|
# Mining (tier 0)
|
||||||
@@ -38,405 +38,406 @@ id = "mine_copper_ore"
|
|||||||
building = "miner"
|
building = "miner"
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = [{item = "copper_ore", amount = 1}]
|
outputs = [{item = "copper_ore", amount = 1}]
|
||||||
duration_seconds = 1.5
|
duration_seconds = 1.0
|
||||||
|
|
||||||
# Titanium is the midgame ore: mined three times slower than iron.
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "mine_titanium_ore"
|
id = "mine_quartz"
|
||||||
building = "miner"
|
building = "miner"
|
||||||
inputs = []
|
inputs = []
|
||||||
outputs = [{item = "titanium_ore", amount = 1}]
|
outputs = [{item = "quartz", amount = 1}]
|
||||||
duration_seconds = 3.0
|
duration_seconds = 2.0
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Smelting (tier 1)
|
# Smelting (tier 1) — one recipe per input item; ratios are 1:1 with miners.
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "iron_ingot"
|
id = "iron_ingot"
|
||||||
building = "smelter"
|
building = "smelter"
|
||||||
inputs = [{item = "iron_ore", amount = 2}]
|
inputs = [{item = "iron_ore", amount = 1}]
|
||||||
outputs = [{item = "iron_ingot", amount = 1}]
|
outputs = [{item = "iron_ingot", amount = 1}]
|
||||||
duration_seconds = 2.0
|
duration_seconds = 1.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "copper_ingot"
|
id = "copper_ingot"
|
||||||
building = "smelter"
|
building = "smelter"
|
||||||
inputs = [{item = "copper_ore", amount = 2}]
|
inputs = [{item = "copper_ore", amount = 1}]
|
||||||
outputs = [{item = "copper_ingot", amount = 1}]
|
outputs = [{item = "copper_ingot", amount = 1}]
|
||||||
duration_seconds = 2.5
|
duration_seconds = 1.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "titanium_ingot"
|
id = "silicon"
|
||||||
building = "smelter"
|
building = "smelter"
|
||||||
inputs = [{item = "titanium_ore", amount = 3}]
|
inputs = [{item = "quartz", amount = 1}]
|
||||||
outputs = [{item = "titanium_ingot", amount = 1}]
|
outputs = [{item = "silicon", amount = 1}]
|
||||||
duration_seconds = 4.0
|
duration_seconds = 2.0
|
||||||
|
|
||||||
|
# Scrap smelting: the safe, boring sink. Deliberately value-losing (4 threat
|
||||||
|
# of scrap becomes a 2-threat ingot) — reprocessing is the value-preserving
|
||||||
|
# path.
|
||||||
|
[[recipe]]
|
||||||
|
id = "scrap_smelting"
|
||||||
|
building = "smelter"
|
||||||
|
inputs = [{item = "scrap", amount = 1}]
|
||||||
|
outputs = [{item = "iron_ingot", amount = 1}]
|
||||||
|
duration_seconds = 1.0
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Reprocessing
|
# Reprocessing — the only source of voidsteel (battle-forged; formed when
|
||||||
#
|
# weapon plasma anneals hull metal in the violence of ship destruction).
|
||||||
# The only source of advanced_alloy: salvaged scrap from destroyed ships.
|
# Weights are authored for the fully unlocked pool state; the pool
|
||||||
|
# renormalizes over implicitly unlocked items early game.
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "reprocessing_cycle"
|
id = "reprocessing_cycle"
|
||||||
building = "reprocessing_plant"
|
building = "reprocessing_plant"
|
||||||
inputs = [{item = "scrap", amount = 5}]
|
inputs = [{item = "scrap", amount = 4}]
|
||||||
duration_seconds = 3.0
|
duration_seconds = 4.0
|
||||||
|
|
||||||
[[recipe.outputs]]
|
[[recipe.outputs]]
|
||||||
item = "iron_ingot"
|
item = "iron_ingot"
|
||||||
amount = 2
|
amount = 1
|
||||||
probability = 0.45
|
probability = 0.3
|
||||||
|
|
||||||
[[recipe.outputs]]
|
[[recipe.outputs]]
|
||||||
item = "copper_ingot"
|
item = "copper_ingot"
|
||||||
amount = 1
|
amount = 1
|
||||||
probability = 0.25
|
probability = 0.3
|
||||||
|
|
||||||
[[recipe.outputs]]
|
[[recipe.outputs]]
|
||||||
item = "titanium_ingot"
|
item = "silicon"
|
||||||
amount = 1
|
amount = 1
|
||||||
probability = 0.15
|
probability = 0.2
|
||||||
|
|
||||||
[[recipe.outputs]]
|
[[recipe.outputs]]
|
||||||
item = "advanced_alloy"
|
item = "voidsteel"
|
||||||
amount = 1
|
amount = 1
|
||||||
probability = 0.15
|
probability = 0.2
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Basic components (tier 2, early game)
|
# Tier 2 — early intermediates (clean ratios, ~2:3)
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "copper_wire"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "copper_ingot", amount = 1}]
|
|
||||||
outputs = [{item = "copper_wire", amount = 2}]
|
|
||||||
duration_seconds = 1.5
|
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "steel_plate"
|
id = "steel_plate"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [{item = "iron_ingot", amount = 2}]
|
inputs = [{item = "iron_ingot", amount = 2}]
|
||||||
outputs = [{item = "steel_plate", amount = 1}]
|
outputs = [{item = "steel_plate", amount = 1}]
|
||||||
|
duration_seconds = 3.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "copper_wire"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "copper_ingot", amount = 1}]
|
||||||
|
outputs = [{item = "copper_wire", amount = 2}]
|
||||||
|
duration_seconds = 1.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "copper_coil"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "copper_wire", amount = 2}]
|
||||||
|
outputs = [{item = "copper_coil", amount = 1}]
|
||||||
|
duration_seconds = 1.5
|
||||||
|
|
||||||
|
# Depth-3 chain (ore -> ingot -> plate -> block) is the factory's
|
||||||
|
# doubling-time knob; see the block economy rules in progression_design.md.
|
||||||
|
[[recipe]]
|
||||||
|
id = "building_block"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "steel_plate", amount = 2}]
|
||||||
|
outputs = [{item = "building_block", amount = 4}]
|
||||||
|
duration_seconds = 2.0
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Tier 3 — mid intermediates (strange ratios begin; need quartz)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "control_chip"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "silicon", amount = 1}, {item = "copper_wire", amount = 2}]
|
||||||
|
outputs = [{item = "control_chip", amount = 1}]
|
||||||
|
duration_seconds = 5.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "capacitor_bank"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "copper_coil", amount = 2}, {item = "silicon", amount = 1}]
|
||||||
|
outputs = [{item = "capacitor_bank", amount = 1}]
|
||||||
|
duration_seconds = 5.0
|
||||||
|
|
||||||
|
# The quality gate for m+ hulls: a deliberately long-running recipe
|
||||||
|
# (time-heavy archetype).
|
||||||
|
[[recipe]]
|
||||||
|
id = "hardened_steel"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "steel_plate", amount = 3}]
|
||||||
|
outputs = [{item = "hardened_steel", amount = 1}]
|
||||||
|
duration_seconds = 12.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "ceramic_plate"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "quartz", amount = 2}]
|
||||||
|
outputs = [{item = "ceramic_plate", amount = 1}]
|
||||||
|
duration_seconds = 4.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "drive_unit"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [
|
||||||
|
{item = "steel_plate", amount = 2},
|
||||||
|
{item = "copper_coil", amount = 2},
|
||||||
|
{item = "control_chip", amount = 1},
|
||||||
|
]
|
||||||
|
outputs = [{item = "drive_unit", amount = 1}]
|
||||||
|
duration_seconds = 8.0
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Tier 4 — late intermediates (need voidsteel)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "voidsteel_plate"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "voidsteel", amount = 1}, {item = "hardened_steel", amount = 1}]
|
||||||
|
outputs = [{item = "voidsteel_plate", amount = 1}]
|
||||||
|
duration_seconds = 8.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "capital_core"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [
|
||||||
|
{item = "voidsteel", amount = 2},
|
||||||
|
{item = "capacitor_bank", amount = 1},
|
||||||
|
{item = "control_chip", amount = 1},
|
||||||
|
]
|
||||||
|
outputs = [{item = "capital_core", amount = 1}]
|
||||||
|
duration_seconds = 10.0
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Shortcut recipes — drop-only assembler recipe schematics
|
||||||
|
# (unlock_at_station_level >= 0). Pure rewards: item threat stays defined by
|
||||||
|
# the base (expensive) path via the max rule, so shortcuts give real factory
|
||||||
|
# efficiency without shifting any balance.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "shortcut_steel_plate"
|
||||||
|
unlock_at_station_level = 1
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "iron_ore", amount = 3}]
|
||||||
|
outputs = [{item = "steel_plate", amount = 1}]
|
||||||
duration_seconds = 2.0
|
duration_seconds = 2.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "circuit_board"
|
id = "shortcut_control_chip"
|
||||||
unlock_at_station_level = -1
|
unlock_at_station_level = 2
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [{item = "iron_ingot", amount = 1}, {item = "copper_wire", amount = 2}]
|
inputs = [{item = "quartz", amount = 2}]
|
||||||
outputs = [{item = "circuit_board", amount = 1}]
|
outputs = [{item = "control_chip", amount = 1}]
|
||||||
duration_seconds = 2.0
|
duration_seconds = 4.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "building_blocks"
|
id = "shortcut_hardened_steel"
|
||||||
unlock_at_station_level = -1
|
unlock_at_station_level = 2
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [{item = "iron_ingot", amount = 4}]
|
inputs = [{item = "iron_ingot", amount = 4}]
|
||||||
outputs = [{item = "building_block", amount = 10}]
|
outputs = [{item = "hardened_steel", amount = 1}]
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Advanced components (tier 3, midgame)
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "mechanical_parts"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "steel_plate", amount = 1}, {item = "iron_ingot", amount = 1}]
|
|
||||||
outputs = [{item = "mechanical_parts", amount = 2}]
|
|
||||||
duration_seconds = 2.5
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "targeting_unit"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "circuit_board", amount = 2}, {item = "copper_wire", amount = 1}]
|
|
||||||
outputs = [{item = "targeting_unit", amount = 1}]
|
|
||||||
duration_seconds = 3.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "drive_unit"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [
|
|
||||||
{item = "steel_plate", amount = 1},
|
|
||||||
{item = "mechanical_parts", amount = 1},
|
|
||||||
{item = "circuit_board", amount = 1},
|
|
||||||
]
|
|
||||||
outputs = [{item = "drive_unit", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "titanium_frame"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "titanium_ingot", amount = 2}, {item = "steel_plate", amount = 1}]
|
|
||||||
outputs = [{item = "titanium_frame", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Capital components (tier 4, lategame — gated on advanced_alloy)
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "reinforced_plating"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "steel_plate", amount = 2}, {item = "advanced_alloy", amount = 1}]
|
|
||||||
outputs = [{item = "reinforced_plating", amount = 1}]
|
|
||||||
duration_seconds = 5.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "capital_core"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [
|
|
||||||
{item = "targeting_unit", amount = 1},
|
|
||||||
{item = "drive_unit", amount = 1},
|
|
||||||
{item = "advanced_alloy", amount = 2},
|
|
||||||
]
|
|
||||||
outputs = [{item = "capital_core", amount = 1}]
|
|
||||||
duration_seconds = 8.0
|
duration_seconds = 8.0
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Module items — early game
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "laser_cannon_s_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "iron_ingot", amount = 2}, {item = "circuit_board", amount = 1}]
|
|
||||||
outputs = [{item = "laser_cannon_s_module", amount = 1}]
|
|
||||||
duration_seconds = 3.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "salvager_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "steel_plate", amount = 1}, {item = "circuit_board", amount = 1}]
|
|
||||||
outputs = [{item = "salvager_module", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "repair_tool_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "circuit_board", amount = 2}, {item = "copper_wire", amount = 1}]
|
|
||||||
outputs = [{item = "repair_tool_module", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "armor_plates_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "steel_plate", amount = 2}]
|
|
||||||
outputs = [{item = "armor_plates_module", amount = 1}]
|
|
||||||
duration_seconds = 3.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "sensor_booster_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "circuit_board", amount = 1}, {item = "copper_wire", amount = 2}]
|
|
||||||
outputs = [{item = "sensor_booster_module", amount = 1}]
|
|
||||||
duration_seconds = 3.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "maneuvering_thrusters_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "mechanical_parts", amount = 1}, {item = "copper_wire", amount = 1}]
|
|
||||||
outputs = [{item = "maneuvering_thrusters_module", amount = 1}]
|
|
||||||
duration_seconds = 3.0
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Module items — midgame
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "afterburner_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "drive_unit", amount = 1}, {item = "steel_plate", amount = 1}]
|
|
||||||
outputs = [{item = "afterburner_module", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "weapon_upgrade_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "targeting_unit", amount = 1}, {item = "steel_plate", amount = 1}]
|
|
||||||
outputs = [{item = "weapon_upgrade_module", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "weapon_primer_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "targeting_unit", amount = 1}, {item = "copper_wire", amount = 2}]
|
|
||||||
outputs = [{item = "weapon_primer_module", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "weapon_stabilizer_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "targeting_unit", amount = 1}, {item = "mechanical_parts", amount = 1}]
|
|
||||||
outputs = [{item = "weapon_stabilizer_module", amount = 1}]
|
|
||||||
duration_seconds = 4.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "laser_cannon_m_module"
|
|
||||||
unlock_at_station_level = 1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [{item = "targeting_unit", amount = 1}, {item = "titanium_frame", amount = 1}]
|
|
||||||
outputs = [{item = "laser_cannon_m_module", amount = 1}]
|
|
||||||
duration_seconds = 6.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "drone_bay_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [
|
|
||||||
{item = "titanium_frame", amount = 1},
|
|
||||||
{item = "mechanical_parts", amount = 1},
|
|
||||||
{item = "circuit_board", amount = 1},
|
|
||||||
]
|
|
||||||
outputs = [{item = "drone_bay_module", amount = 1}]
|
|
||||||
duration_seconds = 6.0
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Module items — lategame
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "laser_cannon_l_module"
|
|
||||||
unlock_at_station_level = 1
|
|
||||||
unlock_requires = ["laser_cannon_m_module"]
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [
|
|
||||||
{item = "targeting_unit", amount = 2},
|
|
||||||
{item = "reinforced_plating", amount = 2},
|
|
||||||
{item = "titanium_frame", amount = 1},
|
|
||||||
]
|
|
||||||
outputs = [{item = "laser_cannon_l_module", amount = 1}]
|
|
||||||
duration_seconds = 12.0
|
|
||||||
|
|
||||||
[[recipe]]
|
|
||||||
id = "drone_hangar_module"
|
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
|
||||||
inputs = [
|
|
||||||
{item = "capital_core", amount = 1},
|
|
||||||
{item = "titanium_frame", amount = 2},
|
|
||||||
{item = "reinforced_plating", amount = 2},
|
|
||||||
]
|
|
||||||
outputs = [{item = "drone_hangar_module", amount = 1}]
|
|
||||||
duration_seconds = 20.0
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Ship hulls
|
# Ship hulls
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "drone_hull"
|
id = "drone_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [{item = "iron_ingot", amount = 5}, {item = "circuit_board", amount = 1}]
|
inputs = [{item = "iron_ingot", amount = 1}]
|
||||||
outputs = [{item = "drone_hull", amount = 1}]
|
outputs = [{item = "drone_hull", amount = 1}]
|
||||||
duration_seconds = 4.0
|
duration_seconds = 1.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "frigate_hull"
|
id = "frigate_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [
|
inputs = [{item = "steel_plate", amount = 2}, {item = "copper_wire", amount = 1}]
|
||||||
{item = "steel_plate", amount = 3},
|
|
||||||
{item = "mechanical_parts", amount = 1},
|
|
||||||
{item = "circuit_board", amount = 1},
|
|
||||||
]
|
|
||||||
outputs = [{item = "frigate_hull", amount = 1}]
|
outputs = [{item = "frigate_hull", amount = 1}]
|
||||||
duration_seconds = 8.0
|
duration_seconds = 2.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "destroyer_hull"
|
id = "destroyer_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [
|
inputs = [{item = "steel_plate", amount = 3}, {item = "copper_coil", amount = 2}]
|
||||||
{item = "steel_plate", amount = 5},
|
|
||||||
{item = "mechanical_parts", amount = 2},
|
|
||||||
{item = "circuit_board", amount = 1},
|
|
||||||
]
|
|
||||||
outputs = [{item = "destroyer_hull", amount = 1}]
|
outputs = [{item = "destroyer_hull", amount = 1}]
|
||||||
duration_seconds = 10.0
|
duration_seconds = 4.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "cruiser_hull"
|
id = "cruiser_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [
|
inputs = [{item = "hardened_steel", amount = 2}, {item = "control_chip", amount = 2}]
|
||||||
{item = "titanium_frame", amount = 2},
|
|
||||||
{item = "steel_plate", amount = 4},
|
|
||||||
{item = "drive_unit", amount = 1},
|
|
||||||
]
|
|
||||||
outputs = [{item = "cruiser_hull", amount = 1}]
|
outputs = [{item = "cruiser_hull", amount = 1}]
|
||||||
duration_seconds = 15.0
|
duration_seconds = 6.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "battlecruiser_hull"
|
id = "battlecruiser_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [
|
inputs = [
|
||||||
{item = "titanium_frame", amount = 3},
|
{item = "hardened_steel", amount = 3},
|
||||||
{item = "steel_plate", amount = 6},
|
{item = "control_chip", amount = 2},
|
||||||
{item = "drive_unit", amount = 1},
|
{item = "drive_unit", amount = 1},
|
||||||
{item = "targeting_unit", amount = 1},
|
|
||||||
]
|
]
|
||||||
outputs = [{item = "battlecruiser_hull", amount = 1}]
|
outputs = [{item = "battlecruiser_hull", amount = 1}]
|
||||||
duration_seconds = 20.0
|
duration_seconds = 8.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "battleship_hull"
|
id = "battleship_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [
|
inputs = [
|
||||||
{item = "titanium_frame", amount = 4},
|
{item = "voidsteel_plate", amount = 3},
|
||||||
{item = "reinforced_plating", amount = 2},
|
{item = "drive_unit", amount = 1},
|
||||||
{item = "drive_unit", amount = 2},
|
{item = "control_chip", amount = 2},
|
||||||
]
|
]
|
||||||
outputs = [{item = "battleship_hull", amount = 1}]
|
outputs = [{item = "battleship_hull", amount = 1}]
|
||||||
duration_seconds = 30.0
|
duration_seconds = 10.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "dreadnought_hull"
|
id = "dreadnought_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [
|
inputs = [
|
||||||
|
{item = "voidsteel_plate", amount = 5},
|
||||||
{item = "capital_core", amount = 1},
|
{item = "capital_core", amount = 1},
|
||||||
{item = "titanium_frame", amount = 6},
|
|
||||||
{item = "reinforced_plating", amount = 4},
|
|
||||||
{item = "drive_unit", amount = 2},
|
{item = "drive_unit", amount = 2},
|
||||||
]
|
]
|
||||||
outputs = [{item = "dreadnought_hull", amount = 1}]
|
outputs = [{item = "dreadnought_hull", amount = 1}]
|
||||||
duration_seconds = 60.0
|
duration_seconds = 12.0
|
||||||
|
|
||||||
[[recipe]]
|
[[recipe]]
|
||||||
id = "carrier_hull"
|
id = "carrier_hull"
|
||||||
unlock_at_station_level = -1
|
|
||||||
building = "assembler"
|
building = "assembler"
|
||||||
inputs = [
|
inputs = [
|
||||||
|
{item = "voidsteel_plate", amount = 5},
|
||||||
{item = "capital_core", amount = 1},
|
{item = "capital_core", amount = 1},
|
||||||
{item = "titanium_frame", amount = 5},
|
|
||||||
{item = "reinforced_plating", amount = 3},
|
|
||||||
{item = "drive_unit", amount = 2},
|
{item = "drive_unit", amount = 2},
|
||||||
]
|
]
|
||||||
outputs = [{item = "carrier_hull", amount = 1}]
|
outputs = [{item = "carrier_hull", amount = 1}]
|
||||||
duration_seconds = 60.0
|
duration_seconds = 12.0
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Module prefabs
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "railgun_s_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "copper_coil", amount = 1}]
|
||||||
|
outputs = [{item = "railgun_s_module", amount = 1}]
|
||||||
|
duration_seconds = 1.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "salvager_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "steel_plate", amount = 1}, {item = "copper_wire", amount = 2}]
|
||||||
|
outputs = [{item = "salvager_module", amount = 1}]
|
||||||
|
duration_seconds = 2.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "repair_tool_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "steel_plate", amount = 1}, {item = "copper_wire", amount = 2}]
|
||||||
|
outputs = [{item = "repair_tool_module", amount = 1}]
|
||||||
|
duration_seconds = 2.0
|
||||||
|
|
||||||
|
# Material-heavy, fast: the armor archetype.
|
||||||
|
[[recipe]]
|
||||||
|
id = "armor_plates_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "steel_plate", amount = 4}]
|
||||||
|
outputs = [{item = "armor_plates_module", amount = 1}]
|
||||||
|
duration_seconds = 3.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "maneuvering_thrusters_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "steel_plate", amount = 1}, {item = "copper_coil", amount = 1}]
|
||||||
|
outputs = [{item = "maneuvering_thrusters_module", amount = 1}]
|
||||||
|
duration_seconds = 2.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "sensor_booster_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "copper_wire", amount = 2}, {item = "copper_coil", amount = 1}]
|
||||||
|
outputs = [{item = "sensor_booster_module", amount = 1}]
|
||||||
|
duration_seconds = 2.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "afterburner_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "copper_coil", amount = 2}, {item = "steel_plate", amount = 1}]
|
||||||
|
outputs = [{item = "afterburner_module", amount = 1}]
|
||||||
|
duration_seconds = 3.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "weapon_stabilizer_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "steel_plate", amount = 1}, {item = "copper_coil", amount = 1}]
|
||||||
|
outputs = [{item = "weapon_stabilizer_module", amount = 1}]
|
||||||
|
duration_seconds = 2.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "weapon_primer_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "capacitor_bank", amount = 1}, {item = "copper_coil", amount = 1}]
|
||||||
|
outputs = [{item = "weapon_primer_module", amount = 1}]
|
||||||
|
duration_seconds = 4.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "weapon_upgrade_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [{item = "control_chip", amount = 1}, {item = "copper_coil", amount = 1}]
|
||||||
|
outputs = [{item = "weapon_upgrade_module", amount = 1}]
|
||||||
|
duration_seconds = 4.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "railgun_m_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [
|
||||||
|
{item = "capacitor_bank", amount = 1},
|
||||||
|
{item = "steel_plate", amount = 2},
|
||||||
|
{item = "copper_coil", amount = 1},
|
||||||
|
]
|
||||||
|
outputs = [{item = "railgun_m_module", amount = 1}]
|
||||||
|
duration_seconds = 4.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "drone_bay_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [
|
||||||
|
{item = "control_chip", amount = 1},
|
||||||
|
{item = "steel_plate", amount = 2},
|
||||||
|
{item = "copper_coil", amount = 1},
|
||||||
|
]
|
||||||
|
outputs = [{item = "drone_bay_module", amount = 1}]
|
||||||
|
duration_seconds = 4.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "railgun_l_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [
|
||||||
|
{item = "capacitor_bank", amount = 1},
|
||||||
|
{item = "hardened_steel", amount = 2},
|
||||||
|
{item = "ceramic_plate", amount = 1},
|
||||||
|
]
|
||||||
|
outputs = [{item = "railgun_l_module", amount = 1}]
|
||||||
|
duration_seconds = 6.0
|
||||||
|
|
||||||
|
[[recipe]]
|
||||||
|
id = "drone_hangar_module"
|
||||||
|
building = "assembler"
|
||||||
|
inputs = [
|
||||||
|
{item = "voidsteel_plate", amount = 1},
|
||||||
|
{item = "control_chip", amount = 2},
|
||||||
|
{item = "drive_unit", amount = 1},
|
||||||
|
]
|
||||||
|
outputs = [{item = "drone_hangar_module", amount = 1}]
|
||||||
|
duration_seconds = 10.0
|
||||||
|
|||||||
@@ -24,11 +24,11 @@
|
|||||||
id = "drone"
|
id = "drone"
|
||||||
unlock_at_station_level = -1
|
unlock_at_station_level = -1
|
||||||
layout = ["O"]
|
layout = ["O"]
|
||||||
default_modules = [{type = "laser_cannon_s", x = 0, y = 0, rotation = "east"}]
|
default_modules = [{type = "railgun_s", x = 0, y = 0, rotation = "east"}]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "iron_ore", amount = 1}]
|
materials = [{item = "drone_hull", amount = 1}]
|
||||||
production_time_seconds = 5
|
production_time_seconds = 1
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 3
|
hp = 3
|
||||||
@@ -55,10 +55,15 @@ layout = [
|
|||||||
"OOO",
|
"OOO",
|
||||||
"XOX",
|
"XOX",
|
||||||
]
|
]
|
||||||
|
default_modules = [
|
||||||
|
{type = "railgun_s", x = 1, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 2, y = 1, rotation = "east"},
|
||||||
|
{type = "maneuvering_thrusters", x = 0, y = 1, rotation = "east"},
|
||||||
|
]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "frigate_hull", amount = 1}]
|
materials = [{item = "frigate_hull", amount = 1}]
|
||||||
production_time_seconds = 10
|
production_time_seconds = 2
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 30
|
hp = 30
|
||||||
@@ -84,10 +89,17 @@ layout = [
|
|||||||
"OXOXO",
|
"OXOXO",
|
||||||
"OOOOO",
|
"OOOOO",
|
||||||
]
|
]
|
||||||
|
default_modules = [
|
||||||
|
{type = "railgun_s", x = 0, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 2, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 4, y = 0, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 0, y = 1, rotation = "east"},
|
||||||
|
{type = "sensor_booster", x = 3, y = 1, rotation = "east"},
|
||||||
|
]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "destroyer_hull", amount = 1}]
|
materials = [{item = "destroyer_hull", amount = 1}]
|
||||||
production_time_seconds = 15
|
production_time_seconds = 3
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 50
|
hp = 50
|
||||||
@@ -115,10 +127,16 @@ layout = [
|
|||||||
"OOOO",
|
"OOOO",
|
||||||
"XOOX",
|
"XOOX",
|
||||||
]
|
]
|
||||||
|
default_modules = [
|
||||||
|
{type = "railgun_m", x = 0, y = 1, rotation = "east"},
|
||||||
|
{type = "railgun_m", x = 2, y = 1, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 1, y = 0, rotation = "east"},
|
||||||
|
{type = "maneuvering_thrusters", x = 1, y = 3, rotation = "east"},
|
||||||
|
]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "cruiser_hull", amount = 1}]
|
materials = [{item = "cruiser_hull", amount = 1}]
|
||||||
production_time_seconds = 25
|
production_time_seconds = 4
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 120
|
hp = 120
|
||||||
@@ -147,10 +165,18 @@ layout = [
|
|||||||
"XOOOOX",
|
"XOOOOX",
|
||||||
"XXOOXX",
|
"XXOOXX",
|
||||||
]
|
]
|
||||||
|
default_modules = [
|
||||||
|
{type = "railgun_m", x = 0, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_m", x = 4, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_m", x = 2, y = 1, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 2, y = 3, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 1, y = 2, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 4, y = 2, rotation = "east"},
|
||||||
|
]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "battlecruiser_hull", amount = 1}]
|
materials = [{item = "battlecruiser_hull", amount = 1}]
|
||||||
production_time_seconds = 35
|
production_time_seconds = 5
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 180
|
hp = 180
|
||||||
@@ -182,10 +208,18 @@ layout = [
|
|||||||
"OOOOOO",
|
"OOOOOO",
|
||||||
"XOOOOX",
|
"XOOOOX",
|
||||||
]
|
]
|
||||||
|
default_modules = [
|
||||||
|
{type = "railgun_l", x = 1, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_m", x = 1, y = 3, rotation = "east"},
|
||||||
|
{type = "railgun_m", x = 3, y = 3, rotation = "east"},
|
||||||
|
{type = "weapon_stabilizer", x = 4, y = 1, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 4, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 0, y = 1, rotation = "east"},
|
||||||
|
]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "battleship_hull", amount = 1}]
|
materials = [{item = "battleship_hull", amount = 1}]
|
||||||
production_time_seconds = 60
|
production_time_seconds = 6
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 350
|
hp = 350
|
||||||
@@ -217,10 +251,20 @@ layout = [
|
|||||||
"OOOXOOOXOOO",
|
"OOOXOOOXOOO",
|
||||||
"XXOOXXXOOXX",
|
"XXOOXXXOOXX",
|
||||||
]
|
]
|
||||||
|
default_modules = [
|
||||||
|
{type = "railgun_l", x = 0, y = 1, rotation = "east"},
|
||||||
|
{type = "railgun_l", x = 4, y = 1, rotation = "east"},
|
||||||
|
{type = "railgun_l", x = 8, y = 1, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 3, y = 0, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 5, y = 0, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 2, y = 4, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 7, y = 4, rotation = "east"},
|
||||||
|
{type = "railgun_s", x = 7, y = 0, rotation = "east"},
|
||||||
|
]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "dreadnought_hull", amount = 1}]
|
materials = [{item = "dreadnought_hull", amount = 1}]
|
||||||
production_time_seconds = 120
|
production_time_seconds = 8
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 800
|
hp = 800
|
||||||
@@ -250,10 +294,18 @@ layout = [
|
|||||||
"XOOOOOOOOX",
|
"XOOOOOOOOX",
|
||||||
"XXXOOOOXXX",
|
"XXXOOOOXXX",
|
||||||
]
|
]
|
||||||
|
default_modules = [
|
||||||
|
{type = "drone_hangar", x = 2, y = 0, rotation = "east"},
|
||||||
|
{type = "railgun_m", x = 3, y = 2, rotation = "east"},
|
||||||
|
{type = "railgun_m", x = 6, y = 2, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 0, y = 1, rotation = "east"},
|
||||||
|
{type = "armor_plates", x = 8, y = 1, rotation = "east"},
|
||||||
|
{type = "sensor_booster", x = 3, y = 4, rotation = "east"},
|
||||||
|
]
|
||||||
|
|
||||||
[ship.schematic]
|
[ship.schematic]
|
||||||
materials = [{item = "carrier_hull", amount = 1}]
|
materials = [{item = "carrier_hull", amount = 1}]
|
||||||
production_time_seconds = 120
|
production_time_seconds = 8
|
||||||
|
|
||||||
[ship.health]
|
[ship.health]
|
||||||
hp = 700
|
hp = 700
|
||||||
|
|||||||
@@ -116,11 +116,11 @@ outline = "#201010"
|
|||||||
fill = "#c47a3a"
|
fill = "#c47a3a"
|
||||||
outline = "#3a1a0a"
|
outline = "#3a1a0a"
|
||||||
|
|
||||||
[items.titanium_ore]
|
[items.quartz]
|
||||||
fill = "#9aa3ad"
|
fill = "#e0d4f0"
|
||||||
outline = "#2a2e33"
|
outline = "#40345a"
|
||||||
|
|
||||||
# --- ingots ---
|
# --- smelted basics ---
|
||||||
|
|
||||||
[items.iron_ingot]
|
[items.iron_ingot]
|
||||||
fill = "#b0b0b8"
|
fill = "#b0b0b8"
|
||||||
@@ -130,9 +130,9 @@ outline = "#202028"
|
|||||||
fill = "#d48a4a"
|
fill = "#d48a4a"
|
||||||
outline = "#402010"
|
outline = "#402010"
|
||||||
|
|
||||||
[items.titanium_ingot]
|
[items.silicon]
|
||||||
fill = "#c8d2dc"
|
fill = "#33415e"
|
||||||
outline = "#3a4048"
|
outline = "#0e1420"
|
||||||
|
|
||||||
# --- salvage loop ---
|
# --- salvage loop ---
|
||||||
|
|
||||||
@@ -140,9 +140,9 @@ outline = "#3a4048"
|
|||||||
fill = "#7a7268"
|
fill = "#7a7268"
|
||||||
outline = "#201a14"
|
outline = "#201a14"
|
||||||
|
|
||||||
[items.advanced_alloy]
|
[items.voidsteel]
|
||||||
fill = "#a06acc"
|
fill = "#4a3a6a"
|
||||||
outline = "#201030"
|
outline = "#151020"
|
||||||
|
|
||||||
# --- basic components ---
|
# --- basic components ---
|
||||||
|
|
||||||
@@ -154,9 +154,9 @@ outline = "#3a2008"
|
|||||||
fill = "#8a92a0"
|
fill = "#8a92a0"
|
||||||
outline = "#22262c"
|
outline = "#22262c"
|
||||||
|
|
||||||
[items.circuit_board]
|
[items.copper_coil]
|
||||||
fill = "#2ea35a"
|
fill = "#d07030"
|
||||||
outline = "#0a2a14"
|
outline = "#381808"
|
||||||
|
|
||||||
[items.building_block]
|
[items.building_block]
|
||||||
fill = "#c8b070"
|
fill = "#c8b070"
|
||||||
@@ -164,26 +164,30 @@ outline = "#302810"
|
|||||||
|
|
||||||
# --- advanced components ---
|
# --- advanced components ---
|
||||||
|
|
||||||
[items.mechanical_parts]
|
[items.control_chip]
|
||||||
fill = "#6f7a66"
|
fill = "#2ea35a"
|
||||||
outline = "#1c2018"
|
outline = "#0a2a14"
|
||||||
|
|
||||||
[items.targeting_unit]
|
[items.capacitor_bank]
|
||||||
fill = "#3a9e8c"
|
fill = "#d0a030"
|
||||||
outline = "#0c2824"
|
outline = "#302408"
|
||||||
|
|
||||||
|
[items.hardened_steel]
|
||||||
|
fill = "#6a7280"
|
||||||
|
outline = "#181c22"
|
||||||
|
|
||||||
|
[items.ceramic_plate]
|
||||||
|
fill = "#e0d8c8"
|
||||||
|
outline = "#3a3428"
|
||||||
|
|
||||||
[items.drive_unit]
|
[items.drive_unit]
|
||||||
fill = "#4a6ad0"
|
fill = "#4a6ad0"
|
||||||
outline = "#101a38"
|
outline = "#101a38"
|
||||||
|
|
||||||
[items.titanium_frame]
|
|
||||||
fill = "#b8c4d4"
|
|
||||||
outline = "#343c48"
|
|
||||||
|
|
||||||
# --- capital components ---
|
# --- capital components ---
|
||||||
|
|
||||||
[items.reinforced_plating]
|
[items.voidsteel_plate]
|
||||||
fill = "#8a6ad0"
|
fill = "#7a5aaa"
|
||||||
outline = "#1c1038"
|
outline = "#1c1038"
|
||||||
|
|
||||||
[items.capital_core]
|
[items.capital_core]
|
||||||
@@ -192,15 +196,15 @@ outline = "#280c30"
|
|||||||
|
|
||||||
# --- module items ---
|
# --- module items ---
|
||||||
|
|
||||||
[items.laser_cannon_s_module]
|
[items.railgun_s_module]
|
||||||
fill = "#691313"
|
fill = "#691313"
|
||||||
outline = "#f3ff4f"
|
outline = "#f3ff4f"
|
||||||
|
|
||||||
[items.laser_cannon_m_module]
|
[items.railgun_m_module]
|
||||||
fill = "#892020"
|
fill = "#892020"
|
||||||
outline = "#f3ff4f"
|
outline = "#f3ff4f"
|
||||||
|
|
||||||
[items.laser_cannon_l_module]
|
[items.railgun_l_module]
|
||||||
fill = "#a92d2d"
|
fill = "#a92d2d"
|
||||||
outline = "#f3ff4f"
|
outline = "#f3ff4f"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ height_tiles = 40
|
|||||||
refund_percentage = 100
|
refund_percentage = 100
|
||||||
starting_building_blocks = 1000
|
starting_building_blocks = 1000
|
||||||
scrap_despawn_seconds = 30
|
scrap_despawn_seconds = 30
|
||||||
scrap_per_threat = 0.01
|
scrap_per_threat = 0.25
|
||||||
tile_size_m = 10
|
tile_size_m = 10
|
||||||
belt_speed_mps = 20
|
belt_speed_mps = 20
|
||||||
tunnel_max_distance_tiles = 10
|
tunnel_max_distance_tiles = 10
|
||||||
|
|||||||
@@ -341,11 +341,15 @@ prints per-item threat values and producer:consumer ratio tables.
|
|||||||
|
|
||||||
### Numbers — first pass
|
### Numbers — first pass
|
||||||
|
|
||||||
Computed with a recursive threat calculator (now available as
|
These numbers are live in the config files and verified by
|
||||||
`tools/threat_report.py`, which reads the real config files — it
|
`tools/threat_report.py`; quantities and durations are tuned so fitted
|
||||||
verifies these numbers once the v2 tree lands in the configs);
|
ships land on the threat-cost ladder and the ratio curve is realized.
|
||||||
quantities and durations tuned so fitted ships land on the threat-cost
|
The typical loadouts are geometry-validated against the hull grids and
|
||||||
ladder and the ratio curve is realized.
|
configured as each ship's `default_modules`: the L-shaped weapon
|
||||||
|
modifiers turned out not to fit alongside the full gun complement on
|
||||||
|
the battlecruiser and dreadnought, so their loadouts use armor and
|
||||||
|
small-railgun fillers instead — which moved all three heavy ships
|
||||||
|
closer to their ladder targets.
|
||||||
|
|
||||||
**Economy constants:** `scrap_per_threat = 0.25` (1 scrap per 4 threat
|
**Economy constants:** `scrap_per_threat = 0.25` (1 scrap per 4 threat
|
||||||
destroyed — a cruiser kill drops ~59 scrap). Reprocessing: 4 scrap per
|
destroyed — a cruiser kill drops ~59 scrap). Reprocessing: 4 scrap per
|
||||||
@@ -405,9 +409,9 @@ typical loadouts double as the `default_modules` for enemy waves):
|
|||||||
| frigate | 2 steel_plate + 1 copper_wire | 2 | 2 | 2× railgun_s, maneuvering_thrusters | 47 (40) |
|
| frigate | 2 steel_plate + 1 copper_wire | 2 | 2 | 2× railgun_s, maneuvering_thrusters | 47 (40) |
|
||||||
| destroyer | 3 steel_plate + 2 copper_coil | 4 | 3 | 3× railgun_s, armor_plates, sensor_booster | 99 (80) |
|
| destroyer | 3 steel_plate + 2 copper_coil | 4 | 3 | 3× railgun_s, armor_plates, sensor_booster | 99 (80) |
|
||||||
| cruiser | 2 hardened_steel + 2 control_chip | 6 | 4 | 2× railgun_m, armor_plates, maneuvering_thrusters | 234 (200) |
|
| cruiser | 2 hardened_steel + 2 control_chip | 6 | 4 | 2× railgun_m, armor_plates, maneuvering_thrusters | 234 (200) |
|
||||||
| battlecruiser | 3 hardened_steel + 2 control_chip + 1 drive_unit | 8 | 5 | 3× railgun_m, weapon_primer, armor_plates | 370 (350) |
|
| battlecruiser | 3 hardened_steel + 2 control_chip + 1 drive_unit | 8 | 5 | 3× railgun_m, armor_plates, 2× railgun_s | 355 (350) |
|
||||||
| battleship | 3 voidsteel_plate + 1 drive_unit + 2 control_chip | 10 | 6 | railgun_l, 2× railgun_m, weapon_stabilizer, armor_plates, sensor_booster | 752 (700) |
|
| battleship | 3 voidsteel_plate + 1 drive_unit + 2 control_chip | 10 | 6 | railgun_l, 2× railgun_m, weapon_stabilizer, 2× railgun_s | 723 (700) |
|
||||||
| dreadnought | 5 voidsteel_plate + 1 capital_core + 2 drive_unit | 12 | 8 | 3× railgun_l, weapon_primer, weapon_upgrade, 2× armor_plates | 1472 (1500) |
|
| dreadnought | 5 voidsteel_plate + 1 capital_core + 2 drive_unit | 12 | 8 | 3× railgun_l, 4× armor_plates, railgun_s | 1492 (1500) |
|
||||||
| carrier | 5 voidsteel_plate + 1 capital_core + 2 drive_unit | 12 | 8 | drone_hangar, 2× railgun_m, 2× armor_plates, sensor_booster | 1436 (1500) |
|
| carrier | 5 voidsteel_plate + 1 capital_core + 2 drive_unit | 12 | 8 | drone_hangar, 2× railgun_m, 2× armor_plates, sensor_booster | 1436 (1500) |
|
||||||
|
|
||||||
**Checks:**
|
**Checks:**
|
||||||
|
|||||||
@@ -392,3 +392,12 @@ in `requirements.md` and the git history). Still open:
|
|||||||
pass instead of iterating; their consumers silently drop the missing
|
pass instead of iterating; their consumers silently drop the missing
|
||||||
materials, so capital hull threat is currently underestimated (found
|
materials, so capital hull threat is currently underestimated (found
|
||||||
by `tools/threat_report.py`, which implements the correct fixpoint).
|
by `tools/threat_report.py`, which implements the correct fixpoint).
|
||||||
|
9. **Max rule across staggered recipes in ThreatCostCalculator.** An
|
||||||
|
item is committed at the first iteration where *any* of its recipes
|
||||||
|
resolves, taking the max only over the recipes resolvable at that
|
||||||
|
point. A shallow shortcut recipe (e.g. steel plate from raw ore)
|
||||||
|
resolves one iteration earlier than the base path and wins, silently
|
||||||
|
underpricing the item and everything downstream — violating the
|
||||||
|
"shortcuts are pure rewards" rule. Fix: commit an item's threat only
|
||||||
|
once every eligible recipe for it is computable (as
|
||||||
|
`tools/threat_report.py` does), with a fallback for recipe cycles.
|
||||||
|
|||||||
@@ -86,23 +86,30 @@ def resolve_items(recipes, scrap_threat):
|
|||||||
|
|
||||||
item_threat = {"scrap": scrap_threat}
|
item_threat = {"scrap": scrap_threat}
|
||||||
|
|
||||||
def resolve_pass():
|
# All eligible (recipe, output) pairs per item: the max rule requires
|
||||||
|
# committing an item only once EVERY eligible recipe for it is
|
||||||
|
# computable — otherwise a shallow shortcut recipe that resolves one
|
||||||
|
# pass earlier than the base path would win and underprice the item.
|
||||||
|
recipes_per_item = {}
|
||||||
|
for recipe in non_repro:
|
||||||
|
for output in recipe.get("outputs", []):
|
||||||
|
if eligible(recipe, output):
|
||||||
|
recipes_per_item.setdefault(output["item"], []).append(
|
||||||
|
(recipe, output))
|
||||||
|
|
||||||
|
def resolve_pass(require_all_recipes=True):
|
||||||
progress = False
|
progress = False
|
||||||
best = {}
|
best = {}
|
||||||
for recipe in non_repro:
|
for item, pairs in recipes_per_item.items():
|
||||||
for output in recipe.get("outputs", []):
|
if item in item_threat:
|
||||||
if output["item"] in item_threat:
|
continue
|
||||||
continue
|
threats = [recipe_threat_per_unit(r, o, item_threat)
|
||||||
if not eligible(recipe, output):
|
for r, o in pairs]
|
||||||
continue
|
if require_all_recipes and any(t is None for t in threats):
|
||||||
threat = recipe_threat_per_unit(recipe, output, item_threat)
|
continue
|
||||||
if threat is None:
|
threats = [t for t in threats if t is not None]
|
||||||
continue
|
if threats:
|
||||||
key = output["item"]
|
best[item] = max(threats)
|
||||||
if key not in best or threat > best[key]:
|
|
||||||
best[key] = threat
|
|
||||||
# A full sweep before committing keeps the max rule correct when
|
|
||||||
# several recipes for the same item resolve in the same pass.
|
|
||||||
for item, threat in best.items():
|
for item, threat in best.items():
|
||||||
item_threat[item] = threat
|
item_threat[item] = threat
|
||||||
progress = True
|
progress = True
|
||||||
@@ -139,6 +146,13 @@ def resolve_items(recipes, scrap_threat):
|
|||||||
progress = resolve_pass()
|
progress = resolve_pass()
|
||||||
progress = repro_pass() or progress
|
progress = repro_pass() or progress
|
||||||
|
|
||||||
|
# Deadlock guard: if recipe cycles keep items waiting on each other,
|
||||||
|
# fall back to committing with the computable subset of recipes.
|
||||||
|
progress = True
|
||||||
|
while progress:
|
||||||
|
progress = resolve_pass(require_all_recipes=False)
|
||||||
|
progress = repro_pass() or progress
|
||||||
|
|
||||||
return item_threat
|
return item_threat
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user