factorio-base-definer/calc2.py
2024-02-14 23:33:18 -08:00

209 lines
8.3 KiB
Python

from pprint import pformat, pprint
recipies: dict[str, dict[str, float]] = {
# mining
'iron-ore': {'mining-drill': -1, 'iron-ore': 0.5},
'copper-ore': {'mining-drill': -1, 'copper-ore': 0.5},
'stone': {'mining-drill': -1, 'stone': 0.5},
'coal': {'mining-drill': -1, 'coal': 0.5},
'uranium-ore': {'mining-drill': -1, 'sulfuric-acid': -0.25, 'uranium-ore': 0.5},
# oil
'basic-oil-processing': {'oil-refinery': -5, 'crude-oil': -100, 'petroleum-gas': 45},
'advanced-oil-processing': {
'oil-refinery': -5,
'crude-oil': -100,
'water': -50,
'petroleum-gas': 55,
'light-oil': 45,
'heavy-oil': 25,
},
'coal-liquefaction': {
'oil-refinery': -5,
'coal': -10,
'steam': -50,
'petroleum-gas': 10,
'light-oil': 20,
'heavy-oil': -25 + 90,
},
'heavy-oil-craking': {'chemical-plant': -2, 'heavy-oil': -40, 'water': -30, 'light-oil': 30},
'light-oil-craking': {'chemical-plant': -2, 'light-oil': -30, 'water': -30, 'petroleum-gas': 20},
# fuel
'solid-fuel-pg': {'chemical-plant': -2, 'petroleum-gas': -20, 'solid-fuel': 1},
'solid-fuel-lo': {'chemical-plant': -2, 'light-oil': -10, 'solid-fuel': 1},
'solid-fuel-ho': {'chemical-plant': -2, 'heavy-oil': -20, 'solid-fuel': 1},
'rocket-fuel': {'assembler': -30, 'light-oil': -10, 'solid-fuel': -10, 'rocket-fuel': 1},
# smelting
'iron-plate': {'furnace': -3.2, 'iron-ore': -1, 'iron-plate': 1},
'copper-plate': {'furnace': -3.2, 'copper-ore': -1, 'copper-plate': 1},
'stone-brick': {'furnace': -3.2, 'stone': -1, 'stone-brick': 1},
'steel': {'furnace': -16, 'iron-plate': -5, 'steel': 1},
# crafting basics
'iron-gear': {'assembler': -0.5, 'iron-plate': -2, 'iron-gear': 1},
'iron-stick': {'assembler': -0.5, 'iron-plate': -1, 'iron-stick': 2},
'pipe': {'assembler': -0.5, 'iron-plate': -1, 'pipe': 1},
'copper-cable': {'assembler': -0.5, 'copper-plate': -1, 'copper-cable': 2},
# circuits
'circuit-a': {'assembler': -0.5, 'copper-cable': -3, 'iron-plate': -1, 'circuit-a': 1},
'circuit-b': {'assembler': -6, 'copper-cable': -4, 'circuit-a': -2, 'plastic': -2, 'circuit-b': 1},
'circuit-c': {'assembler': -10, 'circuit-a': -2, 'circuit-b': -20, 'sulfuric-acid': -5, 'circuit-c': 1},
# logistics
'belt-y': {'assembler': -0.5, 'iron-gear': -1, 'iron-plate': -1, 'belt-y': 2},
'inserter-y': {'assembler': -0.5, 'circuit-a': -1, 'iron-gear': -1, 'iron-plate': -1, 'inserter-y': 1},
# transport
'concrete': {'assembler': -10, 'iron-ore': -1, 'stone-brick': -5, 'water': -100, 'concrete': 10},
'rail': {'assembler': -0.5, 'iron-stick': -1, 'steel': -1, 'stone': -1, 'rail': 1},
# chemicals
'sulfur': {'chemical-plant': -1, 'petroleum-gas': -30, 'water': -30, 'sulfur': 2},
'sulfuric-acid': {'chemical-plant': -1, 'iron-plate': -1, 'sulfur': -5, 'water': -100, 'sulfuric-acid': 50},
'plastic': {'chemical-plant': -1, 'coal': -1, 'petroleum-gas': -20, 'plastic': 2},
'explosives': {'chemical-plant': -4, 'coal': -1, 'sulfur': -1, 'water': -10, 'explosives': 2},
'battery': {'chemical-plant': -4, 'copper-plate': -1, 'iron-plate': -20, 'sulfuric-acid': -20, 'battery': 1},
# military
'magazine-y': {'assembler': -1, 'iron-plate': -4, 'magazine-y': 1},
'magazine-r': {'assembler': -1, 'copper-plate': -5, 'magazine-y': -1, 'steel': -1, 'magazine-r': 1},
'grenade': {'assembler': -8, 'coal': -10, 'iron-plate': -5, 'grenade': 1},
'wall': {'assembler': -0.5, 'stone-brick': -5, 'wall': 1},
'rocket-y': {'assembler': -8, 'circuit-a': -1, 'explosives': -1, 'iron-plate': -2, 'rocket-y': 1},
'rocket-r': {'assembler': -8, 'explosives': -2, 'rocket-r': 1},
# intermediates
'engine-unit': {'assembler': -10, 'iron-gear': -1, 'pipe': -2, 'steel': -1, 'engine-unit': 1},
'engine-unit-electric': {
'assembler': -10,
'circuit-a': -2,
'engine-unit': -1,
'lubricant': -15,
'engine-unit-electric': 1,
},
'accumulator': {'assembler': -10, 'battery': -5, 'iron-plate': -2, 'accumulator': 1},
'solar-panel': {'assembler': -10, 'copper-plate': -5, 'circuit-a': -15, 'steel': -5, 'solar-panel': 1},
'electric-furnace': {'assembler': -5, 'circuit-b': -5, 'steel': -10, 'stone-brick': -10, 'electric-furnace': 1},
'flying-robot-frame': {
'assembler': -20,
'battery': -2,
'engine-unit-electric': -1,
'circuit-a': -3,
'steel': -1,
'flying-robot-frame': 1,
},
'low-density-structure': {
'assembler': -20,
'copper-plate': -20,
'plastic': -5,
'steel': -2,
'low-density-structure': 1,
},
# modules
'module-productivity': {'assembler': -15, 'circuit-b': -5, 'circuit-a': -5, 'module-productivity': 1},
'module-speed': {'assembler': -15, 'circuit-b': -5, 'circuit-a': -5, 'module-speed': 1},
# end-game
'rocket-control-unit': {'assembler': -30, 'circuit-c': -1, 'module-speed': -1, 'rocket-control-unit': 1},
'rocket-part': {
'rocket-silo': -3,
'low-density-structure': -10,
'rocket-control-unit': -10,
'rocket-fuel': -10,
'rocket-part': 1,
},
'sattelite': {
'assembler': -5,
'accumulator': -100,
'low-density-structure': -100,
'circuit-c': -100,
'radar': -5,
'rocket-fuel': -50,
'solar-panel': -100,
'sattelite': 1,
},
# science packs
'science-red': {'assembler': -5, 'copper-plate': -1, 'iron-gear': -1, 'science-red': 1},
'science-green': {'assembler': -6, 'belt-y': -1, 'inserter-y': -1, 'science-green': 1},
'science-gray': {'assembler': -10, 'magazine-r': -1, 'grenade': -1, 'wall': -2, 'science-gray': 2},
'science-blue': {'assembler': -24, 'sulfur': -1, 'circuit-b': -3, 'engine-unit': -2, 'science-blue': 2},
'science-purple': {
'assembler': -21,
'rail': -30,
'electric-furnace': -1,
'module-productivity': -1,
'science-purple': 3,
},
'science-yellow': {
'assembler': -21,
'circuit-c': -2,
'flying-robot-frame': -1,
'low-density-structure': -3,
'science-yellow': 3,
},
'science-white': {'rocket-part': -100, 'sattelite': -1, 'science-white': 1000},
}
def get_resource_name(orig_name: str, recipe_name: str) -> str:
if orig_name in {'assembler', 'chemical-plant', 'oil-refinery'}:
return f'{orig_name}[{recipe_name}]'
else:
return orig_name
def add_assembler_name(recipe_name: str, resources: dict[str, float]) -> dict[str, float]:
return {get_resource_name(resource, recipe_name): count for resource, count in resources.items()}
recipies = {name: add_assembler_name(name, resources) for name, resources in recipies.items()}
def add_recipe(targets: dict[str, float], recipe: dict[str, float], multiplier: float) -> dict[str, float]:
return {
resource: targets.get(resource, 0) - (multiplier * recipe.get(resource, 0))
for resource in targets.keys() | recipe.keys()
if targets.get(resource, 0) - (multiplier * recipe.get(resource, 0)) != 0
}
def compute_base_resource_flow(targets: dict[str, float], base_resources: set[str]) -> dict[str, float]:
results = {}
while len(targets) > 0:
resource, count = next(iter(targets.items()))
# print(f'{resource}: {count}')
if resource in base_resources or '[' in resource:
results = add_recipe(results, {resource: count}, -1)
del targets[resource]
continue
recipe = recipies[resource]
multiplier = count / recipe[resource]
targets = add_recipe(targets, recipe, multiplier)
return results
SPM = 1
targets_groups: list[dict[str, float]] = [
{'science-red': SPM},
{'science-green': SPM},
{'science-gray': SPM},
{'science-blue': SPM},
]
base_resources = {
'iron-plate',
'copper-plate',
'stone',
'stone-brick',
'coal',
'steel',
'sulfur',
'plastic',
}
# TODO: science-blue is wrong
print(f'{SPM=}')
print(f'{base_resources=}')
for targets in targets_groups:
print()
print(f'{targets=}')
results = compute_base_resource_flow(targets, base_resources)
for resource, count in sorted(results.items()):
print(f'{resource:30}: {count:.3g}')