2021-04-01 09:40:58 +00:00
|
|
|
# Factorio technologies are imported from a .json document in /data
|
2021-04-05 13:37:15 +00:00
|
|
|
from typing import Dict, Set
|
2021-04-01 09:40:58 +00:00
|
|
|
import json
|
|
|
|
import Utils
|
|
|
|
|
2021-04-05 13:37:15 +00:00
|
|
|
factorio_id = 2 ** 17
|
2021-04-01 09:40:58 +00:00
|
|
|
|
|
|
|
source_file = Utils.local_path("data", "factorio", "techs.json")
|
2021-04-08 17:53:24 +00:00
|
|
|
recipe_source_file = Utils.local_path("data", "factorio", "recipes.json")
|
2021-04-01 09:40:58 +00:00
|
|
|
with open(source_file) as f:
|
|
|
|
raw = json.load(f)
|
2021-04-08 17:53:24 +00:00
|
|
|
with open(recipe_source_file) as f:
|
|
|
|
raw_recipes = json.load(f)
|
2021-04-01 09:40:58 +00:00
|
|
|
tech_table = {}
|
2021-04-05 13:37:15 +00:00
|
|
|
technology_table = {}
|
|
|
|
|
|
|
|
|
|
|
|
class Technology(): # maybe make subclass of Location?
|
|
|
|
def __init__(self, name, ingredients):
|
|
|
|
self.name = name
|
|
|
|
global factorio_id
|
|
|
|
self.factorio_id = factorio_id
|
|
|
|
factorio_id += 1
|
|
|
|
self.ingredients = ingredients
|
|
|
|
|
|
|
|
def get_required_technologies(self):
|
|
|
|
requirements = set()
|
|
|
|
for ingredient in self.ingredients:
|
2021-04-08 17:53:24 +00:00
|
|
|
if ingredient in recipe_sources: # no source likely means starting item
|
|
|
|
requirements |= recipe_sources[ingredient] # technically any, not all, need to improve later
|
2021-04-05 13:37:15 +00:00
|
|
|
return requirements
|
2021-04-01 09:40:58 +00:00
|
|
|
|
2021-04-08 17:53:24 +00:00
|
|
|
def build_rule(self):
|
|
|
|
ingredient_rules = []
|
|
|
|
for ingredient in self.ingredients:
|
|
|
|
if ingredient in recipe_sources:
|
|
|
|
technologies = recipe_sources[ingredient] # technologies that unlock the recipe
|
|
|
|
ingredient_rules.append(lambda state, technologies=technologies: any(state.has(technology) for technology in technologies))
|
|
|
|
ingredient_rules = frozenset(ingredient_rules)
|
|
|
|
return lambda state: all(rule(state) for rule in ingredient_rules)
|
|
|
|
|
2021-04-05 13:37:15 +00:00
|
|
|
def __hash__(self):
|
|
|
|
return self.factorio_id
|
2021-04-01 09:40:58 +00:00
|
|
|
|
2021-04-08 17:53:24 +00:00
|
|
|
class Recipe():
|
|
|
|
def __init__(self, name, category, ingredients, products):
|
|
|
|
self.name = name
|
|
|
|
self.category = category
|
|
|
|
self.products = ingredients
|
|
|
|
self.ingredients = products
|
2021-04-01 09:40:58 +00:00
|
|
|
|
|
|
|
# recipes and technologies can share names in Factorio
|
2021-04-05 13:37:15 +00:00
|
|
|
for technology_name in sorted(raw):
|
|
|
|
data = raw[technology_name]
|
|
|
|
|
2021-04-01 09:40:58 +00:00
|
|
|
factorio_id += 1
|
2021-04-05 13:37:15 +00:00
|
|
|
# not used yet
|
|
|
|
# if data["requires"]:
|
|
|
|
# requirements[technology] = set(data["requires"])
|
|
|
|
current_ingredients = set(data["ingredients"])
|
|
|
|
technology = Technology(technology_name, current_ingredients)
|
|
|
|
tech_table[technology_name] = technology.factorio_id
|
|
|
|
technology_table[technology_name] = technology
|
|
|
|
|
2021-04-01 09:40:58 +00:00
|
|
|
|
2021-04-05 13:37:15 +00:00
|
|
|
recipe_sources = {} # recipe_name -> technology source
|
2021-04-01 09:40:58 +00:00
|
|
|
|
|
|
|
for technology, data in raw.items():
|
2021-04-05 13:37:15 +00:00
|
|
|
for recipe in data["unlocks"]:
|
|
|
|
recipe_sources.setdefault(recipe, set()).add(technology)
|
|
|
|
|
2021-04-01 09:40:58 +00:00
|
|
|
|
2021-04-05 13:37:15 +00:00
|
|
|
del (raw)
|
|
|
|
lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()}
|
2021-04-08 17:53:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
all_recipes = set()
|
|
|
|
for recipe_name, recipe_data in raw_recipes.items():
|
|
|
|
# example:
|
|
|
|
# "accumulator":{"ingredients":["iron-plate","battery"],"products":["accumulator"],"category":"crafting"}
|
|
|
|
all_recipes.add(Recipe(recipe_name, recipe_data["category"], set(recipe_data["ingredients"]), set(recipe_data["products"])))
|