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

The Wind Waker: Implement New Game #4458

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open

Conversation

tanjo3
Copy link

@tanjo3 tanjo3 commented Jan 11, 2025

What is this fixing or adding?

This PR adds The Legend of Zelda: The Wind Waker as a supported game in Archipelago. The game uses LagoLunatic's randomizer as its base (regarding logic, options, etc.) and builds from there. Work on TWW started with Dev5ter in 2023, and I took over the project in February 2024.

The game requires an external program to randomize the ISO. This program is a modified version of Lago's randomizer that takes an APTWW file as input, which is the game's output. The program has the additional benefit of already supporting custom models, which are popular in the community. The program download can be found here: https://github.com/tanjo3/wwrando/releases/tag/ap_2.5.0. Generating multiworlds does not require this program or the vanilla ISO.

How was this tested?

Over the last year, I have produced numerous public releases of the TWW APWorld, making modifications to implement features from the base randomizer, address issues, and implement a few features unique to AP. The Wind Waker thread has many followers and recently hit the follower limit. The latest release, v2.6.1, has been out since December 31, 2024. The previous release, v2.5.2, was released in August 2024. That release was very stable, and all issues raised between that release and the current version have been fixed. I want to thank the community for their support, patience, and feedback over the last year. Without them, this would not have been possible.

If this makes graphical changes, please attach screenshots.

Adds The Wind Waker client to the AP Launcher with a custom icon.

@github-actions github-actions bot added affects: webhost Issues/PRs that touch webhost and may need additional validation. waiting-on: peer-review Issue/PR has not been reviewed by enough people yet. labels Jan 11, 2025
@ScipioWright ScipioWright added the is: new game Pull requests for implementing new games into Archipelago. label Jan 11, 2025
Copy link
Collaborator

@ScipioWright ScipioWright left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The separate_pools option for Mix Entrances frequently fails. It usually fails on assert len(nonprogress_entrances) == len(nonprogress_exits) from split_nonprogress_entrances_and_exits in Entrances.py.

This is with the different entrance randomization options set on, and most other options set to random.

worlds/tww/Items.py Outdated Show resolved Hide resolved
worlds/tww/Locations.py Show resolved Hide resolved
worlds/tww/randomizers/Charts.py Outdated Show resolved Hide resolved
worlds/tww/__init__.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/ItemPool.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/ItemPool.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/RequiredBosses.py Outdated Show resolved Hide resolved
@tanjo3
Copy link
Author

tanjo3 commented Jan 14, 2025

The randomizer build (2.5.0 pre-release) has been updated to support this latest change (ae6fed7).

@qwint qwint removed the affects: webhost Issues/PRs that touch webhost and may need additional validation. label Jan 15, 2025
worlds/tww/Rules.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/Charts.py Outdated Show resolved Hide resolved
worlds/tww/Macros.py Outdated Show resolved Hide resolved
tanjo3 and others added 2 commits January 15, 2025 18:28
Get the rule function in advance so that each call to check each
entrance's accessibility does not have to redo this work.
worlds/tww/__init__.py Outdated Show resolved Hide resolved
@ScipioWright
Copy link
Collaborator

I recommend hitting the Resolve Conversation button when you've either done the thing in a suggestion/comment or declined it, makes it easier for reviewers (and probably yourself) to see what has/hasn't been done

@tanjo3
Copy link
Author

tanjo3 commented Jan 16, 2025

Sounds good. I never really knew if I should press that in case I had resolved something unsatisfactorily; good to know for the future.

@ScipioWright
Copy link
Collaborator

Yeah, worst case the reviewer gets an Unresolve Conversation button, so it shouldn't be that big of a deal (though I'm not everyone so some may think differently)

Copy link
Contributor

@Mysteryem Mysteryem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bigger issues in this batch of reviews:

  • Nondeterministic generation for Required Bosses
  • Setting item rules in pre_fill is too late
  • I forgot to update fill_slot_data when removing the intermediate entrances and entrance regions

worlds/tww/randomizers/Entrances.py Outdated Show resolved Hide resolved
worlds/tww/__init__.py Outdated Show resolved Hide resolved
worlds/tww/__init__.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/Entrances.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/Dungeons.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/RequiredBosses.py Outdated Show resolved Hide resolved
worlds/tww/randomizers/RequiredBosses.py Outdated Show resolved Hide resolved
worlds/tww/__init__.py Show resolved Hide resolved
worlds/tww/__init__.py Outdated Show resolved Hide resolved
worlds/tww/__init__.py Outdated Show resolved Hide resolved

# Defeat Ganondorf
"Defeat Ganondorf": TWWLocationData(
None, TWWFlag.ALWAYS, "The Great Sea", 0x8, TWWLocationType.SWTCH, 64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that beyond this PR, it is going to be beneficial to rework some of the location and region logic to include additional inner/sub-regions and use rules on entrances between those regions to break up logic.

Running generation with cProfile reveals many dungeon and ganon access rules are taking up more time/calls than others.
In Generate.py, find multiworld = ERMain(erargs, seed) and replace it with:

    import cProfile
    from pstats import Stats, SortKey
    with cProfile.Profile() as pf:
        multiworld = ERmain(erargs, seed)
    # print first 50 lines sorted by cumulative duration
    Stats(pf).sort_stats(SortKey.CUMULATIVE).print_stats(50)

Note that cProfile is less accurate for very quick functions, since it incurs some overhead. It's a useful tool, but take that into account when using it.


The "Defeat Ganondorf" location has once of more complicated access rules in TWW, but it is added to the "The Great Sea" region, which is the starting region, meaning that it will constantly be checked for being reachable.

Many of the dungeon locations closer to the end of dungeons have similar issues in that they include longer, chained rules for reaching that point of the dungeon.

For example, there are 4 locations that check can_reach_earth_temple_many_mirrors_room() in their access rule.
can_reach_earth_temple_many_mirrors_room(), first checks can_reach_earth_temple_tall_vine_room(),
which first checks can_reach_earth_temple_third_crypt(),
which first checks can_reach_earth_temple_redead_hub_room(),
which first checks can_reach_earth_temple_basement(),
which first checks can_reach_earth_temple_sun_statue_room(),
which first checks can_play_command_melody().
can_play_command_melody() is finally the first part of the can_reach_earth_temple_many_mirrors_room() rule that actually checks the state.

These 4 locations are in the Earth Temple region, so when the Earth Temple region is accessible, the access rules of those locations will be checked.

It would likely be beneficial to create sub-regions within dungeons to avoid checking such long chained rules. Changing the order that rules are checked within each function, so that more complex/chained rules are checked last, and simpler rules are checked first may also help.

In the future, I could imagine there being Hyrule and Ganon's Tower regions.
The Great Sea would connect to Hyrule using the has_all_8_triforce_shards() rule. Miniboss Entrance in Hyrule Castle would be placed in the Hyrule region.
Hyrule would connect to Ganon's Tower using the can_access_ganons_tower rule, but with can_access_hyrule removed from can_get_past_hyrule_barrier because that part of the logic will now be controlled by the The Great Sea -> Hyrule entrance. The Ganon's Tower locations would be placed in the Ganon's Tower region.

For dungeons, it is less clear how best it would be to break up regions because I'm not sure there are locations present in every room with some logic tied to it, but otherwise, every room that has a presence in rules, like can_reach_earth_temple_<room name> could become a region with entrances connected them to other rooms.

The 4 locations that check can_reach_earth_temple_many_mirrors_room() could then go in an Earth Temple - Many Mirrors Room region for example, which has a connection from Earth Temple - Tall Vine Room etc.

worlds/tww/__init__.py Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
is: new game Pull requests for implementing new games into Archipelago. waiting-on: peer-review Issue/PR has not been reviewed by enough people yet.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants