From fc35736ef86ba9910edd61ad020d0cae779d8f8f Mon Sep 17 00:00:00 2001 From: Matthew Date: Fri, 5 Jul 2024 23:22:38 -0700 Subject: [PATCH 1/2] sc2: Misc code improvements: * Use sc2mission enum as source-of-truth for mission names * Added missing scorcher unit description * Devastator turrets now improve defense rating * added a unit test to ensure vanilla mission order generates --- worlds/sc2/item_descriptions.py | 1 + worlds/sc2/items.py | 1 + worlds/sc2/locations.py | 3523 +++++++++++++++--------------- worlds/sc2/mission_tables.py | 9 +- worlds/sc2/regions.py | 1446 ++++++------ worlds/sc2/test/test_usecases.py | 15 + 6 files changed, 2506 insertions(+), 2489 deletions(-) diff --git a/worlds/sc2/item_descriptions.py b/worlds/sc2/item_descriptions.py index 82e47ff0ac3e..5dbd15e5fb92 100644 --- a/worlds/sc2/item_descriptions.py +++ b/worlds/sc2/item_descriptions.py @@ -739,6 +739,7 @@ def _ability_desc(unit_name_plural: str, ability_name: str, ability_description: item_names.CORSAIR: "Air superiority starfighter. Can use the Disruption Web ability.", item_names.DESTROYER: "Area assault craft. Can use the Destruction Beam ability to attack multiple units at once.", item_names.WARP_RAY: "Surgical-strike craft. Damage output increases the longer the Warp Ray remains on target.", + item_names.SCORCHER: "Flying Assault Ship. Can use prismatic alignment to temporarily deal increased damage at the cost of movement speed.", item_names.SCOUT: "Versatile high-speed fighter.", item_names.TEMPEST: "Siege artillery craft. Attacks from long range. Can use the Disintegration ability.", item_names.MOTHERSHIP: "Ultimate Protoss vessel, Can use the Vortex and Mass Recall abilities. Cloaks nearby units and structures.", diff --git a/worlds/sc2/items.py b/worlds/sc2/items.py index 9cf13bb9e2bd..ca9dbff73778 100644 --- a/worlds/sc2/items.py +++ b/worlds/sc2/items.py @@ -1952,6 +1952,7 @@ def get_basic_units(world: 'SC2World', race: SC2Race) -> typing.Set[str]: item_names.PLANETARY_FORTRESS: 3, # Bunker w/ Marine/Marauder: 3, item_names.PERDITION_TURRET: 2, + item_names.DEVASTATOR_TURRET: 2, item_names.VULTURE: 1, item_names.BANSHEE: 1, item_names.BATTLECRUISER: 1, diff --git a/worlds/sc2/locations.py b/worlds/sc2/locations.py index fc4680a5ff2a..385e210fd9b2 100644 --- a/worlds/sc2/locations.py +++ b/worlds/sc2/locations.py @@ -1,1762 +1,1763 @@ -from enum import IntEnum -from typing import List, Tuple, Optional, Callable, NamedTuple, Set, Any, TYPE_CHECKING -from . import item_names -from .options import (VanillaItemsOnly, get_option_value, RequiredTactics, - LocationInclusion, KerriganPresence, -) -from .rules import SC2Logic - -from BaseClasses import Location -from worlds.AutoWorld import World - -if TYPE_CHECKING: - from BaseClasses import CollectionState - from . import SC2World - -SC2WOL_LOC_ID_OFFSET = 1000 -SC2HOTS_LOC_ID_OFFSET = 20000000 # Avoid clashes with The Legend of Zelda -SC2LOTV_LOC_ID_OFFSET = SC2HOTS_LOC_ID_OFFSET + 2000 -SC2NCO_LOC_ID_OFFSET = SC2LOTV_LOC_ID_OFFSET + 2500 -SC2_RACESWAP_LOC_ID_OFFSET = SC2NCO_LOC_ID_OFFSET + 900 - - -class SC2Location(Location): - game: str = "Starcraft2" - - -class LocationType(IntEnum): - VICTORY = 0 # Winning a mission - VANILLA = 1 # Objectives that provided metaprogression in the original campaign, along with a few other locations for a balanced experience - EXTRA = 2 # Additional locations based on mission progression, collecting in-mission rewards, etc. that do not significantly increase the challenge. - CHALLENGE = 3 # Challenging objectives, often harder than just completing a mission, and often associated with Achievements - MASTERY = 4 # Extremely challenging objectives often associated with Masteries and Feats of Strength in the original campaign - - -class LocationData(NamedTuple): - region: str - name: str - code: int - type: LocationType - rule: Callable[['CollectionState'], bool] = Location.access_rule - - -def get_location_types(world: 'SC2World', inclusion_type: int) -> Set[LocationType]: - """ - - :param multiworld: - :param player: - :param inclusion_type: Level of inclusion to check for - :return: A list of location types that match the inclusion type - """ - exclusion_options = [ - ("vanilla_locations", LocationType.VANILLA), - ("extra_locations", LocationType.EXTRA), - ("challenge_locations", LocationType.CHALLENGE), - ("mastery_locations", LocationType.MASTERY) - ] - excluded_location_types = set() - for option_name, location_type in exclusion_options: - if get_option_value(world, option_name) is inclusion_type: - excluded_location_types.add(location_type) - return excluded_location_types - - -def get_plando_locations(world: World) -> List[str]: - """ - - :param multiworld: - :param player: - :return: A list of locations affected by a plando in a world - """ - if world is None: - return [] - plando_locations = [] - for plando_setting in world.multiworld.plando_items[world.player]: - plando_locations += plando_setting.get("locations", []) - plando_setting_location = plando_setting.get("location", None) - if plando_setting_location is not None: - plando_locations.append(plando_setting_location) - - return plando_locations - - -def get_locations(world: Optional['SC2World']) -> Tuple[LocationData, ...]: - # Note: rules which are ended with or True are rules identified as needed later when restricted units is an option - if world is None: - logic_level = int(RequiredTactics.default) - kerriganless = False - else: - logic_level = world.options.required_tactics.value - kerriganless = ( - world.options.kerrigan_presence.value != KerriganPresence.option_vanilla - or not world.options.enable_hots_missions.value - ) - adv_tactics = logic_level != RequiredTactics.option_standard - logic = SC2Logic(world) - player = 1 if world is None else world.player - location_table: List[LocationData] = [ - # WoL - LocationData("Liberation Day", "Liberation Day: Victory", SC2WOL_LOC_ID_OFFSET + 100, LocationType.VICTORY), - LocationData("Liberation Day", "Liberation Day: First Statue", SC2WOL_LOC_ID_OFFSET + 101, LocationType.VANILLA), - LocationData("Liberation Day", "Liberation Day: Second Statue", SC2WOL_LOC_ID_OFFSET + 102, LocationType.VANILLA), - LocationData("Liberation Day", "Liberation Day: Third Statue", SC2WOL_LOC_ID_OFFSET + 103, LocationType.VANILLA), - LocationData("Liberation Day", "Liberation Day: Fourth Statue", SC2WOL_LOC_ID_OFFSET + 104, LocationType.VANILLA), - LocationData("Liberation Day", "Liberation Day: Fifth Statue", SC2WOL_LOC_ID_OFFSET + 105, LocationType.VANILLA), - LocationData("Liberation Day", "Liberation Day: Sixth Statue", SC2WOL_LOC_ID_OFFSET + 106, LocationType.VANILLA), - LocationData("Liberation Day", "Liberation Day: Special Delivery", SC2WOL_LOC_ID_OFFSET + 107, LocationType.EXTRA), - LocationData("Liberation Day", "Liberation Day: Transport", SC2WOL_LOC_ID_OFFSET + 108, LocationType.EXTRA), - LocationData("The Outlaws (Terran)", "The Outlaws (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 200, LocationType.VICTORY, - lambda state: logic.terran_early_tech(state)), - LocationData("The Outlaws (Terran)", "The Outlaws (Terran): Rebel Base", SC2WOL_LOC_ID_OFFSET + 201, LocationType.VANILLA, - lambda state: logic.terran_early_tech(state)), - LocationData("The Outlaws (Terran)", "The Outlaws (Terran): North Resource Pickups", SC2WOL_LOC_ID_OFFSET + 202, LocationType.EXTRA, - lambda state: logic.terran_early_tech(state)), - LocationData("The Outlaws (Terran)", "The Outlaws (Terran): Bunker", SC2WOL_LOC_ID_OFFSET + 203, LocationType.VANILLA, - lambda state: logic.terran_early_tech(state)), - LocationData("The Outlaws (Terran)", "The Outlaws (Terran): Close Resource Pickups", SC2WOL_LOC_ID_OFFSET + 204, LocationType.EXTRA), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 300, LocationType.VICTORY, - lambda state: logic.terran_common_unit(state) and - logic.terran_defense_rating(state, True) >= 2 and - (adv_tactics or logic.terran_basic_anti_air(state))), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): First Group Rescued", SC2WOL_LOC_ID_OFFSET + 301, LocationType.VANILLA), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 302, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state)), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 303, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - logic.terran_defense_rating(state, True) >= 2), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): First Hatchery", SC2WOL_LOC_ID_OFFSET + 304, LocationType.CHALLENGE, - lambda state: logic.terran_competent_comp(state)), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Second Hatchery", SC2WOL_LOC_ID_OFFSET + 305, LocationType.CHALLENGE, - lambda state: logic.terran_competent_comp(state)), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Third Hatchery", SC2WOL_LOC_ID_OFFSET + 306, LocationType.CHALLENGE, - lambda state: logic.terran_competent_comp(state)), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Fourth Hatchery", SC2WOL_LOC_ID_OFFSET + 307, LocationType.CHALLENGE, - lambda state: logic.terran_competent_comp(state)), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Ride's on its Way", SC2WOL_LOC_ID_OFFSET + 308, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state)), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Hold Just a Little Longer", SC2WOL_LOC_ID_OFFSET + 309, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_defense_rating(state, True) >= 2), - LocationData("Zero Hour (Terran)", "Zero Hour (Terran): Cavalry's on the Way", SC2WOL_LOC_ID_OFFSET + 310, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_defense_rating(state, True) >= 2), - LocationData("Evacuation", "Evacuation: Victory", SC2WOL_LOC_ID_OFFSET + 400, LocationType.VICTORY, - lambda state: logic.terran_early_tech(state) and - (adv_tactics and logic.terran_basic_anti_air(state) - or logic.terran_competent_anti_air(state))), - LocationData("Evacuation", "Evacuation: North Chrysalis", SC2WOL_LOC_ID_OFFSET + 401, LocationType.VANILLA), - LocationData("Evacuation", "Evacuation: West Chrysalis", SC2WOL_LOC_ID_OFFSET + 402, LocationType.VANILLA, - lambda state: logic.terran_early_tech(state)), - LocationData("Evacuation", "Evacuation: East Chrysalis", SC2WOL_LOC_ID_OFFSET + 403, LocationType.VANILLA, - lambda state: logic.terran_early_tech(state)), - LocationData("Evacuation", "Evacuation: Reach Hanson", SC2WOL_LOC_ID_OFFSET + 404, LocationType.EXTRA), - LocationData("Evacuation", "Evacuation: Secret Resource Stash", SC2WOL_LOC_ID_OFFSET + 405, LocationType.EXTRA), - LocationData("Evacuation", "Evacuation: Flawless", SC2WOL_LOC_ID_OFFSET + 406, LocationType.CHALLENGE, - lambda state: logic.terran_early_tech(state) and - logic.terran_defense_rating(state, True, False) >= 2 and - (adv_tactics and logic.terran_basic_anti_air(state) - or logic.terran_competent_anti_air(state))), - LocationData("Outbreak", "Outbreak: Victory", SC2WOL_LOC_ID_OFFSET + 500, LocationType.VICTORY, - lambda state: logic.terran_defense_rating(state, True, False) >= 4 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Outbreak", "Outbreak: Left Infestor", SC2WOL_LOC_ID_OFFSET + 501, LocationType.VANILLA, - lambda state: logic.terran_defense_rating(state, True, False) >= 2 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Outbreak", "Outbreak: Right Infestor", SC2WOL_LOC_ID_OFFSET + 502, LocationType.VANILLA, - lambda state: logic.terran_defense_rating(state, True, False) >= 2 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Outbreak", "Outbreak: North Infested Command Center", SC2WOL_LOC_ID_OFFSET + 503, LocationType.EXTRA, - lambda state: logic.terran_defense_rating(state, True, False) >= 2 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Outbreak", "Outbreak: South Infested Command Center", SC2WOL_LOC_ID_OFFSET + 504, LocationType.EXTRA, - lambda state: logic.terran_defense_rating(state, True, False) >= 2 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Outbreak", "Outbreak: Northwest Bar", SC2WOL_LOC_ID_OFFSET + 505, LocationType.EXTRA, - lambda state: logic.terran_defense_rating(state, True, False) >= 2 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Outbreak", "Outbreak: North Bar", SC2WOL_LOC_ID_OFFSET + 506, LocationType.EXTRA, - lambda state: logic.terran_defense_rating(state, True, False) >= 2 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Outbreak", "Outbreak: South Bar", SC2WOL_LOC_ID_OFFSET + 507, LocationType.EXTRA, - lambda state: logic.terran_defense_rating(state, True, False) >= 2 and - (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Safe Haven", "Safe Haven: Victory", SC2WOL_LOC_ID_OFFSET + 600, LocationType.VICTORY, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state)), - LocationData("Safe Haven", "Safe Haven: North Nexus", SC2WOL_LOC_ID_OFFSET + 601, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state)), - LocationData("Safe Haven", "Safe Haven: East Nexus", SC2WOL_LOC_ID_OFFSET + 602, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state)), - LocationData("Safe Haven", "Safe Haven: South Nexus", SC2WOL_LOC_ID_OFFSET + 603, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state)), - LocationData("Safe Haven", "Safe Haven: First Terror Fleet", SC2WOL_LOC_ID_OFFSET + 604, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state)), - LocationData("Safe Haven", "Safe Haven: Second Terror Fleet", SC2WOL_LOC_ID_OFFSET + 605, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state)), - LocationData("Safe Haven", "Safe Haven: Third Terror Fleet", SC2WOL_LOC_ID_OFFSET + 606, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state)), - LocationData("Haven's Fall", "Haven's Fall: Victory", SC2WOL_LOC_ID_OFFSET + 700, LocationType.VICTORY, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state) and - logic.terran_defense_rating(state, True) >= 3), - LocationData("Haven's Fall", "Haven's Fall: North Hive", SC2WOL_LOC_ID_OFFSET + 701, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state) and - logic.terran_defense_rating(state, True) >= 3), - LocationData("Haven's Fall", "Haven's Fall: East Hive", SC2WOL_LOC_ID_OFFSET + 702, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state) and - logic.terran_defense_rating(state, True) >= 3), - LocationData("Haven's Fall", "Haven's Fall: South Hive", SC2WOL_LOC_ID_OFFSET + 703, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state) and - logic.terran_defense_rating(state, True) >= 3), - LocationData("Haven's Fall", "Haven's Fall: Northeast Colony Base", SC2WOL_LOC_ID_OFFSET + 704, LocationType.CHALLENGE, - lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData("Haven's Fall", "Haven's Fall: East Colony Base", SC2WOL_LOC_ID_OFFSET + 705, LocationType.CHALLENGE, - lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData("Haven's Fall", "Haven's Fall: Middle Colony Base", SC2WOL_LOC_ID_OFFSET + 706, LocationType.CHALLENGE, - lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData("Haven's Fall", "Haven's Fall: Southeast Colony Base", SC2WOL_LOC_ID_OFFSET + 707, LocationType.CHALLENGE, - lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData("Haven's Fall", "Haven's Fall: Southwest Colony Base", SC2WOL_LOC_ID_OFFSET + 708, LocationType.CHALLENGE, - lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData("Haven's Fall", "Haven's Fall: Southwest Gas Pickups", SC2WOL_LOC_ID_OFFSET + 709, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state) and - logic.terran_defense_rating(state, True) >= 3), - LocationData("Haven's Fall", "Haven's Fall: East Gas Pickups", SC2WOL_LOC_ID_OFFSET + 710, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state) and - logic.terran_defense_rating(state, True) >= 3), - LocationData("Haven's Fall", "Haven's Fall: Southeast Gas Pickups", SC2WOL_LOC_ID_OFFSET + 711, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - logic.terran_competent_anti_air(state) and - logic.terran_defense_rating(state, True) >= 3), - LocationData("Smash and Grab (Terran)", "Smash and Grab (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 800, LocationType.VICTORY, - lambda state: logic.terran_common_unit(state) and - (adv_tactics and logic.terran_basic_anti_air(state) - or logic.terran_competent_anti_air(state))), - LocationData("Smash and Grab (Terran)", "Smash and Grab (Terran): First Relic", SC2WOL_LOC_ID_OFFSET + 801, LocationType.VANILLA), - LocationData("Smash and Grab (Terran)", "Smash and Grab (Terran): Second Relic", SC2WOL_LOC_ID_OFFSET + 802, LocationType.VANILLA), - LocationData("Smash and Grab (Terran)", "Smash and Grab (Terran): Third Relic", SC2WOL_LOC_ID_OFFSET + 803, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - (adv_tactics and logic.terran_basic_anti_air(state) - or logic.terran_competent_anti_air(state))), - LocationData("Smash and Grab (Terran)", "Smash and Grab (Terran): Fourth Relic", SC2WOL_LOC_ID_OFFSET + 804, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state) and - (adv_tactics and logic.terran_basic_anti_air(state) - or logic.terran_competent_anti_air(state))), - LocationData("Smash and Grab (Terran)", "Smash and Grab (Terran): First Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 805, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - (adv_tactics and logic.terran_basic_anti_air(state) - or logic.terran_competent_anti_air(state))), - LocationData("Smash and Grab (Terran)", "Smash and Grab (Terran): Second Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 806, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state) and - (adv_tactics and logic.terran_basic_anti_air(state) - or logic.terran_competent_anti_air(state))), - LocationData("The Dig", "The Dig: Victory", SC2WOL_LOC_ID_OFFSET + 900, LocationType.VICTORY, - lambda state: logic.terran_basic_anti_air(state) - and logic.terran_defense_rating(state, False, True) >= 8 - and logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Dig", "The Dig: Left Relic", SC2WOL_LOC_ID_OFFSET + 901, LocationType.VANILLA, - lambda state: logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Dig", "The Dig: Right Ground Relic", SC2WOL_LOC_ID_OFFSET + 902, LocationType.VANILLA, - lambda state: logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Dig", "The Dig: Right Cliff Relic", SC2WOL_LOC_ID_OFFSET + 903, LocationType.VANILLA, - lambda state: logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Dig", "The Dig: Moebius Base", SC2WOL_LOC_ID_OFFSET + 904, LocationType.EXTRA, - lambda state: logic.marine_medic_upgrade(state) or adv_tactics), - LocationData("The Dig", "The Dig: Door Outer Layer", SC2WOL_LOC_ID_OFFSET + 905, LocationType.EXTRA, - lambda state: logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Dig", "The Dig: Door Thermal Barrier", SC2WOL_LOC_ID_OFFSET + 906, LocationType.EXTRA, - lambda state: logic.terran_basic_anti_air(state) - and logic.terran_defense_rating(state, False, True) >= 8 - and logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Dig", "The Dig: Cutting Through the Core", SC2WOL_LOC_ID_OFFSET + 907, LocationType.EXTRA, - lambda state: logic.terran_basic_anti_air(state) - and logic.terran_defense_rating(state, False, True) >= 8 - and logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Dig", "The Dig: Structure Access Imminent", SC2WOL_LOC_ID_OFFSET + 908, LocationType.EXTRA, - lambda state: logic.terran_basic_anti_air(state) - and logic.terran_defense_rating(state, False, True) >= 8 - and logic.terran_defense_rating(state, False, False) >= 6 - and logic.terran_common_unit(state) - and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData("The Moebius Factor", "The Moebius Factor: Victory", SC2WOL_LOC_ID_OFFSET + 1000, LocationType.VICTORY, - lambda state: logic.terran_basic_anti_air(state) and - (logic.terran_air(state) - or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) - and logic.terran_common_unit(state))), - LocationData("The Moebius Factor", "The Moebius Factor: 1st Data Core", SC2WOL_LOC_ID_OFFSET + 1001, LocationType.VANILLA), - LocationData("The Moebius Factor", "The Moebius Factor: 2nd Data Core", SC2WOL_LOC_ID_OFFSET + 1002, LocationType.VANILLA, - lambda state: (logic.terran_air(state) - or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) - and logic.terran_common_unit(state))), - LocationData("The Moebius Factor", "The Moebius Factor: South Rescue", SC2WOL_LOC_ID_OFFSET + 1003, LocationType.EXTRA, - lambda state: logic.terran_can_rescue(state)), - LocationData("The Moebius Factor", "The Moebius Factor: Wall Rescue", SC2WOL_LOC_ID_OFFSET + 1004, LocationType.EXTRA, - lambda state: logic.terran_can_rescue(state)), - LocationData("The Moebius Factor", "The Moebius Factor: Mid Rescue", SC2WOL_LOC_ID_OFFSET + 1005, LocationType.EXTRA, - lambda state: logic.terran_can_rescue(state)), - LocationData("The Moebius Factor", "The Moebius Factor: Nydus Roof Rescue", SC2WOL_LOC_ID_OFFSET + 1006, LocationType.EXTRA, - lambda state: logic.terran_can_rescue(state)), - LocationData("The Moebius Factor", "The Moebius Factor: Alive Inside Rescue", SC2WOL_LOC_ID_OFFSET + 1007, LocationType.EXTRA, - lambda state: logic.terran_can_rescue(state)), - LocationData("The Moebius Factor", "The Moebius Factor: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1008, LocationType.VANILLA, - lambda state: logic.terran_basic_anti_air(state) and - (logic.terran_air(state) - or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) - and logic.terran_common_unit(state))), - LocationData("The Moebius Factor", "The Moebius Factor: 3rd Data Core", SC2WOL_LOC_ID_OFFSET + 1009, LocationType.VANILLA, - lambda state: logic.terran_basic_anti_air(state) and - (logic.terran_air(state) - or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) - and logic.terran_common_unit(state))), - LocationData("Supernova", "Supernova: Victory", SC2WOL_LOC_ID_OFFSET + 1100, LocationType.VICTORY, - lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData("Supernova", "Supernova: West Relic", SC2WOL_LOC_ID_OFFSET + 1101, LocationType.VANILLA), - LocationData("Supernova", "Supernova: North Relic", SC2WOL_LOC_ID_OFFSET + 1102, LocationType.VANILLA), - LocationData("Supernova", "Supernova: South Relic", SC2WOL_LOC_ID_OFFSET + 1103, LocationType.VANILLA, - lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData("Supernova", "Supernova: East Relic", SC2WOL_LOC_ID_OFFSET + 1104, LocationType.VANILLA, - lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData("Supernova", "Supernova: Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1105, LocationType.EXTRA), - LocationData("Supernova", "Supernova: Middle Base", SC2WOL_LOC_ID_OFFSET + 1106, LocationType.EXTRA, - lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData("Supernova", "Supernova: Southeast Base", SC2WOL_LOC_ID_OFFSET + 1107, LocationType.EXTRA, - lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData("Maw of the Void", "Maw of the Void: Victory", SC2WOL_LOC_ID_OFFSET + 1200, LocationType.VICTORY, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1201, LocationType.EXTRA), - LocationData("Maw of the Void", "Maw of the Void: Expansion Prisoners", SC2WOL_LOC_ID_OFFSET + 1202, LocationType.VANILLA, - lambda state: adv_tactics or logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: South Close Prisoners", SC2WOL_LOC_ID_OFFSET + 1203, LocationType.VANILLA, - lambda state: adv_tactics or logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: South Far Prisoners", SC2WOL_LOC_ID_OFFSET + 1204, LocationType.VANILLA, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: North Prisoners", SC2WOL_LOC_ID_OFFSET + 1205, LocationType.VANILLA, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Mothership", SC2WOL_LOC_ID_OFFSET + 1206, LocationType.EXTRA, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Expansion Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1207, LocationType.EXTRA, - lambda state: adv_tactics or logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Middle Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1208, LocationType.EXTRA, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Southeast Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1209, LocationType.EXTRA, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Stargate Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1210, LocationType.EXTRA, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Northwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1211, LocationType.CHALLENGE, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: West Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1212, LocationType.CHALLENGE, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Maw of the Void", "Maw of the Void: Southwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1213, LocationType.CHALLENGE, - lambda state: logic.terran_survives_rip_field(state)), - LocationData("Devil's Playground", "Devil's Playground: Victory", SC2WOL_LOC_ID_OFFSET + 1300, LocationType.VICTORY, - lambda state: adv_tactics or - logic.terran_basic_anti_air(state) and ( - logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Devil's Playground", "Devil's Playground: Tosh's Miners", SC2WOL_LOC_ID_OFFSET + 1301, LocationType.VANILLA), - LocationData("Devil's Playground", "Devil's Playground: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1302, LocationType.VANILLA, - lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), - LocationData("Devil's Playground", "Devil's Playground: North Reapers", SC2WOL_LOC_ID_OFFSET + 1303, LocationType.EXTRA), - LocationData("Devil's Playground", "Devil's Playground: Middle Reapers", SC2WOL_LOC_ID_OFFSET + 1304, LocationType.EXTRA, - lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), - LocationData("Devil's Playground", "Devil's Playground: Southwest Reapers", SC2WOL_LOC_ID_OFFSET + 1305, LocationType.EXTRA, - lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), - LocationData("Devil's Playground", "Devil's Playground: Southeast Reapers", SC2WOL_LOC_ID_OFFSET + 1306, LocationType.EXTRA, - lambda state: adv_tactics or - logic.terran_basic_anti_air(state) and ( - logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Devil's Playground", "Devil's Playground: East Reapers", SC2WOL_LOC_ID_OFFSET + 1307, LocationType.CHALLENGE, - lambda state: logic.terran_basic_anti_air(state) and - (adv_tactics or - logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Devil's Playground", "Devil's Playground: Zerg Cleared", SC2WOL_LOC_ID_OFFSET + 1308, LocationType.CHALLENGE, - lambda state: logic.terran_competent_anti_air(state) and ( - logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Victory", SC2WOL_LOC_ID_OFFSET + 1400, LocationType.VICTORY, - lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Close Relic", SC2WOL_LOC_ID_OFFSET + 1401, LocationType.VANILLA), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: West Relic", SC2WOL_LOC_ID_OFFSET + 1402, LocationType.VANILLA, - lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: North-East Relic", SC2WOL_LOC_ID_OFFSET + 1403, LocationType.VANILLA, - lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Middle Base", SC2WOL_LOC_ID_OFFSET + 1404, LocationType.EXTRA, - lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Main Base", SC2WOL_LOC_ID_OFFSET + 1405, - LocationType.MASTERY, - lambda state: logic.welcome_to_the_jungle_requirement(state) - and logic.terran_beats_protoss_deathball(state) - and logic.terran_base_trasher(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: No Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1406, LocationType.CHALLENGE, - lambda state: logic.welcome_to_the_jungle_requirement(state) - and logic.terran_competent_ground_to_air(state) - and logic.terran_beats_protoss_deathball(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Up to 1 Terrazine Node Sealed", SC2WOL_LOC_ID_OFFSET + 1407, LocationType.CHALLENGE, - lambda state: logic.welcome_to_the_jungle_requirement(state) - and logic.terran_competent_ground_to_air(state) - and logic.terran_beats_protoss_deathball(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Up to 2 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1408, LocationType.CHALLENGE, - lambda state: logic.welcome_to_the_jungle_requirement(state) - and logic.terran_beats_protoss_deathball(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Up to 3 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1409, LocationType.CHALLENGE, - lambda state: logic.welcome_to_the_jungle_requirement(state) - and logic.terran_competent_comp(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Up to 4 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1410, LocationType.EXTRA, - lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData("Welcome to the Jungle", "Welcome to the Jungle: Up to 5 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1411, LocationType.EXTRA, - lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData("Breakout", "Breakout: Victory", SC2WOL_LOC_ID_OFFSET + 1500, LocationType.VICTORY), - LocationData("Breakout", "Breakout: Diamondback Prison", SC2WOL_LOC_ID_OFFSET + 1501, LocationType.VANILLA), - LocationData("Breakout", "Breakout: Siege Tank Prison", SC2WOL_LOC_ID_OFFSET + 1502, LocationType.VANILLA), - LocationData("Breakout", "Breakout: First Checkpoint", SC2WOL_LOC_ID_OFFSET + 1503, LocationType.EXTRA), - LocationData("Breakout", "Breakout: Second Checkpoint", SC2WOL_LOC_ID_OFFSET + 1504, LocationType.EXTRA), - LocationData("Ghost of a Chance", "Ghost of a Chance: Victory", SC2WOL_LOC_ID_OFFSET + 1600, LocationType.VICTORY), - LocationData("Ghost of a Chance", "Ghost of a Chance: Terrazine Tank", SC2WOL_LOC_ID_OFFSET + 1601, LocationType.EXTRA), - LocationData("Ghost of a Chance", "Ghost of a Chance: Jorium Stockpile", SC2WOL_LOC_ID_OFFSET + 1602, LocationType.EXTRA), - LocationData("Ghost of a Chance", "Ghost of a Chance: First Island Spectres", SC2WOL_LOC_ID_OFFSET + 1603, LocationType.VANILLA), - LocationData("Ghost of a Chance", "Ghost of a Chance: Second Island Spectres", SC2WOL_LOC_ID_OFFSET + 1604, LocationType.VANILLA), - LocationData("Ghost of a Chance", "Ghost of a Chance: Third Island Spectres", SC2WOL_LOC_ID_OFFSET + 1605, LocationType.VANILLA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Victory", SC2WOL_LOC_ID_OFFSET + 1700, LocationType.VICTORY, - lambda state: logic.great_train_robbery_train_stopper(state) and - logic.terran_basic_anti_air(state)), - LocationData("The Great Train Robbery", "The Great Train Robbery: North Defiler", SC2WOL_LOC_ID_OFFSET + 1701, LocationType.VANILLA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Mid Defiler", SC2WOL_LOC_ID_OFFSET + 1702, LocationType.VANILLA), - LocationData("The Great Train Robbery", "The Great Train Robbery: South Defiler", SC2WOL_LOC_ID_OFFSET + 1703, LocationType.VANILLA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Close Diamondback", SC2WOL_LOC_ID_OFFSET + 1704, LocationType.EXTRA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Northwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1705, LocationType.EXTRA), - LocationData("The Great Train Robbery", "The Great Train Robbery: North Diamondback", SC2WOL_LOC_ID_OFFSET + 1706, LocationType.EXTRA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Northeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1707, LocationType.EXTRA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Southwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1708, LocationType.EXTRA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Southeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1709, LocationType.EXTRA), - LocationData("The Great Train Robbery", "The Great Train Robbery: Kill Team", SC2WOL_LOC_ID_OFFSET + 1710, LocationType.CHALLENGE, - lambda state: (adv_tactics or logic.terran_common_unit(state)) and - logic.great_train_robbery_train_stopper(state) and - logic.terran_basic_anti_air(state)), - LocationData("The Great Train Robbery", "The Great Train Robbery: Flawless", SC2WOL_LOC_ID_OFFSET + 1711, LocationType.CHALLENGE, - lambda state: logic.great_train_robbery_train_stopper(state) and - logic.terran_basic_anti_air(state)), - LocationData("The Great Train Robbery", "The Great Train Robbery: 2 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1712, LocationType.EXTRA, - lambda state: logic.great_train_robbery_train_stopper(state)), - LocationData("The Great Train Robbery", "The Great Train Robbery: 4 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1713, LocationType.EXTRA, - lambda state: logic.great_train_robbery_train_stopper(state) and - logic.terran_basic_anti_air(state)), - LocationData("The Great Train Robbery", "The Great Train Robbery: 6 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1714, LocationType.EXTRA, - lambda state: logic.great_train_robbery_train_stopper(state) and - logic.terran_basic_anti_air(state)), - LocationData("Cutthroat", "Cutthroat: Victory", SC2WOL_LOC_ID_OFFSET + 1800, LocationType.VICTORY, - lambda state: logic.terran_common_unit(state) - and (adv_tactics or logic.terran_basic_anti_air(state))), - LocationData("Cutthroat", "Cutthroat: Mira Han", SC2WOL_LOC_ID_OFFSET + 1801, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state)), - LocationData("Cutthroat", "Cutthroat: North Relic", SC2WOL_LOC_ID_OFFSET + 1802, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state)), - LocationData("Cutthroat", "Cutthroat: Mid Relic", SC2WOL_LOC_ID_OFFSET + 1803, LocationType.VANILLA), - LocationData("Cutthroat", "Cutthroat: Southwest Relic", SC2WOL_LOC_ID_OFFSET + 1804, LocationType.VANILLA, - lambda state: logic.terran_common_unit(state)), - LocationData("Cutthroat", "Cutthroat: North Command Center", SC2WOL_LOC_ID_OFFSET + 1805, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state)), - LocationData("Cutthroat", "Cutthroat: South Command Center", SC2WOL_LOC_ID_OFFSET + 1806, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state)), - LocationData("Cutthroat", "Cutthroat: West Command Center", SC2WOL_LOC_ID_OFFSET + 1807, LocationType.EXTRA, - lambda state: logic.terran_common_unit(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Victory", SC2WOL_LOC_ID_OFFSET + 1900, LocationType.VICTORY, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Odin", SC2WOL_LOC_ID_OFFSET + 1901, LocationType.EXTRA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Loki", SC2WOL_LOC_ID_OFFSET + 1902, - LocationType.CHALLENGE, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Lab Devourer", SC2WOL_LOC_ID_OFFSET + 1903, LocationType.VANILLA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Engine of Destruction", "Engine of Destruction: North Devourer", SC2WOL_LOC_ID_OFFSET + 1904, LocationType.VANILLA, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Southeast Devourer", SC2WOL_LOC_ID_OFFSET + 1905, LocationType.VANILLA, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Engine of Destruction", "Engine of Destruction: West Base", SC2WOL_LOC_ID_OFFSET + 1906, LocationType.EXTRA, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Northwest Base", SC2WOL_LOC_ID_OFFSET + 1907, LocationType.EXTRA, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Northeast Base", SC2WOL_LOC_ID_OFFSET + 1908, LocationType.EXTRA, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Engine of Destruction", "Engine of Destruction: Southeast Base", SC2WOL_LOC_ID_OFFSET + 1909, LocationType.EXTRA, - lambda state: logic.engine_of_destruction_requirement(state)), - LocationData("Media Blitz", "Media Blitz: Victory", SC2WOL_LOC_ID_OFFSET + 2000, LocationType.VICTORY, - lambda state: logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: Tower 1", SC2WOL_LOC_ID_OFFSET + 2001, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: Tower 2", SC2WOL_LOC_ID_OFFSET + 2002, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: Tower 3", SC2WOL_LOC_ID_OFFSET + 2003, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: Science Facility", SC2WOL_LOC_ID_OFFSET + 2004, LocationType.VANILLA), - LocationData("Media Blitz", "Media Blitz: All Barracks", SC2WOL_LOC_ID_OFFSET + 2005, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: All Factories", SC2WOL_LOC_ID_OFFSET + 2006, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: All Starports", SC2WOL_LOC_ID_OFFSET + 2007, LocationType.EXTRA, - lambda state: adv_tactics or logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: Odin Not Trashed", SC2WOL_LOC_ID_OFFSET + 2008, LocationType.CHALLENGE, - lambda state: logic.terran_competent_comp(state)), - LocationData("Media Blitz", "Media Blitz: Surprise Attack Ends", SC2WOL_LOC_ID_OFFSET + 2009, LocationType.EXTRA), - LocationData("Piercing the Shroud", "Piercing the Shroud: Victory", SC2WOL_LOC_ID_OFFSET + 2100, LocationType.VICTORY, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Piercing the Shroud", "Piercing the Shroud: Holding Cell Relic", SC2WOL_LOC_ID_OFFSET + 2101, LocationType.VANILLA), - LocationData("Piercing the Shroud", "Piercing the Shroud: Brutalisk Relic", SC2WOL_LOC_ID_OFFSET + 2102, LocationType.VANILLA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Piercing the Shroud", "Piercing the Shroud: First Escape Relic", SC2WOL_LOC_ID_OFFSET + 2103, LocationType.VANILLA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Piercing the Shroud", "Piercing the Shroud: Second Escape Relic", SC2WOL_LOC_ID_OFFSET + 2104, LocationType.VANILLA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Piercing the Shroud", "Piercing the Shroud: Brutalisk", SC2WOL_LOC_ID_OFFSET + 2105, LocationType.VANILLA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Piercing the Shroud", "Piercing the Shroud: Fusion Reactor", SC2WOL_LOC_ID_OFFSET + 2106, LocationType.EXTRA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Piercing the Shroud", "Piercing the Shroud: Entrance Holding Pen", SC2WOL_LOC_ID_OFFSET + 2107, LocationType.EXTRA), - LocationData("Piercing the Shroud", "Piercing the Shroud: Cargo Bay Warbot", SC2WOL_LOC_ID_OFFSET + 2108, LocationType.EXTRA), - LocationData("Piercing the Shroud", "Piercing the Shroud: Escape Warbot", SC2WOL_LOC_ID_OFFSET + 2109, LocationType.EXTRA, - lambda state: logic.marine_medic_upgrade(state)), - LocationData("Whispers of Doom", "Whispers of Doom: Victory", SC2WOL_LOC_ID_OFFSET + 2200, LocationType.VICTORY), - LocationData("Whispers of Doom", "Whispers of Doom: First Hatchery", SC2WOL_LOC_ID_OFFSET + 2201, LocationType.VANILLA), - LocationData("Whispers of Doom", "Whispers of Doom: Second Hatchery", SC2WOL_LOC_ID_OFFSET + 2202, LocationType.VANILLA), - LocationData("Whispers of Doom", "Whispers of Doom: Third Hatchery", SC2WOL_LOC_ID_OFFSET + 2203, LocationType.VANILLA), - LocationData("Whispers of Doom", "Whispers of Doom: First Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2204, LocationType.EXTRA), - LocationData("Whispers of Doom", "Whispers of Doom: Second Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2205, LocationType.EXTRA), - LocationData("Whispers of Doom", "Whispers of Doom: Third Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2206, LocationType.EXTRA), - LocationData("A Sinister Turn", "A Sinister Turn: Victory", SC2WOL_LOC_ID_OFFSET + 2300, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Robotics Facility", SC2WOL_LOC_ID_OFFSET + 2301, LocationType.VANILLA, - lambda state: adv_tactics or logic.protoss_common_unit(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Dark Shrine", SC2WOL_LOC_ID_OFFSET + 2302, LocationType.VANILLA, - lambda state: adv_tactics or logic.protoss_common_unit(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Templar Archives", SC2WOL_LOC_ID_OFFSET + 2303, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Northeast Base", SC2WOL_LOC_ID_OFFSET + 2304, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Southwest Base", SC2WOL_LOC_ID_OFFSET + 2305, LocationType.CHALLENGE, - lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Maar", SC2WOL_LOC_ID_OFFSET + 2306, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Northwest Preserver", SC2WOL_LOC_ID_OFFSET + 2307, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("A Sinister Turn", "A Sinister Turn: Southwest Preserver", SC2WOL_LOC_ID_OFFSET + 2308, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("A Sinister Turn", "A Sinister Turn: East Preserver", SC2WOL_LOC_ID_OFFSET + 2309, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("Echoes of the Future", "Echoes of the Future: Victory", SC2WOL_LOC_ID_OFFSET + 2400, LocationType.VICTORY, - lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData("Echoes of the Future", "Echoes of the Future: Close Obelisk", SC2WOL_LOC_ID_OFFSET + 2401, LocationType.VANILLA), - LocationData("Echoes of the Future", "Echoes of the Future: West Obelisk", SC2WOL_LOC_ID_OFFSET + 2402, LocationType.VANILLA, - lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData("Echoes of the Future", "Echoes of the Future: Base", SC2WOL_LOC_ID_OFFSET + 2403, LocationType.EXTRA), - LocationData("Echoes of the Future", "Echoes of the Future: Southwest Tendril", SC2WOL_LOC_ID_OFFSET + 2404, LocationType.EXTRA), - LocationData("Echoes of the Future", "Echoes of the Future: Southeast Tendril", SC2WOL_LOC_ID_OFFSET + 2405, LocationType.EXTRA, - lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData("Echoes of the Future", "Echoes of the Future: Northeast Tendril", SC2WOL_LOC_ID_OFFSET + 2406, LocationType.EXTRA, - lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData("Echoes of the Future", "Echoes of the Future: Northwest Tendril", SC2WOL_LOC_ID_OFFSET + 2407, LocationType.EXTRA, - lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData("In Utter Darkness", "In Utter Darkness: Defeat", SC2WOL_LOC_ID_OFFSET + 2500, LocationType.VICTORY), - LocationData("In Utter Darkness", "In Utter Darkness: Protoss Archive", SC2WOL_LOC_ID_OFFSET + 2501, LocationType.VANILLA, - lambda state: logic.last_stand_requirement(state)), - LocationData("In Utter Darkness", "In Utter Darkness: Kills", SC2WOL_LOC_ID_OFFSET + 2502, LocationType.VANILLA, - lambda state: logic.last_stand_requirement(state)), - LocationData("In Utter Darkness", "In Utter Darkness: Urun", SC2WOL_LOC_ID_OFFSET + 2503, LocationType.EXTRA), - LocationData("In Utter Darkness", "In Utter Darkness: Mohandar", SC2WOL_LOC_ID_OFFSET + 2504, LocationType.EXTRA, - lambda state: logic.last_stand_requirement(state)), - LocationData("In Utter Darkness", "In Utter Darkness: Selendis", SC2WOL_LOC_ID_OFFSET + 2505, LocationType.EXTRA, - lambda state: logic.last_stand_requirement(state)), - LocationData("In Utter Darkness", "In Utter Darkness: Artanis", SC2WOL_LOC_ID_OFFSET + 2506, LocationType.EXTRA, - lambda state: logic.last_stand_requirement(state)), - LocationData("Gates of Hell", "Gates of Hell: Victory", SC2WOL_LOC_ID_OFFSET + 2600, LocationType.VICTORY, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: Large Army", SC2WOL_LOC_ID_OFFSET + 2601, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: 2 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2602, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: 4 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2603, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: 6 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2604, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: 8 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2605, LocationType.CHALLENGE, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: Southwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2606, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: Northwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2607, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: Northeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2608, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: East Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2609, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: Southeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2610, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Gates of Hell", "Gates of Hell: Expansion Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2611, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state) and - logic.terran_defense_rating(state, True) > 6), - LocationData("Belly of the Beast", "Belly of the Beast: Victory", SC2WOL_LOC_ID_OFFSET + 2700, LocationType.VICTORY), - LocationData("Belly of the Beast", "Belly of the Beast: First Charge", SC2WOL_LOC_ID_OFFSET + 2701, LocationType.EXTRA), - LocationData("Belly of the Beast", "Belly of the Beast: Second Charge", SC2WOL_LOC_ID_OFFSET + 2702, LocationType.EXTRA), - LocationData("Belly of the Beast", "Belly of the Beast: Third Charge", SC2WOL_LOC_ID_OFFSET + 2703, LocationType.EXTRA), - LocationData("Belly of the Beast", "Belly of the Beast: First Group Rescued", SC2WOL_LOC_ID_OFFSET + 2704, LocationType.VANILLA), - LocationData("Belly of the Beast", "Belly of the Beast: Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 2705, LocationType.VANILLA), - LocationData("Belly of the Beast", "Belly of the Beast: Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 2706, LocationType.VANILLA), - LocationData("Shatter the Sky", "Shatter the Sky: Victory", SC2WOL_LOC_ID_OFFSET + 2800, LocationType.VICTORY, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: Close Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2801, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: Northwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2802, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: Southeast Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2803, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: Southwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2804, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: Leviathan", SC2WOL_LOC_ID_OFFSET + 2805, LocationType.VANILLA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: East Hatchery", SC2WOL_LOC_ID_OFFSET + 2806, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: North Hatchery", SC2WOL_LOC_ID_OFFSET + 2807, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state)), - LocationData("Shatter the Sky", "Shatter the Sky: Mid Hatchery", SC2WOL_LOC_ID_OFFSET + 2808, LocationType.EXTRA, - lambda state: logic.terran_competent_comp(state)), - LocationData("All-In", "All-In: Victory", SC2WOL_LOC_ID_OFFSET + 2900, LocationType.VICTORY, - lambda state: logic.all_in_requirement(state)), - LocationData("All-In", "All-In: First Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2901, LocationType.EXTRA, - lambda state: logic.all_in_requirement(state)), - LocationData("All-In", "All-In: Second Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2902, LocationType.EXTRA, - lambda state: logic.all_in_requirement(state)), - LocationData("All-In", "All-In: Third Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2903, LocationType.EXTRA, - lambda state: logic.all_in_requirement(state)), - LocationData("All-In", "All-In: Fourth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2904, LocationType.EXTRA, - lambda state: logic.all_in_requirement(state)), - LocationData("All-In", "All-In: Fifth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2905, LocationType.EXTRA, - lambda state: logic.all_in_requirement(state)), - - # HotS - LocationData("Lab Rat", "Lab Rat: Victory", SC2HOTS_LOC_ID_OFFSET + 100, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state)), - LocationData("Lab Rat", "Lab Rat: Gather Minerals", SC2HOTS_LOC_ID_OFFSET + 101, LocationType.VANILLA), - LocationData("Lab Rat", "Lab Rat: South Zergling Group", SC2HOTS_LOC_ID_OFFSET + 102, LocationType.VANILLA, - lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData("Lab Rat", "Lab Rat: East Zergling Group", SC2HOTS_LOC_ID_OFFSET + 103, LocationType.VANILLA, - lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData("Lab Rat", "Lab Rat: West Zergling Group", SC2HOTS_LOC_ID_OFFSET + 104, LocationType.VANILLA, - lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData("Lab Rat", "Lab Rat: Hatchery", SC2HOTS_LOC_ID_OFFSET + 105, LocationType.EXTRA), - LocationData("Lab Rat", "Lab Rat: Overlord", SC2HOTS_LOC_ID_OFFSET + 106, LocationType.EXTRA), - LocationData("Lab Rat", "Lab Rat: Gas Turrets", SC2HOTS_LOC_ID_OFFSET + 107, LocationType.EXTRA, - lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData("Back in the Saddle", "Back in the Saddle: Victory", SC2HOTS_LOC_ID_OFFSET + 200, LocationType.VICTORY, - lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), - LocationData("Back in the Saddle", "Back in the Saddle: Defend the Tram", SC2HOTS_LOC_ID_OFFSET + 201, LocationType.EXTRA, - lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), - LocationData("Back in the Saddle", "Back in the Saddle: Kinetic Blast", SC2HOTS_LOC_ID_OFFSET + 202, LocationType.VANILLA), - LocationData("Back in the Saddle", "Back in the Saddle: Crushing Grip", SC2HOTS_LOC_ID_OFFSET + 203, LocationType.VANILLA), - LocationData("Back in the Saddle", "Back in the Saddle: Reach the Sublevel", SC2HOTS_LOC_ID_OFFSET + 204, LocationType.EXTRA), - LocationData("Back in the Saddle", "Back in the Saddle: Door Section Cleared", SC2HOTS_LOC_ID_OFFSET + 205, LocationType.EXTRA, - lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), - LocationData("Rendezvous", "Rendezvous: Victory", SC2HOTS_LOC_ID_OFFSET + 300, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Rendezvous", "Rendezvous: Right Queen", SC2HOTS_LOC_ID_OFFSET + 301, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Rendezvous", "Rendezvous: Center Queen", SC2HOTS_LOC_ID_OFFSET + 302, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Rendezvous", "Rendezvous: Left Queen", SC2HOTS_LOC_ID_OFFSET + 303, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Rendezvous", "Rendezvous: Hold Out Finished", SC2HOTS_LOC_ID_OFFSET + 304, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Harvest of Screams", "Harvest of Screams: Victory", SC2HOTS_LOC_ID_OFFSET + 400, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state)), - LocationData("Harvest of Screams", "Harvest of Screams: First Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 401, LocationType.VANILLA), - LocationData("Harvest of Screams", "Harvest of Screams: North Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 402, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Harvest of Screams", "Harvest of Screams: West Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 403, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Harvest of Screams", "Harvest of Screams: Lost Brood", SC2HOTS_LOC_ID_OFFSET + 404, LocationType.EXTRA), - LocationData("Harvest of Screams", "Harvest of Screams: Northeast Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 405, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Harvest of Screams", "Harvest of Screams: Northwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 406, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state)), - LocationData("Harvest of Screams", "Harvest of Screams: Southwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 407, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state)), - LocationData("Harvest of Screams", "Harvest of Screams: Nafash", SC2HOTS_LOC_ID_OFFSET + 408, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state)), - LocationData("Shoot the Messenger", "Shoot the Messenger: Victory", SC2HOTS_LOC_ID_OFFSET + 500, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Shoot the Messenger", "Shoot the Messenger: East Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 501, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData("Shoot the Messenger", "Shoot the Messenger: Center Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 502, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) or adv_tactics), - LocationData("Shoot the Messenger", "Shoot the Messenger: West Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 503, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData("Shoot the Messenger", "Shoot the Messenger: Destroy 4 Shuttles", SC2HOTS_LOC_ID_OFFSET + 504, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData("Shoot the Messenger", "Shoot the Messenger: Frozen Expansion", SC2HOTS_LOC_ID_OFFSET + 505, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Shoot the Messenger", "Shoot the Messenger: Southwest Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 506, LocationType.EXTRA), - LocationData("Shoot the Messenger", "Shoot the Messenger: Southeast Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 507, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) or adv_tactics), - LocationData("Shoot the Messenger", "Shoot the Messenger: West Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 508, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData("Shoot the Messenger", "Shoot the Messenger: East Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 509, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData("Enemy Within", "Enemy Within: Victory", SC2HOTS_LOC_ID_OFFSET + 600, LocationType.VICTORY, - lambda state: logic.zerg_pass_vents(state) - and (logic.story_tech_granted - or state.has_any({item_names.ZERGLING_RAPTOR_STRAIN, item_names.ROACH, - item_names.HYDRALISK, item_names.INFESTOR}, player)) - ), - LocationData("Enemy Within", "Enemy Within: Infest Giant Ursadon", SC2HOTS_LOC_ID_OFFSET + 601, LocationType.VANILLA, - lambda state: logic.zerg_pass_vents(state)), - LocationData("Enemy Within", "Enemy Within: First Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 602, LocationType.VANILLA, - lambda state: logic.zerg_pass_vents(state)), - LocationData("Enemy Within", "Enemy Within: Second Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 603, LocationType.VANILLA, - lambda state: logic.zerg_pass_vents(state)), - LocationData("Enemy Within", "Enemy Within: Third Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 604, LocationType.VANILLA, - lambda state: logic.zerg_pass_vents(state)), - LocationData("Enemy Within", "Enemy Within: Warp Drive", SC2HOTS_LOC_ID_OFFSET + 605, LocationType.EXTRA, - lambda state: logic.zerg_pass_vents(state)), - LocationData("Enemy Within", "Enemy Within: Stasis Quadrant", SC2HOTS_LOC_ID_OFFSET + 606, LocationType.EXTRA, - lambda state: logic.zerg_pass_vents(state)), - LocationData("Domination", "Domination: Victory", SC2HOTS_LOC_ID_OFFSET + 700, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData("Domination", "Domination: Center Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 701, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Domination", "Domination: North Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 702, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Domination", "Domination: Repel Zagara", SC2HOTS_LOC_ID_OFFSET + 703, LocationType.EXTRA), - LocationData("Domination", "Domination: Close Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 704, LocationType.EXTRA), - LocationData("Domination", "Domination: South Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 705, LocationType.EXTRA, - lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData("Domination", "Domination: Southwest Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 706, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Domination", "Domination: Southeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 707, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData("Domination", "Domination: North Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 708, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Domination", "Domination: Northeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 709, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Fire in the Sky", "Fire in the Sky: Victory", SC2HOTS_LOC_ID_OFFSET + 800, LocationType.VICTORY, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Fire in the Sky", "Fire in the Sky: West Biomass", SC2HOTS_LOC_ID_OFFSET + 801, LocationType.VANILLA), - LocationData("Fire in the Sky", "Fire in the Sky: North Biomass", SC2HOTS_LOC_ID_OFFSET + 802, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Fire in the Sky", "Fire in the Sky: South Biomass", SC2HOTS_LOC_ID_OFFSET + 803, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Fire in the Sky", "Fire in the Sky: Destroy 3 Gorgons", SC2HOTS_LOC_ID_OFFSET + 804, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Fire in the Sky", "Fire in the Sky: Close Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 805, LocationType.EXTRA), - LocationData("Fire in the Sky", "Fire in the Sky: South Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 806, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Fire in the Sky", "Fire in the Sky: North Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 807, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Fire in the Sky", "Fire in the Sky: West Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 808, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Fire in the Sky", "Fire in the Sky: East Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 809, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Old Soldiers", "Old Soldiers: Victory", SC2HOTS_LOC_ID_OFFSET + 900, LocationType.VICTORY, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Old Soldiers", "Old Soldiers: East Science Lab", SC2HOTS_LOC_ID_OFFSET + 901, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Old Soldiers", "Old Soldiers: North Science Lab", SC2HOTS_LOC_ID_OFFSET + 902, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Old Soldiers", "Old Soldiers: Get Nuked", SC2HOTS_LOC_ID_OFFSET + 903, LocationType.EXTRA), - LocationData("Old Soldiers", "Old Soldiers: Entrance Gate", SC2HOTS_LOC_ID_OFFSET + 904, LocationType.EXTRA), - LocationData("Old Soldiers", "Old Soldiers: Citadel Gate", SC2HOTS_LOC_ID_OFFSET + 905, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Old Soldiers", "Old Soldiers: South Expansion", SC2HOTS_LOC_ID_OFFSET + 906, LocationType.EXTRA), - LocationData("Old Soldiers", "Old Soldiers: Rich Mineral Expansion", SC2HOTS_LOC_ID_OFFSET + 907, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Waking the Ancient", "Waking the Ancient: Victory", SC2HOTS_LOC_ID_OFFSET + 1000, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Waking the Ancient", "Waking the Ancient: Center Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1001, LocationType.VANILLA), - LocationData("Waking the Ancient", "Waking the Ancient: East Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1002, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - (adv_tactics and logic.zerg_basic_anti_air(state) - or logic.zerg_competent_anti_air(state))), - LocationData("Waking the Ancient", "Waking the Ancient: South Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1003, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - (adv_tactics and logic.zerg_basic_anti_air(state) - or logic.zerg_competent_anti_air(state))), - LocationData("Waking the Ancient", "Waking the Ancient: Finish Feeding", SC2HOTS_LOC_ID_OFFSET + 1004, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Waking the Ancient", "Waking the Ancient: South Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1005, LocationType.CHALLENGE, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Waking the Ancient", "Waking the Ancient: East Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1006, LocationType.CHALLENGE, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Waking the Ancient", "Waking the Ancient: South Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1007, LocationType.CHALLENGE, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Waking the Ancient", "Waking the Ancient: East Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1008, LocationType.CHALLENGE, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_competent_anti_air(state)), - LocationData("The Crucible", "The Crucible: Victory", SC2HOTS_LOC_ID_OFFSET + 1100, LocationType.VICTORY, - lambda state: logic.zerg_competent_defense(state) and - logic.zerg_competent_anti_air(state)), - LocationData("The Crucible", "The Crucible: Tyrannozor", SC2HOTS_LOC_ID_OFFSET + 1101, LocationType.VANILLA, - lambda state: logic.zerg_competent_defense(state) and - logic.zerg_competent_anti_air(state)), - LocationData("The Crucible", "The Crucible: Reach the Pool", SC2HOTS_LOC_ID_OFFSET + 1102, LocationType.VANILLA), - LocationData("The Crucible", "The Crucible: 15 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1103, LocationType.EXTRA, - lambda state: logic.zerg_competent_defense(state) and - logic.zerg_competent_anti_air(state)), - LocationData("The Crucible", "The Crucible: 5 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1104, LocationType.EXTRA, - lambda state: logic.zerg_competent_defense(state) and - logic.zerg_competent_anti_air(state)), - LocationData("The Crucible", "The Crucible: Pincer Attack", SC2HOTS_LOC_ID_OFFSET + 1105, LocationType.EXTRA, - lambda state: logic.zerg_competent_defense(state) and - logic.zerg_competent_anti_air(state)), - LocationData("The Crucible", "The Crucible: Yagdra Claims Brakk's Pack", SC2HOTS_LOC_ID_OFFSET + 1106, LocationType.EXTRA, - lambda state: logic.zerg_competent_defense(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Supreme", "Supreme: Victory", SC2HOTS_LOC_ID_OFFSET + 1200, LocationType.VICTORY, - lambda state: logic.supreme_requirement(state)), - LocationData("Supreme", "Supreme: First Relic", SC2HOTS_LOC_ID_OFFSET + 1201, LocationType.VANILLA, - lambda state: logic.supreme_requirement(state)), - LocationData("Supreme", "Supreme: Second Relic", SC2HOTS_LOC_ID_OFFSET + 1202, LocationType.VANILLA, - lambda state: logic.supreme_requirement(state)), - LocationData("Supreme", "Supreme: Third Relic", SC2HOTS_LOC_ID_OFFSET + 1203, LocationType.VANILLA, - lambda state: logic.supreme_requirement(state)), - LocationData("Supreme", "Supreme: Fourth Relic", SC2HOTS_LOC_ID_OFFSET + 1204, LocationType.VANILLA, - lambda state: logic.supreme_requirement(state)), - LocationData("Supreme", "Supreme: Yagdra", SC2HOTS_LOC_ID_OFFSET + 1205, LocationType.EXTRA, - lambda state: logic.supreme_requirement(state)), - LocationData("Supreme", "Supreme: Kraith", SC2HOTS_LOC_ID_OFFSET + 1206, LocationType.EXTRA, - lambda state: logic.supreme_requirement(state)), - LocationData("Supreme", "Supreme: Slivan", SC2HOTS_LOC_ID_OFFSET + 1207, LocationType.EXTRA, - lambda state: logic.supreme_requirement(state)), - LocationData("Infested", "Infested: Victory", SC2HOTS_LOC_ID_OFFSET + 1300, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state) and - ((logic.zerg_competent_anti_air(state) and state.has(item_names.INFESTOR, player)) or - (adv_tactics and logic.zerg_basic_anti_air(state)))), - LocationData("Infested", "Infested: East Science Facility", SC2HOTS_LOC_ID_OFFSET + 1301, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Infested", "Infested: Center Science Facility", SC2HOTS_LOC_ID_OFFSET + 1302, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Infested", "Infested: West Science Facility", SC2HOTS_LOC_ID_OFFSET + 1303, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - logic.zerg_basic_anti_air(state) and - logic.spread_creep(state)), - LocationData("Infested", "Infested: First Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1304, LocationType.EXTRA), - LocationData("Infested", "Infested: Second Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1305, LocationType.EXTRA), - LocationData("Infested", "Infested: Base Garrison", SC2HOTS_LOC_ID_OFFSET + 1306, LocationType.EXTRA), - LocationData("Infested", "Infested: East Garrison", SC2HOTS_LOC_ID_OFFSET + 1307, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state) - and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData("Infested", "Infested: Mid Garrison", SC2HOTS_LOC_ID_OFFSET + 1308, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state) - and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData("Infested", "Infested: North Garrison", SC2HOTS_LOC_ID_OFFSET + 1309, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state) - and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData("Infested", "Infested: Close Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1310, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state) - and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData("Infested", "Infested: Far Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1311, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) - and logic.zerg_basic_anti_air(state) - and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData("Hand of Darkness", "Hand of Darkness: Victory", SC2HOTS_LOC_ID_OFFSET + 1400, LocationType.VICTORY, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: North Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1401, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: South Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1402, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: Kill 1 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1403, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: Kill 2 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1404, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: Kill 3 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1405, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: Kill 4 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1406, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: Kill 5 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1407, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: Kill 6 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1408, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Hand of Darkness", "Hand of Darkness: Kill 7 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1409, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_basic_anti_air(state)), - LocationData("Phantoms of the Void", "Phantoms of the Void: Victory", SC2HOTS_LOC_ID_OFFSET + 1500, LocationType.VICTORY, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("Phantoms of the Void", "Phantoms of the Void: Northwest Crystal", SC2HOTS_LOC_ID_OFFSET + 1501, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("Phantoms of the Void", "Phantoms of the Void: Northeast Crystal", SC2HOTS_LOC_ID_OFFSET + 1502, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("Phantoms of the Void", "Phantoms of the Void: South Crystal", SC2HOTS_LOC_ID_OFFSET + 1503, LocationType.VANILLA), - LocationData("Phantoms of the Void", "Phantoms of the Void: Base Established", SC2HOTS_LOC_ID_OFFSET + 1504, LocationType.EXTRA), - LocationData("Phantoms of the Void", "Phantoms of the Void: Close Temple", SC2HOTS_LOC_ID_OFFSET + 1505, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("Phantoms of the Void", "Phantoms of the Void: Mid Temple", SC2HOTS_LOC_ID_OFFSET + 1506, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("Phantoms of the Void", "Phantoms of the Void: Southeast Temple", SC2HOTS_LOC_ID_OFFSET + 1507, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("Phantoms of the Void", "Phantoms of the Void: Northeast Temple", SC2HOTS_LOC_ID_OFFSET + 1508, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("Phantoms of the Void", "Phantoms of the Void: Northwest Temple", SC2HOTS_LOC_ID_OFFSET + 1509, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData("With Friends Like These", "With Friends Like These: Victory", SC2HOTS_LOC_ID_OFFSET + 1600, LocationType.VICTORY), - LocationData("With Friends Like These", "With Friends Like These: Pirate Capital Ship", SC2HOTS_LOC_ID_OFFSET + 1601, LocationType.VANILLA), - LocationData("With Friends Like These", "With Friends Like These: First Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1602, LocationType.VANILLA), - LocationData("With Friends Like These", "With Friends Like These: Second Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1603, LocationType.VANILLA), - LocationData("With Friends Like These", "With Friends Like These: Third Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1604, LocationType.VANILLA), - LocationData("Conviction", "Conviction: Victory", SC2HOTS_LOC_ID_OFFSET + 1700, LocationType.VICTORY, - lambda state: logic.two_kerrigan_actives(state) and - (logic.basic_kerrigan(state) or logic.story_tech_granted) or kerriganless), - LocationData("Conviction", "Conviction: First Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1701, LocationType.VANILLA, - lambda state: logic.two_kerrigan_actives(state) or kerriganless), - LocationData("Conviction", "Conviction: Second Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1702, LocationType.VANILLA, - lambda state: logic.two_kerrigan_actives(state) and - (logic.basic_kerrigan(state) or logic.story_tech_granted) or kerriganless), - LocationData("Conviction", "Conviction: Power Coupling", SC2HOTS_LOC_ID_OFFSET + 1703, LocationType.EXTRA, - lambda state: logic.two_kerrigan_actives(state) or kerriganless), - LocationData("Conviction", "Conviction: Door Blasted", SC2HOTS_LOC_ID_OFFSET + 1704, LocationType.EXTRA, - lambda state: logic.two_kerrigan_actives(state) or kerriganless), - LocationData("Planetfall", "Planetfall: Victory", SC2HOTS_LOC_ID_OFFSET + 1800, LocationType.VICTORY, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: East Gate", SC2HOTS_LOC_ID_OFFSET + 1801, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: Northwest Gate", SC2HOTS_LOC_ID_OFFSET + 1802, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: North Gate", SC2HOTS_LOC_ID_OFFSET + 1803, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: 1 Bile Launcher Deployed", SC2HOTS_LOC_ID_OFFSET + 1804, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: 2 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1805, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: 3 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1806, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: 4 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1807, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: 5 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1808, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: Sons of Korhal", SC2HOTS_LOC_ID_OFFSET + 1809, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: Night Wolves", SC2HOTS_LOC_ID_OFFSET + 1810, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: West Expansion", SC2HOTS_LOC_ID_OFFSET + 1811, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Planetfall", "Planetfall: Mid Expansion", SC2HOTS_LOC_ID_OFFSET + 1812, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Death From Above", "Death From Above: Victory", SC2HOTS_LOC_ID_OFFSET + 1900, LocationType.VICTORY, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Death From Above", "Death From Above: First Power Link", SC2HOTS_LOC_ID_OFFSET + 1901, LocationType.VANILLA), - LocationData("Death From Above", "Death From Above: Second Power Link", SC2HOTS_LOC_ID_OFFSET + 1902, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Death From Above", "Death From Above: Third Power Link", SC2HOTS_LOC_ID_OFFSET + 1903, LocationType.VANILLA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Death From Above", "Death From Above: Expansion Command Center", SC2HOTS_LOC_ID_OFFSET + 1904, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("Death From Above", "Death From Above: Main Path Command Center", SC2HOTS_LOC_ID_OFFSET + 1905, LocationType.EXTRA, - lambda state: logic.zerg_competent_comp(state) and - logic.zerg_competent_anti_air(state)), - LocationData("The Reckoning", "The Reckoning: Victory", SC2HOTS_LOC_ID_OFFSET + 2000, LocationType.VICTORY, - lambda state: logic.the_reckoning_requirement(state)), - LocationData("The Reckoning", "The Reckoning: South Lane", SC2HOTS_LOC_ID_OFFSET + 2001, LocationType.VANILLA, - lambda state: logic.the_reckoning_requirement(state)), - LocationData("The Reckoning", "The Reckoning: North Lane", SC2HOTS_LOC_ID_OFFSET + 2002, LocationType.VANILLA, - lambda state: logic.the_reckoning_requirement(state)), - LocationData("The Reckoning", "The Reckoning: East Lane", SC2HOTS_LOC_ID_OFFSET + 2003, LocationType.VANILLA, - lambda state: logic.the_reckoning_requirement(state)), - LocationData("The Reckoning", "The Reckoning: Odin", SC2HOTS_LOC_ID_OFFSET + 2004, LocationType.EXTRA, - lambda state: logic.the_reckoning_requirement(state)), - - # LotV Prologue - LocationData("Dark Whispers", "Dark Whispers: Victory", SC2LOTV_LOC_ID_OFFSET + 100, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_basic_anti_air(state)), - LocationData("Dark Whispers", "Dark Whispers: First Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 101, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_basic_anti_air(state)), - LocationData("Dark Whispers", "Dark Whispers: Second Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 102, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_basic_anti_air(state)), - LocationData("Dark Whispers", "Dark Whispers: First Pylon", SC2LOTV_LOC_ID_OFFSET + 103, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_basic_anti_air(state)), - LocationData("Dark Whispers", "Dark Whispers: Second Pylon", SC2LOTV_LOC_ID_OFFSET + 104, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_basic_anti_air(state)), - LocationData("Ghosts in the Fog", "Ghosts in the Fog: Victory", SC2LOTV_LOC_ID_OFFSET + 200, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Ghosts in the Fog", "Ghosts in the Fog: South Rock Formation", SC2LOTV_LOC_ID_OFFSET + 201, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Ghosts in the Fog", "Ghosts in the Fog: West Rock Formation", SC2LOTV_LOC_ID_OFFSET + 202, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Ghosts in the Fog", "Ghosts in the Fog: East Rock Formation", SC2LOTV_LOC_ID_OFFSET + 203, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) \ - and logic.protoss_anti_armor_anti_air(state) \ - and logic.protoss_can_attack_behind_chasm(state)), - LocationData("Evil Awoken", "Evil Awoken: Victory", SC2LOTV_LOC_ID_OFFSET + 300, LocationType.VICTORY), - LocationData("Evil Awoken", "Evil Awoken: Temple Investigated", SC2LOTV_LOC_ID_OFFSET + 301, LocationType.EXTRA), - LocationData("Evil Awoken", "Evil Awoken: Void Catalyst", SC2LOTV_LOC_ID_OFFSET + 302, LocationType.EXTRA), - LocationData("Evil Awoken", "Evil Awoken: First Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 303, LocationType.VANILLA), - LocationData("Evil Awoken", "Evil Awoken: Second Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 304, LocationType.VANILLA), - LocationData("Evil Awoken", "Evil Awoken: Third Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 305, LocationType.VANILLA), - - - # LotV - LocationData("For Aiur!", "For Aiur!: Victory", SC2LOTV_LOC_ID_OFFSET + 400, LocationType.VICTORY), - LocationData("For Aiur!", "For Aiur!: Southwest Hive", SC2LOTV_LOC_ID_OFFSET + 401, LocationType.VANILLA), - LocationData("For Aiur!", "For Aiur!: Northwest Hive", SC2LOTV_LOC_ID_OFFSET + 402, LocationType.VANILLA), - LocationData("For Aiur!", "For Aiur!: Northeast Hive", SC2LOTV_LOC_ID_OFFSET + 403, LocationType.VANILLA), - LocationData("For Aiur!", "For Aiur!: East Hive", SC2LOTV_LOC_ID_OFFSET + 404, LocationType.VANILLA), - LocationData("For Aiur!", "For Aiur!: West Conduit", SC2LOTV_LOC_ID_OFFSET + 405, LocationType.EXTRA), - LocationData("For Aiur!", "For Aiur!: Middle Conduit", SC2LOTV_LOC_ID_OFFSET + 406, LocationType.EXTRA), - LocationData("For Aiur!", "For Aiur!: Northeast Conduit", SC2LOTV_LOC_ID_OFFSET + 407, LocationType.EXTRA), - LocationData("The Growing Shadow", "The Growing Shadow: Victory", SC2LOTV_LOC_ID_OFFSET + 500, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("The Growing Shadow", "The Growing Shadow: Close Pylon", SC2LOTV_LOC_ID_OFFSET + 501, LocationType.VANILLA), - LocationData("The Growing Shadow", "The Growing Shadow: East Pylon", SC2LOTV_LOC_ID_OFFSET + 502, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("The Growing Shadow", "The Growing Shadow: West Pylon", SC2LOTV_LOC_ID_OFFSET + 503, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("The Growing Shadow", "The Growing Shadow: Nexus", SC2LOTV_LOC_ID_OFFSET + 504, LocationType.EXTRA), - LocationData("The Growing Shadow", "The Growing Shadow: Templar Base", SC2LOTV_LOC_ID_OFFSET + 505, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("The Spear of Adun", "The Spear of Adun: Victory", SC2LOTV_LOC_ID_OFFSET + 600, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("The Spear of Adun", "The Spear of Adun: Close Warp Gate", SC2LOTV_LOC_ID_OFFSET + 601, LocationType.VANILLA), - LocationData("The Spear of Adun", "The Spear of Adun: West Warp Gate", SC2LOTV_LOC_ID_OFFSET + 602, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("The Spear of Adun", "The Spear of Adun: North Warp Gate", SC2LOTV_LOC_ID_OFFSET + 603, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("The Spear of Adun", "The Spear of Adun: North Power Cell", SC2LOTV_LOC_ID_OFFSET + 604, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("The Spear of Adun", "The Spear of Adun: East Power Cell", SC2LOTV_LOC_ID_OFFSET + 605, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("The Spear of Adun", "The Spear of Adun: South Power Cell", SC2LOTV_LOC_ID_OFFSET + 606, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("The Spear of Adun", "The Spear of Adun: Southeast Power Cell", SC2LOTV_LOC_ID_OFFSET + 607, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: Victory", SC2LOTV_LOC_ID_OFFSET + 700, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: Mid EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 701, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: Southeast EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 702, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: North EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 703, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: Mid Stabilizer", SC2LOTV_LOC_ID_OFFSET + 704, LocationType.EXTRA), - LocationData("Sky Shield", "Sky Shield: Southwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 705, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: Northwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 706, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: Northeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 707, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: Southeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 708, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: West Raynor Base", SC2LOTV_LOC_ID_OFFSET + 709, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Sky Shield", "Sky Shield: East Raynor Base", SC2LOTV_LOC_ID_OFFSET + 710, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_basic_anti_air(state)), - LocationData("Brothers in Arms", "Brothers in Arms: Victory", SC2LOTV_LOC_ID_OFFSET + 800, LocationType.VICTORY, - lambda state: logic.brothers_in_arms_requirement(state)), - LocationData("Brothers in Arms", "Brothers in Arms: Mid Science Facility", SC2LOTV_LOC_ID_OFFSET + 801, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) or logic.take_over_ai_allies), - LocationData("Brothers in Arms", "Brothers in Arms: North Science Facility", SC2LOTV_LOC_ID_OFFSET + 802, LocationType.VANILLA, - lambda state: logic.brothers_in_arms_requirement(state) - or logic.take_over_ai_allies - and logic.advanced_tactics - and ( - logic.terran_common_unit(state) - or logic.protoss_common_unit(state) - ) - ), - LocationData("Brothers in Arms", "Brothers in Arms: South Science Facility", SC2LOTV_LOC_ID_OFFSET + 803, LocationType.VANILLA, - lambda state: logic.brothers_in_arms_requirement(state)), - LocationData("Amon's Reach", "Amon's Reach: Victory", SC2LOTV_LOC_ID_OFFSET + 900, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Amon's Reach", "Amon's Reach: Close Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 901, LocationType.VANILLA), - LocationData("Amon's Reach", "Amon's Reach: North Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 902, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Amon's Reach", "Amon's Reach: East Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 903, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Amon's Reach", "Amon's Reach: West Launch Bay", SC2LOTV_LOC_ID_OFFSET + 904, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Amon's Reach", "Amon's Reach: South Launch Bay", SC2LOTV_LOC_ID_OFFSET + 905, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Amon's Reach", "Amon's Reach: Northwest Launch Bay", SC2LOTV_LOC_ID_OFFSET + 906, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Amon's Reach", "Amon's Reach: East Launch Bay", SC2LOTV_LOC_ID_OFFSET + 907, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Last Stand", "Last Stand: Victory", SC2LOTV_LOC_ID_OFFSET + 1000, LocationType.VICTORY, - lambda state: logic.last_stand_requirement(state)), - LocationData("Last Stand", "Last Stand: West Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1001, LocationType.VANILLA, - lambda state: logic.last_stand_requirement(state)), - LocationData("Last Stand", "Last Stand: North Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1002, LocationType.VANILLA, - lambda state: logic.last_stand_requirement(state)), - LocationData("Last Stand", "Last Stand: East Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1003, LocationType.VANILLA, - lambda state: logic.last_stand_requirement(state)), - LocationData("Last Stand", "Last Stand: 1 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1004, LocationType.EXTRA, - lambda state: logic.last_stand_requirement(state)), - LocationData("Last Stand", "Last Stand: 1.5 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1005, LocationType.VANILLA, - lambda state: logic.last_stand_requirement(state) and ( - state.has_all({item_names.KHAYDARIN_MONOLITH, item_names.PHOTON_CANNON, item_names.SHIELD_BATTERY}, player) - or state.has_any({item_names.SOA_SOLAR_LANCE, item_names.SOA_DEPLOY_FENIX}, player) - )), - LocationData("Forbidden Weapon", "Forbidden Weapon: Victory", SC2LOTV_LOC_ID_OFFSET + 1100, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Forbidden Weapon", "Forbidden Weapon: South Solarite", SC2LOTV_LOC_ID_OFFSET + 1101, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Forbidden Weapon", "Forbidden Weapon: North Solarite", SC2LOTV_LOC_ID_OFFSET + 1102, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Forbidden Weapon", "Forbidden Weapon: Northwest Solarite", SC2LOTV_LOC_ID_OFFSET + 1103, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Temple of Unification", "Temple of Unification: Victory", SC2LOTV_LOC_ID_OFFSET + 1200, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Temple of Unification", "Temple of Unification: Mid Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1201, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Temple of Unification", "Temple of Unification: West Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1202, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Temple of Unification", "Temple of Unification: South Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1203, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Temple of Unification", "Temple of Unification: East Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1204, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Temple of Unification", "Temple of Unification: North Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1205, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("Temple of Unification", "Temple of Unification: Titanic Warp Prism", SC2LOTV_LOC_ID_OFFSET + 1206, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) - and logic.protoss_anti_armor_anti_air(state)), - LocationData("The Infinite Cycle", "The Infinite Cycle: Victory", SC2LOTV_LOC_ID_OFFSET + 1300, LocationType.VICTORY, - lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData("The Infinite Cycle", "The Infinite Cycle: First Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1301, LocationType.EXTRA, - lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData("The Infinite Cycle", "The Infinite Cycle: Second Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1302, LocationType.EXTRA, - lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData("The Infinite Cycle", "The Infinite Cycle: First Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1303, LocationType.VANILLA, - lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData("The Infinite Cycle", "The Infinite Cycle: Second Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1304, LocationType.VANILLA, - lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData("The Infinite Cycle", "The Infinite Cycle: Third Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1305, LocationType.VANILLA, - lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: Victory", SC2LOTV_LOC_ID_OFFSET + 1400, LocationType.VICTORY, - lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: Artanis", SC2LOTV_LOC_ID_OFFSET + 1401, LocationType.EXTRA), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: Northwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1402, LocationType.EXTRA, - lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: Northeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1403, LocationType.EXTRA, - lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: Southwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1404, LocationType.EXTRA, - lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: Southeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1405, LocationType.EXTRA, - lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: South Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1406, LocationType.VANILLA), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: Mid Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1407, LocationType.VANILLA, - lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData("Harbinger of Oblivion", "Harbinger of Oblivion: North Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1408, LocationType.VANILLA, - lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData("Unsealing the Past", "Unsealing the Past: Victory", SC2LOTV_LOC_ID_OFFSET + 1500, LocationType.VICTORY, - lambda state: logic.protoss_basic_splash(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Unsealing the Past", "Unsealing the Past: Zerg Cleared", SC2LOTV_LOC_ID_OFFSET + 1501, LocationType.EXTRA), - LocationData("Unsealing the Past", "Unsealing the Past: First Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1502, LocationType.EXTRA, - lambda state: logic.advanced_tactics \ - or logic.protoss_basic_splash(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Unsealing the Past", "Unsealing the Past: Second Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1503, LocationType.EXTRA, - lambda state: logic.protoss_basic_splash(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Unsealing the Past", "Unsealing the Past: Third Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1504, LocationType.EXTRA, - lambda state: logic.protoss_basic_splash(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Unsealing the Past", "Unsealing the Past: Fourth Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1505, LocationType.EXTRA, - lambda state: logic.protoss_basic_splash(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Unsealing the Past", "Unsealing the Past: South Power Core", SC2LOTV_LOC_ID_OFFSET + 1506, LocationType.VANILLA, - lambda state: logic.protoss_basic_splash(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Unsealing the Past", "Unsealing the Past: East Power Core", SC2LOTV_LOC_ID_OFFSET + 1507, LocationType.VANILLA, - lambda state: logic.protoss_basic_splash(state) - and logic.protoss_anti_light_anti_air(state)), - LocationData("Purification", "Purification: Victory", SC2LOTV_LOC_ID_OFFSET + 1600, LocationType.VICTORY, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: North Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1601, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: North Sector: Northeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1602, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: North Sector: Southeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1603, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: South Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1604, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: South Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1605, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: South Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1606, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: West Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1607, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: West Sector: Mid Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1608, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: West Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1609, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: East Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1610, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: East Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1611, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: East Sector: South Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1612, LocationType.EXTRA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Purification", "Purification: Purifier Warden", SC2LOTV_LOC_ID_OFFSET + 1613, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Steps of the Rite", "Steps of the Rite: Victory", SC2LOTV_LOC_ID_OFFSET + 1700, LocationType.VICTORY, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Steps of the Rite", "Steps of the Rite: First Terrazine Fog", SC2LOTV_LOC_ID_OFFSET + 1701, LocationType.EXTRA, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Steps of the Rite", "Steps of the Rite: Southwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1702, LocationType.EXTRA, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Steps of the Rite", "Steps of the Rite: West Guardian", SC2LOTV_LOC_ID_OFFSET + 1703, LocationType.EXTRA, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Steps of the Rite", "Steps of the Rite: Northwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1704, LocationType.EXTRA, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Steps of the Rite", "Steps of the Rite: Northeast Guardian", SC2LOTV_LOC_ID_OFFSET + 1705, LocationType.EXTRA, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Steps of the Rite", "Steps of the Rite: North Mothership", SC2LOTV_LOC_ID_OFFSET + 1706, LocationType.VANILLA, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Steps of the Rite", "Steps of the Rite: South Mothership", SC2LOTV_LOC_ID_OFFSET + 1707, LocationType.VANILLA, - lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData("Rak'Shir", "Rak'Shir: Victory", SC2LOTV_LOC_ID_OFFSET + 1800, LocationType.VICTORY, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Rak'Shir", "Rak'Shir: North Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1801, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Rak'Shir", "Rak'Shir: Southwest Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1802, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Rak'Shir", "Rak'Shir: East Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1803, LocationType.VANILLA, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Templar's Charge", "Templar's Charge: Victory", SC2LOTV_LOC_ID_OFFSET + 1900, LocationType.VICTORY, - lambda state: logic.templars_charge_requirement(state)), - LocationData("Templar's Charge", "Templar's Charge: Northwest Power Core", SC2LOTV_LOC_ID_OFFSET + 1901, LocationType.EXTRA, - lambda state: logic.templars_charge_requirement(state)), - LocationData("Templar's Charge", "Templar's Charge: Northeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1902, LocationType.EXTRA, - lambda state: logic.templars_charge_requirement(state)), - LocationData("Templar's Charge", "Templar's Charge: Southeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1903, LocationType.EXTRA, - lambda state: logic.templars_charge_requirement(state)), - LocationData("Templar's Charge", "Templar's Charge: West Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1904, LocationType.VANILLA, - lambda state: logic.templars_charge_requirement(state)), - LocationData("Templar's Charge", "Templar's Charge: Southeast Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1905, LocationType.VANILLA, - lambda state: logic.protoss_fleet(state)), - LocationData("Templar's Return", "Templar's Return: Victory", SC2LOTV_LOC_ID_OFFSET + 2000, LocationType.VICTORY, - lambda state: logic.templars_return_requirement(state)), - LocationData("Templar's Return", "Templar's Return: Citadel: First Gate", SC2LOTV_LOC_ID_OFFSET + 2001, LocationType.EXTRA), - LocationData("Templar's Return", "Templar's Return: Citadel: Second Gate", SC2LOTV_LOC_ID_OFFSET + 2002, LocationType.EXTRA), - LocationData("Templar's Return", "Templar's Return: Citadel: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2003, LocationType.VANILLA), - LocationData("Templar's Return", "Templar's Return: Temple Grounds: Gather Army", SC2LOTV_LOC_ID_OFFSET + 2004, LocationType.VANILLA, - lambda state: logic.templars_return_requirement(state)), - LocationData("Templar's Return", "Templar's Return: Temple Grounds: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2005, LocationType.VANILLA, - lambda state: logic.templars_return_requirement(state)), - LocationData("Templar's Return", "Templar's Return: Caverns: Purifier", SC2LOTV_LOC_ID_OFFSET + 2006, LocationType.EXTRA, - lambda state: logic.templars_return_requirement(state)), - LocationData("Templar's Return", "Templar's Return: Caverns: Dark Templar", SC2LOTV_LOC_ID_OFFSET + 2007, LocationType.EXTRA, - lambda state: logic.templars_return_requirement(state)), - LocationData("The Host", "The Host: Victory", SC2LOTV_LOC_ID_OFFSET + 2100, LocationType.VICTORY, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: Southeast Void Shard", SC2LOTV_LOC_ID_OFFSET + 2101, LocationType.VICTORY, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: South Void Shard", SC2LOTV_LOC_ID_OFFSET + 2102, LocationType.EXTRA, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: Southwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2103, LocationType.EXTRA, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: North Void Shard", SC2LOTV_LOC_ID_OFFSET + 2104, LocationType.EXTRA, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: Northwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2105, LocationType.EXTRA, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: Nerazim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2106, LocationType.VANILLA, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: Tal'darim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2107, LocationType.VANILLA, - lambda state: logic.the_host_requirement(state)), - LocationData("The Host", "The Host: Purifier Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2108, LocationType.VANILLA, - lambda state: logic.the_host_requirement(state)), - LocationData("Salvation", "Salvation: Victory", SC2LOTV_LOC_ID_OFFSET + 2200, LocationType.VICTORY, - lambda state: logic.salvation_requirement(state)), - LocationData("Salvation", "Salvation: Fabrication Matrix", SC2LOTV_LOC_ID_OFFSET + 2201, LocationType.EXTRA, - lambda state: logic.salvation_requirement(state)), - LocationData("Salvation", "Salvation: Assault Cluster", SC2LOTV_LOC_ID_OFFSET + 2202, LocationType.EXTRA, - lambda state: logic.salvation_requirement(state)), - LocationData("Salvation", "Salvation: Hull Breach", SC2LOTV_LOC_ID_OFFSET + 2203, LocationType.EXTRA, - lambda state: logic.salvation_requirement(state)), - LocationData("Salvation", "Salvation: Core Critical", SC2LOTV_LOC_ID_OFFSET + 2204, LocationType.EXTRA, - lambda state: logic.salvation_requirement(state)), - - # Epilogue - LocationData("Into the Void", "Into the Void: Victory", SC2LOTV_LOC_ID_OFFSET + 2300, LocationType.VICTORY, - lambda state: logic.into_the_void_requirement(state)), - LocationData("Into the Void", "Into the Void: Corruption Source", SC2LOTV_LOC_ID_OFFSET + 2301, LocationType.EXTRA), - LocationData("Into the Void", "Into the Void: Southwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2302, LocationType.VANILLA, - lambda state: logic.into_the_void_requirement(state)), - LocationData("Into the Void", "Into the Void: Northwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2303, LocationType.VANILLA, - lambda state: logic.into_the_void_requirement(state)), - LocationData("Into the Void", "Into the Void: Southeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2304, LocationType.VANILLA, - lambda state: logic.into_the_void_requirement(state)), - LocationData("Into the Void", "Into the Void: Northeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2305, LocationType.VANILLA), - LocationData("The Essence of Eternity", "The Essence of Eternity: Victory", SC2LOTV_LOC_ID_OFFSET + 2400, LocationType.VICTORY, - lambda state: logic.essence_of_eternity_requirement(state)), - LocationData("The Essence of Eternity", "The Essence of Eternity: Void Trashers", SC2LOTV_LOC_ID_OFFSET + 2401, LocationType.EXTRA), - LocationData("Amon's Fall", "Amon's Fall: Victory", SC2LOTV_LOC_ID_OFFSET + 2500, LocationType.VICTORY, - lambda state: logic.amons_fall_requirement(state)), - - # Nova Covert Ops - LocationData("The Escape", "The Escape: Victory", SC2NCO_LOC_ID_OFFSET + 100, LocationType.VICTORY, - lambda state: logic.the_escape_requirement(state)), - LocationData("The Escape", "The Escape: Rifle", SC2NCO_LOC_ID_OFFSET + 101, LocationType.VANILLA, - lambda state: logic.the_escape_first_stage_requirement(state)), - LocationData("The Escape", "The Escape: Grenades", SC2NCO_LOC_ID_OFFSET + 102, LocationType.VANILLA, - lambda state: logic.the_escape_first_stage_requirement(state)), - LocationData("The Escape", "The Escape: Agent Delta", SC2NCO_LOC_ID_OFFSET + 103, LocationType.VANILLA, - lambda state: logic.the_escape_requirement(state)), - LocationData("The Escape", "The Escape: Agent Pierce", SC2NCO_LOC_ID_OFFSET + 104, LocationType.VANILLA, - lambda state: logic.the_escape_requirement(state)), - LocationData("The Escape", "The Escape: Agent Stone", SC2NCO_LOC_ID_OFFSET + 105, LocationType.VANILLA, - lambda state: logic.the_escape_requirement(state)), - LocationData("Sudden Strike", "Sudden Strike: Victory", SC2NCO_LOC_ID_OFFSET + 200, LocationType.VICTORY, - lambda state: logic.sudden_strike_can_reach_objectives(state)), - LocationData("Sudden Strike", "Sudden Strike: Research Center", SC2NCO_LOC_ID_OFFSET + 201, LocationType.VANILLA, - lambda state: logic.sudden_strike_can_reach_objectives(state)), - LocationData("Sudden Strike", "Sudden Strike: Weaponry Labs", SC2NCO_LOC_ID_OFFSET + 202, LocationType.VANILLA, - lambda state: logic.sudden_strike_requirement(state)), - LocationData("Sudden Strike", "Sudden Strike: Brutalisk", SC2NCO_LOC_ID_OFFSET + 203, LocationType.EXTRA, - lambda state: logic.sudden_strike_requirement(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: Victory", SC2NCO_LOC_ID_OFFSET + 300, LocationType.VICTORY, - lambda state: logic.enemy_intelligence_third_stage_requirement(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: West Garrison", SC2NCO_LOC_ID_OFFSET + 301, LocationType.EXTRA, - lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: Close Garrison", SC2NCO_LOC_ID_OFFSET + 302, LocationType.EXTRA, - lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: Northeast Garrison", SC2NCO_LOC_ID_OFFSET + 303, LocationType.EXTRA, - lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: Southeast Garrison", SC2NCO_LOC_ID_OFFSET + 304, LocationType.EXTRA, - lambda state: logic.enemy_intelligence_first_stage_requirement(state) - and logic.enemy_intelligence_cliff_garrison(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: South Garrison", SC2NCO_LOC_ID_OFFSET + 305, LocationType.EXTRA, - lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: All Garrisons", SC2NCO_LOC_ID_OFFSET + 306, LocationType.VANILLA, - lambda state: logic.enemy_intelligence_first_stage_requirement(state) - and logic.enemy_intelligence_cliff_garrison(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: Forces Rescued", SC2NCO_LOC_ID_OFFSET + 307, LocationType.VANILLA, - lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData("Enemy Intelligence", "Enemy Intelligence: Communications Hub", SC2NCO_LOC_ID_OFFSET + 308, LocationType.VANILLA, - lambda state: logic.enemy_intelligence_second_stage_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: Victory", SC2NCO_LOC_ID_OFFSET + 400, LocationType.VICTORY, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: North Base: West Hatchery", SC2NCO_LOC_ID_OFFSET + 401, LocationType.VANILLA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: North Base: North Hatchery", SC2NCO_LOC_ID_OFFSET + 402, LocationType.VANILLA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: North Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 403, LocationType.VANILLA), - LocationData("Trouble In Paradise", "Trouble In Paradise: South Base: Northwest Hatchery", SC2NCO_LOC_ID_OFFSET + 404, LocationType.VANILLA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: South Base: Southwest Hatchery", SC2NCO_LOC_ID_OFFSET + 405, LocationType.VANILLA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: South Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 406, LocationType.VANILLA), - LocationData("Trouble In Paradise", "Trouble In Paradise: North Shield Projector", SC2NCO_LOC_ID_OFFSET + 407, LocationType.EXTRA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: East Shield Projector", SC2NCO_LOC_ID_OFFSET + 408, LocationType.EXTRA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: South Shield Projector", SC2NCO_LOC_ID_OFFSET + 409, LocationType.EXTRA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: West Shield Projector", SC2NCO_LOC_ID_OFFSET + 410, LocationType.EXTRA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Trouble In Paradise", "Trouble In Paradise: Fleet Beacon", SC2NCO_LOC_ID_OFFSET + 411, LocationType.VANILLA, - lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData("Night Terrors", "Night Terrors: Victory", SC2NCO_LOC_ID_OFFSET + 500, LocationType.VICTORY, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: 1 Terrazine Node Collected", SC2NCO_LOC_ID_OFFSET + 501, LocationType.EXTRA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: 2 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 502, LocationType.EXTRA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: 3 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 503, LocationType.EXTRA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: 4 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 504, LocationType.EXTRA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: 5 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 505, LocationType.EXTRA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: HERC Outpost", SC2NCO_LOC_ID_OFFSET + 506, LocationType.VANILLA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: Umojan Mine", SC2NCO_LOC_ID_OFFSET + 507, LocationType.EXTRA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: Blightbringer", SC2NCO_LOC_ID_OFFSET + 508, LocationType.VANILLA, - lambda state: logic.night_terrors_requirement(state) - and logic.nova_ranged_weapon(state) - and state.has_any( - {item_names.NOVA_HELLFIRE_SHOTGUN, item_names.NOVA_PULSE_GRENADES, item_names.NOVA_STIM_INFUSION, - item_names.NOVA_HOLO_DECOY}, player)), - LocationData("Night Terrors", "Night Terrors: Science Facility", SC2NCO_LOC_ID_OFFSET + 509, LocationType.EXTRA, - lambda state: logic.night_terrors_requirement(state)), - LocationData("Night Terrors", "Night Terrors: Eradicators", SC2NCO_LOC_ID_OFFSET + 510, LocationType.VANILLA, - lambda state: logic.night_terrors_requirement(state) - and logic.nova_any_weapon(state)), - LocationData("Flashpoint", "Flashpoint: Victory", SC2NCO_LOC_ID_OFFSET + 600, LocationType.VICTORY, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Close North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 601, LocationType.EXTRA, - lambda state: state.has_any( - {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) - or logic.terran_common_unit(state)), - LocationData("Flashpoint", "Flashpoint: Close East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 602, LocationType.EXTRA, - lambda state: state.has_any( - {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) - or logic.terran_common_unit(state)), - LocationData("Flashpoint", "Flashpoint: Far North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 603, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Far East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 604, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Experimental Weapon", SC2NCO_LOC_ID_OFFSET + 605, LocationType.VANILLA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Northwest Subway Entrance", SC2NCO_LOC_ID_OFFSET + 606, LocationType.VANILLA, - lambda state: state.has_any( - {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) - and logic.terran_common_unit(state) - or logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Southeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 607, LocationType.VANILLA, - lambda state: state.has_any( - {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) - and logic.terran_common_unit(state) - or logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Northeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 608, LocationType.VANILLA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Expansion Hatchery", SC2NCO_LOC_ID_OFFSET + 609, LocationType.EXTRA, - lambda state: state.has(item_names.LIBERATOR_RAID_ARTILLERY, player) and logic.terran_common_unit(state) - or logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Baneling Spawns", SC2NCO_LOC_ID_OFFSET + 610, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Mutalisk Spawns", SC2NCO_LOC_ID_OFFSET + 611, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Nydus Worm Spawns", SC2NCO_LOC_ID_OFFSET + 612, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Lurker Spawns", SC2NCO_LOC_ID_OFFSET + 613, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Brood Lord Spawns", SC2NCO_LOC_ID_OFFSET + 614, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("Flashpoint", "Flashpoint: Ultralisk Spawns", SC2NCO_LOC_ID_OFFSET + 615, LocationType.EXTRA, - lambda state: logic.flashpoint_far_requirement(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Victory", SC2NCO_LOC_ID_OFFSET + 700, LocationType.VICTORY, - lambda state: logic.enemy_shadow_victory(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Sewers: Domination Visor", SC2NCO_LOC_ID_OFFSET + 701, LocationType.VANILLA, - lambda state: logic.enemy_shadow_domination(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Sewers: Resupply Crate", SC2NCO_LOC_ID_OFFSET + 702, LocationType.EXTRA, - lambda state: logic.enemy_shadow_first_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Sewers: Facility Access", SC2NCO_LOC_ID_OFFSET + 703, LocationType.VANILLA, - lambda state: logic.enemy_shadow_first_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: Northwest Door Lock", SC2NCO_LOC_ID_OFFSET + 704, LocationType.VANILLA, - lambda state: logic.enemy_shadow_door_controls(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: Southeast Door Lock", SC2NCO_LOC_ID_OFFSET + 705, LocationType.VANILLA, - lambda state: logic.enemy_shadow_door_controls(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: Blazefire Gunblade", SC2NCO_LOC_ID_OFFSET + 706, LocationType.VANILLA, - lambda state: logic.enemy_shadow_second_stage(state) - and (logic.story_tech_granted - or state.has(item_names.NOVA_BLINK, player) - or (adv_tactics and state.has_all({item_names.NOVA_DOMINATION, item_names.NOVA_HOLO_DECOY, item_names.NOVA_JUMP_SUIT_MODULE}, player)) - ) - ), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: Blink Suit", SC2NCO_LOC_ID_OFFSET + 707, LocationType.VANILLA, - lambda state: logic.enemy_shadow_second_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: Advanced Weaponry", SC2NCO_LOC_ID_OFFSET + 708, LocationType.VANILLA, - lambda state: logic.enemy_shadow_second_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: Entrance Resupply Crate", SC2NCO_LOC_ID_OFFSET + 709, LocationType.EXTRA, - lambda state: logic.enemy_shadow_first_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: West Resupply Crate", SC2NCO_LOC_ID_OFFSET + 710, LocationType.EXTRA, - lambda state: logic.enemy_shadow_second_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: North Resupply Crate", SC2NCO_LOC_ID_OFFSET + 711, LocationType.EXTRA, - lambda state: logic.enemy_shadow_second_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: East Resupply Crate", SC2NCO_LOC_ID_OFFSET + 712, LocationType.EXTRA, - lambda state: logic.enemy_shadow_second_stage(state)), - LocationData("In the Enemy's Shadow", "In the Enemy's Shadow: Facility: South Resupply Crate", SC2NCO_LOC_ID_OFFSET + 713, LocationType.EXTRA, - lambda state: logic.enemy_shadow_second_stage(state)), - LocationData("Dark Skies", "Dark Skies: Victory", SC2NCO_LOC_ID_OFFSET + 800, LocationType.VICTORY, - lambda state: logic.dark_skies_requirement(state)), - LocationData("Dark Skies", "Dark Skies: First Squadron of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 801, LocationType.EXTRA, - lambda state: logic.dark_skies_requirement(state)), - LocationData("Dark Skies", "Dark Skies: Remainder of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 802, LocationType.EXTRA, - lambda state: logic.dark_skies_requirement(state)), - LocationData("Dark Skies", "Dark Skies: Ji'nara", SC2NCO_LOC_ID_OFFSET + 803, LocationType.EXTRA, - lambda state: logic.dark_skies_requirement(state)), - LocationData("Dark Skies", "Dark Skies: Science Facility", SC2NCO_LOC_ID_OFFSET + 804, LocationType.VANILLA, - lambda state: logic.dark_skies_requirement(state)), - LocationData("End Game", "End Game: Victory", SC2NCO_LOC_ID_OFFSET + 900, LocationType.VICTORY, - lambda state: logic.end_game_requirement(state) and logic.nova_any_weapon(state)), - LocationData("End Game", "End Game: Xanthos", SC2NCO_LOC_ID_OFFSET + 901, LocationType.VANILLA, - lambda state: logic.end_game_requirement(state)), - - # Mission Variants - # 10X/20X - Liberation Day - LocationData("The Outlaws (Zerg)", "The Outlaws (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 300, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state)), - LocationData("The Outlaws (Zerg)", "The Outlaws (Zerg): Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 301, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state)), - LocationData("The Outlaws (Zerg)", "The Outlaws (Zerg): North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 302, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("The Outlaws (Zerg)", "The Outlaws (Zerg): Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 303, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state)), - LocationData("The Outlaws (Zerg)", "The Outlaws (Zerg): Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 304, LocationType.EXTRA), - LocationData("The Outlaws (Protoss)", "The Outlaws (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 400, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state)), - LocationData("The Outlaws (Protoss)", "The Outlaws (Protoss): Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 401, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state)), - LocationData("The Outlaws (Protoss)", "The Outlaws (Protoss): North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 402, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state)), - LocationData("The Outlaws (Protoss)", "The Outlaws (Protoss): Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 403, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state)), - LocationData("The Outlaws (Protoss)", "The Outlaws (Protoss): Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 404, LocationType.EXTRA), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 500, LocationType.VICTORY, - lambda state: logic.zerg_competent_defense(state) and - logic.zerg_basic_kerriganless_anti_air(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 501, LocationType.VANILLA), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 502, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 503, LocationType.VANILLA, - lambda state: logic.zerg_competent_defense(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 504, LocationType.CHALLENGE, - lambda state: logic.zerg_competent_comp(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 505, LocationType.CHALLENGE, - lambda state: logic.zerg_competent_comp(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 506, LocationType.CHALLENGE, - lambda state: logic.zerg_competent_comp(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 507, LocationType.CHALLENGE, - lambda state: logic.zerg_competent_comp(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 508, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 509, - LocationType.EXTRA, - lambda state: logic.zerg_competent_defense(state)), - LocationData("Zero Hour (Zerg)", "Zero Hour (Zerg): Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 510, LocationType.EXTRA, - lambda state: logic.zerg_competent_defense(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 600, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) and - (adv_tactics or logic.protoss_basic_anti_air(state))), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 601, LocationType.VANILLA), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 602, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 603, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 604, LocationType.CHALLENGE, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 605, LocationType.CHALLENGE, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 606, LocationType.CHALLENGE, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 607, LocationType.CHALLENGE, - lambda state: logic.protoss_competent_comp(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 608, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 609, - LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state)), - LocationData("Zero Hour (Protoss)", "Zero Hour (Protoss): Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 610, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state)), - # 70X/80X - Evacuation - # 90X/100X - Outbreak - # 110X/120X - Safe Haven - # 130X/140X - Haven's Fall - LocationData("Smash and Grab (Zerg)", "Smash and Grab (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1500, LocationType.VICTORY, - lambda state: logic.zerg_common_unit(state) and - (adv_tactics and logic.zerg_basic_anti_air(state) - or logic.zerg_competent_anti_air(state))), - LocationData("Smash and Grab (Zerg)", "Smash and Grab (Zerg): First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1501, LocationType.VANILLA), - LocationData("Smash and Grab (Zerg)", "Smash and Grab (Zerg): Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1502, LocationType.VANILLA), - LocationData("Smash and Grab (Zerg)", "Smash and Grab (Zerg): Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1503, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) - or logic.zerg_competent_anti_air(state))), - LocationData("Smash and Grab (Zerg)", "Smash and Grab (Zerg): Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1504, LocationType.VANILLA, - lambda state: logic.zerg_common_unit(state) and - (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) - or logic.zerg_competent_anti_air(state))), - LocationData("Smash and Grab (Zerg)", "Smash and Grab (Zerg): First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1505, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and - (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) - or logic.zerg_competent_anti_air(state))), - LocationData("Smash and Grab (Zerg)", "Smash and Grab (Zerg): Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1506, LocationType.EXTRA, - lambda state: logic.zerg_common_unit(state) and - (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) - or logic.zerg_competent_anti_air(state))), - LocationData("Smash and Grab (Protoss)", "Smash and Grab (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1600, LocationType.VICTORY, - lambda state: logic.protoss_common_unit(state) and - (adv_tactics and logic.protoss_basic_anti_air(state) - or logic.protoss_competent_anti_air(state))), - LocationData("Smash and Grab (Protoss)", "Smash and Grab (Protoss): First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1601, LocationType.VANILLA), - LocationData("Smash and Grab (Protoss)", "Smash and Grab (Protoss): Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1602, LocationType.VANILLA), - LocationData("Smash and Grab (Protoss)", "Smash and Grab (Protoss): Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1603, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) and - (adv_tactics and logic.protoss_basic_anti_air(state) - or logic.protoss_competent_anti_air(state))), - LocationData("Smash and Grab (Protoss)", "Smash and Grab (Protoss): Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1604, LocationType.VANILLA, - lambda state: logic.protoss_common_unit(state) and - (adv_tactics and logic.protoss_basic_anti_air(state) - or logic.protoss_competent_anti_air(state))), - LocationData("Smash and Grab (Protoss)", "Smash and Grab (Protoss): First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1605, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) and - (adv_tactics and logic.protoss_basic_anti_air(state) - or logic.protoss_competent_anti_air(state))), - LocationData("Smash and Grab (Protoss)", "Smash and Grab (Protoss): Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1606, LocationType.EXTRA, - lambda state: logic.protoss_common_unit(state) and - (adv_tactics and logic.protoss_basic_anti_air(state) - or logic.protoss_competent_anti_air(state))), - ] - - beat_events = [] - # Filtering out excluded locations - if world is not None: - excluded_location_types = get_location_types(world, LocationInclusion.option_disabled) - plando_locations = get_plando_locations(world) - exclude_locations = world.options.exclude_locations.value - location_table = [location for location in location_table - if (location.type is LocationType.VICTORY or location.name not in exclude_locations) - and location.type not in excluded_location_types - or location.name in plando_locations] - for i, location_data in enumerate(location_table): - # Removing all item-based logic on No Logic - if logic_level == RequiredTactics.option_no_logic: - 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( - location_data._replace(name="Beat " + location_data.name.rsplit(": ", 1)[0], code=None) - ) - return tuple(location_table + beat_events) - +from enum import IntEnum +from typing import List, Tuple, Optional, Callable, NamedTuple, Set, Any, TYPE_CHECKING +from . import item_names +from .options import (get_option_value, RequiredTactics, + LocationInclusion, KerriganPresence, +) +from .rules import SC2Logic +from .mission_tables import SC2Mission + +from BaseClasses import Location +from worlds.AutoWorld import World + +if TYPE_CHECKING: + from BaseClasses import CollectionState + from . import SC2World + +SC2WOL_LOC_ID_OFFSET = 1000 +SC2HOTS_LOC_ID_OFFSET = 20000000 # Avoid clashes with The Legend of Zelda +SC2LOTV_LOC_ID_OFFSET = SC2HOTS_LOC_ID_OFFSET + 2000 +SC2NCO_LOC_ID_OFFSET = SC2LOTV_LOC_ID_OFFSET + 2500 +SC2_RACESWAP_LOC_ID_OFFSET = SC2NCO_LOC_ID_OFFSET + 900 + + +class SC2Location(Location): + game: str = "Starcraft2" + + +class LocationType(IntEnum): + VICTORY = 0 # Winning a mission + VANILLA = 1 # Objectives that provided metaprogression in the original campaign, along with a few other locations for a balanced experience + EXTRA = 2 # Additional locations based on mission progression, collecting in-mission rewards, etc. that do not significantly increase the challenge. + CHALLENGE = 3 # Challenging objectives, often harder than just completing a mission, and often associated with Achievements + MASTERY = 4 # Extremely challenging objectives often associated with Masteries and Feats of Strength in the original campaign + + +class LocationData(NamedTuple): + region: str + name: str + code: int + type: LocationType + rule: Callable[['CollectionState'], bool] = Location.access_rule + + +def get_location_types(world: 'SC2World', inclusion_type: int) -> Set[LocationType]: + """ + + :param multiworld: + :param player: + :param inclusion_type: Level of inclusion to check for + :return: A list of location types that match the inclusion type + """ + exclusion_options = [ + ("vanilla_locations", LocationType.VANILLA), + ("extra_locations", LocationType.EXTRA), + ("challenge_locations", LocationType.CHALLENGE), + ("mastery_locations", LocationType.MASTERY) + ] + excluded_location_types = set() + for option_name, location_type in exclusion_options: + if get_option_value(world, option_name) is inclusion_type: + excluded_location_types.add(location_type) + return excluded_location_types + + +def get_plando_locations(world: World) -> List[str]: + """ + + :param multiworld: + :param player: + :return: A list of locations affected by a plando in a world + """ + if world is None: + return [] + plando_locations = [] + for plando_setting in world.multiworld.plando_items[world.player]: + plando_locations += plando_setting.get("locations", []) + plando_setting_location = plando_setting.get("location", None) + if plando_setting_location is not None: + plando_locations.append(plando_setting_location) + + return plando_locations + + +def get_locations(world: Optional['SC2World']) -> Tuple[LocationData, ...]: + # Note: rules which are ended with or True are rules identified as needed later when restricted units is an option + if world is None: + logic_level = int(RequiredTactics.default) + kerriganless = False + else: + logic_level = world.options.required_tactics.value + kerriganless = ( + world.options.kerrigan_presence.value != KerriganPresence.option_vanilla + or not world.options.enable_hots_missions.value + ) + adv_tactics = logic_level != RequiredTactics.option_standard + logic = SC2Logic(world) + player = 1 if world is None else world.player + location_table: List[LocationData] = [ + # WoL + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Victory", SC2WOL_LOC_ID_OFFSET + 100, LocationType.VICTORY), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: First Statue", SC2WOL_LOC_ID_OFFSET + 101, LocationType.VANILLA), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Second Statue", SC2WOL_LOC_ID_OFFSET + 102, LocationType.VANILLA), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Third Statue", SC2WOL_LOC_ID_OFFSET + 103, LocationType.VANILLA), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Fourth Statue", SC2WOL_LOC_ID_OFFSET + 104, LocationType.VANILLA), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Fifth Statue", SC2WOL_LOC_ID_OFFSET + 105, LocationType.VANILLA), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Sixth Statue", SC2WOL_LOC_ID_OFFSET + 106, LocationType.VANILLA), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Special Delivery", SC2WOL_LOC_ID_OFFSET + 107, LocationType.EXTRA), + LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Transport", SC2WOL_LOC_ID_OFFSET + 108, LocationType.EXTRA), + LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 200, LocationType.VICTORY, + lambda state: logic.terran_early_tech(state)), + LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Rebel Base", SC2WOL_LOC_ID_OFFSET + 201, LocationType.VANILLA, + lambda state: logic.terran_early_tech(state)), + LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): North Resource Pickups", SC2WOL_LOC_ID_OFFSET + 202, LocationType.EXTRA, + lambda state: logic.terran_early_tech(state)), + LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Bunker", SC2WOL_LOC_ID_OFFSET + 203, LocationType.VANILLA, + lambda state: logic.terran_early_tech(state)), + LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Close Resource Pickups", SC2WOL_LOC_ID_OFFSET + 204, LocationType.EXTRA), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 300, LocationType.VICTORY, + lambda state: logic.terran_common_unit(state) and + logic.terran_defense_rating(state, True) >= 2 and + (adv_tactics or logic.terran_basic_anti_air(state))), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): First Group Rescued", SC2WOL_LOC_ID_OFFSET + 301, LocationType.VANILLA), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 302, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 303, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + logic.terran_defense_rating(state, True) >= 2), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): First Hatchery", SC2WOL_LOC_ID_OFFSET + 304, LocationType.CHALLENGE, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Second Hatchery", SC2WOL_LOC_ID_OFFSET + 305, LocationType.CHALLENGE, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Third Hatchery", SC2WOL_LOC_ID_OFFSET + 306, LocationType.CHALLENGE, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Fourth Hatchery", SC2WOL_LOC_ID_OFFSET + 307, LocationType.CHALLENGE, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Ride's on its Way", SC2WOL_LOC_ID_OFFSET + 308, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Hold Just a Little Longer", SC2WOL_LOC_ID_OFFSET + 309, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_defense_rating(state, True) >= 2), + LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Cavalry's on the Way", SC2WOL_LOC_ID_OFFSET + 310, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_defense_rating(state, True) >= 2), + LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Victory", SC2WOL_LOC_ID_OFFSET + 400, LocationType.VICTORY, + lambda state: logic.terran_early_tech(state) and + (adv_tactics and logic.terran_basic_anti_air(state) + or logic.terran_competent_anti_air(state))), + LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: North Chrysalis", SC2WOL_LOC_ID_OFFSET + 401, LocationType.VANILLA), + LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: West Chrysalis", SC2WOL_LOC_ID_OFFSET + 402, LocationType.VANILLA, + lambda state: logic.terran_early_tech(state)), + LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: East Chrysalis", SC2WOL_LOC_ID_OFFSET + 403, LocationType.VANILLA, + lambda state: logic.terran_early_tech(state)), + LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Reach Hanson", SC2WOL_LOC_ID_OFFSET + 404, LocationType.EXTRA), + LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Secret Resource Stash", SC2WOL_LOC_ID_OFFSET + 405, LocationType.EXTRA), + LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Flawless", SC2WOL_LOC_ID_OFFSET + 406, LocationType.CHALLENGE, + lambda state: logic.terran_early_tech(state) and + logic.terran_defense_rating(state, True, False) >= 2 and + (adv_tactics and logic.terran_basic_anti_air(state) + or logic.terran_competent_anti_air(state))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Victory", SC2WOL_LOC_ID_OFFSET + 500, LocationType.VICTORY, + lambda state: logic.terran_defense_rating(state, True, False) >= 4 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Left Infestor", SC2WOL_LOC_ID_OFFSET + 501, LocationType.VANILLA, + lambda state: logic.terran_defense_rating(state, True, False) >= 2 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Right Infestor", SC2WOL_LOC_ID_OFFSET + 502, LocationType.VANILLA, + lambda state: logic.terran_defense_rating(state, True, False) >= 2 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: North Infested Command Center", SC2WOL_LOC_ID_OFFSET + 503, LocationType.EXTRA, + lambda state: logic.terran_defense_rating(state, True, False) >= 2 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: South Infested Command Center", SC2WOL_LOC_ID_OFFSET + 504, LocationType.EXTRA, + lambda state: logic.terran_defense_rating(state, True, False) >= 2 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Northwest Bar", SC2WOL_LOC_ID_OFFSET + 505, LocationType.EXTRA, + lambda state: logic.terran_defense_rating(state, True, False) >= 2 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: North Bar", SC2WOL_LOC_ID_OFFSET + 506, LocationType.EXTRA, + lambda state: logic.terran_defense_rating(state, True, False) >= 2 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: South Bar", SC2WOL_LOC_ID_OFFSET + 507, LocationType.EXTRA, + lambda state: logic.terran_defense_rating(state, True, False) >= 2 and + (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: Victory", SC2WOL_LOC_ID_OFFSET + 600, LocationType.VICTORY, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state)), + LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: North Nexus", SC2WOL_LOC_ID_OFFSET + 601, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state)), + LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: East Nexus", SC2WOL_LOC_ID_OFFSET + 602, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state)), + LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: South Nexus", SC2WOL_LOC_ID_OFFSET + 603, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state)), + LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: First Terror Fleet", SC2WOL_LOC_ID_OFFSET + 604, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state)), + LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: Second Terror Fleet", SC2WOL_LOC_ID_OFFSET + 605, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state)), + LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: Third Terror Fleet", SC2WOL_LOC_ID_OFFSET + 606, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state)), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Victory", SC2WOL_LOC_ID_OFFSET + 700, LocationType.VICTORY, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state) and + logic.terran_defense_rating(state, True) >= 3), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: North Hive", SC2WOL_LOC_ID_OFFSET + 701, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state) and + logic.terran_defense_rating(state, True) >= 3), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: East Hive", SC2WOL_LOC_ID_OFFSET + 702, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state) and + logic.terran_defense_rating(state, True) >= 3), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: South Hive", SC2WOL_LOC_ID_OFFSET + 703, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state) and + logic.terran_defense_rating(state, True) >= 3), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Northeast Colony Base", SC2WOL_LOC_ID_OFFSET + 704, LocationType.CHALLENGE, + lambda state: logic.terran_respond_to_colony_infestations(state)), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: East Colony Base", SC2WOL_LOC_ID_OFFSET + 705, LocationType.CHALLENGE, + lambda state: logic.terran_respond_to_colony_infestations(state)), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Middle Colony Base", SC2WOL_LOC_ID_OFFSET + 706, LocationType.CHALLENGE, + lambda state: logic.terran_respond_to_colony_infestations(state)), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southeast Colony Base", SC2WOL_LOC_ID_OFFSET + 707, LocationType.CHALLENGE, + lambda state: logic.terran_respond_to_colony_infestations(state)), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southwest Colony Base", SC2WOL_LOC_ID_OFFSET + 708, LocationType.CHALLENGE, + lambda state: logic.terran_respond_to_colony_infestations(state)), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southwest Gas Pickups", SC2WOL_LOC_ID_OFFSET + 709, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state) and + logic.terran_defense_rating(state, True) >= 3), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: East Gas Pickups", SC2WOL_LOC_ID_OFFSET + 710, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state) and + logic.terran_defense_rating(state, True) >= 3), + LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southeast Gas Pickups", SC2WOL_LOC_ID_OFFSET + 711, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + logic.terran_competent_anti_air(state) and + logic.terran_defense_rating(state, True) >= 3), + LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 800, LocationType.VICTORY, + lambda state: logic.terran_common_unit(state) and + (adv_tactics and logic.terran_basic_anti_air(state) + or logic.terran_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): First Relic", SC2WOL_LOC_ID_OFFSET + 801, LocationType.VANILLA), + LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Second Relic", SC2WOL_LOC_ID_OFFSET + 802, LocationType.VANILLA), + LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Third Relic", SC2WOL_LOC_ID_OFFSET + 803, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + (adv_tactics and logic.terran_basic_anti_air(state) + or logic.terran_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Fourth Relic", SC2WOL_LOC_ID_OFFSET + 804, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state) and + (adv_tactics and logic.terran_basic_anti_air(state) + or logic.terran_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): First Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 805, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + (adv_tactics and logic.terran_basic_anti_air(state) + or logic.terran_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Second Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 806, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state) and + (adv_tactics and logic.terran_basic_anti_air(state) + or logic.terran_competent_anti_air(state))), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Victory", SC2WOL_LOC_ID_OFFSET + 900, LocationType.VICTORY, + lambda state: logic.terran_basic_anti_air(state) + and logic.terran_defense_rating(state, False, True) >= 8 + and logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Left Relic", SC2WOL_LOC_ID_OFFSET + 901, LocationType.VANILLA, + lambda state: logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Right Ground Relic", SC2WOL_LOC_ID_OFFSET + 902, LocationType.VANILLA, + lambda state: logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Right Cliff Relic", SC2WOL_LOC_ID_OFFSET + 903, LocationType.VANILLA, + lambda state: logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Moebius Base", SC2WOL_LOC_ID_OFFSET + 904, LocationType.EXTRA, + lambda state: logic.marine_medic_upgrade(state) or adv_tactics), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Door Outer Layer", SC2WOL_LOC_ID_OFFSET + 905, LocationType.EXTRA, + lambda state: logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Door Thermal Barrier", SC2WOL_LOC_ID_OFFSET + 906, LocationType.EXTRA, + lambda state: logic.terran_basic_anti_air(state) + and logic.terran_defense_rating(state, False, True) >= 8 + and logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Cutting Through the Core", SC2WOL_LOC_ID_OFFSET + 907, LocationType.EXTRA, + lambda state: logic.terran_basic_anti_air(state) + and logic.terran_defense_rating(state, False, True) >= 8 + and logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Structure Access Imminent", SC2WOL_LOC_ID_OFFSET + 908, LocationType.EXTRA, + lambda state: logic.terran_basic_anti_air(state) + and logic.terran_defense_rating(state, False, True) >= 8 + and logic.terran_defense_rating(state, False, False) >= 6 + and logic.terran_common_unit(state) + and (logic.marine_medic_upgrade(state) or adv_tactics)), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Victory", SC2WOL_LOC_ID_OFFSET + 1000, LocationType.VICTORY, + lambda state: logic.terran_basic_anti_air(state) and + (logic.terran_air(state) + or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) + and logic.terran_common_unit(state))), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: 1st Data Core", SC2WOL_LOC_ID_OFFSET + 1001, LocationType.VANILLA), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: 2nd Data Core", SC2WOL_LOC_ID_OFFSET + 1002, LocationType.VANILLA, + lambda state: (logic.terran_air(state) + or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) + and logic.terran_common_unit(state))), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: South Rescue", SC2WOL_LOC_ID_OFFSET + 1003, LocationType.EXTRA, + lambda state: logic.terran_can_rescue(state)), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Wall Rescue", SC2WOL_LOC_ID_OFFSET + 1004, LocationType.EXTRA, + lambda state: logic.terran_can_rescue(state)), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Mid Rescue", SC2WOL_LOC_ID_OFFSET + 1005, LocationType.EXTRA, + lambda state: logic.terran_can_rescue(state)), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Nydus Roof Rescue", SC2WOL_LOC_ID_OFFSET + 1006, LocationType.EXTRA, + lambda state: logic.terran_can_rescue(state)), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Alive Inside Rescue", SC2WOL_LOC_ID_OFFSET + 1007, LocationType.EXTRA, + lambda state: logic.terran_can_rescue(state)), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1008, LocationType.VANILLA, + lambda state: logic.terran_basic_anti_air(state) and + (logic.terran_air(state) + or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) + and logic.terran_common_unit(state))), + LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: 3rd Data Core", SC2WOL_LOC_ID_OFFSET + 1009, LocationType.VANILLA, + lambda state: logic.terran_basic_anti_air(state) and + (logic.terran_air(state) + or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) + and logic.terran_common_unit(state))), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Victory", SC2WOL_LOC_ID_OFFSET + 1100, LocationType.VICTORY, + lambda state: logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: West Relic", SC2WOL_LOC_ID_OFFSET + 1101, LocationType.VANILLA), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: North Relic", SC2WOL_LOC_ID_OFFSET + 1102, LocationType.VANILLA), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: South Relic", SC2WOL_LOC_ID_OFFSET + 1103, LocationType.VANILLA, + lambda state: logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: East Relic", SC2WOL_LOC_ID_OFFSET + 1104, LocationType.VANILLA, + lambda state: logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1105, LocationType.EXTRA), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Middle Base", SC2WOL_LOC_ID_OFFSET + 1106, LocationType.EXTRA, + lambda state: logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Southeast Base", SC2WOL_LOC_ID_OFFSET + 1107, LocationType.EXTRA, + lambda state: logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Victory", SC2WOL_LOC_ID_OFFSET + 1200, LocationType.VICTORY, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1201, LocationType.EXTRA), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Expansion Prisoners", SC2WOL_LOC_ID_OFFSET + 1202, LocationType.VANILLA, + lambda state: adv_tactics or logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: South Close Prisoners", SC2WOL_LOC_ID_OFFSET + 1203, LocationType.VANILLA, + lambda state: adv_tactics or logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: South Far Prisoners", SC2WOL_LOC_ID_OFFSET + 1204, LocationType.VANILLA, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: North Prisoners", SC2WOL_LOC_ID_OFFSET + 1205, LocationType.VANILLA, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Mothership", SC2WOL_LOC_ID_OFFSET + 1206, LocationType.EXTRA, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Expansion Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1207, LocationType.EXTRA, + lambda state: adv_tactics or logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Middle Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1208, LocationType.EXTRA, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Southeast Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1209, LocationType.EXTRA, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Stargate Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1210, LocationType.EXTRA, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Northwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1211, LocationType.CHALLENGE, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: West Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1212, LocationType.CHALLENGE, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Southwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1213, LocationType.CHALLENGE, + lambda state: logic.terran_survives_rip_field(state)), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Victory", SC2WOL_LOC_ID_OFFSET + 1300, LocationType.VICTORY, + lambda state: adv_tactics or + logic.terran_basic_anti_air(state) and ( + logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Tosh's Miners", SC2WOL_LOC_ID_OFFSET + 1301, LocationType.VANILLA), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1302, LocationType.VANILLA, + lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: North Reapers", SC2WOL_LOC_ID_OFFSET + 1303, LocationType.EXTRA), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Middle Reapers", SC2WOL_LOC_ID_OFFSET + 1304, LocationType.EXTRA, + lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Southwest Reapers", SC2WOL_LOC_ID_OFFSET + 1305, LocationType.EXTRA, + lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Southeast Reapers", SC2WOL_LOC_ID_OFFSET + 1306, LocationType.EXTRA, + lambda state: adv_tactics or + logic.terran_basic_anti_air(state) and ( + logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: East Reapers", SC2WOL_LOC_ID_OFFSET + 1307, LocationType.CHALLENGE, + lambda state: logic.terran_basic_anti_air(state) and + (adv_tactics or + logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Zerg Cleared", SC2WOL_LOC_ID_OFFSET + 1308, LocationType.CHALLENGE, + lambda state: logic.terran_competent_anti_air(state) and ( + logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Victory", SC2WOL_LOC_ID_OFFSET + 1400, LocationType.VICTORY, + lambda state: logic.welcome_to_the_jungle_requirement(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Close Relic", SC2WOL_LOC_ID_OFFSET + 1401, LocationType.VANILLA), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: West Relic", SC2WOL_LOC_ID_OFFSET + 1402, LocationType.VANILLA, + lambda state: logic.welcome_to_the_jungle_requirement(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: North-East Relic", SC2WOL_LOC_ID_OFFSET + 1403, LocationType.VANILLA, + lambda state: logic.welcome_to_the_jungle_requirement(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Middle Base", SC2WOL_LOC_ID_OFFSET + 1404, LocationType.EXTRA, + lambda state: logic.welcome_to_the_jungle_requirement(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Main Base", SC2WOL_LOC_ID_OFFSET + 1405, + LocationType.MASTERY, + lambda state: logic.welcome_to_the_jungle_requirement(state) + and logic.terran_beats_protoss_deathball(state) + and logic.terran_base_trasher(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: No Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1406, LocationType.CHALLENGE, + lambda state: logic.welcome_to_the_jungle_requirement(state) + and logic.terran_competent_ground_to_air(state) + and logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 1 Terrazine Node Sealed", SC2WOL_LOC_ID_OFFSET + 1407, LocationType.CHALLENGE, + lambda state: logic.welcome_to_the_jungle_requirement(state) + and logic.terran_competent_ground_to_air(state) + and logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 2 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1408, LocationType.CHALLENGE, + lambda state: logic.welcome_to_the_jungle_requirement(state) + and logic.terran_beats_protoss_deathball(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 3 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1409, LocationType.CHALLENGE, + lambda state: logic.welcome_to_the_jungle_requirement(state) + and logic.terran_competent_comp(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 4 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1410, LocationType.EXTRA, + lambda state: logic.welcome_to_the_jungle_requirement(state)), + LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 5 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1411, LocationType.EXTRA, + lambda state: logic.welcome_to_the_jungle_requirement(state)), + LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Victory", SC2WOL_LOC_ID_OFFSET + 1500, LocationType.VICTORY), + LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Diamondback Prison", SC2WOL_LOC_ID_OFFSET + 1501, LocationType.VANILLA), + LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Siege Tank Prison", SC2WOL_LOC_ID_OFFSET + 1502, LocationType.VANILLA), + LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: First Checkpoint", SC2WOL_LOC_ID_OFFSET + 1503, LocationType.EXTRA), + LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Second Checkpoint", SC2WOL_LOC_ID_OFFSET + 1504, LocationType.EXTRA), + LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Victory", SC2WOL_LOC_ID_OFFSET + 1600, LocationType.VICTORY), + LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Terrazine Tank", SC2WOL_LOC_ID_OFFSET + 1601, LocationType.EXTRA), + LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Jorium Stockpile", SC2WOL_LOC_ID_OFFSET + 1602, LocationType.EXTRA), + LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: First Island Spectres", SC2WOL_LOC_ID_OFFSET + 1603, LocationType.VANILLA), + LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Second Island Spectres", SC2WOL_LOC_ID_OFFSET + 1604, LocationType.VANILLA), + LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Third Island Spectres", SC2WOL_LOC_ID_OFFSET + 1605, LocationType.VANILLA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Victory", SC2WOL_LOC_ID_OFFSET + 1700, LocationType.VICTORY, + lambda state: logic.great_train_robbery_train_stopper(state) and + logic.terran_basic_anti_air(state)), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: North Defiler", SC2WOL_LOC_ID_OFFSET + 1701, LocationType.VANILLA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Mid Defiler", SC2WOL_LOC_ID_OFFSET + 1702, LocationType.VANILLA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: South Defiler", SC2WOL_LOC_ID_OFFSET + 1703, LocationType.VANILLA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Close Diamondback", SC2WOL_LOC_ID_OFFSET + 1704, LocationType.EXTRA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Northwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1705, LocationType.EXTRA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: North Diamondback", SC2WOL_LOC_ID_OFFSET + 1706, LocationType.EXTRA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Northeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1707, LocationType.EXTRA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Southwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1708, LocationType.EXTRA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Southeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1709, LocationType.EXTRA), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Kill Team", SC2WOL_LOC_ID_OFFSET + 1710, LocationType.CHALLENGE, + lambda state: (adv_tactics or logic.terran_common_unit(state)) and + logic.great_train_robbery_train_stopper(state) and + logic.terran_basic_anti_air(state)), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Flawless", SC2WOL_LOC_ID_OFFSET + 1711, LocationType.CHALLENGE, + lambda state: logic.great_train_robbery_train_stopper(state) and + logic.terran_basic_anti_air(state)), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: 2 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1712, LocationType.EXTRA, + lambda state: logic.great_train_robbery_train_stopper(state)), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: 4 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1713, LocationType.EXTRA, + lambda state: logic.great_train_robbery_train_stopper(state) and + logic.terran_basic_anti_air(state)), + LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: 6 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1714, LocationType.EXTRA, + lambda state: logic.great_train_robbery_train_stopper(state) and + logic.terran_basic_anti_air(state)), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Victory", SC2WOL_LOC_ID_OFFSET + 1800, LocationType.VICTORY, + lambda state: logic.terran_common_unit(state) + and (adv_tactics or logic.terran_basic_anti_air(state))), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Mira Han", SC2WOL_LOC_ID_OFFSET + 1801, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: North Relic", SC2WOL_LOC_ID_OFFSET + 1802, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Mid Relic", SC2WOL_LOC_ID_OFFSET + 1803, LocationType.VANILLA), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Southwest Relic", SC2WOL_LOC_ID_OFFSET + 1804, LocationType.VANILLA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: North Command Center", SC2WOL_LOC_ID_OFFSET + 1805, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: South Command Center", SC2WOL_LOC_ID_OFFSET + 1806, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: West Command Center", SC2WOL_LOC_ID_OFFSET + 1807, LocationType.EXTRA, + lambda state: logic.terran_common_unit(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Victory", SC2WOL_LOC_ID_OFFSET + 1900, LocationType.VICTORY, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Odin", SC2WOL_LOC_ID_OFFSET + 1901, LocationType.EXTRA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Loki", SC2WOL_LOC_ID_OFFSET + 1902, + LocationType.CHALLENGE, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Lab Devourer", SC2WOL_LOC_ID_OFFSET + 1903, LocationType.VANILLA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: North Devourer", SC2WOL_LOC_ID_OFFSET + 1904, LocationType.VANILLA, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Southeast Devourer", SC2WOL_LOC_ID_OFFSET + 1905, LocationType.VANILLA, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: West Base", SC2WOL_LOC_ID_OFFSET + 1906, LocationType.EXTRA, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Northwest Base", SC2WOL_LOC_ID_OFFSET + 1907, LocationType.EXTRA, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Northeast Base", SC2WOL_LOC_ID_OFFSET + 1908, LocationType.EXTRA, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Southeast Base", SC2WOL_LOC_ID_OFFSET + 1909, LocationType.EXTRA, + lambda state: logic.engine_of_destruction_requirement(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Victory", SC2WOL_LOC_ID_OFFSET + 2000, LocationType.VICTORY, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Tower 1", SC2WOL_LOC_ID_OFFSET + 2001, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Tower 2", SC2WOL_LOC_ID_OFFSET + 2002, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Tower 3", SC2WOL_LOC_ID_OFFSET + 2003, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Science Facility", SC2WOL_LOC_ID_OFFSET + 2004, LocationType.VANILLA), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: All Barracks", SC2WOL_LOC_ID_OFFSET + 2005, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: All Factories", SC2WOL_LOC_ID_OFFSET + 2006, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: All Starports", SC2WOL_LOC_ID_OFFSET + 2007, LocationType.EXTRA, + lambda state: adv_tactics or logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Odin Not Trashed", SC2WOL_LOC_ID_OFFSET + 2008, LocationType.CHALLENGE, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Surprise Attack Ends", SC2WOL_LOC_ID_OFFSET + 2009, LocationType.EXTRA), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Victory", SC2WOL_LOC_ID_OFFSET + 2100, LocationType.VICTORY, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Holding Cell Relic", SC2WOL_LOC_ID_OFFSET + 2101, LocationType.VANILLA), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Brutalisk Relic", SC2WOL_LOC_ID_OFFSET + 2102, LocationType.VANILLA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: First Escape Relic", SC2WOL_LOC_ID_OFFSET + 2103, LocationType.VANILLA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Second Escape Relic", SC2WOL_LOC_ID_OFFSET + 2104, LocationType.VANILLA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Brutalisk", SC2WOL_LOC_ID_OFFSET + 2105, LocationType.VANILLA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Fusion Reactor", SC2WOL_LOC_ID_OFFSET + 2106, LocationType.EXTRA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Entrance Holding Pen", SC2WOL_LOC_ID_OFFSET + 2107, LocationType.EXTRA), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Cargo Bay Warbot", SC2WOL_LOC_ID_OFFSET + 2108, LocationType.EXTRA), + LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Escape Warbot", SC2WOL_LOC_ID_OFFSET + 2109, LocationType.EXTRA, + lambda state: logic.marine_medic_upgrade(state)), + LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Victory", SC2WOL_LOC_ID_OFFSET + 2200, LocationType.VICTORY), + LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: First Hatchery", SC2WOL_LOC_ID_OFFSET + 2201, LocationType.VANILLA), + LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Second Hatchery", SC2WOL_LOC_ID_OFFSET + 2202, LocationType.VANILLA), + LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Third Hatchery", SC2WOL_LOC_ID_OFFSET + 2203, LocationType.VANILLA), + LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: First Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2204, LocationType.EXTRA), + LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Second Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2205, LocationType.EXTRA), + LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Third Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2206, LocationType.EXTRA), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Victory", SC2WOL_LOC_ID_OFFSET + 2300, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Robotics Facility", SC2WOL_LOC_ID_OFFSET + 2301, LocationType.VANILLA, + lambda state: adv_tactics or logic.protoss_common_unit(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Dark Shrine", SC2WOL_LOC_ID_OFFSET + 2302, LocationType.VANILLA, + lambda state: adv_tactics or logic.protoss_common_unit(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Templar Archives", SC2WOL_LOC_ID_OFFSET + 2303, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Northeast Base", SC2WOL_LOC_ID_OFFSET + 2304, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Southwest Base", SC2WOL_LOC_ID_OFFSET + 2305, LocationType.CHALLENGE, + lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Maar", SC2WOL_LOC_ID_OFFSET + 2306, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Northwest Preserver", SC2WOL_LOC_ID_OFFSET + 2307, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Southwest Preserver", SC2WOL_LOC_ID_OFFSET + 2308, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: East Preserver", SC2WOL_LOC_ID_OFFSET + 2309, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Victory", SC2WOL_LOC_ID_OFFSET + 2400, LocationType.VICTORY, + lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Close Obelisk", SC2WOL_LOC_ID_OFFSET + 2401, LocationType.VANILLA), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: West Obelisk", SC2WOL_LOC_ID_OFFSET + 2402, LocationType.VANILLA, + lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Base", SC2WOL_LOC_ID_OFFSET + 2403, LocationType.EXTRA), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Southwest Tendril", SC2WOL_LOC_ID_OFFSET + 2404, LocationType.EXTRA), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Southeast Tendril", SC2WOL_LOC_ID_OFFSET + 2405, LocationType.EXTRA, + lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Northeast Tendril", SC2WOL_LOC_ID_OFFSET + 2406, LocationType.EXTRA, + lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), + LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Northwest Tendril", SC2WOL_LOC_ID_OFFSET + 2407, LocationType.EXTRA, + lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), + LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Defeat", SC2WOL_LOC_ID_OFFSET + 2500, LocationType.VICTORY), + LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Protoss Archive", SC2WOL_LOC_ID_OFFSET + 2501, LocationType.VANILLA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Kills", SC2WOL_LOC_ID_OFFSET + 2502, LocationType.VANILLA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Urun", SC2WOL_LOC_ID_OFFSET + 2503, LocationType.EXTRA), + LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Mohandar", SC2WOL_LOC_ID_OFFSET + 2504, LocationType.EXTRA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Selendis", SC2WOL_LOC_ID_OFFSET + 2505, LocationType.EXTRA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Artanis", SC2WOL_LOC_ID_OFFSET + 2506, LocationType.EXTRA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Victory", SC2WOL_LOC_ID_OFFSET + 2600, LocationType.VICTORY, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Large Army", SC2WOL_LOC_ID_OFFSET + 2601, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 2 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2602, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 4 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2603, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 6 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2604, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 8 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2605, LocationType.CHALLENGE, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Southwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2606, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Northwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2607, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Northeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2608, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: East Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2609, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Southeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2610, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Expansion Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2611, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state) and + logic.terran_defense_rating(state, True) > 6), + LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Victory", SC2WOL_LOC_ID_OFFSET + 2700, LocationType.VICTORY), + LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: First Charge", SC2WOL_LOC_ID_OFFSET + 2701, LocationType.EXTRA), + LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Second Charge", SC2WOL_LOC_ID_OFFSET + 2702, LocationType.EXTRA), + LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Third Charge", SC2WOL_LOC_ID_OFFSET + 2703, LocationType.EXTRA), + LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: First Group Rescued", SC2WOL_LOC_ID_OFFSET + 2704, LocationType.VANILLA), + LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 2705, LocationType.VANILLA), + LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 2706, LocationType.VANILLA), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Victory", SC2WOL_LOC_ID_OFFSET + 2800, LocationType.VICTORY, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Close Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2801, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Northwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2802, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Southeast Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2803, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Southwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2804, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Leviathan", SC2WOL_LOC_ID_OFFSET + 2805, LocationType.VANILLA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: East Hatchery", SC2WOL_LOC_ID_OFFSET + 2806, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: North Hatchery", SC2WOL_LOC_ID_OFFSET + 2807, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Mid Hatchery", SC2WOL_LOC_ID_OFFSET + 2808, LocationType.EXTRA, + lambda state: logic.terran_competent_comp(state)), + LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Victory", SC2WOL_LOC_ID_OFFSET + 2900, LocationType.VICTORY, + lambda state: logic.all_in_requirement(state)), + LocationData(SC2Mission.ALL_IN.mission_name, "All-In: First Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2901, LocationType.EXTRA, + lambda state: logic.all_in_requirement(state)), + LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Second Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2902, LocationType.EXTRA, + lambda state: logic.all_in_requirement(state)), + LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Third Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2903, LocationType.EXTRA, + lambda state: logic.all_in_requirement(state)), + LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Fourth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2904, LocationType.EXTRA, + lambda state: logic.all_in_requirement(state)), + LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Fifth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2905, LocationType.EXTRA, + lambda state: logic.all_in_requirement(state)), + + # HotS + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Victory", SC2HOTS_LOC_ID_OFFSET + 100, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Gather Minerals", SC2HOTS_LOC_ID_OFFSET + 101, LocationType.VANILLA), + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: South Zergling Group", SC2HOTS_LOC_ID_OFFSET + 102, LocationType.VANILLA, + lambda state: adv_tactics or logic.zerg_common_unit(state)), + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: East Zergling Group", SC2HOTS_LOC_ID_OFFSET + 103, LocationType.VANILLA, + lambda state: adv_tactics or logic.zerg_common_unit(state)), + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: West Zergling Group", SC2HOTS_LOC_ID_OFFSET + 104, LocationType.VANILLA, + lambda state: adv_tactics or logic.zerg_common_unit(state)), + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Hatchery", SC2HOTS_LOC_ID_OFFSET + 105, LocationType.EXTRA), + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Overlord", SC2HOTS_LOC_ID_OFFSET + 106, LocationType.EXTRA), + LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Gas Turrets", SC2HOTS_LOC_ID_OFFSET + 107, LocationType.EXTRA, + lambda state: adv_tactics or logic.zerg_common_unit(state)), + LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Victory", SC2HOTS_LOC_ID_OFFSET + 200, LocationType.VICTORY, + lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), + LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Defend the Tram", SC2HOTS_LOC_ID_OFFSET + 201, LocationType.EXTRA, + lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), + LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Kinetic Blast", SC2HOTS_LOC_ID_OFFSET + 202, LocationType.VANILLA), + LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Crushing Grip", SC2HOTS_LOC_ID_OFFSET + 203, LocationType.VANILLA), + LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Reach the Sublevel", SC2HOTS_LOC_ID_OFFSET + 204, LocationType.EXTRA), + LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Door Section Cleared", SC2HOTS_LOC_ID_OFFSET + 205, LocationType.EXTRA, + lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), + LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Victory", SC2HOTS_LOC_ID_OFFSET + 300, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Right Queen", SC2HOTS_LOC_ID_OFFSET + 301, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Center Queen", SC2HOTS_LOC_ID_OFFSET + 302, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Left Queen", SC2HOTS_LOC_ID_OFFSET + 303, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Hold Out Finished", SC2HOTS_LOC_ID_OFFSET + 304, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Victory", SC2HOTS_LOC_ID_OFFSET + 400, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: First Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 401, LocationType.VANILLA), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: North Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 402, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: West Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 403, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Lost Brood", SC2HOTS_LOC_ID_OFFSET + 404, LocationType.EXTRA), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Northeast Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 405, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Northwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 406, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Southwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 407, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Nafash", SC2HOTS_LOC_ID_OFFSET + 408, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Victory", SC2HOTS_LOC_ID_OFFSET + 500, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: East Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 501, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Center Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 502, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) or adv_tactics), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: West Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 503, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Destroy 4 Shuttles", SC2HOTS_LOC_ID_OFFSET + 504, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Frozen Expansion", SC2HOTS_LOC_ID_OFFSET + 505, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Southwest Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 506, LocationType.EXTRA), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Southeast Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 507, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) or adv_tactics), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: West Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 508, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: East Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 509, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Victory", SC2HOTS_LOC_ID_OFFSET + 600, LocationType.VICTORY, + lambda state: logic.zerg_pass_vents(state) + and (logic.story_tech_granted + or state.has_any({item_names.ZERGLING_RAPTOR_STRAIN, item_names.ROACH, + item_names.HYDRALISK, item_names.INFESTOR}, player)) + ), + LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Infest Giant Ursadon", SC2HOTS_LOC_ID_OFFSET + 601, LocationType.VANILLA, + lambda state: logic.zerg_pass_vents(state)), + LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: First Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 602, LocationType.VANILLA, + lambda state: logic.zerg_pass_vents(state)), + LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Second Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 603, LocationType.VANILLA, + lambda state: logic.zerg_pass_vents(state)), + LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Third Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 604, LocationType.VANILLA, + lambda state: logic.zerg_pass_vents(state)), + LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Warp Drive", SC2HOTS_LOC_ID_OFFSET + 605, LocationType.EXTRA, + lambda state: logic.zerg_pass_vents(state)), + LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Stasis Quadrant", SC2HOTS_LOC_ID_OFFSET + 606, LocationType.EXTRA, + lambda state: logic.zerg_pass_vents(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Victory", SC2HOTS_LOC_ID_OFFSET + 700, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Center Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 701, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: North Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 702, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Repel Zagara", SC2HOTS_LOC_ID_OFFSET + 703, LocationType.EXTRA), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Close Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 704, LocationType.EXTRA), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: South Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 705, LocationType.EXTRA, + lambda state: adv_tactics or logic.zerg_common_unit(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Southwest Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 706, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Southeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 707, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: North Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 708, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Northeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 709, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: Victory", SC2HOTS_LOC_ID_OFFSET + 800, LocationType.VICTORY, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: West Biomass", SC2HOTS_LOC_ID_OFFSET + 801, LocationType.VANILLA), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: North Biomass", SC2HOTS_LOC_ID_OFFSET + 802, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: South Biomass", SC2HOTS_LOC_ID_OFFSET + 803, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: Destroy 3 Gorgons", SC2HOTS_LOC_ID_OFFSET + 804, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: Close Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 805, LocationType.EXTRA), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: South Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 806, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: North Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 807, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: West Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 808, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: East Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 809, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Victory", SC2HOTS_LOC_ID_OFFSET + 900, LocationType.VICTORY, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: East Science Lab", SC2HOTS_LOC_ID_OFFSET + 901, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: North Science Lab", SC2HOTS_LOC_ID_OFFSET + 902, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Get Nuked", SC2HOTS_LOC_ID_OFFSET + 903, LocationType.EXTRA), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Entrance Gate", SC2HOTS_LOC_ID_OFFSET + 904, LocationType.EXTRA), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Citadel Gate", SC2HOTS_LOC_ID_OFFSET + 905, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: South Expansion", SC2HOTS_LOC_ID_OFFSET + 906, LocationType.EXTRA), + LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Rich Mineral Expansion", SC2HOTS_LOC_ID_OFFSET + 907, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: Victory", SC2HOTS_LOC_ID_OFFSET + 1000, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: Center Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1001, LocationType.VANILLA), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: East Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1002, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + (adv_tactics and logic.zerg_basic_anti_air(state) + or logic.zerg_competent_anti_air(state))), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: South Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1003, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + (adv_tactics and logic.zerg_basic_anti_air(state) + or logic.zerg_competent_anti_air(state))), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: Finish Feeding", SC2HOTS_LOC_ID_OFFSET + 1004, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: South Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1005, LocationType.CHALLENGE, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: East Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1006, LocationType.CHALLENGE, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: South Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1007, LocationType.CHALLENGE, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: East Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1008, LocationType.CHALLENGE, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Victory", SC2HOTS_LOC_ID_OFFSET + 1100, LocationType.VICTORY, + lambda state: logic.zerg_competent_defense(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Tyrannozor", SC2HOTS_LOC_ID_OFFSET + 1101, LocationType.VANILLA, + lambda state: logic.zerg_competent_defense(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Reach the Pool", SC2HOTS_LOC_ID_OFFSET + 1102, LocationType.VANILLA), + LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: 15 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1103, LocationType.EXTRA, + lambda state: logic.zerg_competent_defense(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: 5 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1104, LocationType.EXTRA, + lambda state: logic.zerg_competent_defense(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Pincer Attack", SC2HOTS_LOC_ID_OFFSET + 1105, LocationType.EXTRA, + lambda state: logic.zerg_competent_defense(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Yagdra Claims Brakk's Pack", SC2HOTS_LOC_ID_OFFSET + 1106, LocationType.EXTRA, + lambda state: logic.zerg_competent_defense(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Victory", SC2HOTS_LOC_ID_OFFSET + 1200, LocationType.VICTORY, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: First Relic", SC2HOTS_LOC_ID_OFFSET + 1201, LocationType.VANILLA, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Second Relic", SC2HOTS_LOC_ID_OFFSET + 1202, LocationType.VANILLA, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Third Relic", SC2HOTS_LOC_ID_OFFSET + 1203, LocationType.VANILLA, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Fourth Relic", SC2HOTS_LOC_ID_OFFSET + 1204, LocationType.VANILLA, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Yagdra", SC2HOTS_LOC_ID_OFFSET + 1205, LocationType.EXTRA, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Kraith", SC2HOTS_LOC_ID_OFFSET + 1206, LocationType.EXTRA, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Slivan", SC2HOTS_LOC_ID_OFFSET + 1207, LocationType.EXTRA, + lambda state: logic.supreme_requirement(state)), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: Victory", SC2HOTS_LOC_ID_OFFSET + 1300, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state) and + ((logic.zerg_competent_anti_air(state) and state.has(item_names.INFESTOR, player)) or + (adv_tactics and logic.zerg_basic_anti_air(state)))), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: East Science Facility", SC2HOTS_LOC_ID_OFFSET + 1301, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: Center Science Facility", SC2HOTS_LOC_ID_OFFSET + 1302, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: West Science Facility", SC2HOTS_LOC_ID_OFFSET + 1303, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + logic.zerg_basic_anti_air(state) and + logic.spread_creep(state)), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: First Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1304, LocationType.EXTRA), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: Second Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1305, LocationType.EXTRA), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: Base Garrison", SC2HOTS_LOC_ID_OFFSET + 1306, LocationType.EXTRA), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: East Garrison", SC2HOTS_LOC_ID_OFFSET + 1307, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state) + and (adv_tactics or state.has(item_names.INFESTOR, player))), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: Mid Garrison", SC2HOTS_LOC_ID_OFFSET + 1308, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state) + and (adv_tactics or state.has(item_names.INFESTOR, player))), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: North Garrison", SC2HOTS_LOC_ID_OFFSET + 1309, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state) + and (adv_tactics or state.has(item_names.INFESTOR, player))), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: Close Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1310, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state) + and (adv_tactics or state.has(item_names.INFESTOR, player))), + LocationData(SC2Mission.INFESTED.mission_name, "Infested: Far Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1311, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) + and logic.zerg_basic_anti_air(state) + and (adv_tactics or state.has(item_names.INFESTOR, player))), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Victory", SC2HOTS_LOC_ID_OFFSET + 1400, LocationType.VICTORY, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: North Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1401, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: South Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1402, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 1 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1403, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 2 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1404, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 3 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1405, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 4 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1406, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 5 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1407, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 6 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1408, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 7 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1409, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_basic_anti_air(state)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Victory", SC2HOTS_LOC_ID_OFFSET + 1500, LocationType.VICTORY, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northwest Crystal", SC2HOTS_LOC_ID_OFFSET + 1501, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northeast Crystal", SC2HOTS_LOC_ID_OFFSET + 1502, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: South Crystal", SC2HOTS_LOC_ID_OFFSET + 1503, LocationType.VANILLA), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Base Established", SC2HOTS_LOC_ID_OFFSET + 1504, LocationType.EXTRA), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Close Temple", SC2HOTS_LOC_ID_OFFSET + 1505, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Mid Temple", SC2HOTS_LOC_ID_OFFSET + 1506, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Southeast Temple", SC2HOTS_LOC_ID_OFFSET + 1507, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northeast Temple", SC2HOTS_LOC_ID_OFFSET + 1508, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northwest Temple", SC2HOTS_LOC_ID_OFFSET + 1509, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + (logic.zerg_competent_anti_air(state) or adv_tactics)), + LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Victory", SC2HOTS_LOC_ID_OFFSET + 1600, LocationType.VICTORY), + LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Pirate Capital Ship", SC2HOTS_LOC_ID_OFFSET + 1601, LocationType.VANILLA), + LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: First Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1602, LocationType.VANILLA), + LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Second Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1603, LocationType.VANILLA), + LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Third Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1604, LocationType.VANILLA), + LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Victory", SC2HOTS_LOC_ID_OFFSET + 1700, LocationType.VICTORY, + lambda state: logic.two_kerrigan_actives(state) and + (logic.basic_kerrigan(state) or logic.story_tech_granted) or kerriganless), + LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: First Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1701, LocationType.VANILLA, + lambda state: logic.two_kerrigan_actives(state) or kerriganless), + LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Second Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1702, LocationType.VANILLA, + lambda state: logic.two_kerrigan_actives(state) and + (logic.basic_kerrigan(state) or logic.story_tech_granted) or kerriganless), + LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Power Coupling", SC2HOTS_LOC_ID_OFFSET + 1703, LocationType.EXTRA, + lambda state: logic.two_kerrigan_actives(state) or kerriganless), + LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Door Blasted", SC2HOTS_LOC_ID_OFFSET + 1704, LocationType.EXTRA, + lambda state: logic.two_kerrigan_actives(state) or kerriganless), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Victory", SC2HOTS_LOC_ID_OFFSET + 1800, LocationType.VICTORY, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: East Gate", SC2HOTS_LOC_ID_OFFSET + 1801, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Northwest Gate", SC2HOTS_LOC_ID_OFFSET + 1802, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: North Gate", SC2HOTS_LOC_ID_OFFSET + 1803, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 1 Bile Launcher Deployed", SC2HOTS_LOC_ID_OFFSET + 1804, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 2 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1805, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 3 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1806, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 4 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1807, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 5 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1808, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Sons of Korhal", SC2HOTS_LOC_ID_OFFSET + 1809, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Night Wolves", SC2HOTS_LOC_ID_OFFSET + 1810, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: West Expansion", SC2HOTS_LOC_ID_OFFSET + 1811, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Mid Expansion", SC2HOTS_LOC_ID_OFFSET + 1812, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Victory", SC2HOTS_LOC_ID_OFFSET + 1900, LocationType.VICTORY, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: First Power Link", SC2HOTS_LOC_ID_OFFSET + 1901, LocationType.VANILLA), + LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Second Power Link", SC2HOTS_LOC_ID_OFFSET + 1902, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Third Power Link", SC2HOTS_LOC_ID_OFFSET + 1903, LocationType.VANILLA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Expansion Command Center", SC2HOTS_LOC_ID_OFFSET + 1904, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Main Path Command Center", SC2HOTS_LOC_ID_OFFSET + 1905, LocationType.EXTRA, + lambda state: logic.zerg_competent_comp(state) and + logic.zerg_competent_anti_air(state)), + LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: Victory", SC2HOTS_LOC_ID_OFFSET + 2000, LocationType.VICTORY, + lambda state: logic.the_reckoning_requirement(state)), + LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: South Lane", SC2HOTS_LOC_ID_OFFSET + 2001, LocationType.VANILLA, + lambda state: logic.the_reckoning_requirement(state)), + LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: North Lane", SC2HOTS_LOC_ID_OFFSET + 2002, LocationType.VANILLA, + lambda state: logic.the_reckoning_requirement(state)), + LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: East Lane", SC2HOTS_LOC_ID_OFFSET + 2003, LocationType.VANILLA, + lambda state: logic.the_reckoning_requirement(state)), + LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: Odin", SC2HOTS_LOC_ID_OFFSET + 2004, LocationType.EXTRA, + lambda state: logic.the_reckoning_requirement(state)), + + # LotV Prologue + LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: Victory", SC2LOTV_LOC_ID_OFFSET + 100, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: First Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 101, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: Second Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 102, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: First Pylon", SC2LOTV_LOC_ID_OFFSET + 103, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: Second Pylon", SC2LOTV_LOC_ID_OFFSET + 104, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: Victory", SC2LOTV_LOC_ID_OFFSET + 200, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: South Rock Formation", SC2LOTV_LOC_ID_OFFSET + 201, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: West Rock Formation", SC2LOTV_LOC_ID_OFFSET + 202, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: East Rock Formation", SC2LOTV_LOC_ID_OFFSET + 203, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) \ + and logic.protoss_anti_armor_anti_air(state) \ + and logic.protoss_can_attack_behind_chasm(state)), + LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Victory", SC2LOTV_LOC_ID_OFFSET + 300, LocationType.VICTORY), + LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Temple Investigated", SC2LOTV_LOC_ID_OFFSET + 301, LocationType.EXTRA), + LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Void Catalyst", SC2LOTV_LOC_ID_OFFSET + 302, LocationType.EXTRA), + LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: First Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 303, LocationType.VANILLA), + LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Second Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 304, LocationType.VANILLA), + LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Third Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 305, LocationType.VANILLA), + + + # LotV + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Victory", SC2LOTV_LOC_ID_OFFSET + 400, LocationType.VICTORY), + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Southwest Hive", SC2LOTV_LOC_ID_OFFSET + 401, LocationType.VANILLA), + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Northwest Hive", SC2LOTV_LOC_ID_OFFSET + 402, LocationType.VANILLA), + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Northeast Hive", SC2LOTV_LOC_ID_OFFSET + 403, LocationType.VANILLA), + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: East Hive", SC2LOTV_LOC_ID_OFFSET + 404, LocationType.VANILLA), + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: West Conduit", SC2LOTV_LOC_ID_OFFSET + 405, LocationType.EXTRA), + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Middle Conduit", SC2LOTV_LOC_ID_OFFSET + 406, LocationType.EXTRA), + LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Northeast Conduit", SC2LOTV_LOC_ID_OFFSET + 407, LocationType.EXTRA), + LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Victory", SC2LOTV_LOC_ID_OFFSET + 500, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Close Pylon", SC2LOTV_LOC_ID_OFFSET + 501, LocationType.VANILLA), + LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: East Pylon", SC2LOTV_LOC_ID_OFFSET + 502, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: West Pylon", SC2LOTV_LOC_ID_OFFSET + 503, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Nexus", SC2LOTV_LOC_ID_OFFSET + 504, LocationType.EXTRA), + LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Templar Base", SC2LOTV_LOC_ID_OFFSET + 505, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: Victory", SC2LOTV_LOC_ID_OFFSET + 600, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: Close Warp Gate", SC2LOTV_LOC_ID_OFFSET + 601, LocationType.VANILLA), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: West Warp Gate", SC2LOTV_LOC_ID_OFFSET + 602, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: North Warp Gate", SC2LOTV_LOC_ID_OFFSET + 603, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: North Power Cell", SC2LOTV_LOC_ID_OFFSET + 604, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: East Power Cell", SC2LOTV_LOC_ID_OFFSET + 605, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: South Power Cell", SC2LOTV_LOC_ID_OFFSET + 606, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: Southeast Power Cell", SC2LOTV_LOC_ID_OFFSET + 607, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Victory", SC2LOTV_LOC_ID_OFFSET + 700, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Mid EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 701, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Southeast EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 702, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: North EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 703, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Mid Stabilizer", SC2LOTV_LOC_ID_OFFSET + 704, LocationType.EXTRA), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Southwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 705, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Northwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 706, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Northeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 707, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Southeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 708, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: West Raynor Base", SC2LOTV_LOC_ID_OFFSET + 709, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: East Raynor Base", SC2LOTV_LOC_ID_OFFSET + 710, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_basic_anti_air(state)), + LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: Victory", SC2LOTV_LOC_ID_OFFSET + 800, LocationType.VICTORY, + lambda state: logic.brothers_in_arms_requirement(state)), + LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: Mid Science Facility", SC2LOTV_LOC_ID_OFFSET + 801, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) or logic.take_over_ai_allies), + LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: North Science Facility", SC2LOTV_LOC_ID_OFFSET + 802, LocationType.VANILLA, + lambda state: logic.brothers_in_arms_requirement(state) + or logic.take_over_ai_allies + and logic.advanced_tactics + and ( + logic.terran_common_unit(state) + or logic.protoss_common_unit(state) + ) + ), + LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: South Science Facility", SC2LOTV_LOC_ID_OFFSET + 803, LocationType.VANILLA, + lambda state: logic.brothers_in_arms_requirement(state)), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: Victory", SC2LOTV_LOC_ID_OFFSET + 900, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: Close Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 901, LocationType.VANILLA), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: North Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 902, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: East Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 903, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: West Launch Bay", SC2LOTV_LOC_ID_OFFSET + 904, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: South Launch Bay", SC2LOTV_LOC_ID_OFFSET + 905, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: Northwest Launch Bay", SC2LOTV_LOC_ID_OFFSET + 906, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: East Launch Bay", SC2LOTV_LOC_ID_OFFSET + 907, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: Victory", SC2LOTV_LOC_ID_OFFSET + 1000, LocationType.VICTORY, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: West Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1001, LocationType.VANILLA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: North Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1002, LocationType.VANILLA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: East Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1003, LocationType.VANILLA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: 1 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1004, LocationType.EXTRA, + lambda state: logic.last_stand_requirement(state)), + LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: 1.5 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1005, LocationType.VANILLA, + lambda state: logic.last_stand_requirement(state) and ( + state.has_all({item_names.KHAYDARIN_MONOLITH, item_names.PHOTON_CANNON, item_names.SHIELD_BATTERY}, player) + or state.has_any({item_names.SOA_SOLAR_LANCE, item_names.SOA_DEPLOY_FENIX}, player) + )), + LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: Victory", SC2LOTV_LOC_ID_OFFSET + 1100, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: South Solarite", SC2LOTV_LOC_ID_OFFSET + 1101, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: North Solarite", SC2LOTV_LOC_ID_OFFSET + 1102, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: Northwest Solarite", SC2LOTV_LOC_ID_OFFSET + 1103, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: Victory", SC2LOTV_LOC_ID_OFFSET + 1200, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: Mid Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1201, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: West Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1202, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: South Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1203, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: East Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1204, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: North Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1205, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: Titanic Warp Prism", SC2LOTV_LOC_ID_OFFSET + 1206, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) + and logic.protoss_anti_armor_anti_air(state)), + LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Victory", SC2LOTV_LOC_ID_OFFSET + 1300, LocationType.VICTORY, + lambda state: logic.the_infinite_cycle_requirement(state)), + LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: First Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1301, LocationType.EXTRA, + lambda state: logic.the_infinite_cycle_requirement(state)), + LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Second Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1302, LocationType.EXTRA, + lambda state: logic.the_infinite_cycle_requirement(state)), + LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: First Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1303, LocationType.VANILLA, + lambda state: logic.the_infinite_cycle_requirement(state)), + LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Second Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1304, LocationType.VANILLA, + lambda state: logic.the_infinite_cycle_requirement(state)), + LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Third Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1305, LocationType.VANILLA, + lambda state: logic.the_infinite_cycle_requirement(state)), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Victory", SC2LOTV_LOC_ID_OFFSET + 1400, LocationType.VICTORY, + lambda state: logic.harbinger_of_oblivion_requirement(state)), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Artanis", SC2LOTV_LOC_ID_OFFSET + 1401, LocationType.EXTRA), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Northwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1402, LocationType.EXTRA, + lambda state: logic.harbinger_of_oblivion_requirement(state)), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Northeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1403, LocationType.EXTRA, + lambda state: logic.harbinger_of_oblivion_requirement(state)), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Southwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1404, LocationType.EXTRA, + lambda state: logic.harbinger_of_oblivion_requirement(state)), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Southeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1405, LocationType.EXTRA, + lambda state: logic.harbinger_of_oblivion_requirement(state)), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: South Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1406, LocationType.VANILLA), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Mid Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1407, LocationType.VANILLA, + lambda state: logic.harbinger_of_oblivion_requirement(state)), + LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: North Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1408, LocationType.VANILLA, + lambda state: logic.harbinger_of_oblivion_requirement(state)), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Victory", SC2LOTV_LOC_ID_OFFSET + 1500, LocationType.VICTORY, + lambda state: logic.protoss_basic_splash(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Zerg Cleared", SC2LOTV_LOC_ID_OFFSET + 1501, LocationType.EXTRA), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: First Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1502, LocationType.EXTRA, + lambda state: logic.advanced_tactics \ + or logic.protoss_basic_splash(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Second Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1503, LocationType.EXTRA, + lambda state: logic.protoss_basic_splash(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Third Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1504, LocationType.EXTRA, + lambda state: logic.protoss_basic_splash(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Fourth Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1505, LocationType.EXTRA, + lambda state: logic.protoss_basic_splash(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: South Power Core", SC2LOTV_LOC_ID_OFFSET + 1506, LocationType.VANILLA, + lambda state: logic.protoss_basic_splash(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: East Power Core", SC2LOTV_LOC_ID_OFFSET + 1507, LocationType.VANILLA, + lambda state: logic.protoss_basic_splash(state) + and logic.protoss_anti_light_anti_air(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: Victory", SC2LOTV_LOC_ID_OFFSET + 1600, LocationType.VICTORY, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: North Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1601, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: North Sector: Northeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1602, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: North Sector: Southeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1603, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: South Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1604, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: South Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1605, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: South Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1606, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: West Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1607, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: West Sector: Mid Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1608, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: West Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1609, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: East Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1610, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: East Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1611, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: East Sector: South Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1612, LocationType.EXTRA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: Purifier Warden", SC2LOTV_LOC_ID_OFFSET + 1613, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Victory", SC2LOTV_LOC_ID_OFFSET + 1700, LocationType.VICTORY, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: First Terrazine Fog", SC2LOTV_LOC_ID_OFFSET + 1701, LocationType.EXTRA, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Southwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1702, LocationType.EXTRA, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: West Guardian", SC2LOTV_LOC_ID_OFFSET + 1703, LocationType.EXTRA, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Northwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1704, LocationType.EXTRA, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Northeast Guardian", SC2LOTV_LOC_ID_OFFSET + 1705, LocationType.EXTRA, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: North Mothership", SC2LOTV_LOC_ID_OFFSET + 1706, LocationType.VANILLA, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: South Mothership", SC2LOTV_LOC_ID_OFFSET + 1707, LocationType.VANILLA, + lambda state: logic.steps_of_the_rite_requirement(state)), + LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: Victory", SC2LOTV_LOC_ID_OFFSET + 1800, LocationType.VICTORY, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: North Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1801, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: Southwest Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1802, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: East Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1803, LocationType.VANILLA, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Victory", SC2LOTV_LOC_ID_OFFSET + 1900, LocationType.VICTORY, + lambda state: logic.templars_charge_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Northwest Power Core", SC2LOTV_LOC_ID_OFFSET + 1901, LocationType.EXTRA, + lambda state: logic.templars_charge_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Northeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1902, LocationType.EXTRA, + lambda state: logic.templars_charge_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Southeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1903, LocationType.EXTRA, + lambda state: logic.templars_charge_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: West Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1904, LocationType.VANILLA, + lambda state: logic.templars_charge_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Southeast Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1905, LocationType.VANILLA, + lambda state: logic.protoss_fleet(state)), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Victory", SC2LOTV_LOC_ID_OFFSET + 2000, LocationType.VICTORY, + lambda state: logic.templars_return_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Citadel: First Gate", SC2LOTV_LOC_ID_OFFSET + 2001, LocationType.EXTRA), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Citadel: Second Gate", SC2LOTV_LOC_ID_OFFSET + 2002, LocationType.EXTRA), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Citadel: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2003, LocationType.VANILLA), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Temple Grounds: Gather Army", SC2LOTV_LOC_ID_OFFSET + 2004, LocationType.VANILLA, + lambda state: logic.templars_return_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Temple Grounds: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2005, LocationType.VANILLA, + lambda state: logic.templars_return_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Caverns: Purifier", SC2LOTV_LOC_ID_OFFSET + 2006, LocationType.EXTRA, + lambda state: logic.templars_return_requirement(state)), + LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Caverns: Dark Templar", SC2LOTV_LOC_ID_OFFSET + 2007, LocationType.EXTRA, + lambda state: logic.templars_return_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Victory", SC2LOTV_LOC_ID_OFFSET + 2100, LocationType.VICTORY, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Southeast Void Shard", SC2LOTV_LOC_ID_OFFSET + 2101, LocationType.VICTORY, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: South Void Shard", SC2LOTV_LOC_ID_OFFSET + 2102, LocationType.EXTRA, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Southwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2103, LocationType.EXTRA, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: North Void Shard", SC2LOTV_LOC_ID_OFFSET + 2104, LocationType.EXTRA, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Northwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2105, LocationType.EXTRA, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Nerazim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2106, LocationType.VANILLA, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Tal'darim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2107, LocationType.VANILLA, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Purifier Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2108, LocationType.VANILLA, + lambda state: logic.the_host_requirement(state)), + LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Victory", SC2LOTV_LOC_ID_OFFSET + 2200, LocationType.VICTORY, + lambda state: logic.salvation_requirement(state)), + LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Fabrication Matrix", SC2LOTV_LOC_ID_OFFSET + 2201, LocationType.EXTRA, + lambda state: logic.salvation_requirement(state)), + LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Assault Cluster", SC2LOTV_LOC_ID_OFFSET + 2202, LocationType.EXTRA, + lambda state: logic.salvation_requirement(state)), + LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Hull Breach", SC2LOTV_LOC_ID_OFFSET + 2203, LocationType.EXTRA, + lambda state: logic.salvation_requirement(state)), + LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Core Critical", SC2LOTV_LOC_ID_OFFSET + 2204, LocationType.EXTRA, + lambda state: logic.salvation_requirement(state)), + + # Epilogue + LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Victory", SC2LOTV_LOC_ID_OFFSET + 2300, LocationType.VICTORY, + lambda state: logic.into_the_void_requirement(state)), + LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Corruption Source", SC2LOTV_LOC_ID_OFFSET + 2301, LocationType.EXTRA), + LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Southwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2302, LocationType.VANILLA, + lambda state: logic.into_the_void_requirement(state)), + LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Northwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2303, LocationType.VANILLA, + lambda state: logic.into_the_void_requirement(state)), + LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Southeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2304, LocationType.VANILLA, + lambda state: logic.into_the_void_requirement(state)), + LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Northeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2305, LocationType.VANILLA), + LocationData(SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, "The Essence of Eternity: Victory", SC2LOTV_LOC_ID_OFFSET + 2400, LocationType.VICTORY, + lambda state: logic.essence_of_eternity_requirement(state)), + LocationData(SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, "The Essence of Eternity: Void Trashers", SC2LOTV_LOC_ID_OFFSET + 2401, LocationType.EXTRA), + LocationData(SC2Mission.AMON_S_FALL.mission_name, "Amon's Fall: Victory", SC2LOTV_LOC_ID_OFFSET + 2500, LocationType.VICTORY, + lambda state: logic.amons_fall_requirement(state)), + + # Nova Covert Ops + LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Victory", SC2NCO_LOC_ID_OFFSET + 100, LocationType.VICTORY, + lambda state: logic.the_escape_requirement(state)), + LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Rifle", SC2NCO_LOC_ID_OFFSET + 101, LocationType.VANILLA, + lambda state: logic.the_escape_first_stage_requirement(state)), + LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Grenades", SC2NCO_LOC_ID_OFFSET + 102, LocationType.VANILLA, + lambda state: logic.the_escape_first_stage_requirement(state)), + LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Agent Delta", SC2NCO_LOC_ID_OFFSET + 103, LocationType.VANILLA, + lambda state: logic.the_escape_requirement(state)), + LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Agent Pierce", SC2NCO_LOC_ID_OFFSET + 104, LocationType.VANILLA, + lambda state: logic.the_escape_requirement(state)), + LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Agent Stone", SC2NCO_LOC_ID_OFFSET + 105, LocationType.VANILLA, + lambda state: logic.the_escape_requirement(state)), + LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Victory", SC2NCO_LOC_ID_OFFSET + 200, LocationType.VICTORY, + lambda state: logic.sudden_strike_can_reach_objectives(state)), + LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Research Center", SC2NCO_LOC_ID_OFFSET + 201, LocationType.VANILLA, + lambda state: logic.sudden_strike_can_reach_objectives(state)), + LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Weaponry Labs", SC2NCO_LOC_ID_OFFSET + 202, LocationType.VANILLA, + lambda state: logic.sudden_strike_requirement(state)), + LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Brutalisk", SC2NCO_LOC_ID_OFFSET + 203, LocationType.EXTRA, + lambda state: logic.sudden_strike_requirement(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Victory", SC2NCO_LOC_ID_OFFSET + 300, LocationType.VICTORY, + lambda state: logic.enemy_intelligence_third_stage_requirement(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: West Garrison", SC2NCO_LOC_ID_OFFSET + 301, LocationType.EXTRA, + lambda state: logic.enemy_intelligence_first_stage_requirement(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Close Garrison", SC2NCO_LOC_ID_OFFSET + 302, LocationType.EXTRA, + lambda state: logic.enemy_intelligence_first_stage_requirement(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Northeast Garrison", SC2NCO_LOC_ID_OFFSET + 303, LocationType.EXTRA, + lambda state: logic.enemy_intelligence_first_stage_requirement(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Southeast Garrison", SC2NCO_LOC_ID_OFFSET + 304, LocationType.EXTRA, + lambda state: logic.enemy_intelligence_first_stage_requirement(state) + and logic.enemy_intelligence_cliff_garrison(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: South Garrison", SC2NCO_LOC_ID_OFFSET + 305, LocationType.EXTRA, + lambda state: logic.enemy_intelligence_first_stage_requirement(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: All Garrisons", SC2NCO_LOC_ID_OFFSET + 306, LocationType.VANILLA, + lambda state: logic.enemy_intelligence_first_stage_requirement(state) + and logic.enemy_intelligence_cliff_garrison(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Forces Rescued", SC2NCO_LOC_ID_OFFSET + 307, LocationType.VANILLA, + lambda state: logic.enemy_intelligence_first_stage_requirement(state)), + LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Communications Hub", SC2NCO_LOC_ID_OFFSET + 308, LocationType.VANILLA, + lambda state: logic.enemy_intelligence_second_stage_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: Victory", SC2NCO_LOC_ID_OFFSET + 400, LocationType.VICTORY, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Base: West Hatchery", SC2NCO_LOC_ID_OFFSET + 401, LocationType.VANILLA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Base: North Hatchery", SC2NCO_LOC_ID_OFFSET + 402, LocationType.VANILLA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 403, LocationType.VANILLA), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Base: Northwest Hatchery", SC2NCO_LOC_ID_OFFSET + 404, LocationType.VANILLA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Base: Southwest Hatchery", SC2NCO_LOC_ID_OFFSET + 405, LocationType.VANILLA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 406, LocationType.VANILLA), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Shield Projector", SC2NCO_LOC_ID_OFFSET + 407, LocationType.EXTRA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: East Shield Projector", SC2NCO_LOC_ID_OFFSET + 408, LocationType.EXTRA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Shield Projector", SC2NCO_LOC_ID_OFFSET + 409, LocationType.EXTRA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: West Shield Projector", SC2NCO_LOC_ID_OFFSET + 410, LocationType.EXTRA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: Fleet Beacon", SC2NCO_LOC_ID_OFFSET + 411, LocationType.VANILLA, + lambda state: logic.trouble_in_paradise_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Victory", SC2NCO_LOC_ID_OFFSET + 500, LocationType.VICTORY, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 1 Terrazine Node Collected", SC2NCO_LOC_ID_OFFSET + 501, LocationType.EXTRA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 2 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 502, LocationType.EXTRA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 3 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 503, LocationType.EXTRA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 4 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 504, LocationType.EXTRA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 5 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 505, LocationType.EXTRA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: HERC Outpost", SC2NCO_LOC_ID_OFFSET + 506, LocationType.VANILLA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Umojan Mine", SC2NCO_LOC_ID_OFFSET + 507, LocationType.EXTRA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Blightbringer", SC2NCO_LOC_ID_OFFSET + 508, LocationType.VANILLA, + lambda state: logic.night_terrors_requirement(state) + and logic.nova_ranged_weapon(state) + and state.has_any( + {item_names.NOVA_HELLFIRE_SHOTGUN, item_names.NOVA_PULSE_GRENADES, item_names.NOVA_STIM_INFUSION, + item_names.NOVA_HOLO_DECOY}, player)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Science Facility", SC2NCO_LOC_ID_OFFSET + 509, LocationType.EXTRA, + lambda state: logic.night_terrors_requirement(state)), + LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Eradicators", SC2NCO_LOC_ID_OFFSET + 510, LocationType.VANILLA, + lambda state: logic.night_terrors_requirement(state) + and logic.nova_any_weapon(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Victory", SC2NCO_LOC_ID_OFFSET + 600, LocationType.VICTORY, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Close North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 601, LocationType.EXTRA, + lambda state: state.has_any( + {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) + or logic.terran_common_unit(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Close East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 602, LocationType.EXTRA, + lambda state: state.has_any( + {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) + or logic.terran_common_unit(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Far North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 603, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Far East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 604, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Experimental Weapon", SC2NCO_LOC_ID_OFFSET + 605, LocationType.VANILLA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Northwest Subway Entrance", SC2NCO_LOC_ID_OFFSET + 606, LocationType.VANILLA, + lambda state: state.has_any( + {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) + and logic.terran_common_unit(state) + or logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Southeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 607, LocationType.VANILLA, + lambda state: state.has_any( + {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) + and logic.terran_common_unit(state) + or logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Northeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 608, LocationType.VANILLA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Expansion Hatchery", SC2NCO_LOC_ID_OFFSET + 609, LocationType.EXTRA, + lambda state: state.has(item_names.LIBERATOR_RAID_ARTILLERY, player) and logic.terran_common_unit(state) + or logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Baneling Spawns", SC2NCO_LOC_ID_OFFSET + 610, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Mutalisk Spawns", SC2NCO_LOC_ID_OFFSET + 611, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Nydus Worm Spawns", SC2NCO_LOC_ID_OFFSET + 612, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Lurker Spawns", SC2NCO_LOC_ID_OFFSET + 613, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Brood Lord Spawns", SC2NCO_LOC_ID_OFFSET + 614, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Ultralisk Spawns", SC2NCO_LOC_ID_OFFSET + 615, LocationType.EXTRA, + lambda state: logic.flashpoint_far_requirement(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Victory", SC2NCO_LOC_ID_OFFSET + 700, LocationType.VICTORY, + lambda state: logic.enemy_shadow_victory(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Sewers: Domination Visor", SC2NCO_LOC_ID_OFFSET + 701, LocationType.VANILLA, + lambda state: logic.enemy_shadow_domination(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Sewers: Resupply Crate", SC2NCO_LOC_ID_OFFSET + 702, LocationType.EXTRA, + lambda state: logic.enemy_shadow_first_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Sewers: Facility Access", SC2NCO_LOC_ID_OFFSET + 703, LocationType.VANILLA, + lambda state: logic.enemy_shadow_first_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Northwest Door Lock", SC2NCO_LOC_ID_OFFSET + 704, LocationType.VANILLA, + lambda state: logic.enemy_shadow_door_controls(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Southeast Door Lock", SC2NCO_LOC_ID_OFFSET + 705, LocationType.VANILLA, + lambda state: logic.enemy_shadow_door_controls(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Blazefire Gunblade", SC2NCO_LOC_ID_OFFSET + 706, LocationType.VANILLA, + lambda state: logic.enemy_shadow_second_stage(state) + and (logic.story_tech_granted + or state.has(item_names.NOVA_BLINK, player) + or (adv_tactics and state.has_all({item_names.NOVA_DOMINATION, item_names.NOVA_HOLO_DECOY, item_names.NOVA_JUMP_SUIT_MODULE}, player)) + ) + ), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Blink Suit", SC2NCO_LOC_ID_OFFSET + 707, LocationType.VANILLA, + lambda state: logic.enemy_shadow_second_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Advanced Weaponry", SC2NCO_LOC_ID_OFFSET + 708, LocationType.VANILLA, + lambda state: logic.enemy_shadow_second_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Entrance Resupply Crate", SC2NCO_LOC_ID_OFFSET + 709, LocationType.EXTRA, + lambda state: logic.enemy_shadow_first_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: West Resupply Crate", SC2NCO_LOC_ID_OFFSET + 710, LocationType.EXTRA, + lambda state: logic.enemy_shadow_second_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: North Resupply Crate", SC2NCO_LOC_ID_OFFSET + 711, LocationType.EXTRA, + lambda state: logic.enemy_shadow_second_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: East Resupply Crate", SC2NCO_LOC_ID_OFFSET + 712, LocationType.EXTRA, + lambda state: logic.enemy_shadow_second_stage(state)), + LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: South Resupply Crate", SC2NCO_LOC_ID_OFFSET + 713, LocationType.EXTRA, + lambda state: logic.enemy_shadow_second_stage(state)), + LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Victory", SC2NCO_LOC_ID_OFFSET + 800, LocationType.VICTORY, + lambda state: logic.dark_skies_requirement(state)), + LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: First Squadron of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 801, LocationType.EXTRA, + lambda state: logic.dark_skies_requirement(state)), + LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Remainder of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 802, LocationType.EXTRA, + lambda state: logic.dark_skies_requirement(state)), + LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Ji'nara", SC2NCO_LOC_ID_OFFSET + 803, LocationType.EXTRA, + lambda state: logic.dark_skies_requirement(state)), + LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Science Facility", SC2NCO_LOC_ID_OFFSET + 804, LocationType.VANILLA, + lambda state: logic.dark_skies_requirement(state)), + LocationData(SC2Mission.END_GAME.mission_name, "End Game: Victory", SC2NCO_LOC_ID_OFFSET + 900, LocationType.VICTORY, + lambda state: logic.end_game_requirement(state) and logic.nova_any_weapon(state)), + LocationData(SC2Mission.END_GAME.mission_name, "End Game: Xanthos", SC2NCO_LOC_ID_OFFSET + 901, LocationType.VANILLA, + lambda state: logic.end_game_requirement(state)), + + # Mission Variants + # 10X/20X - Liberation Day + LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 300, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 301, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 302, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 303, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 304, LocationType.EXTRA), + LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 400, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 401, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 402, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 403, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 404, LocationType.EXTRA), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 500, LocationType.VICTORY, + lambda state: logic.zerg_competent_defense(state) and + logic.zerg_basic_kerriganless_anti_air(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 501, LocationType.VANILLA), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 502, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 503, LocationType.VANILLA, + lambda state: logic.zerg_competent_defense(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 504, LocationType.CHALLENGE, + lambda state: logic.zerg_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 505, LocationType.CHALLENGE, + lambda state: logic.zerg_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 506, LocationType.CHALLENGE, + lambda state: logic.zerg_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 507, LocationType.CHALLENGE, + lambda state: logic.zerg_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 508, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 509, + LocationType.EXTRA, + lambda state: logic.zerg_competent_defense(state)), + LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 510, LocationType.EXTRA, + lambda state: logic.zerg_competent_defense(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 600, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) and + (adv_tactics or logic.protoss_basic_anti_air(state))), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 601, LocationType.VANILLA), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 602, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 603, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 604, LocationType.CHALLENGE, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 605, LocationType.CHALLENGE, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 606, LocationType.CHALLENGE, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 607, LocationType.CHALLENGE, + lambda state: logic.protoss_competent_comp(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 608, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 609, + LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state)), + LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 610, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state)), + # 70X/80X - Evacuation + # 90X/100X - Outbreak + # 110X/120X - Safe Haven + # 130X/140X - Haven's Fall + LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1500, LocationType.VICTORY, + lambda state: logic.zerg_common_unit(state) and + (adv_tactics and logic.zerg_basic_anti_air(state) + or logic.zerg_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1501, LocationType.VANILLA), + LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1502, LocationType.VANILLA), + LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1503, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) + or logic.zerg_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1504, LocationType.VANILLA, + lambda state: logic.zerg_common_unit(state) and + (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) + or logic.zerg_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1505, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and + (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) + or logic.zerg_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1506, LocationType.EXTRA, + lambda state: logic.zerg_common_unit(state) and + (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) + or logic.zerg_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1600, LocationType.VICTORY, + lambda state: logic.protoss_common_unit(state) and + (adv_tactics and logic.protoss_basic_anti_air(state) + or logic.protoss_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1601, LocationType.VANILLA), + LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1602, LocationType.VANILLA), + LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1603, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) and + (adv_tactics and logic.protoss_basic_anti_air(state) + or logic.protoss_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1604, LocationType.VANILLA, + lambda state: logic.protoss_common_unit(state) and + (adv_tactics and logic.protoss_basic_anti_air(state) + or logic.protoss_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1605, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) and + (adv_tactics and logic.protoss_basic_anti_air(state) + or logic.protoss_competent_anti_air(state))), + LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1606, LocationType.EXTRA, + lambda state: logic.protoss_common_unit(state) and + (adv_tactics and logic.protoss_basic_anti_air(state) + or logic.protoss_competent_anti_air(state))), + ] + + beat_events = [] + # Filtering out excluded locations + if world is not None: + excluded_location_types = get_location_types(world, LocationInclusion.option_disabled) + plando_locations = get_plando_locations(world) + exclude_locations = world.options.exclude_locations.value + location_table = [location for location in location_table + if (location.type is LocationType.VICTORY or location.name not in exclude_locations) + and location.type not in excluded_location_types + or location.name in plando_locations] + for i, location_data in enumerate(location_table): + # Removing all item-based logic on No Logic + if logic_level == RequiredTactics.option_no_logic: + 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( + location_data._replace(name="Beat " + location_data.name.rsplit(": ", 1)[0], code=None) + ) + return tuple(location_table + beat_events) + lookup_location_id_to_type = {loc.code: loc.type for loc in get_locations(None) if loc.code is not None} \ No newline at end of file diff --git a/worlds/sc2/mission_tables.py b/worlds/sc2/mission_tables.py index fa1d5d2bd77e..265dee7f8c76 100644 --- a/worlds/sc2/mission_tables.py +++ b/worlds/sc2/mission_tables.py @@ -354,11 +354,10 @@ class FillMission(NamedTuple): mission.mission_name: mission for mission in SC2Mission } for mission in SC2Mission: - if mission.id <= SC2Mission.END_GAME.id: - if '(' in mission.mission_name: - # Short names for non-race-swapped missions for client compatibility - short_name = mission.mission_name[:mission.mission_name.find(' (')] - lookup_name_to_mission[short_name] = mission + if MissionFlag.HasRaceSwap in mission.flags and ' (' in mission.mission_name: + # Short names for non-race-swapped missions for client compatibility + short_name = mission.mission_name[:mission.mission_name.find(' (')] + lookup_name_to_mission[short_name] = mission lookup_id_to_campaign: Dict[int, SC2Campaign] = { campaign.id: campaign for campaign in SC2Campaign diff --git a/worlds/sc2/regions.py b/worlds/sc2/regions.py index 4fc8c20f4d8e..cf4a09c4ae3f 100644 --- a/worlds/sc2/regions.py +++ b/worlds/sc2/regions.py @@ -1,723 +1,723 @@ -from typing import List, Dict, Tuple, Optional, Callable, NamedTuple, Union, TYPE_CHECKING -import math - -from BaseClasses import Region, Entrance, Location, CollectionState -from .locations import LocationData -from .options import get_option_value, MissionOrder, get_enabled_campaigns, campaign_depending_orders, \ - GridTwoStartPositions, static_mission_orders, dynamic_mission_orders -from .mission_tables import MissionInfo, vanilla_mission_req_table, \ - MissionPools, SC2Campaign, get_goal_location, SC2Mission, MissionConnection, FillMission -from .mission_orders import make_gauntlet, make_blitz, make_golden_path, make_hopscotch -from .pool_filter import filter_missions - - -if TYPE_CHECKING: - from . import SC2World - - -class SC2MissionSlot(NamedTuple): - campaign: SC2Campaign - slot: Union[MissionPools, SC2Mission, None] - - -def create_regions( - world: 'SC2World', locations: Tuple[LocationData, ...], location_cache: List[Location] -) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: - """ - Creates region connections by calling the multiworld's `connect()` methods - Returns a 3-tuple containing: - * dict[SC2Campaign, Dict[str, MissionInfo]] mapping a campaign and mission name to its data - * int The number of missions in the world - * str The name of the goal location - """ - mission_order_type: MissionOrder = world.options.mission_order - - if mission_order_type == MissionOrder.option_vanilla: - return create_vanilla_regions(world, locations, location_cache) - elif mission_order_type == MissionOrder.option_grid: - return create_grid_regions(world, locations, location_cache) - else: - return create_structured_regions(world, locations, location_cache, mission_order_type) - -def create_vanilla_regions( - world: 'SC2World', - locations: Tuple[LocationData, ...], - location_cache: List[Location], -) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: - locations_per_region = get_locations_per_region(locations) - regions = [create_region(world, locations_per_region, location_cache, "Menu")] - - mission_pools: Dict[MissionPools, List[SC2Mission]] = filter_missions(world) - final_mission = mission_pools[MissionPools.FINAL][0] - - enabled_campaigns = get_enabled_campaigns(world) - names: Dict[str, int] = {} - - # Generating all regions and locations for each enabled campaign - for campaign in enabled_campaigns: - for region_name in vanilla_mission_req_table[campaign].keys(): - regions.append(create_region(world, locations_per_region, location_cache, region_name)) - world.multiworld.regions += regions - vanilla_mission_reqs = {campaign: missions for campaign, missions in vanilla_mission_req_table.items() if campaign in enabled_campaigns} - - def wol_cleared_missions(state: CollectionState, mission_count: int) -> bool: - return state.has_group("WoL Missions", world.player, mission_count) - - player: int = world.player - if SC2Campaign.WOL in enabled_campaigns: - connect(world, names, 'Menu', 'Liberation Day') - connect(world, names, 'Liberation Day', 'The Outlaws (Terran)', - lambda state: state.has("Beat Liberation Day", player)) - connect(world, names, 'The Outlaws (Terran)', 'Zero Hour (Terran)', - lambda state: state.has("Beat The Outlaws (Terran)", player)) - connect(world, names, 'Zero Hour (Terran)', 'Evacuation', - lambda state: state.has("Beat Zero Hour (Terran)", player)) - connect(world, names, 'Evacuation', 'Outbreak', - lambda state: state.has("Beat Evacuation", player)) - connect(world, names, "Outbreak", "Safe Haven", - lambda state: wol_cleared_missions(state, 7) and state.has("Beat Outbreak", player)) - connect(world, names, "Outbreak", "Haven's Fall", - lambda state: wol_cleared_missions(state, 7) and state.has("Beat Outbreak", player)) - connect(world, names, 'Zero Hour (Terran)', 'Smash and Grab (Terran)', - lambda state: state.has("Beat Zero Hour (Terran)", player)) - connect(world, names, 'Smash and Grab (Terran)', 'The Dig', - lambda state: wol_cleared_missions(state, 8) and state.has("Beat Smash and Grab (Terran)", player)) - connect(world, names, 'The Dig', 'The Moebius Factor', - lambda state: wol_cleared_missions(state, 11) and state.has("Beat The Dig", player)) - connect(world, names, 'The Moebius Factor', 'Supernova', - lambda state: wol_cleared_missions(state, 14) and state.has("Beat The Moebius Factor", player)) - connect(world, names, 'Supernova', 'Maw of the Void', - lambda state: state.has("Beat Supernova", player)) - connect(world, names, 'Zero Hour (Terran)', "Devil's Playground", - lambda state: wol_cleared_missions(state, 4) and state.has("Beat Zero Hour (Terran)", player)) - connect(world, names, "Devil's Playground", 'Welcome to the Jungle', - lambda state: state.has("Beat Devil's Playground", player)) - connect(world, names, "Welcome to the Jungle", 'Breakout', - lambda state: wol_cleared_missions(state, 8) and state.has("Beat Welcome to the Jungle", player)) - connect(world, names, "Welcome to the Jungle", 'Ghost of a Chance', - lambda state: wol_cleared_missions(state, 8) and state.has("Beat Welcome to the Jungle", player)) - connect(world, names, "Zero Hour (Terran)", 'The Great Train Robbery', - lambda state: wol_cleared_missions(state, 6) and state.has("Beat Zero Hour (Terran)", player)) - connect(world, names, 'The Great Train Robbery', 'Cutthroat', - lambda state: state.has("Beat The Great Train Robbery", player)) - connect(world, names, 'Cutthroat', 'Engine of Destruction', - lambda state: state.has("Beat Cutthroat", player)) - connect(world, names, 'Engine of Destruction', 'Media Blitz', - lambda state: state.has("Beat Engine of Destruction", player)) - connect(world, names, 'Media Blitz', 'Piercing the Shroud', - lambda state: state.has("Beat Media Blitz", player)) - connect(world, names, 'Maw of the Void', 'Gates of Hell', - lambda state: state.has("Beat Maw of the Void", player)) - connect(world, names, 'Gates of Hell', 'Belly of the Beast', - lambda state: state.has("Beat Gates of Hell", player)) - connect(world, names, 'Gates of Hell', 'Shatter the Sky', - lambda state: state.has("Beat Gates of Hell", player)) - connect(world, 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))) - - if SC2Campaign.PROPHECY in enabled_campaigns: - if SC2Campaign.WOL in enabled_campaigns: - connect(world, names, 'The Dig', 'Whispers of Doom', - lambda state: state.has("Beat The Dig", player)), - else: - vanilla_mission_reqs[SC2Campaign.PROPHECY] = vanilla_mission_reqs[SC2Campaign.PROPHECY].copy() - vanilla_mission_reqs[SC2Campaign.PROPHECY][SC2Mission.WHISPERS_OF_DOOM.mission_name] = MissionInfo( - SC2Mission.WHISPERS_OF_DOOM, [], SC2Mission.WHISPERS_OF_DOOM.area) - connect(world, names, 'Menu', 'Whispers of Doom'), - connect(world, names, 'Whispers of Doom', 'A Sinister Turn', - lambda state: state.has("Beat Whispers of Doom", player)) - connect(world, names, 'A Sinister Turn', 'Echoes of the Future', - lambda state: state.has("Beat A Sinister Turn", player)) - connect(world, names, 'Echoes of the Future', 'In Utter Darkness', - lambda state: state.has("Beat Echoes of the Future", player)) - - if SC2Campaign.HOTS in enabled_campaigns: - connect(world, names, 'Menu', 'Lab Rat'), - connect(world, names, 'Lab Rat', 'Back in the Saddle', - lambda state: state.has("Beat Lab Rat", player)), - connect(world, names, 'Back in the Saddle', 'Rendezvous', - lambda state: state.has("Beat Back in the Saddle", player)), - connect(world, names, 'Rendezvous', 'Harvest of Screams', - lambda state: state.has("Beat Rendezvous", player)), - connect(world, names, 'Harvest of Screams', 'Shoot the Messenger', - lambda state: state.has("Beat Harvest of Screams", player)), - connect(world, names, 'Shoot the Messenger', 'Enemy Within', - lambda state: state.has("Beat Shoot the Messenger", player)), - connect(world, names, 'Rendezvous', 'Domination', - lambda state: state.has("Beat Rendezvous", player)), - connect(world, names, 'Domination', 'Fire in the Sky', - lambda state: state.has("Beat Domination", player)), - connect(world, names, 'Fire in the Sky', 'Old Soldiers', - lambda state: state.has("Beat Fire in the Sky", player)), - connect(world, names, 'Old Soldiers', 'Waking the Ancient', - lambda state: state.has("Beat Old Soldiers", player)), - connect(world, names, 'Enemy Within', 'Waking the Ancient', - lambda state: state.has("Beat Enemy Within", player)), - connect(world, names, 'Waking the Ancient', 'The Crucible', - lambda state: state.has("Beat Waking the Ancient", player)), - connect(world, names, 'The Crucible', 'Supreme', - lambda state: state.has("Beat The Crucible", player)), - connect(world, names, 'Supreme', 'Infested', - lambda state: state.has("Beat Supreme", player) and - state.has("Beat Old Soldiers", player) and - state.has("Beat Enemy Within", player)), - connect(world, names, 'Infested', 'Hand of Darkness', - lambda state: state.has("Beat Infested", player)), - connect(world, names, 'Hand of Darkness', 'Phantoms of the Void', - lambda state: state.has("Beat Hand of Darkness", player)), - connect(world, names, 'Supreme', 'With Friends Like These', - lambda state: state.has("Beat Supreme", player) and - state.has("Beat Old Soldiers", player) and - state.has("Beat Enemy Within", player)), - connect(world, names, 'With Friends Like These', 'Conviction', - lambda state: state.has("Beat With Friends Like These", player)), - connect(world, names, 'Conviction', 'Planetfall', - lambda state: state.has("Beat Conviction", player) and - state.has("Beat Phantoms of the Void", player)), - connect(world, names, 'Planetfall', 'Death From Above', - lambda state: state.has("Beat Planetfall", player)), - connect(world, names, 'Death From Above', 'The Reckoning', - lambda state: state.has("Beat Death From Above", player)), - - if SC2Campaign.PROLOGUE in enabled_campaigns: - connect(world, names, "Menu", "Dark Whispers") - connect(world, names, "Dark Whispers", "Ghosts in the Fog", - lambda state: state.has("Beat Dark Whispers", player)) - connect(world, names, "Ghosts in the Fog", "Evil Awoken", - lambda state: state.has("Beat Ghosts in the Fog", player)) - - if SC2Campaign.LOTV in enabled_campaigns: - connect(world, names, "Menu", "For Aiur!") - connect(world, names, "For Aiur!", "The Growing Shadow", - lambda state: state.has("Beat For Aiur!", player)), - connect(world, names, "The Growing Shadow", "The Spear of Adun", - lambda state: state.has("Beat The Growing Shadow", player)), - connect(world, names, "The Spear of Adun", "Sky Shield", - lambda state: state.has("Beat The Spear of Adun", player)), - connect(world, names, "Sky Shield", "Brothers in Arms", - lambda state: state.has("Beat Sky Shield", player)), - connect(world, names, "Brothers in Arms", "Forbidden Weapon", - lambda state: state.has("Beat Brothers in Arms", player)), - connect(world, names, "The Spear of Adun", "Amon's Reach", - lambda state: state.has("Beat The Spear of Adun", player)), - connect(world, names, "Amon's Reach", "Last Stand", - lambda state: state.has("Beat Amon's Reach", player)), - connect(world, names, "Last Stand", "Forbidden Weapon", - lambda state: state.has("Beat Last Stand", player)), - connect(world, names, "Forbidden Weapon", "Temple of Unification", - lambda state: state.has("Beat Brothers in Arms", player) - and state.has("Beat Last Stand", player) - and state.has("Beat Forbidden Weapon", player)), - connect(world, names, "Temple of Unification", "The Infinite Cycle", - lambda state: state.has("Beat Temple of Unification", player)), - connect(world, names, "The Infinite Cycle", "Harbinger of Oblivion", - lambda state: state.has("Beat The Infinite Cycle", player)), - connect(world, names, "Harbinger of Oblivion", "Unsealing the Past", - lambda state: state.has("Beat Harbinger of Oblivion", player)), - connect(world, names, "Unsealing the Past", "Purification", - lambda state: state.has("Beat Unsealing the Past", player)), - connect(world, names, "Purification", "Templar's Charge", - lambda state: state.has("Beat Purification", player)), - connect(world, names, "Harbinger of Oblivion", "Steps of the Rite", - lambda state: state.has("Beat Harbinger of Oblivion", player)), - connect(world, names, "Steps of the Rite", "Rak'Shir", - lambda state: state.has("Beat Steps of the Rite", player)), - connect(world, names, "Rak'Shir", "Templar's Charge", - lambda state: state.has("Beat Rak'Shir", player)), - connect(world, names, "Templar's Charge", "Templar's Return", - lambda state: state.has("Beat Purification", player) - and state.has("Beat Rak'Shir", player) - and state.has("Beat Templar's Charge", player)), - connect(world, names, "Templar's Return", "The Host", - lambda state: state.has("Beat Templar's Return", player)), - connect(world, names, "The Host", "Salvation", - lambda state: state.has("Beat The Host", player)), - - if SC2Campaign.EPILOGUE in enabled_campaigns: - # TODO: Make this aware about excluded campaigns - connect(world, names, "Salvation", "Into the Void", - lambda state: state.has("Beat Salvation", player) - and state.has("Beat The Reckoning", player) - and state.has("Beat All-In", player)), - connect(world, names, "Into the Void", "The Essence of Eternity", - lambda state: state.has("Beat Into the Void", player)), - connect(world, names, "The Essence of Eternity", "Amon's Fall", - lambda state: state.has("Beat The Essence of Eternity", player)), - - if SC2Campaign.NCO in enabled_campaigns: - connect(world, names, "Menu", "The Escape") - connect(world, names, "The Escape", "Sudden Strike", - lambda state: state.has("Beat The Escape", player)) - connect(world, names, "Sudden Strike", "Enemy Intelligence", - lambda state: state.has("Beat Sudden Strike", player)) - connect(world, names, "Enemy Intelligence", "Trouble In Paradise", - lambda state: state.has("Beat Enemy Intelligence", player)) - connect(world, names, "Trouble In Paradise", "Night Terrors", - lambda state: state.has("Beat Trouble In Paradise", player)) - connect(world, names, "Night Terrors", "Flashpoint", - lambda state: state.has("Beat Night Terrors", player)) - connect(world, names, "Flashpoint", "In the Enemy's Shadow", - lambda state: state.has("Beat Flashpoint", player)) - connect(world, names, "In the Enemy's Shadow", "Dark Skies", - lambda state: state.has("Beat In the Enemy's Shadow", player)) - connect(world, names, "Dark Skies", "End Game", - lambda state: state.has("Beat Dark Skies", player)) - - goal_location = get_goal_location(final_mission) - assert goal_location, f"Unable to find a goal location for mission {final_mission}" - setup_final_location(goal_location, location_cache) - - return (vanilla_mission_reqs, final_mission.id, goal_location) - - -def create_grid_regions( - world: 'SC2World', - locations: Tuple[LocationData, ...], - location_cache: List[Location], -) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: - locations_per_region = get_locations_per_region(locations) - - mission_pools = filter_missions(world) - final_mission = mission_pools[MissionPools.FINAL][0] - - mission_pool = [mission for mission_pool in mission_pools.values() for mission in mission_pool] - - num_missions = min(len(mission_pool), get_option_value(world, "maximum_campaign_size")) - remove_top_left: bool = get_option_value(world, "grid_two_start_positions") == GridTwoStartPositions.option_true - - regions = [create_region(world, locations_per_region, location_cache, "Menu")] - names: Dict[str, int] = {} - missions: Dict[Tuple[int, int], SC2Mission] = {} - - grid_size_x, grid_size_y, num_corners_to_remove = get_grid_dimensions(num_missions + remove_top_left) - # pick missions in order along concentric diagonals - # each diagonal will have the same difficulty - # this keeps long sides from possibly stealing lower-difficulty missions from future columns - num_diagonals = grid_size_x + grid_size_y - 1 - diagonal_difficulty = MissionPools.STARTER - missions_to_add = mission_pools[MissionPools.STARTER] - for diagonal in range(num_diagonals): - if diagonal == num_diagonals - 1: - diagonal_difficulty = MissionPools.FINAL - grid_coords = (grid_size_x-1, grid_size_y-1) - missions[grid_coords] = final_mission - break - if diagonal == 0 and remove_top_left: - continue - diagonal_length = min(diagonal + 1, num_diagonals - diagonal, grid_size_x, grid_size_y) - if len(missions_to_add) < diagonal_length: - raise Exception(f"There are not enough {diagonal_difficulty.name} missions to fill the campaign. Please exclude fewer missions.") - for i in range(diagonal_length): - # (0,0) + (0,1)*diagonal + (1,-1)*i + (1,-1)*max(diagonal - grid_size_y + 1, 0) - grid_coords = (i + max(diagonal - grid_size_y + 1, 0), diagonal - i - max(diagonal - grid_size_y + 1, 0)) - if grid_coords == (grid_size_x - 1, 0) and num_corners_to_remove >= 2: - pass - elif grid_coords == (0, grid_size_y - 1) and num_corners_to_remove >= 1: - pass - else: - mission_index = world.random.randint(0, len(missions_to_add) - 1) - missions[grid_coords] = missions_to_add.pop(mission_index) - - if diagonal_difficulty < MissionPools.VERY_HARD: - diagonal_difficulty = MissionPools(diagonal_difficulty.value + 1) - missions_to_add.extend(mission_pools[diagonal_difficulty]) - - # Generating regions and locations from selected missions - for x in range(grid_size_x): - for y in range(grid_size_y): - if missions.get((x, y)): - regions.append(create_region(world, locations_per_region, location_cache, missions[(x, y)].mission_name)) - world.multiworld.regions += regions - - # This pattern is horrifying, why are we using the dict as an ordered dict??? - slot_map: Dict[Tuple[int, int], int] = {} - for index, coords in enumerate(missions): - slot_map[coords] = index + 1 - - mission_req_table: Dict[str, MissionInfo] = {} - for coords, mission in missions.items(): - prepend_vertical = 0 - if not mission: - continue - connections: List[MissionConnection] = [] - if coords == (0, 0) or (remove_top_left and sum(coords) == 1): - # Connect to the "Menu" starting region - connect(world, names, "Menu", mission.mission_name) - else: - for dx, dy in ((-1, 0), (1, 0), (0, -1), (0, 1)): - connected_coords = (coords[0] + dx, coords[1] + dy) - if connected_coords in missions: - # connections.append(missions[connected_coords]) - connections.append(MissionConnection(slot_map[connected_coords])) - connect(world, names, missions[connected_coords].mission_name, mission.mission_name, - make_grid_connect_rule(missions, connected_coords, world.player), - ) - if coords[1] == 1 and not missions.get((coords[0], 0)): - prepend_vertical = 1 - mission_req_table[mission.mission_name] = MissionInfo( - mission, - connections, - category=f'_{coords[0] + 1}', - or_requirements=True, - ui_vertical_padding=prepend_vertical, - ) - - final_mission_id = final_mission.id - # Changing the completion condition for alternate final missions into an event - final_location = get_goal_location(final_mission) - assert final_location, f"Unable to find a goal location for mission {final_mission}" - setup_final_location(final_location, location_cache) - - return {SC2Campaign.GLOBAL: mission_req_table}, final_mission_id, final_location - - -def make_grid_connect_rule( - missions: Dict[Tuple[int, int], SC2Mission], - connected_coords: Tuple[int, int], - player: int -) -> Callable[[CollectionState], bool]: - return lambda state: state.has(f"Beat {missions[connected_coords].mission_name}", player) - - -def make_dynamic_mission_order( - world: 'SC2World', - mission_order_type: int -) -> Dict[SC2Campaign, List[FillMission]]: - mission_pools = filter_missions(world) - - mission_pool = [mission for mission_pool in mission_pools.values() for mission in mission_pool] - - num_missions = min(len(mission_pool), get_option_value(world, "maximum_campaign_size")) - num_missions = max(2, num_missions) - if mission_order_type == MissionOrder.option_golden_path: - return make_golden_path(world, num_missions) - # Grid handled by dedicated region generator - elif mission_order_type == MissionOrder.option_gauntlet: - return make_gauntlet(num_missions) - elif mission_order_type == MissionOrder.option_blitz: - return make_blitz(num_missions) - elif mission_order_type == MissionOrder.option_hopscotch: - return make_hopscotch(world.options.grid_two_start_positions, num_missions) - - -def create_structured_regions( - world: 'SC2World', - locations: Tuple[LocationData, ...], - location_cache: List[Location], - mission_order_type: MissionOrder, -) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: - locations_per_region = get_locations_per_region(locations) - - if mission_order_type in static_mission_orders: - mission_order = static_mission_orders[mission_order_type]() - else: - mission_order = make_dynamic_mission_order(world, mission_order_type) - enabled_campaigns = get_enabled_campaigns(world) - shuffle_campaigns = get_option_value(world, "shuffle_campaigns") - - mission_pools: Dict[MissionPools, List[SC2Mission]] = filter_missions(world) - final_mission = mission_pools[MissionPools.FINAL][0] - - regions = [create_region(world, locations_per_region, location_cache, "Menu")] - - names: Dict[str, int] = {} - - mission_slots: List[SC2MissionSlot] = [] - mission_pool = [mission for mission_pool in mission_pools.values() for mission in mission_pool] - - if mission_order_type in campaign_depending_orders: - # Do slot removal per campaign - for campaign in enabled_campaigns: - campaign_mission_pool = [mission for mission in mission_pool if mission.campaign == campaign] - campaign_mission_pool_size = len(campaign_mission_pool) - - removals = len(mission_order[campaign]) - campaign_mission_pool_size - - for fill_mission in mission_order[campaign]: - # Removing extra missions if mission pool is too small - if 0 < fill_mission.removal_priority <= removals: - mission_slots.append(SC2MissionSlot(campaign, None)) - elif fill_mission.type == MissionPools.FINAL: - if campaign == final_mission.campaign: - # Campaign is elected to be goal - mission_slots.append(SC2MissionSlot(campaign, final_mission)) - else: - # Not the goal, find the most difficult mission in the pool and set the difficulty - campaign_difficulty = max(fill_mission.pool for fill_mission in campaign_mission_pool) - mission_slots.append(SC2MissionSlot(campaign, campaign_difficulty)) - else: - mission_slots.append(SC2MissionSlot(campaign, fill_mission.type)) - else: - order = mission_order[SC2Campaign.GLOBAL] - # Determining if missions must be removed - mission_pool_size = sum(len(mission_pool) for mission_pool in mission_pools.values()) - removals = len(order) - mission_pool_size - - # Initial fill out of mission list and marking All-In mission - for fill_mission in order: - # Removing extra missions if mission pool is too small - if 0 < fill_mission.removal_priority <= removals: - mission_slots.append(SC2MissionSlot(SC2Campaign.GLOBAL, None)) - elif fill_mission.type == MissionPools.FINAL: - mission_slots.append(SC2MissionSlot(SC2Campaign.GLOBAL, final_mission)) - else: - mission_slots.append(SC2MissionSlot(SC2Campaign.GLOBAL, fill_mission.type)) - - no_build_slots = [] - easy_slots = [] - medium_slots = [] - hard_slots = [] - very_hard_slots = [] - - # Search through missions to find slots needed to fill - for i in range(len(mission_slots)): - mission_slot = mission_slots[i] - if mission_slot is None: - continue - if isinstance(mission_slot, SC2MissionSlot): - if mission_slot.slot is None: - continue - if mission_slot.slot == MissionPools.STARTER: - no_build_slots.append(i) - elif mission_slot.slot == MissionPools.EASY: - easy_slots.append(i) - elif mission_slot.slot == MissionPools.MEDIUM: - medium_slots.append(i) - elif mission_slot.slot == MissionPools.HARD: - hard_slots.append(i) - elif mission_slot.slot == MissionPools.VERY_HARD: - very_hard_slots.append(i) - - def pick_mission(slot): - if shuffle_campaigns or mission_order_type not in campaign_depending_orders: - # Pick a mission from any campaign - filler = world.random.randint(0, len(missions_to_add) - 1) - mission = missions_to_add.pop(filler) - slot_campaign = mission_slots[slot].campaign - mission_slots[slot] = SC2MissionSlot(slot_campaign, mission) - else: - # Pick a mission from required campaign - slot_campaign = mission_slots[slot].campaign - campaign_mission_candidates = [mission for mission in missions_to_add if mission.campaign == slot_campaign] - mission = world.random.choice(campaign_mission_candidates) - missions_to_add.remove(mission) - mission_slots[slot] = SC2MissionSlot(slot_campaign, mission) - - # Add no_build missions to the pool and fill in no_build slots - missions_to_add: List[SC2Mission] = mission_pools[MissionPools.STARTER] - if len(no_build_slots) > len(missions_to_add): - raise Exception("There are no valid No-Build missions. Please exclude fewer missions.") - for slot in no_build_slots: - pick_mission(slot) - - # Add easy missions into pool and fill in easy slots - missions_to_add = missions_to_add + mission_pools[MissionPools.EASY] - if len(easy_slots) > len(missions_to_add): - raise Exception("There are not enough Easy missions to fill the campaign. Please exclude fewer missions.") - for slot in easy_slots: - pick_mission(slot) - - # Add medium missions into pool and fill in medium slots - missions_to_add = missions_to_add + mission_pools[MissionPools.MEDIUM] - if len(medium_slots) > len(missions_to_add): - raise Exception("There are not enough Easy and Medium missions to fill the campaign. Please exclude fewer missions.") - for slot in medium_slots: - pick_mission(slot) - - # Add hard missions into pool and fill in hard slots - missions_to_add = missions_to_add + mission_pools[MissionPools.HARD] - if len(hard_slots) > len(missions_to_add): - raise Exception("There are not enough missions to fill the campaign. Please exclude fewer missions.") - for slot in hard_slots: - pick_mission(slot) - - # Add very hard missions into pool and fill in very hard slots - missions_to_add = missions_to_add + mission_pools[MissionPools.VERY_HARD] - if len(very_hard_slots) > len(missions_to_add): - raise Exception("There are not enough missions to fill the campaign. Please exclude fewer missions.") - for slot in very_hard_slots: - pick_mission(slot) - - # Generating regions and locations from selected missions - for mission_slot in mission_slots: - if isinstance(mission_slot.slot, SC2Mission): - regions.append(create_region(world, locations_per_region, location_cache, mission_slot.slot.mission_name)) - world.multiworld.regions += regions - - campaigns: List[SC2Campaign] - if mission_order_type in campaign_depending_orders: - campaigns = list(enabled_campaigns) - else: - campaigns = [SC2Campaign.GLOBAL] - - mission_req_table: Dict[SC2Campaign, Dict[str, MissionInfo]] = {} - campaign_mission_slots: Dict[SC2Campaign, List[SC2MissionSlot]] = \ - { - campaign: [mission_slot for mission_slot in mission_slots if campaign == mission_slot.campaign] - for campaign in campaigns - } - - slot_map: Dict[SC2Campaign, List[int]] = dict() - - for campaign in campaigns: - mission_req_table.update({campaign: dict()}) - - # Mapping original mission slots to shifted mission slots when missions are removed - slot_map[campaign] = [] - slot_offset = 0 - for position, mission in enumerate(campaign_mission_slots[campaign]): - slot_map[campaign].append(position - slot_offset + 1) - if mission is None or mission.slot is None: - slot_offset += 1 - - def build_connection_rule(mission_names: List[str], missions_req: int) -> Callable: - player = world.player - if len(mission_names) > 1: - return lambda state: state.has_all({f"Beat {name}" for name in mission_names}, player) \ - and state.has_group("Missions", player, missions_req) - else: - return lambda state: state.has(f"Beat {mission_names[0]}", player) \ - and state.has_group("Missions", player, missions_req) - - for campaign in campaigns: - # Loop through missions to create requirements table and connect regions - for i, mission in enumerate(campaign_mission_slots[campaign]): - if mission is None or mission.slot is None: - continue - connections: List[MissionConnection] = [] - all_connections: List[SC2MissionSlot] = [] - connection: MissionConnection - for connection in mission_order[campaign][i].connect_to: - if connection.connect_to == -1: - continue - # If mission normally connects to an excluded campaign, connect to menu instead - if connection.campaign not in campaign_mission_slots: - connection.connect_to = -1 - continue - while campaign_mission_slots[connection.campaign][connection.connect_to].slot is None: - connection.connect_to -= 1 - all_connections.append(campaign_mission_slots[connection.campaign][connection.connect_to]) - for connection in mission_order[campaign][i].connect_to: - if connection.connect_to == -1: - connect(world, names, "Menu", mission.slot.mission_name) - else: - required_mission = campaign_mission_slots[connection.campaign][connection.connect_to] - if ((required_mission is None or required_mission.slot is None) - and not mission_order[campaign][i].completion_critical): # Drop non-critical null slots - continue - while required_mission is None or required_mission.slot is None: # Substituting null slot with prior slot - connection.connect_to -= 1 - required_mission = campaign_mission_slots[connection.campaign][connection.connect_to] - required_missions = [required_mission] if mission_order[campaign][i].or_requirements else all_connections - if isinstance(required_mission.slot, SC2Mission): - required_mission_name = required_mission.slot.mission_name - required_missions_names = [mission.slot.mission_name for mission in required_missions] - connect(world, names, required_mission_name, mission.slot.mission_name, - build_connection_rule(required_missions_names, mission_order[campaign][i].number)) - connections.append(MissionConnection(slot_map[connection.campaign][connection.connect_to], connection.campaign)) - - mission_req_table[campaign].update({mission.slot.mission_name: MissionInfo( - mission.slot, connections, mission_order[campaign][i].category, - number=mission_order[campaign][i].number, - completion_critical=mission_order[campaign][i].completion_critical, - or_requirements=mission_order[campaign][i].or_requirements, - ui_vertical_padding=mission_order[campaign][i].ui_vertical_padding), - }) - - final_mission_id = final_mission.id - # Changing the completion condition for alternate final missions into an event - final_location = get_goal_location(final_mission) - assert final_location, f"Unable to find a goal location for mission {final_mission}" - setup_final_location(final_location, location_cache) - - return mission_req_table, final_mission_id, final_location - - -def setup_final_location(final_location, location_cache): - # Final location should be near the end of the cache - for i in range(len(location_cache) - 1, -1, -1): - if location_cache[i].name == final_location: - location_cache[i].address = None - break - - -def create_location(player: int, location_data: LocationData, region: Region, - location_cache: List[Location]) -> Location: - location = Location(player, location_data.name, location_data.code, region) - location.access_rule = location_data.rule - - location_cache.append(location) - - return location - - -def create_region(world: 'SC2World', locations_per_region: Dict[str, List[LocationData]], - location_cache: List[Location], name: str) -> Region: - region = Region(name, world.player, world.multiworld) - - if name in locations_per_region: - for location_data in locations_per_region[name]: - location = create_location(world.player, location_data, region, location_cache) - region.locations.append(location) - - return region - - -def connect(world: 'SC2World', used_names: Dict[str, int], source: str, target: str, - rule: Optional[Callable] = None): - source_region = world.get_region(source) - target_region = world.get_region(target) - - if target not in used_names: - used_names[target] = 1 - name = target - else: - used_names[target] += 1 - name = target + (' ' * used_names[target]) - - connection = Entrance(world.player, name, source_region) - - if rule: - connection.access_rule = rule - - source_region.exits.append(connection) - connection.connect(target_region) - - -def get_locations_per_region(locations: Tuple[LocationData, ...]) -> Dict[str, List[LocationData]]: - per_region: Dict[str, List[LocationData]] = {} - - for location in locations: - per_region.setdefault(location.region, []).append(location) - - return per_region - - -def get_factors(number: int) -> Tuple[int, int]: - """ - Simple factorization into pairs of numbers (x, y) using a sieve method. - Returns the factorization that is most square, i.e. where x + y is minimized. - Factor order is such that x <= y. - """ - assert number > 0 - for divisor in range(math.floor(math.sqrt(number)), 1, -1): - quotient = number // divisor - if quotient * divisor == number: - return divisor, quotient - return 1, number - - -def get_grid_dimensions(size: int) -> Tuple[int, int, int]: - """ - Get the dimensions of a grid mission order from the number of missions, int the format (x, y, error). - * Error will always be 0, 1, or 2, so the missions can be removed from the corners that aren't the start or end. - * Dimensions are chosen such that x <= y, as buttons in the UI are wider than they are tall. - * Dimensions are chosen to be maximally square. That is, x + y + error is minimized. - * If multiple options of the same rating are possible, the one with the larger error is chosen, - as it will appear more square. Compare 3x11 to 5x7-2 for an example of this. - """ - dimension_candidates: List[Tuple[int, int, int]] = [(*get_factors(size + x), x) for x in (2, 1, 0)] - best_dimension = min(dimension_candidates, key=sum) - return best_dimension - +from typing import List, Dict, Tuple, Optional, Callable, NamedTuple, Union, TYPE_CHECKING +import math + +from BaseClasses import Region, Entrance, Location, CollectionState +from .locations import LocationData +from .options import get_option_value, MissionOrder, get_enabled_campaigns, campaign_depending_orders, \ + GridTwoStartPositions, static_mission_orders, dynamic_mission_orders +from .mission_tables import MissionInfo, vanilla_mission_req_table, \ + MissionPools, SC2Campaign, get_goal_location, SC2Mission, MissionConnection, FillMission +from .mission_orders import make_gauntlet, make_blitz, make_golden_path, make_hopscotch +from .pool_filter import filter_missions + + +if TYPE_CHECKING: + from . import SC2World + + +class SC2MissionSlot(NamedTuple): + campaign: SC2Campaign + slot: Union[MissionPools, SC2Mission, None] + + +def create_regions( + world: 'SC2World', locations: Tuple[LocationData, ...], location_cache: List[Location] +) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: + """ + Creates region connections by calling the multiworld's `connect()` methods + Returns a 3-tuple containing: + * dict[SC2Campaign, Dict[str, MissionInfo]] mapping a campaign and mission name to its data + * int The number of missions in the world + * str The name of the goal location + """ + mission_order_type: MissionOrder = world.options.mission_order + + if mission_order_type == MissionOrder.option_vanilla: + return create_vanilla_regions(world, locations, location_cache) + elif mission_order_type == MissionOrder.option_grid: + return create_grid_regions(world, locations, location_cache) + else: + return create_structured_regions(world, locations, location_cache, mission_order_type) + +def create_vanilla_regions( + world: 'SC2World', + locations: Tuple[LocationData, ...], + location_cache: List[Location], +) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: + locations_per_region = get_locations_per_region(locations) + regions = [create_region(world, locations_per_region, location_cache, "Menu")] + + mission_pools: Dict[MissionPools, List[SC2Mission]] = filter_missions(world) + final_mission = mission_pools[MissionPools.FINAL][0] + + enabled_campaigns = get_enabled_campaigns(world) + names: Dict[str, int] = {} + + # Generating all regions and locations for each enabled campaign + for campaign in enabled_campaigns: + for region_name in vanilla_mission_req_table[campaign].keys(): + regions.append(create_region(world, locations_per_region, location_cache, region_name)) + world.multiworld.regions += regions + vanilla_mission_reqs = {campaign: missions for campaign, missions in vanilla_mission_req_table.items() if campaign in enabled_campaigns} + + def wol_cleared_missions(state: CollectionState, mission_count: int) -> bool: + return state.has_group("WoL Missions", world.player, mission_count) + + player: int = world.player + if SC2Campaign.WOL in enabled_campaigns: + connect(world, names, 'Menu', SC2Mission.LIBERATION_DAY.mission_name) + connect(world, names, SC2Mission.LIBERATION_DAY.mission_name, SC2Mission.THE_OUTLAWS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.LIBERATION_DAY.mission_name}", player)) + connect(world, names, SC2Mission.THE_OUTLAWS.mission_name, SC2Mission.ZERO_HOUR.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_OUTLAWS.mission_name}", player)) + connect(world, names, SC2Mission.ZERO_HOUR.mission_name, SC2Mission.EVACUATION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.ZERO_HOUR.mission_name}", player)) + connect(world, names, SC2Mission.EVACUATION.mission_name, SC2Mission.OUTBREAK.mission_name, + lambda state: state.has(f"Beat {SC2Mission.EVACUATION.mission_name}", player)) + connect(world, names, SC2Mission.OUTBREAK.mission_name, SC2Mission.SAFE_HAVEN.mission_name, + lambda state: wol_cleared_missions(state, 7) and state.has(f"Beat {SC2Mission.OUTBREAK.mission_name}", player)) + connect(world, names, SC2Mission.OUTBREAK.mission_name, SC2Mission.HAVENS_FALL.mission_name, + lambda state: wol_cleared_missions(state, 7) and state.has(f"Beat {SC2Mission.OUTBREAK.mission_name}", player)) + connect(world, names, SC2Mission.ZERO_HOUR.mission_name, SC2Mission.SMASH_AND_GRAB.mission_name, + lambda state: state.has(f"Beat {SC2Mission.ZERO_HOUR.mission_name}", player)) + connect(world, names, SC2Mission.SMASH_AND_GRAB.mission_name, SC2Mission.THE_DIG.mission_name, + lambda state: wol_cleared_missions(state, 8) and state.has(f"Beat {SC2Mission.SMASH_AND_GRAB.mission_name}", player)) + connect(world, names, SC2Mission.THE_DIG.mission_name, SC2Mission.THE_MOEBIUS_FACTOR.mission_name, + lambda state: wol_cleared_missions(state, 11) and state.has(f"Beat {SC2Mission.THE_DIG.mission_name}", player)) + connect(world, names, SC2Mission.THE_MOEBIUS_FACTOR.mission_name, SC2Mission.SUPERNOVA.mission_name, + lambda state: wol_cleared_missions(state, 14) and state.has(f"Beat {SC2Mission.THE_MOEBIUS_FACTOR.mission_name}", player)) + connect(world, names, SC2Mission.SUPERNOVA.mission_name, SC2Mission.MAW_OF_THE_VOID.mission_name, + lambda state: state.has(f"Beat {SC2Mission.SUPERNOVA.mission_name}", player)) + connect(world, names, SC2Mission.ZERO_HOUR.mission_name, SC2Mission.DEVILS_PLAYGROUND.mission_name, + lambda state: wol_cleared_missions(state, 4) and state.has(f"Beat {SC2Mission.ZERO_HOUR.mission_name}", player)) + connect(world, names, SC2Mission.DEVILS_PLAYGROUND.mission_name, SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.DEVILS_PLAYGROUND.mission_name}", player)) + connect(world, names, SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, SC2Mission.BREAKOUT.mission_name, + lambda state: wol_cleared_missions(state, 8) and state.has(f"Beat {SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name}", player)) + connect(world, names, SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, SC2Mission.GHOST_OF_A_CHANCE.mission_name, + lambda state: wol_cleared_missions(state, 8) and state.has(f"Beat {SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name}", player)) + connect(world, names, SC2Mission.ZERO_HOUR.mission_name, SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, + lambda state: wol_cleared_missions(state, 6) and state.has(f"Beat {SC2Mission.ZERO_HOUR.mission_name}", player)) + connect(world, names, SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, SC2Mission.CUTTHROAT.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name}", player)) + connect(world, names, SC2Mission.CUTTHROAT.mission_name, SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.CUTTHROAT.mission_name}", player)) + connect(world, names, SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, SC2Mission.MEDIA_BLITZ.mission_name, + lambda state: state.has(f"Beat {SC2Mission.ENGINE_OF_DESTRUCTION.mission_name}", player)) + connect(world, names, SC2Mission.MEDIA_BLITZ.mission_name, SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, + lambda state: state.has(f"Beat {SC2Mission.MEDIA_BLITZ.mission_name}", player)) + connect(world, names, SC2Mission.MAW_OF_THE_VOID.mission_name, SC2Mission.GATES_OF_HELL.mission_name, + lambda state: state.has(f"Beat {SC2Mission.MAW_OF_THE_VOID.mission_name}", player)) + connect(world, names, SC2Mission.GATES_OF_HELL.mission_name, SC2Mission.BELLY_OF_THE_BEAST.mission_name, + lambda state: state.has(f"Beat {SC2Mission.GATES_OF_HELL.mission_name}", player)) + connect(world, names, SC2Mission.GATES_OF_HELL.mission_name, SC2Mission.SHATTER_THE_SKY.mission_name, + lambda state: state.has(f"Beat {SC2Mission.GATES_OF_HELL.mission_name}", player)) + connect(world, names, SC2Mission.GATES_OF_HELL.mission_name, SC2Mission.ALL_IN.mission_name, + 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))) + + if SC2Campaign.PROPHECY in enabled_campaigns: + if SC2Campaign.WOL in enabled_campaigns: + connect(world, names, SC2Mission.THE_DIG.mission_name, SC2Mission.WHISPERS_OF_DOOM.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_DIG.mission_name}", player)), + else: + vanilla_mission_reqs[SC2Campaign.PROPHECY] = vanilla_mission_reqs[SC2Campaign.PROPHECY].copy() + vanilla_mission_reqs[SC2Campaign.PROPHECY][SC2Mission.WHISPERS_OF_DOOM.mission_name] = MissionInfo( + SC2Mission.WHISPERS_OF_DOOM, [], SC2Mission.WHISPERS_OF_DOOM.area) + connect(world, names, 'Menu', SC2Mission.WHISPERS_OF_DOOM.mission_name), + connect(world, names, SC2Mission.WHISPERS_OF_DOOM.mission_name, SC2Mission.A_SINISTER_TURN.mission_name, + lambda state: state.has(f"Beat {SC2Mission.WHISPERS_OF_DOOM.mission_name}", player)) + connect(world, names, SC2Mission.A_SINISTER_TURN.mission_name, SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.A_SINISTER_TURN.mission_name}", player)) + connect(world, names, SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, SC2Mission.IN_UTTER_DARKNESS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.ECHOES_OF_THE_FUTURE.mission_name}", player)) + + if SC2Campaign.HOTS in enabled_campaigns: + connect(world, names, 'Menu', SC2Mission.LAB_RAT.mission_name), + connect(world, names, SC2Mission.LAB_RAT.mission_name, SC2Mission.BACK_IN_THE_SADDLE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.LAB_RAT.mission_name}", player)), + connect(world, names, SC2Mission.BACK_IN_THE_SADDLE.mission_name, SC2Mission.RENDEZVOUS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.BACK_IN_THE_SADDLE.mission_name}", player)), + connect(world, names, SC2Mission.RENDEZVOUS.mission_name, SC2Mission.HARVEST_OF_SCREAMS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.RENDEZVOUS.mission_name}", player)), + connect(world, names, SC2Mission.HARVEST_OF_SCREAMS.mission_name, SC2Mission.SHOOT_THE_MESSENGER.mission_name, + lambda state: state.has(f"Beat {SC2Mission.HARVEST_OF_SCREAMS.mission_name}", player)), + connect(world, names, SC2Mission.SHOOT_THE_MESSENGER.mission_name, SC2Mission.ENEMY_WITHIN.mission_name, + lambda state: state.has(f"Beat {SC2Mission.SHOOT_THE_MESSENGER.mission_name}", player)), + connect(world, names, SC2Mission.RENDEZVOUS.mission_name, SC2Mission.DOMINATION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.RENDEZVOUS.mission_name}", player)), + connect(world, names, SC2Mission.DOMINATION.mission_name, SC2Mission.FIRE_IN_THE_SKY.mission_name, + lambda state: state.has(f"Beat {SC2Mission.DOMINATION.mission_name}", player)), + connect(world, names, SC2Mission.FIRE_IN_THE_SKY.mission_name, SC2Mission.OLD_SOLDIERS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.FIRE_IN_THE_SKY.mission_name}", player)), + connect(world, names, SC2Mission.OLD_SOLDIERS.mission_name, SC2Mission.WAKING_THE_ANCIENT.mission_name, + lambda state: state.has(f"Beat {SC2Mission.OLD_SOLDIERS.mission_name}", player)), + connect(world, names, SC2Mission.ENEMY_WITHIN.mission_name, SC2Mission.WAKING_THE_ANCIENT.mission_name, + lambda state: state.has(f"Beat {SC2Mission.ENEMY_WITHIN.mission_name}", player)), + connect(world, names, SC2Mission.WAKING_THE_ANCIENT.mission_name, SC2Mission.THE_CRUCIBLE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.WAKING_THE_ANCIENT.mission_name}", player)), + connect(world, names, SC2Mission.THE_CRUCIBLE.mission_name, SC2Mission.SUPREME.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_CRUCIBLE.mission_name}", player)), + connect(world, names, SC2Mission.SUPREME.mission_name, SC2Mission.INFESTED.mission_name, + lambda state: state.has(f"Beat {SC2Mission.SUPREME.mission_name}", player) and + state.has(f"Beat {SC2Mission.OLD_SOLDIERS.mission_name}", player) and + state.has(f"Beat {SC2Mission.ENEMY_WITHIN.mission_name}", player)), + connect(world, names, SC2Mission.INFESTED.mission_name, SC2Mission.HAND_OF_DARKNESS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.INFESTED.mission_name}", player)), + connect(world, names, SC2Mission.HAND_OF_DARKNESS.mission_name, SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, + lambda state: state.has(f"Beat {SC2Mission.HAND_OF_DARKNESS.mission_name}", player)), + connect(world, names, SC2Mission.SUPREME.mission_name, SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.SUPREME.mission_name}", player) and + state.has(f"Beat {SC2Mission.OLD_SOLDIERS.mission_name}", player) and + state.has(f"Beat {SC2Mission.ENEMY_WITHIN.mission_name}", player)), + connect(world, names, SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, SC2Mission.CONVICTION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name}", player)), + connect(world, names, SC2Mission.CONVICTION.mission_name, SC2Mission.PLANETFALL.mission_name, + lambda state: state.has(f"Beat {SC2Mission.CONVICTION.mission_name}", player) and + state.has(f"Beat {SC2Mission.PHANTOMS_OF_THE_VOID.mission_name}", player)), + connect(world, names, SC2Mission.PLANETFALL.mission_name, SC2Mission.DEATH_FROM_ABOVE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.PLANETFALL.mission_name}", player)), + connect(world, names, SC2Mission.DEATH_FROM_ABOVE.mission_name, SC2Mission.THE_RECKONING.mission_name, + lambda state: state.has(f"Beat {SC2Mission.DEATH_FROM_ABOVE.mission_name}", player)), + + if SC2Campaign.PROLOGUE in enabled_campaigns: + connect(world, names, "Menu", SC2Mission.DARK_WHISPERS.mission_name) + connect(world, names, SC2Mission.DARK_WHISPERS.mission_name, SC2Mission.GHOSTS_IN_THE_FOG.mission_name, + lambda state: state.has(f"Beat {SC2Mission.DARK_WHISPERS.mission_name}", player)) + connect(world, names, SC2Mission.GHOSTS_IN_THE_FOG.mission_name, SC2Mission.EVIL_AWOKEN.mission_name, + lambda state: state.has(f"Beat {SC2Mission.GHOSTS_IN_THE_FOG.mission_name}", player)) + + if SC2Campaign.LOTV in enabled_campaigns: + connect(world, names, "Menu", SC2Mission.FOR_AIUR.mission_name) + connect(world, names, SC2Mission.FOR_AIUR.mission_name, SC2Mission.THE_GROWING_SHADOW.mission_name, + lambda state: state.has(f"Beat {SC2Mission.FOR_AIUR.mission_name}", player)), + connect(world, names, SC2Mission.THE_GROWING_SHADOW.mission_name, SC2Mission.THE_SPEAR_OF_ADUN.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_GROWING_SHADOW.mission_name}", player)), + connect(world, names, SC2Mission.THE_SPEAR_OF_ADUN.mission_name, SC2Mission.SKY_SHIELD.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_SPEAR_OF_ADUN.mission_name}", player)), + connect(world, names, SC2Mission.SKY_SHIELD.mission_name, SC2Mission.BROTHERS_IN_ARMS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.SKY_SHIELD.mission_name}", player)), + connect(world, names, SC2Mission.BROTHERS_IN_ARMS.mission_name, SC2Mission.FORBIDDEN_WEAPON.mission_name, + lambda state: state.has(f"Beat {SC2Mission.BROTHERS_IN_ARMS.mission_name}", player)), + connect(world, names, SC2Mission.THE_SPEAR_OF_ADUN.mission_name, SC2Mission.AMON_S_REACH.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_SPEAR_OF_ADUN.mission_name}", player)), + connect(world, names, SC2Mission.AMON_S_REACH.mission_name, SC2Mission.LAST_STAND.mission_name, + lambda state: state.has(f"Beat {SC2Mission.AMON_S_REACH.mission_name}", player)), + connect(world, names, SC2Mission.LAST_STAND.mission_name, SC2Mission.FORBIDDEN_WEAPON.mission_name, + lambda state: state.has(f"Beat {SC2Mission.LAST_STAND.mission_name}", player)), + connect(world, names, SC2Mission.FORBIDDEN_WEAPON.mission_name, SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.BROTHERS_IN_ARMS.mission_name}", player) + and state.has(f"Beat {SC2Mission.LAST_STAND.mission_name}", player) + and state.has(f"Beat {SC2Mission.FORBIDDEN_WEAPON.mission_name}", player)), + connect(world, names, SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, SC2Mission.THE_INFINITE_CYCLE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.TEMPLE_OF_UNIFICATION.mission_name}", player)), + connect(world, names, SC2Mission.THE_INFINITE_CYCLE.mission_name, SC2Mission.HARBINGER_OF_OBLIVION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_INFINITE_CYCLE.mission_name}", player)), + connect(world, names, SC2Mission.HARBINGER_OF_OBLIVION.mission_name, SC2Mission.UNSEALING_THE_PAST.mission_name, + lambda state: state.has(f"Beat {SC2Mission.HARBINGER_OF_OBLIVION.mission_name}", player)), + connect(world, names, SC2Mission.UNSEALING_THE_PAST.mission_name, SC2Mission.PURIFICATION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.UNSEALING_THE_PAST.mission_name}", player)), + connect(world, names, SC2Mission.PURIFICATION.mission_name, SC2Mission.TEMPLAR_S_CHARGE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.PURIFICATION.mission_name}", player)), + connect(world, names, SC2Mission.HARBINGER_OF_OBLIVION.mission_name, SC2Mission.STEPS_OF_THE_RITE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.HARBINGER_OF_OBLIVION.mission_name}", player)), + connect(world, names, SC2Mission.STEPS_OF_THE_RITE.mission_name, SC2Mission.RAK_SHIR.mission_name, + lambda state: state.has(f"Beat {SC2Mission.STEPS_OF_THE_RITE.mission_name}", player)), + connect(world, names, SC2Mission.RAK_SHIR.mission_name, SC2Mission.TEMPLAR_S_CHARGE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.RAK_SHIR.mission_name}", player)), + connect(world, names, SC2Mission.TEMPLAR_S_CHARGE.mission_name, SC2Mission.TEMPLAR_S_RETURN.mission_name, + lambda state: state.has(f"Beat {SC2Mission.PURIFICATION.mission_name}", player) + and state.has(f"Beat {SC2Mission.RAK_SHIR.mission_name}", player) + and state.has(f"Beat {SC2Mission.TEMPLAR_S_CHARGE.mission_name}", player)), + connect(world, names, SC2Mission.TEMPLAR_S_RETURN.mission_name, SC2Mission.THE_HOST.mission_name, + lambda state: state.has(f"Beat {SC2Mission.TEMPLAR_S_RETURN.mission_name}", player)), + connect(world, names, SC2Mission.THE_HOST.mission_name, SC2Mission.SALVATION.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_HOST.mission_name}", player)), + + if SC2Campaign.EPILOGUE in enabled_campaigns: + # TODO: Make this aware about excluded campaigns + connect(world, names, SC2Mission.SALVATION.mission_name, SC2Mission.INTO_THE_VOID.mission_name, + lambda state: state.has(f"Beat {SC2Mission.SALVATION.mission_name}", player) + and state.has(f"Beat {SC2Mission.THE_RECKONING.mission_name}", player) + and state.has(f"Beat {SC2Mission.ALL_IN.mission_name}", player)), + connect(world, names, SC2Mission.INTO_THE_VOID.mission_name, SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, + lambda state: state.has(f"Beat {SC2Mission.INTO_THE_VOID.mission_name}", player)), + connect(world, names, SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, SC2Mission.AMON_S_FALL.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name}", player)), + + if SC2Campaign.NCO in enabled_campaigns: + connect(world, names, "Menu", SC2Mission.THE_ESCAPE.mission_name) + connect(world, names, SC2Mission.THE_ESCAPE.mission_name, SC2Mission.SUDDEN_STRIKE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.THE_ESCAPE.mission_name}", player)) + connect(world, names, SC2Mission.SUDDEN_STRIKE.mission_name, SC2Mission.ENEMY_INTELLIGENCE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.SUDDEN_STRIKE.mission_name}", player)) + connect(world, names, SC2Mission.ENEMY_INTELLIGENCE.mission_name, SC2Mission.TROUBLE_IN_PARADISE.mission_name, + lambda state: state.has(f"Beat {SC2Mission.ENEMY_INTELLIGENCE.mission_name}", player)) + connect(world, names, SC2Mission.TROUBLE_IN_PARADISE.mission_name, SC2Mission.NIGHT_TERRORS.mission_name, + lambda state: state.has(f"Beat {SC2Mission.TROUBLE_IN_PARADISE.mission_name}", player)) + connect(world, names, SC2Mission.NIGHT_TERRORS.mission_name, SC2Mission.FLASHPOINT.mission_name, + lambda state: state.has(f"Beat {SC2Mission.NIGHT_TERRORS.mission_name}", player)) + connect(world, names, SC2Mission.FLASHPOINT.mission_name, SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, + lambda state: state.has(f"Beat {SC2Mission.FLASHPOINT.mission_name}", player)) + connect(world, names, SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, SC2Mission.DARK_SKIES.mission_name, + lambda state: state.has(f"Beat {SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name}", player)) + connect(world, names, SC2Mission.DARK_SKIES.mission_name, SC2Mission.END_GAME.mission_name, + lambda state: state.has(f"Beat {SC2Mission.DARK_SKIES.mission_name}", player)) + + goal_location = get_goal_location(final_mission) + assert goal_location, f"Unable to find a goal location for mission {final_mission}" + setup_final_location(goal_location, location_cache) + + return (vanilla_mission_reqs, final_mission.id, goal_location) + + +def create_grid_regions( + world: 'SC2World', + locations: Tuple[LocationData, ...], + location_cache: List[Location], +) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: + locations_per_region = get_locations_per_region(locations) + + mission_pools = filter_missions(world) + final_mission = mission_pools[MissionPools.FINAL][0] + + mission_pool = [mission for mission_pool in mission_pools.values() for mission in mission_pool] + + num_missions = min(len(mission_pool), get_option_value(world, "maximum_campaign_size")) + remove_top_left: bool = get_option_value(world, "grid_two_start_positions") == GridTwoStartPositions.option_true + + regions = [create_region(world, locations_per_region, location_cache, "Menu")] + names: Dict[str, int] = {} + missions: Dict[Tuple[int, int], SC2Mission] = {} + + grid_size_x, grid_size_y, num_corners_to_remove = get_grid_dimensions(num_missions + remove_top_left) + # pick missions in order along concentric diagonals + # each diagonal will have the same difficulty + # this keeps long sides from possibly stealing lower-difficulty missions from future columns + num_diagonals = grid_size_x + grid_size_y - 1 + diagonal_difficulty = MissionPools.STARTER + missions_to_add = mission_pools[MissionPools.STARTER] + for diagonal in range(num_diagonals): + if diagonal == num_diagonals - 1: + diagonal_difficulty = MissionPools.FINAL + grid_coords = (grid_size_x-1, grid_size_y-1) + missions[grid_coords] = final_mission + break + if diagonal == 0 and remove_top_left: + continue + diagonal_length = min(diagonal + 1, num_diagonals - diagonal, grid_size_x, grid_size_y) + if len(missions_to_add) < diagonal_length: + raise Exception(f"There are not enough {diagonal_difficulty.name} missions to fill the campaign. Please exclude fewer missions.") + for i in range(diagonal_length): + # (0,0) + (0,1)*diagonal + (1,-1)*i + (1,-1)*max(diagonal - grid_size_y + 1, 0) + grid_coords = (i + max(diagonal - grid_size_y + 1, 0), diagonal - i - max(diagonal - grid_size_y + 1, 0)) + if grid_coords == (grid_size_x - 1, 0) and num_corners_to_remove >= 2: + pass + elif grid_coords == (0, grid_size_y - 1) and num_corners_to_remove >= 1: + pass + else: + mission_index = world.random.randint(0, len(missions_to_add) - 1) + missions[grid_coords] = missions_to_add.pop(mission_index) + + if diagonal_difficulty < MissionPools.VERY_HARD: + diagonal_difficulty = MissionPools(diagonal_difficulty.value + 1) + missions_to_add.extend(mission_pools[diagonal_difficulty]) + + # Generating regions and locations from selected missions + for x in range(grid_size_x): + for y in range(grid_size_y): + if missions.get((x, y)): + regions.append(create_region(world, locations_per_region, location_cache, missions[(x, y)].mission_name)) + world.multiworld.regions += regions + + # This pattern is horrifying, why are we using the dict as an ordered dict??? + slot_map: Dict[Tuple[int, int], int] = {} + for index, coords in enumerate(missions): + slot_map[coords] = index + 1 + + mission_req_table: Dict[str, MissionInfo] = {} + for coords, mission in missions.items(): + prepend_vertical = 0 + if not mission: + continue + connections: List[MissionConnection] = [] + if coords == (0, 0) or (remove_top_left and sum(coords) == 1): + # Connect to the "Menu" starting region + connect(world, names, "Menu", mission.mission_name) + else: + for dx, dy in ((-1, 0), (1, 0), (0, -1), (0, 1)): + connected_coords = (coords[0] + dx, coords[1] + dy) + if connected_coords in missions: + # connections.append(missions[connected_coords]) + connections.append(MissionConnection(slot_map[connected_coords])) + connect(world, names, missions[connected_coords].mission_name, mission.mission_name, + make_grid_connect_rule(missions, connected_coords, world.player), + ) + if coords[1] == 1 and not missions.get((coords[0], 0)): + prepend_vertical = 1 + mission_req_table[mission.mission_name] = MissionInfo( + mission, + connections, + category=f'_{coords[0] + 1}', + or_requirements=True, + ui_vertical_padding=prepend_vertical, + ) + + final_mission_id = final_mission.id + # Changing the completion condition for alternate final missions into an event + final_location = get_goal_location(final_mission) + assert final_location, f"Unable to find a goal location for mission {final_mission}" + setup_final_location(final_location, location_cache) + + return {SC2Campaign.GLOBAL: mission_req_table}, final_mission_id, final_location + + +def make_grid_connect_rule( + missions: Dict[Tuple[int, int], SC2Mission], + connected_coords: Tuple[int, int], + player: int +) -> Callable[[CollectionState], bool]: + return lambda state: state.has(f"Beat {missions[connected_coords].mission_name}", player) + + +def make_dynamic_mission_order( + world: 'SC2World', + mission_order_type: int +) -> Dict[SC2Campaign, List[FillMission]]: + mission_pools = filter_missions(world) + + mission_pool = [mission for mission_pool in mission_pools.values() for mission in mission_pool] + + num_missions = min(len(mission_pool), get_option_value(world, "maximum_campaign_size")) + num_missions = max(2, num_missions) + if mission_order_type == MissionOrder.option_golden_path: + return make_golden_path(world, num_missions) + # Grid handled by dedicated region generator + elif mission_order_type == MissionOrder.option_gauntlet: + return make_gauntlet(num_missions) + elif mission_order_type == MissionOrder.option_blitz: + return make_blitz(num_missions) + elif mission_order_type == MissionOrder.option_hopscotch: + return make_hopscotch(world.options.grid_two_start_positions, num_missions) + + +def create_structured_regions( + world: 'SC2World', + locations: Tuple[LocationData, ...], + location_cache: List[Location], + mission_order_type: MissionOrder, +) -> Tuple[Dict[SC2Campaign, Dict[str, MissionInfo]], int, str]: + locations_per_region = get_locations_per_region(locations) + + if mission_order_type in static_mission_orders: + mission_order = static_mission_orders[mission_order_type]() + else: + mission_order = make_dynamic_mission_order(world, mission_order_type) + enabled_campaigns = get_enabled_campaigns(world) + shuffle_campaigns = get_option_value(world, "shuffle_campaigns") + + mission_pools: Dict[MissionPools, List[SC2Mission]] = filter_missions(world) + final_mission = mission_pools[MissionPools.FINAL][0] + + regions = [create_region(world, locations_per_region, location_cache, "Menu")] + + names: Dict[str, int] = {} + + mission_slots: List[SC2MissionSlot] = [] + mission_pool = [mission for mission_pool in mission_pools.values() for mission in mission_pool] + + if mission_order_type in campaign_depending_orders: + # Do slot removal per campaign + for campaign in enabled_campaigns: + campaign_mission_pool = [mission for mission in mission_pool if mission.campaign == campaign] + campaign_mission_pool_size = len(campaign_mission_pool) + + removals = len(mission_order[campaign]) - campaign_mission_pool_size + + for fill_mission in mission_order[campaign]: + # Removing extra missions if mission pool is too small + if 0 < fill_mission.removal_priority <= removals: + mission_slots.append(SC2MissionSlot(campaign, None)) + elif fill_mission.type == MissionPools.FINAL: + if campaign == final_mission.campaign: + # Campaign is elected to be goal + mission_slots.append(SC2MissionSlot(campaign, final_mission)) + else: + # Not the goal, find the most difficult mission in the pool and set the difficulty + campaign_difficulty = max(fill_mission.pool for fill_mission in campaign_mission_pool) + mission_slots.append(SC2MissionSlot(campaign, campaign_difficulty)) + else: + mission_slots.append(SC2MissionSlot(campaign, fill_mission.type)) + else: + order = mission_order[SC2Campaign.GLOBAL] + # Determining if missions must be removed + mission_pool_size = sum(len(mission_pool) for mission_pool in mission_pools.values()) + removals = len(order) - mission_pool_size + + # Initial fill out of mission list and marking All-In mission + for fill_mission in order: + # Removing extra missions if mission pool is too small + if 0 < fill_mission.removal_priority <= removals: + mission_slots.append(SC2MissionSlot(SC2Campaign.GLOBAL, None)) + elif fill_mission.type == MissionPools.FINAL: + mission_slots.append(SC2MissionSlot(SC2Campaign.GLOBAL, final_mission)) + else: + mission_slots.append(SC2MissionSlot(SC2Campaign.GLOBAL, fill_mission.type)) + + no_build_slots = [] + easy_slots = [] + medium_slots = [] + hard_slots = [] + very_hard_slots = [] + + # Search through missions to find slots needed to fill + for i in range(len(mission_slots)): + mission_slot = mission_slots[i] + if mission_slot is None: + continue + if isinstance(mission_slot, SC2MissionSlot): + if mission_slot.slot is None: + continue + if mission_slot.slot == MissionPools.STARTER: + no_build_slots.append(i) + elif mission_slot.slot == MissionPools.EASY: + easy_slots.append(i) + elif mission_slot.slot == MissionPools.MEDIUM: + medium_slots.append(i) + elif mission_slot.slot == MissionPools.HARD: + hard_slots.append(i) + elif mission_slot.slot == MissionPools.VERY_HARD: + very_hard_slots.append(i) + + def pick_mission(slot): + if shuffle_campaigns or mission_order_type not in campaign_depending_orders: + # Pick a mission from any campaign + filler = world.random.randint(0, len(missions_to_add) - 1) + mission = missions_to_add.pop(filler) + slot_campaign = mission_slots[slot].campaign + mission_slots[slot] = SC2MissionSlot(slot_campaign, mission) + else: + # Pick a mission from required campaign + slot_campaign = mission_slots[slot].campaign + campaign_mission_candidates = [mission for mission in missions_to_add if mission.campaign == slot_campaign] + mission = world.random.choice(campaign_mission_candidates) + missions_to_add.remove(mission) + mission_slots[slot] = SC2MissionSlot(slot_campaign, mission) + + # Add no_build missions to the pool and fill in no_build slots + missions_to_add: List[SC2Mission] = mission_pools[MissionPools.STARTER] + if len(no_build_slots) > len(missions_to_add): + raise Exception("There are no valid No-Build missions. Please exclude fewer missions.") + for slot in no_build_slots: + pick_mission(slot) + + # Add easy missions into pool and fill in easy slots + missions_to_add = missions_to_add + mission_pools[MissionPools.EASY] + if len(easy_slots) > len(missions_to_add): + raise Exception("There are not enough Easy missions to fill the campaign. Please exclude fewer missions.") + for slot in easy_slots: + pick_mission(slot) + + # Add medium missions into pool and fill in medium slots + missions_to_add = missions_to_add + mission_pools[MissionPools.MEDIUM] + if len(medium_slots) > len(missions_to_add): + raise Exception("There are not enough Easy and Medium missions to fill the campaign. Please exclude fewer missions.") + for slot in medium_slots: + pick_mission(slot) + + # Add hard missions into pool and fill in hard slots + missions_to_add = missions_to_add + mission_pools[MissionPools.HARD] + if len(hard_slots) > len(missions_to_add): + raise Exception("There are not enough missions to fill the campaign. Please exclude fewer missions.") + for slot in hard_slots: + pick_mission(slot) + + # Add very hard missions into pool and fill in very hard slots + missions_to_add = missions_to_add + mission_pools[MissionPools.VERY_HARD] + if len(very_hard_slots) > len(missions_to_add): + raise Exception("There are not enough missions to fill the campaign. Please exclude fewer missions.") + for slot in very_hard_slots: + pick_mission(slot) + + # Generating regions and locations from selected missions + for mission_slot in mission_slots: + if isinstance(mission_slot.slot, SC2Mission): + regions.append(create_region(world, locations_per_region, location_cache, mission_slot.slot.mission_name)) + world.multiworld.regions += regions + + campaigns: List[SC2Campaign] + if mission_order_type in campaign_depending_orders: + campaigns = list(enabled_campaigns) + else: + campaigns = [SC2Campaign.GLOBAL] + + mission_req_table: Dict[SC2Campaign, Dict[str, MissionInfo]] = {} + campaign_mission_slots: Dict[SC2Campaign, List[SC2MissionSlot]] = \ + { + campaign: [mission_slot for mission_slot in mission_slots if campaign == mission_slot.campaign] + for campaign in campaigns + } + + slot_map: Dict[SC2Campaign, List[int]] = dict() + + for campaign in campaigns: + mission_req_table.update({campaign: dict()}) + + # Mapping original mission slots to shifted mission slots when missions are removed + slot_map[campaign] = [] + slot_offset = 0 + for position, mission in enumerate(campaign_mission_slots[campaign]): + slot_map[campaign].append(position - slot_offset + 1) + if mission is None or mission.slot is None: + slot_offset += 1 + + def build_connection_rule(mission_names: List[str], missions_req: int) -> Callable: + player = world.player + if len(mission_names) > 1: + return lambda state: state.has_all({f"Beat {name}" for name in mission_names}, player) \ + and state.has_group("Missions", player, missions_req) + else: + return lambda state: state.has(f"Beat {mission_names[0]}", player) \ + and state.has_group("Missions", player, missions_req) + + for campaign in campaigns: + # Loop through missions to create requirements table and connect regions + for i, mission in enumerate(campaign_mission_slots[campaign]): + if mission is None or mission.slot is None: + continue + connections: List[MissionConnection] = [] + all_connections: List[SC2MissionSlot] = [] + connection: MissionConnection + for connection in mission_order[campaign][i].connect_to: + if connection.connect_to == -1: + continue + # If mission normally connects to an excluded campaign, connect to menu instead + if connection.campaign not in campaign_mission_slots: + connection.connect_to = -1 + continue + while campaign_mission_slots[connection.campaign][connection.connect_to].slot is None: + connection.connect_to -= 1 + all_connections.append(campaign_mission_slots[connection.campaign][connection.connect_to]) + for connection in mission_order[campaign][i].connect_to: + if connection.connect_to == -1: + connect(world, names, "Menu", mission.slot.mission_name) + else: + required_mission = campaign_mission_slots[connection.campaign][connection.connect_to] + if ((required_mission is None or required_mission.slot is None) + and not mission_order[campaign][i].completion_critical): # Drop non-critical null slots + continue + while required_mission is None or required_mission.slot is None: # Substituting null slot with prior slot + connection.connect_to -= 1 + required_mission = campaign_mission_slots[connection.campaign][connection.connect_to] + required_missions = [required_mission] if mission_order[campaign][i].or_requirements else all_connections + if isinstance(required_mission.slot, SC2Mission): + required_mission_name = required_mission.slot.mission_name + required_missions_names = [mission.slot.mission_name for mission in required_missions] + connect(world, names, required_mission_name, mission.slot.mission_name, + build_connection_rule(required_missions_names, mission_order[campaign][i].number)) + connections.append(MissionConnection(slot_map[connection.campaign][connection.connect_to], connection.campaign)) + + mission_req_table[campaign].update({mission.slot.mission_name: MissionInfo( + mission.slot, connections, mission_order[campaign][i].category, + number=mission_order[campaign][i].number, + completion_critical=mission_order[campaign][i].completion_critical, + or_requirements=mission_order[campaign][i].or_requirements, + ui_vertical_padding=mission_order[campaign][i].ui_vertical_padding), + }) + + final_mission_id = final_mission.id + # Changing the completion condition for alternate final missions into an event + final_location = get_goal_location(final_mission) + assert final_location, f"Unable to find a goal location for mission {final_mission}" + setup_final_location(final_location, location_cache) + + return mission_req_table, final_mission_id, final_location + + +def setup_final_location(final_location, location_cache): + # Final location should be near the end of the cache + for i in range(len(location_cache) - 1, -1, -1): + if location_cache[i].name == final_location: + location_cache[i].address = None + break + + +def create_location(player: int, location_data: LocationData, region: Region, + location_cache: List[Location]) -> Location: + location = Location(player, location_data.name, location_data.code, region) + location.access_rule = location_data.rule + + location_cache.append(location) + + return location + + +def create_region(world: 'SC2World', locations_per_region: Dict[str, List[LocationData]], + location_cache: List[Location], name: str) -> Region: + region = Region(name, world.player, world.multiworld) + + if name in locations_per_region: + for location_data in locations_per_region[name]: + location = create_location(world.player, location_data, region, location_cache) + region.locations.append(location) + + return region + + +def connect(world: 'SC2World', used_names: Dict[str, int], source: str, target: str, + rule: Optional[Callable] = None): + source_region = world.get_region(source) + target_region = world.get_region(target) + + if target not in used_names: + used_names[target] = 1 + name = target + else: + used_names[target] += 1 + name = target + (' ' * used_names[target]) + + connection = Entrance(world.player, name, source_region) + + if rule: + connection.access_rule = rule + + source_region.exits.append(connection) + connection.connect(target_region) + + +def get_locations_per_region(locations: Tuple[LocationData, ...]) -> Dict[str, List[LocationData]]: + per_region: Dict[str, List[LocationData]] = {} + + for location in locations: + per_region.setdefault(location.region, []).append(location) + + return per_region + + +def get_factors(number: int) -> Tuple[int, int]: + """ + Simple factorization into pairs of numbers (x, y) using a sieve method. + Returns the factorization that is most square, i.e. where x + y is minimized. + Factor order is such that x <= y. + """ + assert number > 0 + for divisor in range(math.floor(math.sqrt(number)), 1, -1): + quotient = number // divisor + if quotient * divisor == number: + return divisor, quotient + return 1, number + + +def get_grid_dimensions(size: int) -> Tuple[int, int, int]: + """ + Get the dimensions of a grid mission order from the number of missions, int the format (x, y, error). + * Error will always be 0, 1, or 2, so the missions can be removed from the corners that aren't the start or end. + * Dimensions are chosen such that x <= y, as buttons in the UI are wider than they are tall. + * Dimensions are chosen to be maximally square. That is, x + y + error is minimized. + * If multiple options of the same rating are possible, the one with the larger error is chosen, + as it will appear more square. Compare 3x11 to 5x7-2 for an example of this. + """ + dimension_candidates: List[Tuple[int, int, int]] = [(*get_factors(size + x), x) for x in (2, 1, 0)] + best_dimension = min(dimension_candidates, key=sum) + return best_dimension + diff --git a/worlds/sc2/test/test_usecases.py b/worlds/sc2/test/test_usecases.py index 664f6af430ef..303514782a31 100644 --- a/worlds/sc2/test/test_usecases.py +++ b/worlds/sc2/test/test_usecases.py @@ -7,6 +7,21 @@ class TestSupportedUseCases(Sc2SetupTestBase): + def test_vanilla_all_campaigns_generates(self) -> None: + world_options = { + 'mission_order': options.MissionOrder.option_vanilla, + 'enable_wol_missions': True, + 'enable_nco_missions': True, + 'enable_prophecy_missions': True, + 'enable_hots_missions': True, + 'enable_lotv_prologue_missions': True, + 'enable_lotv_missions': True, + 'enable_epilogue_missions': True, + } + self.generate_world(world_options) + world_regions = [region.name for region in self.multiworld.regions if region.name != "Menu"] + self.assertEqual(len(world_regions), 83, "Unexpected number of missions for vanilla mission order") + def test_terran_with_nco_units_only_generates(self): world_options = { 'enable_prophecy_missions': False, From 50c5269bdd77299998eef3a52d2c2852944e9bb6 Mon Sep 17 00:00:00 2001 From: Matthew Date: Fri, 5 Jul 2024 23:55:10 -0700 Subject: [PATCH 2/2] sc2: Simplified location data creation in locations to automatically prepend mission name to location name --- worlds/sc2/locations.py | 1428 ++++++++++++++++++++------------------- 1 file changed, 719 insertions(+), 709 deletions(-) diff --git a/worlds/sc2/locations.py b/worlds/sc2/locations.py index 385e210fd9b2..9a9f806a1b45 100644 --- a/worlds/sc2/locations.py +++ b/worlds/sc2/locations.py @@ -41,6 +41,16 @@ class LocationData(NamedTuple): rule: Callable[['CollectionState'], bool] = Location.access_rule +def make_location_data( + region: str, + name: str, + code: int, + type: LocationType, + rule: Callable[['CollectionState'], bool] = Location.access_rule +) -> LocationData: + return LocationData(region, f'{region}: {name}', code, type, rule) + + def get_location_types(world: 'SC2World', inclusion_type: int) -> Set[LocationType]: """ @@ -97,1096 +107,1096 @@ def get_locations(world: Optional['SC2World']) -> Tuple[LocationData, ...]: player = 1 if world is None else world.player location_table: List[LocationData] = [ # WoL - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Victory", SC2WOL_LOC_ID_OFFSET + 100, LocationType.VICTORY), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: First Statue", SC2WOL_LOC_ID_OFFSET + 101, LocationType.VANILLA), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Second Statue", SC2WOL_LOC_ID_OFFSET + 102, LocationType.VANILLA), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Third Statue", SC2WOL_LOC_ID_OFFSET + 103, LocationType.VANILLA), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Fourth Statue", SC2WOL_LOC_ID_OFFSET + 104, LocationType.VANILLA), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Fifth Statue", SC2WOL_LOC_ID_OFFSET + 105, LocationType.VANILLA), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Sixth Statue", SC2WOL_LOC_ID_OFFSET + 106, LocationType.VANILLA), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Special Delivery", SC2WOL_LOC_ID_OFFSET + 107, LocationType.EXTRA), - LocationData(SC2Mission.LIBERATION_DAY.mission_name, "Liberation Day: Transport", SC2WOL_LOC_ID_OFFSET + 108, LocationType.EXTRA), - LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 200, LocationType.VICTORY, + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 100, LocationType.VICTORY), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "First Statue", SC2WOL_LOC_ID_OFFSET + 101, LocationType.VANILLA), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Second Statue", SC2WOL_LOC_ID_OFFSET + 102, LocationType.VANILLA), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Third Statue", SC2WOL_LOC_ID_OFFSET + 103, LocationType.VANILLA), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Fourth Statue", SC2WOL_LOC_ID_OFFSET + 104, LocationType.VANILLA), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Fifth Statue", SC2WOL_LOC_ID_OFFSET + 105, LocationType.VANILLA), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Sixth Statue", SC2WOL_LOC_ID_OFFSET + 106, LocationType.VANILLA), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Special Delivery", SC2WOL_LOC_ID_OFFSET + 107, LocationType.EXTRA), + make_location_data(SC2Mission.LIBERATION_DAY.mission_name, "Transport", SC2WOL_LOC_ID_OFFSET + 108, LocationType.EXTRA), + make_location_data(SC2Mission.THE_OUTLAWS.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 200, LocationType.VICTORY, lambda state: logic.terran_early_tech(state)), - LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Rebel Base", SC2WOL_LOC_ID_OFFSET + 201, LocationType.VANILLA, + make_location_data(SC2Mission.THE_OUTLAWS.mission_name, "Rebel Base", SC2WOL_LOC_ID_OFFSET + 201, LocationType.VANILLA, lambda state: logic.terran_early_tech(state)), - LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): North Resource Pickups", SC2WOL_LOC_ID_OFFSET + 202, LocationType.EXTRA, + make_location_data(SC2Mission.THE_OUTLAWS.mission_name, "North Resource Pickups", SC2WOL_LOC_ID_OFFSET + 202, LocationType.EXTRA, lambda state: logic.terran_early_tech(state)), - LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Bunker", SC2WOL_LOC_ID_OFFSET + 203, LocationType.VANILLA, + make_location_data(SC2Mission.THE_OUTLAWS.mission_name, "Bunker", SC2WOL_LOC_ID_OFFSET + 203, LocationType.VANILLA, lambda state: logic.terran_early_tech(state)), - LocationData(SC2Mission.THE_OUTLAWS.mission_name, "The Outlaws (Terran): Close Resource Pickups", SC2WOL_LOC_ID_OFFSET + 204, LocationType.EXTRA), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 300, LocationType.VICTORY, + make_location_data(SC2Mission.THE_OUTLAWS.mission_name, "Close Resource Pickups", SC2WOL_LOC_ID_OFFSET + 204, LocationType.EXTRA), + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 300, LocationType.VICTORY, lambda state: logic.terran_common_unit(state) and logic.terran_defense_rating(state, True) >= 2 and (adv_tactics or logic.terran_basic_anti_air(state))), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): First Group Rescued", SC2WOL_LOC_ID_OFFSET + 301, LocationType.VANILLA), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 302, LocationType.VANILLA, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "First Group Rescued", SC2WOL_LOC_ID_OFFSET + 301, LocationType.VANILLA), + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 302, LocationType.VANILLA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 303, LocationType.VANILLA, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 303, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and logic.terran_defense_rating(state, True) >= 2), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): First Hatchery", SC2WOL_LOC_ID_OFFSET + 304, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "First Hatchery", SC2WOL_LOC_ID_OFFSET + 304, LocationType.CHALLENGE, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Second Hatchery", SC2WOL_LOC_ID_OFFSET + 305, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Second Hatchery", SC2WOL_LOC_ID_OFFSET + 305, LocationType.CHALLENGE, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Third Hatchery", SC2WOL_LOC_ID_OFFSET + 306, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Third Hatchery", SC2WOL_LOC_ID_OFFSET + 306, LocationType.CHALLENGE, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Fourth Hatchery", SC2WOL_LOC_ID_OFFSET + 307, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Fourth Hatchery", SC2WOL_LOC_ID_OFFSET + 307, LocationType.CHALLENGE, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Ride's on its Way", SC2WOL_LOC_ID_OFFSET + 308, LocationType.EXTRA, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Ride's on its Way", SC2WOL_LOC_ID_OFFSET + 308, LocationType.EXTRA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Hold Just a Little Longer", SC2WOL_LOC_ID_OFFSET + 309, LocationType.EXTRA, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Hold Just a Little Longer", SC2WOL_LOC_ID_OFFSET + 309, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_defense_rating(state, True) >= 2), - LocationData(SC2Mission.ZERO_HOUR.mission_name, "Zero Hour (Terran): Cavalry's on the Way", SC2WOL_LOC_ID_OFFSET + 310, LocationType.EXTRA, + make_location_data(SC2Mission.ZERO_HOUR.mission_name, "Cavalry's on the Way", SC2WOL_LOC_ID_OFFSET + 310, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_defense_rating(state, True) >= 2), - LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Victory", SC2WOL_LOC_ID_OFFSET + 400, LocationType.VICTORY, + make_location_data(SC2Mission.EVACUATION.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 400, LocationType.VICTORY, lambda state: logic.terran_early_tech(state) and (adv_tactics and logic.terran_basic_anti_air(state) or logic.terran_competent_anti_air(state))), - LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: North Chrysalis", SC2WOL_LOC_ID_OFFSET + 401, LocationType.VANILLA), - LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: West Chrysalis", SC2WOL_LOC_ID_OFFSET + 402, LocationType.VANILLA, + make_location_data(SC2Mission.EVACUATION.mission_name, "North Chrysalis", SC2WOL_LOC_ID_OFFSET + 401, LocationType.VANILLA), + make_location_data(SC2Mission.EVACUATION.mission_name, "West Chrysalis", SC2WOL_LOC_ID_OFFSET + 402, LocationType.VANILLA, lambda state: logic.terran_early_tech(state)), - LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: East Chrysalis", SC2WOL_LOC_ID_OFFSET + 403, LocationType.VANILLA, + make_location_data(SC2Mission.EVACUATION.mission_name, "East Chrysalis", SC2WOL_LOC_ID_OFFSET + 403, LocationType.VANILLA, lambda state: logic.terran_early_tech(state)), - LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Reach Hanson", SC2WOL_LOC_ID_OFFSET + 404, LocationType.EXTRA), - LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Secret Resource Stash", SC2WOL_LOC_ID_OFFSET + 405, LocationType.EXTRA), - LocationData(SC2Mission.EVACUATION.mission_name, "Evacuation: Flawless", SC2WOL_LOC_ID_OFFSET + 406, LocationType.CHALLENGE, + make_location_data(SC2Mission.EVACUATION.mission_name, "Reach Hanson", SC2WOL_LOC_ID_OFFSET + 404, LocationType.EXTRA), + make_location_data(SC2Mission.EVACUATION.mission_name, "Secret Resource Stash", SC2WOL_LOC_ID_OFFSET + 405, LocationType.EXTRA), + make_location_data(SC2Mission.EVACUATION.mission_name, "Flawless", SC2WOL_LOC_ID_OFFSET + 406, LocationType.CHALLENGE, lambda state: logic.terran_early_tech(state) and logic.terran_defense_rating(state, True, False) >= 2 and (adv_tactics and logic.terran_basic_anti_air(state) or logic.terran_competent_anti_air(state))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Victory", SC2WOL_LOC_ID_OFFSET + 500, LocationType.VICTORY, + make_location_data(SC2Mission.OUTBREAK.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 500, LocationType.VICTORY, lambda state: logic.terran_defense_rating(state, True, False) >= 4 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Left Infestor", SC2WOL_LOC_ID_OFFSET + 501, LocationType.VANILLA, + make_location_data(SC2Mission.OUTBREAK.mission_name, "Left Infestor", SC2WOL_LOC_ID_OFFSET + 501, LocationType.VANILLA, lambda state: logic.terran_defense_rating(state, True, False) >= 2 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Right Infestor", SC2WOL_LOC_ID_OFFSET + 502, LocationType.VANILLA, + make_location_data(SC2Mission.OUTBREAK.mission_name, "Right Infestor", SC2WOL_LOC_ID_OFFSET + 502, LocationType.VANILLA, lambda state: logic.terran_defense_rating(state, True, False) >= 2 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: North Infested Command Center", SC2WOL_LOC_ID_OFFSET + 503, LocationType.EXTRA, + make_location_data(SC2Mission.OUTBREAK.mission_name, "North Infested Command Center", SC2WOL_LOC_ID_OFFSET + 503, LocationType.EXTRA, lambda state: logic.terran_defense_rating(state, True, False) >= 2 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: South Infested Command Center", SC2WOL_LOC_ID_OFFSET + 504, LocationType.EXTRA, + make_location_data(SC2Mission.OUTBREAK.mission_name, "South Infested Command Center", SC2WOL_LOC_ID_OFFSET + 504, LocationType.EXTRA, lambda state: logic.terran_defense_rating(state, True, False) >= 2 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: Northwest Bar", SC2WOL_LOC_ID_OFFSET + 505, LocationType.EXTRA, + make_location_data(SC2Mission.OUTBREAK.mission_name, "Northwest Bar", SC2WOL_LOC_ID_OFFSET + 505, LocationType.EXTRA, lambda state: logic.terran_defense_rating(state, True, False) >= 2 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: North Bar", SC2WOL_LOC_ID_OFFSET + 506, LocationType.EXTRA, + make_location_data(SC2Mission.OUTBREAK.mission_name, "North Bar", SC2WOL_LOC_ID_OFFSET + 506, LocationType.EXTRA, lambda state: logic.terran_defense_rating(state, True, False) >= 2 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.OUTBREAK.mission_name, "Outbreak: South Bar", SC2WOL_LOC_ID_OFFSET + 507, LocationType.EXTRA, + make_location_data(SC2Mission.OUTBREAK.mission_name, "South Bar", SC2WOL_LOC_ID_OFFSET + 507, LocationType.EXTRA, lambda state: logic.terran_defense_rating(state, True, False) >= 2 and (logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: Victory", SC2WOL_LOC_ID_OFFSET + 600, LocationType.VICTORY, + make_location_data(SC2Mission.SAFE_HAVEN.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 600, LocationType.VICTORY, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state)), - LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: North Nexus", SC2WOL_LOC_ID_OFFSET + 601, LocationType.EXTRA, + make_location_data(SC2Mission.SAFE_HAVEN.mission_name, "North Nexus", SC2WOL_LOC_ID_OFFSET + 601, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state)), - LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: East Nexus", SC2WOL_LOC_ID_OFFSET + 602, LocationType.EXTRA, + make_location_data(SC2Mission.SAFE_HAVEN.mission_name, "East Nexus", SC2WOL_LOC_ID_OFFSET + 602, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state)), - LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: South Nexus", SC2WOL_LOC_ID_OFFSET + 603, LocationType.EXTRA, + make_location_data(SC2Mission.SAFE_HAVEN.mission_name, "South Nexus", SC2WOL_LOC_ID_OFFSET + 603, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state)), - LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: First Terror Fleet", SC2WOL_LOC_ID_OFFSET + 604, LocationType.VANILLA, + make_location_data(SC2Mission.SAFE_HAVEN.mission_name, "First Terror Fleet", SC2WOL_LOC_ID_OFFSET + 604, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state)), - LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: Second Terror Fleet", SC2WOL_LOC_ID_OFFSET + 605, LocationType.VANILLA, + make_location_data(SC2Mission.SAFE_HAVEN.mission_name, "Second Terror Fleet", SC2WOL_LOC_ID_OFFSET + 605, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state)), - LocationData(SC2Mission.SAFE_HAVEN.mission_name, "Safe Haven: Third Terror Fleet", SC2WOL_LOC_ID_OFFSET + 606, LocationType.VANILLA, + make_location_data(SC2Mission.SAFE_HAVEN.mission_name, "Third Terror Fleet", SC2WOL_LOC_ID_OFFSET + 606, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state)), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Victory", SC2WOL_LOC_ID_OFFSET + 700, LocationType.VICTORY, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 700, LocationType.VICTORY, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state) and logic.terran_defense_rating(state, True) >= 3), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: North Hive", SC2WOL_LOC_ID_OFFSET + 701, LocationType.VANILLA, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "North Hive", SC2WOL_LOC_ID_OFFSET + 701, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state) and logic.terran_defense_rating(state, True) >= 3), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: East Hive", SC2WOL_LOC_ID_OFFSET + 702, LocationType.VANILLA, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "East Hive", SC2WOL_LOC_ID_OFFSET + 702, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state) and logic.terran_defense_rating(state, True) >= 3), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: South Hive", SC2WOL_LOC_ID_OFFSET + 703, LocationType.VANILLA, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "South Hive", SC2WOL_LOC_ID_OFFSET + 703, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state) and logic.terran_defense_rating(state, True) >= 3), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Northeast Colony Base", SC2WOL_LOC_ID_OFFSET + 704, LocationType.CHALLENGE, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "Northeast Colony Base", SC2WOL_LOC_ID_OFFSET + 704, LocationType.CHALLENGE, lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: East Colony Base", SC2WOL_LOC_ID_OFFSET + 705, LocationType.CHALLENGE, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "East Colony Base", SC2WOL_LOC_ID_OFFSET + 705, LocationType.CHALLENGE, lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Middle Colony Base", SC2WOL_LOC_ID_OFFSET + 706, LocationType.CHALLENGE, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "Middle Colony Base", SC2WOL_LOC_ID_OFFSET + 706, LocationType.CHALLENGE, lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southeast Colony Base", SC2WOL_LOC_ID_OFFSET + 707, LocationType.CHALLENGE, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "Southeast Colony Base", SC2WOL_LOC_ID_OFFSET + 707, LocationType.CHALLENGE, lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southwest Colony Base", SC2WOL_LOC_ID_OFFSET + 708, LocationType.CHALLENGE, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "Southwest Colony Base", SC2WOL_LOC_ID_OFFSET + 708, LocationType.CHALLENGE, lambda state: logic.terran_respond_to_colony_infestations(state)), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southwest Gas Pickups", SC2WOL_LOC_ID_OFFSET + 709, LocationType.EXTRA, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "Southwest Gas Pickups", SC2WOL_LOC_ID_OFFSET + 709, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state) and logic.terran_defense_rating(state, True) >= 3), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: East Gas Pickups", SC2WOL_LOC_ID_OFFSET + 710, LocationType.EXTRA, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "East Gas Pickups", SC2WOL_LOC_ID_OFFSET + 710, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state) and logic.terran_defense_rating(state, True) >= 3), - LocationData(SC2Mission.HAVENS_FALL.mission_name, "Haven's Fall: Southeast Gas Pickups", SC2WOL_LOC_ID_OFFSET + 711, LocationType.EXTRA, + make_location_data(SC2Mission.HAVENS_FALL.mission_name, "Southeast Gas Pickups", SC2WOL_LOC_ID_OFFSET + 711, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and logic.terran_competent_anti_air(state) and logic.terran_defense_rating(state, True) >= 3), - LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Victory", SC2WOL_LOC_ID_OFFSET + 800, LocationType.VICTORY, + make_location_data(SC2Mission.SMASH_AND_GRAB.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 800, LocationType.VICTORY, lambda state: logic.terran_common_unit(state) and (adv_tactics and logic.terran_basic_anti_air(state) or logic.terran_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): First Relic", SC2WOL_LOC_ID_OFFSET + 801, LocationType.VANILLA), - LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Second Relic", SC2WOL_LOC_ID_OFFSET + 802, LocationType.VANILLA), - LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Third Relic", SC2WOL_LOC_ID_OFFSET + 803, LocationType.VANILLA, + make_location_data(SC2Mission.SMASH_AND_GRAB.mission_name, "First Relic", SC2WOL_LOC_ID_OFFSET + 801, LocationType.VANILLA), + make_location_data(SC2Mission.SMASH_AND_GRAB.mission_name, "Second Relic", SC2WOL_LOC_ID_OFFSET + 802, LocationType.VANILLA), + make_location_data(SC2Mission.SMASH_AND_GRAB.mission_name, "Third Relic", SC2WOL_LOC_ID_OFFSET + 803, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and (adv_tactics and logic.terran_basic_anti_air(state) or logic.terran_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Fourth Relic", SC2WOL_LOC_ID_OFFSET + 804, LocationType.VANILLA, + make_location_data(SC2Mission.SMASH_AND_GRAB.mission_name, "Fourth Relic", SC2WOL_LOC_ID_OFFSET + 804, LocationType.VANILLA, lambda state: logic.terran_common_unit(state) and (adv_tactics and logic.terran_basic_anti_air(state) or logic.terran_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): First Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 805, LocationType.EXTRA, + make_location_data(SC2Mission.SMASH_AND_GRAB.mission_name, "First Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 805, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and (adv_tactics and logic.terran_basic_anti_air(state) or logic.terran_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB.mission_name, "Smash and Grab (Terran): Second Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 806, LocationType.EXTRA, + make_location_data(SC2Mission.SMASH_AND_GRAB.mission_name, "Second Forcefield Area Busted", SC2WOL_LOC_ID_OFFSET + 806, LocationType.EXTRA, lambda state: logic.terran_common_unit(state) and (adv_tactics and logic.terran_basic_anti_air(state) or logic.terran_competent_anti_air(state))), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Victory", SC2WOL_LOC_ID_OFFSET + 900, LocationType.VICTORY, + make_location_data(SC2Mission.THE_DIG.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 900, LocationType.VICTORY, lambda state: logic.terran_basic_anti_air(state) and logic.terran_defense_rating(state, False, True) >= 8 and logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Left Relic", SC2WOL_LOC_ID_OFFSET + 901, LocationType.VANILLA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Left Relic", SC2WOL_LOC_ID_OFFSET + 901, LocationType.VANILLA, lambda state: logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Right Ground Relic", SC2WOL_LOC_ID_OFFSET + 902, LocationType.VANILLA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Right Ground Relic", SC2WOL_LOC_ID_OFFSET + 902, LocationType.VANILLA, lambda state: logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Right Cliff Relic", SC2WOL_LOC_ID_OFFSET + 903, LocationType.VANILLA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Right Cliff Relic", SC2WOL_LOC_ID_OFFSET + 903, LocationType.VANILLA, lambda state: logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Moebius Base", SC2WOL_LOC_ID_OFFSET + 904, LocationType.EXTRA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Moebius Base", SC2WOL_LOC_ID_OFFSET + 904, LocationType.EXTRA, lambda state: logic.marine_medic_upgrade(state) or adv_tactics), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Door Outer Layer", SC2WOL_LOC_ID_OFFSET + 905, LocationType.EXTRA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Door Outer Layer", SC2WOL_LOC_ID_OFFSET + 905, LocationType.EXTRA, lambda state: logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Door Thermal Barrier", SC2WOL_LOC_ID_OFFSET + 906, LocationType.EXTRA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Door Thermal Barrier", SC2WOL_LOC_ID_OFFSET + 906, LocationType.EXTRA, lambda state: logic.terran_basic_anti_air(state) and logic.terran_defense_rating(state, False, True) >= 8 and logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Cutting Through the Core", SC2WOL_LOC_ID_OFFSET + 907, LocationType.EXTRA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Cutting Through the Core", SC2WOL_LOC_ID_OFFSET + 907, LocationType.EXTRA, lambda state: logic.terran_basic_anti_air(state) and logic.terran_defense_rating(state, False, True) >= 8 and logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_DIG.mission_name, "The Dig: Structure Access Imminent", SC2WOL_LOC_ID_OFFSET + 908, LocationType.EXTRA, + make_location_data(SC2Mission.THE_DIG.mission_name, "Structure Access Imminent", SC2WOL_LOC_ID_OFFSET + 908, LocationType.EXTRA, lambda state: logic.terran_basic_anti_air(state) and logic.terran_defense_rating(state, False, True) >= 8 and logic.terran_defense_rating(state, False, False) >= 6 and logic.terran_common_unit(state) and (logic.marine_medic_upgrade(state) or adv_tactics)), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Victory", SC2WOL_LOC_ID_OFFSET + 1000, LocationType.VICTORY, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1000, LocationType.VICTORY, lambda state: logic.terran_basic_anti_air(state) and (logic.terran_air(state) or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) and logic.terran_common_unit(state))), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: 1st Data Core", SC2WOL_LOC_ID_OFFSET + 1001, LocationType.VANILLA), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: 2nd Data Core", SC2WOL_LOC_ID_OFFSET + 1002, LocationType.VANILLA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "1st Data Core", SC2WOL_LOC_ID_OFFSET + 1001, LocationType.VANILLA), + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "2nd Data Core", SC2WOL_LOC_ID_OFFSET + 1002, LocationType.VANILLA, lambda state: (logic.terran_air(state) or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) and logic.terran_common_unit(state))), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: South Rescue", SC2WOL_LOC_ID_OFFSET + 1003, LocationType.EXTRA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "South Rescue", SC2WOL_LOC_ID_OFFSET + 1003, LocationType.EXTRA, lambda state: logic.terran_can_rescue(state)), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Wall Rescue", SC2WOL_LOC_ID_OFFSET + 1004, LocationType.EXTRA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "Wall Rescue", SC2WOL_LOC_ID_OFFSET + 1004, LocationType.EXTRA, lambda state: logic.terran_can_rescue(state)), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Mid Rescue", SC2WOL_LOC_ID_OFFSET + 1005, LocationType.EXTRA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "Mid Rescue", SC2WOL_LOC_ID_OFFSET + 1005, LocationType.EXTRA, lambda state: logic.terran_can_rescue(state)), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Nydus Roof Rescue", SC2WOL_LOC_ID_OFFSET + 1006, LocationType.EXTRA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "Nydus Roof Rescue", SC2WOL_LOC_ID_OFFSET + 1006, LocationType.EXTRA, lambda state: logic.terran_can_rescue(state)), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Alive Inside Rescue", SC2WOL_LOC_ID_OFFSET + 1007, LocationType.EXTRA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "Alive Inside Rescue", SC2WOL_LOC_ID_OFFSET + 1007, LocationType.EXTRA, lambda state: logic.terran_can_rescue(state)), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1008, LocationType.VANILLA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "Brutalisk", SC2WOL_LOC_ID_OFFSET + 1008, LocationType.VANILLA, lambda state: logic.terran_basic_anti_air(state) and (logic.terran_air(state) or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) and logic.terran_common_unit(state))), - LocationData(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "The Moebius Factor: 3rd Data Core", SC2WOL_LOC_ID_OFFSET + 1009, LocationType.VANILLA, + make_location_data(SC2Mission.THE_MOEBIUS_FACTOR.mission_name, "3rd Data Core", SC2WOL_LOC_ID_OFFSET + 1009, LocationType.VANILLA, lambda state: logic.terran_basic_anti_air(state) and (logic.terran_air(state) or state.has_any({item_names.MEDIVAC, item_names.HERCULES}, player) and logic.terran_common_unit(state))), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Victory", SC2WOL_LOC_ID_OFFSET + 1100, LocationType.VICTORY, + make_location_data(SC2Mission.SUPERNOVA.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1100, LocationType.VICTORY, lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: West Relic", SC2WOL_LOC_ID_OFFSET + 1101, LocationType.VANILLA), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: North Relic", SC2WOL_LOC_ID_OFFSET + 1102, LocationType.VANILLA), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: South Relic", SC2WOL_LOC_ID_OFFSET + 1103, LocationType.VANILLA, + make_location_data(SC2Mission.SUPERNOVA.mission_name, "West Relic", SC2WOL_LOC_ID_OFFSET + 1101, LocationType.VANILLA), + make_location_data(SC2Mission.SUPERNOVA.mission_name, "North Relic", SC2WOL_LOC_ID_OFFSET + 1102, LocationType.VANILLA), + make_location_data(SC2Mission.SUPERNOVA.mission_name, "South Relic", SC2WOL_LOC_ID_OFFSET + 1103, LocationType.VANILLA, lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: East Relic", SC2WOL_LOC_ID_OFFSET + 1104, LocationType.VANILLA, + make_location_data(SC2Mission.SUPERNOVA.mission_name, "East Relic", SC2WOL_LOC_ID_OFFSET + 1104, LocationType.VANILLA, lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1105, LocationType.EXTRA), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Middle Base", SC2WOL_LOC_ID_OFFSET + 1106, LocationType.EXTRA, + make_location_data(SC2Mission.SUPERNOVA.mission_name, "Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1105, LocationType.EXTRA), + make_location_data(SC2Mission.SUPERNOVA.mission_name, "Middle Base", SC2WOL_LOC_ID_OFFSET + 1106, LocationType.EXTRA, lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.SUPERNOVA.mission_name, "Supernova: Southeast Base", SC2WOL_LOC_ID_OFFSET + 1107, LocationType.EXTRA, + make_location_data(SC2Mission.SUPERNOVA.mission_name, "Southeast Base", SC2WOL_LOC_ID_OFFSET + 1107, LocationType.EXTRA, lambda state: logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Victory", SC2WOL_LOC_ID_OFFSET + 1200, LocationType.VICTORY, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1200, LocationType.VICTORY, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1201, LocationType.EXTRA), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Expansion Prisoners", SC2WOL_LOC_ID_OFFSET + 1202, LocationType.VANILLA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Landing Zone Cleared", SC2WOL_LOC_ID_OFFSET + 1201, LocationType.EXTRA), + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Expansion Prisoners", SC2WOL_LOC_ID_OFFSET + 1202, LocationType.VANILLA, lambda state: adv_tactics or logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: South Close Prisoners", SC2WOL_LOC_ID_OFFSET + 1203, LocationType.VANILLA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "South Close Prisoners", SC2WOL_LOC_ID_OFFSET + 1203, LocationType.VANILLA, lambda state: adv_tactics or logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: South Far Prisoners", SC2WOL_LOC_ID_OFFSET + 1204, LocationType.VANILLA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "South Far Prisoners", SC2WOL_LOC_ID_OFFSET + 1204, LocationType.VANILLA, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: North Prisoners", SC2WOL_LOC_ID_OFFSET + 1205, LocationType.VANILLA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "North Prisoners", SC2WOL_LOC_ID_OFFSET + 1205, LocationType.VANILLA, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Mothership", SC2WOL_LOC_ID_OFFSET + 1206, LocationType.EXTRA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Mothership", SC2WOL_LOC_ID_OFFSET + 1206, LocationType.EXTRA, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Expansion Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1207, LocationType.EXTRA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Expansion Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1207, LocationType.EXTRA, lambda state: adv_tactics or logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Middle Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1208, LocationType.EXTRA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Middle Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1208, LocationType.EXTRA, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Southeast Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1209, LocationType.EXTRA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Southeast Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1209, LocationType.EXTRA, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Stargate Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1210, LocationType.EXTRA, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Stargate Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1210, LocationType.EXTRA, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Northwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1211, LocationType.CHALLENGE, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Northwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1211, LocationType.CHALLENGE, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: West Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1212, LocationType.CHALLENGE, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "West Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1212, LocationType.CHALLENGE, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.MAW_OF_THE_VOID.mission_name, "Maw of the Void: Southwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1213, LocationType.CHALLENGE, + make_location_data(SC2Mission.MAW_OF_THE_VOID.mission_name, "Southwest Rip Field Generator", SC2WOL_LOC_ID_OFFSET + 1213, LocationType.CHALLENGE, lambda state: logic.terran_survives_rip_field(state)), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Victory", SC2WOL_LOC_ID_OFFSET + 1300, LocationType.VICTORY, + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1300, LocationType.VICTORY, lambda state: adv_tactics or logic.terran_basic_anti_air(state) and ( logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Tosh's Miners", SC2WOL_LOC_ID_OFFSET + 1301, LocationType.VANILLA), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Brutalisk", SC2WOL_LOC_ID_OFFSET + 1302, LocationType.VANILLA, + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Tosh's Miners", SC2WOL_LOC_ID_OFFSET + 1301, LocationType.VANILLA), + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Brutalisk", SC2WOL_LOC_ID_OFFSET + 1302, LocationType.VANILLA, lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: North Reapers", SC2WOL_LOC_ID_OFFSET + 1303, LocationType.EXTRA), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Middle Reapers", SC2WOL_LOC_ID_OFFSET + 1304, LocationType.EXTRA, + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "North Reapers", SC2WOL_LOC_ID_OFFSET + 1303, LocationType.EXTRA), + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Middle Reapers", SC2WOL_LOC_ID_OFFSET + 1304, LocationType.EXTRA, lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Southwest Reapers", SC2WOL_LOC_ID_OFFSET + 1305, LocationType.EXTRA, + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Southwest Reapers", SC2WOL_LOC_ID_OFFSET + 1305, LocationType.EXTRA, lambda state: adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player)), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Southeast Reapers", SC2WOL_LOC_ID_OFFSET + 1306, LocationType.EXTRA, + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Southeast Reapers", SC2WOL_LOC_ID_OFFSET + 1306, LocationType.EXTRA, lambda state: adv_tactics or logic.terran_basic_anti_air(state) and ( logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: East Reapers", SC2WOL_LOC_ID_OFFSET + 1307, LocationType.CHALLENGE, + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "East Reapers", SC2WOL_LOC_ID_OFFSET + 1307, LocationType.CHALLENGE, lambda state: logic.terran_basic_anti_air(state) and (adv_tactics or logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Devil's Playground: Zerg Cleared", SC2WOL_LOC_ID_OFFSET + 1308, LocationType.CHALLENGE, + make_location_data(SC2Mission.DEVILS_PLAYGROUND.mission_name, "Zerg Cleared", SC2WOL_LOC_ID_OFFSET + 1308, LocationType.CHALLENGE, lambda state: logic.terran_competent_anti_air(state) and ( logic.terran_common_unit(state) or state.has(item_names.REAPER, player))), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Victory", SC2WOL_LOC_ID_OFFSET + 1400, LocationType.VICTORY, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1400, LocationType.VICTORY, lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Close Relic", SC2WOL_LOC_ID_OFFSET + 1401, LocationType.VANILLA), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: West Relic", SC2WOL_LOC_ID_OFFSET + 1402, LocationType.VANILLA, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Close Relic", SC2WOL_LOC_ID_OFFSET + 1401, LocationType.VANILLA), + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "West Relic", SC2WOL_LOC_ID_OFFSET + 1402, LocationType.VANILLA, lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: North-East Relic", SC2WOL_LOC_ID_OFFSET + 1403, LocationType.VANILLA, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "North-East Relic", SC2WOL_LOC_ID_OFFSET + 1403, LocationType.VANILLA, lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Middle Base", SC2WOL_LOC_ID_OFFSET + 1404, LocationType.EXTRA, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Middle Base", SC2WOL_LOC_ID_OFFSET + 1404, LocationType.EXTRA, lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Main Base", SC2WOL_LOC_ID_OFFSET + 1405, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Main Base", SC2WOL_LOC_ID_OFFSET + 1405, LocationType.MASTERY, lambda state: logic.welcome_to_the_jungle_requirement(state) and logic.terran_beats_protoss_deathball(state) and logic.terran_base_trasher(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: No Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1406, LocationType.CHALLENGE, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "No Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1406, LocationType.CHALLENGE, lambda state: logic.welcome_to_the_jungle_requirement(state) and logic.terran_competent_ground_to_air(state) and logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 1 Terrazine Node Sealed", SC2WOL_LOC_ID_OFFSET + 1407, LocationType.CHALLENGE, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Up to 1 Terrazine Node Sealed", SC2WOL_LOC_ID_OFFSET + 1407, LocationType.CHALLENGE, lambda state: logic.welcome_to_the_jungle_requirement(state) and logic.terran_competent_ground_to_air(state) and logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 2 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1408, LocationType.CHALLENGE, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Up to 2 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1408, LocationType.CHALLENGE, lambda state: logic.welcome_to_the_jungle_requirement(state) and logic.terran_beats_protoss_deathball(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 3 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1409, LocationType.CHALLENGE, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Up to 3 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1409, LocationType.CHALLENGE, lambda state: logic.welcome_to_the_jungle_requirement(state) and logic.terran_competent_comp(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 4 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1410, LocationType.EXTRA, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Up to 4 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1410, LocationType.EXTRA, lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Welcome to the Jungle: Up to 5 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1411, LocationType.EXTRA, + make_location_data(SC2Mission.WELCOME_TO_THE_JUNGLE.mission_name, "Up to 5 Terrazine Nodes Sealed", SC2WOL_LOC_ID_OFFSET + 1411, LocationType.EXTRA, lambda state: logic.welcome_to_the_jungle_requirement(state)), - LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Victory", SC2WOL_LOC_ID_OFFSET + 1500, LocationType.VICTORY), - LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Diamondback Prison", SC2WOL_LOC_ID_OFFSET + 1501, LocationType.VANILLA), - LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Siege Tank Prison", SC2WOL_LOC_ID_OFFSET + 1502, LocationType.VANILLA), - LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: First Checkpoint", SC2WOL_LOC_ID_OFFSET + 1503, LocationType.EXTRA), - LocationData(SC2Mission.BREAKOUT.mission_name, "Breakout: Second Checkpoint", SC2WOL_LOC_ID_OFFSET + 1504, LocationType.EXTRA), - LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Victory", SC2WOL_LOC_ID_OFFSET + 1600, LocationType.VICTORY), - LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Terrazine Tank", SC2WOL_LOC_ID_OFFSET + 1601, LocationType.EXTRA), - LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Jorium Stockpile", SC2WOL_LOC_ID_OFFSET + 1602, LocationType.EXTRA), - LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: First Island Spectres", SC2WOL_LOC_ID_OFFSET + 1603, LocationType.VANILLA), - LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Second Island Spectres", SC2WOL_LOC_ID_OFFSET + 1604, LocationType.VANILLA), - LocationData(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Ghost of a Chance: Third Island Spectres", SC2WOL_LOC_ID_OFFSET + 1605, LocationType.VANILLA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Victory", SC2WOL_LOC_ID_OFFSET + 1700, LocationType.VICTORY, + make_location_data(SC2Mission.BREAKOUT.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1500, LocationType.VICTORY), + make_location_data(SC2Mission.BREAKOUT.mission_name, "Diamondback Prison", SC2WOL_LOC_ID_OFFSET + 1501, LocationType.VANILLA), + make_location_data(SC2Mission.BREAKOUT.mission_name, "Siege Tank Prison", SC2WOL_LOC_ID_OFFSET + 1502, LocationType.VANILLA), + make_location_data(SC2Mission.BREAKOUT.mission_name, "First Checkpoint", SC2WOL_LOC_ID_OFFSET + 1503, LocationType.EXTRA), + make_location_data(SC2Mission.BREAKOUT.mission_name, "Second Checkpoint", SC2WOL_LOC_ID_OFFSET + 1504, LocationType.EXTRA), + make_location_data(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1600, LocationType.VICTORY), + make_location_data(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Terrazine Tank", SC2WOL_LOC_ID_OFFSET + 1601, LocationType.EXTRA), + make_location_data(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Jorium Stockpile", SC2WOL_LOC_ID_OFFSET + 1602, LocationType.EXTRA), + make_location_data(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "First Island Spectres", SC2WOL_LOC_ID_OFFSET + 1603, LocationType.VANILLA), + make_location_data(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Second Island Spectres", SC2WOL_LOC_ID_OFFSET + 1604, LocationType.VANILLA), + make_location_data(SC2Mission.GHOST_OF_A_CHANCE.mission_name, "Third Island Spectres", SC2WOL_LOC_ID_OFFSET + 1605, LocationType.VANILLA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1700, LocationType.VICTORY, lambda state: logic.great_train_robbery_train_stopper(state) and logic.terran_basic_anti_air(state)), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: North Defiler", SC2WOL_LOC_ID_OFFSET + 1701, LocationType.VANILLA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Mid Defiler", SC2WOL_LOC_ID_OFFSET + 1702, LocationType.VANILLA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: South Defiler", SC2WOL_LOC_ID_OFFSET + 1703, LocationType.VANILLA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Close Diamondback", SC2WOL_LOC_ID_OFFSET + 1704, LocationType.EXTRA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Northwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1705, LocationType.EXTRA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: North Diamondback", SC2WOL_LOC_ID_OFFSET + 1706, LocationType.EXTRA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Northeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1707, LocationType.EXTRA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Southwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1708, LocationType.EXTRA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Southeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1709, LocationType.EXTRA), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Kill Team", SC2WOL_LOC_ID_OFFSET + 1710, LocationType.CHALLENGE, + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "North Defiler", SC2WOL_LOC_ID_OFFSET + 1701, LocationType.VANILLA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Mid Defiler", SC2WOL_LOC_ID_OFFSET + 1702, LocationType.VANILLA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "South Defiler", SC2WOL_LOC_ID_OFFSET + 1703, LocationType.VANILLA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Close Diamondback", SC2WOL_LOC_ID_OFFSET + 1704, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Northwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1705, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "North Diamondback", SC2WOL_LOC_ID_OFFSET + 1706, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Northeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1707, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Southwest Diamondback", SC2WOL_LOC_ID_OFFSET + 1708, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Southeast Diamondback", SC2WOL_LOC_ID_OFFSET + 1709, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Kill Team", SC2WOL_LOC_ID_OFFSET + 1710, LocationType.CHALLENGE, lambda state: (adv_tactics or logic.terran_common_unit(state)) and logic.great_train_robbery_train_stopper(state) and logic.terran_basic_anti_air(state)), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: Flawless", SC2WOL_LOC_ID_OFFSET + 1711, LocationType.CHALLENGE, + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "Flawless", SC2WOL_LOC_ID_OFFSET + 1711, LocationType.CHALLENGE, lambda state: logic.great_train_robbery_train_stopper(state) and logic.terran_basic_anti_air(state)), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: 2 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1712, LocationType.EXTRA, + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "2 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1712, LocationType.EXTRA, lambda state: logic.great_train_robbery_train_stopper(state)), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: 4 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1713, LocationType.EXTRA, + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "4 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1713, LocationType.EXTRA, lambda state: logic.great_train_robbery_train_stopper(state) and logic.terran_basic_anti_air(state)), - LocationData(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "The Great Train Robbery: 6 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1714, LocationType.EXTRA, + make_location_data(SC2Mission.THE_GREAT_TRAIN_ROBBERY.mission_name, "6 Trains Destroyed", SC2WOL_LOC_ID_OFFSET + 1714, LocationType.EXTRA, lambda state: logic.great_train_robbery_train_stopper(state) and logic.terran_basic_anti_air(state)), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Victory", SC2WOL_LOC_ID_OFFSET + 1800, LocationType.VICTORY, + make_location_data(SC2Mission.CUTTHROAT.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1800, LocationType.VICTORY, lambda state: logic.terran_common_unit(state) and (adv_tactics or logic.terran_basic_anti_air(state))), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Mira Han", SC2WOL_LOC_ID_OFFSET + 1801, LocationType.EXTRA, + make_location_data(SC2Mission.CUTTHROAT.mission_name, "Mira Han", SC2WOL_LOC_ID_OFFSET + 1801, LocationType.EXTRA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: North Relic", SC2WOL_LOC_ID_OFFSET + 1802, LocationType.VANILLA, + make_location_data(SC2Mission.CUTTHROAT.mission_name, "North Relic", SC2WOL_LOC_ID_OFFSET + 1802, LocationType.VANILLA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Mid Relic", SC2WOL_LOC_ID_OFFSET + 1803, LocationType.VANILLA), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: Southwest Relic", SC2WOL_LOC_ID_OFFSET + 1804, LocationType.VANILLA, + make_location_data(SC2Mission.CUTTHROAT.mission_name, "Mid Relic", SC2WOL_LOC_ID_OFFSET + 1803, LocationType.VANILLA), + make_location_data(SC2Mission.CUTTHROAT.mission_name, "Southwest Relic", SC2WOL_LOC_ID_OFFSET + 1804, LocationType.VANILLA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: North Command Center", SC2WOL_LOC_ID_OFFSET + 1805, LocationType.EXTRA, + make_location_data(SC2Mission.CUTTHROAT.mission_name, "North Command Center", SC2WOL_LOC_ID_OFFSET + 1805, LocationType.EXTRA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: South Command Center", SC2WOL_LOC_ID_OFFSET + 1806, LocationType.EXTRA, + make_location_data(SC2Mission.CUTTHROAT.mission_name, "South Command Center", SC2WOL_LOC_ID_OFFSET + 1806, LocationType.EXTRA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.CUTTHROAT.mission_name, "Cutthroat: West Command Center", SC2WOL_LOC_ID_OFFSET + 1807, LocationType.EXTRA, + make_location_data(SC2Mission.CUTTHROAT.mission_name, "West Command Center", SC2WOL_LOC_ID_OFFSET + 1807, LocationType.EXTRA, lambda state: logic.terran_common_unit(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Victory", SC2WOL_LOC_ID_OFFSET + 1900, LocationType.VICTORY, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 1900, LocationType.VICTORY, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Odin", SC2WOL_LOC_ID_OFFSET + 1901, LocationType.EXTRA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Odin", SC2WOL_LOC_ID_OFFSET + 1901, LocationType.EXTRA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Loki", SC2WOL_LOC_ID_OFFSET + 1902, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Loki", SC2WOL_LOC_ID_OFFSET + 1902, LocationType.CHALLENGE, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Lab Devourer", SC2WOL_LOC_ID_OFFSET + 1903, LocationType.VANILLA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Lab Devourer", SC2WOL_LOC_ID_OFFSET + 1903, LocationType.VANILLA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: North Devourer", SC2WOL_LOC_ID_OFFSET + 1904, LocationType.VANILLA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "North Devourer", SC2WOL_LOC_ID_OFFSET + 1904, LocationType.VANILLA, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Southeast Devourer", SC2WOL_LOC_ID_OFFSET + 1905, LocationType.VANILLA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Southeast Devourer", SC2WOL_LOC_ID_OFFSET + 1905, LocationType.VANILLA, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: West Base", SC2WOL_LOC_ID_OFFSET + 1906, LocationType.EXTRA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "West Base", SC2WOL_LOC_ID_OFFSET + 1906, LocationType.EXTRA, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Northwest Base", SC2WOL_LOC_ID_OFFSET + 1907, LocationType.EXTRA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Northwest Base", SC2WOL_LOC_ID_OFFSET + 1907, LocationType.EXTRA, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Northeast Base", SC2WOL_LOC_ID_OFFSET + 1908, LocationType.EXTRA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Northeast Base", SC2WOL_LOC_ID_OFFSET + 1908, LocationType.EXTRA, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Engine of Destruction: Southeast Base", SC2WOL_LOC_ID_OFFSET + 1909, LocationType.EXTRA, + make_location_data(SC2Mission.ENGINE_OF_DESTRUCTION.mission_name, "Southeast Base", SC2WOL_LOC_ID_OFFSET + 1909, LocationType.EXTRA, lambda state: logic.engine_of_destruction_requirement(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Victory", SC2WOL_LOC_ID_OFFSET + 2000, LocationType.VICTORY, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2000, LocationType.VICTORY, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Tower 1", SC2WOL_LOC_ID_OFFSET + 2001, LocationType.VANILLA, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "Tower 1", SC2WOL_LOC_ID_OFFSET + 2001, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Tower 2", SC2WOL_LOC_ID_OFFSET + 2002, LocationType.VANILLA, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "Tower 2", SC2WOL_LOC_ID_OFFSET + 2002, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Tower 3", SC2WOL_LOC_ID_OFFSET + 2003, LocationType.VANILLA, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "Tower 3", SC2WOL_LOC_ID_OFFSET + 2003, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Science Facility", SC2WOL_LOC_ID_OFFSET + 2004, LocationType.VANILLA), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: All Barracks", SC2WOL_LOC_ID_OFFSET + 2005, LocationType.EXTRA, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "Science Facility", SC2WOL_LOC_ID_OFFSET + 2004, LocationType.VANILLA), + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "All Barracks", SC2WOL_LOC_ID_OFFSET + 2005, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: All Factories", SC2WOL_LOC_ID_OFFSET + 2006, LocationType.EXTRA, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "All Factories", SC2WOL_LOC_ID_OFFSET + 2006, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: All Starports", SC2WOL_LOC_ID_OFFSET + 2007, LocationType.EXTRA, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "All Starports", SC2WOL_LOC_ID_OFFSET + 2007, LocationType.EXTRA, lambda state: adv_tactics or logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Odin Not Trashed", SC2WOL_LOC_ID_OFFSET + 2008, LocationType.CHALLENGE, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "Odin Not Trashed", SC2WOL_LOC_ID_OFFSET + 2008, LocationType.CHALLENGE, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.MEDIA_BLITZ.mission_name, "Media Blitz: Surprise Attack Ends", SC2WOL_LOC_ID_OFFSET + 2009, LocationType.EXTRA), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Victory", SC2WOL_LOC_ID_OFFSET + 2100, LocationType.VICTORY, + make_location_data(SC2Mission.MEDIA_BLITZ.mission_name, "Surprise Attack Ends", SC2WOL_LOC_ID_OFFSET + 2009, LocationType.EXTRA), + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2100, LocationType.VICTORY, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Holding Cell Relic", SC2WOL_LOC_ID_OFFSET + 2101, LocationType.VANILLA), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Brutalisk Relic", SC2WOL_LOC_ID_OFFSET + 2102, LocationType.VANILLA, + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Holding Cell Relic", SC2WOL_LOC_ID_OFFSET + 2101, LocationType.VANILLA), + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Brutalisk Relic", SC2WOL_LOC_ID_OFFSET + 2102, LocationType.VANILLA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: First Escape Relic", SC2WOL_LOC_ID_OFFSET + 2103, LocationType.VANILLA, + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "First Escape Relic", SC2WOL_LOC_ID_OFFSET + 2103, LocationType.VANILLA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Second Escape Relic", SC2WOL_LOC_ID_OFFSET + 2104, LocationType.VANILLA, + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Second Escape Relic", SC2WOL_LOC_ID_OFFSET + 2104, LocationType.VANILLA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Brutalisk", SC2WOL_LOC_ID_OFFSET + 2105, LocationType.VANILLA, + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Brutalisk", SC2WOL_LOC_ID_OFFSET + 2105, LocationType.VANILLA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Fusion Reactor", SC2WOL_LOC_ID_OFFSET + 2106, LocationType.EXTRA, + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Fusion Reactor", SC2WOL_LOC_ID_OFFSET + 2106, LocationType.EXTRA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Entrance Holding Pen", SC2WOL_LOC_ID_OFFSET + 2107, LocationType.EXTRA), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Cargo Bay Warbot", SC2WOL_LOC_ID_OFFSET + 2108, LocationType.EXTRA), - LocationData(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Piercing the Shroud: Escape Warbot", SC2WOL_LOC_ID_OFFSET + 2109, LocationType.EXTRA, + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Entrance Holding Pen", SC2WOL_LOC_ID_OFFSET + 2107, LocationType.EXTRA), + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Cargo Bay Warbot", SC2WOL_LOC_ID_OFFSET + 2108, LocationType.EXTRA), + make_location_data(SC2Mission.PIERCING_OF_THE_SHROUD.mission_name, "Escape Warbot", SC2WOL_LOC_ID_OFFSET + 2109, LocationType.EXTRA, lambda state: logic.marine_medic_upgrade(state)), - LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Victory", SC2WOL_LOC_ID_OFFSET + 2200, LocationType.VICTORY), - LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: First Hatchery", SC2WOL_LOC_ID_OFFSET + 2201, LocationType.VANILLA), - LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Second Hatchery", SC2WOL_LOC_ID_OFFSET + 2202, LocationType.VANILLA), - LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Third Hatchery", SC2WOL_LOC_ID_OFFSET + 2203, LocationType.VANILLA), - LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: First Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2204, LocationType.EXTRA), - LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Second Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2205, LocationType.EXTRA), - LocationData(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Whispers of Doom: Third Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2206, LocationType.EXTRA), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Victory", SC2WOL_LOC_ID_OFFSET + 2300, LocationType.VICTORY, + make_location_data(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2200, LocationType.VICTORY), + make_location_data(SC2Mission.WHISPERS_OF_DOOM.mission_name, "First Hatchery", SC2WOL_LOC_ID_OFFSET + 2201, LocationType.VANILLA), + make_location_data(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Second Hatchery", SC2WOL_LOC_ID_OFFSET + 2202, LocationType.VANILLA), + make_location_data(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Third Hatchery", SC2WOL_LOC_ID_OFFSET + 2203, LocationType.VANILLA), + make_location_data(SC2Mission.WHISPERS_OF_DOOM.mission_name, "First Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2204, LocationType.EXTRA), + make_location_data(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Second Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2205, LocationType.EXTRA), + make_location_data(SC2Mission.WHISPERS_OF_DOOM.mission_name, "Third Prophecy Fragment", SC2WOL_LOC_ID_OFFSET + 2206, LocationType.EXTRA), + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2300, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Robotics Facility", SC2WOL_LOC_ID_OFFSET + 2301, LocationType.VANILLA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Robotics Facility", SC2WOL_LOC_ID_OFFSET + 2301, LocationType.VANILLA, lambda state: adv_tactics or logic.protoss_common_unit(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Dark Shrine", SC2WOL_LOC_ID_OFFSET + 2302, LocationType.VANILLA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Dark Shrine", SC2WOL_LOC_ID_OFFSET + 2302, LocationType.VANILLA, lambda state: adv_tactics or logic.protoss_common_unit(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Templar Archives", SC2WOL_LOC_ID_OFFSET + 2303, LocationType.VANILLA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Templar Archives", SC2WOL_LOC_ID_OFFSET + 2303, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Northeast Base", SC2WOL_LOC_ID_OFFSET + 2304, LocationType.EXTRA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Northeast Base", SC2WOL_LOC_ID_OFFSET + 2304, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Southwest Base", SC2WOL_LOC_ID_OFFSET + 2305, LocationType.CHALLENGE, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Southwest Base", SC2WOL_LOC_ID_OFFSET + 2305, LocationType.CHALLENGE, lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Maar", SC2WOL_LOC_ID_OFFSET + 2306, LocationType.EXTRA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Maar", SC2WOL_LOC_ID_OFFSET + 2306, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Northwest Preserver", SC2WOL_LOC_ID_OFFSET + 2307, LocationType.EXTRA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Northwest Preserver", SC2WOL_LOC_ID_OFFSET + 2307, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: Southwest Preserver", SC2WOL_LOC_ID_OFFSET + 2308, LocationType.EXTRA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "Southwest Preserver", SC2WOL_LOC_ID_OFFSET + 2308, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.A_SINISTER_TURN.mission_name, "A Sinister Turn: East Preserver", SC2WOL_LOC_ID_OFFSET + 2309, LocationType.EXTRA, + make_location_data(SC2Mission.A_SINISTER_TURN.mission_name, "East Preserver", SC2WOL_LOC_ID_OFFSET + 2309, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Victory", SC2WOL_LOC_ID_OFFSET + 2400, LocationType.VICTORY, + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2400, LocationType.VICTORY, lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state) and logic.protoss_competent_anti_air(state)), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Close Obelisk", SC2WOL_LOC_ID_OFFSET + 2401, LocationType.VANILLA), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: West Obelisk", SC2WOL_LOC_ID_OFFSET + 2402, LocationType.VANILLA, + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Close Obelisk", SC2WOL_LOC_ID_OFFSET + 2401, LocationType.VANILLA), + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "West Obelisk", SC2WOL_LOC_ID_OFFSET + 2402, LocationType.VANILLA, lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Base", SC2WOL_LOC_ID_OFFSET + 2403, LocationType.EXTRA), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Southwest Tendril", SC2WOL_LOC_ID_OFFSET + 2404, LocationType.EXTRA), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Southeast Tendril", SC2WOL_LOC_ID_OFFSET + 2405, LocationType.EXTRA, + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Base", SC2WOL_LOC_ID_OFFSET + 2403, LocationType.EXTRA), + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Southwest Tendril", SC2WOL_LOC_ID_OFFSET + 2404, LocationType.EXTRA), + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Southeast Tendril", SC2WOL_LOC_ID_OFFSET + 2405, LocationType.EXTRA, lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Northeast Tendril", SC2WOL_LOC_ID_OFFSET + 2406, LocationType.EXTRA, + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Northeast Tendril", SC2WOL_LOC_ID_OFFSET + 2406, LocationType.EXTRA, lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Echoes of the Future: Northwest Tendril", SC2WOL_LOC_ID_OFFSET + 2407, LocationType.EXTRA, + make_location_data(SC2Mission.ECHOES_OF_THE_FUTURE.mission_name, "Northwest Tendril", SC2WOL_LOC_ID_OFFSET + 2407, LocationType.EXTRA, lambda state: adv_tactics and logic.protoss_static_defense(state) or logic.protoss_common_unit(state)), - LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Defeat", SC2WOL_LOC_ID_OFFSET + 2500, LocationType.VICTORY), - LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Protoss Archive", SC2WOL_LOC_ID_OFFSET + 2501, LocationType.VANILLA, + make_location_data(SC2Mission.IN_UTTER_DARKNESS.mission_name, "Defeat", SC2WOL_LOC_ID_OFFSET + 2500, LocationType.VICTORY), + make_location_data(SC2Mission.IN_UTTER_DARKNESS.mission_name, "Protoss Archive", SC2WOL_LOC_ID_OFFSET + 2501, LocationType.VANILLA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Kills", SC2WOL_LOC_ID_OFFSET + 2502, LocationType.VANILLA, + make_location_data(SC2Mission.IN_UTTER_DARKNESS.mission_name, "Kills", SC2WOL_LOC_ID_OFFSET + 2502, LocationType.VANILLA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Urun", SC2WOL_LOC_ID_OFFSET + 2503, LocationType.EXTRA), - LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Mohandar", SC2WOL_LOC_ID_OFFSET + 2504, LocationType.EXTRA, + make_location_data(SC2Mission.IN_UTTER_DARKNESS.mission_name, "Urun", SC2WOL_LOC_ID_OFFSET + 2503, LocationType.EXTRA), + make_location_data(SC2Mission.IN_UTTER_DARKNESS.mission_name, "Mohandar", SC2WOL_LOC_ID_OFFSET + 2504, LocationType.EXTRA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Selendis", SC2WOL_LOC_ID_OFFSET + 2505, LocationType.EXTRA, + make_location_data(SC2Mission.IN_UTTER_DARKNESS.mission_name, "Selendis", SC2WOL_LOC_ID_OFFSET + 2505, LocationType.EXTRA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.IN_UTTER_DARKNESS.mission_name, "In Utter Darkness: Artanis", SC2WOL_LOC_ID_OFFSET + 2506, LocationType.EXTRA, + make_location_data(SC2Mission.IN_UTTER_DARKNESS.mission_name, "Artanis", SC2WOL_LOC_ID_OFFSET + 2506, LocationType.EXTRA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Victory", SC2WOL_LOC_ID_OFFSET + 2600, LocationType.VICTORY, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2600, LocationType.VICTORY, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Large Army", SC2WOL_LOC_ID_OFFSET + 2601, LocationType.VANILLA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "Large Army", SC2WOL_LOC_ID_OFFSET + 2601, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 2 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2602, LocationType.VANILLA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "2 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2602, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 4 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2603, LocationType.VANILLA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "4 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2603, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 6 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2604, LocationType.EXTRA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "6 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2604, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: 8 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2605, LocationType.CHALLENGE, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "8 Drop Pods", SC2WOL_LOC_ID_OFFSET + 2605, LocationType.CHALLENGE, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Southwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2606, LocationType.EXTRA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "Southwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2606, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Northwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2607, LocationType.EXTRA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "Northwest Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2607, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Northeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2608, LocationType.EXTRA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "Northeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2608, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: East Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2609, LocationType.EXTRA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "East Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2609, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Southeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2610, LocationType.EXTRA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "Southeast Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2610, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.GATES_OF_HELL.mission_name, "Gates of Hell: Expansion Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2611, LocationType.EXTRA, + make_location_data(SC2Mission.GATES_OF_HELL.mission_name, "Expansion Spore Cannon", SC2WOL_LOC_ID_OFFSET + 2611, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state) and logic.terran_defense_rating(state, True) > 6), - LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Victory", SC2WOL_LOC_ID_OFFSET + 2700, LocationType.VICTORY), - LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: First Charge", SC2WOL_LOC_ID_OFFSET + 2701, LocationType.EXTRA), - LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Second Charge", SC2WOL_LOC_ID_OFFSET + 2702, LocationType.EXTRA), - LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Third Charge", SC2WOL_LOC_ID_OFFSET + 2703, LocationType.EXTRA), - LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: First Group Rescued", SC2WOL_LOC_ID_OFFSET + 2704, LocationType.VANILLA), - LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 2705, LocationType.VANILLA), - LocationData(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Belly of the Beast: Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 2706, LocationType.VANILLA), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Victory", SC2WOL_LOC_ID_OFFSET + 2800, LocationType.VICTORY, + make_location_data(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2700, LocationType.VICTORY), + make_location_data(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "First Charge", SC2WOL_LOC_ID_OFFSET + 2701, LocationType.EXTRA), + make_location_data(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Second Charge", SC2WOL_LOC_ID_OFFSET + 2702, LocationType.EXTRA), + make_location_data(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Third Charge", SC2WOL_LOC_ID_OFFSET + 2703, LocationType.EXTRA), + make_location_data(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "First Group Rescued", SC2WOL_LOC_ID_OFFSET + 2704, LocationType.VANILLA), + make_location_data(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Second Group Rescued", SC2WOL_LOC_ID_OFFSET + 2705, LocationType.VANILLA), + make_location_data(SC2Mission.BELLY_OF_THE_BEAST.mission_name, "Third Group Rescued", SC2WOL_LOC_ID_OFFSET + 2706, LocationType.VANILLA), + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2800, LocationType.VICTORY, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Close Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2801, LocationType.VANILLA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "Close Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2801, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Northwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2802, LocationType.VANILLA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "Northwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2802, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Southeast Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2803, LocationType.VANILLA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "Southeast Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2803, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Southwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2804, LocationType.VANILLA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "Southwest Coolant Tower", SC2WOL_LOC_ID_OFFSET + 2804, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Leviathan", SC2WOL_LOC_ID_OFFSET + 2805, LocationType.VANILLA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "Leviathan", SC2WOL_LOC_ID_OFFSET + 2805, LocationType.VANILLA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: East Hatchery", SC2WOL_LOC_ID_OFFSET + 2806, LocationType.EXTRA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "East Hatchery", SC2WOL_LOC_ID_OFFSET + 2806, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: North Hatchery", SC2WOL_LOC_ID_OFFSET + 2807, LocationType.EXTRA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "North Hatchery", SC2WOL_LOC_ID_OFFSET + 2807, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.SHATTER_THE_SKY.mission_name, "Shatter the Sky: Mid Hatchery", SC2WOL_LOC_ID_OFFSET + 2808, LocationType.EXTRA, + make_location_data(SC2Mission.SHATTER_THE_SKY.mission_name, "Mid Hatchery", SC2WOL_LOC_ID_OFFSET + 2808, LocationType.EXTRA, lambda state: logic.terran_competent_comp(state)), - LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Victory", SC2WOL_LOC_ID_OFFSET + 2900, LocationType.VICTORY, + make_location_data(SC2Mission.ALL_IN.mission_name, "Victory", SC2WOL_LOC_ID_OFFSET + 2900, LocationType.VICTORY, lambda state: logic.all_in_requirement(state)), - LocationData(SC2Mission.ALL_IN.mission_name, "All-In: First Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2901, LocationType.EXTRA, + make_location_data(SC2Mission.ALL_IN.mission_name, "First Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2901, LocationType.EXTRA, lambda state: logic.all_in_requirement(state)), - LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Second Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2902, LocationType.EXTRA, + make_location_data(SC2Mission.ALL_IN.mission_name, "Second Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2902, LocationType.EXTRA, lambda state: logic.all_in_requirement(state)), - LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Third Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2903, LocationType.EXTRA, + make_location_data(SC2Mission.ALL_IN.mission_name, "Third Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2903, LocationType.EXTRA, lambda state: logic.all_in_requirement(state)), - LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Fourth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2904, LocationType.EXTRA, + make_location_data(SC2Mission.ALL_IN.mission_name, "Fourth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2904, LocationType.EXTRA, lambda state: logic.all_in_requirement(state)), - LocationData(SC2Mission.ALL_IN.mission_name, "All-In: Fifth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2905, LocationType.EXTRA, + make_location_data(SC2Mission.ALL_IN.mission_name, "Fifth Kerrigan Attack", SC2WOL_LOC_ID_OFFSET + 2905, LocationType.EXTRA, lambda state: logic.all_in_requirement(state)), # HotS - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Victory", SC2HOTS_LOC_ID_OFFSET + 100, LocationType.VICTORY, + make_location_data(SC2Mission.LAB_RAT.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 100, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Gather Minerals", SC2HOTS_LOC_ID_OFFSET + 101, LocationType.VANILLA), - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: South Zergling Group", SC2HOTS_LOC_ID_OFFSET + 102, LocationType.VANILLA, + make_location_data(SC2Mission.LAB_RAT.mission_name, "Gather Minerals", SC2HOTS_LOC_ID_OFFSET + 101, LocationType.VANILLA), + make_location_data(SC2Mission.LAB_RAT.mission_name, "South Zergling Group", SC2HOTS_LOC_ID_OFFSET + 102, LocationType.VANILLA, lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: East Zergling Group", SC2HOTS_LOC_ID_OFFSET + 103, LocationType.VANILLA, + make_location_data(SC2Mission.LAB_RAT.mission_name, "East Zergling Group", SC2HOTS_LOC_ID_OFFSET + 103, LocationType.VANILLA, lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: West Zergling Group", SC2HOTS_LOC_ID_OFFSET + 104, LocationType.VANILLA, + make_location_data(SC2Mission.LAB_RAT.mission_name, "West Zergling Group", SC2HOTS_LOC_ID_OFFSET + 104, LocationType.VANILLA, lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Hatchery", SC2HOTS_LOC_ID_OFFSET + 105, LocationType.EXTRA), - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Overlord", SC2HOTS_LOC_ID_OFFSET + 106, LocationType.EXTRA), - LocationData(SC2Mission.LAB_RAT.mission_name, "Lab Rat: Gas Turrets", SC2HOTS_LOC_ID_OFFSET + 107, LocationType.EXTRA, + make_location_data(SC2Mission.LAB_RAT.mission_name, "Hatchery", SC2HOTS_LOC_ID_OFFSET + 105, LocationType.EXTRA), + make_location_data(SC2Mission.LAB_RAT.mission_name, "Overlord", SC2HOTS_LOC_ID_OFFSET + 106, LocationType.EXTRA), + make_location_data(SC2Mission.LAB_RAT.mission_name, "Gas Turrets", SC2HOTS_LOC_ID_OFFSET + 107, LocationType.EXTRA, lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Victory", SC2HOTS_LOC_ID_OFFSET + 200, LocationType.VICTORY, + make_location_data(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 200, LocationType.VICTORY, lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), - LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Defend the Tram", SC2HOTS_LOC_ID_OFFSET + 201, LocationType.EXTRA, + make_location_data(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Defend the Tram", SC2HOTS_LOC_ID_OFFSET + 201, LocationType.EXTRA, lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), - LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Kinetic Blast", SC2HOTS_LOC_ID_OFFSET + 202, LocationType.VANILLA), - LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Crushing Grip", SC2HOTS_LOC_ID_OFFSET + 203, LocationType.VANILLA), - LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Reach the Sublevel", SC2HOTS_LOC_ID_OFFSET + 204, LocationType.EXTRA), - LocationData(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Back in the Saddle: Door Section Cleared", SC2HOTS_LOC_ID_OFFSET + 205, LocationType.EXTRA, + make_location_data(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Kinetic Blast", SC2HOTS_LOC_ID_OFFSET + 202, LocationType.VANILLA), + make_location_data(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Crushing Grip", SC2HOTS_LOC_ID_OFFSET + 203, LocationType.VANILLA), + make_location_data(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Reach the Sublevel", SC2HOTS_LOC_ID_OFFSET + 204, LocationType.EXTRA), + make_location_data(SC2Mission.BACK_IN_THE_SADDLE.mission_name, "Door Section Cleared", SC2HOTS_LOC_ID_OFFSET + 205, LocationType.EXTRA, lambda state: logic.basic_kerrigan(state) or kerriganless or logic.story_tech_granted), - LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Victory", SC2HOTS_LOC_ID_OFFSET + 300, LocationType.VICTORY, + make_location_data(SC2Mission.RENDEZVOUS.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 300, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Right Queen", SC2HOTS_LOC_ID_OFFSET + 301, LocationType.VANILLA, + make_location_data(SC2Mission.RENDEZVOUS.mission_name, "Right Queen", SC2HOTS_LOC_ID_OFFSET + 301, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Center Queen", SC2HOTS_LOC_ID_OFFSET + 302, LocationType.VANILLA, + make_location_data(SC2Mission.RENDEZVOUS.mission_name, "Center Queen", SC2HOTS_LOC_ID_OFFSET + 302, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Left Queen", SC2HOTS_LOC_ID_OFFSET + 303, LocationType.VANILLA, + make_location_data(SC2Mission.RENDEZVOUS.mission_name, "Left Queen", SC2HOTS_LOC_ID_OFFSET + 303, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.RENDEZVOUS.mission_name, "Rendezvous: Hold Out Finished", SC2HOTS_LOC_ID_OFFSET + 304, LocationType.EXTRA, + make_location_data(SC2Mission.RENDEZVOUS.mission_name, "Hold Out Finished", SC2HOTS_LOC_ID_OFFSET + 304, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Victory", SC2HOTS_LOC_ID_OFFSET + 400, LocationType.VICTORY, + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 400, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: First Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 401, LocationType.VANILLA), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: North Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 402, LocationType.VANILLA, + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "First Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 401, LocationType.VANILLA), + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "North Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 402, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: West Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 403, LocationType.VANILLA, + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "West Ursadon Matriarch", SC2HOTS_LOC_ID_OFFSET + 403, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Lost Brood", SC2HOTS_LOC_ID_OFFSET + 404, LocationType.EXTRA), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Northeast Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 405, LocationType.EXTRA, + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Lost Brood", SC2HOTS_LOC_ID_OFFSET + 404, LocationType.EXTRA), + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Northeast Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 405, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Northwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 406, LocationType.EXTRA, + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Northwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 406, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Southwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 407, LocationType.EXTRA, + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Southwest Psi-link Spire", SC2HOTS_LOC_ID_OFFSET + 407, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Harvest of Screams: Nafash", SC2HOTS_LOC_ID_OFFSET + 408, LocationType.EXTRA, + make_location_data(SC2Mission.HARVEST_OF_SCREAMS.mission_name, "Nafash", SC2HOTS_LOC_ID_OFFSET + 408, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Victory", SC2HOTS_LOC_ID_OFFSET + 500, LocationType.VICTORY, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 500, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: East Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 501, LocationType.VANILLA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "East Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 501, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Center Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 502, LocationType.VANILLA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Center Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 502, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) or adv_tactics), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: West Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 503, LocationType.VANILLA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "West Stasis Chamber", SC2HOTS_LOC_ID_OFFSET + 503, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Destroy 4 Shuttles", SC2HOTS_LOC_ID_OFFSET + 504, LocationType.EXTRA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Destroy 4 Shuttles", SC2HOTS_LOC_ID_OFFSET + 504, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Frozen Expansion", SC2HOTS_LOC_ID_OFFSET + 505, LocationType.EXTRA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Frozen Expansion", SC2HOTS_LOC_ID_OFFSET + 505, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Southwest Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 506, LocationType.EXTRA), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: Southeast Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 507, LocationType.EXTRA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Southwest Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 506, LocationType.EXTRA), + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Southeast Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 507, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) or adv_tactics), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: West Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 508, LocationType.EXTRA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "West Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 508, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "Shoot the Messenger: East Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 509, LocationType.EXTRA, + make_location_data(SC2Mission.SHOOT_THE_MESSENGER.mission_name, "East Frozen Zerg", SC2HOTS_LOC_ID_OFFSET + 509, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Victory", SC2HOTS_LOC_ID_OFFSET + 600, LocationType.VICTORY, + make_location_data(SC2Mission.ENEMY_WITHIN.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 600, LocationType.VICTORY, lambda state: logic.zerg_pass_vents(state) and (logic.story_tech_granted or state.has_any({item_names.ZERGLING_RAPTOR_STRAIN, item_names.ROACH, item_names.HYDRALISK, item_names.INFESTOR}, player)) ), - LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Infest Giant Ursadon", SC2HOTS_LOC_ID_OFFSET + 601, LocationType.VANILLA, + make_location_data(SC2Mission.ENEMY_WITHIN.mission_name, "Infest Giant Ursadon", SC2HOTS_LOC_ID_OFFSET + 601, LocationType.VANILLA, lambda state: logic.zerg_pass_vents(state)), - LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: First Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 602, LocationType.VANILLA, + make_location_data(SC2Mission.ENEMY_WITHIN.mission_name, "First Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 602, LocationType.VANILLA, lambda state: logic.zerg_pass_vents(state)), - LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Second Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 603, LocationType.VANILLA, + make_location_data(SC2Mission.ENEMY_WITHIN.mission_name, "Second Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 603, LocationType.VANILLA, lambda state: logic.zerg_pass_vents(state)), - LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Third Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 604, LocationType.VANILLA, + make_location_data(SC2Mission.ENEMY_WITHIN.mission_name, "Third Niadra Evolution", SC2HOTS_LOC_ID_OFFSET + 604, LocationType.VANILLA, lambda state: logic.zerg_pass_vents(state)), - LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Warp Drive", SC2HOTS_LOC_ID_OFFSET + 605, LocationType.EXTRA, + make_location_data(SC2Mission.ENEMY_WITHIN.mission_name, "Warp Drive", SC2HOTS_LOC_ID_OFFSET + 605, LocationType.EXTRA, lambda state: logic.zerg_pass_vents(state)), - LocationData(SC2Mission.ENEMY_WITHIN.mission_name, "Enemy Within: Stasis Quadrant", SC2HOTS_LOC_ID_OFFSET + 606, LocationType.EXTRA, + make_location_data(SC2Mission.ENEMY_WITHIN.mission_name, "Stasis Quadrant", SC2HOTS_LOC_ID_OFFSET + 606, LocationType.EXTRA, lambda state: logic.zerg_pass_vents(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Victory", SC2HOTS_LOC_ID_OFFSET + 700, LocationType.VICTORY, + make_location_data(SC2Mission.DOMINATION.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 700, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Center Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 701, LocationType.VANILLA, + make_location_data(SC2Mission.DOMINATION.mission_name, "Center Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 701, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: North Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 702, LocationType.VANILLA, + make_location_data(SC2Mission.DOMINATION.mission_name, "North Infested Command Center", SC2HOTS_LOC_ID_OFFSET + 702, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Repel Zagara", SC2HOTS_LOC_ID_OFFSET + 703, LocationType.EXTRA), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Close Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 704, LocationType.EXTRA), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: South Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 705, LocationType.EXTRA, + make_location_data(SC2Mission.DOMINATION.mission_name, "Repel Zagara", SC2HOTS_LOC_ID_OFFSET + 703, LocationType.EXTRA), + make_location_data(SC2Mission.DOMINATION.mission_name, "Close Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 704, LocationType.EXTRA), + make_location_data(SC2Mission.DOMINATION.mission_name, "South Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 705, LocationType.EXTRA, lambda state: adv_tactics or logic.zerg_common_unit(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Southwest Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 706, LocationType.EXTRA, + make_location_data(SC2Mission.DOMINATION.mission_name, "Southwest Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 706, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Southeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 707, LocationType.EXTRA, + make_location_data(SC2Mission.DOMINATION.mission_name, "Southeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 707, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: North Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 708, LocationType.EXTRA, + make_location_data(SC2Mission.DOMINATION.mission_name, "North Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 708, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.DOMINATION.mission_name, "Domination: Northeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 709, LocationType.EXTRA, + make_location_data(SC2Mission.DOMINATION.mission_name, "Northeast Baneling Nest", SC2HOTS_LOC_ID_OFFSET + 709, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: Victory", SC2HOTS_LOC_ID_OFFSET + 800, LocationType.VICTORY, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 800, LocationType.VICTORY, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: West Biomass", SC2HOTS_LOC_ID_OFFSET + 801, LocationType.VANILLA), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: North Biomass", SC2HOTS_LOC_ID_OFFSET + 802, LocationType.VANILLA, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "West Biomass", SC2HOTS_LOC_ID_OFFSET + 801, LocationType.VANILLA), + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "North Biomass", SC2HOTS_LOC_ID_OFFSET + 802, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: South Biomass", SC2HOTS_LOC_ID_OFFSET + 803, LocationType.VANILLA, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "South Biomass", SC2HOTS_LOC_ID_OFFSET + 803, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: Destroy 3 Gorgons", SC2HOTS_LOC_ID_OFFSET + 804, LocationType.EXTRA, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Destroy 3 Gorgons", SC2HOTS_LOC_ID_OFFSET + 804, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: Close Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 805, LocationType.EXTRA), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: South Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 806, LocationType.EXTRA, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Close Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 805, LocationType.EXTRA), + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "South Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 806, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: North Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 807, LocationType.EXTRA, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "North Zerg Rescue", SC2HOTS_LOC_ID_OFFSET + 807, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: West Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 808, LocationType.EXTRA, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "West Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 808, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.FIRE_IN_THE_SKY.mission_name, "Fire in the Sky: East Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 809, LocationType.EXTRA, + make_location_data(SC2Mission.FIRE_IN_THE_SKY.mission_name, "East Queen Rescue", SC2HOTS_LOC_ID_OFFSET + 809, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Victory", SC2HOTS_LOC_ID_OFFSET + 900, LocationType.VICTORY, + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 900, LocationType.VICTORY, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: East Science Lab", SC2HOTS_LOC_ID_OFFSET + 901, LocationType.VANILLA, + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "East Science Lab", SC2HOTS_LOC_ID_OFFSET + 901, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: North Science Lab", SC2HOTS_LOC_ID_OFFSET + 902, LocationType.VANILLA, + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "North Science Lab", SC2HOTS_LOC_ID_OFFSET + 902, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Get Nuked", SC2HOTS_LOC_ID_OFFSET + 903, LocationType.EXTRA), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Entrance Gate", SC2HOTS_LOC_ID_OFFSET + 904, LocationType.EXTRA), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Citadel Gate", SC2HOTS_LOC_ID_OFFSET + 905, LocationType.EXTRA, + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "Get Nuked", SC2HOTS_LOC_ID_OFFSET + 903, LocationType.EXTRA), + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "Entrance Gate", SC2HOTS_LOC_ID_OFFSET + 904, LocationType.EXTRA), + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "Citadel Gate", SC2HOTS_LOC_ID_OFFSET + 905, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: South Expansion", SC2HOTS_LOC_ID_OFFSET + 906, LocationType.EXTRA), - LocationData(SC2Mission.OLD_SOLDIERS.mission_name, "Old Soldiers: Rich Mineral Expansion", SC2HOTS_LOC_ID_OFFSET + 907, LocationType.EXTRA, + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "South Expansion", SC2HOTS_LOC_ID_OFFSET + 906, LocationType.EXTRA), + make_location_data(SC2Mission.OLD_SOLDIERS.mission_name, "Rich Mineral Expansion", SC2HOTS_LOC_ID_OFFSET + 907, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: Victory", SC2HOTS_LOC_ID_OFFSET + 1000, LocationType.VICTORY, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1000, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: Center Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1001, LocationType.VANILLA), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: East Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1002, LocationType.VANILLA, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Center Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1001, LocationType.VANILLA), + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "East Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1002, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and (adv_tactics and logic.zerg_basic_anti_air(state) or logic.zerg_competent_anti_air(state))), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: South Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1003, LocationType.VANILLA, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "South Essence Pool", SC2HOTS_LOC_ID_OFFSET + 1003, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and (adv_tactics and logic.zerg_basic_anti_air(state) or logic.zerg_competent_anti_air(state))), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: Finish Feeding", SC2HOTS_LOC_ID_OFFSET + 1004, LocationType.EXTRA, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Finish Feeding", SC2HOTS_LOC_ID_OFFSET + 1004, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: South Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1005, LocationType.CHALLENGE, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "South Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1005, LocationType.CHALLENGE, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: East Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1006, LocationType.CHALLENGE, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "East Proxy Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1006, LocationType.CHALLENGE, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: South Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1007, LocationType.CHALLENGE, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "South Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1007, LocationType.CHALLENGE, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.WAKING_THE_ANCIENT.mission_name, "Waking the Ancient: East Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1008, LocationType.CHALLENGE, + make_location_data(SC2Mission.WAKING_THE_ANCIENT.mission_name, "East Main Primal Hive", SC2HOTS_LOC_ID_OFFSET + 1008, LocationType.CHALLENGE, lambda state: logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Victory", SC2HOTS_LOC_ID_OFFSET + 1100, LocationType.VICTORY, + make_location_data(SC2Mission.THE_CRUCIBLE.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1100, LocationType.VICTORY, lambda state: logic.zerg_competent_defense(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Tyrannozor", SC2HOTS_LOC_ID_OFFSET + 1101, LocationType.VANILLA, + make_location_data(SC2Mission.THE_CRUCIBLE.mission_name, "Tyrannozor", SC2HOTS_LOC_ID_OFFSET + 1101, LocationType.VANILLA, lambda state: logic.zerg_competent_defense(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Reach the Pool", SC2HOTS_LOC_ID_OFFSET + 1102, LocationType.VANILLA), - LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: 15 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1103, LocationType.EXTRA, + make_location_data(SC2Mission.THE_CRUCIBLE.mission_name, "Reach the Pool", SC2HOTS_LOC_ID_OFFSET + 1102, LocationType.VANILLA), + make_location_data(SC2Mission.THE_CRUCIBLE.mission_name, "15 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1103, LocationType.EXTRA, lambda state: logic.zerg_competent_defense(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: 5 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1104, LocationType.EXTRA, + make_location_data(SC2Mission.THE_CRUCIBLE.mission_name, "5 Minutes Remaining", SC2HOTS_LOC_ID_OFFSET + 1104, LocationType.EXTRA, lambda state: logic.zerg_competent_defense(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Pincer Attack", SC2HOTS_LOC_ID_OFFSET + 1105, LocationType.EXTRA, + make_location_data(SC2Mission.THE_CRUCIBLE.mission_name, "Pincer Attack", SC2HOTS_LOC_ID_OFFSET + 1105, LocationType.EXTRA, lambda state: logic.zerg_competent_defense(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.THE_CRUCIBLE.mission_name, "The Crucible: Yagdra Claims Brakk's Pack", SC2HOTS_LOC_ID_OFFSET + 1106, LocationType.EXTRA, + make_location_data(SC2Mission.THE_CRUCIBLE.mission_name, "Yagdra Claims Brakk's Pack", SC2HOTS_LOC_ID_OFFSET + 1106, LocationType.EXTRA, lambda state: logic.zerg_competent_defense(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Victory", SC2HOTS_LOC_ID_OFFSET + 1200, LocationType.VICTORY, + make_location_data(SC2Mission.SUPREME.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1200, LocationType.VICTORY, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: First Relic", SC2HOTS_LOC_ID_OFFSET + 1201, LocationType.VANILLA, + make_location_data(SC2Mission.SUPREME.mission_name, "First Relic", SC2HOTS_LOC_ID_OFFSET + 1201, LocationType.VANILLA, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Second Relic", SC2HOTS_LOC_ID_OFFSET + 1202, LocationType.VANILLA, + make_location_data(SC2Mission.SUPREME.mission_name, "Second Relic", SC2HOTS_LOC_ID_OFFSET + 1202, LocationType.VANILLA, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Third Relic", SC2HOTS_LOC_ID_OFFSET + 1203, LocationType.VANILLA, + make_location_data(SC2Mission.SUPREME.mission_name, "Third Relic", SC2HOTS_LOC_ID_OFFSET + 1203, LocationType.VANILLA, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Fourth Relic", SC2HOTS_LOC_ID_OFFSET + 1204, LocationType.VANILLA, + make_location_data(SC2Mission.SUPREME.mission_name, "Fourth Relic", SC2HOTS_LOC_ID_OFFSET + 1204, LocationType.VANILLA, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Yagdra", SC2HOTS_LOC_ID_OFFSET + 1205, LocationType.EXTRA, + make_location_data(SC2Mission.SUPREME.mission_name, "Yagdra", SC2HOTS_LOC_ID_OFFSET + 1205, LocationType.EXTRA, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Kraith", SC2HOTS_LOC_ID_OFFSET + 1206, LocationType.EXTRA, + make_location_data(SC2Mission.SUPREME.mission_name, "Kraith", SC2HOTS_LOC_ID_OFFSET + 1206, LocationType.EXTRA, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.SUPREME.mission_name, "Supreme: Slivan", SC2HOTS_LOC_ID_OFFSET + 1207, LocationType.EXTRA, + make_location_data(SC2Mission.SUPREME.mission_name, "Slivan", SC2HOTS_LOC_ID_OFFSET + 1207, LocationType.EXTRA, lambda state: logic.supreme_requirement(state)), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: Victory", SC2HOTS_LOC_ID_OFFSET + 1300, LocationType.VICTORY, + make_location_data(SC2Mission.INFESTED.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1300, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state) and ((logic.zerg_competent_anti_air(state) and state.has(item_names.INFESTOR, player)) or (adv_tactics and logic.zerg_basic_anti_air(state)))), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: East Science Facility", SC2HOTS_LOC_ID_OFFSET + 1301, LocationType.VANILLA, + make_location_data(SC2Mission.INFESTED.mission_name, "East Science Facility", SC2HOTS_LOC_ID_OFFSET + 1301, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: Center Science Facility", SC2HOTS_LOC_ID_OFFSET + 1302, LocationType.VANILLA, + make_location_data(SC2Mission.INFESTED.mission_name, "Center Science Facility", SC2HOTS_LOC_ID_OFFSET + 1302, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: West Science Facility", SC2HOTS_LOC_ID_OFFSET + 1303, LocationType.VANILLA, + make_location_data(SC2Mission.INFESTED.mission_name, "West Science Facility", SC2HOTS_LOC_ID_OFFSET + 1303, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and logic.spread_creep(state)), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: First Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1304, LocationType.EXTRA), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: Second Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1305, LocationType.EXTRA), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: Base Garrison", SC2HOTS_LOC_ID_OFFSET + 1306, LocationType.EXTRA), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: East Garrison", SC2HOTS_LOC_ID_OFFSET + 1307, LocationType.EXTRA, + make_location_data(SC2Mission.INFESTED.mission_name, "First Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1304, LocationType.EXTRA), + make_location_data(SC2Mission.INFESTED.mission_name, "Second Intro Garrison", SC2HOTS_LOC_ID_OFFSET + 1305, LocationType.EXTRA), + make_location_data(SC2Mission.INFESTED.mission_name, "Base Garrison", SC2HOTS_LOC_ID_OFFSET + 1306, LocationType.EXTRA), + make_location_data(SC2Mission.INFESTED.mission_name, "East Garrison", SC2HOTS_LOC_ID_OFFSET + 1307, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: Mid Garrison", SC2HOTS_LOC_ID_OFFSET + 1308, LocationType.EXTRA, + make_location_data(SC2Mission.INFESTED.mission_name, "Mid Garrison", SC2HOTS_LOC_ID_OFFSET + 1308, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: North Garrison", SC2HOTS_LOC_ID_OFFSET + 1309, LocationType.EXTRA, + make_location_data(SC2Mission.INFESTED.mission_name, "North Garrison", SC2HOTS_LOC_ID_OFFSET + 1309, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: Close Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1310, LocationType.EXTRA, + make_location_data(SC2Mission.INFESTED.mission_name, "Close Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1310, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData(SC2Mission.INFESTED.mission_name, "Infested: Far Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1311, LocationType.EXTRA, + make_location_data(SC2Mission.INFESTED.mission_name, "Far Southwest Garrison", SC2HOTS_LOC_ID_OFFSET + 1311, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and logic.zerg_basic_anti_air(state) and (adv_tactics or state.has(item_names.INFESTOR, player))), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Victory", SC2HOTS_LOC_ID_OFFSET + 1400, LocationType.VICTORY, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1400, LocationType.VICTORY, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: North Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1401, LocationType.VANILLA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "North Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1401, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: South Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1402, LocationType.VANILLA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "South Brutalisk", SC2HOTS_LOC_ID_OFFSET + 1402, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 1 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1403, LocationType.EXTRA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Kill 1 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1403, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 2 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1404, LocationType.EXTRA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Kill 2 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1404, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 3 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1405, LocationType.EXTRA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Kill 3 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1405, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 4 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1406, LocationType.EXTRA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Kill 4 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1406, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 5 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1407, LocationType.EXTRA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Kill 5 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1407, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 6 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1408, LocationType.EXTRA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Kill 6 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1408, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.HAND_OF_DARKNESS.mission_name, "Hand of Darkness: Kill 7 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1409, LocationType.EXTRA, + make_location_data(SC2Mission.HAND_OF_DARKNESS.mission_name, "Kill 7 Hybrid", SC2HOTS_LOC_ID_OFFSET + 1409, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_basic_anti_air(state)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Victory", SC2HOTS_LOC_ID_OFFSET + 1500, LocationType.VICTORY, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1500, LocationType.VICTORY, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northwest Crystal", SC2HOTS_LOC_ID_OFFSET + 1501, LocationType.VANILLA, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Northwest Crystal", SC2HOTS_LOC_ID_OFFSET + 1501, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northeast Crystal", SC2HOTS_LOC_ID_OFFSET + 1502, LocationType.VANILLA, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Northeast Crystal", SC2HOTS_LOC_ID_OFFSET + 1502, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: South Crystal", SC2HOTS_LOC_ID_OFFSET + 1503, LocationType.VANILLA), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Base Established", SC2HOTS_LOC_ID_OFFSET + 1504, LocationType.EXTRA), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Close Temple", SC2HOTS_LOC_ID_OFFSET + 1505, LocationType.EXTRA, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "South Crystal", SC2HOTS_LOC_ID_OFFSET + 1503, LocationType.VANILLA), + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Base Established", SC2HOTS_LOC_ID_OFFSET + 1504, LocationType.EXTRA), + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Close Temple", SC2HOTS_LOC_ID_OFFSET + 1505, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Mid Temple", SC2HOTS_LOC_ID_OFFSET + 1506, LocationType.EXTRA, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Mid Temple", SC2HOTS_LOC_ID_OFFSET + 1506, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Southeast Temple", SC2HOTS_LOC_ID_OFFSET + 1507, LocationType.EXTRA, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Southeast Temple", SC2HOTS_LOC_ID_OFFSET + 1507, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northeast Temple", SC2HOTS_LOC_ID_OFFSET + 1508, LocationType.EXTRA, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Northeast Temple", SC2HOTS_LOC_ID_OFFSET + 1508, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Phantoms of the Void: Northwest Temple", SC2HOTS_LOC_ID_OFFSET + 1509, LocationType.EXTRA, + make_location_data(SC2Mission.PHANTOMS_OF_THE_VOID.mission_name, "Northwest Temple", SC2HOTS_LOC_ID_OFFSET + 1509, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and (logic.zerg_competent_anti_air(state) or adv_tactics)), - LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Victory", SC2HOTS_LOC_ID_OFFSET + 1600, LocationType.VICTORY), - LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Pirate Capital Ship", SC2HOTS_LOC_ID_OFFSET + 1601, LocationType.VANILLA), - LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: First Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1602, LocationType.VANILLA), - LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Second Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1603, LocationType.VANILLA), - LocationData(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "With Friends Like These: Third Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1604, LocationType.VANILLA), - LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Victory", SC2HOTS_LOC_ID_OFFSET + 1700, LocationType.VICTORY, + make_location_data(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1600, LocationType.VICTORY), + make_location_data(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "Pirate Capital Ship", SC2HOTS_LOC_ID_OFFSET + 1601, LocationType.VANILLA), + make_location_data(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "First Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1602, LocationType.VANILLA), + make_location_data(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "Second Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1603, LocationType.VANILLA), + make_location_data(SC2Mission.WITH_FRIENDS_LIKE_THESE.mission_name, "Third Mineral Patch", SC2HOTS_LOC_ID_OFFSET + 1604, LocationType.VANILLA), + make_location_data(SC2Mission.CONVICTION.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1700, LocationType.VICTORY, lambda state: logic.two_kerrigan_actives(state) and (logic.basic_kerrigan(state) or logic.story_tech_granted) or kerriganless), - LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: First Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1701, LocationType.VANILLA, + make_location_data(SC2Mission.CONVICTION.mission_name, "First Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1701, LocationType.VANILLA, lambda state: logic.two_kerrigan_actives(state) or kerriganless), - LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Second Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1702, LocationType.VANILLA, + make_location_data(SC2Mission.CONVICTION.mission_name, "Second Secret Documents", SC2HOTS_LOC_ID_OFFSET + 1702, LocationType.VANILLA, lambda state: logic.two_kerrigan_actives(state) and (logic.basic_kerrigan(state) or logic.story_tech_granted) or kerriganless), - LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Power Coupling", SC2HOTS_LOC_ID_OFFSET + 1703, LocationType.EXTRA, + make_location_data(SC2Mission.CONVICTION.mission_name, "Power Coupling", SC2HOTS_LOC_ID_OFFSET + 1703, LocationType.EXTRA, lambda state: logic.two_kerrigan_actives(state) or kerriganless), - LocationData(SC2Mission.CONVICTION.mission_name, "Conviction: Door Blasted", SC2HOTS_LOC_ID_OFFSET + 1704, LocationType.EXTRA, + make_location_data(SC2Mission.CONVICTION.mission_name, "Door Blasted", SC2HOTS_LOC_ID_OFFSET + 1704, LocationType.EXTRA, lambda state: logic.two_kerrigan_actives(state) or kerriganless), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Victory", SC2HOTS_LOC_ID_OFFSET + 1800, LocationType.VICTORY, + make_location_data(SC2Mission.PLANETFALL.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1800, LocationType.VICTORY, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: East Gate", SC2HOTS_LOC_ID_OFFSET + 1801, LocationType.VANILLA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "East Gate", SC2HOTS_LOC_ID_OFFSET + 1801, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Northwest Gate", SC2HOTS_LOC_ID_OFFSET + 1802, LocationType.VANILLA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "Northwest Gate", SC2HOTS_LOC_ID_OFFSET + 1802, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: North Gate", SC2HOTS_LOC_ID_OFFSET + 1803, LocationType.VANILLA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "North Gate", SC2HOTS_LOC_ID_OFFSET + 1803, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 1 Bile Launcher Deployed", SC2HOTS_LOC_ID_OFFSET + 1804, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "1 Bile Launcher Deployed", SC2HOTS_LOC_ID_OFFSET + 1804, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 2 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1805, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "2 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1805, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 3 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1806, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "3 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1806, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 4 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1807, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "4 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1807, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: 5 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1808, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "5 Bile Launchers Deployed", SC2HOTS_LOC_ID_OFFSET + 1808, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Sons of Korhal", SC2HOTS_LOC_ID_OFFSET + 1809, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "Sons of Korhal", SC2HOTS_LOC_ID_OFFSET + 1809, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Night Wolves", SC2HOTS_LOC_ID_OFFSET + 1810, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "Night Wolves", SC2HOTS_LOC_ID_OFFSET + 1810, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: West Expansion", SC2HOTS_LOC_ID_OFFSET + 1811, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "West Expansion", SC2HOTS_LOC_ID_OFFSET + 1811, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.PLANETFALL.mission_name, "Planetfall: Mid Expansion", SC2HOTS_LOC_ID_OFFSET + 1812, LocationType.EXTRA, + make_location_data(SC2Mission.PLANETFALL.mission_name, "Mid Expansion", SC2HOTS_LOC_ID_OFFSET + 1812, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Victory", SC2HOTS_LOC_ID_OFFSET + 1900, LocationType.VICTORY, + make_location_data(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 1900, LocationType.VICTORY, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: First Power Link", SC2HOTS_LOC_ID_OFFSET + 1901, LocationType.VANILLA), - LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Second Power Link", SC2HOTS_LOC_ID_OFFSET + 1902, LocationType.VANILLA, + make_location_data(SC2Mission.DEATH_FROM_ABOVE.mission_name, "First Power Link", SC2HOTS_LOC_ID_OFFSET + 1901, LocationType.VANILLA), + make_location_data(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Second Power Link", SC2HOTS_LOC_ID_OFFSET + 1902, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Third Power Link", SC2HOTS_LOC_ID_OFFSET + 1903, LocationType.VANILLA, + make_location_data(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Third Power Link", SC2HOTS_LOC_ID_OFFSET + 1903, LocationType.VANILLA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Expansion Command Center", SC2HOTS_LOC_ID_OFFSET + 1904, LocationType.EXTRA, + make_location_data(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Expansion Command Center", SC2HOTS_LOC_ID_OFFSET + 1904, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Death From Above: Main Path Command Center", SC2HOTS_LOC_ID_OFFSET + 1905, LocationType.EXTRA, + make_location_data(SC2Mission.DEATH_FROM_ABOVE.mission_name, "Main Path Command Center", SC2HOTS_LOC_ID_OFFSET + 1905, LocationType.EXTRA, lambda state: logic.zerg_competent_comp(state) and logic.zerg_competent_anti_air(state)), - LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: Victory", SC2HOTS_LOC_ID_OFFSET + 2000, LocationType.VICTORY, + make_location_data(SC2Mission.THE_RECKONING.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 2000, LocationType.VICTORY, lambda state: logic.the_reckoning_requirement(state)), - LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: South Lane", SC2HOTS_LOC_ID_OFFSET + 2001, LocationType.VANILLA, + make_location_data(SC2Mission.THE_RECKONING.mission_name, "South Lane", SC2HOTS_LOC_ID_OFFSET + 2001, LocationType.VANILLA, lambda state: logic.the_reckoning_requirement(state)), - LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: North Lane", SC2HOTS_LOC_ID_OFFSET + 2002, LocationType.VANILLA, + make_location_data(SC2Mission.THE_RECKONING.mission_name, "North Lane", SC2HOTS_LOC_ID_OFFSET + 2002, LocationType.VANILLA, lambda state: logic.the_reckoning_requirement(state)), - LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: East Lane", SC2HOTS_LOC_ID_OFFSET + 2003, LocationType.VANILLA, + make_location_data(SC2Mission.THE_RECKONING.mission_name, "East Lane", SC2HOTS_LOC_ID_OFFSET + 2003, LocationType.VANILLA, lambda state: logic.the_reckoning_requirement(state)), - LocationData(SC2Mission.THE_RECKONING.mission_name, "The Reckoning: Odin", SC2HOTS_LOC_ID_OFFSET + 2004, LocationType.EXTRA, + make_location_data(SC2Mission.THE_RECKONING.mission_name, "Odin", SC2HOTS_LOC_ID_OFFSET + 2004, LocationType.EXTRA, lambda state: logic.the_reckoning_requirement(state)), # LotV Prologue - LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: Victory", SC2LOTV_LOC_ID_OFFSET + 100, LocationType.VICTORY, + make_location_data(SC2Mission.DARK_WHISPERS.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 100, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: First Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 101, LocationType.VANILLA, + make_location_data(SC2Mission.DARK_WHISPERS.mission_name, "First Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 101, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: Second Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 102, LocationType.VANILLA, + make_location_data(SC2Mission.DARK_WHISPERS.mission_name, "Second Prisoner Group", SC2LOTV_LOC_ID_OFFSET + 102, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: First Pylon", SC2LOTV_LOC_ID_OFFSET + 103, LocationType.VANILLA, + make_location_data(SC2Mission.DARK_WHISPERS.mission_name, "First Pylon", SC2LOTV_LOC_ID_OFFSET + 103, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.DARK_WHISPERS.mission_name, "Dark Whispers: Second Pylon", SC2LOTV_LOC_ID_OFFSET + 104, LocationType.VANILLA, + make_location_data(SC2Mission.DARK_WHISPERS.mission_name, "Second Pylon", SC2LOTV_LOC_ID_OFFSET + 104, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: Victory", SC2LOTV_LOC_ID_OFFSET + 200, LocationType.VICTORY, + make_location_data(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 200, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: South Rock Formation", SC2LOTV_LOC_ID_OFFSET + 201, LocationType.VANILLA, + make_location_data(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "South Rock Formation", SC2LOTV_LOC_ID_OFFSET + 201, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: West Rock Formation", SC2LOTV_LOC_ID_OFFSET + 202, LocationType.VANILLA, + make_location_data(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "West Rock Formation", SC2LOTV_LOC_ID_OFFSET + 202, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "Ghosts in the Fog: East Rock Formation", SC2LOTV_LOC_ID_OFFSET + 203, LocationType.VANILLA, + make_location_data(SC2Mission.GHOSTS_IN_THE_FOG.mission_name, "East Rock Formation", SC2LOTV_LOC_ID_OFFSET + 203, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) \ and logic.protoss_anti_armor_anti_air(state) \ and logic.protoss_can_attack_behind_chasm(state)), - LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Victory", SC2LOTV_LOC_ID_OFFSET + 300, LocationType.VICTORY), - LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Temple Investigated", SC2LOTV_LOC_ID_OFFSET + 301, LocationType.EXTRA), - LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Void Catalyst", SC2LOTV_LOC_ID_OFFSET + 302, LocationType.EXTRA), - LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: First Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 303, LocationType.VANILLA), - LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Second Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 304, LocationType.VANILLA), - LocationData(SC2Mission.EVIL_AWOKEN.mission_name, "Evil Awoken: Third Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 305, LocationType.VANILLA), + make_location_data(SC2Mission.EVIL_AWOKEN.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 300, LocationType.VICTORY), + make_location_data(SC2Mission.EVIL_AWOKEN.mission_name, "Temple Investigated", SC2LOTV_LOC_ID_OFFSET + 301, LocationType.EXTRA), + make_location_data(SC2Mission.EVIL_AWOKEN.mission_name, "Void Catalyst", SC2LOTV_LOC_ID_OFFSET + 302, LocationType.EXTRA), + make_location_data(SC2Mission.EVIL_AWOKEN.mission_name, "First Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 303, LocationType.VANILLA), + make_location_data(SC2Mission.EVIL_AWOKEN.mission_name, "Second Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 304, LocationType.VANILLA), + make_location_data(SC2Mission.EVIL_AWOKEN.mission_name, "Third Particle Cannon", SC2LOTV_LOC_ID_OFFSET + 305, LocationType.VANILLA), # LotV - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Victory", SC2LOTV_LOC_ID_OFFSET + 400, LocationType.VICTORY), - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Southwest Hive", SC2LOTV_LOC_ID_OFFSET + 401, LocationType.VANILLA), - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Northwest Hive", SC2LOTV_LOC_ID_OFFSET + 402, LocationType.VANILLA), - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Northeast Hive", SC2LOTV_LOC_ID_OFFSET + 403, LocationType.VANILLA), - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: East Hive", SC2LOTV_LOC_ID_OFFSET + 404, LocationType.VANILLA), - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: West Conduit", SC2LOTV_LOC_ID_OFFSET + 405, LocationType.EXTRA), - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Middle Conduit", SC2LOTV_LOC_ID_OFFSET + 406, LocationType.EXTRA), - LocationData(SC2Mission.FOR_AIUR.mission_name, "For Aiur!: Northeast Conduit", SC2LOTV_LOC_ID_OFFSET + 407, LocationType.EXTRA), - LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Victory", SC2LOTV_LOC_ID_OFFSET + 500, LocationType.VICTORY, + make_location_data(SC2Mission.FOR_AIUR.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 400, LocationType.VICTORY), + make_location_data(SC2Mission.FOR_AIUR.mission_name, "Southwest Hive", SC2LOTV_LOC_ID_OFFSET + 401, LocationType.VANILLA), + make_location_data(SC2Mission.FOR_AIUR.mission_name, "Northwest Hive", SC2LOTV_LOC_ID_OFFSET + 402, LocationType.VANILLA), + make_location_data(SC2Mission.FOR_AIUR.mission_name, "Northeast Hive", SC2LOTV_LOC_ID_OFFSET + 403, LocationType.VANILLA), + make_location_data(SC2Mission.FOR_AIUR.mission_name, "East Hive", SC2LOTV_LOC_ID_OFFSET + 404, LocationType.VANILLA), + make_location_data(SC2Mission.FOR_AIUR.mission_name, "West Conduit", SC2LOTV_LOC_ID_OFFSET + 405, LocationType.EXTRA), + make_location_data(SC2Mission.FOR_AIUR.mission_name, "Middle Conduit", SC2LOTV_LOC_ID_OFFSET + 406, LocationType.EXTRA), + make_location_data(SC2Mission.FOR_AIUR.mission_name, "Northeast Conduit", SC2LOTV_LOC_ID_OFFSET + 407, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GROWING_SHADOW.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 500, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Close Pylon", SC2LOTV_LOC_ID_OFFSET + 501, LocationType.VANILLA), - LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: East Pylon", SC2LOTV_LOC_ID_OFFSET + 502, LocationType.VANILLA, + make_location_data(SC2Mission.THE_GROWING_SHADOW.mission_name, "Close Pylon", SC2LOTV_LOC_ID_OFFSET + 501, LocationType.VANILLA), + make_location_data(SC2Mission.THE_GROWING_SHADOW.mission_name, "East Pylon", SC2LOTV_LOC_ID_OFFSET + 502, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: West Pylon", SC2LOTV_LOC_ID_OFFSET + 503, LocationType.VANILLA, + make_location_data(SC2Mission.THE_GROWING_SHADOW.mission_name, "West Pylon", SC2LOTV_LOC_ID_OFFSET + 503, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Nexus", SC2LOTV_LOC_ID_OFFSET + 504, LocationType.EXTRA), - LocationData(SC2Mission.THE_GROWING_SHADOW.mission_name, "The Growing Shadow: Templar Base", SC2LOTV_LOC_ID_OFFSET + 505, LocationType.EXTRA, + make_location_data(SC2Mission.THE_GROWING_SHADOW.mission_name, "Nexus", SC2LOTV_LOC_ID_OFFSET + 504, LocationType.EXTRA), + make_location_data(SC2Mission.THE_GROWING_SHADOW.mission_name, "Templar Base", SC2LOTV_LOC_ID_OFFSET + 505, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: Victory", SC2LOTV_LOC_ID_OFFSET + 600, LocationType.VICTORY, + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 600, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: Close Warp Gate", SC2LOTV_LOC_ID_OFFSET + 601, LocationType.VANILLA), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: West Warp Gate", SC2LOTV_LOC_ID_OFFSET + 602, LocationType.VANILLA, + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "Close Warp Gate", SC2LOTV_LOC_ID_OFFSET + 601, LocationType.VANILLA), + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "West Warp Gate", SC2LOTV_LOC_ID_OFFSET + 602, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: North Warp Gate", SC2LOTV_LOC_ID_OFFSET + 603, LocationType.VANILLA, + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "North Warp Gate", SC2LOTV_LOC_ID_OFFSET + 603, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: North Power Cell", SC2LOTV_LOC_ID_OFFSET + 604, LocationType.EXTRA, + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "North Power Cell", SC2LOTV_LOC_ID_OFFSET + 604, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: East Power Cell", SC2LOTV_LOC_ID_OFFSET + 605, LocationType.EXTRA, + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "East Power Cell", SC2LOTV_LOC_ID_OFFSET + 605, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: South Power Cell", SC2LOTV_LOC_ID_OFFSET + 606, LocationType.EXTRA, + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "South Power Cell", SC2LOTV_LOC_ID_OFFSET + 606, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "The Spear of Adun: Southeast Power Cell", SC2LOTV_LOC_ID_OFFSET + 607, LocationType.EXTRA, + make_location_data(SC2Mission.THE_SPEAR_OF_ADUN.mission_name, "Southeast Power Cell", SC2LOTV_LOC_ID_OFFSET + 607, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Victory", SC2LOTV_LOC_ID_OFFSET + 700, LocationType.VICTORY, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 700, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Mid EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 701, LocationType.VANILLA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Mid EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 701, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Southeast EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 702, LocationType.VANILLA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Southeast EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 702, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: North EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 703, LocationType.VANILLA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "North EMP Scrambler", SC2LOTV_LOC_ID_OFFSET + 703, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Mid Stabilizer", SC2LOTV_LOC_ID_OFFSET + 704, LocationType.EXTRA), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Southwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 705, LocationType.EXTRA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Mid Stabilizer", SC2LOTV_LOC_ID_OFFSET + 704, LocationType.EXTRA), + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Southwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 705, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Northwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 706, LocationType.EXTRA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Northwest Stabilizer", SC2LOTV_LOC_ID_OFFSET + 706, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Northeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 707, LocationType.EXTRA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Northeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 707, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: Southeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 708, LocationType.EXTRA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "Southeast Stabilizer", SC2LOTV_LOC_ID_OFFSET + 708, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: West Raynor Base", SC2LOTV_LOC_ID_OFFSET + 709, LocationType.EXTRA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "West Raynor Base", SC2LOTV_LOC_ID_OFFSET + 709, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.SKY_SHIELD.mission_name, "Sky Shield: East Raynor Base", SC2LOTV_LOC_ID_OFFSET + 710, LocationType.EXTRA, + make_location_data(SC2Mission.SKY_SHIELD.mission_name, "East Raynor Base", SC2LOTV_LOC_ID_OFFSET + 710, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_basic_anti_air(state)), - LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: Victory", SC2LOTV_LOC_ID_OFFSET + 800, LocationType.VICTORY, + make_location_data(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 800, LocationType.VICTORY, lambda state: logic.brothers_in_arms_requirement(state)), - LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: Mid Science Facility", SC2LOTV_LOC_ID_OFFSET + 801, LocationType.VANILLA, + make_location_data(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Mid Science Facility", SC2LOTV_LOC_ID_OFFSET + 801, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) or logic.take_over_ai_allies), - LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: North Science Facility", SC2LOTV_LOC_ID_OFFSET + 802, LocationType.VANILLA, + make_location_data(SC2Mission.BROTHERS_IN_ARMS.mission_name, "North Science Facility", SC2LOTV_LOC_ID_OFFSET + 802, LocationType.VANILLA, lambda state: logic.brothers_in_arms_requirement(state) or logic.take_over_ai_allies and logic.advanced_tactics @@ -1195,544 +1205,544 @@ def get_locations(world: Optional['SC2World']) -> Tuple[LocationData, ...]: or logic.protoss_common_unit(state) ) ), - LocationData(SC2Mission.BROTHERS_IN_ARMS.mission_name, "Brothers in Arms: South Science Facility", SC2LOTV_LOC_ID_OFFSET + 803, LocationType.VANILLA, + make_location_data(SC2Mission.BROTHERS_IN_ARMS.mission_name, "South Science Facility", SC2LOTV_LOC_ID_OFFSET + 803, LocationType.VANILLA, lambda state: logic.brothers_in_arms_requirement(state)), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: Victory", SC2LOTV_LOC_ID_OFFSET + 900, LocationType.VICTORY, + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 900, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: Close Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 901, LocationType.VANILLA), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: North Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 902, LocationType.VANILLA, + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "Close Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 901, LocationType.VANILLA), + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "North Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 902, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: East Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 903, LocationType.VANILLA, + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "East Solarite Reserve", SC2LOTV_LOC_ID_OFFSET + 903, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: West Launch Bay", SC2LOTV_LOC_ID_OFFSET + 904, LocationType.EXTRA, + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "West Launch Bay", SC2LOTV_LOC_ID_OFFSET + 904, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: South Launch Bay", SC2LOTV_LOC_ID_OFFSET + 905, LocationType.EXTRA, + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "South Launch Bay", SC2LOTV_LOC_ID_OFFSET + 905, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: Northwest Launch Bay", SC2LOTV_LOC_ID_OFFSET + 906, LocationType.EXTRA, + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "Northwest Launch Bay", SC2LOTV_LOC_ID_OFFSET + 906, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.AMON_S_REACH.mission_name, "Amon's Reach: East Launch Bay", SC2LOTV_LOC_ID_OFFSET + 907, LocationType.EXTRA, + make_location_data(SC2Mission.AMON_S_REACH.mission_name, "East Launch Bay", SC2LOTV_LOC_ID_OFFSET + 907, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: Victory", SC2LOTV_LOC_ID_OFFSET + 1000, LocationType.VICTORY, + make_location_data(SC2Mission.LAST_STAND.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1000, LocationType.VICTORY, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: West Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1001, LocationType.VANILLA, + make_location_data(SC2Mission.LAST_STAND.mission_name, "West Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1001, LocationType.VANILLA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: North Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1002, LocationType.VANILLA, + make_location_data(SC2Mission.LAST_STAND.mission_name, "North Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1002, LocationType.VANILLA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: East Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1003, LocationType.VANILLA, + make_location_data(SC2Mission.LAST_STAND.mission_name, "East Zenith Stone", SC2LOTV_LOC_ID_OFFSET + 1003, LocationType.VANILLA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: 1 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1004, LocationType.EXTRA, + make_location_data(SC2Mission.LAST_STAND.mission_name, "1 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1004, LocationType.EXTRA, lambda state: logic.last_stand_requirement(state)), - LocationData(SC2Mission.LAST_STAND.mission_name, "Last Stand: 1.5 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1005, LocationType.VANILLA, + make_location_data(SC2Mission.LAST_STAND.mission_name, "1.5 Billion Zerg", SC2LOTV_LOC_ID_OFFSET + 1005, LocationType.VANILLA, lambda state: logic.last_stand_requirement(state) and ( state.has_all({item_names.KHAYDARIN_MONOLITH, item_names.PHOTON_CANNON, item_names.SHIELD_BATTERY}, player) or state.has_any({item_names.SOA_SOLAR_LANCE, item_names.SOA_DEPLOY_FENIX}, player) )), - LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: Victory", SC2LOTV_LOC_ID_OFFSET + 1100, LocationType.VICTORY, + make_location_data(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1100, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: South Solarite", SC2LOTV_LOC_ID_OFFSET + 1101, LocationType.VANILLA, + make_location_data(SC2Mission.FORBIDDEN_WEAPON.mission_name, "South Solarite", SC2LOTV_LOC_ID_OFFSET + 1101, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: North Solarite", SC2LOTV_LOC_ID_OFFSET + 1102, LocationType.VANILLA, + make_location_data(SC2Mission.FORBIDDEN_WEAPON.mission_name, "North Solarite", SC2LOTV_LOC_ID_OFFSET + 1102, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Forbidden Weapon: Northwest Solarite", SC2LOTV_LOC_ID_OFFSET + 1103, LocationType.VANILLA, + make_location_data(SC2Mission.FORBIDDEN_WEAPON.mission_name, "Northwest Solarite", SC2LOTV_LOC_ID_OFFSET + 1103, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: Victory", SC2LOTV_LOC_ID_OFFSET + 1200, LocationType.VICTORY, + make_location_data(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1200, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: Mid Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1201, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Mid Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1201, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: West Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1202, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "West Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1202, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: South Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1203, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "South Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1203, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: East Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1204, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "East Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1204, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: North Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1205, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "North Celestial Lock", SC2LOTV_LOC_ID_OFFSET + 1205, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Temple of Unification: Titanic Warp Prism", SC2LOTV_LOC_ID_OFFSET + 1206, LocationType.VANILLA, + make_location_data(SC2Mission.TEMPLE_OF_UNIFICATION.mission_name, "Titanic Warp Prism", SC2LOTV_LOC_ID_OFFSET + 1206, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and logic.protoss_anti_armor_anti_air(state)), - LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Victory", SC2LOTV_LOC_ID_OFFSET + 1300, LocationType.VICTORY, + make_location_data(SC2Mission.THE_INFINITE_CYCLE.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1300, LocationType.VICTORY, lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: First Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1301, LocationType.EXTRA, + make_location_data(SC2Mission.THE_INFINITE_CYCLE.mission_name, "First Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1301, LocationType.EXTRA, lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Second Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1302, LocationType.EXTRA, + make_location_data(SC2Mission.THE_INFINITE_CYCLE.mission_name, "Second Hall of Revelation", SC2LOTV_LOC_ID_OFFSET + 1302, LocationType.EXTRA, lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: First Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1303, LocationType.VANILLA, + make_location_data(SC2Mission.THE_INFINITE_CYCLE.mission_name, "First Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1303, LocationType.VANILLA, lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Second Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1304, LocationType.VANILLA, + make_location_data(SC2Mission.THE_INFINITE_CYCLE.mission_name, "Second Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1304, LocationType.VANILLA, lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData(SC2Mission.THE_INFINITE_CYCLE.mission_name, "The Infinite Cycle: Third Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1305, LocationType.VANILLA, + make_location_data(SC2Mission.THE_INFINITE_CYCLE.mission_name, "Third Xel'Naga Device", SC2LOTV_LOC_ID_OFFSET + 1305, LocationType.VANILLA, lambda state: logic.the_infinite_cycle_requirement(state)), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Victory", SC2LOTV_LOC_ID_OFFSET + 1400, LocationType.VICTORY, + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1400, LocationType.VICTORY, lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Artanis", SC2LOTV_LOC_ID_OFFSET + 1401, LocationType.EXTRA), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Northwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1402, LocationType.EXTRA, + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Artanis", SC2LOTV_LOC_ID_OFFSET + 1401, LocationType.EXTRA), + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Northwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1402, LocationType.EXTRA, lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Northeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1403, LocationType.EXTRA, + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Northeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1403, LocationType.EXTRA, lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Southwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1404, LocationType.EXTRA, + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Southwest Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1404, LocationType.EXTRA, lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Southeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1405, LocationType.EXTRA, + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Southeast Void Crystal", SC2LOTV_LOC_ID_OFFSET + 1405, LocationType.EXTRA, lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: South Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1406, LocationType.VANILLA), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: Mid Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1407, LocationType.VANILLA, + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "South Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1406, LocationType.VANILLA), + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Mid Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1407, LocationType.VANILLA, lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "Harbinger of Oblivion: North Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1408, LocationType.VANILLA, + make_location_data(SC2Mission.HARBINGER_OF_OBLIVION.mission_name, "North Xel'Naga Vessel", SC2LOTV_LOC_ID_OFFSET + 1408, LocationType.VANILLA, lambda state: logic.harbinger_of_oblivion_requirement(state)), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Victory", SC2LOTV_LOC_ID_OFFSET + 1500, LocationType.VICTORY, + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1500, LocationType.VICTORY, lambda state: logic.protoss_basic_splash(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Zerg Cleared", SC2LOTV_LOC_ID_OFFSET + 1501, LocationType.EXTRA), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: First Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1502, LocationType.EXTRA, + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "Zerg Cleared", SC2LOTV_LOC_ID_OFFSET + 1501, LocationType.EXTRA), + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "First Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1502, LocationType.EXTRA, lambda state: logic.advanced_tactics \ or logic.protoss_basic_splash(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Second Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1503, LocationType.EXTRA, + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "Second Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1503, LocationType.EXTRA, lambda state: logic.protoss_basic_splash(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Third Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1504, LocationType.EXTRA, + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "Third Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1504, LocationType.EXTRA, lambda state: logic.protoss_basic_splash(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: Fourth Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1505, LocationType.EXTRA, + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "Fourth Stasis Lock", SC2LOTV_LOC_ID_OFFSET + 1505, LocationType.EXTRA, lambda state: logic.protoss_basic_splash(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: South Power Core", SC2LOTV_LOC_ID_OFFSET + 1506, LocationType.VANILLA, + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "South Power Core", SC2LOTV_LOC_ID_OFFSET + 1506, LocationType.VANILLA, lambda state: logic.protoss_basic_splash(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.UNSEALING_THE_PAST.mission_name, "Unsealing the Past: East Power Core", SC2LOTV_LOC_ID_OFFSET + 1507, LocationType.VANILLA, + make_location_data(SC2Mission.UNSEALING_THE_PAST.mission_name, "East Power Core", SC2LOTV_LOC_ID_OFFSET + 1507, LocationType.VANILLA, lambda state: logic.protoss_basic_splash(state) and logic.protoss_anti_light_anti_air(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: Victory", SC2LOTV_LOC_ID_OFFSET + 1600, LocationType.VICTORY, + make_location_data(SC2Mission.PURIFICATION.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1600, LocationType.VICTORY, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: North Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1601, LocationType.VANILLA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "North Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1601, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: North Sector: Northeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1602, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "North Sector: Northeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1602, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: North Sector: Southeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1603, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "North Sector: Southeast Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1603, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: South Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1604, LocationType.VANILLA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "South Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1604, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: South Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1605, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "South Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1605, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: South Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1606, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "South Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1606, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: West Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1607, LocationType.VANILLA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "West Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1607, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: West Sector: Mid Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1608, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "West Sector: Mid Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1608, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: West Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1609, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "West Sector: East Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1609, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: East Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1610, LocationType.VANILLA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "East Sector: North Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1610, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: East Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1611, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "East Sector: West Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1611, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: East Sector: South Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1612, LocationType.EXTRA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "East Sector: South Null Circuit", SC2LOTV_LOC_ID_OFFSET + 1612, LocationType.EXTRA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.PURIFICATION.mission_name, "Purification: Purifier Warden", SC2LOTV_LOC_ID_OFFSET + 1613, LocationType.VANILLA, + make_location_data(SC2Mission.PURIFICATION.mission_name, "Purifier Warden", SC2LOTV_LOC_ID_OFFSET + 1613, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Victory", SC2LOTV_LOC_ID_OFFSET + 1700, LocationType.VICTORY, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1700, LocationType.VICTORY, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: First Terrazine Fog", SC2LOTV_LOC_ID_OFFSET + 1701, LocationType.EXTRA, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "First Terrazine Fog", SC2LOTV_LOC_ID_OFFSET + 1701, LocationType.EXTRA, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Southwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1702, LocationType.EXTRA, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Southwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1702, LocationType.EXTRA, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: West Guardian", SC2LOTV_LOC_ID_OFFSET + 1703, LocationType.EXTRA, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "West Guardian", SC2LOTV_LOC_ID_OFFSET + 1703, LocationType.EXTRA, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Northwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1704, LocationType.EXTRA, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Northwest Guardian", SC2LOTV_LOC_ID_OFFSET + 1704, LocationType.EXTRA, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: Northeast Guardian", SC2LOTV_LOC_ID_OFFSET + 1705, LocationType.EXTRA, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Northeast Guardian", SC2LOTV_LOC_ID_OFFSET + 1705, LocationType.EXTRA, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: North Mothership", SC2LOTV_LOC_ID_OFFSET + 1706, LocationType.VANILLA, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "North Mothership", SC2LOTV_LOC_ID_OFFSET + 1706, LocationType.VANILLA, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.STEPS_OF_THE_RITE.mission_name, "Steps of the Rite: South Mothership", SC2LOTV_LOC_ID_OFFSET + 1707, LocationType.VANILLA, + make_location_data(SC2Mission.STEPS_OF_THE_RITE.mission_name, "South Mothership", SC2LOTV_LOC_ID_OFFSET + 1707, LocationType.VANILLA, lambda state: logic.steps_of_the_rite_requirement(state)), - LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: Victory", SC2LOTV_LOC_ID_OFFSET + 1800, LocationType.VICTORY, + make_location_data(SC2Mission.RAK_SHIR.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1800, LocationType.VICTORY, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: North Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1801, LocationType.VANILLA, + make_location_data(SC2Mission.RAK_SHIR.mission_name, "North Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1801, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: Southwest Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1802, LocationType.VANILLA, + make_location_data(SC2Mission.RAK_SHIR.mission_name, "Southwest Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1802, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.RAK_SHIR.mission_name, "Rak'Shir: East Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1803, LocationType.VANILLA, + make_location_data(SC2Mission.RAK_SHIR.mission_name, "East Slayn Elemental", SC2LOTV_LOC_ID_OFFSET + 1803, LocationType.VANILLA, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Victory", SC2LOTV_LOC_ID_OFFSET + 1900, LocationType.VICTORY, + make_location_data(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 1900, LocationType.VICTORY, lambda state: logic.templars_charge_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Northwest Power Core", SC2LOTV_LOC_ID_OFFSET + 1901, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Northwest Power Core", SC2LOTV_LOC_ID_OFFSET + 1901, LocationType.EXTRA, lambda state: logic.templars_charge_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Northeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1902, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Northeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1902, LocationType.EXTRA, lambda state: logic.templars_charge_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Southeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1903, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Southeast Power Core", SC2LOTV_LOC_ID_OFFSET + 1903, LocationType.EXTRA, lambda state: logic.templars_charge_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: West Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1904, LocationType.VANILLA, + make_location_data(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "West Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1904, LocationType.VANILLA, lambda state: logic.templars_charge_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Templar's Charge: Southeast Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1905, LocationType.VANILLA, + make_location_data(SC2Mission.TEMPLAR_S_CHARGE.mission_name, "Southeast Hybrid Stasis Chamber", SC2LOTV_LOC_ID_OFFSET + 1905, LocationType.VANILLA, lambda state: logic.protoss_fleet(state)), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Victory", SC2LOTV_LOC_ID_OFFSET + 2000, LocationType.VICTORY, + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 2000, LocationType.VICTORY, lambda state: logic.templars_return_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Citadel: First Gate", SC2LOTV_LOC_ID_OFFSET + 2001, LocationType.EXTRA), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Citadel: Second Gate", SC2LOTV_LOC_ID_OFFSET + 2002, LocationType.EXTRA), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Citadel: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2003, LocationType.VANILLA), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Temple Grounds: Gather Army", SC2LOTV_LOC_ID_OFFSET + 2004, LocationType.VANILLA, + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Citadel: First Gate", SC2LOTV_LOC_ID_OFFSET + 2001, LocationType.EXTRA), + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Citadel: Second Gate", SC2LOTV_LOC_ID_OFFSET + 2002, LocationType.EXTRA), + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Citadel: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2003, LocationType.VANILLA), + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Temple Grounds: Gather Army", SC2LOTV_LOC_ID_OFFSET + 2004, LocationType.VANILLA, lambda state: logic.templars_return_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Temple Grounds: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2005, LocationType.VANILLA, + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Temple Grounds: Power Structure", SC2LOTV_LOC_ID_OFFSET + 2005, LocationType.VANILLA, lambda state: logic.templars_return_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Caverns: Purifier", SC2LOTV_LOC_ID_OFFSET + 2006, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Caverns: Purifier", SC2LOTV_LOC_ID_OFFSET + 2006, LocationType.EXTRA, lambda state: logic.templars_return_requirement(state)), - LocationData(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Templar's Return: Caverns: Dark Templar", SC2LOTV_LOC_ID_OFFSET + 2007, LocationType.EXTRA, + make_location_data(SC2Mission.TEMPLAR_S_RETURN.mission_name, "Caverns: Dark Templar", SC2LOTV_LOC_ID_OFFSET + 2007, LocationType.EXTRA, lambda state: logic.templars_return_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Victory", SC2LOTV_LOC_ID_OFFSET + 2100, LocationType.VICTORY, + make_location_data(SC2Mission.THE_HOST.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 2100, LocationType.VICTORY, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Southeast Void Shard", SC2LOTV_LOC_ID_OFFSET + 2101, LocationType.VICTORY, + make_location_data(SC2Mission.THE_HOST.mission_name, "Southeast Void Shard", SC2LOTV_LOC_ID_OFFSET + 2101, LocationType.VICTORY, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: South Void Shard", SC2LOTV_LOC_ID_OFFSET + 2102, LocationType.EXTRA, + make_location_data(SC2Mission.THE_HOST.mission_name, "South Void Shard", SC2LOTV_LOC_ID_OFFSET + 2102, LocationType.EXTRA, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Southwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2103, LocationType.EXTRA, + make_location_data(SC2Mission.THE_HOST.mission_name, "Southwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2103, LocationType.EXTRA, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: North Void Shard", SC2LOTV_LOC_ID_OFFSET + 2104, LocationType.EXTRA, + make_location_data(SC2Mission.THE_HOST.mission_name, "North Void Shard", SC2LOTV_LOC_ID_OFFSET + 2104, LocationType.EXTRA, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Northwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2105, LocationType.EXTRA, + make_location_data(SC2Mission.THE_HOST.mission_name, "Northwest Void Shard", SC2LOTV_LOC_ID_OFFSET + 2105, LocationType.EXTRA, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Nerazim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2106, LocationType.VANILLA, + make_location_data(SC2Mission.THE_HOST.mission_name, "Nerazim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2106, LocationType.VANILLA, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Tal'darim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2107, LocationType.VANILLA, + make_location_data(SC2Mission.THE_HOST.mission_name, "Tal'darim Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2107, LocationType.VANILLA, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.THE_HOST.mission_name, "The Host: Purifier Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2108, LocationType.VANILLA, + make_location_data(SC2Mission.THE_HOST.mission_name, "Purifier Warp in Zone", SC2LOTV_LOC_ID_OFFSET + 2108, LocationType.VANILLA, lambda state: logic.the_host_requirement(state)), - LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Victory", SC2LOTV_LOC_ID_OFFSET + 2200, LocationType.VICTORY, + make_location_data(SC2Mission.SALVATION.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 2200, LocationType.VICTORY, lambda state: logic.salvation_requirement(state)), - LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Fabrication Matrix", SC2LOTV_LOC_ID_OFFSET + 2201, LocationType.EXTRA, + make_location_data(SC2Mission.SALVATION.mission_name, "Fabrication Matrix", SC2LOTV_LOC_ID_OFFSET + 2201, LocationType.EXTRA, lambda state: logic.salvation_requirement(state)), - LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Assault Cluster", SC2LOTV_LOC_ID_OFFSET + 2202, LocationType.EXTRA, + make_location_data(SC2Mission.SALVATION.mission_name, "Assault Cluster", SC2LOTV_LOC_ID_OFFSET + 2202, LocationType.EXTRA, lambda state: logic.salvation_requirement(state)), - LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Hull Breach", SC2LOTV_LOC_ID_OFFSET + 2203, LocationType.EXTRA, + make_location_data(SC2Mission.SALVATION.mission_name, "Hull Breach", SC2LOTV_LOC_ID_OFFSET + 2203, LocationType.EXTRA, lambda state: logic.salvation_requirement(state)), - LocationData(SC2Mission.SALVATION.mission_name, "Salvation: Core Critical", SC2LOTV_LOC_ID_OFFSET + 2204, LocationType.EXTRA, + make_location_data(SC2Mission.SALVATION.mission_name, "Core Critical", SC2LOTV_LOC_ID_OFFSET + 2204, LocationType.EXTRA, lambda state: logic.salvation_requirement(state)), # Epilogue - LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Victory", SC2LOTV_LOC_ID_OFFSET + 2300, LocationType.VICTORY, + make_location_data(SC2Mission.INTO_THE_VOID.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 2300, LocationType.VICTORY, lambda state: logic.into_the_void_requirement(state)), - LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Corruption Source", SC2LOTV_LOC_ID_OFFSET + 2301, LocationType.EXTRA), - LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Southwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2302, LocationType.VANILLA, + make_location_data(SC2Mission.INTO_THE_VOID.mission_name, "Corruption Source", SC2LOTV_LOC_ID_OFFSET + 2301, LocationType.EXTRA), + make_location_data(SC2Mission.INTO_THE_VOID.mission_name, "Southwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2302, LocationType.VANILLA, lambda state: logic.into_the_void_requirement(state)), - LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Northwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2303, LocationType.VANILLA, + make_location_data(SC2Mission.INTO_THE_VOID.mission_name, "Northwest Forward Position", SC2LOTV_LOC_ID_OFFSET + 2303, LocationType.VANILLA, lambda state: logic.into_the_void_requirement(state)), - LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Southeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2304, LocationType.VANILLA, + make_location_data(SC2Mission.INTO_THE_VOID.mission_name, "Southeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2304, LocationType.VANILLA, lambda state: logic.into_the_void_requirement(state)), - LocationData(SC2Mission.INTO_THE_VOID.mission_name, "Into the Void: Northeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2305, LocationType.VANILLA), - LocationData(SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, "The Essence of Eternity: Victory", SC2LOTV_LOC_ID_OFFSET + 2400, LocationType.VICTORY, + make_location_data(SC2Mission.INTO_THE_VOID.mission_name, "Northeast Forward Position", SC2LOTV_LOC_ID_OFFSET + 2305, LocationType.VANILLA), + make_location_data(SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 2400, LocationType.VICTORY, lambda state: logic.essence_of_eternity_requirement(state)), - LocationData(SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, "The Essence of Eternity: Void Trashers", SC2LOTV_LOC_ID_OFFSET + 2401, LocationType.EXTRA), - LocationData(SC2Mission.AMON_S_FALL.mission_name, "Amon's Fall: Victory", SC2LOTV_LOC_ID_OFFSET + 2500, LocationType.VICTORY, + make_location_data(SC2Mission.THE_ESSENCE_OF_ETERNITY.mission_name, "Void Trashers", SC2LOTV_LOC_ID_OFFSET + 2401, LocationType.EXTRA), + make_location_data(SC2Mission.AMON_S_FALL.mission_name, "Victory", SC2LOTV_LOC_ID_OFFSET + 2500, LocationType.VICTORY, lambda state: logic.amons_fall_requirement(state)), # Nova Covert Ops - LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Victory", SC2NCO_LOC_ID_OFFSET + 100, LocationType.VICTORY, + make_location_data(SC2Mission.THE_ESCAPE.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 100, LocationType.VICTORY, lambda state: logic.the_escape_requirement(state)), - LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Rifle", SC2NCO_LOC_ID_OFFSET + 101, LocationType.VANILLA, + make_location_data(SC2Mission.THE_ESCAPE.mission_name, "Rifle", SC2NCO_LOC_ID_OFFSET + 101, LocationType.VANILLA, lambda state: logic.the_escape_first_stage_requirement(state)), - LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Grenades", SC2NCO_LOC_ID_OFFSET + 102, LocationType.VANILLA, + make_location_data(SC2Mission.THE_ESCAPE.mission_name, "Grenades", SC2NCO_LOC_ID_OFFSET + 102, LocationType.VANILLA, lambda state: logic.the_escape_first_stage_requirement(state)), - LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Agent Delta", SC2NCO_LOC_ID_OFFSET + 103, LocationType.VANILLA, + make_location_data(SC2Mission.THE_ESCAPE.mission_name, "Agent Delta", SC2NCO_LOC_ID_OFFSET + 103, LocationType.VANILLA, lambda state: logic.the_escape_requirement(state)), - LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Agent Pierce", SC2NCO_LOC_ID_OFFSET + 104, LocationType.VANILLA, + make_location_data(SC2Mission.THE_ESCAPE.mission_name, "Agent Pierce", SC2NCO_LOC_ID_OFFSET + 104, LocationType.VANILLA, lambda state: logic.the_escape_requirement(state)), - LocationData(SC2Mission.THE_ESCAPE.mission_name, "The Escape: Agent Stone", SC2NCO_LOC_ID_OFFSET + 105, LocationType.VANILLA, + make_location_data(SC2Mission.THE_ESCAPE.mission_name, "Agent Stone", SC2NCO_LOC_ID_OFFSET + 105, LocationType.VANILLA, lambda state: logic.the_escape_requirement(state)), - LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Victory", SC2NCO_LOC_ID_OFFSET + 200, LocationType.VICTORY, + make_location_data(SC2Mission.SUDDEN_STRIKE.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 200, LocationType.VICTORY, lambda state: logic.sudden_strike_can_reach_objectives(state)), - LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Research Center", SC2NCO_LOC_ID_OFFSET + 201, LocationType.VANILLA, + make_location_data(SC2Mission.SUDDEN_STRIKE.mission_name, "Research Center", SC2NCO_LOC_ID_OFFSET + 201, LocationType.VANILLA, lambda state: logic.sudden_strike_can_reach_objectives(state)), - LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Weaponry Labs", SC2NCO_LOC_ID_OFFSET + 202, LocationType.VANILLA, + make_location_data(SC2Mission.SUDDEN_STRIKE.mission_name, "Weaponry Labs", SC2NCO_LOC_ID_OFFSET + 202, LocationType.VANILLA, lambda state: logic.sudden_strike_requirement(state)), - LocationData(SC2Mission.SUDDEN_STRIKE.mission_name, "Sudden Strike: Brutalisk", SC2NCO_LOC_ID_OFFSET + 203, LocationType.EXTRA, + make_location_data(SC2Mission.SUDDEN_STRIKE.mission_name, "Brutalisk", SC2NCO_LOC_ID_OFFSET + 203, LocationType.EXTRA, lambda state: logic.sudden_strike_requirement(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Victory", SC2NCO_LOC_ID_OFFSET + 300, LocationType.VICTORY, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 300, LocationType.VICTORY, lambda state: logic.enemy_intelligence_third_stage_requirement(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: West Garrison", SC2NCO_LOC_ID_OFFSET + 301, LocationType.EXTRA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "West Garrison", SC2NCO_LOC_ID_OFFSET + 301, LocationType.EXTRA, lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Close Garrison", SC2NCO_LOC_ID_OFFSET + 302, LocationType.EXTRA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Close Garrison", SC2NCO_LOC_ID_OFFSET + 302, LocationType.EXTRA, lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Northeast Garrison", SC2NCO_LOC_ID_OFFSET + 303, LocationType.EXTRA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Northeast Garrison", SC2NCO_LOC_ID_OFFSET + 303, LocationType.EXTRA, lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Southeast Garrison", SC2NCO_LOC_ID_OFFSET + 304, LocationType.EXTRA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Southeast Garrison", SC2NCO_LOC_ID_OFFSET + 304, LocationType.EXTRA, lambda state: logic.enemy_intelligence_first_stage_requirement(state) and logic.enemy_intelligence_cliff_garrison(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: South Garrison", SC2NCO_LOC_ID_OFFSET + 305, LocationType.EXTRA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "South Garrison", SC2NCO_LOC_ID_OFFSET + 305, LocationType.EXTRA, lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: All Garrisons", SC2NCO_LOC_ID_OFFSET + 306, LocationType.VANILLA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "All Garrisons", SC2NCO_LOC_ID_OFFSET + 306, LocationType.VANILLA, lambda state: logic.enemy_intelligence_first_stage_requirement(state) and logic.enemy_intelligence_cliff_garrison(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Forces Rescued", SC2NCO_LOC_ID_OFFSET + 307, LocationType.VANILLA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Forces Rescued", SC2NCO_LOC_ID_OFFSET + 307, LocationType.VANILLA, lambda state: logic.enemy_intelligence_first_stage_requirement(state)), - LocationData(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Enemy Intelligence: Communications Hub", SC2NCO_LOC_ID_OFFSET + 308, LocationType.VANILLA, + make_location_data(SC2Mission.ENEMY_INTELLIGENCE.mission_name, "Communications Hub", SC2NCO_LOC_ID_OFFSET + 308, LocationType.VANILLA, lambda state: logic.enemy_intelligence_second_stage_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: Victory", SC2NCO_LOC_ID_OFFSET + 400, LocationType.VICTORY, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 400, LocationType.VICTORY, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Base: West Hatchery", SC2NCO_LOC_ID_OFFSET + 401, LocationType.VANILLA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "North Base: West Hatchery", SC2NCO_LOC_ID_OFFSET + 401, LocationType.VANILLA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Base: North Hatchery", SC2NCO_LOC_ID_OFFSET + 402, LocationType.VANILLA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "North Base: North Hatchery", SC2NCO_LOC_ID_OFFSET + 402, LocationType.VANILLA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 403, LocationType.VANILLA), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Base: Northwest Hatchery", SC2NCO_LOC_ID_OFFSET + 404, LocationType.VANILLA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "North Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 403, LocationType.VANILLA), + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "South Base: Northwest Hatchery", SC2NCO_LOC_ID_OFFSET + 404, LocationType.VANILLA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Base: Southwest Hatchery", SC2NCO_LOC_ID_OFFSET + 405, LocationType.VANILLA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "South Base: Southwest Hatchery", SC2NCO_LOC_ID_OFFSET + 405, LocationType.VANILLA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 406, LocationType.VANILLA), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: North Shield Projector", SC2NCO_LOC_ID_OFFSET + 407, LocationType.EXTRA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "South Base: East Hatchery", SC2NCO_LOC_ID_OFFSET + 406, LocationType.VANILLA), + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "North Shield Projector", SC2NCO_LOC_ID_OFFSET + 407, LocationType.EXTRA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: East Shield Projector", SC2NCO_LOC_ID_OFFSET + 408, LocationType.EXTRA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "East Shield Projector", SC2NCO_LOC_ID_OFFSET + 408, LocationType.EXTRA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: South Shield Projector", SC2NCO_LOC_ID_OFFSET + 409, LocationType.EXTRA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "South Shield Projector", SC2NCO_LOC_ID_OFFSET + 409, LocationType.EXTRA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: West Shield Projector", SC2NCO_LOC_ID_OFFSET + 410, LocationType.EXTRA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "West Shield Projector", SC2NCO_LOC_ID_OFFSET + 410, LocationType.EXTRA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Trouble In Paradise: Fleet Beacon", SC2NCO_LOC_ID_OFFSET + 411, LocationType.VANILLA, + make_location_data(SC2Mission.TROUBLE_IN_PARADISE.mission_name, "Fleet Beacon", SC2NCO_LOC_ID_OFFSET + 411, LocationType.VANILLA, lambda state: logic.trouble_in_paradise_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Victory", SC2NCO_LOC_ID_OFFSET + 500, LocationType.VICTORY, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 500, LocationType.VICTORY, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 1 Terrazine Node Collected", SC2NCO_LOC_ID_OFFSET + 501, LocationType.EXTRA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "1 Terrazine Node Collected", SC2NCO_LOC_ID_OFFSET + 501, LocationType.EXTRA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 2 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 502, LocationType.EXTRA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "2 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 502, LocationType.EXTRA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 3 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 503, LocationType.EXTRA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "3 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 503, LocationType.EXTRA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 4 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 504, LocationType.EXTRA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "4 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 504, LocationType.EXTRA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: 5 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 505, LocationType.EXTRA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "5 Terrazine Nodes Collected", SC2NCO_LOC_ID_OFFSET + 505, LocationType.EXTRA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: HERC Outpost", SC2NCO_LOC_ID_OFFSET + 506, LocationType.VANILLA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "HERC Outpost", SC2NCO_LOC_ID_OFFSET + 506, LocationType.VANILLA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Umojan Mine", SC2NCO_LOC_ID_OFFSET + 507, LocationType.EXTRA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "Umojan Mine", SC2NCO_LOC_ID_OFFSET + 507, LocationType.EXTRA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Blightbringer", SC2NCO_LOC_ID_OFFSET + 508, LocationType.VANILLA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "Blightbringer", SC2NCO_LOC_ID_OFFSET + 508, LocationType.VANILLA, lambda state: logic.night_terrors_requirement(state) and logic.nova_ranged_weapon(state) and state.has_any( {item_names.NOVA_HELLFIRE_SHOTGUN, item_names.NOVA_PULSE_GRENADES, item_names.NOVA_STIM_INFUSION, item_names.NOVA_HOLO_DECOY}, player)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Science Facility", SC2NCO_LOC_ID_OFFSET + 509, LocationType.EXTRA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "Science Facility", SC2NCO_LOC_ID_OFFSET + 509, LocationType.EXTRA, lambda state: logic.night_terrors_requirement(state)), - LocationData(SC2Mission.NIGHT_TERRORS.mission_name, "Night Terrors: Eradicators", SC2NCO_LOC_ID_OFFSET + 510, LocationType.VANILLA, + make_location_data(SC2Mission.NIGHT_TERRORS.mission_name, "Eradicators", SC2NCO_LOC_ID_OFFSET + 510, LocationType.VANILLA, lambda state: logic.night_terrors_requirement(state) and logic.nova_any_weapon(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Victory", SC2NCO_LOC_ID_OFFSET + 600, LocationType.VICTORY, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 600, LocationType.VICTORY, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Close North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 601, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Close North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 601, LocationType.EXTRA, lambda state: state.has_any( {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) or logic.terran_common_unit(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Close East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 602, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Close East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 602, LocationType.EXTRA, lambda state: state.has_any( {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) or logic.terran_common_unit(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Far North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 603, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Far North Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 603, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Far East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 604, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Far East Evidence Coordinates", SC2NCO_LOC_ID_OFFSET + 604, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Experimental Weapon", SC2NCO_LOC_ID_OFFSET + 605, LocationType.VANILLA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Experimental Weapon", SC2NCO_LOC_ID_OFFSET + 605, LocationType.VANILLA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Northwest Subway Entrance", SC2NCO_LOC_ID_OFFSET + 606, LocationType.VANILLA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Northwest Subway Entrance", SC2NCO_LOC_ID_OFFSET + 606, LocationType.VANILLA, lambda state: state.has_any( {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) and logic.terran_common_unit(state) or logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Southeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 607, LocationType.VANILLA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Southeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 607, LocationType.VANILLA, lambda state: state.has_any( {item_names.LIBERATOR_RAID_ARTILLERY, item_names.RAVEN_HUNTER_SEEKER_WEAPON}, player) and logic.terran_common_unit(state) or logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Northeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 608, LocationType.VANILLA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Northeast Subway Entrance", SC2NCO_LOC_ID_OFFSET + 608, LocationType.VANILLA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Expansion Hatchery", SC2NCO_LOC_ID_OFFSET + 609, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Expansion Hatchery", SC2NCO_LOC_ID_OFFSET + 609, LocationType.EXTRA, lambda state: state.has(item_names.LIBERATOR_RAID_ARTILLERY, player) and logic.terran_common_unit(state) or logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Baneling Spawns", SC2NCO_LOC_ID_OFFSET + 610, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Baneling Spawns", SC2NCO_LOC_ID_OFFSET + 610, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Mutalisk Spawns", SC2NCO_LOC_ID_OFFSET + 611, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Mutalisk Spawns", SC2NCO_LOC_ID_OFFSET + 611, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Nydus Worm Spawns", SC2NCO_LOC_ID_OFFSET + 612, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Nydus Worm Spawns", SC2NCO_LOC_ID_OFFSET + 612, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Lurker Spawns", SC2NCO_LOC_ID_OFFSET + 613, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Lurker Spawns", SC2NCO_LOC_ID_OFFSET + 613, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Brood Lord Spawns", SC2NCO_LOC_ID_OFFSET + 614, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Brood Lord Spawns", SC2NCO_LOC_ID_OFFSET + 614, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.FLASHPOINT.mission_name, "Flashpoint: Ultralisk Spawns", SC2NCO_LOC_ID_OFFSET + 615, LocationType.EXTRA, + make_location_data(SC2Mission.FLASHPOINT.mission_name, "Ultralisk Spawns", SC2NCO_LOC_ID_OFFSET + 615, LocationType.EXTRA, lambda state: logic.flashpoint_far_requirement(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Victory", SC2NCO_LOC_ID_OFFSET + 700, LocationType.VICTORY, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 700, LocationType.VICTORY, lambda state: logic.enemy_shadow_victory(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Sewers: Domination Visor", SC2NCO_LOC_ID_OFFSET + 701, LocationType.VANILLA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Sewers: Domination Visor", SC2NCO_LOC_ID_OFFSET + 701, LocationType.VANILLA, lambda state: logic.enemy_shadow_domination(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Sewers: Resupply Crate", SC2NCO_LOC_ID_OFFSET + 702, LocationType.EXTRA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Sewers: Resupply Crate", SC2NCO_LOC_ID_OFFSET + 702, LocationType.EXTRA, lambda state: logic.enemy_shadow_first_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Sewers: Facility Access", SC2NCO_LOC_ID_OFFSET + 703, LocationType.VANILLA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Sewers: Facility Access", SC2NCO_LOC_ID_OFFSET + 703, LocationType.VANILLA, lambda state: logic.enemy_shadow_first_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Northwest Door Lock", SC2NCO_LOC_ID_OFFSET + 704, LocationType.VANILLA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: Northwest Door Lock", SC2NCO_LOC_ID_OFFSET + 704, LocationType.VANILLA, lambda state: logic.enemy_shadow_door_controls(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Southeast Door Lock", SC2NCO_LOC_ID_OFFSET + 705, LocationType.VANILLA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: Southeast Door Lock", SC2NCO_LOC_ID_OFFSET + 705, LocationType.VANILLA, lambda state: logic.enemy_shadow_door_controls(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Blazefire Gunblade", SC2NCO_LOC_ID_OFFSET + 706, LocationType.VANILLA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: Blazefire Gunblade", SC2NCO_LOC_ID_OFFSET + 706, LocationType.VANILLA, lambda state: logic.enemy_shadow_second_stage(state) and (logic.story_tech_granted or state.has(item_names.NOVA_BLINK, player) or (adv_tactics and state.has_all({item_names.NOVA_DOMINATION, item_names.NOVA_HOLO_DECOY, item_names.NOVA_JUMP_SUIT_MODULE}, player)) ) ), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Blink Suit", SC2NCO_LOC_ID_OFFSET + 707, LocationType.VANILLA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: Blink Suit", SC2NCO_LOC_ID_OFFSET + 707, LocationType.VANILLA, lambda state: logic.enemy_shadow_second_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Advanced Weaponry", SC2NCO_LOC_ID_OFFSET + 708, LocationType.VANILLA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: Advanced Weaponry", SC2NCO_LOC_ID_OFFSET + 708, LocationType.VANILLA, lambda state: logic.enemy_shadow_second_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: Entrance Resupply Crate", SC2NCO_LOC_ID_OFFSET + 709, LocationType.EXTRA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: Entrance Resupply Crate", SC2NCO_LOC_ID_OFFSET + 709, LocationType.EXTRA, lambda state: logic.enemy_shadow_first_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: West Resupply Crate", SC2NCO_LOC_ID_OFFSET + 710, LocationType.EXTRA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: West Resupply Crate", SC2NCO_LOC_ID_OFFSET + 710, LocationType.EXTRA, lambda state: logic.enemy_shadow_second_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: North Resupply Crate", SC2NCO_LOC_ID_OFFSET + 711, LocationType.EXTRA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: North Resupply Crate", SC2NCO_LOC_ID_OFFSET + 711, LocationType.EXTRA, lambda state: logic.enemy_shadow_second_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: East Resupply Crate", SC2NCO_LOC_ID_OFFSET + 712, LocationType.EXTRA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: East Resupply Crate", SC2NCO_LOC_ID_OFFSET + 712, LocationType.EXTRA, lambda state: logic.enemy_shadow_second_stage(state)), - LocationData(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "In the Enemy's Shadow: Facility: South Resupply Crate", SC2NCO_LOC_ID_OFFSET + 713, LocationType.EXTRA, + make_location_data(SC2Mission.IN_THE_ENEMY_S_SHADOW.mission_name, "Facility: South Resupply Crate", SC2NCO_LOC_ID_OFFSET + 713, LocationType.EXTRA, lambda state: logic.enemy_shadow_second_stage(state)), - LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Victory", SC2NCO_LOC_ID_OFFSET + 800, LocationType.VICTORY, + make_location_data(SC2Mission.DARK_SKIES.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 800, LocationType.VICTORY, lambda state: logic.dark_skies_requirement(state)), - LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: First Squadron of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 801, LocationType.EXTRA, + make_location_data(SC2Mission.DARK_SKIES.mission_name, "First Squadron of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 801, LocationType.EXTRA, lambda state: logic.dark_skies_requirement(state)), - LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Remainder of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 802, LocationType.EXTRA, + make_location_data(SC2Mission.DARK_SKIES.mission_name, "Remainder of Dominion Fleet", SC2NCO_LOC_ID_OFFSET + 802, LocationType.EXTRA, lambda state: logic.dark_skies_requirement(state)), - LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Ji'nara", SC2NCO_LOC_ID_OFFSET + 803, LocationType.EXTRA, + make_location_data(SC2Mission.DARK_SKIES.mission_name, "Ji'nara", SC2NCO_LOC_ID_OFFSET + 803, LocationType.EXTRA, lambda state: logic.dark_skies_requirement(state)), - LocationData(SC2Mission.DARK_SKIES.mission_name, "Dark Skies: Science Facility", SC2NCO_LOC_ID_OFFSET + 804, LocationType.VANILLA, + make_location_data(SC2Mission.DARK_SKIES.mission_name, "Science Facility", SC2NCO_LOC_ID_OFFSET + 804, LocationType.VANILLA, lambda state: logic.dark_skies_requirement(state)), - LocationData(SC2Mission.END_GAME.mission_name, "End Game: Victory", SC2NCO_LOC_ID_OFFSET + 900, LocationType.VICTORY, + make_location_data(SC2Mission.END_GAME.mission_name, "Victory", SC2NCO_LOC_ID_OFFSET + 900, LocationType.VICTORY, lambda state: logic.end_game_requirement(state) and logic.nova_any_weapon(state)), - LocationData(SC2Mission.END_GAME.mission_name, "End Game: Xanthos", SC2NCO_LOC_ID_OFFSET + 901, LocationType.VANILLA, + make_location_data(SC2Mission.END_GAME.mission_name, "Xanthos", SC2NCO_LOC_ID_OFFSET + 901, LocationType.VANILLA, lambda state: logic.end_game_requirement(state)), # Mission Variants # 10X/20X - Liberation Day - LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 300, LocationType.VICTORY, + make_location_data(SC2Mission.THE_OUTLAWS_Z.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 300, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 301, LocationType.VANILLA, + make_location_data(SC2Mission.THE_OUTLAWS_Z.mission_name, "Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 301, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 302, LocationType.EXTRA, + make_location_data(SC2Mission.THE_OUTLAWS_Z.mission_name, "North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 302, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 303, LocationType.VANILLA, + make_location_data(SC2Mission.THE_OUTLAWS_Z.mission_name, "Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 303, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_Z.mission_name, "The Outlaws (Zerg): Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 304, LocationType.EXTRA), - LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 400, LocationType.VICTORY, + make_location_data(SC2Mission.THE_OUTLAWS_Z.mission_name, "Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 304, LocationType.EXTRA), + make_location_data(SC2Mission.THE_OUTLAWS_P.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 400, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 401, LocationType.VANILLA, + make_location_data(SC2Mission.THE_OUTLAWS_P.mission_name, "Rebel Base", SC2_RACESWAP_LOC_ID_OFFSET + 401, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 402, LocationType.EXTRA, + make_location_data(SC2Mission.THE_OUTLAWS_P.mission_name, "North Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 402, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 403, LocationType.VANILLA, + make_location_data(SC2Mission.THE_OUTLAWS_P.mission_name, "Bunker", SC2_RACESWAP_LOC_ID_OFFSET + 403, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.THE_OUTLAWS_P.mission_name, "The Outlaws (Protoss): Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 404, LocationType.EXTRA), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 500, LocationType.VICTORY, + make_location_data(SC2Mission.THE_OUTLAWS_P.mission_name, "Close Resource Pickups", SC2_RACESWAP_LOC_ID_OFFSET + 404, LocationType.EXTRA), + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 500, LocationType.VICTORY, lambda state: logic.zerg_competent_defense(state) and logic.zerg_basic_kerriganless_anti_air(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 501, LocationType.VANILLA), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 502, LocationType.VANILLA, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 501, LocationType.VANILLA), + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 502, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 503, LocationType.VANILLA, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 503, LocationType.VANILLA, lambda state: logic.zerg_competent_defense(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 504, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 504, LocationType.CHALLENGE, lambda state: logic.zerg_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 505, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 505, LocationType.CHALLENGE, lambda state: logic.zerg_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 506, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 506, LocationType.CHALLENGE, lambda state: logic.zerg_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 507, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 507, LocationType.CHALLENGE, lambda state: logic.zerg_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 508, LocationType.EXTRA, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 508, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 509, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 509, LocationType.EXTRA, lambda state: logic.zerg_competent_defense(state)), - LocationData(SC2Mission.ZERO_HOUR_Z.mission_name, "Zero Hour (Zerg): Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 510, LocationType.EXTRA, + make_location_data(SC2Mission.ZERO_HOUR_Z.mission_name, "Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 510, LocationType.EXTRA, lambda state: logic.zerg_competent_defense(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 600, LocationType.VICTORY, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 600, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and (adv_tactics or logic.protoss_basic_anti_air(state))), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 601, LocationType.VANILLA), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 602, LocationType.VANILLA, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "First Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 601, LocationType.VANILLA), + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Second Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 602, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 603, LocationType.VANILLA, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Third Group Rescued", SC2_RACESWAP_LOC_ID_OFFSET + 603, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 604, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "First Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 604, LocationType.CHALLENGE, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 605, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Second Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 605, LocationType.CHALLENGE, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 606, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Third Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 606, LocationType.CHALLENGE, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 607, LocationType.CHALLENGE, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Fourth Hatchery", SC2_RACESWAP_LOC_ID_OFFSET + 607, LocationType.CHALLENGE, lambda state: logic.protoss_competent_comp(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 608, LocationType.EXTRA, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Ride's on its Way", SC2_RACESWAP_LOC_ID_OFFSET + 608, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 609, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Hold Just a Little Longer", SC2_RACESWAP_LOC_ID_OFFSET + 609, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state)), - LocationData(SC2Mission.ZERO_HOUR_P.mission_name, "Zero Hour (Protoss): Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 610, LocationType.EXTRA, + make_location_data(SC2Mission.ZERO_HOUR_P.mission_name, "Cavalry's on the Way", SC2_RACESWAP_LOC_ID_OFFSET + 610, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state)), # 70X/80X - Evacuation # 90X/100X - Outbreak # 110X/120X - Safe Haven # 130X/140X - Haven's Fall - LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1500, LocationType.VICTORY, + make_location_data(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1500, LocationType.VICTORY, lambda state: logic.zerg_common_unit(state) and (adv_tactics and logic.zerg_basic_anti_air(state) or logic.zerg_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1501, LocationType.VANILLA), - LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1502, LocationType.VANILLA), - LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1503, LocationType.VANILLA, + make_location_data(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1501, LocationType.VANILLA), + make_location_data(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1502, LocationType.VANILLA), + make_location_data(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1503, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) or logic.zerg_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1504, LocationType.VANILLA, + make_location_data(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1504, LocationType.VANILLA, lambda state: logic.zerg_common_unit(state) and (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) or logic.zerg_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1505, LocationType.EXTRA, + make_location_data(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1505, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) or logic.zerg_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Smash and Grab (Zerg): Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1506, LocationType.EXTRA, + make_location_data(SC2Mission.SMASH_AND_GRAB_Z.mission_name, "Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1506, LocationType.EXTRA, lambda state: logic.zerg_common_unit(state) and (adv_tactics and logic.zerg_basic_kerriganless_anti_air(state) or logic.zerg_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1600, LocationType.VICTORY, + make_location_data(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 1600, LocationType.VICTORY, lambda state: logic.protoss_common_unit(state) and (adv_tactics and logic.protoss_basic_anti_air(state) or logic.protoss_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1601, LocationType.VANILLA), - LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1602, LocationType.VANILLA), - LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1603, LocationType.VANILLA, + make_location_data(SC2Mission.SMASH_AND_GRAB_P.mission_name, "First Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1601, LocationType.VANILLA), + make_location_data(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Second Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1602, LocationType.VANILLA), + make_location_data(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Third Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1603, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and (adv_tactics and logic.protoss_basic_anti_air(state) or logic.protoss_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1604, LocationType.VANILLA, + make_location_data(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Fourth Relic", SC2_RACESWAP_LOC_ID_OFFSET + 1604, LocationType.VANILLA, lambda state: logic.protoss_common_unit(state) and (adv_tactics and logic.protoss_basic_anti_air(state) or logic.protoss_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1605, LocationType.EXTRA, + make_location_data(SC2Mission.SMASH_AND_GRAB_P.mission_name, "First Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1605, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and (adv_tactics and logic.protoss_basic_anti_air(state) or logic.protoss_competent_anti_air(state))), - LocationData(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Smash and Grab (Protoss): Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1606, LocationType.EXTRA, + make_location_data(SC2Mission.SMASH_AND_GRAB_P.mission_name, "Second Forcefield Area Busted", SC2_RACESWAP_LOC_ID_OFFSET + 1606, LocationType.EXTRA, lambda state: logic.protoss_common_unit(state) and (adv_tactics and logic.protoss_basic_anti_air(state) or logic.protoss_competent_anti_air(state))),