Merged glitched mode fixes from Muffins PR/21
This commit is contained in:
31
Main.py
31
Main.py
@@ -28,7 +28,7 @@ from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dunge
|
|||||||
from Fill import dungeon_tracking
|
from Fill import dungeon_tracking
|
||||||
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations, set_prize_drops
|
from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations, set_prize_drops
|
||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items, create_farm_locations
|
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops, fill_specific_items, create_farm_locations
|
||||||
from UnderworldGlitchRules import create_hybridmajor_connections, create_hybridmajor_connectors, get_hybridmajor_connector_entrances
|
from UnderworldGlitchRules import create_hybridmajor_connections, get_hybridmajor_connection_entrances
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
from source.item.District import init_districts
|
from source.item.District import init_districts
|
||||||
@@ -176,8 +176,6 @@ def main(args, seed=None, fish=None):
|
|||||||
world.data_tables[player] = init_data_tables(world, player)
|
world.data_tables[player] = init_data_tables(world, player)
|
||||||
place_bosses(world, player)
|
place_bosses(world, player)
|
||||||
randomize_enemies(world, player)
|
randomize_enemies(world, player)
|
||||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
|
||||||
create_hybridmajor_connections(world, player)
|
|
||||||
adjust_locations(world, player)
|
adjust_locations(world, player)
|
||||||
|
|
||||||
if any(world.potshuffle.values()):
|
if any(world.potshuffle.values()):
|
||||||
@@ -204,8 +202,6 @@ def main(args, seed=None, fish=None):
|
|||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
link_entrances_new(world, player)
|
link_entrances_new(world, player)
|
||||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
|
||||||
create_hybridmajor_connectors(world, player)
|
|
||||||
|
|
||||||
logger.info(world.fish.translate("cli", "cli", "shuffling.prep"))
|
logger.info(world.fish.translate("cli", "cli", "shuffling.prep"))
|
||||||
|
|
||||||
@@ -227,6 +223,8 @@ def main(args, seed=None, fish=None):
|
|||||||
create_farm_locations(world, player)
|
create_farm_locations(world, player)
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
|
create_hybridmajor_connections(world, player)
|
||||||
generate_itempool(world, player)
|
generate_itempool(world, player)
|
||||||
|
|
||||||
verify_item_pool_config(world)
|
verify_item_pool_config(world)
|
||||||
@@ -628,8 +626,6 @@ def copy_world(world):
|
|||||||
create_owg_connections(ret, player)
|
create_owg_connections(ret, player)
|
||||||
create_dynamic_exits(ret, player)
|
create_dynamic_exits(ret, player)
|
||||||
create_dungeon_regions(ret, player)
|
create_dungeon_regions(ret, player)
|
||||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
|
||||||
create_hybridmajor_connections(ret, player)
|
|
||||||
create_owedges(ret, player)
|
create_owedges(ret, player)
|
||||||
create_shops(ret, player)
|
create_shops(ret, player)
|
||||||
#create_doors(ret, player)
|
#create_doors(ret, player)
|
||||||
@@ -660,7 +656,11 @@ def copy_world(world):
|
|||||||
|
|
||||||
# connect copied world
|
# connect copied world
|
||||||
copied_locations = {(loc.name, loc.player): loc for loc in ret.get_locations()} # caches all locations
|
copied_locations = {(loc.name, loc.player): loc for loc in ret.get_locations()} # caches all locations
|
||||||
hmg_entrances = get_hybridmajor_connector_entrances()
|
|
||||||
|
# We have to skip these for now. They require both the rest of the entrances _and_ the dungeon portals to be copied first
|
||||||
|
# We will connect them later
|
||||||
|
hmg_entrances = get_hybridmajor_connection_entrances()
|
||||||
|
|
||||||
for region in world.regions:
|
for region in world.regions:
|
||||||
copied_region = ret.get_region(region.name, region.player)
|
copied_region = ret.get_region(region.name, region.player)
|
||||||
copied_region.is_light_world = region.is_light_world
|
copied_region.is_light_world = region.is_light_world
|
||||||
@@ -739,7 +739,16 @@ def copy_world(world):
|
|||||||
categorize_world_regions(ret, player)
|
categorize_world_regions(ret, player)
|
||||||
create_farm_locations(ret, player)
|
create_farm_locations(ret, player)
|
||||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
create_hybridmajor_connectors(ret, player)
|
create_hybridmajor_connections(ret, player)
|
||||||
|
|
||||||
|
for region in world.regions:
|
||||||
|
copied_region = ret.get_region(region.name, region.player)
|
||||||
|
for entrance in region.entrances:
|
||||||
|
if entrance.name not in hmg_entrances:
|
||||||
|
continue
|
||||||
|
ret.get_entrance(entrance.name, entrance.player).connect(copied_region)
|
||||||
|
|
||||||
|
for player in range(1, world.players + 1):
|
||||||
set_rules(ret, player)
|
set_rules(ret, player)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -830,8 +839,6 @@ def copy_world_premature(world, player):
|
|||||||
create_owg_connections(ret, player)
|
create_owg_connections(ret, player)
|
||||||
create_dynamic_exits(ret, player)
|
create_dynamic_exits(ret, player)
|
||||||
create_dungeon_regions(ret, player)
|
create_dungeon_regions(ret, player)
|
||||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
|
||||||
create_hybridmajor_connections(ret, player)
|
|
||||||
create_owedges(ret, player)
|
create_owedges(ret, player)
|
||||||
create_shops(ret, player)
|
create_shops(ret, player)
|
||||||
create_doors(ret, player)
|
create_doors(ret, player)
|
||||||
@@ -891,7 +898,7 @@ def copy_world_premature(world, player):
|
|||||||
connect_portal(portal, ret, player)
|
connect_portal(portal, ret, player)
|
||||||
|
|
||||||
if world.logic[player] in ('nologic', 'hybridglitches'):
|
if world.logic[player] in ('nologic', 'hybridglitches'):
|
||||||
create_hybridmajor_connectors(ret, player)
|
create_hybridmajor_connections(ret, player)
|
||||||
|
|
||||||
set_rules(ret, player)
|
set_rules(ret, player)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
Helper functions to deliver entrance/exit/region sets to OWG rules.
|
Helper functions to deliver entrance/exit/region sets to OWG rules.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from BaseClasses import Entrance
|
from BaseClasses import Entrance, Region
|
||||||
from OWEdges import OWTileRegions
|
from OWEdges import OWTileRegions
|
||||||
|
|
||||||
# Cave regions that superbunny can get through - but only with a sword.
|
# Cave regions that superbunny can get through - but only with a sword.
|
||||||
@@ -327,10 +327,18 @@ def add_additional_rule(entrance, rule):
|
|||||||
entrance.access_rule = lambda state: old_rule(state) and rule(state)
|
entrance.access_rule = lambda state: old_rule(state) and rule(state)
|
||||||
|
|
||||||
|
|
||||||
def create_no_logic_connections(player, world, connections):
|
def create_no_logic_connections(player, world, connections, connect_external=False):
|
||||||
for entrance, parent_region, target_region, *_ in connections:
|
for entrance, parent_region, target_region, *_ in connections:
|
||||||
parent = world.get_region(parent_region, player)
|
parent = world.get_region(parent_region, player)
|
||||||
target = world.get_region(target_region, player)
|
|
||||||
|
if isinstance(target_region, Region):
|
||||||
|
target_region = target_region.name
|
||||||
|
|
||||||
|
if connect_external and target_region.endswith(" Portal"):
|
||||||
|
target = world.get_portal(target_region[:-7], player).find_portal_entrance().parent_region
|
||||||
|
else:
|
||||||
|
target = world.get_region(target_region, player)
|
||||||
|
|
||||||
connection = Entrance(player, entrance, parent)
|
connection = Entrance(player, entrance, parent)
|
||||||
connection.spot_type = 'OWG'
|
connection.spot_type = 'OWG'
|
||||||
parent.exits.append(connection)
|
parent.exits.append(connection)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
from BaseClasses import Entrance
|
import functools
|
||||||
|
from BaseClasses import Entrance, DoorType
|
||||||
|
from DoorShuffle import connect_simple_door
|
||||||
import Rules
|
import Rules
|
||||||
from OverworldGlitchRules import create_no_logic_connections
|
from OverworldGlitchRules import create_no_logic_connections
|
||||||
|
from Doors import create_door
|
||||||
|
|
||||||
kikiskip_spots = [
|
kikiskip_spots = [
|
||||||
("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal")
|
("Kiki Skip", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Portal")
|
||||||
@@ -26,44 +29,10 @@ paradox_spots = [
|
|||||||
("Paradox Front Teleport", "Paradox Cave Front", "Paradox Cave Chest Area")
|
("Paradox Front Teleport", "Paradox Cave Front", "Paradox Cave Chest Area")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# We need to make connectors at a separate time from the connections, because of how dungeons are linked to regions
|
|
||||||
kikiskip_connectors = [
|
|
||||||
("Kiki Skip Connector", "Spectacle Rock Cave (Bottom)", "Palace of Darkness Exit")
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
mirehera_connectors = [
|
|
||||||
("Mire to Hera Connector", "Mire Torches Top", "Tower of Hera Exit")
|
|
||||||
]
|
|
||||||
heraswamp_connectors = [
|
|
||||||
("Mire to Swamp Connector", "Mire Torches Top", "Swamp Palace Exit")
|
|
||||||
]
|
|
||||||
thievesdesert_connectors = [
|
|
||||||
("Thieves to Desert West Connector", "Thieves Attic", "Desert Palace Exit (West)"),
|
|
||||||
(
|
|
||||||
"Thieves to Desert South Connector",
|
|
||||||
"Thieves Attic",
|
|
||||||
"Desert Palace Exit (South)",
|
|
||||||
),
|
|
||||||
("Thieves to Desert East Connector", "Thieves Attic", "Desert Palace Exit (East)"),
|
|
||||||
]
|
|
||||||
specrock_connectors = [
|
|
||||||
(
|
|
||||||
"Spec Rock Top Connector",
|
|
||||||
"Spectacle Rock Cave (Peak)",
|
|
||||||
"Spectacle Rock Cave Exit (Top)",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"Spec Rock Exit Connector",
|
|
||||||
"Spectacle Rock Cave (Peak)",
|
|
||||||
"Spectacle Rock Cave Exit",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# Create connections between dungeons/locations
|
# Create connections between dungeons/locations
|
||||||
def create_hybridmajor_connections(world, player):
|
def create_hybridmajor_connections(world, player):
|
||||||
|
fix_fake_worlds = world.fix_fake_world[player]
|
||||||
|
|
||||||
for spots in [
|
for spots in [
|
||||||
kikiskip_spots,
|
kikiskip_spots,
|
||||||
mirehera_spots,
|
mirehera_spots,
|
||||||
@@ -73,41 +42,33 @@ def create_hybridmajor_connections(world, player):
|
|||||||
specrock_spots,
|
specrock_spots,
|
||||||
paradox_spots,
|
paradox_spots,
|
||||||
]:
|
]:
|
||||||
create_no_logic_connections(player, world, spots)
|
create_no_logic_connections(player, world, spots, connect_external=fix_fake_worlds)
|
||||||
|
|
||||||
|
# Add the new Ice path (back of bomb drop to front) to the world and model it properly
|
||||||
|
clip_door = create_door(player, "Ice Bomb Drop Clip", DoorType.Logical)
|
||||||
|
world.doors += [clip_door]
|
||||||
|
world.initialize_doors([clip_door])
|
||||||
|
|
||||||
# Turn dungeons into connectors
|
ice_bomb_top_reg = world.get_region("Ice Bomb Drop - Top", player)
|
||||||
def create_hybridmajor_connectors(world, player):
|
ice_bomb_top_reg.exits.append(
|
||||||
for connectors in [
|
Entrance(player, "Ice Bomb Drop Clip", ice_bomb_top_reg)
|
||||||
kikiskip_connectors,
|
)
|
||||||
mirehera_connectors,
|
connect_simple_door(world, "Ice Bomb Drop Clip", "Ice Bomb Drop", player)
|
||||||
heraswamp_connectors,
|
|
||||||
thievesdesert_connectors,
|
|
||||||
specrock_connectors,
|
|
||||||
]:
|
|
||||||
new_connectors = [
|
|
||||||
(
|
|
||||||
connector[0],
|
|
||||||
connector[1],
|
|
||||||
world.get_entrance(connector[2], player).connected_region,
|
|
||||||
)
|
|
||||||
for connector in connectors
|
|
||||||
]
|
|
||||||
new_connectors = [c for c in new_connectors if c[2] is not None]
|
|
||||||
create_no_logic_connections(player, world, new_connectors)
|
|
||||||
|
|
||||||
|
def get_hybridmajor_connection_entrances():
|
||||||
def get_hybridmajor_connector_entrances():
|
connections = []
|
||||||
connectors = []
|
|
||||||
for connector in (
|
for connector in (
|
||||||
kikiskip_connectors
|
kikiskip_spots
|
||||||
+ mirehera_connectors
|
+ mirehera_spots
|
||||||
+ heraswamp_connectors
|
+ heraswamp_spots
|
||||||
+ thievesdesert_connectors
|
+ icepalace_spots
|
||||||
+ specrock_connectors
|
+ thievesdesert_spots
|
||||||
):
|
+ specrock_spots
|
||||||
connectors.append(connector[0])
|
+ paradox_spots
|
||||||
return set(connectors)
|
):
|
||||||
|
connections.append(connector[0])
|
||||||
|
connections.append('Ice Bomb Drop Clip')
|
||||||
|
return set(connections)
|
||||||
|
|
||||||
|
|
||||||
# For some entrances, we need to fake having pearl, because we're in fake DW/LW.
|
# For some entrances, we need to fake having pearl, because we're in fake DW/LW.
|
||||||
@@ -123,19 +84,40 @@ 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
|
||||||
|
]
|
||||||
|
|
||||||
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
|
||||||
@@ -186,32 +168,66 @@ 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)
|
||||||
|
# Bomb clips
|
||||||
|
for clip in (
|
||||||
|
kikiskip_spots
|
||||||
|
+ icepalace_spots
|
||||||
|
+ thievesdesert_spots
|
||||||
|
+ specrock_spots
|
||||||
|
):
|
||||||
|
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 clip in mirehera_spots:
|
||||||
|
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),
|
||||||
@@ -222,20 +238,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
|
||||||
@@ -259,7 +265,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),
|
||||||
@@ -312,21 +317,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} Clip", 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 = [
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ advanced_placements:
|
|||||||
locations:
|
locations:
|
||||||
Link's House: True
|
Link's House: True
|
||||||
Magic Bat: False
|
Magic Bat: False
|
||||||
advanced_placements:
|
|
||||||
1:
|
|
||||||
- type: Verification
|
- type: Verification
|
||||||
item: Progressive Glove
|
item: Progressive Glove
|
||||||
locations:
|
locations:
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ settings:
|
|||||||
logic: hybridglitches
|
logic: hybridglitches
|
||||||
mode: inverted
|
mode: inverted
|
||||||
shuffle: crossed
|
shuffle: crossed
|
||||||
|
|
||||||
start_inventory:
|
start_inventory:
|
||||||
1:
|
1:
|
||||||
- Pegasus Boots
|
- Pegasus Boots
|
||||||
@@ -15,6 +14,8 @@ start_inventory:
|
|||||||
placements:
|
placements:
|
||||||
1:
|
1:
|
||||||
Desert Palace - Boss: Moon Pearl
|
Desert Palace - Boss: Moon Pearl
|
||||||
|
Desert Palace - Prize: Green Pendant
|
||||||
|
Sahasrahla: Magic Mirror
|
||||||
entrances:
|
entrances:
|
||||||
1:
|
1:
|
||||||
two-way:
|
two-way:
|
||||||
@@ -23,4 +24,6 @@ entrances:
|
|||||||
Thieves Town: Thieves Town Exit
|
Thieves Town: Thieves Town Exit
|
||||||
Hyrule Castle Entrance (East): Desert Palace Exit (South)
|
Hyrule Castle Entrance (East): Desert Palace Exit (South)
|
||||||
Hyrule Castle Entrance (West): Desert Palace Exit (North)
|
Hyrule Castle Entrance (West): Desert Palace Exit (North)
|
||||||
|
entrances:
|
||||||
|
Agahnims Tower: Pyramid Fairy
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ start_inventory:
|
|||||||
- Ether
|
- Ether
|
||||||
- Quake
|
- Quake
|
||||||
- Bombos
|
- Bombos
|
||||||
|
- Big Key (Tower of Hera)
|
||||||
|
- Big Key (Desert Palace)
|
||||||
|
- Big Key (Eastern Palace)
|
||||||
advanced_placements:
|
advanced_placements:
|
||||||
1:
|
1:
|
||||||
- type: Verification
|
- type: Verification
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ meta:
|
|||||||
settings:
|
settings:
|
||||||
1:
|
1:
|
||||||
logic: hybridglitches
|
logic: hybridglitches
|
||||||
|
shuffle: vanilla
|
||||||
start_inventory:
|
start_inventory:
|
||||||
1:
|
1:
|
||||||
- Pegasus Boots
|
- Pegasus Boots
|
||||||
@@ -10,9 +11,8 @@ start_inventory:
|
|||||||
- Fire Rod
|
- Fire Rod
|
||||||
- Book of Mudora
|
- Book of Mudora
|
||||||
- Progressive Sword
|
- Progressive Sword
|
||||||
- Progressive Sword
|
|
||||||
- Lamp
|
- Lamp
|
||||||
- Magic Mirror
|
- Hammer
|
||||||
- Ether
|
- Ether
|
||||||
- Quake
|
- Quake
|
||||||
- Bombos
|
- Bombos
|
||||||
@@ -41,6 +41,7 @@ advanced_placements:
|
|||||||
C-Shaped House: True
|
C-Shaped House: True
|
||||||
Pyramid Fairy - Left: True
|
Pyramid Fairy - Left: True
|
||||||
Swamp Palace - Entrance: False
|
Swamp Palace - Entrance: False
|
||||||
|
Swamp Palace - Boss: False
|
||||||
Thieves' Town - Map Chest: False
|
Thieves' Town - Map Chest: False
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
49
test/suite/hmg/no_east_dw_from_kikiskip.yaml
Normal file
49
test/suite/hmg/no_east_dw_from_kikiskip.yaml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
shuffle: vanilla
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
- Flippers
|
||||||
|
- Fire Rod
|
||||||
|
- Book of Mudora
|
||||||
|
- Progressive Sword
|
||||||
|
- Lamp
|
||||||
|
- Hammer
|
||||||
|
- Ether
|
||||||
|
- Quake
|
||||||
|
- Bombos
|
||||||
|
- Bombs (10)
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
# Put mirror in PF so we can't DMD
|
||||||
|
Pyramid Fairy - Right: Magic Mirror
|
||||||
|
# Lock all swords and cape behind pearl so we can't do aga 1 for pyramid access
|
||||||
|
Thieves' Town - Big Chest: Progressive Sword
|
||||||
|
Thieves' Town - Attic: Progressive Sword
|
||||||
|
Thieves' Town - Blind's Cell: Progressive Sword
|
||||||
|
Thieves' Town - Map Chest: Cape
|
||||||
|
advanced_placements:
|
||||||
|
1:
|
||||||
|
- type: Verification
|
||||||
|
item: Moon Pearl
|
||||||
|
locations:
|
||||||
|
Palace of Darkness - Shooter Room: True
|
||||||
|
Palace of Darkness - The Arena - Bridge: True
|
||||||
|
Palace of Darkness - Stalfos Basement: True
|
||||||
|
Palace of Darkness - Big Key Chest: True
|
||||||
|
Palace of Darkness - The Arena - Ledge: True
|
||||||
|
Palace of Darkness - Map Chest: True
|
||||||
|
Palace of Darkness - Compass Chest: True
|
||||||
|
Palace of Darkness - Dark Basement - Left: True
|
||||||
|
Palace of Darkness - Dark Basement - Right: True
|
||||||
|
Palace of Darkness - Dark Maze - Top: True
|
||||||
|
Palace of Darkness - Dark Maze - Bottom: True
|
||||||
|
Palace of Darkness - Big Chest: True
|
||||||
|
Palace of Darkness - Harmless Hellway: True
|
||||||
|
Palace of Darkness - Boss: True
|
||||||
|
Pyramid Fairy - Left: False
|
||||||
|
Pyramid: False
|
||||||
@@ -9,6 +9,7 @@ start_inventory:
|
|||||||
- Flippers
|
- Flippers
|
||||||
- Pegasus Boots
|
- Pegasus Boots
|
||||||
- Progressive Sword
|
- Progressive Sword
|
||||||
|
- Progressive Sword
|
||||||
- Hammer
|
- Hammer
|
||||||
- Progressive Glove
|
- Progressive Glove
|
||||||
- Progressive Glove
|
- Progressive Glove
|
||||||
@@ -17,9 +18,16 @@ start_inventory:
|
|||||||
- Bottle
|
- Bottle
|
||||||
- Magic Mirror
|
- Magic Mirror
|
||||||
- Lamp
|
- Lamp
|
||||||
|
- Beat Agahnim 1
|
||||||
|
- Cane of Somaria
|
||||||
|
- Hookshot
|
||||||
|
- Quake
|
||||||
|
- Ether
|
||||||
|
- Bombos
|
||||||
advanced_placements:
|
advanced_placements:
|
||||||
1:
|
1:
|
||||||
- type: Verification
|
- type: Verification
|
||||||
item: Moon Pearl
|
item: Moon Pearl
|
||||||
locations:
|
locations:
|
||||||
Skull Woods - Bridge Room: True
|
Skull Woods - Bridge Room: True
|
||||||
|
Skull Woods - Boss: True
|
||||||
|
|||||||
13
test/suite/hmg/pod_mp.yaml
Normal file
13
test/suite/hmg/pod_mp.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
meta:
|
||||||
|
players: 1
|
||||||
|
settings:
|
||||||
|
1:
|
||||||
|
logic: hybridglitches
|
||||||
|
mode: open
|
||||||
|
shuffle: vanilla
|
||||||
|
start_inventory:
|
||||||
|
1:
|
||||||
|
- Pegasus Boots
|
||||||
|
placements:
|
||||||
|
1:
|
||||||
|
Palace of Darkness - Shooter Room: Moon Pearl
|
||||||
Reference in New Issue
Block a user