def _name_for_location(world_list: WorldList, location: AreaIdentifier) -> str: loc = location.as_tuple if loc in prime1_elevators.RANDOM_PRIME_CUSTOM_NAMES and loc != ( "Frigate Orpheon", "Exterior Docking Hangar"): return prime1_elevators.RANDOM_PRIME_CUSTOM_NAMES[loc] else: return world_list.area_name(world_list.area_by_area_location(location), separator=":")
def distances_to_node(world_list: WorldList, starting_node: Node, *, ignore_elevators: bool = True, cutoff: Optional[int] = None, patches: Optional[GamePatches] = None, ) -> Dict[Area, int]: """ Compute the shortest distance from a node to all reachable areas. :param world_list: :param starting_node: :param ignore_elevators: :param cutoff: Exclude areas with a length longer that cutoff. :param patches: :return: Dict keyed by area to shortest distance to starting_node. """ import networkx g = networkx.DiGraph() if patches is None: def get_elevator_connection_for(n: TeleporterNode): return n.default_connection def get_dock_connection_for(n: DockNode): return n.default_connection else: get_elevator_connection_for = patches.get_elevator_connection_for def get_dock_connection_for(n: DockNode): return patches.get_dock_connection_for(n).identifier for area in world_list.all_areas: g.add_node(area) for world in world_list.worlds: for area in world.areas: new_areas = set() for node in area.nodes: connection = None if isinstance(node, DockNode): connection = get_dock_connection_for(node).area_identifier elif isinstance(node, TeleporterNode) and not ignore_elevators: connection = get_elevator_connection_for(node) if connection is not None: new_areas.add(world_list.area_by_area_location(connection)) for next_area in new_areas: g.add_edge(area, next_area) return networkx.single_source_shortest_path_length(g, world_list.nodes_to_area(starting_node), cutoff)
def _get_elevator_or_area_name(custom_names_to_use: dict[RandovaniaGame, dict[tuple[str, str], str]], game: RandovaniaGame, world_list: WorldList, area_location: AreaIdentifier, include_world_name: bool) -> str: custom_names_by_game = custom_names_to_use.get(game, {}) area_loc = area_location.as_tuple if area_loc in custom_names_by_game: return custom_names_by_game[area_loc] else: area = world_list.area_by_area_location(area_location) if include_world_name: return world_list.area_name(area) else: return area.name
def pretty_print_node_type(node: Node, world_list: WorldList): if isinstance(node, DockNode): try: other = world_list.node_by_identifier(node.default_connection) other_name = world_list.node_name(other) except IndexError as e: other_name = (f"(Area {node.default_connection.area_name}, " f"index {node.default_connection.node_name}) [{e}]") return f"{node.default_dock_weakness.name} to {other_name}" elif isinstance(node, TeleporterNode): other = world_list.area_by_area_location(node.default_connection) return f"Teleporter to {world_list.area_name(other)}" elif isinstance(node, PickupNode): return f"Pickup {node.pickup_index.index}; Major Location? {node.major_location}" elif isinstance(node, EventNode): return f"Event {node.event.long_name}" elif isinstance(node, ConfigurableNode): return f"Configurable Node" elif isinstance(node, LogbookNode): message = "" if node.lore_type == LoreType.REQUIRES_ITEM: message = f" ({node.required_translator.long_name})" return f"Logbook {node.lore_type.long_name}{message} for {node.string_asset_id:x}" elif isinstance(node, PlayerShipNode): unlocked_pretty = list(pretty_print_requirement(node.is_unlocked)) if len(unlocked_pretty) > 1: unlocked_by = "Complex requirement" else: unlocked_by = unlocked_pretty[0][1] return f"Player Ship (Unlocked by {unlocked_by})" return ""
def _find_area_with_teleporter(world_list: WorldList, teleporter: NodeIdentifier) -> Area: return world_list.area_by_area_location(teleporter.area_location)