The Messenger: Fix various portal shuffle issues (#2976)
* put constants in a bit more sensical order * fix accidental incorrect scoping * fix plando rules not being respected * add docstrings for the plando functions * fix the portal output pools being overwritten * use shuffle and pop instead of removing by content so plando can go to the same area twice * move portal pool rebuilding outside mapping creation * remove plando_connection cleansing since it isn't shared with transition shuffle
This commit is contained in:
		
							parent
							
								
									5f0112e783
								
							
						
					
					
						commit
						b7ac6a4cbd
					
				|  | @ -1,3 +1,4 @@ | ||||||
|  | from copy import deepcopy | ||||||
| from typing import List, TYPE_CHECKING | from typing import List, TYPE_CHECKING | ||||||
| 
 | 
 | ||||||
| from BaseClasses import CollectionState, PlandoOptions | from BaseClasses import CollectionState, PlandoOptions | ||||||
|  | @ -18,24 +19,6 @@ PORTALS = [ | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| REGION_ORDER = [ |  | ||||||
|     "Autumn Hills", |  | ||||||
|     "Forlorn Temple", |  | ||||||
|     "Catacombs", |  | ||||||
|     "Bamboo Creek", |  | ||||||
|     "Howling Grotto", |  | ||||||
|     "Quillshroom Marsh", |  | ||||||
|     "Searing Crags", |  | ||||||
|     "Glacial Peak", |  | ||||||
|     "Tower of Time", |  | ||||||
|     "Cloud Ruins", |  | ||||||
|     "Underworld", |  | ||||||
|     "Riviere Turquoise", |  | ||||||
|     "Elemental Skylands", |  | ||||||
|     "Sunken Shrine", |  | ||||||
| ] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| SHOP_POINTS = { | SHOP_POINTS = { | ||||||
|     "Autumn Hills": [ |     "Autumn Hills": [ | ||||||
|         "Climbing Claws", |         "Climbing Claws", | ||||||
|  | @ -204,30 +187,48 @@ CHECKPOINTS = { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | REGION_ORDER = [ | ||||||
|  |     "Autumn Hills", | ||||||
|  |     "Forlorn Temple", | ||||||
|  |     "Catacombs", | ||||||
|  |     "Bamboo Creek", | ||||||
|  |     "Howling Grotto", | ||||||
|  |     "Quillshroom Marsh", | ||||||
|  |     "Searing Crags", | ||||||
|  |     "Glacial Peak", | ||||||
|  |     "Tower of Time", | ||||||
|  |     "Cloud Ruins", | ||||||
|  |     "Underworld", | ||||||
|  |     "Riviere Turquoise", | ||||||
|  |     "Elemental Skylands", | ||||||
|  |     "Sunken Shrine", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def shuffle_portals(world: "MessengerWorld") -> None: | def shuffle_portals(world: "MessengerWorld") -> None: | ||||||
|     def create_mapping(in_portal: str, warp: str) -> None: |     """shuffles the output of the portals from the main hub""" | ||||||
|         nonlocal available_portals |     def create_mapping(in_portal: str, warp: str) -> str: | ||||||
|  |         """assigns the chosen output to the input""" | ||||||
|         parent = out_to_parent[warp] |         parent = out_to_parent[warp] | ||||||
|         exit_string = f"{parent.strip(' ')} - " |         exit_string = f"{parent.strip(' ')} - " | ||||||
| 
 | 
 | ||||||
|         if "Portal" in warp: |         if "Portal" in warp: | ||||||
|             exit_string += "Portal" |             exit_string += "Portal" | ||||||
|             world.portal_mapping.append(int(f"{REGION_ORDER.index(parent)}00")) |             world.portal_mapping.append(int(f"{REGION_ORDER.index(parent)}00")) | ||||||
|         elif warp_point in SHOP_POINTS[parent]: |         elif warp in SHOP_POINTS[parent]: | ||||||
|             exit_string += f"{warp_point} Shop" |             exit_string += f"{warp} Shop" | ||||||
|             world.portal_mapping.append(int(f"{REGION_ORDER.index(parent)}1{SHOP_POINTS[parent].index(warp_point)}")) |             world.portal_mapping.append(int(f"{REGION_ORDER.index(parent)}1{SHOP_POINTS[parent].index(warp)}")) | ||||||
|         else: |         else: | ||||||
|             exit_string += f"{warp_point} Checkpoint" |             exit_string += f"{warp} Checkpoint" | ||||||
|             world.portal_mapping.append(int(f"{REGION_ORDER.index(parent)}2{CHECKPOINTS[parent].index(warp_point)}")) |             world.portal_mapping.append(int(f"{REGION_ORDER.index(parent)}2{CHECKPOINTS[parent].index(warp)}")) | ||||||
| 
 | 
 | ||||||
|         world.spoiler_portal_mapping[in_portal] = exit_string |         world.spoiler_portal_mapping[in_portal] = exit_string | ||||||
|         connect_portal(world, in_portal, exit_string) |         connect_portal(world, in_portal, exit_string) | ||||||
| 
 | 
 | ||||||
|         available_portals.remove(warp) |         return parent | ||||||
|         if shuffle_type < ShufflePortals.option_anywhere: |  | ||||||
|             available_portals = [port for port in available_portals if port not in shop_points[parent]] |  | ||||||
| 
 | 
 | ||||||
|     def handle_planned_portals(plando_connections: List[PlandoConnection]) -> None: |     def handle_planned_portals(plando_connections: List[PlandoConnection]) -> None: | ||||||
|  |         """checks the provided plando connections for portals and connects them""" | ||||||
|         for connection in plando_connections: |         for connection in plando_connections: | ||||||
|             if connection.entrance not in PORTALS: |             if connection.entrance not in PORTALS: | ||||||
|                 continue |                 continue | ||||||
|  | @ -236,22 +237,28 @@ def shuffle_portals(world: "MessengerWorld") -> None: | ||||||
|             world.plando_portals.append(connection.entrance) |             world.plando_portals.append(connection.entrance) | ||||||
| 
 | 
 | ||||||
|     shuffle_type = world.options.shuffle_portals |     shuffle_type = world.options.shuffle_portals | ||||||
|     shop_points = SHOP_POINTS.copy() |     shop_points = deepcopy(SHOP_POINTS) | ||||||
|     for portal in PORTALS: |     for portal in PORTALS: | ||||||
|         shop_points[portal].append(f"{portal} Portal") |         shop_points[portal].append(f"{portal} Portal") | ||||||
|     if shuffle_type > ShufflePortals.option_shops: |     if shuffle_type > ShufflePortals.option_shops: | ||||||
|         shop_points.update(CHECKPOINTS) |         for area, points in CHECKPOINTS.items(): | ||||||
|  |             shop_points[area] += points | ||||||
|     out_to_parent = {checkpoint: parent for parent, checkpoints in shop_points.items() for checkpoint in checkpoints} |     out_to_parent = {checkpoint: parent for parent, checkpoints in shop_points.items() for checkpoint in checkpoints} | ||||||
|     available_portals = [val for zone in shop_points.values() for val in zone] |     available_portals = [val for zone in shop_points.values() for val in zone] | ||||||
|  |     world.random.shuffle(available_portals) | ||||||
| 
 | 
 | ||||||
|     plando = world.multiworld.plando_connections[world.player] |     plando = world.multiworld.plando_connections[world.player] | ||||||
|     if plando and world.multiworld.plando_options & PlandoOptions.connections: |     if plando and world.multiworld.plando_options & PlandoOptions.connections: | ||||||
|         handle_planned_portals(plando) |         handle_planned_portals(plando) | ||||||
|         world.multiworld.plando_connections[world.player] = [connection for connection in plando | 
 | ||||||
|                                                              if connection.entrance not in PORTALS] |  | ||||||
|     for portal in PORTALS: |     for portal in PORTALS: | ||||||
|         warp_point = world.random.choice(available_portals) |         if portal in world.plando_portals: | ||||||
|         create_mapping(portal, warp_point) |             continue | ||||||
|  |         warp_point = available_portals.pop() | ||||||
|  |         parent = create_mapping(portal, warp_point) | ||||||
|  |         if shuffle_type < ShufflePortals.option_anywhere: | ||||||
|  |             available_portals = [port for port in available_portals if port not in shop_points[parent]] | ||||||
|  |             world.random.shuffle(available_portals) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def connect_portal(world: "MessengerWorld", portal: str, out_region: str) -> None: | def connect_portal(world: "MessengerWorld", portal: str, out_region: str) -> None: | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue