Files
Grinch-AP/worlds/tunic/ladder_storage_data.py
Scipio Wright b0b3e3668f TUNIC: The Big Refactor (#5195)
* Make it actually return false if it gets to the backup lists and fails them

* Fix stuff after merge

* Add outlet regions, create new regions as needed for them

* Put together part of decoupled and direction pairs

* make direction pairs work

* Make decoupled work

* Make fixed shop work again

* Fix a few minor bugs

* Fix a few minor bugs

* Fix plando

* god i love programming

* Reorder portal list

* Update portal sorter for variable shops

* Add missing parameter

* Some cleanup of prints and functions

* Fix typo

* it's aliiiiiive

* Make seed groups not sync decoupled

* Add test with full-shop plando

* Fix bug with vanilla portals

* Handle plando connections and direction pair errors

* Update plando checking for decoupled

* Fix typo

* Fix exception text to be shorter

* Add some more comments

* Add todo note

* Remove unused safety thing

* Remove extra plando connections definition in options

* Make seed groups in decoupled with overlapping but not fully overlapped plando connections interact nicely without messing with what the entrances look like in the spoiler log

* Fix weird edge case that is technically user error

* Add note to fixed shop

* Fix parsing shop names in UT

* Remove debug print

* Actually make UT work

* multiworld. to world.

* Fix typo from merge

* Make it so the shops show up in the entrance hints

* Fix bug in ladder storage rules

* Remove blank line

* # Conflicts:
#	worlds/tunic/__init__.py
#	worlds/tunic/er_data.py
#	worlds/tunic/er_rules.py
#	worlds/tunic/er_scripts.py
#	worlds/tunic/rules.py
#	worlds/tunic/test/test_access.py

* Fix issues after merge

* Update plando connections stuff in docs

* Make early bushes only contain grass

* Fix library mistake

* Backport changes to grass rando (#20)

* Backport changes to grass rando

* add_rule instead of set_rule for the special cases, add special cases for back of swamp laurels area cause I should've made a new region for the swamp upper entrance

* Remove item name group for grass

* Update grass rando option descriptions

- Also ignore grass fill for single player games

* Ignore grass fill option for solo rando

* Update er_rules.py

* Fix pre fill issue

* Remove duplicate option

* Add excluded grass locations back

* Hide grass fill option from simple ui options page

* Check for start with sword before setting grass rules

* Update worlds/tunic/options.py

Co-authored-by: Scipio Wright <scipiowright@gmail.com>

* has_stick -> has_melee

* has_stick -> has_melee

* Add a failsafe for direction pairing

* Fix playthrough crash bug

* Remove init from logicmixin

* Updates per code review (thanks hesto)

* has_stick to has_melee in newer update

* has_stick to has_melee in newer update

* Exclude grass from get_filler_item_name

- non-grass rando games were accidentally seeing grass items get shuffled in as filler, which is funny but probably shouldn't happen

* Update worlds/tunic/__init__.py

Co-authored-by: Scipio Wright <scipiowright@gmail.com>

* Apply suggestions from code review

Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
Co-authored-by: Scipio Wright <scipiowright@gmail.com>

* change the rest of grass_fill to local_fill

* Filter out grass from filler_items

* remove -> discard

* Update worlds/tunic/__init__.py

Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>

* Starting out

* Rules for breakable regions

* # Conflicts:
#	worlds/tunic/__init__.py
#	worlds/tunic/combat_logic.py
#	worlds/tunic/er_data.py
#	worlds/tunic/er_rules.py
#	worlds/tunic/er_scripts.py

* Cleanup more stuff after merge

* Revert "Cleanup more stuff after merge"

This reverts commit a6ee9a93da8f2fcc4413de6df6927b246017889d.

* Revert "# Conflicts:"

This reverts commit c74ccd74a45b6ad6b9abe6e339d115a0c98baf30.

* Cleanup more stuff after merge

* change has_stick to has_melee

* Update grass list with combat logic regions

* More fixes from combat logic merge

* Fix some dumb stuff (#21)

* Reorganize pre fill for grass

* make the rest of it work, it's pr ready, boom

* Make it work in not pot shuffle

* Merge grass rando

* multiworld -> world get_location, use has_any

* Swap out region for West Garden Before Terry grass

* Adjust west garden rules to add west combat region

* Adjust grass regions for south checkpoint grass

* Adjust grass regions for after terry grass

* Adjust grass regions for west combat grass

* Adjust grass regions for dagger house grass

* Adjust grass regions for south checkpoint grass, adjust regions and rules for some related locations

* Finish the remainder of the west garden grass, reformat ruined atoll a little

* More hex quest updates

- Implement page ability shuffle for hex quest
- Fix keys behind bosses if hex goal is less than 3
- Added check to fix conflicting hex quest options
- Add option to slot data

* Change option comparison

* Change option checking and fix some stuff

- also keep prayer first on low hex counts

* Update option defaulting

* Update option checking

* Fix option assignment again

* Merge in hex hunt

* Merge in changes

* Clean up imports

* Add ability type to UT stuff

* merge it all

* Make local fill work across pot and grass (to be adjusted later)

* Make separate pools for the grass and non-grass fills

* Fix id overlap

* Update option description

* Fix default

* Reorder localfill option desc

* Load the purgatory ones in

* Adjustments after merge

* Fully remove logicrules

* Fix UT support with fixed shop option

* Add breakable shuffle to the ut stuff

* Make it load in a specific number of locations

* Add Silent's spoiler log ability thing

* Fix for groups

* Fix for groups

* Fix typo

* Fix hex quest UT support

* Use .get

* UT fixes, classification fixes

* Rename some locations

* Adjust guard house names

* Adjust guard house names

* Rework create_item

* Fix for plando connections

* Rename, add new breakables

* Rename more stuff

* Time to rename them again

* Fix issue with fixed shop + decoupled

* Put in an exception to catch that error in the future

* Update create_item to match main

* Update spoiler log lines for hex abilities

* Burn the signs down

* Bring over the combat logic fix

* Merge in combat logic fix

* Silly static method thing

* Move a few areas to before well instead of east forest

* Add an all_random hidden option for dev stuff

* Port over changes from main

* Fix west courtyard pot regions

* Remove debug prints

* Fix fortress courtyard and beneath the fortress loc groups again

* Add exception handling to deal with duplicate apworlds

* Fix typo

* More missing loc group conversions

* Initial fuse shuffle stuff

* Fix gun missing from combat_items, add new for combat logic cache, very slight refactor of check_combat_reqs to let it do the changeover in a less complicated fashion, fix area being a boss area rather than non-boss area for a check

* Add fuse shuffle logic

* reorder atoll statue rule

* Update traversal reqs

* Remove fuse shuffle from temple door

* Combine rules and option checking

* Add bell shuffle; fix fuse location groups

* Fix portal rules not requiring prayer

* Merge the grass laurels exit grass PR

* Merge in fortress bridge PR

* Do a little clean up

* Fix a regression

* Update after merge

* Some more stuff

* More Silent changes

* Update more info section in game info page

* Fix rules for atoll and swamp fuses

* Precollect cathedral fuse in ER

* actually just make the fuse useful instead of progression

* Add it to the swamp and cath rules too

* Fix cath fuse name

* Minor fixes and edits

* Some UT stuff

* Fix a couple more groups

* Move a bunch of UT stuff to its own file

* Fix up a couple UT things

* Couple minor ER fixes

* Formatting change

* UT poptracker stuff enabled since it's optional in one of the releases

* Add author string to world class

* Adjust local fill option name

* Update ut_stuff to match the PR

* Add exception handling for UT with old apworld

* Fix missing tracker_world

* Remove extra entrance from cath main -> elevator

Entry <-> Elev exists,
Entry <-> Main exists
So no connection is needed between Main and Elev

* Fix so that decoupled doesn't incorrectly use get_portal_info and get_paired_portal

* Fix so that decoupled doesn't incorrectly use get_portal_info and get_paired_portal

* Update for breakables poptracker

* Backup and warnings instead

* Update typing

* Delete old regions and rules, move stuff to logic_helpers and constants

* Delete now much less useful tests

* Fix breakables map tracking

* Add more comments to init

* Add todo to grass.py

* Fix up tests

* Pull out fuse and bell shuffle

* Pull out fuse and bell shuffle

* Update worlds/tunic/options.py

Co-authored-by: qwint <qwint.42@gmail.com>

* Update worlds/tunic/logic_helpers.py

Co-authored-by: qwint <qwint.42@gmail.com>

* {} -> () in state functions

* {} -> () in state functions

* Change {} -> () in state functions, use constant for gun

* Remove floating constants in er_data

* Finish hard deprecating FixedShop

* Finish hard deprecating FixedShop

* Fix zig skip showing up in decoupled fixed shop

---------

Co-authored-by: silent-destroyer <osilentdestroyer@gmail.com>
Co-authored-by: Silent <110704408+silent-destroyer@users.noreply.github.com>
Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
Co-authored-by: qwint <qwint.42@gmail.com>
2025-09-05 00:44:32 +02:00

190 lines
11 KiB
Python

from typing import NamedTuple
# ladders in overworld, since it is the most complex area for ladder storage
class OWLadderInfo(NamedTuple):
ladders: set[str] # ladders where the top or bottom is at the same elevation
portals: list[str] # portals at the same elevation, only those without doors
regions: list[str] # regions where a melee enemy can hit you out of ladder storage
# groups for ladders at the same elevation, for use in determing whether you can ls to entrances in diff rulesets
ow_ladder_groups: dict[str, OWLadderInfo] = {
# lowest elevation
"LS Elev 0": OWLadderInfo({"Ladders in Overworld Town", "Ladder to Ruined Atoll", "Ladder to Swamp"},
["Swamp Redux 2_conduit", "Overworld Cave_", "Atoll Redux_lower", "Maze Room_",
"Town Basement_beach", "Archipelagos Redux_lower", "Archipelagos Redux_lowest"],
["Overworld Beach"]),
# also the east filigree room
"LS Elev 1": OWLadderInfo({"Ladders near Weathervane", "Ladders in Overworld Town", "Ladder to Swamp"},
["Furnace_gyro_lower", "Furnace_gyro_west", "Swamp Redux 2_wall"],
["Overworld Tunnel Turret"]),
# also the fountain filigree room and ruined passage door
"LS Elev 2": OWLadderInfo({"Ladders near Weathervane", "Ladders to West Bell"},
["Archipelagos Redux_upper", "Ruins Passage_east"],
["After Ruined Passage"]),
# also old house door
"LS Elev 3": OWLadderInfo({"Ladders near Weathervane", "Ladder to Quarry", "Ladders to West Bell",
"Ladders in Overworld Town"},
[],
["Overworld after Envoy", "East Overworld"]),
# skip top of top ladder next to weathervane level, does not provide logical access to anything
"LS Elev 4": OWLadderInfo({"Ladders near Dark Tomb", "Ladder to Quarry", "Ladders to West Bell", "Ladders in Well",
"Ladders in Overworld Town"},
["Darkwoods Tunnel_"],
[]),
"LS Elev 5": OWLadderInfo({"Ladders near Overworld Checkpoint", "Ladders near Patrol Cave"},
["PatrolCave_", "Forest Belltower_", "Fortress Courtyard_", "ShopSpecial_"],
["East Overworld"]),
# skip top of belltower, middle of dark tomb ladders, and top of checkpoint, does not grant access to anything
"LS Elev 6": OWLadderInfo({"Ladders near Patrol Cave", "Ladder near Temple Rafters"},
["Temple_rafters"],
["Overworld above Patrol Cave"]),
# in-line with the chest above dark tomb, gets you up the mountain stairs
"LS Elev 7": OWLadderInfo({"Ladders near Patrol Cave", "Ladder near Temple Rafters", "Ladders near Dark Tomb"},
["Mountain_"],
["Upper Overworld"]),
}
# ladders accessible within different regions of overworld, only those that are relevant
# other scenes will just have them hardcoded since this type of structure is not necessary there
region_ladders: dict[str, set[str]] = {
"Overworld": {"Ladders near Weathervane", "Ladders near Overworld Checkpoint", "Ladders near Dark Tomb",
"Ladders in Overworld Town", "Ladder to Swamp", "Ladders in Well"},
"Overworld Beach": {"Ladder to Ruined Atoll"},
"Overworld at Patrol Cave": {"Ladders near Patrol Cave"},
"Overworld Quarry Entry": {"Ladder to Quarry"},
"Overworld Belltower": {"Ladders to West Bell"},
"Overworld after Temple Rafters": {"Ladders near Temple Rafters"},
}
class LadderInfo(NamedTuple):
origin: str # origin region
destination: str # destination portal
ladders_req: str | None = None # ladders required to do this
dest_is_region: bool = False # whether it is a region that you are going to
easy_ls: list[LadderInfo] = [
# In the furnace
# Furnace ladder to the fuse entrance
LadderInfo("Furnace Ladder Area", "Furnace, Overworld Redux_gyro_upper_north"),
# Furnace ladder to Dark Tomb
LadderInfo("Furnace Ladder Area", "Furnace, Crypt Redux_"),
# Furnace ladder to the West Garden connector
LadderInfo("Furnace Ladder Area", "Furnace, Overworld Redux_gyro_west"),
# West Garden
# exit after Garden Knight
LadderInfo("West Garden before Boss", "Archipelagos Redux, Overworld Redux_upper"),
# West Garden laurels exit
LadderInfo("West Garden after Terry", "Archipelagos Redux, Overworld Redux_lowest"),
# Magic dagger house, only relevant with combat logic on
LadderInfo("West Garden after Terry", "Archipelagos Redux, archipelagos_house_"),
# Atoll, use the little ladder you fix at the beginning
LadderInfo("Ruined Atoll", "Atoll Redux, Overworld Redux_lower"),
LadderInfo("Ruined Atoll", "Atoll Redux, Frog Stairs_mouth"), # special case
# East Forest
# Entrance by the dancing fox holy cross spot
LadderInfo("East Forest", "East Forest Redux, East Forest Redux Laddercave_upper"),
# From the west side of Guard House 1 to the east side
LadderInfo("Guard House 1 West", "East Forest Redux Laddercave, East Forest Redux_gate"),
LadderInfo("Guard House 1 West", "East Forest Redux Laddercave, Forest Boss Room_"),
# Fortress Exterior
# shop, ls at the ladder by the telescope
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard, Shop_"),
# Fortress main entry and grave path lower entry, ls at the ladder by the telescope
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress Main_Big Door"),
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress Reliquary_Lower"),
# Use the top of the ladder by the telescope
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress Reliquary_Upper"),
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress East_"),
# same as above, except from the east side of the area
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard, Overworld Redux_"),
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard, Shop_"),
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress Main_Big Door"),
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress Reliquary_Lower"),
# same as above, except from the Beneath the Vault entrance ladder
LadderInfo("Fortress Exterior near cave", "Fortress Courtyard, Overworld Redux_", "Ladder to Beneath the Vault"),
LadderInfo("Fortress Exterior near cave", "Fortress Courtyard, Fortress Main_Big Door",
"Ladder to Beneath the Vault"),
LadderInfo("Fortress Exterior near cave", "Fortress Courtyard, Fortress Reliquary_Lower",
"Ladder to Beneath the Vault"),
# Swamp to Gauntlet
LadderInfo("Swamp Mid", "Swamp Redux 2, Cathedral Arena_", "Ladders in Swamp"),
# Ladder by the hero grave
LadderInfo("Back of Swamp", "Swamp Redux 2, Overworld Redux_conduit"),
LadderInfo("Back of Swamp", "Swamp Redux 2, Shop_"),
]
# if we can gain elevation or get knocked down, add the harder ones
medium_ls: list[LadderInfo] = [
# region-destination versions of easy ls spots
LadderInfo("East Forest", "East Forest Dance Fox Spot", dest_is_region=True),
# fortress courtyard knockdowns are never logically relevant, the fuse requires upper
LadderInfo("Back of Swamp", "Swamp Mid", dest_is_region=True),
LadderInfo("Back of Swamp", "Swamp Front", dest_is_region=True),
# gain height off the northeast fuse ramp
LadderInfo("Ruined Atoll", "Atoll Redux, Frog Stairs_eye"),
# Upper exit from the Forest Grave Path, use LS at the ladder by the gate switch
LadderInfo("Forest Grave Path Main", "Sword Access, East Forest Redux_upper"),
# Upper exits from the courtyard. Use the ramp in the courtyard, then the blocks north of the first fuse
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard Upper", dest_is_region=True),
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress Reliquary_Upper"),
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress East_"),
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard Upper", dest_is_region=True),
LadderInfo("Fortress Exterior near cave", "Fortress Courtyard, Fortress Reliquary_Upper",
"Ladder to Beneath the Vault"),
LadderInfo("Fortress Exterior near cave", "Fortress Courtyard, Fortress East_", "Ladder to Beneath the Vault"),
LadderInfo("Fortress Exterior near cave", "Fortress Courtyard Upper", "Ladder to Beneath the Vault",
dest_is_region=True),
# need to gain height to get up the stairs
LadderInfo("Lower Mountain", "Mountain, Mountaintop_"),
# Where the rope is behind Monastery
LadderInfo("Quarry Entry", "Quarry Redux, Monastery_back"),
LadderInfo("Quarry Monastery Entry", "Quarry Redux, Monastery_back"),
LadderInfo("Quarry Back", "Quarry Redux, Monastery_back"),
LadderInfo("Rooted Ziggurat Lower Back", "ziggurat2020_3, ziggurat2020_2_"),
LadderInfo("Rooted Ziggurat Lower Back", "Rooted Ziggurat Lower Entry", dest_is_region=True),
LadderInfo("Rooted Ziggurat Lower Back", "Rooted Ziggurat Lower Mid Checkpoint", dest_is_region=True),
# Swamp to Overworld upper
LadderInfo("Swamp Mid", "Swamp Redux 2, Overworld Redux_wall", "Ladders in Swamp"),
LadderInfo("Back of Swamp", "Swamp Redux 2, Overworld Redux_wall"),
]
hard_ls: list[LadderInfo] = [
# lower ladder, go into the waterfall then above the bonfire, up a ramp, then through the right wall
LadderInfo("Beneath the Well Front", "Sewer, Sewer_Boss_", "Ladders in Well"),
LadderInfo("Beneath the Well Front", "Sewer, Overworld Redux_west_aqueduct", "Ladders in Well"),
LadderInfo("Beneath the Well Front", "Beneath the Well Back", "Ladders in Well", dest_is_region=True),
# go through the hexagon engraving above the vault door
LadderInfo("Frog's Domain Front", "frog cave main, Frog Stairs_Exit", "Ladders to Frog's Domain"),
# the turret at the end here is not affected by enemy rando
LadderInfo("Frog's Domain Front", "Frog's Domain Back", "Ladders to Frog's Domain", dest_is_region=True),
# todo: see if we can use that new laurels strat here
# LadderInfo("Rooted Ziggurat Lower Back", "ziggurat2020_3, ziggurat2020_FTRoom_"),
# go behind the cathedral to reach the door, pretty easily doable
LadderInfo("Swamp Mid", "Swamp Redux 2, Cathedral Redux_main", "Ladders in Swamp"),
LadderInfo("Back of Swamp", "Swamp Redux 2, Cathedral Redux_main"),
# need to do hc midair, probably cannot get into this without hc
LadderInfo("Swamp Mid", "Swamp Redux 2, Cathedral Redux_secret", "Ladders in Swamp"),
LadderInfo("Back of Swamp", "Swamp Redux 2, Cathedral Redux_secret"),
]