Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add informational styling to graph edges #78

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Dolphin scripts/Entrance Randomizer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ To add a changelog entry, add a new file `<issue_or_pr_#>.<type>.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))

Expand Down
27 changes: 12 additions & 15 deletions Dolphin scripts/Entrance Randomizer/lib/entrance_rando.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
112 changes: 79 additions & 33 deletions Dolphin scripts/Entrance Randomizer/lib/graph_creation.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"&quot;{key}&quot;:&quot;{value}&quot;"
for key, value in params.items()
if value is not None
])
return ' ownStyles="{&quot;0&quot;:{' + style + '}}"' if style else ""


def create_vertices(
transitions_map: Mapping[tuple[int, int], tuple[int, int]],
starting_area: int,
Expand Down Expand Up @@ -63,26 +85,15 @@ def create_vertices(
output_text += (
f'<node positionX="{counter_x * 100 + counter_y * 20}" '
+ f'positionY="{counter_x * 50 + counter_y * 50}" '
+ f'id="{int(area_id)}" mainText="{area_name}"'
+ f'id="{int(area_id)}" '
+ f'mainText="{area_name}"'
)
if area_id == starting_area:
output_text += (
' ownStyles="{&quot;0&quot;:{&quot;fillStyle&quot;:&quot;'
+ STARTING_AREA_COLOR
+ '&quot;}}"'
)
output_text += create_own_style({"fillStyle": STARTING_AREA_COLOR})
elif area_id in UPGRADE_AREAS:
output_text += (
' ownStyles="{&quot;0&quot;:{&quot;fillStyle&quot;:&quot;'
+ UPGRADE_AREAS_COLOR
+ '&quot;}}"'
)
output_text += create_own_style({"fillStyle": UPGRADE_AREAS_COLOR})
elif area_id in IMPORTANT_STORY_TRIGGER_AREAS:
output_text += (
' ownStyles="{&quot;0&quot;:{&quot;fillStyle&quot;:&quot;'
+ IMPORTANT_STORY_TRIGGER_AREAS_COLOR
+ '&quot;}}"'
)
output_text += create_own_style({"fillStyle": IMPORTANT_STORY_TRIGGER_AREAS_COLOR})
output_text += "></node>\n"
row_length = 10
counter_x += 1
Expand All @@ -92,31 +103,66 @@ def create_vertices(
return output_text


def create_edges(transitions_map: Mapping[tuple[int, int], tuple[int, int]]):
connections = [(original[0], redirect[1]) for original, redirect in transitions_map.items()]
connections_two_way: list[tuple[int, int]] = []
connections_one_way: list[tuple[int, int]] = []
def edge_component(
start: int,
end: int,
counter: int,
direct: Direction,
color: str | None,
line_type: LineType,
):
direct_str = str(direct == Direction.ONEWAY).lower()
return (
f'<edge source="{TRANSITION_INFOS_DICT[start].area_id}" '
+ f'target="{TRANSITION_INFOS_DICT[end].area_id}" '
+ f'isDirect="{direct_str}" '
+ f'id="{counter}"'
+ create_own_style({
"strokeStyle": color,
"lineDash": "2" if line_type == LineType.DASHED else None,
})
+ "></edge>\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)

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'<edge source="{TRANSITION_INFOS_DICT[pairing[0]].area_id}" '
+ f'target="{TRANSITION_INFOS_DICT[pairing[1]].area_id}" isDirect="false" '
+ f'id="{counter}"></edge>\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'<edge source="{TRANSITION_INFOS_DICT[pairing[0]].area_id}" '
+ f'target="{TRANSITION_INFOS_DICT[pairing[1]].area_id}" isDirect="true" '
+ f'id="{counter}"></edge>\n'
output_text += edge_component(
pairing[0][0],
pairing[1][1],
counter,
Direction.ONEWAY,
None,
LineType.DASHED,
)
counter += 1
return output_text
Expand All @@ -134,7 +180,7 @@ def create_graphml(
'<?xml version="1.0" encoding="UTF-8"?>'
+ '<graphml><graph id="Graph" uidGraph="1" uidEdge="1">\n'
+ create_vertices(all_transitions, starting_area)
+ create_edges(all_transitions)
+ create_edges(all_transitions, shown_disabled_transitions)
+ "</graph></graphml>"
)

Expand Down