diff --git a/worlds/satisfactory/CriticalPathCalculator.py b/worlds/satisfactory/CriticalPathCalculator.py index 7664a50998..74f9e47404 100644 --- a/worlds/satisfactory/CriticalPathCalculator.py +++ b/worlds/satisfactory/CriticalPathCalculator.py @@ -37,16 +37,6 @@ class CriticalPathCalculator: self.select_minimal_required_parts_for(tree.access_items) for node in tree.nodes: - # Bullet Guidance System - Rifle Ammo - # Stun Rebar - Iron Rebar - # Radar Technology - Heavy Modular Frame - # Turbo Rifle Ammo - Packaged Turbofuel, Rifle Ammo - # Nuclear Deterrent Development - Encased Uranium Cell - # Rocket Fuel - Packaged Turbofuel - # Ionized Fuel - Ionized Fuel - if node.name == "Hostile Organism Detection": - Debug = True - if node.minimal_tier > options.final_elevator_package: continue @@ -63,6 +53,10 @@ class CriticalPathCalculator: self.select_minimal_required_parts_for_building("Walls Orange") self.select_minimal_required_parts_for_building("Power Storage") + #equipment + self.select_minimal_required_parts_for(self.logic.recipes["Hazmat Suit"][0].inputs) + self.select_minimal_required_parts_for(self.logic.recipes["Iodine Infused Filter"][0].inputs) + for i in range(1, self.potential_required_belt_speed + 1): self.select_minimal_required_parts_for_building(f"Conveyor Mk.{i}") if self.potential_required_pipes: @@ -102,21 +96,12 @@ class CriticalPathCalculator: if part in self.potential_required_parts: continue - if part == "Radio Control Unit": - Debug = True - self.potential_required_parts.add(part) for recipe in self.logic.recipes[part]: - if part == "Fuel": - Debug = True - if recipe.minimal_tier > self.options.final_elevator_package: continue - if recipe.minimal_belt_speed == 5: - Debug = True - self.potential_required_belt_speed = \ max(self.potential_required_belt_speed, recipe.minimal_belt_speed) @@ -128,9 +113,6 @@ class CriticalPathCalculator: self.potential_required_radioactive = True if recipe.building: - if recipe.building == "Blender": - debug = True - self.select_minimal_required_parts_for(self.logic.buildings[recipe.building].inputs) self.potential_required_buildings.add(recipe.building) diff --git a/worlds/satisfactory/GameLogic.py b/worlds/satisfactory/GameLogic.py index aa14a4b345..f9cc8b447f 100644 --- a/worlds/satisfactory/GameLogic.py +++ b/worlds/satisfactory/GameLogic.py @@ -593,8 +593,8 @@ class GameLogic: "Geothermal Generator": Building("Geothermal Generator", ("Motor", "Modular Frame", "High-Speed Connector", "Copper Sheet", "Wire")), "Nuclear Power Plant": Building("Nuclear Power Plant", ("Concrete", "Heavy Modular Frame", "Supercomputer", "Cable", "Alclad Aluminum Sheet")), "Miner Mk.1": Building("Miner Mk.1", ("Iron Plate", "Concrete"), PowerInfrastructureLevel.Basic, implicitly_unlocked=True), - "Miner Mk.2": Building("Miner Mk.2", ("Encased Industrial Beam", "Steel Pipe", "Modular Frame"), PowerInfrastructureLevel.Automated), - "Miner Mk.3": Building("Miner Mk.3", ("Steel Pipe", "Supercomputer", "Fused Modular Frame", "Turbo Motor"), PowerInfrastructureLevel.Advanced), + "Miner Mk.2": Building("Miner Mk.2", ("Encased Industrial Beam", "Steel Pipe", "Modular Frame"), PowerInfrastructureLevel.Automated, can_produce=False), + "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), diff --git a/worlds/satisfactory/Items.py b/worlds/satisfactory/Items.py index 01f3e18f83..6ac4f0f857 100644 --- a/worlds/satisfactory/Items.py +++ b/worlds/satisfactory/Items.py @@ -840,8 +840,8 @@ class Items: if not (data.category & G.BasicNeeds) and name not in instance.critical_path.potential_required_recipes_names: type = C.filler logging.info(f"Dropping... {name}") - else: - logging.warning(f"Required .. {name}") + #else: + # logging.warning(f"Required .. {name}") return Item(name, type, data.code, player) @@ -888,7 +888,7 @@ class Items: 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") - + logging.warning(f"Itempool size: {len(pool)}, number of locations: {number_of_locations}, spare: {filler_pool_size}") for _ in range(filler_pool_size): item = self.create_item(self, self.get_filler_item_name(random, options), self.player) pool.append(item) diff --git a/worlds/satisfactory/Locations.py b/worlds/satisfactory/Locations.py index 04c860c30d..53059a9118 100644 --- a/worlds/satisfactory/Locations.py +++ b/worlds/satisfactory/Locations.py @@ -48,9 +48,6 @@ class Part(LocationData): def can_produce_any_recipe_for_part(self, state_logic: StateLogic, recipes: Iterable[Recipe], name: str, items: Items) -> Callable[[CollectionState], bool]: def can_build_by_any_recipe(state: CollectionState) -> bool: - if name == "Iron Ingot": - debug = True - if items.precalculated_progression_recipes and name in items.precalculated_progression_recipes: can_produce: bool = state_logic.can_produce_specific_recipe_for_part( state, items.precalculated_progression_recipes[name]) @@ -81,9 +78,6 @@ class EventBuilding(LocationData): ) -> Callable[[CollectionState], bool]: def can_build(state: CollectionState) -> bool: - if building.name == "Building: Manufacturer": - debug = True - return (building.implicitly_unlocked or state_logic.has_recipe(state, building)) \ and state_logic.can_power(state, building.power_requirement) \ and state_logic.can_produce_all_allowing_handcrafting(state, game_logic, building.inputs) @@ -102,9 +96,6 @@ class PowerInfrastructure(LocationData): ) -> Callable[[CollectionState], bool]: def can_power(state: CollectionState) -> bool: - if powerLevel == PowerInfrastructureLevel.Automated: - debug = True - return any(state_logic.can_power(state, level) for level in PowerInfrastructureLevel if level > powerLevel)\ or any(state_logic.can_build(state, recipe.building) and state_logic.can_produce_all_allowing_handcrafting(state, game_logic, recipe.inputs) @@ -157,12 +148,6 @@ class DropPod(LocationData): # we currently do not know how many hdd require gas or radioactive protection # coordinates are for us to reference them, there is no real link between coordinate and check def get_region(gassed: Optional[bool], radioactive: Optional[bool]) -> str: - #if radioactive: - # return "Radioactive Area" - #elif gassed: - # return "Gas Area" - #else: - # return "Overworld" return f"Hub Tier {tier}" def get_rule(unlocked_by: Optional[str], power_needed: int) -> Callable[[CollectionState], bool]: @@ -319,17 +304,17 @@ class Locations(): ] #TODO: should be based on self.game_logic - if 4 <= max_tier: + if max_tier > 8: all_locations.append(MamSlot("Power Slugs", "Synthetic Power Shards", 1338572)) - if 4 <= max_tier: + if max_tier > 8: all_locations.append(MamSlot("Alien Technology", "Alien Power Matrix", 1338593)) - if 2 <= max_tier: + if max_tier > 2: all_locations.append(MamSlot("Sulfur", "Turbo Rifle Ammo", 1338568)) - if 2 <= max_tier: + if max_tier > 2: all_locations.append(MamSlot("Sulfur", "Nuclear Deterrent Development", 1338571)) - if 3 <= max_tier: + if max_tier > 4: all_locations.append(MamSlot("Sulfur", "Rocket Fuel", 1338573)) - if 4 <= max_tier: + if max_tier > 6: all_locations.append(MamSlot("Sulfur", "Ionized Fuel", 1338574)) return all_locations diff --git a/worlds/satisfactory/Regions.py b/worlds/satisfactory/Regions.py index aab87bf344..b0ba5b0023 100644 --- a/worlds/satisfactory/Regions.py +++ b/worlds/satisfactory/Regions.py @@ -4,6 +4,7 @@ from .Locations import LocationData from .GameLogic import GameLogic, PowerInfrastructureLevel from .StateLogic import StateLogic from .Options import SatisfactoryOptions, Placement +from .CriticalPathCalculator import CriticalPathCalculator class SatisfactoryLocation(Location): game: str = "Satisfactory" @@ -29,13 +30,12 @@ class SatisfactoryLocation(Location): return not item.advancement -def create_regions_and_return_locations(world: MultiWorld, options: SatisfactoryOptions, player: int, - game_logic: GameLogic, state_logic: StateLogic, locations: List[LocationData]): +def create_regions_and_return_locations(world: MultiWorld, options: SatisfactoryOptions, player: int, + game_logic: GameLogic, state_logic: StateLogic, critical_path: CriticalPathCalculator, + locations: List[LocationData]): region_names: List[str] = [ "Overworld", - "Gas Area", - "Radioactive Area", "Mam", "AWESOME Shop" ] @@ -50,14 +50,15 @@ def create_regions_and_return_locations(world: MultiWorld, options: Satisfactory region_names.append(f"Hub {hub_tier}-{minestone}") for building_name, building in game_logic.buildings.items(): - if building.can_produce: + if building.can_produce and building_name in critical_path.potential_required_buildings: region_names.append(building_name) for tree_name, tree in game_logic.man_trees.items(): region_names.append(tree_name) for node in tree.nodes: - region_names.append(f"{tree_name}: {node.name}") + if node.minimal_tier <= options.final_elevator_package: + region_names.append(f"{tree_name}: {node.name}") locations_per_region: Dict[str, LocationData] = get_locations_per_region(locations) regions: Dict[str, Region] = create_regions(world, player, locations_per_region, region_names) @@ -107,10 +108,6 @@ def create_regions_and_return_locations(world: MultiWorld, options: Satisfactory if options.final_elevator_package >= 5: connect(regions, "Hub Tier 8", "Hub Tier 9", lambda state: state.has("Elevator Tier 4", player)) - connect(regions, "Overworld", "Gas Area", lambda state: - state_logic.can_produce_all(state, ("Gas Mask", "Gas Filter"))) - connect(regions, "Overworld", "Radioactive Area", lambda state: - state_logic.can_produce_all(state, ("Hazmat Suit", "Iodine Infused Filter"))) connect(regions, "Overworld", "Mam", lambda state: state_logic.can_build(state, "MAM")) connect(regions, "Overworld", "AWESOME Shop", lambda state: state_logic.can_build_all(state, ("AWESOME Shop", "AWESOME Sink"))) @@ -130,7 +127,7 @@ def create_regions_and_return_locations(world: MultiWorld, options: Satisfactory can_produce_all_allowing_handcrafting(parts_per_milestone.keys())) for building_name, building in game_logic.buildings.items(): - if building.can_produce: + if building.can_produce and building_name in critical_path.potential_required_buildings: connect(regions, "Overworld", building_name, lambda state, building_name=building_name: state_logic.can_build(state, building_name)) @@ -138,13 +135,17 @@ def create_regions_and_return_locations(world: MultiWorld, options: Satisfactory connect(regions, "Mam", tree_name) for node in tree.nodes: + if node.minimal_tier > options.final_elevator_package: + continue + if not node.depends_on: connect(regions, tree_name, f"{tree_name}: {node.name}", lambda state, parts=node.unlock_cost.keys(): state_logic.can_produce_all(state, parts)) else: for parent in node.depends_on: - connect(regions, f"{tree_name}: {parent}", f"{tree_name}: {node.name}", - lambda state, parts=node.unlock_cost.keys(): state_logic.can_produce_all(state, parts)) + if f"{tree_name}: {parent}" in region_names: + connect(regions, f"{tree_name}: {parent}", f"{tree_name}: {node.name}", + lambda state, parts=node.unlock_cost.keys(): state_logic.can_produce_all(state, parts)) def throwIfAnyLocationIsNotAssignedToARegion(regions: Dict[str, Region], regionNames: Set[str]): diff --git a/worlds/satisfactory/__init__.py b/worlds/satisfactory/__init__.py index ebc521dad3..e25d4752db 100644 --- a/worlds/satisfactory/__init__.py +++ b/worlds/satisfactory/__init__.py @@ -73,7 +73,8 @@ class SatisfactoryWorld(World): locations: List[LocationData] = \ Locations(self.game_logic, self.options, self.state_logic, self.items, self.critical_path).get_locations() create_regions_and_return_locations( - self.multiworld, self.options, self.player, self.game_logic, self.state_logic, locations) + self.multiworld, self.options, self.player, self.game_logic, self.state_logic, self.critical_path, + locations) def create_items(self) -> None: