| 
									
										
										
										
											2022-10-01 15:24:05 +02:00
										 |  |  | from typing import List, Set, Dict, Tuple, Optional, Callable | 
					
						
							| 
									
										
										
										
											2023-02-13 18:06:43 -06:00
										 |  |  | from BaseClasses import MultiWorld, Region, Entrance, Location | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | from .Locations import LocationData | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | from .Options import get_option_value | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  | from .MissionTables import MissionInfo, mission_orders, vanilla_mission_req_table, alt_final_mission_locations | 
					
						
							|  |  |  | from .PoolFilter import filter_missions | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  | def create_regions(multiworld: MultiWorld, player: int, locations: Tuple[LocationData, ...], location_cache: List[Location])\ | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         -> Tuple[Dict[str, MissionInfo], int, str]: | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  |     locations_per_region = get_locations_per_region(locations) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |     mission_order_type = get_option_value(multiworld, player, "mission_order") | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |     mission_order = mission_orders[mission_order_type] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |     mission_pools = filter_missions(multiworld, player) | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |     final_mission = mission_pools['all_in'][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     used_regions = [mission for mission_pool in mission_pools.values() for mission in mission_pool] | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |     regions = [create_region(multiworld, player, locations_per_region, location_cache, "Menu")] | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |     for region_name in used_regions: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         regions.append(create_region(multiworld, player, locations_per_region, location_cache, region_name)) | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |     # Changing the completion condition for alternate final missions into an event | 
					
						
							|  |  |  |     if final_mission != 'All-In': | 
					
						
							|  |  |  |         final_location = alt_final_mission_locations[final_mission] | 
					
						
							|  |  |  |         # 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].locked = True | 
					
						
							|  |  |  |                 location_cache[i].event = True | 
					
						
							|  |  |  |                 location_cache[i].address = None | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         final_location = 'All-In: Victory' | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if __debug__: | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         if mission_order_type in (0, 1): | 
					
						
							|  |  |  |             throwIfAnyLocationIsNotAssignedToARegion(regions, locations_per_region.keys()) | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |     multiworld.regions += regions | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     names: Dict[str, int] = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |     if mission_order_type == 0: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Menu', 'Liberation Day'), | 
					
						
							|  |  |  |         connect(multiworld, player, names, 'Liberation Day', 'The Outlaws', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Liberation Day", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'The Outlaws', 'Zero Hour', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat The Outlaws", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Zero Hour', 'Evacuation', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Zero Hour", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Evacuation', 'Outbreak', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Evacuation", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, "Outbreak", "Safe Haven", | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 7) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat Outbreak", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, "Outbreak", "Haven's Fall", | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 7) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat Outbreak", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Zero Hour', 'Smash and Grab', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Zero Hour", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Smash and Grab', 'The Dig', | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 8) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat Smash and Grab", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'The Dig', 'The Moebius Factor', | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 11) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat The Dig", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'The Moebius Factor', 'Supernova', | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 14) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat The Moebius Factor", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Supernova', 'Maw of the Void', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Supernova", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Zero Hour', "Devil's Playground", | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 4) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat Zero Hour", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, "Devil's Playground", 'Welcome to the Jungle', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Devil's Playground", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, "Welcome to the Jungle", 'Breakout', | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 8) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat Welcome to the Jungle", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, "Welcome to the Jungle", 'Ghost of a Chance', | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 8) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat Welcome to the Jungle", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, "Zero Hour", 'The Great Train Robbery', | 
					
						
							|  |  |  |                 lambda state: state._sc2wol_cleared_missions(multiworld, player, 6) and | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                               state.has("Beat Zero Hour", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'The Great Train Robbery', 'Cutthroat', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat The Great Train Robbery", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Cutthroat', 'Engine of Destruction', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Cutthroat", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Engine of Destruction', 'Media Blitz', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Engine of Destruction", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Media Blitz', 'Piercing the Shroud', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Media Blitz", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'The Dig', 'Whispers of Doom', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat The Dig", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Whispers of Doom', 'A Sinister Turn', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Whispers of Doom", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'A Sinister Turn', 'Echoes of the Future', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat A Sinister Turn", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Echoes of the Future', 'In Utter Darkness', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Echoes of the Future", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Maw of the Void', 'Gates of Hell', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Maw of the Void", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Gates of Hell', 'Belly of the Beast', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Gates of Hell", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Gates of Hell', 'Shatter the Sky', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 lambda state: state.has("Beat Gates of Hell", player)), | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         connect(multiworld, player, names, 'Gates of Hell', 'All-In', | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 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))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         return vanilla_mission_req_table, 29, final_location | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |         missions = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Initial fill out of mission list and marking all-in mission | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         for mission in mission_order: | 
					
						
							|  |  |  |             if mission is None: | 
					
						
							|  |  |  |                 missions.append(None) | 
					
						
							|  |  |  |             elif mission.type == "all_in": | 
					
						
							|  |  |  |                 missions.append(final_mission) | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |             elif mission.relegate and not get_option_value(multiworld, player, "shuffle_no_build"): | 
					
						
							| 
									
										
										
										
											2022-06-03 14:18:36 -04:00
										 |  |  |                 missions.append("no_build") | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 missions.append(mission.type) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         # Place Protoss Missions if we are not using ShuffleProtoss and are in Vanilla Shuffled | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |         if get_option_value(multiworld, player, "shuffle_protoss") == 0 and mission_order_type == 1: | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |             missions[22] = "A Sinister Turn" | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |             mission_pools['medium'].remove("A Sinister Turn") | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |             missions[23] = "Echoes of the Future" | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |             mission_pools['medium'].remove("Echoes of the Future") | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |             missions[24] = "In Utter Darkness" | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |             mission_pools['hard'].remove("In Utter Darkness") | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         no_build_slots = [] | 
					
						
							|  |  |  |         easy_slots = [] | 
					
						
							|  |  |  |         medium_slots = [] | 
					
						
							|  |  |  |         hard_slots = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Search through missions to find slots needed to fill | 
					
						
							|  |  |  |         for i in range(len(missions)): | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |             if missions[i] is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |             if missions[i] == "no_build": | 
					
						
							|  |  |  |                 no_build_slots.append(i) | 
					
						
							|  |  |  |             elif missions[i] == "easy": | 
					
						
							|  |  |  |                 easy_slots.append(i) | 
					
						
							|  |  |  |             elif missions[i] == "medium": | 
					
						
							|  |  |  |                 medium_slots.append(i) | 
					
						
							|  |  |  |             elif missions[i] == "hard": | 
					
						
							|  |  |  |                 hard_slots.append(i) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add no_build missions to the pool and fill in no_build slots | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         missions_to_add = mission_pools['no_build'] | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |         for slot in no_build_slots: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |             filler = multiworld.random.randint(0, len(missions_to_add) - 1) | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             missions[slot] = missions_to_add.pop(filler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add easy missions into pool and fill in easy slots | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         missions_to_add = missions_to_add + mission_pools['easy'] | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |         for slot in easy_slots: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |             filler = multiworld.random.randint(0, len(missions_to_add) - 1) | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             missions[slot] = missions_to_add.pop(filler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add medium missions into pool and fill in medium slots | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         missions_to_add = missions_to_add + mission_pools['medium'] | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |         for slot in medium_slots: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |             filler = multiworld.random.randint(0, len(missions_to_add) - 1) | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             missions[slot] = missions_to_add.pop(filler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add hard missions into pool and fill in hard slots | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         missions_to_add = missions_to_add + mission_pools['hard'] | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |         for slot in hard_slots: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |             filler = multiworld.random.randint(0, len(missions_to_add) - 1) | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |             missions[slot] = missions_to_add.pop(filler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Loop through missions to create requirements table and connect regions | 
					
						
							|  |  |  |         # TODO: Handle 'and' connections | 
					
						
							|  |  |  |         mission_req_table = {} | 
					
						
							|  |  |  |         for i in range(len(missions)): | 
					
						
							|  |  |  |             connections = [] | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |             for connection in mission_order[i].connect_to: | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 if connection == -1: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |                     connect(multiworld, player, names, "Menu", missions[i]) | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |                     connect(multiworld, player, names, missions[connection], missions[i], | 
					
						
							| 
									
										
										
										
											2022-08-19 13:50:44 -07:00
										 |  |  |                             (lambda name, missions_req: (lambda state: state.has(f"Beat {name}", player) and | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  |                                                                        state._sc2wol_cleared_missions(multiworld, player, | 
					
						
							| 
									
										
										
										
											2022-08-19 13:50:44 -07:00
										 |  |  |                                                                                                       missions_req))) | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |                             (missions[connection], mission_order[i].number)) | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  |                     connections.append(connection + 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             mission_req_table.update({missions[i]: MissionInfo( | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |                 vanilla_mission_req_table[missions[i]].id, connections, mission_order[i].category, | 
					
						
							|  |  |  |                 number=mission_order[i].number, | 
					
						
							|  |  |  |                 completion_critical=mission_order[i].completion_critical, | 
					
						
							|  |  |  |                 or_requirements=mission_order[i].or_requirements)}) | 
					
						
							| 
									
										
										
										
											2022-05-26 13:28:10 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 06:24:54 -04:00
										 |  |  |         final_mission_id = vanilla_mission_req_table[final_mission].id | 
					
						
							|  |  |  |         return mission_req_table, final_mission_id, final_mission + ': Victory' | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def throwIfAnyLocationIsNotAssignedToARegion(regions: List[Region], regionNames: Set[str]): | 
					
						
							|  |  |  |     existingRegions = set() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for region in regions: | 
					
						
							|  |  |  |         existingRegions.add(region.name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (regionNames - existingRegions): | 
					
						
							| 
									
										
										
										
											2022-05-20 20:47:16 -04:00
										 |  |  |         raise Exception("Starcraft: the following regions are used in locations: {}, but no such region exists".format( | 
					
						
							|  |  |  |             regionNames - existingRegions)) | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 20:47:16 -04:00
										 |  |  | def create_location(player: int, location_data: LocationData, region: Region, | 
					
						
							|  |  |  |                     location_cache: List[Location]) -> Location: | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  |     location = Location(player, location_data.name, location_data.code, region) | 
					
						
							|  |  |  |     location.access_rule = location_data.rule | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if id is None: | 
					
						
							|  |  |  |         location.event = True | 
					
						
							|  |  |  |         location.locked = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     location_cache.append(location) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return location | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 14:46:24 -05:00
										 |  |  | def create_region(multiworld: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]], | 
					
						
							| 
									
										
										
										
											2022-05-20 20:47:16 -04:00
										 |  |  |                   location_cache: List[Location], name: str) -> Region: | 
					
						
							| 
									
										
										
										
											2023-02-13 18:06:43 -06:00
										 |  |  |     region = Region(name, player, multiworld) | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if name in locations_per_region: | 
					
						
							|  |  |  |         for location_data in locations_per_region[name]: | 
					
						
							|  |  |  |             location = create_location(player, location_data, region, location_cache) | 
					
						
							|  |  |  |             region.locations.append(location) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return region | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-20 20:47:16 -04:00
										 |  |  | def connect(world: MultiWorld, player: int, used_names: Dict[str, int], source: str, target: str, | 
					
						
							|  |  |  |             rule: Optional[Callable] = None): | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  |     sourceRegion = world.get_region(source, player) | 
					
						
							|  |  |  |     targetRegion = world.get_region(target, player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if target not in used_names: | 
					
						
							|  |  |  |         used_names[target] = 1 | 
					
						
							|  |  |  |         name = target | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         used_names[target] += 1 | 
					
						
							|  |  |  |         name = target + (' ' * used_names[target]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connection = Entrance(player, name, sourceRegion) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if rule: | 
					
						
							|  |  |  |         connection.access_rule = rule | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sourceRegion.exits.append(connection) | 
					
						
							|  |  |  |     connection.connect(targetRegion) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_locations_per_region(locations: Tuple[LocationData, ...]) -> Dict[str, List[LocationData]]: | 
					
						
							| 
									
										
										
										
											2022-05-20 20:47:16 -04:00
										 |  |  |     per_region: Dict[str, List[LocationData]] = {} | 
					
						
							| 
									
										
										
										
											2022-05-18 17:27:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for location in locations: | 
					
						
							|  |  |  |         per_region.setdefault(location.region, []).append(location) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return per_region |