HMG PoD Region fix + reformatting
* Create a region in HMG when PoD entrance isn't pre-opened that limits access to the overworld unless already available * Change rule generations to loop * Check for bomb and dash clips properly
This commit is contained in:
@@ -15,6 +15,9 @@ def link_overworld(world, player):
|
|||||||
for exitname, regionname in inverted_mandatory_connections:
|
for exitname, regionname in inverted_mandatory_connections:
|
||||||
connect_simple(world, exitname, regionname, player)
|
connect_simple(world, exitname, regionname, player)
|
||||||
|
|
||||||
|
if world.logic[player] in ['hybridglitches', 'nologic'] and not world.fix_palaceofdarkness_exit[player]:
|
||||||
|
connect_two_way(world, 'Palace of Darkness HMG Exit', 'Palace of Darkness HMG Entrance', player)
|
||||||
|
|
||||||
for forward_edge, back_edge in default_connections:
|
for forward_edge, back_edge in default_connections:
|
||||||
connect_two_way(world, forward_edge, back_edge, player)
|
connect_two_way(world, forward_edge, back_edge, player)
|
||||||
|
|
||||||
|
|||||||
15
Regions.py
15
Regions.py
@@ -191,8 +191,19 @@ def create_regions(world, player):
|
|||||||
create_dw_region(player, 'Broken Bridge Area', None, ['Broken Bridge Hammer Rock (South)', 'Broken Bridge Water Drop', 'Broken Bridge SW']),
|
create_dw_region(player, 'Broken Bridge Area', None, ['Broken Bridge Hammer Rock (South)', 'Broken Bridge Water Drop', 'Broken Bridge SW']),
|
||||||
create_dw_region(player, 'Broken Bridge Northeast', None, ['Broken Bridge Hammer Rock (North)', 'Broken Bridge Hookshot Gap', 'Broken Bridge Northeast Water Drop', 'Broken Bridge NE']),
|
create_dw_region(player, 'Broken Bridge Northeast', None, ['Broken Bridge Hammer Rock (North)', 'Broken Bridge Hookshot Gap', 'Broken Bridge Northeast Water Drop', 'Broken Bridge NE']),
|
||||||
create_dw_region(player, 'Broken Bridge West', None, ['Broken Bridge West Water Drop', 'Broken Bridge NW']),
|
create_dw_region(player, 'Broken Bridge West', None, ['Broken Bridge West Water Drop', 'Broken Bridge NW']),
|
||||||
create_dw_region(player, 'Broken Bridge Water', None, ['Broken Bridge NC'], 'Dark World', Terrain.Water),
|
create_dw_region(player, 'Broken Bridge Water', None, ['Broken Bridge NC'], 'Dark World', Terrain.Water)
|
||||||
create_dw_region(player, 'Palace of Darkness Area', None, ['Palace of Darkness Hint', 'Palace of Darkness', 'Palace of Darkness SW', 'Palace of Darkness SE']),
|
]
|
||||||
|
if world.logic[player] in ['hybridglitches', 'nologic'] and not world.fix_palaceofdarkness_exit[player]:
|
||||||
|
world.regions += [
|
||||||
|
create_dw_region(player, 'Palace of Darkness HMG Area', None, ['Palace of Darkness', 'Palace of Darkness HMG Exit']),
|
||||||
|
create_dw_region(player, 'Palace of Darkness Area', None, ['Palace of Darkness Hint', 'Palace of Darkness SW', 'Palace of Darkness SE', 'Palace of Darkness HMG Entrance'])
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
world.regions += [
|
||||||
|
create_dw_region(player, 'Palace of Darkness Area', None, ['Palace of Darkness Hint', 'Palace of Darkness', 'Palace of Darkness SW', 'Palace of Darkness SE'])
|
||||||
|
]
|
||||||
|
|
||||||
|
world.regions += [
|
||||||
create_dw_region(player, 'Hammer Pegs Area', ['Dark Blacksmith Ruins'], ['Hammer Peg Cave', 'Peg Area Rocks (East)']),
|
create_dw_region(player, 'Hammer Pegs Area', ['Dark Blacksmith Ruins'], ['Hammer Peg Cave', 'Peg Area Rocks (East)']),
|
||||||
create_dw_region(player, 'Hammer Pegs Entry', None, ['Peg Area Rocks (West)', 'Hammer Pegs WS']),
|
create_dw_region(player, 'Hammer Pegs Entry', None, ['Peg Area Rocks (West)', 'Hammer Pegs WS']),
|
||||||
create_dw_region(player, 'Dark Dunes Area', None, ['Dark Dunes NW', 'Dark Dunes WN', 'Dark Dunes SC']),
|
create_dw_region(player, 'Dark Dunes Area', None, ['Dark Dunes NW', 'Dark Dunes WN', 'Dark Dunes SC']),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import functools
|
||||||
from BaseClasses import Entrance, DoorType
|
from BaseClasses import Entrance, DoorType
|
||||||
from DoorShuffle import connect_simple_door
|
from DoorShuffle import connect_simple_door
|
||||||
import Rules
|
import Rules
|
||||||
@@ -133,19 +134,45 @@ def fake_pearl_state(state, player):
|
|||||||
# Sets the rules on where we can actually go using this clip.
|
# Sets the rules on where we can actually go using this clip.
|
||||||
# Behavior differs based on what type of ER shuffle we're playing.
|
# Behavior differs based on what type of ER shuffle we're playing.
|
||||||
def dungeon_reentry_rules(
|
def dungeon_reentry_rules(
|
||||||
world, player, clip: Entrance, dungeon_region: str, dungeon_exit: str
|
world,
|
||||||
|
player,
|
||||||
|
clip: Entrance,
|
||||||
|
dungeon_region: str,
|
||||||
):
|
):
|
||||||
fix_dungeon_exits = world.fix_palaceofdarkness_exit[player]
|
fix_dungeon_exits = world.fix_palaceofdarkness_exit[player]
|
||||||
fix_fake_worlds = world.fix_fake_world[player]
|
fix_fake_worlds = world.fix_fake_world[player]
|
||||||
|
|
||||||
|
all_clips = [
|
||||||
|
x[0]
|
||||||
|
for x in kikiskip_spots
|
||||||
|
+ mirehera_spots
|
||||||
|
+ heraswamp_spots
|
||||||
|
+ icepalace_spots
|
||||||
|
+ thievesdesert_spots
|
||||||
|
+ specrock_spots
|
||||||
|
+ paradox_spots
|
||||||
|
+ kikiskip_connectors
|
||||||
|
+ mirehera_connectors
|
||||||
|
+ heraswamp_connectors
|
||||||
|
+ thievesdesert_connectors
|
||||||
|
+ specrock_connectors
|
||||||
|
]
|
||||||
|
|
||||||
dungeon_entrance = [
|
dungeon_entrance = [
|
||||||
r
|
r
|
||||||
for r in world.get_region(dungeon_region, player).entrances
|
for r in world.get_region(dungeon_region, player).entrances
|
||||||
if r.name != clip.name
|
if r.name not in all_clips
|
||||||
][0]
|
][0]
|
||||||
if (
|
|
||||||
not fix_dungeon_exits
|
dungeon_exit = [
|
||||||
): # vanilla, simple, restricted, dungeonssimple; should never have fake worlds fix
|
r
|
||||||
|
for r in world.get_region(dungeon_region, player).exits
|
||||||
|
if r.name not in all_clips
|
||||||
|
][0]
|
||||||
|
|
||||||
|
|
||||||
|
if not fix_dungeon_exits:
|
||||||
|
# vanilla, simple, restricted, dungeonssimple; should never have fake worlds fix
|
||||||
# Dungeons are only shuffled among themselves. We need to check SW, MM, and AT because they can't be reentered trivially.
|
# Dungeons are only shuffled among themselves. We need to check SW, MM, and AT because they can't be reentered trivially.
|
||||||
|
|
||||||
# entrance doesn't exist until you fire rod it from the other side
|
# entrance doesn't exist until you fire rod it from the other side
|
||||||
@@ -196,32 +223,85 @@ def dungeon_reentry_rules(
|
|||||||
|
|
||||||
|
|
||||||
def underworld_glitches_rules(world, player):
|
def underworld_glitches_rules(world, player):
|
||||||
# Ice Palace Entrance Clip, needs bombs or cane of somaria to exit bomb drop room
|
|
||||||
Rules.add_rule(
|
|
||||||
world.get_entrance("Ice Bomb Drop SE", player),
|
|
||||||
lambda state: state.can_dash_clip(world.get_region("Ice Lobby", player), player)
|
|
||||||
and (state.can_use_bombs(player) or state.has("Cane of Somaria", player)),
|
|
||||||
combine="or",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Kiki Skip
|
|
||||||
kks = world.get_entrance("Kiki Skip", player)
|
|
||||||
Rules.set_rule(kks, lambda state: state.can_bomb_clip(kks.parent_region, player))
|
|
||||||
dungeon_reentry_rules(
|
|
||||||
world, player, kks, "Palace of Darkness Portal", "Palace of Darkness Exit"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Mire -> Hera -> Swamp
|
|
||||||
def mire_clip(state):
|
def mire_clip(state):
|
||||||
return state.can_reach(
|
torches = world.get_region("Mire Torches Top", player)
|
||||||
"Mire Torches Top", "Region", player
|
return state.can_dash_clip(torches, player) or (
|
||||||
) and state.can_dash_clip(world.get_region("Mire Torches Top", player), player)
|
state.can_bomb_clip(torches, player) and state.has_fire_source(player)
|
||||||
|
|
||||||
def hera_clip(state):
|
|
||||||
return state.can_reach("Hera 4F", "Region", player) and state.can_dash_clip(
|
|
||||||
world.get_region("Hera 4F", player), player
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def hera_clip(state):
|
||||||
|
hera = world.get_region("Hera 4F", player)
|
||||||
|
return state.can_bomb_clip(hera, player) or state.can_dash_clip(hera, player)
|
||||||
|
|
||||||
|
# We use these plus functool.partial because lambdas don't work in loops properly.
|
||||||
|
def bomb_clip(state, region, player):
|
||||||
|
return state.can_bomb_clip(region, player)
|
||||||
|
|
||||||
|
def dash_clip(state, region, player):
|
||||||
|
return state.can_dash_clip(region, player)
|
||||||
|
|
||||||
|
if not world.fix_palaceofdarkness_exit[player]:
|
||||||
|
Rules.set_rule(
|
||||||
|
world.get_entrance("Palace of Darkness HMG Exit", player),
|
||||||
|
lambda state: state.can_reach(world.get_entrance("Palace of Darkness", player), player),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Bomb clips
|
||||||
|
for clip in (
|
||||||
|
kikiskip_spots
|
||||||
|
+ icepalace_spots
|
||||||
|
+ thievesdesert_spots
|
||||||
|
+ specrock_spots
|
||||||
|
+ kikiskip_connectors
|
||||||
|
+ thievesdesert_connectors
|
||||||
|
+ specrock_connectors
|
||||||
|
):
|
||||||
|
region = world.get_region(clip[1], player)
|
||||||
|
Rules.set_rule(
|
||||||
|
world.get_entrance(clip[0], player),
|
||||||
|
functools.partial(bomb_clip, region=region, player=player),
|
||||||
|
)
|
||||||
|
# Dash clips
|
||||||
|
for clip in icepalace_spots:
|
||||||
|
region = world.get_region(clip[1], player)
|
||||||
|
Rules.add_rule(
|
||||||
|
world.get_entrance(clip[0], player),
|
||||||
|
functools.partial(dash_clip, region=region, player=player),
|
||||||
|
combine="or",
|
||||||
|
)
|
||||||
|
|
||||||
|
for spot in kikiskip_spots + thievesdesert_spots:
|
||||||
|
dungeon_reentry_rules(
|
||||||
|
world,
|
||||||
|
player,
|
||||||
|
world.get_entrance(spot[0], player),
|
||||||
|
spot[2],
|
||||||
|
)
|
||||||
|
|
||||||
|
for connector in kikiskip_connectors + thievesdesert_connectors:
|
||||||
|
dungeon_reentry_rules(
|
||||||
|
world,
|
||||||
|
player,
|
||||||
|
world.get_entrance(connector[0], player),
|
||||||
|
world.get_entrance(connector[2], player).parent_region.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
for clip in mirehera_spots + mirehera_connectors:
|
||||||
|
Rules.set_rule(
|
||||||
|
world.get_entrance(clip[0], player),
|
||||||
|
lambda state: mire_clip(state),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Need to be able to escape by hitting the switch from the back
|
||||||
|
Rules.set_rule(
|
||||||
|
world.get_entrance("Ice Bomb Drop Clip", player),
|
||||||
|
lambda state: (
|
||||||
|
state.can_use_bombs(player) or state.has("Cane of Somaria", player)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Allow mire big key to be used in Hera
|
||||||
Rules.add_rule(
|
Rules.add_rule(
|
||||||
world.get_entrance("Hera Startile Corner NW", player),
|
world.get_entrance("Hera Startile Corner NW", player),
|
||||||
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
||||||
@@ -232,20 +312,10 @@ def underworld_glitches_rules(world, player):
|
|||||||
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
lambda state: mire_clip(state) and state.has("Big Key (Misery Mire)", player),
|
||||||
combine="or",
|
combine="or",
|
||||||
)
|
)
|
||||||
|
# This uses the mire clip because it's always expected to come from mire
|
||||||
mire_to_hera = world.get_entrance("Mire to Hera Clip", player)
|
|
||||||
mire_to_swamp = world.get_entrance("Hera to Swamp Clip", player)
|
|
||||||
Rules.set_rule(mire_to_hera, mire_clip)
|
|
||||||
Rules.set_rule(
|
Rules.set_rule(
|
||||||
mire_to_swamp, lambda state: mire_clip(state) and state.has("Flippers", player)
|
world.get_entrance("Hera to Swamp Clip", player),
|
||||||
)
|
lambda state: mire_clip(state) and state.has("Flippers", player),
|
||||||
|
|
||||||
# Using the entrances for various ER types. Hera -> Swamp never matters because you can only logically traverse with the mire keys
|
|
||||||
dungeon_reentry_rules(
|
|
||||||
world, player, mire_to_hera, "Hera Lobby", "Tower of Hera Exit"
|
|
||||||
)
|
|
||||||
dungeon_reentry_rules(
|
|
||||||
world, player, mire_to_swamp, "Swamp Lobby", "Swamp Palace Exit"
|
|
||||||
)
|
)
|
||||||
# We need to set _all_ swamp doors to be openable with mire keys, otherwise the small key can't be behind them - 6 keys because of Pots
|
# We need to set _all_ swamp doors to be openable with mire keys, otherwise the small key can't be behind them - 6 keys because of Pots
|
||||||
# Flippers required for all of these doors to prevent locks when flooding
|
# Flippers required for all of these doors to prevent locks when flooding
|
||||||
@@ -269,7 +339,6 @@ def underworld_glitches_rules(world, player):
|
|||||||
and state.has("Flippers", player),
|
and state.has("Flippers", player),
|
||||||
combine="or",
|
combine="or",
|
||||||
)
|
)
|
||||||
# Rules.add_rule(world.get_entrance(door, player), lambda state: mire_clip(state) and state.has('Flippers', player), combine="or")
|
|
||||||
|
|
||||||
Rules.add_rule(
|
Rules.add_rule(
|
||||||
world.get_location("Trench 1 Switch", player),
|
world.get_location("Trench 1 Switch", player),
|
||||||
@@ -322,21 +391,16 @@ def underworld_glitches_rules(world, player):
|
|||||||
lambda state: mirrorless_moat_rule(state),
|
lambda state: mirrorless_moat_rule(state),
|
||||||
combine="or",
|
combine="or",
|
||||||
)
|
)
|
||||||
|
desert_exits = ["West", "South", "East"]
|
||||||
|
|
||||||
for desert_exit in ["East", "South", "West"]:
|
for desert_exit in desert_exits:
|
||||||
Rules.add_rule(
|
Rules.add_rule(
|
||||||
world.get_entrance(f"Thieves to Desert {desert_exit} Connector", player),
|
world.get_entrance(f"Thieves to Desert {desert_exit} Connector", player),
|
||||||
lambda state: state.can_dash_clip(
|
lambda state: state.can_dash_clip(
|
||||||
world.get_region("Thieves Attic", player), player
|
world.get_region("Thieves Attic", player), player
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
dungeon_reentry_rules(
|
|
||||||
world,
|
|
||||||
player,
|
|
||||||
world.get_entrance(f"Thieves to Desert {desert_exit} Connector", player),
|
|
||||||
f"Desert {desert_exit} Portal",
|
|
||||||
f"Desert Palace Exit ({desert_exit})",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Collecting left chests in Paradox Cave using a dash clip -> dash citrus, 1f right, teleport up
|
# Collecting left chests in Paradox Cave using a dash clip -> dash citrus, 1f right, teleport up
|
||||||
paradox_left_chests = [
|
paradox_left_chests = [
|
||||||
|
|||||||
Reference in New Issue
Block a user