Fix ThreatCostCalculator: per-unit division, scrap fallback, fixpoint, staggered-recipe max

This commit is contained in:
2026-07-08 20:28:31 +02:00
parent c6db4bf24a
commit 5b86b15c71
6 changed files with 333 additions and 98 deletions

View File

@@ -92,3 +92,60 @@ duration_seconds = 3.0
item = "advanced_alloy"
amount = 1
probability = 0.1
# -------------------------------------------------------------------
# Extra recipes for ThreatCostCalculator unit tests (fixes 6-9)
# -------------------------------------------------------------------
# Fix 6: scrap-consuming smelter recipe for iron_ingot. Because iron_ingot
# already has a scrap-free smelter recipe above, this recipe must be excluded
# from iron_ingot's threat computation.
[[recipe]]
id = "scrap_iron"
building = "smelter"
inputs = [{item = "scrap", amount = 1}]
outputs = [{item = "iron_ingot", amount = 1}]
duration_seconds = 1.0
# Fix 7: a recipe that produces 2 items per cycle. Per-unit threat must
# divide by the output amount.
# dual_wire: (duration=3.0 + iron_ore(1.0)*1) / 2 = 4.0 / 2 = 2.0 per unit.
[[recipe]]
id = "dual_wire"
building = "assembler"
inputs = [{item = "iron_ore", amount = 1}]
outputs = [{item = "dual_wire", amount = 2}]
duration_seconds = 3.0
# Fix 8: an item downstream of a reprocessing-only item (advanced_alloy).
# advanced_alloy is resolved only by the reprocessing pass; downstream_product
# can only resolve in a non-reprocessing pass that runs AFTER the reprocessing
# pass, requiring proper fixpoint iteration.
# downstream_product: 2.0 + advanced_alloy(80.0)*1 = 82.0
[[recipe]]
id = "downstream_product"
building = "assembler"
inputs = [{item = "advanced_alloy", amount = 1}]
outputs = [{item = "downstream_product", amount = 1}]
duration_seconds = 2.0
# Fix 9: two recipes producing the same staggered_item. The cheap recipe
# resolves before circuit_board is known; the expensive one requires
# circuit_board. The item must be committed only once BOTH are computable,
# so the result is max(cheap, expensive).
# staggered_item_cheap: 1.0 + iron_ore(1.0)*1 = 2.0 (resolves early)
# staggered_item_expensive: 1.0 + circuit_board(28.0)*1 = 29.0 (resolves later)
# expected: max = 29.0
[[recipe]]
id = "staggered_item_cheap"
building = "assembler"
inputs = [{item = "iron_ore", amount = 1}]
outputs = [{item = "staggered_item", amount = 1}]
duration_seconds = 1.0
[[recipe]]
id = "staggered_item_expensive"
building = "assembler"
inputs = [{item = "circuit_board", amount = 1}]
outputs = [{item = "staggered_item", amount = 1}]
duration_seconds = 1.0