Skip to content

Commit

Permalink
Add informational styling to graph edges
Browse files Browse the repository at this point in the history
Co-authored-by: Avasam <[email protected]>
  • Loading branch information
wossnameGitHub and Avasam committed Jul 16, 2024
1 parent 59fa71d commit e425349
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 50 deletions.
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
4 changes: 2 additions & 2 deletions Dolphin scripts/Entrance Randomizer/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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():
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

0 comments on commit e425349

Please sign in to comment.