clean up technology handling a bit

This commit is contained in:
Fabian Dill 2021-04-05 15:37:15 +02:00
parent 0eca0b2209
commit 635897574f
4 changed files with 50 additions and 43 deletions

View File

@ -142,7 +142,7 @@ async def factorio_server_watcher(ctx: FactorioContext):
while ctx.send_index < len(ctx.items_received):
item_id = ctx.items_received[ctx.send_index].item
if item_id not in lookup_id_to_name:
logging.error(f"Unknown item ID: {item_id}")
logging.error(f"Cannot send unknown item ID: {item_id}")
else:
item_name = lookup_id_to_name[item_id]
factorio_server_logger.info(f"Sending {item_name} to Nauvis.")

View File

@ -9,6 +9,7 @@ from .alttp.Items import lookup_id_to_name as alttp
from .hk.Items import lookup_id_to_name as hk
from .factorio import Technologies
lookup_any_item_id_to_name = {**alttp, **hk, **Technologies.lookup_id_to_name}
assert len(alttp) + len(hk) + len(Technologies.lookup_id_to_name) == len(lookup_any_item_id_to_name)
lookup_any_item_name_to_id = {name: id for id, name in lookup_any_item_id_to_name.items()}
@ -16,6 +17,8 @@ from .alttp import Regions
from .hk import Locations
lookup_any_location_id_to_name = {**Regions.lookup_id_to_name, **Locations.lookup_id_to_name,
**Technologies.lookup_id_to_name}
assert len(Regions.lookup_id_to_name) + len(Locations.lookup_id_to_name) + len(Technologies.lookup_id_to_name) == \
len(lookup_any_location_id_to_name)
lookup_any_location_name_to_id = {name: id for id, name in lookup_any_location_id_to_name.items()}

View File

@ -1,44 +1,58 @@
# Factorio technologies are imported from a .json document in /data
from typing import Dict
import os
from typing import Dict, Set
import json
import Utils
factorio_id = 2**17
factorio_id = 2 ** 17
source_file = Utils.local_path("data", "factorio", "techs.json")
with open(source_file) as f:
raw = json.load(f)
tech_table = {}
technology_table = {}
requirements = {} # tech_name -> Set[required_technologies]
requirements = {}
ingredients = {}
all_ingredients = set()
# TODO: export this dynamically, or filter it during export
starting_ingredient_recipes = {"automation-science-pack"}
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:
if ingredient in recipe_sources: # no source likely means starting item
requirements |= recipe_sources[ingredient] # technically any, not all, need to improve later
return requirements
def __hash__(self):
return self.factorio_id
# recipes and technologies can share names in Factorio
for technology in sorted(raw):
data = raw[technology]
tech_table[technology] = factorio_id
factorio_id += 1
if data["requires"]:
requirements[technology] = set(data["requires"])
current_ingredients = set(data["ingredients"])-starting_ingredient_recipes
if current_ingredients:
all_ingredients |= current_ingredients
ingredients[technology] = {"recipe-"+ingredient for ingredient in current_ingredients}
for technology_name in sorted(raw):
data = raw[technology_name]
recipe_sources = {}
factorio_id += 1
# 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
recipe_sources = {} # recipe_name -> technology source
for technology, data in raw.items():
recipe_source = all_ingredients & set(data["unlocks"])
for recipe in recipe_source:
recipe_sources["recipe-"+recipe] = technology
for recipe in data["unlocks"]:
recipe_sources.setdefault(recipe, set()).add(technology)
all_ingredients_recipe = {"recipe-"+ingredient for ingredient in all_ingredients}
del(raw)
lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()}
del (raw)
lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()}

View File

@ -2,7 +2,7 @@ import logging
from BaseClasses import Region, Entrance, Location, MultiWorld, Item
from .Technologies import tech_table, requirements, ingredients, all_ingredients, recipe_sources, all_ingredients_recipe
from .Technologies import tech_table, requirements, recipe_sources, technology_table
static_nodes = {"automation", "logistics"}
@ -30,11 +30,6 @@ def factorio_create_regions(world: MultiWorld, player: int):
tech = Location(player, tech_name, tech_id, nauvis)
nauvis.locations.append(tech)
tech.game = "Factorio"
for ingredient in all_ingredients_recipe: # register science packs as events
ingredient_location = Location(player, ingredient, 0, nauvis)
ingredient_location.item = Item(ingredient, True, 0, player)
ingredient_location.event = ingredient_location.locked = True
menu.locations.append(ingredient_location)
crash.connect(nauvis)
world.regions += [menu, nauvis]
@ -42,18 +37,13 @@ def factorio_create_regions(world: MultiWorld, player: int):
def set_rules(world: MultiWorld, player: int):
if world.logic[player] != 'nologic':
from worlds.generic import Rules
for tech_name in tech_table:
# vanilla layout, to be implemented
# rules = requirements.get(tech_name, set()) | ingredients.get(tech_name, set())
for tech_name, technology in technology_table.items():
# loose nodes
rules = ingredients.get(tech_name, set())
rules = technology.get_required_technologies()
if rules:
location = world.get_location(tech_name, player)
Rules.set_rule(location, lambda state, rules=rules: all(state.has(rule, player) for rule in rules))
for recipe, technology in recipe_sources.items():
Rules.set_rule(world.get_location(recipe, player), lambda state, tech=technology: state.has(tech, player))
world.completion_condition[player] = lambda state: all(state.has(ingredient, player)
for ingredient in all_ingredients_recipe)
# get all technologies
world.completion_condition[player] = lambda state: all(state.has(technology, player)
for technology in tech_table)