Factorio: cleanup and optimize some requirement graph functions

This commit is contained in:
Fabian Dill 2021-11-26 02:37:15 +01:00
parent 383d0f1a66
commit 8af5855af6
2 changed files with 23 additions and 21 deletions

View File

@ -131,6 +131,7 @@ class Recipe(FactorioElement):
base = {technology_table[tech_name] for tech_name in recipe_sources.get(self.name, ())}
for ingredient in self.ingredients:
base |= required_technologies[ingredient]
base |= required_technologies[self.crafting_machine]
return base
@property
@ -472,7 +473,7 @@ def get_science_pack_pools() -> Dict[str, Set[str]]:
cost += rel_cost.get(ingredient_name, 1) * amount
return cost
science_pack_pools = {}
science_pack_pools: Dict[str, Set[str]] = {}
already_taken = blacklist.copy()
current_difficulty = 5
for science_pack in Options.MaxSciencePack.get_ordered_science_packs():
@ -483,7 +484,8 @@ def get_science_pack_pools() -> Dict[str, Set[str]]:
current |= set(recipe.products)
if science_pack == "automation-science-pack":
current |= {"iron-ore", "copper-ore", "coal", "stone"}
current -= liquids # Can't hand craft automation science if liquids end up in its recipe, making the seed impossible.
# Can't hand craft automation science if liquids end up in its recipe, making the seed impossible.
current -= liquids
elif science_pack == "logistic-science-pack":
current |= {"steam"}
current -= already_taken

View File

@ -184,7 +184,8 @@ class Factorio(World):
for recipe in world.worlds[player].custom_recipes.values():
spoiler_handle.write(f"\n{recipe.name} ({name}): {recipe.ingredients} -> {recipe.products}")
def make_balanced_recipe(self, original: Recipe, pool: list, factor: float = 1) -> Recipe:
def make_balanced_recipe(self, original: Recipe, pool: list, factor: float = 1, allow_liquids: int = 2) -> \
Recipe:
"""Generate a recipe from pool with time and cost similar to original * factor"""
new_ingredients = {}
self.world.random.shuffle(pool)
@ -200,6 +201,17 @@ class Factorio(World):
# fill all but one slot with random ingredients, last with a good match
while remaining_num_ingredients > 0 and pool:
ingredient = pool.pop()
if liquids_used == allow_liquids and ingredient in liquids:
continue # can't use this ingredient as we already have maximum liquid in our recipe.
if ingredient in all_product_sources:
ingredient_recipe = min(all_product_sources[ingredient], key=lambda recipe: recipe.rel_cost)
ingredient_raw = sum((count for ingredient, count in ingredient_recipe.base_cost.items()))
ingredient_energy = ingredient_recipe.total_energy
else:
# assume simple ore TODO: remove if tree when mining data is harvested from Factorio
ingredient_raw = 1
ingredient_energy = 2
if remaining_num_ingredients == 1:
max_raw = 1.1 * remaining_raw
min_raw = 0.9 * remaining_raw
@ -210,15 +222,6 @@ class Factorio(World):
min_raw = (remaining_raw - max_raw) / remaining_num_ingredients
max_energy = remaining_energy * 0.75
min_energy = (remaining_energy - max_energy) / remaining_num_ingredients
ingredient = pool.pop()
if ingredient in all_product_sources:
ingredient_recipe = min(all_product_sources[ingredient], key=lambda recipe: recipe.rel_cost)
ingredient_raw = sum((count for ingredient, count in ingredient_recipe.base_cost.items()))
ingredient_energy = ingredient_recipe.total_energy
else:
# assume simple ore TODO: remove if tree when mining data is harvested from Factorio
ingredient_raw = 1
ingredient_energy = 2
min_num_raw = min_raw / ingredient_raw
max_num_raw = max_raw / ingredient_raw
min_num_energy = min_energy / ingredient_energy
@ -228,8 +231,6 @@ class Factorio(World):
if min_num > max_num:
fallback_pool.append(ingredient)
continue # can't use that ingredient
if liquids_used == 2 and ingredient in liquids:
continue # can't use this ingredient as we already have a liquid in our recipe.
num = self.world.random.randint(min_num, max_num)
new_ingredients[ingredient] = num
remaining_raw -= num * ingredient_raw
@ -246,6 +247,9 @@ class Factorio(World):
pool = fallback_pool
while remaining_num_ingredients > 0 and pool:
ingredient = pool.pop()
if liquids_used == allow_liquids and ingredient in liquids:
continue # can't use this ingredient as we already have maximum liquid in our recipe.
ingredient_recipe = recipes.get(ingredient, None)
if not ingredient_recipe and ingredient.endswith("-barrel"):
ingredient_recipe = recipes.get(f"fill-{ingredient}", None)
@ -257,9 +261,9 @@ class Factorio(World):
num_raw = remaining_raw / ingredient_raw / remaining_num_ingredients
num_energy = remaining_energy / ingredient_energy / remaining_num_ingredients
num = int(min(num_raw, num_energy))
if num < 1: continue
if liquids_used == 2 and ingredient in liquids:
continue # can't use this ingredient as we already have a liquid in our recipe.
if num < 1:
continue
new_ingredients[ingredient] = num
remaining_raw -= num * ingredient_raw
remaining_energy -= num * ingredient_energy
@ -343,12 +347,8 @@ class Factorio(World):
if self.world.max_science_pack[self.player].value == MaxSciencePack.option_space_science_pack:
needed_recipes |= {"satellite"}
if any([recipe.category == "chemistry" for _, recipe in self.custom_recipes.items()]):
needed_recipes |= {"chemical-plant"}
for recipe in needed_recipes:
recipe = self.custom_recipes.get(recipe, recipes[recipe])
self.advancement_technologies |= {tech.name for tech in recipe.unlocking_technologies}
self.advancement_technologies |= {tech.name for tech in recipe.recursive_unlocking_technologies}
# handle marking progressive techs as advancement