Implemented random Tier 0

This commit is contained in:
Jarno Westhof
2025-04-13 00:16:48 +02:00
parent 86971adc49
commit c8309b2acd
5 changed files with 135 additions and 59 deletions

View File

@@ -23,6 +23,7 @@ class CriticalPathCalculator:
implicitly_unlocked: set[str]
handcraftable_parts: dict[str, list[Recipe]]
tier_0_recipes: set[str]
def __init__(self, logic: GameLogic, random: Random, options: SatisfactoryOptions):
self.logic = logic
@@ -35,9 +36,6 @@ class CriticalPathCalculator:
self.__potential_required_belt_speed = 1
selected_power_infrastructure: dict[int, Recipe] = {}
self.configure_implicitly_unlocked_and_handcraftable_parts()
self.select_minimal_required_parts_for(self.logic.space_elevator_tiers[options.final_elevator_package-1].keys())
@@ -75,7 +73,6 @@ class CriticalPathCalculator:
for i in range(1, self.required_power_level + 1):
power_recipe = random.choice(self.logic.requirement_per_powerlevel[i])
selected_power_infrastructure[i] = power_recipe
self.select_minimal_required_parts_for(power_recipe.inputs)
self.select_minimal_required_parts_for_building(power_recipe.building)
@@ -88,6 +85,7 @@ class CriticalPathCalculator:
self.required_item_names.update({"Building: "+ building for building in self.required_buildings})
self.calculate_excluded_things()
self.select_starter_recipes()
def select_minimal_required_parts_for_building(self, building: str) -> None:
@@ -190,7 +188,84 @@ class CriticalPathCalculator:
if recipe.handcraftable:
self.handcraftable_parts.setdefault(part, []).append(recipe)
if self.options.randomize_tier_0:
pass
#decide what to re-randomize, like smelter / iron ingot etc
#self.implicitly_unlocked.remove("")
def select_starter_recipes(self) -> None:
# cable is left unaffected as all its alternative recipes require refinery
if not self.options.randomize_starter_recipes:
self.tier_0_recipes = {
"Recipe: Iron Ingot",
"Recipe: Iron Plate",
"Recipe: Iron Rod",
"Recipe: Copper Ingot",
"Recipe: Wire",
"Recipe: Concrete",
"Recipe: Screw",
"Recipe: Reinforced Iron Plate"
}
else:
# we only allow basic parts to be made without the need of refineries
# could be made more based of GameLogic rather than hardcoded but this is likely faster
# would likely need to be based of GameLogic when we add mod support
self.tier_0_recipes = set()
self.tier_0_recipes.add(self.random.choice(
("Recipe: Iron Ingot", "Recipe: Basic Iron Ingot", "Recipe: Iron Alloy Ingot")))
selected_recipe = self.random.choice(("Recipe: Iron Plate", "Recipe: Steel Cast Plate"))
self.tier_0_recipes.add(selected_recipe)
if selected_recipe == "Recipe: Steel Cast Plate":
self.add_steel_ingot_to_starter_recipes()
selected_recipe = self.random.choice(("Recipe: Iron Rod", "Recipe: Steel Rod"))
self.tier_0_recipes.add(selected_recipe)
if selected_recipe == "Recipe: Steel Rod":
self.add_steel_ingot_to_starter_recipes()
self.tier_0_recipes.add(self.random.choice(("Recipe: Copper Ingot", "Recipe: Copper Alloy Ingot")))
selected_recipe = self.random.choice(
("Recipe: Wire", "Recipe: Caterium Wire", "Recipe: Fused Wire", "Recipe: Iron Wire"))
self.tier_0_recipes.add(selected_recipe)
if selected_recipe in {"Recipe: Caterium Wire", "Recipe: Fused Wire"}:
# add Caterium Ingot
self.tier_0_recipes.add("Recipe: Caterium Ingot")
selected_recipe = self.random.choice(("Recipe: Concrete", "Recipe: Fine Concrete"))
self.tier_0_recipes.add(selected_recipe)
if selected_recipe == "Recipe: Fine Concrete":
# add Silica
self.tier_0_recipes.add(self.random.choice(("Recipe: Silica", "Recipe: Cheap Silica")))
selected_recipe = self.random.choice(("Recipe: Screw", "Recipe: Cast Screw", "Recipe: Steel Screw"))
self.tier_0_recipes.add(selected_recipe)
if selected_recipe == "Recipe: Steel Screw":
# add Steel Beam and steel Ingot
self.add_steel_ingot_to_starter_recipes()
self.tier_0_recipes.add(self.random.choice(("Recipe: Steel Beam", "Recipe: Molded Beam")))
self.tier_0_recipes.add(self.random.choice(
("Recipe: Reinforced Iron Plate", "Recipe: Bolted Iron Plate", "Recipe: Stitched Iron Plate")))
for part, recipes in self.logic.recipes.items():
for recipe in recipes:
if recipe.name in self.tier_0_recipes:
if part in self.handcraftable_parts:
self.handcraftable_parts[part].append(recipe)
else:
self.handcraftable_parts[part] = [recipe]
self.tier_0_recipes.add(self.logic.buildings[recipe.building].name)
self.implicitly_unlocked.update(self.tier_0_recipes)
def add_steel_ingot_to_starter_recipes(self) -> None:
if "Recipe: Steel Ingot" not in self.tier_0_recipes \
and "Recipe: Compacted Steel Ingot" not in self.tier_0_recipes \
and "Recipe: Solid Steel Ingot" not in self.tier_0_recipes:
selected_recipe = self.random.choice(
("Recipe: Steel Ingot", "Recipe: Compacted Steel Ingot", "Recipe: Solid Steel Ingot"))
self.tier_0_recipes.add(selected_recipe)
if selected_recipe == "Recipe: Compacted Steel Ingot":
self.tier_0_recipes.add("Recipe: Compacted Coal")

View File

@@ -205,7 +205,7 @@ class GameLogic:
# Recipes
"Reinforced Iron Plate": (
Recipe("Reinforced Iron Plate", "Assembler", ("Iron Plate", "Screw"), handcraftable=True, implicitly_unlocked=True),
Recipe("Reinforced Iron Plate", "Assembler", ("Iron Plate", "Screw")),
Recipe("Adhered Iron Plate", "Assembler", ("Iron Plate", "Rubber")),
Recipe("Bolted Iron Plate", "Assembler", ("Iron Plate", "Screw"), minimal_belt_speed=3),
Recipe("Stitched Iron Plate", "Assembler", ("Iron Plate", "Wire"))),
@@ -225,19 +225,19 @@ class GameLogic:
Recipe("Residual Rubber", "Refinery", ("Polymer Resin", "Water")),
Recipe("Recycled Rubber", "Refinery", ("Plastic", "Fuel"))),
"Iron Plate": (
Recipe("Iron Plate", "Constructor", ("Iron Ingot", ), handcraftable=True, implicitly_unlocked=True),
Recipe("Iron Plate", "Constructor", ("Iron Ingot", )),
Recipe("Coated Iron Plate", "Assembler", ("Iron Ingot", "Plastic"), minimal_belt_speed=2),
Recipe("Steel Cast Plate", "Foundry", ("Iron Ingot", "Steel Ingot"))),
"Iron Rod": (
Recipe("Iron Rod", "Constructor", ("Iron Ingot", ), handcraftable=True, implicitly_unlocked=True),
Recipe("Iron Rod", "Constructor", ("Iron Ingot", )),
Recipe("Steel Rod", "Constructor", ("Steel Ingot", )),
Recipe("Aluminum Rod", "Constructor", ("Aluminum Ingot", ))),
"Screw": (
Recipe("Screw", "Constructor", ("Iron Rod", ), handcraftable=True, implicitly_unlocked=True),
Recipe("Screw", "Constructor", ("Iron Rod", )),
Recipe("Cast Screw", "Constructor", ("Iron Ingot", )),
Recipe("Steel Screw", "Constructor", ("Steel Beam", ), minimal_belt_speed=3)),
"Wire": (
Recipe("Wire", "Constructor", ("Copper Ingot", ), handcraftable=True, implicitly_unlocked=True),
Recipe("Wire", "Constructor", ("Copper Ingot", )),
Recipe("Fused Wire", "Assembler", ("Copper Ingot", "Caterium Ingot"), minimal_belt_speed=2),
Recipe("Iron Wire", "Constructor", ("Iron Ingot", )),
Recipe("Caterium Wire", "Constructor", ("Caterium Ingot", ), minimal_belt_speed=2)),
@@ -274,7 +274,7 @@ class GameLogic:
Recipe("Diluted Fuel", "Blender", ("Heavy Oil Residue", "Water"), minimal_tier=2),
Recipe("Residual Fuel", "Refinery", ("Heavy Oil Residue", ))),
"Concrete": (
Recipe("Concrete", "Constructor", ("Limestone", ), handcraftable=True, implicitly_unlocked=True),
Recipe("Concrete", "Constructor", ("Limestone", )),
Recipe("Fine Concrete", "Assembler", ("Limestone", "Silica")),
Recipe("Rubber Concrete", "Assembler", ("Limestone", "Rubber")),
Recipe("Wet Concrete", "Refinery", ("Limestone", "Water"), minimal_belt_speed=2)),
@@ -291,7 +291,7 @@ class GameLogic:
Recipe("Fused Quartz Crystal", "Foundry", ("Raw Quartz", "Coal"), minimal_belt_speed=2),
Recipe("Quartz Purification", "Refinery", ("Raw Quartz", "Nitric Acid"), additional_outputs=("Dissolved Silica", ), minimal_belt_speed=2, minimal_tier=2)),
"Iron Ingot": (
Recipe("Iron Ingot", "Smelter", ("Iron Ore", ), handcraftable=True, implicitly_unlocked=True),
Recipe("Iron Ingot", "Smelter", ("Iron Ore", )),
Recipe("Pure Iron Ingot", "Refinery", ("Iron Ore", "Water"), minimal_belt_speed=2),
Recipe("Iron Alloy Ingot", "Foundry", ("Iron Ore", "Copper Ore")),
Recipe("Basic Iron Ingot", "Foundry", ("Iron Ore", "Limestone")),
@@ -302,7 +302,7 @@ class GameLogic:
Recipe("Compacted Steel Ingot", "Foundry", ("Iron Ore", "Compacted Coal")),
Recipe("Solid Steel Ingot", "Foundry", ("Iron Ingot", "Coal"))),
"Copper Ingot": (
Recipe("Copper Ingot", "Smelter", ("Copper Ore", ), handcraftable=True, implicitly_unlocked=True),
Recipe("Copper Ingot", "Smelter", ("Copper Ore", )),
Recipe("Copper Alloy Ingot", "Foundry", ("Copper Ore", "Iron Ore"), minimal_belt_speed=2),
Recipe("Pure Copper Ingot", "Refinery", ("Copper Ore", "Water")),
Recipe("Leached Copper Ingot", "Refinery", ("Copper Ore", "Sulfuric Acid"), minimal_belt_speed=2),
@@ -580,7 +580,7 @@ class GameLogic:
}
buildings: dict[str, Building] = {
"Constructor": Building("Constructor", ("Reinforced Iron Plate", "Cable"), PowerInfrastructureLevel.Basic, implicitly_unlocked=True),
"Constructor": Building("Constructor", ("Reinforced Iron Plate", "Cable"), PowerInfrastructureLevel.Basic),
"Assembler": Building("Assembler", ("Reinforced Iron Plate", "Rotor", "Cable"), PowerInfrastructureLevel.Basic),
"Manufacturer": Building("Manufacturer", ("Motor", "Heavy Modular Frame", "Cable", "Plastic"), PowerInfrastructureLevel.Advanced),
"Packager": Building("Packager", ("Steel Beam", "Rubber", "Plastic"), PowerInfrastructureLevel.Basic),
@@ -597,7 +597,7 @@ class GameLogic:
"Miner Mk.3": Building("Miner Mk.3", ("Steel Pipe", "Supercomputer", "Fused Modular Frame", "Turbo Motor"), PowerInfrastructureLevel.Advanced, can_produce=False),
"Oil Extractor": Building("Oil Extractor", ("Motor", "Encased Industrial Beam", "Cable")),
"Water Extractor": Building("Water Extractor", ("Copper Sheet", "Reinforced Iron Plate", "Rotor")),
"Smelter": Building("Smelter", ("Iron Rod", "Wire"), PowerInfrastructureLevel.Basic, implicitly_unlocked=True),
"Smelter": Building("Smelter", ("Iron Rod", "Wire"), PowerInfrastructureLevel.Basic),
"Foundry": Building("Foundry", ("Modular Frame", "Rotor", "Concrete"), PowerInfrastructureLevel.Basic),
"Resource Well Pressurizer": Building("Resource Well Pressurizer", ("Wire", "Rubber", "Encased Industrial Beam", "Motor", "Steel Beam", "Plastic"), PowerInfrastructureLevel.Advanced),
"Equipment Workshop": Building("Equipment Workshop", ("Iron Plate", "Iron Rod"), implicitly_unlocked=True),
@@ -744,20 +744,20 @@ class GameLogic:
MamNode("Hostile Organism Detection", {"Alien DNA Capsule":10,"Crystal Oscillator":5,"High-Speed Connector":5,}, depends_on=("Bio-Organic Properties", )), #(Research_AOrganisms_2_C)
MamNode("Expanded Toolbelt", {"Alien DNA Capsule":5,"Steel Beam":500,}, depends_on=("Inflated Pocket Dimension", )), #(Research_ACarapace_3_C)
MamNode("Bio-Organic Properties", {"Alien Protein":5,}, depends_on=("Spitter Research", "Hog Research", "Hatcher Research", "Stinger Research")), #(Research_AO_DNACapsule_C)
MamNode("Stinger Research", {"Stinger Remains":1,}, depends_on=()), #(Research_AO_Stinger_C)
MamNode("Hatcher Research", {"Hatcher Remains":1,}, depends_on=()), #(Research_AO_Hatcher_C)
MamNode("Hog Research", {"Hog Remains":1,}, depends_on=()), #(Research_ACarapace_0_C)
MamNode("Spitter Research", {"Plasma Spitter Remains":1,}, depends_on=()), #(Research_AOrgans_0_C)
MamNode("Stinger Research", {"Stinger Remains":1,}, depends_on=tuple()), #(Research_AO_Stinger_C)
MamNode("Hatcher Research", {"Hatcher Remains":1,}, depends_on=tuple()), #(Research_AO_Hatcher_C)
MamNode("Hog Research", {"Hog Remains":1,}, depends_on=tuple()), #(Research_ACarapace_0_C)
MamNode("Spitter Research", {"Plasma Spitter Remains":1,}, depends_on=tuple()), #(Research_AOrgans_0_C)
MamNode("Structural Analysis", {"Alien DNA Capsule":5,"Iron Rod":100,}, depends_on=("Bio-Organic Properties", )), #(Research_AO_Pre_Rebar_C)
MamNode("Protein Inhaler", {"Alien Protein":2,"Beryl Nut":20,"Rotor":50,}, depends_on=("Bio-Organic Properties", )), #(Research_AOrgans_2_C)
MamNode("The Rebar Gun", {"Rotor":25,"Reinforced Iron Plate":50,"Screw":500,}, depends_on=("Structural Analysis", )), #(Research_ACarapace_2_C)
)),
# 1.0
"Alien Technology": MamTree(("SAM", "Mercer Sphere", "Somersloop"), (
MamNode("SAM Analysis", {"SAM":10,}, depends_on=()),
MamNode("SAM Analysis", {"SAM":10,}, depends_on=tuple()),
MamNode("SAM Reanimation", {"SAM":20,}, depends_on=("SAM Analysis",)),
MamNode("SAM Fluctuator", {"Reanimated SAM":10,"Steel Pipe":100,"Wire":200,}, depends_on=("SAM Reanimation",)),
MamNode("Mercer Sphere Analysis", {"Mercer Sphere":1,}, depends_on=()),
MamNode("Mercer Sphere Analysis", {"Mercer Sphere":1,}, depends_on=tuple()),
MamNode("Dimensional Depot", {"Mercer Sphere":1,"SAM Fluctuator":11,}, depends_on=("Mercer Sphere Analysis", "SAM Fluctuator")),
MamNode("Manual Depot Uploader", {"Mercer Sphere":3,"Computer":17,"SAM Fluctuator":19,}, depends_on=("Dimensional Depot",)),
MamNode("Depot Expansion (200%)", {"Mercer Sphere":3,"SAM Fluctuator":47,}, depends_on=("Dimensional Depot",)),
@@ -768,7 +768,7 @@ class GameLogic:
MamNode("Upload Upgrade: 60/min", {"Mercer Sphere":7,"SAM Fluctuator":103,}, depends_on=("Upload Upgrade: 30/min",)),
MamNode("Upload Upgrade: 120/min", {"Mercer Sphere":13,"SAM Fluctuator":151,}, depends_on=("Upload Upgrade: 60/min",)),
MamNode("Upload Upgrade: 240/min", {"Mercer Sphere":23,"SAM Fluctuator":199,}, depends_on=("Upload Upgrade: 120/min",)),
MamNode("Somersloop Analysis", {"Somersloop":1,}, depends_on=()),
MamNode("Somersloop Analysis", {"Somersloop":1,}, depends_on=tuple()),
MamNode("Alien Energy Harvesting", {"SAM Fluctuator":10,}, depends_on=("Somersloop Analysis", "SAM Fluctuator")),
MamNode("Production Amplifier", {"Somersloop":1,"SAM Fluctuator":100,"Circuit Board":50,}, depends_on=("Alien Energy Harvesting",)),
MamNode("Power Augmenter", {"Somersloop":1,"SAM Fluctuator":100,"Computer":50,}, depends_on=("Alien Energy Harvesting",)),
@@ -779,7 +779,7 @@ class GameLogic:
MamNode("Caterium Electronics", {"Quickwire":100,}, depends_on=("Quickwire", )), #(Research_Caterium_3_C)
MamNode("Bullet Guidance System", {"High-Speed Connector":10,"Rifle Ammo":500,}, depends_on=("High-Speed Connector", )), #(Research_Caterium_6_3_C)
MamNode("High-Speed Connector", {"Quickwire":500,"Plastic":50,}, depends_on=("Caterium Electronics", )), #(Research_Caterium_5_C)
MamNode("Caterium", {"Caterium Ore":10,}, depends_on=()), #(Research_Caterium_0_C)
MamNode("Caterium", {"Caterium Ore":10,}, depends_on=tuple()), #(Research_Caterium_0_C)
MamNode("Caterium Ingots", {"Caterium Ore":50,}, depends_on=("Caterium", )), #(Research_Caterium_1_C)
MamNode("Quickwire", {"Caterium Ingot":50,}, depends_on=("Caterium Ingots", )), #(Research_Caterium_2_C)
MamNode("Power Switch", {"Steel Beam":100,"AI Limiter":50,}, depends_on=("AI Limiter", )), #(Research_Caterium_4_1_2_C)
@@ -806,15 +806,15 @@ class GameLogic:
MamNode("Gas Mask", {"Coal":10,"Fabric":50,"Steel Pipe":50}, depends_on=("Fabric", )), # 1.0
)),
"Nutrients": MamTree(("Paleberry", "Beryl Nut", "Bacon Agaric"), ( # Nutrients (BPD_ResearchTree_Nutrients_C)
MamNode("Bacon Agaric", {"Bacon Agaric":1,}, depends_on=()), #(Research_Nutrients_2_C)
MamNode("Beryl Nut", {"Beryl Nut":5,}, depends_on=()), #(Research_Nutrients_1_C)
MamNode("Paleberry", {"Paleberry":2,}, depends_on=()), #(Research_Nutrients_0_C)
MamNode("Bacon Agaric", {"Bacon Agaric":1,}, depends_on=tuple()), #(Research_Nutrients_2_C)
MamNode("Beryl Nut", {"Beryl Nut":5,}, depends_on=tuple()), #(Research_Nutrients_1_C)
MamNode("Paleberry", {"Paleberry":2,}, depends_on=tuple()), #(Research_Nutrients_0_C)
MamNode("Nutritional Processor", {"Modular Frame":25,"Steel Pipe":50,"Wire":500,}, depends_on=("Beryl Nut", "Bacon Agaric", "Paleberry")), #(Research_Nutrients_3_C)
MamNode("Nutritional Inhaler", {"Bacon Agaric":2,"Paleberry":4,"Beryl Nut":10,}, depends_on=("Nutritional Processor", )), #(Research_Nutrients_4_C)
)),
"Power Slugs": MamTree(("Blue Power Slug", ), ( # Power Slugs (BPD_ResearchTree_PowerSlugs_C)
MamNode("Slug Scanning", {"Iron Rod":50,"Wire":100,"Screw":200,}, depends_on=("Blue Power Slugs", )), #(Research_PowerSlugs_3_C)
MamNode("Blue Power Slugs", {"Blue Power Slug":1,}, depends_on=()), #(Research_PowerSlugs_1_C)
MamNode("Blue Power Slugs", {"Blue Power Slug":1,}, depends_on=tuple()), #(Research_PowerSlugs_1_C)
MamNode("Yellow Power Shards", {"Yellow Power Slug":1,"Rotor":25,"Cable":100,}, depends_on=("Blue Power Slugs", )), #(Research_PowerSlugs_4_C)
MamNode("Purple Power Shards", {"Purple Power Slug":1,"Modular Frame":25,"Copper Sheet":100,}, depends_on=("Yellow Power Shards", )), #(Research_PowerSlugs_5_C)
MamNode("Overclock Production", {"Power Shard":1,"Iron Plate":50,"Wire":50,}, depends_on=("Blue Power Slugs", )), #(Research_PowerSlugs_2_C)
@@ -823,7 +823,7 @@ class GameLogic:
"Quartz": MamTree(("Raw Quartz", ), ( # Quartz (BPD_ResearchTree_Quartz_C)
MamNode("Crystal Oscillator", {"Quartz Crystal":100,"Reinforced Iron Plate":50,}, depends_on=("Quartz Crystals", )), #(Research_Quartz_2_C)
MamNode("Quartz Crystals", {"Raw Quartz":20,}, depends_on=("Quartz", )), #(Research_Quartz_1_1_C)
MamNode("Quartz", {"Raw Quartz":10,}, depends_on=()), #(Research_Quartz_0_C)
MamNode("Quartz", {"Raw Quartz":10,}, depends_on=tuple()), #(Research_Quartz_0_C)
MamNode("Shatter Rebar", {"Quartz Crystal":30,"Iron Rebar":150,}, depends_on=("Quartz Crystals", )), #(Research_Quartz_2_1_C)
MamNode("Silica", {"Raw Quartz":20,}, depends_on=("Quartz", )), #(Research_Quartz_1_2_C)
MamNode("Explosive Resonance Application", {"Crystal Oscillator":5,"Nobelisk":100,}, depends_on=("Crystal Oscillator", )), #(Research_Quartz_3_4_C)
@@ -837,7 +837,7 @@ class GameLogic:
"Sulfur": MamTree(("Sulfur", ), ( # Sulfur (BPD_ResearchTree_Sulfur_C)
MamNode("The Nobelisk Detonator", {"Black Powder":50,"Steel Pipe":100,"Cable":200,}, depends_on=("Black Powder", )), #(Research_Sulfur_3_1_C)
MamNode("Smokeless Powder", {"Black Powder":100,"Plastic":50,}, depends_on=("Black Powder", )), #(Research_Sulfur_3_C)
MamNode("Sulfur", {"Sulfur":10,}, depends_on=()), #(Research_Sulfur_0_C)
MamNode("Sulfur", {"Sulfur":10,}, depends_on=tuple()), #(Research_Sulfur_0_C)
MamNode("Inflated Pocket Dimension", {"Smokeless Powder":50,"Computer":50,}, depends_on=("Nuclear Deterrent Development", "Turbo Rifle Ammo", "Cluster Nobelisk", "The Rifle")), #(Research_Sulfur_6_C)
MamNode("The Rifle", {"Smokeless Powder":50,"Motor":100,"Rubber":200,}, depends_on=("Smokeless Powder", )), #(Research_Sulfur_4_1_C)
MamNode("Compacted Coal", {"Hard Drive":1,"Sulfur":25,"Coal":25,}, depends_on=("Experimental Power Generation", )), #(Research_Sulfur_CompactedCoal_C)

View File

@@ -947,14 +947,14 @@ class Items:
pool.append(item)
filler_pool_size: int = number_of_locations - len(pool)
if (filler_pool_size < 0):
raise Exception(f"Location pool starved, trying to add {len(pool)} items to {number_of_locations} locations")
filtered_filler_items = tuple(item for item in self.filler_items if item not in excluded_from_pool)
for _ in range(filler_pool_size):
filler_item_name = self.get_filler_item_name(filtered_filler_items, random, options)
item = self.create_item(self, filler_item_name, self.player)
pool.append(item)
pool += [
self.create_item(self, self.get_filler_item_name(filtered_filler_items, random, options), self.player)
for _ in range(filler_pool_size)
]
return pool

View File

@@ -1,7 +1,7 @@
from dataclasses import dataclass
from typing import ClassVar, Any, cast
from enum import IntEnum
from Options import PerGameCommonOptions, DeathLinkMixin, AssembleOptions, Visibility, OptionGroup
from Options import PerGameCommonOptions, DeathLinkMixin, AssembleOptions, OptionGroup
from Options import Range, NamedRange, Toggle, DefaultOnToggle, OptionSet, StartInventoryPool, Choice
from schema import Schema, And
@@ -421,9 +421,13 @@ class GoalRequirement(Choice):
class RandomizeTier0(DefaultOnToggle):
"""
Randomizer the way you obtain basic parts such as ingots and wire
Randomizes the recipes used to craft the default unlocked parts:
Iron Ingot, Iron Plate, Iron Rod, Copper Ingot, Wire, Concrete, Screw, Reinforced Iron Plate
* They could require usage of Foundries or Assemblers that will than also get unlocked by default if needed
* They could require other ores to be mixed in
"""
display_name = "Randomize tier 0 recipes"
display_name = "Randomize default part recipes"
@dataclass
class SatisfactoryOptions(PerGameCommonOptions, DeathLinkMixin):
@@ -449,7 +453,7 @@ class SatisfactoryOptions(PerGameCommonOptions, DeathLinkMixin):
trap_selection_override: TrapSelectionOverride
energy_link: EnergyLink
start_inventory_from_pool: StartInventoryPool
randomize_tier_0: RandomizeTier0
randomize_starter_recipes: RandomizeTier0
option_groups = [
OptionGroup("Game Scope", [
@@ -492,7 +496,7 @@ option_presets: dict[str, dict[str, Any]] = {
"goal_awesome_sink_points_total": 17804500, # 100 coupons
"hard_drive_progression_limit": 20,
"starting_inventory_preset": 3, # "Foundations"
"randomize_tier_0": False,
"randomizer_starter_recipes": False,
"mam_logic_placement": int(Placement.starting_inventory),
"awesome_logic_placement": int(Placement.starting_inventory),
"energy_link_logic_placement": int(Placement.starting_inventory),

View File

@@ -50,9 +50,11 @@ def create_regions_and_return_locations(world: MultiWorld, options: Satisfactory
for minestone, _ in enumerate(milestones_per_hub_tier, 1):
region_names.append(f"Hub {hub_tier}-{minestone}")
for building_name, building in game_logic.buildings.items():
if building.can_produce and building_name in critical_path.required_buildings:
region_names.append(building_name)
region_names += [
building_name
for building_name, building in game_logic.buildings.items()
if building.can_produce and building_name in critical_path.required_buildings
]
for tree_name, tree in game_logic.man_trees.items():
region_names.append(tree_name)
@@ -150,10 +152,7 @@ def create_regions_and_return_locations(world: MultiWorld, options: Satisfactory
def throwIfAnyLocationIsNotAssignedToARegion(regions: dict[str, Region], regionNames: set[str]):
existingRegions = set()
for region in regions.keys():
existingRegions.add(region)
existingRegions = set(regions.keys())
if (regionNames - existingRegions):
raise Exception(f"Satisfactory: the following regions are used in locations: {regionNames - existingRegions}, but no such region exists")
@@ -165,22 +164,20 @@ def create_region(world: MultiWorld, player: int,
region = Region(name, player, world)
if name in locations_per_region:
for location_data in locations_per_region[name]:
location = SatisfactoryLocation(player, location_data, region)
region.locations.append(location)
region.locations += [
SatisfactoryLocation(player, location_data, region)
for location_data in locations_per_region[name]
]
return region
def create_regions(world: MultiWorld, player: int, locations_per_region: dict[str, list[LocationData]],
region_names: list[str]) -> dict[str, Region]:
regions: dict[str, Region] = {}
for name in region_names:
regions[name] = create_region(world, player, locations_per_region, name)
return regions
return {
name : create_region(world, player, locations_per_region, name)
for name in region_names
}
def connect(regions: dict[str, Region], source: str, target: str,