diff --git a/Starcraft2Client.py b/Starcraft2Client.py index 7431b6ea..de26cc15 100644 --- a/Starcraft2Client.py +++ b/Starcraft2Client.py @@ -639,6 +639,13 @@ def request_unfinished_missions(ctx: SC2Context): _, unfinished_missions = calc_unfinished_missions(ctx, unlocks=unlocks) + # Removing All-In from location pool + final_mission = lookup_id_to_mission[ctx.final_mission] + if final_mission in unfinished_missions.keys(): + message = f"Final Mission Available: {final_mission}[{ctx.final_mission}]\n" + message + if unfinished_missions[final_mission] == -1: + unfinished_missions.pop(final_mission) + message += ", ".join(f"{mark_up_mission_name(ctx, mission, unlocks)}[{ctx.mission_req_table[mission].id}] " + mark_up_objectives( f"[{len(unfinished_missions[mission])}/" diff --git a/worlds/sc2wol/Items.py b/worlds/sc2wol/Items.py index 6cb768de..aae83f50 100644 --- a/worlds/sc2wol/Items.py +++ b/worlds/sc2wol/Items.py @@ -157,17 +157,17 @@ basic_units = { 'Vulture' } -advanced_basic_units = { +advanced_basic_units = basic_units.union({ 'Reaper', 'Goliath', 'Diamondback', 'Viking' -} +}) -def get_basic_units(world: MultiWorld, player: int) -> typing.Set[str]: - if get_option_value(world, player, 'required_tactics') > 0: - return basic_units.union(advanced_basic_units) +def get_basic_units(multiworld: MultiWorld, player: int) -> typing.Set[str]: + if get_option_value(multiworld, player, 'required_tactics') > 0: + return advanced_basic_units else: return basic_units @@ -193,7 +193,7 @@ defense_ratings = { } zerg_defense_ratings = { "Perdition Turret": 2, - # Bunker w/ Firebat + # Bunker w/ Firebat: 2 "Hive Mind Emulator": 3, "Psi Disruptor": 3 } diff --git a/worlds/sc2wol/Locations.py b/worlds/sc2wol/Locations.py index f778c91b..b476fc5e 100644 --- a/worlds/sc2wol/Locations.py +++ b/worlds/sc2wol/Locations.py @@ -18,9 +18,9 @@ class LocationData(NamedTuple): rule: Callable = lambda state: True -def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[LocationData, ...]: +def get_locations(multiworld: Optional[MultiWorld], player: Optional[int]) -> Tuple[LocationData, ...]: # Note: rules which are ended with or True are rules identified as needed later when restricted units is an option - logic_level = get_option_value(world, player, 'required_tactics') + logic_level = get_option_value(multiworld, player, 'required_tactics') location_table: List[LocationData] = [ LocationData("Liberation Day", "Liberation Day: Victory", SC2WOL_LOC_ID_OFFSET + 100), LocationData("Liberation Day", "Liberation Day: First Statue", SC2WOL_LOC_ID_OFFSET + 101), @@ -30,144 +30,144 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L LocationData("Liberation Day", "Liberation Day: Fifth Statue", SC2WOL_LOC_ID_OFFSET + 105), LocationData("Liberation Day", "Liberation Day: Sixth Statue", SC2WOL_LOC_ID_OFFSET + 106), LocationData("The Outlaws", "The Outlaws: Victory", SC2WOL_LOC_ID_OFFSET + 200, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("The Outlaws", "The Outlaws: Rebel Base", SC2WOL_LOC_ID_OFFSET + 201, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("Zero Hour", "Zero Hour: Victory", SC2WOL_LOC_ID_OFFSET + 300, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_defense_rating(world, player, True) >= 2 and - (logic_level > 0 or state._sc2wol_has_anti_air(world, player))), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) >= 2 and + (logic_level > 0 or state._sc2wol_has_anti_air(multiworld, player))), LocationData("Zero Hour", "Zero Hour: First Group Rescued", SC2WOL_LOC_ID_OFFSET + 301), LocationData("Zero Hour", "Zero Hour: Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 302, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("Zero Hour", "Zero Hour: Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 303, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_defense_rating(world, player, True) >= 2), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) >= 2), LocationData("Evacuation", "Evacuation: Victory", SC2WOL_LOC_ID_OFFSET + 400, - lambda state: state._sc2wol_has_common_unit(world, player) and - (logic_level > 0 and state._sc2wol_has_anti_air(world, player) - or state._sc2wol_has_competent_anti_air(world, player))), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + (logic_level > 0 and state._sc2wol_has_anti_air(multiworld, player) + or state._sc2wol_has_competent_anti_air(multiworld, player))), LocationData("Evacuation", "Evacuation: First Chysalis", SC2WOL_LOC_ID_OFFSET + 401), LocationData("Evacuation", "Evacuation: Second Chysalis", SC2WOL_LOC_ID_OFFSET + 402, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("Evacuation", "Evacuation: Third Chysalis", SC2WOL_LOC_ID_OFFSET + 403, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("Outbreak", "Outbreak: Victory", SC2WOL_LOC_ID_OFFSET + 500, - lambda state: state._sc2wol_defense_rating(world, player, True, False) >= 4 and - (state._sc2wol_has_common_unit(world, player) or state.has("Reaper", player))), + lambda state: state._sc2wol_defense_rating(multiworld, player, True, False) >= 4 and + (state._sc2wol_has_common_unit(multiworld, player) or state.has("Reaper", player))), LocationData("Outbreak", "Outbreak: Left Infestor", SC2WOL_LOC_ID_OFFSET + 501, - lambda state: state._sc2wol_defense_rating(world, player, True, False) >= 2 and - (state._sc2wol_has_common_unit(world, player) or state.has("Reaper", player))), + lambda state: state._sc2wol_defense_rating(multiworld, player, True, False) >= 2 and + (state._sc2wol_has_common_unit(multiworld, player) or state.has("Reaper", player))), LocationData("Outbreak", "Outbreak: Right Infestor", SC2WOL_LOC_ID_OFFSET + 502, - lambda state: state._sc2wol_defense_rating(world, player, True, False) >= 2 and - (state._sc2wol_has_common_unit(world, player) or state.has("Reaper", player))), + lambda state: state._sc2wol_defense_rating(multiworld, player, True, False) >= 2 and + (state._sc2wol_has_common_unit(multiworld, player) or state.has("Reaper", player))), LocationData("Safe Haven", "Safe Haven: Victory", SC2WOL_LOC_ID_OFFSET + 600, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player)), LocationData("Safe Haven", "Safe Haven: North Nexus", SC2WOL_LOC_ID_OFFSET + 601, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player)), LocationData("Safe Haven", "Safe Haven: East Nexus", SC2WOL_LOC_ID_OFFSET + 602, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player)), LocationData("Safe Haven", "Safe Haven: South Nexus", SC2WOL_LOC_ID_OFFSET + 603, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player)), LocationData("Haven's Fall", "Haven's Fall: Victory", SC2WOL_LOC_ID_OFFSET + 700, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_defense_rating(world, player, True) >= 3), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) >= 3), LocationData("Haven's Fall", "Haven's Fall: North Hive", SC2WOL_LOC_ID_OFFSET + 701, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_defense_rating(world, player, True) >= 3), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) >= 3), LocationData("Haven's Fall", "Haven's Fall: East Hive", SC2WOL_LOC_ID_OFFSET + 702, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_defense_rating(world, player, True) >= 3), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) >= 3), LocationData("Haven's Fall", "Haven's Fall: South Hive", SC2WOL_LOC_ID_OFFSET + 703, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_defense_rating(world, player, True) >= 3), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) >= 3), LocationData("Smash and Grab", "Smash and Grab: Victory", SC2WOL_LOC_ID_OFFSET + 800, - lambda state: state._sc2wol_has_common_unit(world, player) and - (logic_level > 0 and state._sc2wol_has_anti_air(world, player) - or state._sc2wol_has_competent_anti_air(world, player))), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + (logic_level > 0 and state._sc2wol_has_anti_air(multiworld, player) + or state._sc2wol_has_competent_anti_air(multiworld, player))), LocationData("Smash and Grab", "Smash and Grab: First Relic", SC2WOL_LOC_ID_OFFSET + 801), LocationData("Smash and Grab", "Smash and Grab: Second Relic", SC2WOL_LOC_ID_OFFSET + 802), LocationData("Smash and Grab", "Smash and Grab: Third Relic", SC2WOL_LOC_ID_OFFSET + 803, - lambda state: state._sc2wol_has_common_unit(world, player) and - (logic_level > 0 and state._sc2wol_has_anti_air(world, player) - or state._sc2wol_has_competent_anti_air(world, player))), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + (logic_level > 0 and state._sc2wol_has_anti_air(multiworld, player) + or state._sc2wol_has_competent_anti_air(multiworld, player))), LocationData("Smash and Grab", "Smash and Grab: Fourth Relic", SC2WOL_LOC_ID_OFFSET + 804, - lambda state: state._sc2wol_has_common_unit(world, player) and - (logic_level > 0 and state._sc2wol_has_anti_air(world, player) - or state._sc2wol_has_competent_anti_air(world, player))), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + (logic_level > 0 and state._sc2wol_has_anti_air(multiworld, player) + or state._sc2wol_has_competent_anti_air(multiworld, player))), LocationData("The Dig", "The Dig: Victory", SC2WOL_LOC_ID_OFFSET + 900, - lambda state: state._sc2wol_has_anti_air(world, player) and - state._sc2wol_defense_rating(world, player, False) >= 7), + lambda state: state._sc2wol_has_anti_air(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, False) >= 7), LocationData("The Dig", "The Dig: Left Relic", SC2WOL_LOC_ID_OFFSET + 901, - lambda state: state._sc2wol_defense_rating(world, player, False) >= 5), + lambda state: state._sc2wol_defense_rating(multiworld, player, False) >= 5), LocationData("The Dig", "The Dig: Right Ground Relic", SC2WOL_LOC_ID_OFFSET + 902, - lambda state: state._sc2wol_defense_rating(world, player, False) >= 5), + lambda state: state._sc2wol_defense_rating(multiworld, player, False) >= 5), LocationData("The Dig", "The Dig: Right Cliff Relic", SC2WOL_LOC_ID_OFFSET + 903, - lambda state: state._sc2wol_defense_rating(world, player, False) >= 5), + lambda state: state._sc2wol_defense_rating(multiworld, player, False) >= 5), LocationData("The Moebius Factor", "The Moebius Factor: Victory", SC2WOL_LOC_ID_OFFSET + 1000, - lambda state: state._sc2wol_has_anti_air(world, player) and - (state._sc2wol_has_air(world, player) + lambda state: state._sc2wol_has_anti_air(multiworld, player) and + (state._sc2wol_has_air(multiworld, player) or state.has_any({'Medivac', 'Hercules'}, player) - and state._sc2wol_has_common_unit(world, player))), + and state._sc2wol_has_common_unit(multiworld, player))), LocationData("The Moebius Factor", "The Moebius Factor: South Rescue", SC2WOL_LOC_ID_OFFSET + 1003, - lambda state: state._sc2wol_able_to_rescue(world, player)), + lambda state: state._sc2wol_able_to_rescue(multiworld, player)), LocationData("The Moebius Factor", "The Moebius Factor: Wall Rescue", SC2WOL_LOC_ID_OFFSET + 1004, - lambda state: state._sc2wol_able_to_rescue(world, player)), + lambda state: state._sc2wol_able_to_rescue(multiworld, player)), LocationData("The Moebius Factor", "The Moebius Factor: Mid Rescue", SC2WOL_LOC_ID_OFFSET + 1005, - lambda state: state._sc2wol_able_to_rescue(world, player)), + lambda state: state._sc2wol_able_to_rescue(multiworld, player)), LocationData("The Moebius Factor", "The Moebius Factor: Nydus Roof Rescue", SC2WOL_LOC_ID_OFFSET + 1006, - lambda state: state._sc2wol_able_to_rescue(world, player)), + lambda state: state._sc2wol_able_to_rescue(multiworld, player)), LocationData("The Moebius Factor", "The Moebius Factor: Alive Inside Rescue", SC2WOL_LOC_ID_OFFSET + 1007, - lambda state: state._sc2wol_able_to_rescue(world, player)), + lambda state: state._sc2wol_able_to_rescue(multiworld, player)), LocationData("The Moebius Factor", "The Moebius Factor: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1008, - lambda state: state._sc2wol_has_anti_air(world, player) and - (state._sc2wol_has_air(world, player) + lambda state: state._sc2wol_has_anti_air(multiworld, player) and + (state._sc2wol_has_air(multiworld, player) or state.has_any({'Medivac', 'Hercules'}, player) - and state._sc2wol_has_common_unit(world, player))), + and state._sc2wol_has_common_unit(multiworld, player))), LocationData("Supernova", "Supernova: Victory", SC2WOL_LOC_ID_OFFSET + 1100, - lambda state: state._sc2wol_beats_protoss_deathball(world, player)), + lambda state: state._sc2wol_beats_protoss_deathball(multiworld, player)), LocationData("Supernova", "Supernova: West Relic", SC2WOL_LOC_ID_OFFSET + 1101), LocationData("Supernova", "Supernova: North Relic", SC2WOL_LOC_ID_OFFSET + 1102), LocationData("Supernova", "Supernova: South Relic", SC2WOL_LOC_ID_OFFSET + 1103, - lambda state: state._sc2wol_beats_protoss_deathball(world, player)), + lambda state: state._sc2wol_beats_protoss_deathball(multiworld, player)), LocationData("Supernova", "Supernova: East Relic", SC2WOL_LOC_ID_OFFSET + 1104, - lambda state: state._sc2wol_beats_protoss_deathball(world, player)), + lambda state: state._sc2wol_beats_protoss_deathball(multiworld, player)), LocationData("Maw of the Void", "Maw of the Void: Victory", SC2WOL_LOC_ID_OFFSET + 1200, - lambda state: state._sc2wol_survives_rip_field(world, player)), + lambda state: state._sc2wol_survives_rip_field(multiworld, player)), LocationData("Maw of the Void", "Maw of the Void: Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1201), LocationData("Maw of the Void", "Maw of the Void: Expansion Prisoners", SC2WOL_LOC_ID_OFFSET + 1202, - lambda state: logic_level > 0 or state._sc2wol_survives_rip_field(world, player)), + lambda state: logic_level > 0 or state._sc2wol_survives_rip_field(multiworld, player)), LocationData("Maw of the Void", "Maw of the Void: South Close Prisoners", SC2WOL_LOC_ID_OFFSET + 1203, - lambda state: logic_level > 0 or state._sc2wol_survives_rip_field(world, player)), + lambda state: logic_level > 0 or state._sc2wol_survives_rip_field(multiworld, player)), LocationData("Maw of the Void", "Maw of the Void: South Far Prisoners", SC2WOL_LOC_ID_OFFSET + 1204, - lambda state: state._sc2wol_survives_rip_field(world, player)), + lambda state: state._sc2wol_survives_rip_field(multiworld, player)), LocationData("Maw of the Void", "Maw of the Void: North Prisoners", SC2WOL_LOC_ID_OFFSET + 1205, - lambda state: state._sc2wol_survives_rip_field(world, player)), + lambda state: state._sc2wol_survives_rip_field(multiworld, player)), LocationData("Devil's Playground", "Devil's Playground: Victory", SC2WOL_LOC_ID_OFFSET + 1300, lambda state: logic_level > 0 or - state._sc2wol_has_anti_air(world, player) and ( - state._sc2wol_has_common_unit(world, player) or state.has("Reaper", player))), + state._sc2wol_has_anti_air(multiworld, player) and ( + state._sc2wol_has_common_unit(multiworld, player) or state.has("Reaper", player))), LocationData("Devil's Playground", "Devil's Playground: Tosh's Miners", SC2WOL_LOC_ID_OFFSET + 1301), LocationData("Devil's Playground", "Devil's Playground: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1302, - lambda state: logic_level > 0 or state._sc2wol_has_common_unit(world, player) or state.has("Reaper", player)), + lambda state: logic_level > 0 or state._sc2wol_has_common_unit(multiworld, player) or state.has("Reaper", player)), LocationData("Welcome to the Jungle", "Welcome to the Jungle: Victory", SC2WOL_LOC_ID_OFFSET + 1400, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player)), LocationData("Welcome to the Jungle", "Welcome to the Jungle: Close Relic", SC2WOL_LOC_ID_OFFSET + 1401), LocationData("Welcome to the Jungle", "Welcome to the Jungle: West Relic", SC2WOL_LOC_ID_OFFSET + 1402, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player)), LocationData("Welcome to the Jungle", "Welcome to the Jungle: North-East Relic", SC2WOL_LOC_ID_OFFSET + 1403, - lambda state: state._sc2wol_has_common_unit(world, player) and - state._sc2wol_has_competent_anti_air(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player) and + state._sc2wol_has_competent_anti_air(multiworld, player)), LocationData("Breakout", "Breakout: Victory", SC2WOL_LOC_ID_OFFSET + 1500), LocationData("Breakout", "Breakout: Diamondback Prison", SC2WOL_LOC_ID_OFFSET + 1501), LocationData("Breakout", "Breakout: Siegetank Prison", SC2WOL_LOC_ID_OFFSET + 1502), @@ -178,101 +178,101 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L LocationData("Ghost of a Chance", "Ghost of a Chance: Second Island Spectres", SC2WOL_LOC_ID_OFFSET + 1604), LocationData("Ghost of a Chance", "Ghost of a Chance: Third Island Spectres", SC2WOL_LOC_ID_OFFSET + 1605), LocationData("The Great Train Robbery", "The Great Train Robbery: Victory", SC2WOL_LOC_ID_OFFSET + 1700, - lambda state: state._sc2wol_has_train_killers(world, player) and - state._sc2wol_has_anti_air(world, player)), + lambda state: state._sc2wol_has_train_killers(multiworld, player) and + state._sc2wol_has_anti_air(multiworld, player)), LocationData("The Great Train Robbery", "The Great Train Robbery: North Defiler", SC2WOL_LOC_ID_OFFSET + 1701), LocationData("The Great Train Robbery", "The Great Train Robbery: Mid Defiler", SC2WOL_LOC_ID_OFFSET + 1702), LocationData("The Great Train Robbery", "The Great Train Robbery: South Defiler", SC2WOL_LOC_ID_OFFSET + 1703), LocationData("Cutthroat", "Cutthroat: Victory", SC2WOL_LOC_ID_OFFSET + 1800, - lambda state: state._sc2wol_has_common_unit(world, player) and + lambda state: state._sc2wol_has_common_unit(multiworld, player) and (logic_level > 0 or state._sc2wol_has_anti_air)), LocationData("Cutthroat", "Cutthroat: Mira Han", SC2WOL_LOC_ID_OFFSET + 1801, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("Cutthroat", "Cutthroat: North Relic", SC2WOL_LOC_ID_OFFSET + 1802, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("Cutthroat", "Cutthroat: Mid Relic", SC2WOL_LOC_ID_OFFSET + 1803), LocationData("Cutthroat", "Cutthroat: Southwest Relic", SC2WOL_LOC_ID_OFFSET + 1804, - lambda state: state._sc2wol_has_common_unit(world, player)), + lambda state: state._sc2wol_has_common_unit(multiworld, player)), LocationData("Engine of Destruction", "Engine of Destruction: Victory", SC2WOL_LOC_ID_OFFSET + 1900, - lambda state: state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_has_common_unit(world, player) or state.has('Wraith', player)), + lambda state: state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_has_common_unit(multiworld, player) or state.has('Wraith', player)), LocationData("Engine of Destruction", "Engine of Destruction: Odin", SC2WOL_LOC_ID_OFFSET + 1901), LocationData("Engine of Destruction", "Engine of Destruction: Loki", SC2WOL_LOC_ID_OFFSET + 1902, - lambda state: state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_has_common_unit(world, player) or state.has('Wraith', player)), + lambda state: state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_has_common_unit(multiworld, player) or state.has('Wraith', player)), LocationData("Engine of Destruction", "Engine of Destruction: Lab Devourer", SC2WOL_LOC_ID_OFFSET + 1903), LocationData("Engine of Destruction", "Engine of Destruction: North Devourer", SC2WOL_LOC_ID_OFFSET + 1904, - lambda state: state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_has_common_unit(world, player) or state.has('Wraith', player)), + lambda state: state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_has_common_unit(multiworld, player) or state.has('Wraith', player)), LocationData("Engine of Destruction", "Engine of Destruction: Southeast Devourer", SC2WOL_LOC_ID_OFFSET + 1905, - lambda state: state._sc2wol_has_competent_anti_air(world, player) and - state._sc2wol_has_common_unit(world, player) or state.has('Wraith', player)), + lambda state: state._sc2wol_has_competent_anti_air(multiworld, player) and + state._sc2wol_has_common_unit(multiworld, player) or state.has('Wraith', player)), LocationData("Media Blitz", "Media Blitz: Victory", SC2WOL_LOC_ID_OFFSET + 2000, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Media Blitz", "Media Blitz: Tower 1", SC2WOL_LOC_ID_OFFSET + 2001, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Media Blitz", "Media Blitz: Tower 2", SC2WOL_LOC_ID_OFFSET + 2002, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Media Blitz", "Media Blitz: Tower 3", SC2WOL_LOC_ID_OFFSET + 2003, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Media Blitz", "Media Blitz: Science Facility", SC2WOL_LOC_ID_OFFSET + 2004), LocationData("Piercing the Shroud", "Piercing the Shroud: Victory", SC2WOL_LOC_ID_OFFSET + 2100, - lambda state: state._sc2wol_has_mm_upgrade(world, player)), + lambda state: state._sc2wol_has_mm_upgrade(multiworld, player)), LocationData("Piercing the Shroud", "Piercing the Shroud: Holding Cell Relic", SC2WOL_LOC_ID_OFFSET + 2101), LocationData("Piercing the Shroud", "Piercing the Shroud: Brutalisk Relic", SC2WOL_LOC_ID_OFFSET + 2102, - lambda state: state._sc2wol_has_mm_upgrade(world, player)), + lambda state: state._sc2wol_has_mm_upgrade(multiworld, player)), LocationData("Piercing the Shroud", "Piercing the Shroud: First Escape Relic", SC2WOL_LOC_ID_OFFSET + 2103, - lambda state: state._sc2wol_has_mm_upgrade(world, player)), + lambda state: state._sc2wol_has_mm_upgrade(multiworld, player)), LocationData("Piercing the Shroud", "Piercing the Shroud: Second Escape Relic", SC2WOL_LOC_ID_OFFSET + 2104, - lambda state: state._sc2wol_has_mm_upgrade(world, player)), + lambda state: state._sc2wol_has_mm_upgrade(multiworld, player)), LocationData("Piercing the Shroud", "Piercing the Shroud: Brutalisk ", SC2WOL_LOC_ID_OFFSET + 2105, - lambda state: state._sc2wol_has_mm_upgrade(world, player)), + lambda state: state._sc2wol_has_mm_upgrade(multiworld, player)), LocationData("Whispers of Doom", "Whispers of Doom: Victory", SC2WOL_LOC_ID_OFFSET + 2200), LocationData("Whispers of Doom", "Whispers of Doom: First Hatchery", SC2WOL_LOC_ID_OFFSET + 2201), LocationData("Whispers of Doom", "Whispers of Doom: Second Hatchery", SC2WOL_LOC_ID_OFFSET + 2202), LocationData("Whispers of Doom", "Whispers of Doom: Third Hatchery", SC2WOL_LOC_ID_OFFSET + 2203), LocationData("A Sinister Turn", "A Sinister Turn: Victory", SC2WOL_LOC_ID_OFFSET + 2300, - lambda state: state._sc2wol_has_protoss_medium_units(world, player)), + lambda state: state._sc2wol_has_protoss_medium_units(multiworld, player)), LocationData("A Sinister Turn", "A Sinister Turn: Robotics Facility", SC2WOL_LOC_ID_OFFSET + 2301, - lambda state: logic_level > 0 or state._sc2wol_has_protoss_common_units(world, player)), + lambda state: logic_level > 0 or state._sc2wol_has_protoss_common_units(multiworld, player)), LocationData("A Sinister Turn", "A Sinister Turn: Dark Shrine", SC2WOL_LOC_ID_OFFSET + 2302, - lambda state: logic_level > 0 or state._sc2wol_has_protoss_common_units(world, player)), + lambda state: logic_level > 0 or state._sc2wol_has_protoss_common_units(multiworld, player)), LocationData("A Sinister Turn", "A Sinister Turn: Templar Archives", SC2WOL_LOC_ID_OFFSET + 2303, - lambda state: state._sc2wol_has_protoss_common_units(world, player)), + lambda state: state._sc2wol_has_protoss_common_units(multiworld, player)), LocationData("Echoes of the Future", "Echoes of the Future: Victory", SC2WOL_LOC_ID_OFFSET + 2400, - lambda state: logic_level > 0 or state._sc2wol_has_protoss_medium_units(world, player)), + lambda state: logic_level > 0 or state._sc2wol_has_protoss_medium_units(multiworld, player)), LocationData("Echoes of the Future", "Echoes of the Future: Close Obelisk", SC2WOL_LOC_ID_OFFSET + 2401), LocationData("Echoes of the Future", "Echoes of the Future: West Obelisk", SC2WOL_LOC_ID_OFFSET + 2402, - lambda state: logic_level > 0 or state._sc2wol_has_protoss_common_units(world, player)), + lambda state: logic_level > 0 or state._sc2wol_has_protoss_common_units(multiworld, player)), LocationData("In Utter Darkness", "In Utter Darkness: Defeat", SC2WOL_LOC_ID_OFFSET + 2500), LocationData("In Utter Darkness", "In Utter Darkness: Protoss Archive", SC2WOL_LOC_ID_OFFSET + 2501, - lambda state: state._sc2wol_has_protoss_medium_units(world, player)), + lambda state: state._sc2wol_has_protoss_medium_units(multiworld, player)), LocationData("In Utter Darkness", "In Utter Darkness: Kills", SC2WOL_LOC_ID_OFFSET + 2502, - lambda state: state._sc2wol_has_protoss_common_units(world, player)), + lambda state: state._sc2wol_has_protoss_common_units(multiworld, player)), LocationData("Gates of Hell", "Gates of Hell: Victory", SC2WOL_LOC_ID_OFFSET + 2600, - lambda state: state._sc2wol_has_competent_comp(world, player) and - state._sc2wol_defense_rating(world, player, True) > 6), + lambda state: state._sc2wol_has_competent_comp(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) > 6), LocationData("Gates of Hell", "Gates of Hell: Large Army", SC2WOL_LOC_ID_OFFSET + 2601, - lambda state: state._sc2wol_has_competent_comp(world, player) and - state._sc2wol_defense_rating(world, player, True) > 6), + lambda state: state._sc2wol_has_competent_comp(multiworld, player) and + state._sc2wol_defense_rating(multiworld, player, True) > 6), LocationData("Belly of the Beast", "Belly of the Beast: Victory", SC2WOL_LOC_ID_OFFSET + 2700), LocationData("Belly of the Beast", "Belly of the Beast: First Charge", SC2WOL_LOC_ID_OFFSET + 2701), LocationData("Belly of the Beast", "Belly of the Beast: Second Charge", SC2WOL_LOC_ID_OFFSET + 2702), LocationData("Belly of the Beast", "Belly of the Beast: Third Charge", SC2WOL_LOC_ID_OFFSET + 2703), LocationData("Shatter the Sky", "Shatter the Sky: Victory", SC2WOL_LOC_ID_OFFSET + 2800, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Shatter the Sky", "Shatter the Sky: Close Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2801, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Shatter the Sky", "Shatter the Sky: Northwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2802, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Shatter the Sky", "Shatter the Sky: Southeast Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2803, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Shatter the Sky", "Shatter the Sky: Southwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2804, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("Shatter the Sky", "Shatter the Sky: Leviathan", SC2WOL_LOC_ID_OFFSET + 2805, - lambda state: state._sc2wol_has_competent_comp(world, player)), + lambda state: state._sc2wol_has_competent_comp(multiworld, player)), LocationData("All-In", "All-In: Victory", None, - lambda state: state._sc2wol_final_mission_requirements(world, player)) + lambda state: state._sc2wol_final_mission_requirements(multiworld, player)) ] beat_events = [] @@ -280,7 +280,8 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L for i, location_data in enumerate(location_table): # Removing all item-based logic on No Logic if logic_level == 2: - location_table[i] = location_data._replace(rule=Location.access_rule) + location_data = location_data._replace(rule=Location.access_rule) + location_table[i] = location_data # Generating Beat event locations if location_data.name.endswith((": Victory", ": Defeat")): beat_events.append( diff --git a/worlds/sc2wol/LogicMixin.py b/worlds/sc2wol/LogicMixin.py index 1de82959..dac9d856 100644 --- a/worlds/sc2wol/LogicMixin.py +++ b/worlds/sc2wol/LogicMixin.py @@ -5,26 +5,26 @@ from .Items import get_basic_units, defense_ratings, zerg_defense_ratings class SC2WoLLogic(LogicMixin): - def _sc2wol_has_common_unit(self, world: MultiWorld, player: int) -> bool: - return self.has_any(get_basic_units(world, player), player) + def _sc2wol_has_common_unit(self, multiworld: MultiWorld, player: int) -> bool: + return self.has_any(get_basic_units(multiworld, player), player) - def _sc2wol_has_air(self, world: MultiWorld, player: int) -> bool: - return self.has_any({'Viking', 'Wraith', 'Banshee'}, player) or get_option_value(world, player, 'required_tactics') > 0 \ - and self.has_any({'Hercules', 'Medivac'}, player) and self._sc2wol_has_common_unit(world, player) + def _sc2wol_has_air(self, multiworld: MultiWorld, player: int) -> bool: + return self.has_any({'Viking', 'Wraith', 'Banshee'}, player) or get_option_value(multiworld, player, 'required_tactics') > 0 \ + and self.has_any({'Hercules', 'Medivac'}, player) and self._sc2wol_has_common_unit(multiworld, player) - def _sc2wol_has_air_anti_air(self, world: MultiWorld, player: int) -> bool: + def _sc2wol_has_air_anti_air(self, multiworld: MultiWorld, player: int) -> bool: return self.has('Viking', player) \ - or get_option_value(world, player, 'required_tactics') > 0 and self.has('Wraith', player) + or get_option_value(multiworld, player, 'required_tactics') > 0 and self.has('Wraith', player) - def _sc2wol_has_competent_anti_air(self, world: MultiWorld, player: int) -> bool: - return self.has_any({'Marine', 'Goliath'}, player) or self._sc2wol_has_air_anti_air(world, player) + def _sc2wol_has_competent_anti_air(self, multiworld: MultiWorld, player: int) -> bool: + return self.has_any({'Marine', 'Goliath'}, player) or self._sc2wol_has_air_anti_air(multiworld, player) - def _sc2wol_has_anti_air(self, world: MultiWorld, player: int) -> bool: + def _sc2wol_has_anti_air(self, multiworld: MultiWorld, player: int) -> bool: return self.has_any({'Missile Turret', 'Thor', 'War Pigs', 'Spartan Company', "Hel's Angel", 'Battlecruiser', 'Wraith'}, player) \ - or self._sc2wol_has_competent_anti_air(world, player) \ - or get_option_value(world, player, 'required_tactics') > 0 and self.has_any({'Ghost', 'Spectre'}, player) + or self._sc2wol_has_competent_anti_air(multiworld, player) \ + or get_option_value(multiworld, player, 'required_tactics') > 0 and self.has_any({'Ghost', 'Spectre'}, player) - def _sc2wol_defense_rating(self, world: MultiWorld, player: int, zerg_enemy: bool, air_enemy: bool = True) -> bool: + def _sc2wol_defense_rating(self, multiworld: MultiWorld, player: int, zerg_enemy: bool, air_enemy: bool = True) -> bool: defense_score = sum((defense_ratings[item] for item in defense_ratings if self.has(item, player))) if self.has_any({'Marine', 'Marauder'}, player) and self.has('Bunker', player): defense_score += 3 @@ -35,62 +35,63 @@ class SC2WoLLogic(LogicMixin): if not air_enemy and self.has('Missile Turret', player): defense_score -= defense_ratings['Missile Turret'] # Advanced Tactics bumps defense rating requirements down by 2 - if get_option_value(world, player, 'required_tactics') > 0: + if get_option_value(multiworld, player, 'required_tactics') > 0: defense_score += 2 return defense_score - def _sc2wol_has_competent_comp(self, world: MultiWorld, player: int) -> bool: + def _sc2wol_has_competent_comp(self, multiworld: MultiWorld, player: int) -> bool: return (self.has('Marine', player) or self.has('Marauder', player) and - self._sc2wol_has_competent_anti_air(world, player)) and self.has_any({'Medivac', 'Medic'}, player) or \ - self.has('Thor', player) or self.has("Banshee", player) and self._sc2wol_has_competent_anti_air(world, player) or \ - self.has('Battlecruiser', player) and self._sc2wol_has_common_unit(world, player) or \ - self.has('Siege Tank', player) and self._sc2wol_has_competent_anti_air(world, player) + self._sc2wol_has_competent_anti_air(multiworld, player)) and self.has_any({'Medivac', 'Medic'}, player) or \ + self.has('Thor', player) or self.has("Banshee", player) and self._sc2wol_has_competent_anti_air(multiworld, player) or \ + self.has('Battlecruiser', player) and self._sc2wol_has_common_unit(multiworld, player) or \ + self.has('Siege Tank', player) and self._sc2wol_has_competent_anti_air(multiworld, player) - def _sc2wol_has_train_killers(self, world: MultiWorld, player: int) -> bool: - return (self.has_any({'Siege Tank', 'Diamondback', 'Marauder'}, player) or get_option_value(world, player, 'required_tactics') > 0 + def _sc2wol_has_train_killers(self, multiworld: MultiWorld, player: int) -> bool: + return (self.has_any({'Siege Tank', 'Diamondback', 'Marauder'}, player) or get_option_value(multiworld, player, 'required_tactics') > 0 and self.has_all({'Reaper', "G-4 Clusterbomb"}, player) or self.has_all({'Spectre', 'Psionic Lash'}, player)) - def _sc2wol_able_to_rescue(self, world: MultiWorld, player: int) -> bool: - return self.has_any({'Medivac', 'Hercules', 'Raven', 'Viking'}, player) or get_option_value(world, player, 'required_tactics') > 0 + def _sc2wol_able_to_rescue(self, multiworld: MultiWorld, player: int) -> bool: + return self.has_any({'Medivac', 'Hercules', 'Raven', 'Viking'}, player) or get_option_value(multiworld, player, 'required_tactics') > 0 - def _sc2wol_has_protoss_common_units(self, world: MultiWorld, player: int) -> bool: + def _sc2wol_has_protoss_common_units(self, multiworld: MultiWorld, player: int) -> bool: return self.has_any({'Zealot', 'Immortal', 'Stalker', 'Dark Templar'}, player) \ - or get_option_value(world, player, 'required_tactics') > 0 and self.has_any({'High Templar', 'Dark Templar'}, player) + or get_option_value(multiworld, player, 'required_tactics') > 0 and self.has_any({'High Templar', 'Dark Templar'}, player) - def _sc2wol_has_protoss_medium_units(self, world: MultiWorld, player: int) -> bool: - return self._sc2wol_has_protoss_common_units(world, player) and \ + def _sc2wol_has_protoss_medium_units(self, multiworld: MultiWorld, player: int) -> bool: + return self._sc2wol_has_protoss_common_units(multiworld, player) and \ self.has_any({'Stalker', 'Void Ray', 'Phoenix', 'Carrier'}, player) \ - or get_option_value(world, player, 'required_tactics') > 0 and self.has_any({'High Templar', 'Dark Templar'}, player) + or get_option_value(multiworld, player, 'required_tactics') > 0 and self.has_any({'High Templar', 'Dark Templar'}, player) - def _sc2wol_beats_protoss_deathball(self, world: MultiWorld, player: int) -> bool: - return self.has_any({'Banshee', 'Battlecruiser'}, player) and self._sc2wol_has_competent_anti_air or \ - self._sc2wol_has_competent_comp(world, player) and self._sc2wol_has_air_anti_air(world, player) + def _sc2wol_beats_protoss_deathball(self, multiworld: MultiWorld, player: int) -> bool: + return self.has_any({'Banshee', 'Battlecruiser'}, player) and self._sc2wol_has_competent_anti_air(multiworld, player) or \ + self._sc2wol_has_competent_comp(multiworld, player) and self._sc2wol_has_air_anti_air(multiworld, player) - def _sc2wol_has_mm_upgrade(self, world: MultiWorld, player: int) -> bool: + def _sc2wol_has_mm_upgrade(self, multiworld: MultiWorld, player: int) -> bool: return self.has_any({"Combat Shield (Marine)", "Stabilizer Medpacks (Medic)"}, player) - def _sc2wol_survives_rip_field(self, world: MultiWorld, player: int) -> bool: + def _sc2wol_survives_rip_field(self, multiworld: MultiWorld, player: int) -> bool: return self.has("Battlecruiser", player) or \ - self._sc2wol_has_air(world, player) and \ - self._sc2wol_has_competent_anti_air(world, player) and \ + self._sc2wol_has_air(multiworld, player) and \ + self._sc2wol_has_competent_anti_air(multiworld, player) and \ self.has("Science Vessel", player) - def _sc2wol_has_nukes(self, world: MultiWorld, player: int) -> bool: - return get_option_value(world, player, 'required_tactics') > 0 and self.has_any({'Ghost', 'Spectre'}, player) + def _sc2wol_has_nukes(self, multiworld: MultiWorld, player: int) -> bool: + return get_option_value(multiworld, player, 'required_tactics') > 0 and self.has_any({'Ghost', 'Spectre'}, player) - def _sc2wol_final_mission_requirements(self, world: MultiWorld, player: int): - defense_rating = self._sc2wol_defense_rating(world, player, True) - beats_kerrigan = self.has_any({'Marine', 'Banshee', 'Ghost'}, player) or get_option_value(world, player, 'required_tactics') > 0 - if get_option_value(world, player, 'all_in_map') == 0: + def _sc2wol_final_mission_requirements(self, multiworld: MultiWorld, player: int): + beats_kerrigan = self.has_any({'Marine', 'Banshee', 'Ghost'}, player) or get_option_value(multiworld, player, 'required_tactics') > 0 + if get_option_value(multiworld, player, 'all_in_map') == 0: # Ground + defense_rating = self._sc2wol_defense_rating(multiworld, player, True, False) if self.has_any({'Battlecruiser', 'Banshee'}, player): defense_rating += 3 return defense_rating >= 12 and beats_kerrigan else: # Air + defense_rating = self._sc2wol_defense_rating(multiworld, player, True, True) return defense_rating >= 8 and beats_kerrigan \ and self.has_any({'Viking', 'Battlecruiser'}, player) \ and self.has_any({'Hive Mind Emulator', 'Psi Disruptor', 'Missile Turret'}, player) - def _sc2wol_cleared_missions(self, world: MultiWorld, player: int, mission_count: int) -> bool: + def _sc2wol_cleared_missions(self, multiworld: MultiWorld, player: int, mission_count: int) -> bool: return self.has_group("Missions", player, mission_count) diff --git a/worlds/sc2wol/MissionTables.py b/worlds/sc2wol/MissionTables.py index 8d069446..d926ea62 100644 --- a/worlds/sc2wol/MissionTables.py +++ b/worlds/sc2wol/MissionTables.py @@ -197,12 +197,12 @@ advanced_starting_mission_locations = { } -def get_starting_mission_locations(world: MultiWorld, player: int) -> Set[str]: - if get_option_value(world, player, 'shuffle_no_build') or get_option_value(world, player, 'mission_order') < 2: +def get_starting_mission_locations(multiworld: MultiWorld, player: int) -> Set[str]: + if get_option_value(multiworld, player, 'shuffle_no_build') or get_option_value(multiworld, player, 'mission_order') < 2: # Always start with a no-build mission unless explicitly relegating them # Vanilla and Vanilla Shuffled always start with a no-build even when relegated return no_build_starting_mission_locations - elif get_option_value(world, player, 'required_tactics') > 0: + elif get_option_value(multiworld, player, 'required_tactics') > 0: # Advanced Tactics/No Logic add more starting missions to the pool return {**build_starting_mission_locations, **advanced_starting_mission_locations} else: diff --git a/worlds/sc2wol/Options.py b/worlds/sc2wol/Options.py index 62780fa2..4526328f 100644 --- a/worlds/sc2wol/Options.py +++ b/worlds/sc2wol/Options.py @@ -130,8 +130,8 @@ sc2wol_options: Dict[str, Option] = { } -def get_option_value(world: MultiWorld, player: int, name: str) -> int: - option = getattr(world, name, None) +def get_option_value(multiworld: MultiWorld, player: int, name: str) -> int: + option = getattr(multiworld, name, None) if option is None: return 0 @@ -139,8 +139,8 @@ def get_option_value(world: MultiWorld, player: int, name: str) -> int: return int(option[player].value) -def get_option_set_value(world: MultiWorld, player: int, name: str) -> set: - option = getattr(world, name, None) +def get_option_set_value(multiworld: MultiWorld, player: int, name: str) -> set: + option = getattr(multiworld, name, None) if option is None: return set() diff --git a/worlds/sc2wol/PoolFilter.py b/worlds/sc2wol/PoolFilter.py index 91fef13a..c4aa1098 100644 --- a/worlds/sc2wol/PoolFilter.py +++ b/worlds/sc2wol/PoolFilter.py @@ -21,14 +21,14 @@ STARPORT_UNITS = {"Medivac", "Wraith", "Viking", "Banshee", "Battlecruiser", "He PROTOSS_REGIONS = {"A Sinister Turn", "Echoes of the Future", "In Utter Darkness"} -def filter_missions(world: MultiWorld, player: int) -> Dict[str, List[str]]: +def filter_missions(multiworld: MultiWorld, player: int) -> Dict[str, List[str]]: """ Returns a semi-randomly pruned tuple of no-build, easy, medium, and hard mission sets """ - mission_order_type = get_option_value(world, player, "mission_order") - shuffle_protoss = get_option_value(world, player, "shuffle_protoss") - excluded_missions = set(get_option_set_value(world, player, "excluded_missions")) + mission_order_type = get_option_value(multiworld, player, "mission_order") + shuffle_protoss = get_option_value(multiworld, player, "shuffle_protoss") + excluded_missions = set(get_option_set_value(multiworld, player, "excluded_missions")) invalid_mission_names = excluded_missions.difference(vanilla_mission_req_table.keys()) if invalid_mission_names: raise Exception("Error in locked_missions - the following are not valid mission names: " + ", ".join(invalid_mission_names)) @@ -54,17 +54,17 @@ def filter_missions(world: MultiWorld, player: int) -> Dict[str, List[str]]: excluded_missions = excluded_missions.union(PROTOSS_REGIONS) # Replacing All-In on low mission counts if mission_count < 14: - final_mission = world.random.choice([mission for mission in alt_final_mission_locations.keys() if mission not in excluded_missions]) + final_mission = multiworld.random.choice([mission for mission in alt_final_mission_locations.keys() if mission not in excluded_missions]) excluded_missions.add(final_mission) else: final_mission = 'All-In' # Yaml settings determine which missions can be placed in the first slot - mission_pools[0] = [mission for mission in get_starting_mission_locations(world, player).keys() if mission not in excluded_missions] + mission_pools[0] = [mission for mission in get_starting_mission_locations(multiworld, player).keys() if mission not in excluded_missions] # Removing the new no-build missions from their original sets for i in range(1, len(mission_pools)): mission_pools[i] = [mission for mission in mission_pools[i] if mission not in excluded_missions.union(mission_pools[0])] # If the first mission is a build mission, there may not be enough locations to reach Outbreak as a second mission - if not get_option_value(world, player, 'shuffle_no_build'): + if not get_option_value(multiworld, player, 'shuffle_no_build'): # Swapping Outbreak and The Great Train Robbery if "Outbreak" in mission_pools[1]: mission_pools[1].remove("Outbreak") @@ -87,7 +87,7 @@ def filter_missions(world: MultiWorld, player: int) -> Dict[str, List[str]]: if all(len(mission_pool) <= 1 for mission_pool in mission_pools): raise Exception("Not enough missions available to fill the campaign on current settings. Please exclude fewer missions.") else: - mission_pool.remove(world.random.choice(mission_pool)) + mission_pool.remove(multiworld.random.choice(mission_pool)) current_count -= 1 set_cycle += 1 @@ -134,7 +134,7 @@ class ValidInventory: } requirements = mission_requirements cascade_keys = self.cascade_removal_map.keys() - units_always_have_upgrades = get_option_value(self.world, self.player, "units_always_have_upgrades") + units_always_have_upgrades = get_option_value(self.multiworld, self.player, "units_always_have_upgrades") if self.min_units_per_structure > 0: requirements.append(lambda state: state.has_units_per_structure()) @@ -155,7 +155,7 @@ class ValidInventory: if len(inventory) == 0: raise Exception("Reduced item pool generation failed - not enough locations available to place items.") # Select random item from removable items - item = self.world.random.choice(inventory) + item = self.multiworld.random.choice(inventory) # Cascade removals to associated items if item in cascade_keys: items_to_remove = self.cascade_removal_map[item] @@ -206,10 +206,10 @@ class ValidInventory: self._sc2wol_has_mm_upgrade = lambda world, player: SC2WoLLogic._sc2wol_has_mm_upgrade(self, world, player) self._sc2wol_final_mission_requirements = lambda world, player: SC2WoLLogic._sc2wol_final_mission_requirements(self, world, player) - def __init__(self, world: MultiWorld, player: int, + def __init__(self, multiworld: MultiWorld, player: int, item_pool: List[Item], existing_items: List[Item], locked_items: List[Item], has_protoss: bool): - self.world = world + self.multiworld = multiworld self.player = player self.logical_inventory = set() self.locked_items = locked_items[:] @@ -219,7 +219,7 @@ class ValidInventory: self.item_pool = [] item_quantities: dict[str, int] = dict() # Inventory restrictiveness based on number of missions with checks - mission_order_type = get_option_value(self.world, self.player, "mission_order") + mission_order_type = get_option_value(self.multiworld, self.player, "mission_order") mission_count = len(mission_orders[mission_order_type]) - 1 self.min_units_per_structure = int(mission_count / 7) min_upgrades = 1 if mission_count < 10 else 2 @@ -244,12 +244,12 @@ class ValidInventory: upgrades = get_item_upgrades(self.item_pool, item) associated_items = [*upgrades, item] self.cascade_removal_map[item] = associated_items - if get_option_value(world, player, "units_always_have_upgrades"): + if get_option_value(multiworld, player, "units_always_have_upgrades"): for upgrade in upgrades: self.cascade_removal_map[upgrade] = associated_items -def filter_items(world: MultiWorld, player: int, mission_req_table: Dict[str, MissionInfo], location_cache: List[Location], +def filter_items(multiworld: MultiWorld, player: int, mission_req_table: Dict[str, MissionInfo], location_cache: List[Location], item_pool: List[Item], existing_items: List[Item], locked_items: List[Item]) -> List[Item]: """ Returns a semi-randomly pruned set of items based on number of available locations. @@ -259,7 +259,7 @@ def filter_items(world: MultiWorld, player: int, mission_req_table: Dict[str, Mi inventory_size = len(open_locations) has_protoss = bool(PROTOSS_REGIONS.intersection(mission_req_table.keys())) mission_requirements = [location.access_rule for location in location_cache] - valid_inventory = ValidInventory(world, player, item_pool, existing_items, locked_items, has_protoss) + valid_inventory = ValidInventory(multiworld, player, item_pool, existing_items, locked_items, has_protoss) valid_items = valid_inventory.generate_reduced_inventory(inventory_size, mission_requirements) return valid_items diff --git a/worlds/sc2wol/Regions.py b/worlds/sc2wol/Regions.py index d42a417b..a714b8fd 100644 --- a/worlds/sc2wol/Regions.py +++ b/worlds/sc2wol/Regions.py @@ -4,23 +4,22 @@ from .Locations import LocationData from .Options import get_option_value from .MissionTables import MissionInfo, mission_orders, vanilla_mission_req_table, alt_final_mission_locations from .PoolFilter import filter_missions -import random -def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData, ...], location_cache: List[Location])\ +def create_regions(multiworld: MultiWorld, player: int, locations: Tuple[LocationData, ...], location_cache: List[Location])\ -> Tuple[Dict[str, MissionInfo], int, str]: locations_per_region = get_locations_per_region(locations) - mission_order_type = get_option_value(world, player, "mission_order") + mission_order_type = get_option_value(multiworld, player, "mission_order") mission_order = mission_orders[mission_order_type] - mission_pools = filter_missions(world, player) + mission_pools = filter_missions(multiworld, player) final_mission = mission_pools['all_in'][0] used_regions = [mission for mission_pool in mission_pools.values() for mission in mission_pool] - regions = [create_region(world, player, locations_per_region, location_cache, "Menu")] + regions = [create_region(multiworld, player, locations_per_region, location_cache, "Menu")] for region_name in used_regions: - regions.append(create_region(world, player, locations_per_region, location_cache, region_name)) + regions.append(create_region(multiworld, player, locations_per_region, location_cache, region_name)) # Changing the completion condition for alternate final missions into an event if final_mission != 'All-In': final_location = alt_final_mission_locations[final_mission] @@ -38,76 +37,76 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData if mission_order_type in (0, 1): throwIfAnyLocationIsNotAssignedToARegion(regions, locations_per_region.keys()) - world.regions += regions + multiworld.regions += regions names: Dict[str, int] = {} if mission_order_type == 0: - connect(world, player, names, 'Menu', 'Liberation Day'), - connect(world, player, names, 'Liberation Day', 'The Outlaws', + connect(multiworld, player, names, 'Menu', 'Liberation Day'), + connect(multiworld, player, names, 'Liberation Day', 'The Outlaws', lambda state: state.has("Beat Liberation Day", player)), - connect(world, player, names, 'The Outlaws', 'Zero Hour', + connect(multiworld, player, names, 'The Outlaws', 'Zero Hour', lambda state: state.has("Beat The Outlaws", player)), - connect(world, player, names, 'Zero Hour', 'Evacuation', + connect(multiworld, player, names, 'Zero Hour', 'Evacuation', lambda state: state.has("Beat Zero Hour", player)), - connect(world, player, names, 'Evacuation', 'Outbreak', + connect(multiworld, player, names, 'Evacuation', 'Outbreak', lambda state: state.has("Beat Evacuation", player)), - connect(world, player, names, "Outbreak", "Safe Haven", - lambda state: state._sc2wol_cleared_missions(world, player, 7) and + connect(multiworld, player, names, "Outbreak", "Safe Haven", + lambda state: state._sc2wol_cleared_missions(multiworld, player, 7) and state.has("Beat Outbreak", player)), - connect(world, player, names, "Outbreak", "Haven's Fall", - lambda state: state._sc2wol_cleared_missions(world, player, 7) and + connect(multiworld, player, names, "Outbreak", "Haven's Fall", + lambda state: state._sc2wol_cleared_missions(multiworld, player, 7) and state.has("Beat Outbreak", player)), - connect(world, player, names, 'Zero Hour', 'Smash and Grab', + connect(multiworld, player, names, 'Zero Hour', 'Smash and Grab', lambda state: state.has("Beat Zero Hour", player)), - connect(world, player, names, 'Smash and Grab', 'The Dig', - lambda state: state._sc2wol_cleared_missions(world, player, 8) and + connect(multiworld, player, names, 'Smash and Grab', 'The Dig', + lambda state: state._sc2wol_cleared_missions(multiworld, player, 8) and state.has("Beat Smash and Grab", player)), - connect(world, player, names, 'The Dig', 'The Moebius Factor', - lambda state: state._sc2wol_cleared_missions(world, player, 11) and + connect(multiworld, player, names, 'The Dig', 'The Moebius Factor', + lambda state: state._sc2wol_cleared_missions(multiworld, player, 11) and state.has("Beat The Dig", player)), - connect(world, player, names, 'The Moebius Factor', 'Supernova', - lambda state: state._sc2wol_cleared_missions(world, player, 14) and + connect(multiworld, player, names, 'The Moebius Factor', 'Supernova', + lambda state: state._sc2wol_cleared_missions(multiworld, player, 14) and state.has("Beat The Moebius Factor", player)), - connect(world, player, names, 'Supernova', 'Maw of the Void', + connect(multiworld, player, names, 'Supernova', 'Maw of the Void', lambda state: state.has("Beat Supernova", player)), - connect(world, player, names, 'Zero Hour', "Devil's Playground", - lambda state: state._sc2wol_cleared_missions(world, player, 4) and + connect(multiworld, player, names, 'Zero Hour', "Devil's Playground", + lambda state: state._sc2wol_cleared_missions(multiworld, player, 4) and state.has("Beat Zero Hour", player)), - connect(world, player, names, "Devil's Playground", 'Welcome to the Jungle', + connect(multiworld, player, names, "Devil's Playground", 'Welcome to the Jungle', lambda state: state.has("Beat Devil's Playground", player)), - connect(world, player, names, "Welcome to the Jungle", 'Breakout', - lambda state: state._sc2wol_cleared_missions(world, player, 8) and + connect(multiworld, player, names, "Welcome to the Jungle", 'Breakout', + lambda state: state._sc2wol_cleared_missions(multiworld, player, 8) and state.has("Beat Welcome to the Jungle", player)), - connect(world, player, names, "Welcome to the Jungle", 'Ghost of a Chance', - lambda state: state._sc2wol_cleared_missions(world, player, 8) and + connect(multiworld, player, names, "Welcome to the Jungle", 'Ghost of a Chance', + lambda state: state._sc2wol_cleared_missions(multiworld, player, 8) and state.has("Beat Welcome to the Jungle", player)), - connect(world, player, names, "Zero Hour", 'The Great Train Robbery', - lambda state: state._sc2wol_cleared_missions(world, player, 6) and + connect(multiworld, player, names, "Zero Hour", 'The Great Train Robbery', + lambda state: state._sc2wol_cleared_missions(multiworld, player, 6) and state.has("Beat Zero Hour", player)), - connect(world, player, names, 'The Great Train Robbery', 'Cutthroat', + connect(multiworld, player, names, 'The Great Train Robbery', 'Cutthroat', lambda state: state.has("Beat The Great Train Robbery", player)), - connect(world, player, names, 'Cutthroat', 'Engine of Destruction', + connect(multiworld, player, names, 'Cutthroat', 'Engine of Destruction', lambda state: state.has("Beat Cutthroat", player)), - connect(world, player, names, 'Engine of Destruction', 'Media Blitz', + connect(multiworld, player, names, 'Engine of Destruction', 'Media Blitz', lambda state: state.has("Beat Engine of Destruction", player)), - connect(world, player, names, 'Media Blitz', 'Piercing the Shroud', + connect(multiworld, player, names, 'Media Blitz', 'Piercing the Shroud', lambda state: state.has("Beat Media Blitz", player)), - connect(world, player, names, 'The Dig', 'Whispers of Doom', + connect(multiworld, player, names, 'The Dig', 'Whispers of Doom', lambda state: state.has("Beat The Dig", player)), - connect(world, player, names, 'Whispers of Doom', 'A Sinister Turn', + connect(multiworld, player, names, 'Whispers of Doom', 'A Sinister Turn', lambda state: state.has("Beat Whispers of Doom", player)), - connect(world, player, names, 'A Sinister Turn', 'Echoes of the Future', + connect(multiworld, player, names, 'A Sinister Turn', 'Echoes of the Future', lambda state: state.has("Beat A Sinister Turn", player)), - connect(world, player, names, 'Echoes of the Future', 'In Utter Darkness', + connect(multiworld, player, names, 'Echoes of the Future', 'In Utter Darkness', lambda state: state.has("Beat Echoes of the Future", player)), - connect(world, player, names, 'Maw of the Void', 'Gates of Hell', + connect(multiworld, player, names, 'Maw of the Void', 'Gates of Hell', lambda state: state.has("Beat Maw of the Void", player)), - connect(world, player, names, 'Gates of Hell', 'Belly of the Beast', + connect(multiworld, player, names, 'Gates of Hell', 'Belly of the Beast', lambda state: state.has("Beat Gates of Hell", player)), - connect(world, player, names, 'Gates of Hell', 'Shatter the Sky', + connect(multiworld, player, names, 'Gates of Hell', 'Shatter the Sky', lambda state: state.has("Beat Gates of Hell", player)), - connect(world, player, names, 'Gates of Hell', 'All-In', + connect(multiworld, player, names, 'Gates of Hell', 'All-In', lambda state: state.has('Beat Gates of Hell', player) and ( state.has('Beat Shatter the Sky', player) or state.has('Beat Belly of the Beast', player))) @@ -122,13 +121,13 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData missions.append(None) elif mission.type == "all_in": missions.append(final_mission) - elif mission.relegate and not get_option_value(world, player, "shuffle_no_build"): + elif mission.relegate and not get_option_value(multiworld, player, "shuffle_no_build"): missions.append("no_build") else: missions.append(mission.type) # Place Protoss Missions if we are not using ShuffleProtoss and are in Vanilla Shuffled - if get_option_value(world, player, "shuffle_protoss") == 0 and mission_order_type == 1: + if get_option_value(multiworld, player, "shuffle_protoss") == 0 and mission_order_type == 1: missions[22] = "A Sinister Turn" mission_pools['medium'].remove("A Sinister Turn") missions[23] = "Echoes of the Future" @@ -157,28 +156,28 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData # Add no_build missions to the pool and fill in no_build slots missions_to_add = mission_pools['no_build'] for slot in no_build_slots: - filler = world.random.randint(0, len(missions_to_add)-1) + filler = multiworld.random.randint(0, len(missions_to_add) - 1) missions[slot] = missions_to_add.pop(filler) # Add easy missions into pool and fill in easy slots missions_to_add = missions_to_add + mission_pools['easy'] for slot in easy_slots: - filler = world.random.randint(0, len(missions_to_add) - 1) + filler = multiworld.random.randint(0, len(missions_to_add) - 1) missions[slot] = missions_to_add.pop(filler) # Add medium missions into pool and fill in medium slots missions_to_add = missions_to_add + mission_pools['medium'] for slot in medium_slots: - filler = world.random.randint(0, len(missions_to_add) - 1) + filler = multiworld.random.randint(0, len(missions_to_add) - 1) missions[slot] = missions_to_add.pop(filler) # Add hard missions into pool and fill in hard slots missions_to_add = missions_to_add + mission_pools['hard'] for slot in hard_slots: - filler = world.random.randint(0, len(missions_to_add) - 1) + filler = multiworld.random.randint(0, len(missions_to_add) - 1) missions[slot] = missions_to_add.pop(filler) @@ -189,11 +188,11 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData connections = [] for connection in mission_order[i].connect_to: if connection == -1: - connect(world, player, names, "Menu", missions[i]) + connect(multiworld, player, names, "Menu", missions[i]) else: - connect(world, player, names, missions[connection], missions[i], + connect(multiworld, player, names, missions[connection], missions[i], (lambda name, missions_req: (lambda state: state.has(f"Beat {name}", player) and - state._sc2wol_cleared_missions(world, player, + state._sc2wol_cleared_missions(multiworld, player, missions_req))) (missions[connection], mission_order[i].number)) connections.append(connection + 1) @@ -233,10 +232,10 @@ def create_location(player: int, location_data: LocationData, region: Region, return location -def create_region(world: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]], +def create_region(multiworld: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]], location_cache: List[Location], name: str) -> Region: region = Region(name, RegionType.Generic, name, player) - region.multiworld = world + region.multiworld = multiworld if name in locations_per_region: for location_data in locations_per_region[name]: diff --git a/worlds/sc2wol/__init__.py b/worlds/sc2wol/__init__.py index 2e13deb0..878f3882 100644 --- a/worlds/sc2wol/__init__.py +++ b/worlds/sc2wol/__init__.py @@ -48,8 +48,8 @@ class SC2WoLWorld(World): victory_item: str required_client_version = 0, 3, 6 - def __init__(self, world: MultiWorld, player: int): - super(SC2WoLWorld, self).__init__(world, player) + def __init__(self, multiworld: MultiWorld, player: int): + super(SC2WoLWorld, self).__init__(multiworld, player) self.location_cache = [] self.locked_locations = [] @@ -63,7 +63,7 @@ class SC2WoLWorld(World): ) def generate_basic(self): - excluded_items = get_excluded_items(self, self.multiworld, self.player) + excluded_items = get_excluded_items(self.multiworld, self.player) starter_items = assign_starter_items(self.multiworld, self.player, excluded_items, self.locked_locations) @@ -74,7 +74,7 @@ class SC2WoLWorld(World): self.multiworld.itempool += pool def set_rules(self): - setup_events(self.multiworld, self.player, self.locked_locations, self.location_cache) + setup_events(self.player, self.locked_locations, self.location_cache) self.multiworld.completion_condition[self.player] = lambda state: state.has(self.victory_item, self.player) def get_filler_item_name(self) -> str: @@ -95,7 +95,7 @@ class SC2WoLWorld(World): return slot_data -def setup_events(world: MultiWorld, player: int, locked_locations: typing.List[str], location_cache: typing.List[Location]): +def setup_events(player: int, locked_locations: typing.List[str], location_cache: typing.List[Location]): for location in location_cache: if location.address is None: item = Item(location.name, ItemClassification.progression, None, player) @@ -105,39 +105,39 @@ def setup_events(world: MultiWorld, player: int, locked_locations: typing.List[s location.place_locked_item(item) -def get_excluded_items(self: SC2WoLWorld, world: MultiWorld, player: int) -> Set[str]: +def get_excluded_items(multiworld: MultiWorld, player: int) -> Set[str]: excluded_items: Set[str] = set() - if get_option_value(world, player, "upgrade_bonus") == 1: + if get_option_value(multiworld, player, "upgrade_bonus") == 1: excluded_items.add("Ultra-Capacitors") else: excluded_items.add("Vanadium Plating") - if get_option_value(world, player, "bunker_upgrade") == 1: + if get_option_value(multiworld, player, "bunker_upgrade") == 1: excluded_items.add("Shrike Turret") else: excluded_items.add("Fortified Bunker") - for item in world.precollected_items[player]: + for item in multiworld.precollected_items[player]: excluded_items.add(item.name) - excluded_items_option = getattr(world, 'excluded_items', []) + excluded_items_option = getattr(multiworld, 'excluded_items', []) excluded_items.update(excluded_items_option[player].value) return excluded_items -def assign_starter_items(world: MultiWorld, player: int, excluded_items: Set[str], locked_locations: List[str]) -> List[Item]: - non_local_items = world.non_local_items[player].value - if get_option_value(world, player, "early_unit"): - local_basic_unit = tuple(item for item in get_basic_units(world, player) if item not in non_local_items and item not in excluded_items) +def assign_starter_items(multiworld: MultiWorld, player: int, excluded_items: Set[str], locked_locations: List[str]) -> List[Item]: + non_local_items = multiworld.non_local_items[player].value + if get_option_value(multiworld, player, "early_unit"): + local_basic_unit = sorted(item for item in get_basic_units(multiworld, player) if item not in non_local_items and item not in excluded_items) if not local_basic_unit: raise Exception("At least one basic unit must be local") # The first world should also be the starting world - first_mission = list(world.worlds[player].mission_req_table)[0] - starting_mission_locations = get_starting_mission_locations(world, player) + first_mission = list(multiworld.worlds[player].mission_req_table)[0] + starting_mission_locations = get_starting_mission_locations(multiworld, player) if first_mission in starting_mission_locations: first_location = starting_mission_locations[first_mission] elif first_mission == "In Utter Darkness": @@ -145,28 +145,28 @@ def assign_starter_items(world: MultiWorld, player: int, excluded_items: Set[str else: first_location = first_mission + ": Victory" - return [assign_starter_item(world, player, excluded_items, locked_locations, first_location, local_basic_unit)] + return [assign_starter_item(multiworld, player, excluded_items, locked_locations, first_location, local_basic_unit)] else: return [] -def assign_starter_item(world: MultiWorld, player: int, excluded_items: Set[str], locked_locations: List[str], +def assign_starter_item(multiworld: MultiWorld, player: int, excluded_items: Set[str], locked_locations: List[str], location: str, item_list: Tuple[str, ...]) -> Item: - item_name = world.random.choice(item_list) + item_name = multiworld.random.choice(item_list) excluded_items.add(item_name) - item = create_item_with_correct_settings(world, player, item_name) + item = create_item_with_correct_settings(player, item_name) - world.get_location(location, player).place_locked_item(item) + multiworld.get_location(location, player).place_locked_item(item) locked_locations.append(location) return item -def get_item_pool(world: MultiWorld, player: int, mission_req_table: Dict[str, MissionInfo], +def get_item_pool(multiworld: MultiWorld, player: int, mission_req_table: Dict[str, MissionInfo], starter_items: List[str], excluded_items: Set[str], location_cache: List[Location]) -> List[Item]: pool: List[Item] = [] @@ -174,18 +174,18 @@ def get_item_pool(world: MultiWorld, player: int, mission_req_table: Dict[str, M locked_items = [] # YAML items - yaml_locked_items = get_option_set_value(world, player, 'locked_items') + yaml_locked_items = get_option_set_value(multiworld, player, 'locked_items') for name, data in item_table.items(): if name not in excluded_items: for _ in range(data.quantity): - item = create_item_with_correct_settings(world, player, name) + item = create_item_with_correct_settings(player, name) if name in yaml_locked_items: locked_items.append(item) else: pool.append(item) - existing_items = starter_items + [item for item in world.precollected_items[player]] + existing_items = starter_items + [item for item in multiworld.precollected_items[player]] existing_names = [item.name for item in existing_items] # Removing upgrades for excluded items for item_name in excluded_items: @@ -195,18 +195,18 @@ def get_item_pool(world: MultiWorld, player: int, mission_req_table: Dict[str, M for invalid_upgrade in invalid_upgrades: pool.remove(invalid_upgrade) - filtered_pool = filter_items(world, player, mission_req_table, location_cache, pool, existing_items, locked_items) + filtered_pool = filter_items(multiworld, player, mission_req_table, location_cache, pool, existing_items, locked_items) return filtered_pool -def fill_item_pool_with_dummy_items(self: SC2WoLWorld, world: MultiWorld, player: int, locked_locations: List[str], +def fill_item_pool_with_dummy_items(self: SC2WoLWorld, multiworld: MultiWorld, player: int, locked_locations: List[str], location_cache: List[Location], pool: List[Item]): for _ in range(len(location_cache) - len(locked_locations) - len(pool)): - item = create_item_with_correct_settings(world, player, self.get_filler_item_name()) + item = create_item_with_correct_settings(player, self.get_filler_item_name()) pool.append(item) -def create_item_with_correct_settings(world: MultiWorld, player: int, name: str) -> Item: +def create_item_with_correct_settings(player: int, name: str) -> Item: data = item_table[name] item = Item(name, data.classification, data.code, player)