diff --git a/Dolphin scripts/Entrance Randomizer/CHANGELOG.md b/Dolphin scripts/Entrance Randomizer/CHANGELOG.md index 43185c3..56adcf6 100644 --- a/Dolphin scripts/Entrance Randomizer/CHANGELOG.md +++ b/Dolphin scripts/Entrance Randomizer/CHANGELOG.md @@ -23,6 +23,11 @@ To add a changelog entry, add a new file `..md` to the `new ### Features +- Added informational styling to graph edges + - One-way-transitions are marked by using a dashed line + - Transitions that are disabled but we plan on re-enabling are marked in black + + -- by @wossnameGitHub - When being sent to an Animal Temple that you haven't beaten yet, you will now instead be redirected to the Spirit Fight immediately -- by @wossnameGitHub ([#87](https://github.com/Avasam/ptle-tools/issues/87)) - "Immediate spirit fights" is optional and configurable -- by @Avasam ([#65](https://github.com/Avasam/ptle-tools/issues/65)) diff --git a/Dolphin scripts/Entrance Randomizer/__main__.py b/Dolphin scripts/Entrance Randomizer/__main__.py index 80237f3..c660820 100644 --- a/Dolphin scripts/Entrance Randomizer/__main__.py +++ b/Dolphin scripts/Entrance Randomizer/__main__.py @@ -20,7 +20,7 @@ from lib.constants import * # noqa: F403 from lib.constants import __version__ from lib.entrance_rando import ( - DISABLED_TRANSITIONS, + SHOWN_DISABLED_TRANSITIONS, highjack_transition_rando, set_transitions_map, starting_area, @@ -50,7 +50,7 @@ # Dump spoiler logs and graph dump_spoiler_logs(starting_area_name, transitions_map, seed_string) -create_graphml(transitions_map, DISABLED_TRANSITIONS, seed_string, starting_area) +create_graphml(transitions_map, SHOWN_DISABLED_TRANSITIONS, seed_string, starting_area) async def main_loop(): diff --git a/Dolphin scripts/Entrance Randomizer/lib/entrance_rando.py b/Dolphin scripts/Entrance Randomizer/lib/entrance_rando.py index 9aabd0a..29ee6ac 100644 --- a/Dolphin scripts/Entrance Randomizer/lib/entrance_rando.py +++ b/Dolphin scripts/Entrance Randomizer/lib/entrance_rando.py @@ -126,8 +126,8 @@ class Choice(IntEnum): if CONFIGS.STARTING_AREA is not None: starting_area = CONFIGS.STARTING_AREA -TRANSITION_INFOS_DICT_RANDO = TRANSITION_INFOS_DICT.copy() -ALL_POSSIBLE_TRANSITIONS_RANDO = ALL_POSSIBLE_TRANSITIONS +_transition_infos_dict_rando = TRANSITION_INFOS_DICT.copy() +_all_possible_transitions_rando = list(ALL_POSSIBLE_TRANSITIONS) transitions_map: dict[tuple[int, int], Transition] = {} """```python @@ -187,28 +187,25 @@ def initialize_connections_left(): def remove_disabled_exits(): - # remove exits from TRANSITION_INFOS_DICT_RANDO + # remove exits from _transition_infos_dict_rando for area in TRANSITION_INFOS_DICT.values(): for ex in area.exits: current = (area.area_id, ex.area_id) if current in ONE_WAY_TRANSITIONS or current in DISABLED_TRANSITIONS: - TRANSITION_INFOS_DICT_RANDO[area.area_id] = Area( + _transition_infos_dict_rando[area.area_id] = Area( area.area_id, area.name, area.default_entrance, tuple([ - x for x in TRANSITION_INFOS_DICT_RANDO[area.area_id].exits if x != ex + x for x in _transition_infos_dict_rando[area.area_id].exits if x != ex ]), ) __connections_left[area.area_id] -= 1 - # remove exits from ALL_POSSIBLE_TRANSITIONS_RANDO - global ALL_POSSIBLE_TRANSITIONS_RANDO + # remove exits from _all_possible_transitions_rando for trans in ALL_POSSIBLE_TRANSITIONS: if trans in ONE_WAY_TRANSITIONS or trans in DISABLED_TRANSITIONS: - ALL_POSSIBLE_TRANSITIONS_RANDO = [ # pyright: ignore[reportConstantRedefinition] - x for x in ALL_POSSIBLE_TRANSITIONS_RANDO if x != trans - ] + _all_possible_transitions_rando.remove(trans) def link_two_levels(first: Area, second: Area): @@ -339,22 +336,22 @@ def set_transitions_map(): # noqa: PLR0915 # TODO: Break up in smaller function initialize_connections_left() remove_disabled_exits() if not CONFIGS.SKIP_JAGUAR: - starting_default = TRANSITION_INFOS_DICT_RANDO[starting_area].default_entrance + starting_default = _transition_infos_dict_rando[starting_area].default_entrance tutorial_original = Transition(from_=LevelCRC.JAGUAR, to=LevelCRC.PLANE_CUTSCENE) tutorial_redirect = Transition(from_=starting_default, to=starting_area) transitions_map[tutorial_original] = tutorial_redirect - _possible_redirections_bucket = list(starmap(Transition, ALL_POSSIBLE_TRANSITIONS_RANDO)) + _possible_redirections_bucket = list(starmap(Transition, _all_possible_transitions_rando)) if CONFIGS.LINKED_TRANSITIONS: # Ground rules: # 1. you can't make a transition from a level to itself # 2. any 2 levels may have a maximum of 1 connection between them (as long as it's 2-way) - _possible_origins_bucket = list(starmap(Transition, ALL_POSSIBLE_TRANSITIONS_RANDO)) + _possible_origins_bucket = list(starmap(Transition, _all_possible_transitions_rando)) level_list = [ - area for area in TRANSITION_INFOS_DICT_RANDO.values() + area for area in _transition_infos_dict_rando.values() if __connections_left[area.area_id] > 0 ] random.shuffle(level_list) @@ -410,7 +407,7 @@ def set_transitions_map(): # noqa: PLR0915 # TODO: Break up in smaller function # Ground rules: # 1. you can't make a transition from a level to itself _possible_redirections_bucket.extend(ONE_WAY_TRANSITIONS) - for area in TRANSITION_INFOS_DICT_RANDO.values(): + for area in _transition_infos_dict_rando.values(): for to_og in (exit_.area_id for exit_ in area.exits): original = Transition(from_=area.area_id, to=to_og) redirect = get_random_redirection(original, _possible_redirections_bucket) diff --git a/Dolphin scripts/Entrance Randomizer/lib/graph_creation.py b/Dolphin scripts/Entrance Randomizer/lib/graph_creation.py index 81b96fa..f965c64 100644 --- a/Dolphin scripts/Entrance Randomizer/lib/graph_creation.py +++ b/Dolphin scripts/Entrance Randomizer/lib/graph_creation.py @@ -1,15 +1,29 @@ from __future__ import annotations -from collections.abc import Mapping, Sequence +from collections.abc import Iterable, Mapping, Sequence +from enum import IntEnum, auto from pathlib import Path from lib.constants import * # noqa: F403 from lib.constants import __version__ from lib.types_ import SeedType + +class Direction(IntEnum): + ONEWAY = auto() + TWOWAY = auto() + + +class LineType(IntEnum): + SOLID = auto() + DASHED = auto() + + STARTING_AREA_COLOR = "#ff8000" # Orange UPGRADE_AREAS_COLOR = "#0080ff" # Blue IMPORTANT_STORY_TRIGGER_AREAS_COLOR = "#ff0000" # Red +UNRANDOMIZED_EDGE_COLOR = "#000000" # Black + UPGRADE_AREAS = { LevelCRC.PLANE_COCKPIT, # Canteen LevelCRC.BITTENBINDERS_CAMP, # Sling + Rising Strike @@ -26,12 +40,20 @@ } IMPORTANT_STORY_TRIGGER_AREAS = { LevelCRC.ALTAR_OF_AGES, - LevelCRC.ST_CLAIRE_NIGHT, LevelCRC.ST_CLAIRE_DAY, LevelCRC.GATES_OF_EL_DORADO, } +def create_own_style(params: dict[str, str | None]): + style = ", ".join([ + f""{key}":"{value}"" + for key, value in params.items() + if value is not None + ]) + return ' ownStyles="{"0":{' + style + '}}"' if style else "" + + def create_vertices( transitions_map: Mapping[tuple[int, int], tuple[int, int]], starting_area: int, @@ -63,26 +85,15 @@ def create_vertices( output_text += ( f'\n" + ) + + +def create_edges( + transitions_map: Mapping[tuple[int, int], tuple[int, int]], + shown_disabled_transitions: Iterable[tuple[int, int]], +): + connections = list(transitions_map.items()) + connections_two_way: list[tuple[tuple[int, int], tuple[int, int]]] = [] + connections_one_way: list[tuple[tuple[int, int], tuple[int, int]]] = [] for pairing in connections: - if (pairing[1], pairing[0]) not in connections_two_way: - if (pairing[1], pairing[0]) in connections: + reverse = ( + (pairing[1][1], pairing[1][0]), + (pairing[0][1], pairing[0][0]), + ) + if reverse not in connections_two_way: + if reverse in connections: connections_two_way.append(pairing) else: connections_one_way.append(pairing) @@ -106,17 +146,23 @@ def create_edges(transitions_map: Mapping[tuple[int, int], tuple[int, int]]): output_text = "" counter = 1 # Can't start at 0 since that's the MAIN_MENU id for pairing in connections_two_way: - output_text += ( - f'\n' + output_text += edge_component( + pairing[0][0], + pairing[1][1], + counter, + Direction.TWOWAY, + UNRANDOMIZED_EDGE_COLOR if pairing[1] in shown_disabled_transitions else None, + LineType.SOLID, ) counter += 1 for pairing in connections_one_way: - output_text += ( - f'\n' + output_text += edge_component( + pairing[0][0], + pairing[1][1], + counter, + Direction.ONEWAY, + None, + LineType.DASHED, ) counter += 1 return output_text @@ -134,7 +180,7 @@ def create_graphml( '' + '\n' + create_vertices(all_transitions, starting_area) - + create_edges(all_transitions) + + create_edges(all_transitions, shown_disabled_transitions) + "" )