mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-04-04 13:23:40 -07:00
Finish the ladder storage rules
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
from typing import Dict, Set, List, Tuple, TYPE_CHECKING
|
||||
from typing import Dict, Set, Tuple, Optional, TYPE_CHECKING
|
||||
from worlds.generic.Rules import set_rule, forbid_item
|
||||
from .options import IceGrappling, LadderStorage
|
||||
from .rules import (has_ability, has_sword, has_stick, has_ice_grapple_logic, has_lantern, has_mask, can_ladder_storage,
|
||||
laurels_zip)
|
||||
from .er_data import Portal
|
||||
from .ladder_storage_data import ow_ladder_groups, region_ladders
|
||||
from .ladder_storage_data import ow_ladder_groups, region_ladders, easy_ls, medium_ls, hard_ls
|
||||
from BaseClasses import Region, CollectionState
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -1009,11 +1009,25 @@ def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_
|
||||
return portal2.name, portal1.region
|
||||
raise Exception("no matches found in get_paired_region")
|
||||
|
||||
def ls_connect(ladder_elev: str, portal_sdt: str) -> None:
|
||||
def ls_connect(origin_name: str, portal_sdt: str, ladder_req: Optional[str] = None) -> None:
|
||||
p_name, paired_region_name = get_portal_info(portal_sdt)
|
||||
ladder_regions[ladder_elev].connect(
|
||||
regions[paired_region_name],
|
||||
name=p_name + " (LS) " + ladder_elev)
|
||||
if ladder_req:
|
||||
ladder_regions[origin_name].connect(
|
||||
regions[paired_region_name],
|
||||
name=p_name + " (LS) " + origin_name,
|
||||
rule=lambda state: can_ladder_storage(state, world) and state.has(ladder_req, player))
|
||||
else:
|
||||
ladder_regions[origin_name].connect(
|
||||
regions[paired_region_name],
|
||||
name=p_name + " (LS) " + origin_name,
|
||||
rule=lambda state: can_ladder_storage(state, world))
|
||||
|
||||
non_ow_ls_list = []
|
||||
non_ow_ls_list.extend(easy_ls)
|
||||
if options.ladder_storage >= LadderStorage.option_medium:
|
||||
non_ow_ls_list.extend(medium_ls)
|
||||
if options.ladder_storage >= LadderStorage.option_hard:
|
||||
non_ow_ls_list.extend(hard_ls)
|
||||
|
||||
# create the ls elevation regions
|
||||
ladder_regions: Dict[str, Region] = {}
|
||||
@@ -1031,7 +1045,8 @@ def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_
|
||||
common_ladders: Set[str] = ladders.intersection(region_info.ladders)
|
||||
if common_ladders:
|
||||
regions[origin_region].connect(ladder_regions[ladder_region],
|
||||
rule=lambda state: state.has_any(common_ladders, player))
|
||||
rule=lambda state: state.has_any(common_ladders, player)
|
||||
and can_ladder_storage(state, world))
|
||||
|
||||
# connect ls elevation regions to the region on the other side of the portals
|
||||
for ladder_region, region_info in ow_ladder_groups.items():
|
||||
@@ -1052,335 +1067,40 @@ def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_
|
||||
ls_connect("LS Elev 2", "Overworld Redux, Town_FiligreeRoom_")
|
||||
ls_connect("LS Elev 3", "Overworld Redux, Overworld Interiors_house")
|
||||
ls_connect("LS Elev 5", "Overworld Redux, Temple_main")
|
||||
# todo: add ls in other areas
|
||||
# todo: add rules when er is off
|
||||
|
||||
# connecting the regions portals are in to other portals you can access via ladder storage
|
||||
# using has_stick instead of can_ladder_storage since it's already checking the logic rules
|
||||
if options.logic_rules == "unrestricted":
|
||||
def get_portal_info(portal_sd: str) -> Tuple[str, str]:
|
||||
for portal1, portal2 in portal_pairs.items():
|
||||
if portal1.scene_destination() == portal_sd:
|
||||
return portal1.name, portal2.region
|
||||
if portal2.scene_destination() == portal_sd:
|
||||
return portal2.name, portal1.region
|
||||
raise Exception("no matches found in get_paired_region")
|
||||
|
||||
ladder_storages: List[Tuple[str, str, Set[str]]] = [
|
||||
# LS from Overworld main
|
||||
# The upper Swamp entrance
|
||||
("Overworld", "Overworld Redux, Swamp Redux 2_wall",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town"}),
|
||||
# Upper atoll entrance
|
||||
("Overworld", "Overworld Redux, Atoll Redux_upper",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town"}),
|
||||
# Furnace entrance, next to the sign that leads to West Garden
|
||||
("Overworld", "Overworld Redux, Furnace_gyro_west",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town"}),
|
||||
# Upper West Garden entry, by the belltower
|
||||
("Overworld", "Overworld Redux, Archipelagos Redux_upper",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town"}),
|
||||
# Ruined Passage
|
||||
("Overworld", "Overworld Redux, Ruins Passage_east",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town"}),
|
||||
# Well rail, west side. Can ls in town, get extra height by going over the portal pad
|
||||
("Overworld", "Overworld Redux, Sewer_west_aqueduct",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladder to Quarry"}),
|
||||
# Well rail, east side. Need some height from the temple stairs
|
||||
("Overworld", "Overworld Redux, Furnace_gyro_upper_north",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladder to Quarry"}),
|
||||
# Quarry entry
|
||||
("Overworld", "Overworld Redux, Darkwoods Tunnel_",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladders in Well"}),
|
||||
# East Forest entry
|
||||
("Overworld", "Overworld Redux, Forest Belltower_",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladders in Well",
|
||||
"Ladders near Patrol Cave", "Ladder to Quarry", "Ladders near Dark Tomb"}),
|
||||
# Fortress entry
|
||||
("Overworld", "Overworld Redux, Fortress Courtyard_",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladders in Well",
|
||||
"Ladders near Patrol Cave", "Ladder to Quarry", "Ladders near Dark Tomb"}),
|
||||
# Patrol Cave entry
|
||||
("Overworld", "Overworld Redux, PatrolCave_",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladders in Well",
|
||||
"Ladders near Overworld Checkpoint", "Ladder to Quarry", "Ladders near Dark Tomb"}),
|
||||
# Special Shop entry, excluded in non-ER due to soft lock potential
|
||||
("Overworld", "Overworld Redux, ShopSpecial_",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladders in Well",
|
||||
"Ladders near Overworld Checkpoint", "Ladders near Patrol Cave", "Ladder to Quarry",
|
||||
"Ladders near Dark Tomb"}),
|
||||
# Temple Rafters, excluded in non-ER + ladder rando due to soft lock potential
|
||||
("Overworld", "Overworld Redux, Temple_rafters",
|
||||
{"Ladders near Weathervane", "Ladder to Swamp", "Ladders in Overworld Town", "Ladders in Well",
|
||||
"Ladders near Overworld Checkpoint", "Ladders near Patrol Cave", "Ladder to Quarry",
|
||||
"Ladders near Dark Tomb"}),
|
||||
# Spot above the Quarry entrance,
|
||||
# only gets you to the mountain stairs
|
||||
("Overworld above Quarry Entrance", "Overworld Redux, Mountain_",
|
||||
{"Ladders near Dark Tomb"}),
|
||||
|
||||
# LS from the Overworld Beach
|
||||
# West Garden entry by the Furnace
|
||||
("Overworld Beach", "Overworld Redux, Archipelagos Redux_lower",
|
||||
{"Ladders in Overworld Town", "Ladder to Ruined Atoll"}),
|
||||
# West Garden laurels entry
|
||||
("Overworld Beach", "Overworld Redux, Archipelagos Redux_lowest",
|
||||
{"Ladders in Overworld Town", "Ladder to Ruined Atoll"}),
|
||||
# Swamp lower entrance
|
||||
("Overworld Beach", "Overworld Redux, Swamp Redux 2_conduit",
|
||||
{"Ladders in Overworld Town", "Ladder to Ruined Atoll"}),
|
||||
# Rotating Lights entrance
|
||||
("Overworld Beach", "Overworld Redux, Overworld Cave_",
|
||||
{"Ladders in Overworld Town", "Ladder to Ruined Atoll"}),
|
||||
# Swamp upper entrance
|
||||
("Overworld Beach", "Overworld Redux, Swamp Redux 2_wall",
|
||||
{"Ladder to Ruined Atoll"}),
|
||||
# Furnace entrance, next to the sign that leads to West Garden
|
||||
("Overworld Beach", "Overworld Redux, Furnace_gyro_west",
|
||||
{"Ladder to Ruined Atoll"}),
|
||||
# Upper West Garden entry, by the belltower
|
||||
("Overworld Beach", "Overworld Redux, Archipelagos Redux_upper",
|
||||
{"Ladder to Ruined Atoll"}),
|
||||
# Ruined Passage
|
||||
("Overworld Beach", "Overworld Redux, Ruins Passage_east",
|
||||
{"Ladder to Ruined Atoll"}),
|
||||
# Well rail, west side. Can ls in town, get extra height by going over the portal pad
|
||||
("Overworld Beach", "Overworld Redux, Sewer_west_aqueduct",
|
||||
{"Ladder to Ruined Atoll"}),
|
||||
# Well rail, east side. Need some height from the temple stairs
|
||||
("Overworld Beach", "Overworld Redux, Furnace_gyro_upper_north",
|
||||
{"Ladder to Ruined Atoll"}),
|
||||
# Quarry entry
|
||||
("Overworld Beach", "Overworld Redux, Darkwoods Tunnel_",
|
||||
{"Ladder to Ruined Atoll"}),
|
||||
|
||||
# LS from that low spot where you normally walk to swamp
|
||||
# Only has low ones you can't get to from main Overworld
|
||||
# West Garden main entry from swamp ladder
|
||||
("Overworld Swamp Lower Entry", "Overworld Redux, Archipelagos Redux_lower",
|
||||
{"Ladder to Swamp"}),
|
||||
# Maze Cave entry from swamp ladder
|
||||
("Overworld Swamp Lower Entry", "Overworld Redux, Maze Room_",
|
||||
{"Ladder to Swamp"}),
|
||||
# Hourglass Cave entry from swamp ladder
|
||||
("Overworld Swamp Lower Entry", "Overworld Redux, Town Basement_beach",
|
||||
{"Ladder to Swamp"}),
|
||||
# Lower Atoll entry from swamp ladder
|
||||
("Overworld Swamp Lower Entry", "Overworld Redux, Atoll Redux_lower",
|
||||
{"Ladder to Swamp"}),
|
||||
# Lowest West Garden entry from swamp ladder
|
||||
("Overworld Swamp Lower Entry", "Overworld Redux, Archipelagos Redux_lowest",
|
||||
{"Ladder to Swamp"}),
|
||||
|
||||
# from the ladders by the belltower
|
||||
# Ruined Passage
|
||||
("Overworld to West Garden Upper", "Overworld Redux, Ruins Passage_east",
|
||||
{"Ladders to West Bell"}),
|
||||
# Well rail, west side. Can ls in town, get extra height by going over the portal pad
|
||||
("Overworld to West Garden Upper", "Overworld Redux, Sewer_west_aqueduct",
|
||||
{"Ladders to West Bell"}),
|
||||
# Well rail, east side. Need some height from the temple stairs
|
||||
("Overworld to West Garden Upper", "Overworld Redux, Furnace_gyro_upper_north",
|
||||
{"Ladders to West Bell"}),
|
||||
# Quarry entry
|
||||
("Overworld to West Garden Upper", "Overworld Redux, Darkwoods Tunnel_",
|
||||
{"Ladders to West Bell"}),
|
||||
# East Forest entry
|
||||
("Overworld to West Garden Upper", "Overworld Redux, Forest Belltower_",
|
||||
{"Ladders to West Bell"}),
|
||||
# Fortress entry
|
||||
("Overworld to West Garden Upper", "Overworld Redux, Fortress Courtyard_",
|
||||
{"Ladders to West Bell"}),
|
||||
# Patrol Cave entry
|
||||
("Overworld to West Garden Upper", "Overworld Redux, PatrolCave_",
|
||||
{"Ladders to West Bell"}),
|
||||
# Special Shop entry, excluded in non-ER due to soft lock potential
|
||||
("Overworld to West Garden Upper", "Overworld Redux, ShopSpecial_",
|
||||
{"Ladders to West Bell"}),
|
||||
# Temple Rafters, excluded in non-ER and ladder rando due to soft lock potential
|
||||
("Overworld to West Garden Upper", "Overworld Redux, Temple_rafters",
|
||||
{"Ladders to West Bell"}),
|
||||
|
||||
# In the furnace
|
||||
# Furnace ladder to the fuse entrance
|
||||
("Furnace Ladder Area", "Furnace, Overworld Redux_gyro_upper_north", set()),
|
||||
# Furnace ladder to Dark Tomb
|
||||
("Furnace Ladder Area", "Furnace, Crypt Redux_", set()),
|
||||
# Furnace ladder to the West Garden connector
|
||||
("Furnace Ladder Area", "Furnace, Overworld Redux_gyro_west", set()),
|
||||
|
||||
# West Garden
|
||||
# exit after Garden Knight
|
||||
("West Garden", "Archipelagos Redux, Overworld Redux_upper", set()),
|
||||
# West Garden laurels exit
|
||||
("West Garden", "Archipelagos Redux, Overworld Redux_lowest", set()),
|
||||
|
||||
# Atoll, use the little ladder you fix at the beginning
|
||||
("Ruined Atoll", "Atoll Redux, Overworld Redux_lower", set()),
|
||||
("Ruined Atoll", "Atoll Redux, Frog Stairs_mouth", set()),
|
||||
("Ruined Atoll", "Atoll Redux, Frog Stairs_eye", set()),
|
||||
|
||||
# East Forest
|
||||
# Entrance by the dancing fox holy cross spot
|
||||
("East Forest", "East Forest Redux, East Forest Redux Laddercave_upper", set()),
|
||||
|
||||
# From the west side of Guard House 1 to the east side
|
||||
("Guard House 1 West", "East Forest Redux Laddercave, East Forest Redux_gate", set()),
|
||||
("Guard House 1 West", "East Forest Redux Laddercave, Forest Boss Room_", set()),
|
||||
|
||||
# Upper exit from the Forest Grave Path, use LS at the ladder by the gate switch
|
||||
("Forest Grave Path Main", "Sword Access, East Forest Redux_upper", set()),
|
||||
|
||||
# Fortress Exterior
|
||||
# shop, ls at the ladder by the telescope
|
||||
("Fortress Exterior from Overworld", "Fortress Courtyard, Shop_", set()),
|
||||
# Fortress main entry and grave path lower entry, ls at the ladder by the telescope
|
||||
("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress Main_Big Door", set()),
|
||||
("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress Reliquary_Lower", set()),
|
||||
# Upper exits from the courtyard. Use the ramp in the courtyard, then the blocks north of the first fuse
|
||||
("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress Reliquary_Upper", set()),
|
||||
("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress East_", set()),
|
||||
|
||||
# same as above, except from the east side of the area
|
||||
("Fortress Exterior from East Forest", "Fortress Courtyard, Overworld Redux_", set()),
|
||||
("Fortress Exterior from East Forest", "Fortress Courtyard, Shop_", set()),
|
||||
("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress Main_Big Door", set()),
|
||||
("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress Reliquary_Lower", set()),
|
||||
("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress Reliquary_Upper", set()),
|
||||
("Fortress Exterior from East Forest", "Fortress Courtyard, Fortress East_", set()),
|
||||
|
||||
# same as above, except from the Beneath the Vault entrance ladder
|
||||
("Fortress Exterior near cave", "Fortress Courtyard, Overworld Redux_",
|
||||
{"Ladder to Beneath the Vault"}),
|
||||
("Fortress Exterior near cave", "Fortress Courtyard, Fortress Main_Big Door",
|
||||
{"Ladder to Beneath the Vault"}),
|
||||
("Fortress Exterior near cave", "Fortress Courtyard, Fortress Reliquary_Lower",
|
||||
{"Ladder to Beneath the Vault"}),
|
||||
("Fortress Exterior near cave", "Fortress Courtyard, Fortress Reliquary_Upper",
|
||||
{"Ladder to Beneath the Vault"}),
|
||||
("Fortress Exterior near cave", "Fortress Courtyard, Fortress East_",
|
||||
{"Ladder to Beneath the Vault"}),
|
||||
|
||||
# ls at the ladder, need to gain a little height to get up the stairs
|
||||
# excluded in non-ER due to soft lock potential
|
||||
("Lower Mountain", "Mountain, Mountaintop_", set()),
|
||||
|
||||
# Where the rope is behind Monastery. Connecting here since, if you have this region, you don't need a sword
|
||||
("Quarry Monastery Entry", "Quarry Redux, Monastery_back", set()),
|
||||
|
||||
# Swamp to Gauntlet
|
||||
("Swamp Mid", "Swamp Redux 2, Cathedral Arena_",
|
||||
{"Ladders in Swamp"}),
|
||||
# Swamp to Overworld upper
|
||||
("Swamp Mid", "Swamp Redux 2, Overworld Redux_wall",
|
||||
{"Ladders in Swamp"}),
|
||||
# Ladder by the hero grave
|
||||
("Back of Swamp", "Swamp Redux 2, Overworld Redux_conduit", set()),
|
||||
("Back of Swamp", "Swamp Redux 2, Shop_", set()),
|
||||
# Need to put the cathedral HC code mid-flight
|
||||
("Back of Swamp", "Swamp Redux 2, Cathedral Redux_secret", set()),
|
||||
]
|
||||
|
||||
for region_name, scene_dest, ladders in ladder_storages:
|
||||
portal_name, paired_region = get_portal_info(scene_dest)
|
||||
# this is the only exception, requiring holy cross as well
|
||||
if portal_name == "Swamp to Cathedral Secret Legend Room Entrance" and region_name == "Back of Swamp":
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player)
|
||||
and has_ability(holy_cross, state, world)
|
||||
and (has_ladder("Ladders in Swamp", state, world)
|
||||
or has_ice_grapple_logic(True, state, world)
|
||||
or not options.entrance_rando))
|
||||
# soft locked without this ladder
|
||||
elif portal_name == "West Garden Exit after Boss" and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player)
|
||||
and (state.has("Ladders to West Bell", player)))
|
||||
# soft locked unless you have either ladder. if you have laurels, you use the other Entrance
|
||||
elif portal_name in {"Furnace Exit towards West Garden", "Furnace Exit to Dark Tomb"} \
|
||||
and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player)
|
||||
and state.has_any({"Ladder in Dark Tomb", "Ladders to West Bell"}, player))
|
||||
# soft locked for the same reasons as above
|
||||
elif portal_name in {"Entrance to Furnace near West Garden", "West Garden Entrance from Furnace"} \
|
||||
and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player) and state.has_any(ladders, player)
|
||||
and state.has_any({"Ladder in Dark Tomb", "Ladders to West Bell"}, player))
|
||||
# soft locked if you can't get past garden knight backwards or up the belltower ladders
|
||||
elif portal_name == "West Garden Entrance near Belltower" and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player) and state.has_any(ladders, player)
|
||||
and state.has_any({"Ladders to West Bell", laurels}, player))
|
||||
# soft locked if you can't get back out
|
||||
elif portal_name == "Fortress Courtyard to Beneath the Vault" and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player) and state.has("Ladder to Beneath the Vault", player)
|
||||
and has_lantern(state, world))
|
||||
elif portal_name == "Atoll Lower Entrance" and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player) and state.has_any(ladders, player)
|
||||
and (state.has_any({"Ladders in Overworld Town", grapple}, player)
|
||||
or has_ice_grapple_logic(True, state, world)))
|
||||
elif portal_name == "Atoll Upper Entrance" and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player) and state.has_any(ladders, player)
|
||||
and state.has(grapple, player) or has_ability(prayer, state, world))
|
||||
# soft lock potential
|
||||
elif portal_name in {"Special Shop Entrance", "Stairs to Top of the Mountain", "Swamp Upper Entrance",
|
||||
"Swamp Lower Entrance", "Caustic Light Cave Entrance"} and not options.entrance_rando:
|
||||
# connect the non-overworld ones
|
||||
for ls_info in non_ow_ls_list:
|
||||
if ls_info.dest_is_region:
|
||||
regions[ls_info.origin].connect(
|
||||
connecting_region=regions[ls_info.destination],
|
||||
name=ls_info.destination + " (LS) " + ls_info.origin,
|
||||
rule=lambda state: can_ladder_storage(state, world))
|
||||
continue
|
||||
# soft lock if you don't have the ladder, I regret writing unrestricted logic
|
||||
elif portal_name == "Temple Rafters Entrance" and not options.entrance_rando:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player)
|
||||
and state.has_any(ladders, player)
|
||||
and (state.has("Ladder near Temple Rafters", player)
|
||||
or (state.has_all({laurels, grapple}, player)
|
||||
and ((state.has("Ladders near Patrol Cave", player)
|
||||
and (state.has("Ladders near Dark Tomb", player)
|
||||
or state.has("Ladder to Quarry", player)
|
||||
and (state.has(fire_wand, player) or has_sword(state, player))))
|
||||
or state.has("Ladders near Overworld Checkpoint", player)
|
||||
or has_ice_grapple_logic(True, state, world)))))
|
||||
# if no ladder items are required, just do the basic stick only lambda
|
||||
elif not ladders or not options.shuffle_ladders:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player))
|
||||
# one ladder required
|
||||
elif len(ladders) == 1:
|
||||
ladder = ladders.pop()
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player) and state.has(ladder, player))
|
||||
# if multiple ladders can be used
|
||||
|
||||
portal_name, dest_region = get_portal_info(ls_info.destination)
|
||||
if ls_info.destination == "Atoll Redux, Frog Stairs_mouth":
|
||||
regions[ls_info.origin].connect(
|
||||
connecting_region=regions[dest_region],
|
||||
name=portal_name + " (LS) " + ls_info.origin,
|
||||
rule=lambda state: can_ladder_storage(state, world)
|
||||
and (state.has("Ladders in South Atoll", player)
|
||||
or state.has(key, player, 2) # can do it from the rope
|
||||
or options.ladder_storage >= LadderStorage.option_medium))
|
||||
# holy cross mid-ls to get in here
|
||||
elif ls_info.destination == "Swamp Redux 2, Cathedral Redux_secret":
|
||||
if ls_info.origin == "Swamp Mid":
|
||||
regions[ls_info.origin].connect(
|
||||
connecting_region=regions[dest_region],
|
||||
name=portal_name + " (LS) " + ls_info.origin,
|
||||
rule=lambda state: can_ladder_storage(state, world) and has_ability(prayer, state, world)
|
||||
and state.has(ls_info.ladders_req))
|
||||
else:
|
||||
regions[ls_info.origin].connect(
|
||||
connecting_region=regions[dest_region],
|
||||
name=portal_name + " (LS) " + ls_info.origin,
|
||||
rule=lambda state: can_ladder_storage(state, world) and has_ability(prayer, state, world))
|
||||
else:
|
||||
regions[region_name].connect(
|
||||
regions[paired_region],
|
||||
name=portal_name + " (LS) " + region_name,
|
||||
rule=lambda state: has_stick(state, player) and state.has_any(ladders, player))
|
||||
ls_connect(ls_info.origin, ls_info.destination, ls_info.ladders_req)
|
||||
|
||||
|
||||
def set_er_location_rules(world: "TunicWorld") -> None:
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
# for making rules for ladder storage in overworld
|
||||
from typing import Dict, List, Set, NamedTuple
|
||||
from typing import Dict, List, Set, NamedTuple, Optional
|
||||
|
||||
|
||||
class LadderInfo(NamedTuple):
|
||||
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, LadderInfo] = {
|
||||
ow_ladder_groups: Dict[str, OWLadderInfo] = {
|
||||
# lowest elevation
|
||||
"LS Elev 0": LadderInfo({"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_lowest"],
|
||||
["Overworld Beach"]),
|
||||
"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_lowest"],
|
||||
["Overworld Beach"]),
|
||||
# also the east filigree room
|
||||
"LS Elev 1": LadderInfo({"Ladders near Weathervane", "Ladders in Overworld Town", "Ladder to Swamp"},
|
||||
["Furnace_gyro_lower", "Swamp Redux 2_wall"],
|
||||
["Overworld Tunnel Turret"]),
|
||||
"LS Elev 1": OWLadderInfo({"Ladders near Weathervane", "Ladders in Overworld Town", "Ladder to Swamp"},
|
||||
["Furnace_gyro_lower", "Swamp Redux 2_wall"],
|
||||
["Overworld Tunnel Turret"]),
|
||||
# also the fountain filigree room and ruined passage door
|
||||
"LS Elev 2": LadderInfo({"Ladders near Weathervane", "Ladders to West Bell"},
|
||||
["Archipelagos Redux_lower", "Ruins Passage_east"],
|
||||
["After Ruined Passage"]),
|
||||
"LS Elev 2": OWLadderInfo({"Ladders near Weathervane", "Ladders to West Bell"},
|
||||
["Archipelagos Redux_lower", "Ruins Passage_east"],
|
||||
["After Ruined Passage"]),
|
||||
# also old house door
|
||||
"LS Elev 3": LadderInfo({"Ladders near Weathervane", "Ladder to Quarry", "Ladders to West Bell",
|
||||
"Ladders in Overworld Town"},
|
||||
[],
|
||||
["Overworld after Envoy", "East Overworld"]),
|
||||
"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": LadderInfo({"Ladders near Dark Tomb", "Ladder to Quarry", "Ladders to West Bell", "Ladders in Well",
|
||||
"Ladders in Overworld Town"},
|
||||
["Darkwoods Tunnel_"],
|
||||
[]),
|
||||
"LS Elev 5": LadderInfo({"Ladders near Overworld Checkpoint", "Ladders near Patrol Cave"},
|
||||
["PatrolCave_", "Forest Belltower_", "Fortress Courtyard_", "ShopSpecial_"],
|
||||
["East Overworld"]),
|
||||
"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": LadderInfo({"Ladders near Patrol Cave", "Ladder near Temple Rafters"},
|
||||
["Temple_rafters"],
|
||||
["Overworld above Patrol Cave"]),
|
||||
"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": LadderInfo({"Ladders near Patrol Cave", "Ladder near Temple Rafters", "Ladders near Dark Tomb"},
|
||||
["Mountain_"],
|
||||
["Upper Overworld"]),
|
||||
"LS Elev 7": OWLadderInfo({"Ladders near Patrol Cave", "Ladder near Temple Rafters", "Ladders near Dark Tomb"},
|
||||
["Mountain_"],
|
||||
["Upper Overworld"]),
|
||||
}
|
||||
|
||||
|
||||
@@ -58,3 +58,119 @@ region_ladders: Dict[str, Set[str]] = {
|
||||
"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: Optional[str] = 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", "Archipelagos Redux, Overworld Redux_upper"),
|
||||
# West Garden laurels exit
|
||||
LadderInfo("West Garden", "Archipelagos Redux, Overworld Redux_lowest"),
|
||||
|
||||
# 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"),
|
||||
LadderInfo("East Forest", "East Forest Dance Fox Spot", dest_is_region=True),
|
||||
|
||||
# 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"),
|
||||
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard", dest_is_region=True),
|
||||
|
||||
# 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"),
|
||||
LadderInfo("Fortress Exterior from East Forest", "Fortress Courtyard", dest_is_region=True),
|
||||
|
||||
# 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"),
|
||||
LadderInfo("Fortress Exterior near cave", "Fortress Courtyard", "Ladder to Beneath the Vault", dest_is_region=True),
|
||||
|
||||
# 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_"),
|
||||
LadderInfo("Back of Swamp", "Swamp Mid", dest_is_region=True),
|
||||
LadderInfo("Back of Swamp", "Swamp Front", dest_is_region=True),
|
||||
]
|
||||
|
||||
# if we can gain elevation, add the harder ones
|
||||
medium_ls: List[LadderInfo] = [
|
||||
# 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, Fortress Reliquary_Upper"),
|
||||
LadderInfo("Fortress Exterior from Overworld", "Fortress Courtyard, Fortress East_"),
|
||||
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, Fortress East_", "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 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 Front", 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] = [
|
||||
LadderInfo("Frog's Domain", "frog cave main, Frog Stairs_Exit", "Ladders to Frog's Domain"),
|
||||
LadderInfo("Rooted Ziggurat Lower Back", "ziggurat2020_3, ziggurat2020_FTRoom_"),
|
||||
LadderInfo("Swamp Mid", "Swamp Redux 2, Cathedral Redux_main", "Ladders in Swamp"),
|
||||
# need to do hc midair
|
||||
LadderInfo("Swamp Mid", "Swamp Redux 2, Cathedral Redux_secret", "Ladders in Swamp"),
|
||||
LadderInfo("Back of Swamp", "Swamp Redux 2, Cathedral Redux_main"),
|
||||
# need to do hc midair
|
||||
LadderInfo("Back of Swamp", "Swamp Redux 2, Cathedral Redux_secret"),
|
||||
]
|
||||
|
||||
@@ -204,12 +204,10 @@ class IceGrappling(Choice):
|
||||
class LadderStorage(Choice):
|
||||
"""
|
||||
Choose whether Ladder Storage is in logic.
|
||||
Easy includes uses of Ladder Storage to get to open doors over a long distance without too much difficulty.
|
||||
May include convenient elevation changes (going up Mountain stairs, stairs in front of Special Shop, etc.).
|
||||
Easy includes uses of Ladder Storage to get to open doors over a long distance without too much difficulty. May include convenient elevation changes (going up Mountain stairs, stairs in front of Special Shop, etc.).
|
||||
Medium includes the above as well as changing your elevation using the environment and getting knocked down by melee enemies mid-LS.
|
||||
Hard includes the above as well as going behind the map to enter closed doors from behind.
|
||||
Enabling any of these difficulty options will give the player the Torch item to return to the Overworld checkpoint to avoid softlocks.
|
||||
Checks that require you to get softlocked are not in logic. Needing to death warp or quit to menu to escape a situation is not considered a softlock.
|
||||
Hard includes the above as well as going behind the map to enter closed doors from behind. Also includes getting into the Cathedral Secret Legend room mid-LS.
|
||||
Enabling any of these difficulty options will give the player the Torch item to return to the Overworld checkpoint to avoid softlocks. Using the Torch is considered in logic.
|
||||
Opening individual chests while doing ladder storage is excluded due to tedium.
|
||||
"""
|
||||
internal_name = "ladder_storage"
|
||||
|
||||
Reference in New Issue
Block a user