Core: Remove ALTTP cruft from BaseClasses (#1451)

This commit is contained in:
zig-for 2023-03-03 23:23:52 -08:00 committed by GitHub
parent a4b61118cf
commit d74c4c4c94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 339 additions and 352 deletions

View File

@ -16,7 +16,6 @@ import NetUtils
import Options import Options
import Utils import Utils
class Group(TypedDict, total=False): class Group(TypedDict, total=False):
name: str name: str
game: str game: str
@ -760,169 +759,9 @@ class CollectionState():
found += self.prog_items[item_name, player] found += self.prog_items[item_name, player]
return found return found
def can_buy_unlimited(self, item: str, player: int) -> bool:
return any(shop.region.player == player and shop.has_unlimited(item) and shop.region.can_reach(self) for
shop in self.multiworld.shops)
def can_buy(self, item: str, player: int) -> bool:
return any(shop.region.player == player and shop.has(item) and shop.region.can_reach(self) for
shop in self.multiworld.shops)
def item_count(self, item: str, player: int) -> int: def item_count(self, item: str, player: int) -> int:
return self.prog_items[item, player] return self.prog_items[item, player]
def has_triforce_pieces(self, count: int, player: int) -> bool:
return self.item_count('Triforce Piece', player) + self.item_count('Power Star', player) >= count
def has_crystals(self, count: int, player: int) -> bool:
found: int = 0
for crystalnumber in range(1, 8):
found += self.prog_items[f"Crystal {crystalnumber}", player]
if found >= count:
return True
return False
def can_lift_rocks(self, player: int):
return self.has('Power Glove', player) or self.has('Titans Mitts', player)
def bottle_count(self, player: int) -> int:
return min(self.multiworld.difficulty_requirements[player].progressive_bottle_limit,
self.count_group("Bottles", player))
def has_hearts(self, player: int, count: int) -> int:
# Warning: This only considers items that are marked as advancement items
return self.heart_count(player) >= count
def heart_count(self, player: int) -> int:
# Warning: This only considers items that are marked as advancement items
diff = self.multiworld.difficulty_requirements[player]
return min(self.item_count('Boss Heart Container', player), diff.boss_heart_container_limit) \
+ self.item_count('Sanctuary Heart Container', player) \
+ min(self.item_count('Piece of Heart', player), diff.heart_piece_limit) // 4 \
+ 3 # starting hearts
def can_lift_heavy_rocks(self, player: int) -> bool:
return self.has('Titans Mitts', player)
def can_extend_magic(self, player: int, smallmagic: int = 16,
fullrefill: bool = False): # This reflects the total magic Link has, not the total extra he has.
basemagic = 8
if self.has('Magic Upgrade (1/4)', player):
basemagic = 32
elif self.has('Magic Upgrade (1/2)', player):
basemagic = 16
if self.can_buy_unlimited('Green Potion', player) or self.can_buy_unlimited('Blue Potion', player):
if self.multiworld.item_functionality[player] == 'hard' and not fullrefill:
basemagic = basemagic + int(basemagic * 0.5 * self.bottle_count(player))
elif self.multiworld.item_functionality[player] == 'expert' and not fullrefill:
basemagic = basemagic + int(basemagic * 0.25 * self.bottle_count(player))
else:
basemagic = basemagic + basemagic * self.bottle_count(player)
return basemagic >= smallmagic
def can_kill_most_things(self, player: int, enemies: int = 5) -> bool:
return (self.has_melee_weapon(player)
or self.has('Cane of Somaria', player)
or (self.has('Cane of Byrna', player) and (enemies < 6 or self.can_extend_magic(player)))
or self.can_shoot_arrows(player)
or self.has('Fire Rod', player)
or (self.has('Bombs (10)', player) and enemies < 6))
def can_shoot_arrows(self, player: int) -> bool:
if self.multiworld.retro_bow[player]:
return (self.has('Bow', player) or self.has('Silver Bow', player)) and self.can_buy('Single Arrow', player)
return self.has('Bow', player) or self.has('Silver Bow', player)
def can_get_good_bee(self, player: int) -> bool:
cave = self.multiworld.get_region('Good Bee Cave', player)
return (
self.has_group("Bottles", player) and
self.has('Bug Catching Net', player) and
(self.has('Pegasus Boots', player) or (self.has_sword(player) and self.has('Quake', player))) and
cave.can_reach(self) and
self.is_not_bunny(cave, player)
)
def can_retrieve_tablet(self, player: int) -> bool:
return self.has('Book of Mudora', player) and (self.has_beam_sword(player) or
(self.multiworld.swordless[player] and
self.has("Hammer", player)))
def has_sword(self, player: int) -> bool:
return self.has('Fighter Sword', player) \
or self.has('Master Sword', player) \
or self.has('Tempered Sword', player) \
or self.has('Golden Sword', player)
def has_beam_sword(self, player: int) -> bool:
return self.has('Master Sword', player) or self.has('Tempered Sword', player) or self.has('Golden Sword',
player)
def has_melee_weapon(self, player: int) -> bool:
return self.has_sword(player) or self.has('Hammer', player)
def has_fire_source(self, player: int) -> bool:
return self.has('Fire Rod', player) or self.has('Lamp', player)
def can_melt_things(self, player: int) -> bool:
return self.has('Fire Rod', player) or \
(self.has('Bombos', player) and
(self.multiworld.swordless[player] or
self.has_sword(player)))
def can_avoid_lasers(self, player: int) -> bool:
return self.has('Mirror Shield', player) or self.has('Cane of Byrna', player) or self.has('Cape', player)
def is_not_bunny(self, region: Region, player: int) -> bool:
if self.has('Moon Pearl', player):
return True
return region.is_light_world if self.multiworld.mode[player] != 'inverted' else region.is_dark_world
def can_reach_light_world(self, player: int) -> bool:
if True in [i.is_light_world for i in self.reachable_regions[player]]:
return True
return False
def can_reach_dark_world(self, player: int) -> bool:
if True in [i.is_dark_world for i in self.reachable_regions[player]]:
return True
return False
def has_misery_mire_medallion(self, player: int) -> bool:
return self.has(self.multiworld.required_medallions[player][0], player)
def has_turtle_rock_medallion(self, player: int) -> bool:
return self.has(self.multiworld.required_medallions[player][1], player)
def can_boots_clip_lw(self, player: int) -> bool:
if self.multiworld.mode[player] == 'inverted':
return self.has('Pegasus Boots', player) and self.has('Moon Pearl', player)
return self.has('Pegasus Boots', player)
def can_boots_clip_dw(self, player: int) -> bool:
if self.multiworld.mode[player] != 'inverted':
return self.has('Pegasus Boots', player) and self.has('Moon Pearl', player)
return self.has('Pegasus Boots', player)
def can_get_glitched_speed_lw(self, player: int) -> bool:
rules = [self.has('Pegasus Boots', player), any([self.has('Hookshot', player), self.has_sword(player)])]
if self.multiworld.mode[player] == 'inverted':
rules.append(self.has('Moon Pearl', player))
return all(rules)
def can_superbunny_mirror_with_sword(self, player: int) -> bool:
return self.has('Magic Mirror', player) and self.has_sword(player)
def can_get_glitched_speed_dw(self, player: int) -> bool:
rules = [self.has('Pegasus Boots', player), any([self.has('Hookshot', player), self.has_sword(player)])]
if self.multiworld.mode[player] != 'inverted':
rules.append(self.has('Moon Pearl', player))
return all(rules)
def can_bomb_clip(self, region: Region, player: int) -> bool:
return self.is_not_bunny(region, player) and self.has('Pegasus Boots', player)
def collect(self, item: Item, event: bool = False, location: Optional[Location] = None) -> bool: def collect(self, item: Item, event: bool = False, location: Optional[Location] = None) -> bool:
if location: if location:
self.locations_checked.add(location) self.locations_checked.add(location)
@ -958,12 +797,6 @@ class Region:
exits: List[Entrance] exits: List[Entrance]
locations: List[Location] locations: List[Location]
dungeon: Optional[Dungeon] = None dungeon: Optional[Dungeon] = None
shop: Optional = None
# LttP specific. TODO: move to a LttPRegion
# will be set after making connections.
is_light_world: bool = False
is_dark_world: bool = False
def __init__(self, name: str, player: int, multiworld: MultiWorld, hint: Optional[str] = None): def __init__(self, name: str, player: int, multiworld: MultiWorld, hint: Optional[str] = None):
self.name = name self.name = name

View File

@ -4,7 +4,7 @@ from typing import Optional, Union, List, Tuple, Callable, Dict
from BaseClasses import Boss from BaseClasses import Boss
from Fill import FillError from Fill import FillError
from .Options import LTTPBosses as Bosses from .Options import LTTPBosses as Bosses
from .StateHelpers import can_shoot_arrows, can_extend_magic, can_get_good_bee, has_sword, has_beam_sword, has_melee_weapon, has_fire_source
def BossFactory(boss: str, player: int) -> Optional[Boss]: def BossFactory(boss: str, player: int) -> Optional[Boss]:
if boss in boss_table: if boss in boss_table:
@ -16,33 +16,33 @@ def BossFactory(boss: str, player: int) -> Optional[Boss]:
def ArmosKnightsDefeatRule(state, player: int) -> bool: def ArmosKnightsDefeatRule(state, player: int) -> bool:
# Magic amounts are probably a bit overkill # Magic amounts are probably a bit overkill
return ( return (
state.has_melee_weapon(player) or has_melee_weapon(state, player) or
state.can_shoot_arrows(player) or can_shoot_arrows(state, player) or
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 10)) or (state.has('Cane of Somaria', player) and can_extend_magic(state, player, 10)) or
(state.has('Cane of Byrna', player) and state.can_extend_magic(player, 16)) or (state.has('Cane of Byrna', player) and can_extend_magic(state, player, 16)) or
(state.has('Ice Rod', player) and state.can_extend_magic(player, 32)) or (state.has('Ice Rod', player) and can_extend_magic(state, player, 32)) or
(state.has('Fire Rod', player) and state.can_extend_magic(player, 32)) or (state.has('Fire Rod', player) and can_extend_magic(state, player, 32)) or
state.has('Blue Boomerang', player) or state.has('Blue Boomerang', player) or
state.has('Red Boomerang', player)) state.has('Red Boomerang', player))
def LanmolasDefeatRule(state, player: int) -> bool: def LanmolasDefeatRule(state, player: int) -> bool:
return ( return (
state.has_melee_weapon(player) or has_melee_weapon(state, player) or
state.has('Fire Rod', player) or state.has('Fire Rod', player) or
state.has('Ice Rod', player) or state.has('Ice Rod', player) or
state.has('Cane of Somaria', player) or state.has('Cane of Somaria', player) or
state.has('Cane of Byrna', player) or state.has('Cane of Byrna', player) or
state.can_shoot_arrows(player)) can_shoot_arrows(state, player))
def MoldormDefeatRule(state, player: int) -> bool: def MoldormDefeatRule(state, player: int) -> bool:
return state.has_melee_weapon(player) return has_melee_weapon(state, player)
def HelmasaurKingDefeatRule(state, player: int) -> bool: def HelmasaurKingDefeatRule(state, player: int) -> bool:
# TODO: technically possible with the hammer # TODO: technically possible with the hammer
return state.has_sword(player) or state.can_shoot_arrows(player) return has_sword(state, player) or can_shoot_arrows(state, player)
def ArrghusDefeatRule(state, player: int) -> bool: def ArrghusDefeatRule(state, player: int) -> bool:
@ -51,28 +51,28 @@ def ArrghusDefeatRule(state, player: int) -> bool:
# TODO: ideally we would have a check for bow and silvers, which combined with the # TODO: ideally we would have a check for bow and silvers, which combined with the
# hookshot is enough. This is not coded yet because the silvers that only work in pyramid feature # hookshot is enough. This is not coded yet because the silvers that only work in pyramid feature
# makes this complicated # makes this complicated
if state.has_melee_weapon(player): if has_melee_weapon(state, player):
return True return True
return ((state.has('Fire Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, return ((state.has('Fire Rod', player) and (can_shoot_arrows(state, player) or can_extend_magic(state, player,
12))) or # assuming mostly gitting two puff with one shot 12))) or # assuming mostly gitting two puff with one shot
(state.has('Ice Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 16)))) (state.has('Ice Rod', player) and (can_shoot_arrows(state, player) or can_extend_magic(state, player, 16))))
def MothulaDefeatRule(state, player: int) -> bool: def MothulaDefeatRule(state, player: int) -> bool:
return ( return (
state.has_melee_weapon(player) or has_melee_weapon(state, player) or
(state.has('Fire Rod', player) and state.can_extend_magic(player, 10)) or (state.has('Fire Rod', player) and can_extend_magic(state, player, 10)) or
# TODO: Not sure how much (if any) extend magic is needed for these two, since they only apply # TODO: Not sure how much (if any) extend magic is needed for these two, since they only apply
# to non-vanilla locations, so are harder to test, so sticking with what VT has for now: # to non-vanilla locations, so are harder to test, so sticking with what VT has for now:
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 16)) or (state.has('Cane of Somaria', player) and can_extend_magic(state, player, 16)) or
(state.has('Cane of Byrna', player) and state.can_extend_magic(player, 16)) or (state.has('Cane of Byrna', player) and can_extend_magic(state, player, 16)) or
state.can_get_good_bee(player) can_get_good_bee(state, player)
) )
def BlindDefeatRule(state, player: int) -> bool: def BlindDefeatRule(state, player: int) -> bool:
return state.has_melee_weapon(player) or state.has('Cane of Somaria', player) or state.has('Cane of Byrna', player) return has_melee_weapon(state, player) or state.has('Cane of Somaria', player) or state.has('Cane of Byrna', player)
def KholdstareDefeatRule(state, player: int) -> bool: def KholdstareDefeatRule(state, player: int) -> bool:
@ -81,56 +81,56 @@ def KholdstareDefeatRule(state, player: int) -> bool:
state.has('Fire Rod', player) or state.has('Fire Rod', player) or
( (
state.has('Bombos', player) and state.has('Bombos', player) and
(state.has_sword(player) or state.multiworld.swordless[player]) (has_sword(state, player) or state.multiworld.swordless[player])
) )
) and ) and
( (
state.has_melee_weapon(player) or has_melee_weapon(state, player) or
(state.has('Fire Rod', player) and state.can_extend_magic(player, 20)) or (state.has('Fire Rod', player) and can_extend_magic(state, player, 20)) or
( (
state.has('Fire Rod', player) and state.has('Fire Rod', player) and
state.has('Bombos', player) and state.has('Bombos', player) and
state.multiworld.swordless[player] and state.multiworld.swordless[player] and
state.can_extend_magic(player, 16) can_extend_magic(state, player, 16)
) )
) )
) )
def VitreousDefeatRule(state, player: int) -> bool: def VitreousDefeatRule(state, player: int) -> bool:
return state.can_shoot_arrows(player) or state.has_melee_weapon(player) return can_shoot_arrows(state, player) or has_melee_weapon(state, player)
def TrinexxDefeatRule(state, player: int) -> bool: def TrinexxDefeatRule(state, player: int) -> bool:
if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)): if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)):
return False return False
return state.has('Hammer', player) or state.has('Tempered Sword', player) or state.has('Golden Sword', player) or \ return state.has('Hammer', player) or state.has('Tempered Sword', player) or state.has('Golden Sword', player) or \
(state.has('Master Sword', player) and state.can_extend_magic(player, 16)) or \ (state.has('Master Sword', player) and can_extend_magic(state, player, 16)) or \
(state.has_sword(player) and state.can_extend_magic(player, 32)) (has_sword(state, player) and can_extend_magic(state, player, 32))
def AgahnimDefeatRule(state, player: int) -> bool: def AgahnimDefeatRule(state, player: int) -> bool:
return state.has_sword(player) or state.has('Hammer', player) or state.has('Bug Catching Net', player) return has_sword(state, player) or state.has('Hammer', player) or state.has('Bug Catching Net', player)
def GanonDefeatRule(state, player: int) -> bool: def GanonDefeatRule(state, player: int) -> bool:
if state.multiworld.swordless[player]: if state.multiworld.swordless[player]:
return state.has('Hammer', player) and \ return state.has('Hammer', player) and \
state.has_fire_source(player) and \ has_fire_source(state, player) and \
state.has('Silver Bow', player) and \ state.has('Silver Bow', player) and \
state.can_shoot_arrows(player) can_shoot_arrows(state, player)
can_hurt = state.has_beam_sword(player) can_hurt = has_beam_sword(state, player)
common = can_hurt and state.has_fire_source(player) common = can_hurt and has_fire_source(state, player)
# silverless ganon may be needed in anything higher than no glitches # silverless ganon may be needed in anything higher than no glitches
if state.multiworld.logic[player] != 'noglitches': if state.multiworld.logic[player] != 'noglitches':
# need to light torch a sufficient amount of times # need to light torch a sufficient amount of times
return common and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or ( return common and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or (
state.has('Silver Bow', player) and state.can_shoot_arrows(player)) or state.has('Silver Bow', player) and can_shoot_arrows(state, player)) or
state.has('Lamp', player) or state.can_extend_magic(player, 12)) state.has('Lamp', player) or can_extend_magic(state, player, 12))
else: else:
return common and state.has('Silver Bow', player) and state.can_shoot_arrows(player) return common and state.has('Silver Bow', player) and can_shoot_arrows(state, player)
boss_table: Dict[str, Tuple[str, Optional[Callable]]] = { boss_table: Dict[str, Tuple[str, Optional[Callable]]] = {

View File

@ -10,6 +10,7 @@ from worlds.alttp.EntranceShuffle import connect_entrance
from Fill import FillError from Fill import FillError
from worlds.alttp.Items import ItemFactory, GetBeemizerItem from worlds.alttp.Items import ItemFactory, GetBeemizerItem
from worlds.alttp.Options import smallkey_shuffle, compass_shuffle, bigkey_shuffle, map_shuffle from worlds.alttp.Options import smallkey_shuffle, compass_shuffle, bigkey_shuffle, map_shuffle
from .StateHelpers import has_triforce_pieces, has_melee_weapon
# This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space. # This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space.
# Some basic items that various modes require are placed here, including pendants and crystals. Medallion requirements for the two relevant entrances are also decided. # Some basic items that various modes require are placed here, including pendants and crystals. Medallion requirements for the two relevant entrances are also decided.
@ -286,7 +287,7 @@ def generate_itempool(world):
region = world.get_region('Light World', player) region = world.get_region('Light World', player)
loc = ALttPLocation(player, "Murahdahla", parent=region) loc = ALttPLocation(player, "Murahdahla", parent=region)
loc.access_rule = lambda state: state.has_triforce_pieces(state.multiworld.treasure_hunt_count[player], player) loc.access_rule = lambda state: has_triforce_pieces(state, player)
region.locations.append(loc) region.locations.append(loc)
world.clear_location_cache() world.clear_location_cache()
@ -327,7 +328,7 @@ def generate_itempool(world):
for item in precollected_items: for item in precollected_items:
world.push_precollected(ItemFactory(item, player)) world.push_precollected(ItemFactory(item, player))
if world.mode[player] == 'standard' and not world.state.has_melee_weapon(player): if world.mode[player] == 'standard' and not has_melee_weapon(world.state, player):
if "Link's Uncle" not in placed_items: if "Link's Uncle" not in placed_items:
found_sword = False found_sword = False
found_bow = False found_bow = False

View File

@ -4,6 +4,7 @@ Helper functions to deliver entrance/exit/region sets to OWG rules.
from BaseClasses import Entrance from BaseClasses import Entrance
from .StateHelpers import can_lift_heavy_rocks, can_boots_clip_lw, can_boots_clip_dw, can_get_glitched_speed_dw
def get_sword_required_superbunny_mirror_regions(): def get_sword_required_superbunny_mirror_regions():
""" """
@ -169,7 +170,7 @@ def get_boots_clip_exits_dw(inverted, player):
yield ('Ganons Tower Ascent', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain (Top)') # This only gets you to the GT entrance yield ('Ganons Tower Ascent', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain (Top)') # This only gets you to the GT entrance
yield ('Dark Death Mountain Glitched Bridge', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain (Top)') yield ('Dark Death Mountain Glitched Bridge', 'Dark Death Mountain (West Bottom)', 'Dark Death Mountain (Top)')
yield ('Turtle Rock (Top) Clip Spot', 'Dark Death Mountain (Top)', 'Turtle Rock (Top)') yield ('Turtle Rock (Top) Clip Spot', 'Dark Death Mountain (Top)', 'Turtle Rock (Top)')
yield ('Ice Palace Clip', 'South Dark World', 'Dark Lake Hylia Central Island', lambda state: state.can_boots_clip_dw(player) and state.has('Flippers', player)) yield ('Ice Palace Clip', 'South Dark World', 'Dark Lake Hylia Central Island', lambda state: can_boots_clip_dw(state, player) and state.has('Flippers', player))
else: else:
yield ('Dark Desert Teleporter Clip Spot', 'Dark Desert', 'Dark Desert Ledge') yield ('Dark Desert Teleporter Clip Spot', 'Dark Desert', 'Dark Desert Ledge')
@ -203,7 +204,7 @@ def get_mirror_offset_spots_lw(player):
Mirror shenanigans placing a mirror portal with a broken camera Mirror shenanigans placing a mirror portal with a broken camera
""" """
yield ('Death Mountain Offset Mirror', 'Death Mountain', 'Light World') yield ('Death Mountain Offset Mirror', 'Death Mountain', 'Light World')
yield ('Death Mountain Offset Mirror (Houlihan Exit)', 'Death Mountain', 'Hyrule Castle Ledge', lambda state: state.has('Magic Mirror', player) and state.can_boots_clip_dw(player) and state.has('Moon Pearl', player)) yield ('Death Mountain Offset Mirror (Houlihan Exit)', 'Death Mountain', 'Hyrule Castle Ledge', lambda state: state.has('Magic Mirror', player) and can_boots_clip_dw(state, player) and state.has('Moon Pearl', player))
@ -255,11 +256,11 @@ def overworld_glitch_connections(world, player):
def overworld_glitches_rules(world, player): def overworld_glitches_rules(world, player):
# Boots-accessible locations. # Boots-accessible locations.
set_owg_connection_rules(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_lw(player)) set_owg_connection_rules(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'), lambda state: can_boots_clip_lw(state, player))
set_owg_connection_rules(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted', player), lambda state: state.can_boots_clip_dw(player)) set_owg_connection_rules(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted', player), lambda state: can_boots_clip_dw(state, player))
# Glitched speed drops. # Glitched speed drops.
set_owg_connection_rules(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'), lambda state: state.can_get_glitched_speed_dw(player)) set_owg_connection_rules(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'), lambda state: can_get_glitched_speed_dw(state, player))
# Dark Death Mountain Ledge Clip Spot also accessible with mirror. # Dark Death Mountain Ledge Clip Spot also accessible with mirror.
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
add_alternate_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has('Magic Mirror', player)) add_alternate_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has('Magic Mirror', player))
@ -267,20 +268,20 @@ def overworld_glitches_rules(world, player):
# Mirror clip spots. # Mirror clip spots.
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
set_owg_connection_rules(player, world, get_mirror_clip_spots_dw(), lambda state: state.has('Magic Mirror', player)) set_owg_connection_rules(player, world, get_mirror_clip_spots_dw(), lambda state: state.has('Magic Mirror', player))
set_owg_connection_rules(player, world, get_mirror_offset_spots_dw(), lambda state: state.has('Magic Mirror', player) and state.can_boots_clip_lw(player)) set_owg_connection_rules(player, world, get_mirror_offset_spots_dw(), lambda state: state.has('Magic Mirror', player) and can_boots_clip_lw(state, player))
else: else:
set_owg_connection_rules(player, world, get_mirror_offset_spots_lw(player), lambda state: state.has('Magic Mirror', player) and state.can_boots_clip_dw(player)) set_owg_connection_rules(player, world, get_mirror_offset_spots_lw(player), lambda state: state.has('Magic Mirror', player) and can_boots_clip_dw(state, player))
# Regions that require the boots and some other stuff. # Regions that require the boots and some other stuff.
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
world.get_entrance('Turtle Rock Teleporter', player).access_rule = lambda state: (state.can_boots_clip_lw(player) or state.can_lift_heavy_rocks(player)) and state.has('Hammer', player) world.get_entrance('Turtle Rock Teleporter', player).access_rule = lambda state: (can_boots_clip_lw(state, player) or can_lift_heavy_rocks(state, player)) and state.has('Hammer', player)
add_alternate_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Moon Pearl', player) or state.has('Pegasus Boots', player)) add_alternate_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Moon Pearl', player) or state.has('Pegasus Boots', player))
else: else:
add_alternate_rule(world.get_entrance('Waterfall of Wishing Cave', player), lambda state: state.has('Moon Pearl', player)) add_alternate_rule(world.get_entrance('Waterfall of Wishing Cave', player), lambda state: state.has('Moon Pearl', player))
world.get_entrance('Dark Desert Teleporter', player).access_rule = lambda state: (state.has('Flute', player) or state.has('Pegasus Boots', player)) and state.can_lift_heavy_rocks(player) world.get_entrance('Dark Desert Teleporter', player).access_rule = lambda state: (state.has('Flute', player) or state.has('Pegasus Boots', player)) and can_lift_heavy_rocks(state, player)
add_alternate_rule(world.get_entrance('Catfish Exit Rock', player), lambda state: state.can_boots_clip_dw(player)) add_alternate_rule(world.get_entrance('Catfish Exit Rock', player), lambda state: can_boots_clip_dw(state, player))
add_alternate_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: state.can_boots_clip_dw(player)) add_alternate_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: can_boots_clip_dw(state, player))
# Zora's Ledge via waterwalk setup. # Zora's Ledge via waterwalk setup.
add_alternate_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Pegasus Boots', player)) add_alternate_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Pegasus Boots', player))

View File

@ -2,17 +2,24 @@ import collections
import logging import logging
from typing import Iterator, Set from typing import Iterator, Set
from worlds.alttp import OverworldGlitchRules from BaseClasses import Entrance, MultiWorld
from BaseClasses import MultiWorld, Entrance from worlds.generic.Rules import (add_item_rule, add_rule, forbid_item,
from worlds.alttp.Items import ItemFactory, progression_items, item_name_groups, item_table item_in_locations, item_name, set_rule)
from worlds.alttp.OverworldGlitchRules import overworld_glitches_rules, no_logic_rules
from worlds.alttp.Regions import location_table from . import OverworldGlitchRules
from worlds.alttp.UnderworldGlitchRules import underworld_glitches_rules from .Bosses import GanonDefeatRule
from worlds.alttp.Bosses import GanonDefeatRule from .Items import ItemFactory, item_name_groups, item_table, progression_items
from worlds.generic.Rules import set_rule, add_rule, forbid_item, add_item_rule, item_in_locations, \ from .Options import smallkey_shuffle
item_name from .OverworldGlitchRules import no_logic_rules, overworld_glitches_rules
from worlds.alttp.Options import smallkey_shuffle from .Regions import LTTPRegionType, location_table
from worlds.alttp.Regions import LTTPRegionType from .StateHelpers import (can_extend_magic, can_kill_most_things,
can_lift_heavy_rocks, can_lift_rocks,
can_melt_things, can_retrieve_tablet,
can_shoot_arrows, has_beam_sword, has_crystals,
has_fire_source, has_hearts,
has_misery_mire_medallion, has_sword, has_turtle_rock_medallion,
has_triforce_pieces)
from .UnderworldGlitchRules import underworld_glitches_rules
def set_rules(world): def set_rules(world):
@ -76,7 +83,7 @@ def set_rules(world):
if world.goal[player] == 'bosses': if world.goal[player] == 'bosses':
# require all bosses to beat ganon # require all bosses to beat ganon
add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player) and state.has('Beat Agahnim 1', player) and state.has('Beat Agahnim 2', player) and state.has_crystals(7, player)) add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player) and state.has('Beat Agahnim 1', player) and state.has('Beat Agahnim 2', player) and has_crystals(state, 7, player))
elif world.goal[player] == 'ganon': elif world.goal[player] == 'ganon':
# require aga2 to beat ganon # require aga2 to beat ganon
add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player)) add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player))
@ -101,7 +108,7 @@ def set_rules(world):
set_trock_key_rules(world, player) set_trock_key_rules(world, player)
set_rule(ganons_tower, lambda state: state.has_crystals(state.multiworld.crystals_needed_for_gt[player], player)) set_rule(ganons_tower, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_gt[player], player))
if world.mode[player] != 'inverted' and world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']: if world.mode[player] != 'inverted' and world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.multiworld.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or') add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.multiworld.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or')
@ -199,7 +206,7 @@ def global_rules(world, player):
set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player))
set_rule(world.get_location('Purple Chest', player), set_rule(world.get_location('Purple Chest', player),
lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest
set_rule(world.get_location('Ether Tablet', player), lambda state: state.can_retrieve_tablet(player)) set_rule(world.get_location('Ether Tablet', player), lambda state: can_retrieve_tablet(state, player))
set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player))
set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith
@ -212,11 +219,11 @@ def global_rules(world, player):
set_rule(world.get_location('Spike Cave', player), lambda state: set_rule(world.get_location('Spike Cave', player), lambda state:
state.has('Hammer', player) and state.can_lift_rocks(player) and state.has('Hammer', player) and can_lift_rocks(state, player) and
((state.has('Cape', player) and state.can_extend_magic(player, 16, True)) or ((state.has('Cape', player) and can_extend_magic(state, player, 16, True)) or
(state.has('Cane of Byrna', player) and (state.has('Cane of Byrna', player) and
(state.can_extend_magic(player, 12, True) or (can_extend_magic(state, player, 12, True) or
(state.multiworld.can_take_damage[player] and (state.has('Pegasus Boots', player) or state.has_hearts(player, 4)))))) (state.multiworld.can_take_damage[player] and (state.has('Pegasus Boots', player) or has_hearts(state, player, 4))))))
) )
set_rule(world.get_location('Hookshot Cave - Top Right', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_location('Hookshot Cave - Top Right', player), lambda state: state.has('Hookshot', player))
@ -232,11 +239,11 @@ def global_rules(world, player):
set_rule(world.get_entrance('Sewers Back Door', player), set_rule(world.get_entrance('Sewers Back Door', player),
lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player)) lambda state: state._lttp_has_key('Small Key (Hyrule Castle)', player))
set_rule(world.get_entrance('Agahnim 1', player), set_rule(world.get_entrance('Agahnim 1', player),
lambda state: state.has_sword(player) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 2)) lambda state: has_sword(state, player) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 2))
set_rule(world.get_location('Castle Tower - Room 03', player), lambda state: state.can_kill_most_things(player, 8)) set_rule(world.get_location('Castle Tower - Room 03', player), lambda state: can_kill_most_things(state, player, 8))
set_rule(world.get_location('Castle Tower - Dark Maze', player), set_rule(world.get_location('Castle Tower - Dark Maze', player),
lambda state: state.can_kill_most_things(player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)', lambda state: can_kill_most_things(state, player, 8) and state._lttp_has_key('Small Key (Agahnims Tower)',
player)) player))
set_rule(world.get_location('Eastern Palace - Big Chest', player), set_rule(world.get_location('Eastern Palace - Big Chest', player),
@ -248,14 +255,14 @@ def global_rules(world, player):
set_rule(ep_prize, lambda state: state.has('Big Key (Eastern Palace)', player) and set_rule(ep_prize, lambda state: state.has('Big Key (Eastern Palace)', player) and
ep_prize.parent_region.dungeon.boss.can_defeat(state)) ep_prize.parent_region.dungeon.boss.can_defeat(state))
if not world.enemy_shuffle[player]: if not world.enemy_shuffle[player]:
add_rule(ep_boss, lambda state: state.can_shoot_arrows(player)) add_rule(ep_boss, lambda state: can_shoot_arrows(state, player))
add_rule(ep_prize, lambda state: state.can_shoot_arrows(player)) add_rule(ep_prize, lambda state: can_shoot_arrows(state, player))
set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player)) set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player))
set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player)) set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player))
set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and state.multiworld.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state))
set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and state.multiworld.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and has_fire_source(state, player) and state.multiworld.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state))
# logic patch to prevent placing a crystal in Desert that's required to reach the required keys # logic patch to prevent placing a crystal in Desert that's required to reach the required keys
if not (world.smallkey_shuffle[player] and world.bigkey_shuffle[player]): if not (world.smallkey_shuffle[player] and world.bigkey_shuffle[player]):
@ -264,7 +271,7 @@ def global_rules(world, player):
set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state._lttp_has_key('Small Key (Tower of Hera)', player) or item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player)) set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state._lttp_has_key('Small Key (Tower of Hera)', player) or item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player))
set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player)) set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player))
set_rule(world.get_location('Tower of Hera - Big Chest', player), lambda state: state.has('Big Key (Tower of Hera)', player)) set_rule(world.get_location('Tower of Hera - Big Chest', player), lambda state: state.has('Big Key (Tower of Hera)', player))
set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: state.has_fire_source(player)) set_rule(world.get_location('Tower of Hera - Big Key Chest', player), lambda state: has_fire_source(state, player))
if world.accessibility[player] != 'locations': if world.accessibility[player] != 'locations':
set_always_allow(world.get_location('Tower of Hera - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Tower of Hera)' and item.player == player) set_always_allow(world.get_location('Tower of Hera - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Tower of Hera)' and item.player == player)
@ -292,18 +299,18 @@ def global_rules(world, player):
set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player) or item_name(state, 'Skull Woods - Big Chest', player) == ('Big Key (Skull Woods)', player)) set_rule(world.get_location('Skull Woods - Big Chest', player), lambda state: state.has('Big Key (Skull Woods)', player) or item_name(state, 'Skull Woods - Big Chest', player) == ('Big Key (Skull Woods)', player))
if world.accessibility[player] != 'locations': if world.accessibility[player] != 'locations':
set_always_allow(world.get_location('Skull Woods - Big Chest', player), lambda state, item: item.name == 'Big Key (Skull Woods)' and item.player == player) set_always_allow(world.get_location('Skull Woods - Big Chest', player), lambda state, item: item.name == 'Big Key (Skull Woods)' and item.player == player)
set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player) and state.has_sword(player)) # sword required for curtain set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player) and has_sword(state, player)) # sword required for curtain
set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.can_melt_things(player)) set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: can_melt_things(state, player))
set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player)) set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player))
set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state._lttp_has_key('Small Key (Ice Palace)', player, 2) or (state.has('Cane of Somaria', player) and state._lttp_has_key('Small Key (Ice Palace)', player, 1)))) set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: can_lift_rocks(state, player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state._lttp_has_key('Small Key (Ice Palace)', player, 2) or (state.has('Cane of Somaria', player) and state._lttp_has_key('Small Key (Ice Palace)', player, 1))))
set_rule(world.get_entrance('Ice Palace (East)', player), lambda state: (state.has('Hookshot', player) or ( set_rule(world.get_entrance('Ice Palace (East)', player), lambda state: (state.has('Hookshot', player) or (
item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state._lttp_has_key('Small Key (Ice Palace)', player))) and (state.multiworld.can_take_damage[player] or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state._lttp_has_key('Small Key (Ice Palace)', player))) and (state.multiworld.can_take_damage[player] or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player)))
set_rule(world.get_entrance('Ice Palace (East Top)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) set_rule(world.get_entrance('Ice Palace (East Top)', player), lambda state: can_lift_rocks(state, player) and state.has('Hammer', player))
set_rule(world.get_entrance('Misery Mire Entrance Gap', player), lambda state: (state.has('Pegasus Boots', player) or state.has('Hookshot', player)) and (state.has_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player))) # need to defeat wizzrobes, bombs don't work ... set_rule(world.get_entrance('Misery Mire Entrance Gap', player), lambda state: (state.has('Pegasus Boots', player) or state.has('Hookshot', player)) and (has_sword(state, player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or can_shoot_arrows(state, player))) # need to defeat wizzrobes, bombs don't work ...
set_rule(world.get_location('Misery Mire - Big Chest', player), lambda state: state.has('Big Key (Misery Mire)', player)) set_rule(world.get_location('Misery Mire - Big Chest', player), lambda state: state.has('Big Key (Misery Mire)', player))
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.multiworld.can_take_damage[player] and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.multiworld.can_take_damage[player] and has_hearts(state, player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
set_rule(world.get_entrance('Misery Mire Big Key Door', player), lambda state: state.has('Big Key (Misery Mire)', player)) set_rule(world.get_entrance('Misery Mire Big Key Door', player), lambda state: state.has('Big Key (Misery Mire)', player))
# you can squander the free small key from the pot by opening the south door to the north west switch room, locking you out of accessing a color switch ... # you can squander the free small key from the pot by opening the south door to the north west switch room, locking you out of accessing a color switch ...
# big key gives backdoor access to that from the teleporter in the north west # big key gives backdoor access to that from the teleporter in the north west
@ -314,8 +321,8 @@ def global_rules(world, player):
item_name(state, 'Misery Mire - Compass Chest', player) in [('Big Key (Misery Mire)', player)]) or item_name(state, 'Misery Mire - Compass Chest', player) in [('Big Key (Misery Mire)', player)]) or
( (
item_name(state, 'Misery Mire - Big Key Chest', player) in [('Big Key (Misery Mire)', player)])) else state._lttp_has_key('Small Key (Misery Mire)', player, 3)) item_name(state, 'Misery Mire - Big Key Chest', player) in [('Big Key (Misery Mire)', player)])) else state._lttp_has_key('Small Key (Misery Mire)', player, 3))
set_rule(world.get_location('Misery Mire - Compass Chest', player), lambda state: state.has_fire_source(player)) set_rule(world.get_location('Misery Mire - Compass Chest', player), lambda state: has_fire_source(state, player))
set_rule(world.get_location('Misery Mire - Big Key Chest', player), lambda state: state.has_fire_source(player)) set_rule(world.get_location('Misery Mire - Big Key Chest', player), lambda state: has_fire_source(state, player))
set_rule(world.get_entrance('Misery Mire (Vitreous)', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('Misery Mire (Vitreous)', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_entrance('Turtle Rock Entrance Gap', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('Turtle Rock Entrance Gap', player), lambda state: state.has('Cane of Somaria', player))
@ -335,10 +342,10 @@ def global_rules(world, player):
set_rule(world.get_entrance('Turtle Rock (Trinexx)', player), lambda state: state._lttp_has_key('Small Key (Turtle Rock)', player, 4) and state.has('Big Key (Turtle Rock)', player) and state.has('Cane of Somaria', player)) set_rule(world.get_entrance('Turtle Rock (Trinexx)', player), lambda state: state._lttp_has_key('Small Key (Turtle Rock)', player, 4) and state.has('Big Key (Turtle Rock)', player) and state.has('Cane of Somaria', player))
if not world.enemy_shuffle[player]: if not world.enemy_shuffle[player]:
set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: state.can_shoot_arrows(player)) set_rule(world.get_entrance('Palace of Darkness Bonk Wall', player), lambda state: can_shoot_arrows(state, player))
set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Palace of Darkness Hammer Peg Drop', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Palace of Darkness Bridge Room', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 1)) # If we can reach any other small key door, we already have back door access to this area set_rule(world.get_entrance('Palace of Darkness Bridge Room', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 1)) # If we can reach any other small key door, we already have back door access to this area
set_rule(world.get_entrance('Palace of Darkness Big Key Door', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) and state.has('Big Key (Palace of Darkness)', player) and state.can_shoot_arrows(player) and state.has('Hammer', player)) set_rule(world.get_entrance('Palace of Darkness Big Key Door', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 6) and state.has('Big Key (Palace of Darkness)', player) and can_shoot_arrows(state, player) and state.has('Hammer', player))
set_rule(world.get_entrance('Palace of Darkness (North)', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 4)) set_rule(world.get_entrance('Palace of Darkness (North)', player), lambda state: state._lttp_has_key('Small Key (Palace of Darkness)', player, 4))
set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: state.has('Big Key (Palace of Darkness)', player)) set_rule(world.get_location('Palace of Darkness - Big Chest', player), lambda state: state.has('Big Key (Palace of Darkness)', player))
@ -399,9 +406,9 @@ def global_rules(world, player):
lambda state: state.has('Big Key (Ganons Tower)', player)) lambda state: state.has('Big Key (Ganons Tower)', player))
else: else:
set_rule(world.get_entrance('Ganons Tower Big Key Door', player), set_rule(world.get_entrance('Ganons Tower Big Key Door', player),
lambda state: state.has('Big Key (Ganons Tower)', player) and state.can_shoot_arrows(player)) lambda state: state.has('Big Key (Ganons Tower)', player) and can_shoot_arrows(state, player))
set_rule(world.get_entrance('Ganons Tower Torch Rooms', player), set_rule(world.get_entrance('Ganons Tower Torch Rooms', player),
lambda state: state.has_fire_source(player) and state.multiworld.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) lambda state: has_fire_source(state, player) and state.multiworld.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state))
set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player), set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player),
lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 3)) lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 3))
set_rule(world.get_entrance('Ganons Tower Moldorm Door', player), set_rule(world.get_entrance('Ganons Tower Moldorm Door', player),
@ -412,12 +419,12 @@ def global_rules(world, player):
ganon = world.get_location('Ganon', player) ganon = world.get_location('Ganon', player)
set_rule(ganon, lambda state: GanonDefeatRule(state, player)) set_rule(ganon, lambda state: GanonDefeatRule(state, player))
if world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']: if world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
add_rule(ganon, lambda state: state.has_triforce_pieces(state.multiworld.treasure_hunt_count[player], player)) add_rule(ganon, lambda state: has_triforce_pieces(state, player))
elif world.goal[player] == 'ganonpedestal': elif world.goal[player] == 'ganonpedestal':
add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player)) add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player))
else: else:
add_rule(ganon, lambda state: state.has_crystals(state.multiworld.crystals_needed_for_ganon[player], player)) add_rule(ganon, lambda state: has_crystals(state, state.multiworld.crystals_needed_for_ganon[player], player))
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop set_rule(world.get_entrance('Ganon Drop', player), lambda state: has_beam_sword(state, player)) # need to damage ganon to get tiles to drop
set_rule(world.get_location('Flute Activation Spot', player), lambda state: state.has('Flute', player)) set_rule(world.get_location('Flute Activation Spot', player), lambda state: state.has('Flute', player))
@ -426,51 +433,51 @@ def default_rules(world, player):
"""Default world rules when world state is not inverted.""" """Default world rules when world state is not inverted."""
# overworld requirements # overworld requirements
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has('Moon Pearl', player) and state.has('Magic Mirror', player)) set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has('Moon Pearl', player) and state.has('Magic Mirror', player))
# Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it) # Caution: If king's grave is releaxed at all to account for reaching it via a two way cave's exit in insanity mode, then the bomb shop logic will need to be updated (that would involve create a small ledge-like Region for it)
set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has('Pegasus Boots', player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has('Pegasus Boots', player) and state.has('Beat Agahnim 1', player))
set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player))
set_rule(world.get_entrance('Sanctuary Grave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Sanctuary Grave', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('20 Rupee Cave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('20 Rupee Cave', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('50 Rupee Cave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('50 Rupee Cave', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Death Mountain Entrance Rock', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Death Mountain Entrance Rock', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Bumper Cave Entrance Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Bumper Cave Entrance Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Flute Spot 1', player), lambda state: state.has('Activated Flute', player)) set_rule(world.get_entrance('Flute Spot 1', player), lambda state: state.has('Activated Flute', player))
set_rule(world.get_entrance('Lake Hylia Central Island Teleporter', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Lake Hylia Central Island Teleporter', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Activated Flute', player) and state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Activated Flute', player) and can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('East Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has('Moon Pearl', player)) # bunny cannot use hammer set_rule(world.get_entrance('East Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and can_lift_rocks(state, player) and state.has('Moon Pearl', player)) # bunny cannot use hammer
set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has('Moon Pearl', player)) # bunny cannot use hammer set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and can_lift_rocks(state, player) and state.has('Moon Pearl', player)) # bunny cannot use hammer
set_rule(world.get_entrance('Kakariko Teleporter', player), lambda state: ((state.has('Hammer', player) and state.can_lift_rocks(player)) or state.can_lift_heavy_rocks(player)) and state.has('Moon Pearl', player)) # bunny cannot lift bushes set_rule(world.get_entrance('Kakariko Teleporter', player), lambda state: ((state.has('Hammer', player) and can_lift_rocks(state, player)) or can_lift_heavy_rocks(state, player)) and state.has('Moon Pearl', player)) # bunny cannot lift bushes
set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player)) set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player))
set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player))
set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player)) set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Waterfall of Wishing', player), lambda state: state.has('Flippers', player))
set_rule(world.get_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player)) # will get automatic moon pearl requirement set_rule(world.get_location('Frog', player), lambda state: can_lift_heavy_rocks(state, player)) # will get automatic moon pearl requirement
set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player)) set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player))
set_rule(world.get_entrance('Desert Palace Entrance (North) Rocks', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Desert Palace Entrance (North) Rocks', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Desert Ledge Return Rocks', player), lambda state: state.can_lift_rocks(player)) # should we decide to place something that is not a dungeon end up there at some point set_rule(world.get_entrance('Desert Ledge Return Rocks', player), lambda state: can_lift_rocks(state, player)) # should we decide to place something that is not a dungeon end up there at some point
set_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Checkerboard Cave', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or has_beam_sword(state, player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player))
set_rule(world.get_entrance('Old Man Cave Exit (West)', player), lambda state: False) # drop cannot be climbed up set_rule(world.get_entrance('Old Man Cave Exit (West)', player), lambda state: False) # drop cannot be climbed up
set_rule(world.get_entrance('Broken Bridge (West)', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Broken Bridge (West)', player), lambda state: state.has('Hookshot', player))
set_rule(world.get_entrance('Broken Bridge (East)', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Broken Bridge (East)', player), lambda state: state.has('Hookshot', player))
set_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Fairy Ascension Rocks', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Fairy Ascension Rocks', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block
set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: can_lift_heavy_rocks(state, player) and state.has('Hammer', player))
set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Catfish Exit Rock', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Catfish Exit Rock', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Catfish Entrance Rock', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Catfish Entrance Rock', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Northeast Dark World Broken Bridge Pass', player), lambda state: state.has('Moon Pearl', player) and (state.can_lift_rocks(player) or state.has('Hammer', player) or state.has('Flippers', player))) set_rule(world.get_entrance('Northeast Dark World Broken Bridge Pass', player), lambda state: state.has('Moon Pearl', player) and (can_lift_rocks(state, player) or state.has('Hammer', player) or state.has('Flippers', player)))
set_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: state.has('Moon Pearl', player) and (state.can_lift_rocks(player) or state.has('Hammer', player))) set_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: state.has('Moon Pearl', player) and (can_lift_rocks(state, player) or state.has('Hammer', player)))
set_rule(world.get_entrance('South Dark World Bridge', player), lambda state: state.has('Hammer', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('South Dark World Bridge', player), lambda state: state.has('Hammer', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Bonk Fairy (Dark)', player), lambda state: state.has('Moon Pearl', player) and state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Bonk Fairy (Dark)', player), lambda state: state.has('Moon Pearl', player) and state.has('Pegasus Boots', player))
set_rule(world.get_entrance('West Dark World Gap', player), lambda state: state.has('Moon Pearl', player) and state.has('Hookshot', player)) set_rule(world.get_entrance('West Dark World Gap', player), lambda state: state.has('Moon Pearl', player) and state.has('Hookshot', player))
@ -478,12 +485,12 @@ def default_rules(world, player):
set_rule(world.get_entrance('Hyrule Castle Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Hyrule Castle Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Hyrule Castle Main Gate', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Hyrule Castle Main Gate', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: (state.has('Moon Pearl', player) and state.has('Flippers', player) or state.has('Magic Mirror', player))) # Overworld Bunny Revival set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: (state.has('Moon Pearl', player) and state.has('Flippers', player) or state.has('Magic Mirror', player))) # Overworld Bunny Revival
set_rule(world.get_location('Bombos Tablet', player), lambda state: state.can_retrieve_tablet(player)) set_rule(world.get_location('Bombos Tablet', player), lambda state: can_retrieve_tablet(state, player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # ToDo any fake flipper set up? set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # ToDo any fake flipper set up?
set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has('Moon Pearl', player)) # bomb required set_rule(world.get_entrance('Dark Lake Hylia Ledge Fairy', player), lambda state: state.has('Moon Pearl', player)) # bomb required
set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: state.has('Moon Pearl', player) and state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: state.has('Moon Pearl', player) and can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has('Moon Pearl', player)) # bomb required set_rule(world.get_entrance('Hype Cave', player), lambda state: state.has('Moon Pearl', player)) # bomb required
set_rule(world.get_entrance('Brewery', player), lambda state: state.has('Moon Pearl', player)) # bomb required set_rule(world.get_entrance('Brewery', player), lambda state: state.has('Moon Pearl', player)) # bomb required
set_rule(world.get_entrance('Thieves Town', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot pull set_rule(world.get_entrance('Thieves Town', player), lambda state: state.has('Moon Pearl', player)) # bunny cannot pull
@ -497,26 +504,26 @@ def default_rules(world, player):
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player))
set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has('Moon Pearl', player) and state.has('Magic Mirror', player)) set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has('Moon Pearl', player) and state.has('Magic Mirror', player))
set_rule(world.get_entrance('Bumper Cave Entrance Rock', player), lambda state: state.has('Moon Pearl', player) and state.can_lift_rocks(player)) set_rule(world.get_entrance('Bumper Cave Entrance Rock', player), lambda state: state.has('Moon Pearl', player) and can_lift_rocks(state, player))
set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Bat Cave Drop Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Bat Cave Drop Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Dark World Hammer Peg Cave', player), lambda state: state.has('Moon Pearl', player) and state.has('Hammer', player)) set_rule(world.get_entrance('Dark World Hammer Peg Cave', player), lambda state: state.has('Moon Pearl', player) and state.has('Hammer', player))
set_rule(world.get_entrance('Village of Outcasts Eastern Rocks', player), lambda state: state.has('Moon Pearl', player) and state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Village of Outcasts Eastern Rocks', player), lambda state: state.has('Moon Pearl', player) and can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Peg Area Rocks', player), lambda state: state.has('Moon Pearl', player) and state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Peg Area Rocks', player), lambda state: state.has('Moon Pearl', player) and can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Village of Outcasts Pegs', player), lambda state: state.has('Moon Pearl', player) and state.has('Hammer', player)) set_rule(world.get_entrance('Village of Outcasts Pegs', player), lambda state: state.has('Moon Pearl', player) and state.has('Hammer', player))
set_rule(world.get_entrance('Grassy Lawn Pegs', player), lambda state: state.has('Moon Pearl', player) and state.has('Hammer', player)) set_rule(world.get_entrance('Grassy Lawn Pegs', player), lambda state: state.has('Moon Pearl', player) and state.has('Hammer', player))
set_rule(world.get_entrance('Bumper Cave Exit (Top)', player), lambda state: state.has('Cape', player)) set_rule(world.get_entrance('Bumper Cave Exit (Top)', player), lambda state: state.has('Cape', player))
set_rule(world.get_entrance('Bumper Cave Exit (Bottom)', player), lambda state: state.has('Cape', player) or state.has('Hookshot', player)) set_rule(world.get_entrance('Bumper Cave Exit (Bottom)', player), lambda state: state.has('Cape', player) or state.has('Hookshot', player))
set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player) and state.has('Moon Pearl', player)) # bunny cannot use fire rod set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player) and state.has('Moon Pearl', player)) # bunny cannot use fire rod
set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has('Moon Pearl', player) and state.has_sword(player) and state.has_misery_mire_medallion(player)) # sword required to cast magic (!) set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has('Moon Pearl', player) and has_sword(state, player) and has_misery_mire_medallion(state, player)) # sword required to cast magic (!)
set_rule(world.get_entrance('Desert Ledge (Northeast) Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Desert Ledge (Northeast) Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Desert Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Desert Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Desert Palace Stairs Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Desert Palace Stairs Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Desert Palace Entrance (North) Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Desert Palace Entrance (North) Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Spectacle Rock Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Spectacle Rock Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Hookshot Cave', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Hookshot Cave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('East Death Mountain (Top) Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('East Death Mountain (Top) Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Mimic Cave Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Mimic Cave Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
@ -525,7 +532,7 @@ def default_rules(world, player):
set_rule(world.get_entrance('Isolated Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Isolated Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Superbunny Cave Exit (Bottom)', player), lambda state: False) # Cannot get to bottom exit from top. Just exists for shuffling set_rule(world.get_entrance('Superbunny Cave Exit (Bottom)', player), lambda state: False) # Cannot get to bottom exit from top. Just exists for shuffling
set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has('Moon Pearl', player) and state.has_sword(player) and state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword required to cast magic (!) set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has('Moon Pearl', player) and has_sword(state, player) and has_turtle_rock_medallion(state, player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword required to cast magic (!)
set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player].to_bool(world, player)) set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player].to_bool(world, player))
@ -545,12 +552,12 @@ def inverted_rules(world, player):
set_rule(world.get_entrance('Potion Shop Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Potion Shop Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Light World Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Light World Pier', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: can_lift_heavy_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: can_lift_heavy_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Potion Shop Inner Bushes', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Potion Shop Inner Bushes', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Potion Shop Outer Bushes', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Potion Shop Outer Bushes', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Potion Shop Outer Rock', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Potion Shop Outer Rock', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Potion Shop Inner Rock', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Potion Shop Inner Rock', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Graveyard Cave Inner Bushes', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Graveyard Cave Inner Bushes', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Graveyard Cave Outer Bushes', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Graveyard Cave Outer Bushes', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Secret Passage Inner Bushes', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Secret Passage Inner Bushes', player), lambda state: state.has('Moon Pearl', player))
@ -560,23 +567,23 @@ def inverted_rules(world, player):
set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player) and state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player) and state.has('Beat Agahnim 1', player))
set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has('Pegasus Boots', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) # bunny can use book set_rule(world.get_entrance('Desert Palace Stairs', player), lambda state: state.has('Book of Mudora', player)) # bunny can use book
set_rule(world.get_entrance('Sanctuary Grave', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Sanctuary Grave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('20 Rupee Cave', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('20 Rupee Cave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('50 Rupee Cave', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('50 Rupee Cave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Death Mountain Entrance Rock', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Death Mountain Entrance Rock', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Bumper Cave Entrance Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Bumper Cave Entrance Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Dark Lake Hylia Central Island Teleporter', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Dark Lake Hylia Central Island Teleporter', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Activated Flute', player) and state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Dark Desert Teleporter', player), lambda state: state.has('Activated Flute', player) and can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('East Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has('Moon Pearl', player)) # bunny cannot use hammer set_rule(world.get_entrance('East Dark World Teleporter', player), lambda state: state.has('Hammer', player) and can_lift_rocks(state, player) and state.has('Moon Pearl', player)) # bunny cannot use hammer
set_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has('Moon Pearl', player)) # bunny cannot use hammer set_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has('Hammer', player) and can_lift_rocks(state, player) and state.has('Moon Pearl', player)) # bunny cannot use hammer
set_rule(world.get_entrance('West Dark World Teleporter', player), lambda state: ((state.has('Hammer', player) and state.can_lift_rocks(player)) or state.can_lift_heavy_rocks(player)) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('West Dark World Teleporter', player), lambda state: ((state.has('Hammer', player) and can_lift_rocks(state, player)) or can_lift_heavy_rocks(state, player)) and state.has('Moon Pearl', player))
set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player) and state.has('Moon Pearl', player)) set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player) and state.has('Moon Pearl', player))
set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player)) set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Waterfall of Wishing Cave', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Waterfall of Wishing Cave', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Northeast Light World Return', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Northeast Light World Return', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player))
set_rule(world.get_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player) and (state.has('Moon Pearl', player) or state.has('Beat Agahnim 1', player)) or (state.can_reach('Light World', 'Region', player) and state.has('Magic Mirror', player))) # Need LW access using Mirror or Portal set_rule(world.get_location('Frog', player), lambda state: can_lift_heavy_rocks(state, player) and (state.has('Moon Pearl', player) or state.has('Beat Agahnim 1', player)) or (state.can_reach('Light World', 'Region', player) and state.has('Magic Mirror', player))) # Need LW access using Mirror or Portal
set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith
set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player))
set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player) and state.has('Moon Pearl', player)) set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player) and state.has('Moon Pearl', player))
@ -591,52 +598,52 @@ def inverted_rules(world, player):
set_rule(world.get_entrance('North Fairy Cave Drop', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('North Fairy Cave Drop', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Lost Woods Hideout Drop', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Lost Woods Hideout Drop', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player) and (state.can_reach('Potion Shop Area', 'Region', player))) # new inverted region, need pearl for bushes or access to potion shop door/waterfall fairy set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player) and (state.can_reach('Potion Shop Area', 'Region', player))) # new inverted region, need pearl for bushes or access to potion shop door/waterfall fairy
set_rule(world.get_entrance('Desert Palace Entrance (North) Rocks', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Desert Palace Entrance (North) Rocks', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Desert Ledge Return Rocks', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) # should we decide to place something that is not a dungeon end up there at some point set_rule(world.get_entrance('Desert Ledge Return Rocks', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player)) # should we decide to place something that is not a dungeon end up there at some point
set_rule(world.get_entrance('Checkerboard Cave', player), lambda state: state.can_lift_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Checkerboard Cave', player), lambda state: can_lift_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Hyrule Castle Secret Entrance Drop', player), lambda state: state.has('Moon Pearl', player)) set_rule(world.get_entrance('Hyrule Castle Secret Entrance Drop', player), lambda state: state.has('Moon Pearl', player))
set_rule(world.get_entrance('Old Man Cave Exit (West)', player), lambda state: False) # drop cannot be climbed up set_rule(world.get_entrance('Old Man Cave Exit (West)', player), lambda state: False) # drop cannot be climbed up
set_rule(world.get_entrance('Broken Bridge (West)', player), lambda state: state.has('Hookshot', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Broken Bridge (West)', player), lambda state: state.has('Hookshot', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Broken Bridge (East)', player), lambda state: state.has('Hookshot', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Broken Bridge (East)', player), lambda state: state.has('Hookshot', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Dark Death Mountain Teleporter (East Bottom)', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Dark Death Mountain Teleporter (East Bottom)', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Fairy Ascension Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Fairy Ascension Rocks', player), lambda state: can_lift_heavy_rocks(state, player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block
set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has('Moon Pearl', player)) set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has('Moon Pearl', player))
set_rule(world.get_entrance('Dark Death Mountain Teleporter (East)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Hammer', player) and state.has('Moon Pearl', player)) # bunny cannot use hammer set_rule(world.get_entrance('Dark Death Mountain Teleporter (East)', player), lambda state: can_lift_heavy_rocks(state, player) and state.has('Hammer', player) and state.has('Moon Pearl', player)) # bunny cannot use hammer
set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has('Moon Pearl', player)) # bunny can not use hammer set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has('Moon Pearl', player)) # bunny can not use hammer
set_rule(world.get_entrance('Catfish Entrance Rock', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Catfish Entrance Rock', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Northeast Dark World Broken Bridge Pass', player), lambda state: ((state.can_lift_rocks(player) or state.has('Hammer', player)) or state.has('Flippers', player))) set_rule(world.get_entrance('Northeast Dark World Broken Bridge Pass', player), lambda state: ((can_lift_rocks(state, player) or state.has('Hammer', player)) or state.has('Flippers', player)))
set_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: (state.can_lift_rocks(player) or state.has('Hammer', player))) set_rule(world.get_entrance('East Dark World Broken Bridge Pass', player), lambda state: (can_lift_rocks(state, player) or state.has('Hammer', player)))
set_rule(world.get_entrance('South Dark World Bridge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('South Dark World Bridge', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Bonk Fairy (Dark)', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Bonk Fairy (Dark)', player), lambda state: state.has('Pegasus Boots', player))
set_rule(world.get_entrance('West Dark World Gap', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('West Dark World Gap', player), lambda state: state.has('Hookshot', player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Flippers', player))
set_rule(world.get_location('Bombos Tablet', player), lambda state: state.can_retrieve_tablet(player)) set_rule(world.get_location('Bombos Tablet', player), lambda state: can_retrieve_tablet(state, player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has('Flippers', player)) # ToDo any fake flipper set up? set_rule(world.get_entrance('Dark Lake Hylia Drop (South)', player), lambda state: state.has('Flippers', player)) # ToDo any fake flipper set up?
set_rule(world.get_entrance('Dark Lake Hylia Ledge Pier', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Ledge Pier', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Dark Lake Hylia Ledge Spike Cave', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player)) # Fake Flippers set_rule(world.get_entrance('Dark Lake Hylia Teleporter', player), lambda state: state.has('Flippers', player)) # Fake Flippers
set_rule(world.get_entrance('Dark Lake Hylia Shallows', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Shallows', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Village of Outcasts Heavy Rock', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('East Dark World Bridge', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('East Dark World Bridge', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('East Dark World River Pier', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Bumper Cave Entrance Rock', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Bumper Cave Entrance Rock', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Hammer Peg Area Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Hammer Peg Area Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Dark World Hammer Peg Cave', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Dark World Hammer Peg Cave', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Village of Outcasts Eastern Rocks', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Village of Outcasts Eastern Rocks', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Peg Area Rocks', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Peg Area Rocks', player), lambda state: can_lift_heavy_rocks(state, player))
set_rule(world.get_entrance('Village of Outcasts Pegs', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Village of Outcasts Pegs', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Grassy Lawn Pegs', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Grassy Lawn Pegs', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Bumper Cave Exit (Top)', player), lambda state: state.has('Cape', player)) set_rule(world.get_entrance('Bumper Cave Exit (Top)', player), lambda state: state.has('Cape', player))
set_rule(world.get_entrance('Bumper Cave Exit (Bottom)', player), lambda state: state.has('Cape', player) or state.has('Hookshot', player)) set_rule(world.get_entrance('Bumper Cave Exit (Bottom)', player), lambda state: state.has('Cape', player) or state.has('Hookshot', player))
set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player)) set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player))
set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has_sword(player) and state.has_misery_mire_medallion(player)) # sword required to cast magic (!) set_rule(world.get_entrance('Misery Mire', player), lambda state: has_sword(state, player) and has_misery_mire_medallion(state, player)) # sword required to cast magic (!)
set_rule(world.get_entrance('Hookshot Cave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Hookshot Cave', player), lambda state: can_lift_rocks(state, player))
set_rule(world.get_entrance('East Death Mountain Mirror Spot (Top)', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('East Death Mountain Mirror Spot (Top)', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Death Mountain (Top) Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Death Mountain (Top) Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
@ -646,7 +653,7 @@ def inverted_rules(world, player):
set_rule(world.get_entrance('Dark Death Mountain Ledge Mirror Spot (West)', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Dark Death Mountain Ledge Mirror Spot (West)', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Laser Bridge Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Laser Bridge Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player)) set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has('Magic Mirror', player))
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_sword(player) and state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword required to cast magic (!) set_rule(world.get_entrance('Turtle Rock', player), lambda state: has_sword(state, player) and has_turtle_rock_medallion(state, player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword required to cast magic (!)
# new inverted spots # new inverted spots
set_rule(world.get_entrance('Post Aga Teleporter', player), lambda state: state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Post Aga Teleporter', player), lambda state: state.has('Beat Agahnim 1', player))
@ -687,7 +694,7 @@ def inverted_rules(world, player):
def no_glitches_rules(world, player): def no_glitches_rules(world, player):
"""""" """"""
if world.mode[player] == 'inverted': if world.mode[player] == 'inverted':
set_rule(world.get_entrance('Zoras River', player), lambda state: state.has('Moon Pearl', player) and (state.has('Flippers', player) or state.can_lift_rocks(player))) set_rule(world.get_entrance('Zoras River', player), lambda state: state.has('Moon Pearl', player) and (state.has('Flippers', player) or can_lift_rocks(state, player)))
set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # can be fake flippered to set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # can be fake flippered to
set_rule(world.get_entrance('Lake Hylia Island Pier', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # can be fake flippered to set_rule(world.get_entrance('Lake Hylia Island Pier', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # can be fake flippered to
set_rule(world.get_entrance('Lake Hylia Warp', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # can be fake flippered to set_rule(world.get_entrance('Lake Hylia Warp', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) # can be fake flippered to
@ -698,7 +705,7 @@ def no_glitches_rules(world, player):
set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Ledge Drop', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('East Dark World Pier', player), lambda state: state.has('Flippers', player))
else: else:
set_rule(world.get_entrance('Zoras River', player), lambda state: state.has('Flippers', player) or state.can_lift_rocks(player)) set_rule(world.get_entrance('Zoras River', player), lambda state: state.has('Flippers', player) or can_lift_rocks(state, player))
set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has('Flippers', player)) # can be fake flippered to set_rule(world.get_entrance('Lake Hylia Central Island Pier', player), lambda state: state.has('Flippers', player)) # can be fake flippered to
set_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has('Flippers', player)) set_rule(world.get_entrance('Hobo Bridge', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player)) set_rule(world.get_entrance('Dark Lake Hylia Drop (East)', player), lambda state: state.has('Moon Pearl', player) and state.has('Flippers', player))
@ -820,19 +827,19 @@ def open_rules(world, player):
def swordless_rules(world, player): def swordless_rules(world, player):
set_rule(world.get_entrance('Agahnim 1', player), lambda state: (state.has('Hammer', player) or state.has('Fire Rod', player) or state.can_shoot_arrows(player) or state.has('Cane of Somaria', player)) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 2)) set_rule(world.get_entrance('Agahnim 1', player), lambda state: (state.has('Hammer', player) or state.has('Fire Rod', player) or can_shoot_arrows(state, player) or state.has('Cane of Somaria', player)) and state._lttp_has_key('Small Key (Agahnims Tower)', player, 2))
set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player)) # no curtain set_rule(world.get_entrance('Skull Woods Torch Room', player), lambda state: state._lttp_has_key('Small Key (Skull Woods)', player, 3) and state.has('Fire Rod', player)) # no curtain
set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.has('Fire Rod', player) or state.has('Bombos', player)) #in swordless mode bombos pads are present in the relevant parts of ice palace set_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.has('Fire Rod', player) or state.has('Bombos', player)) #in swordless mode bombos pads are present in the relevant parts of ice palace
set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has('Hammer', player)) # need to damage ganon to get tiles to drop set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has('Hammer', player)) # need to damage ganon to get tiles to drop
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has('Moon Pearl', player) and state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword not required to use medallion for opening in swordless (!) set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has('Moon Pearl', player) and has_turtle_rock_medallion(state, player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword not required to use medallion for opening in swordless (!)
set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has('Moon Pearl', player) and state.has_misery_mire_medallion(player)) # sword not required to use medallion for opening in swordless (!) set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has('Moon Pearl', player) and has_misery_mire_medallion(state, player)) # sword not required to use medallion for opening in swordless (!)
else: else:
# only need ddm access for aga tower in inverted # only need ddm access for aga tower in inverted
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword not required to use medallion for opening in swordless (!) set_rule(world.get_entrance('Turtle Rock', player), lambda state: has_turtle_rock_medallion(state, player) and state.can_reach('Turtle Rock (Top)', 'Region', player)) # sword not required to use medallion for opening in swordless (!)
set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has_misery_mire_medallion(player)) # sword not required to use medallion for opening in swordless (!) set_rule(world.get_entrance('Misery Mire', player), lambda state: has_misery_mire_medallion(state, player)) # sword not required to use medallion for opening in swordless (!)
def add_connection(parent_name, target_name, entrance_name, world, player): def add_connection(parent_name, target_name, entrance_name, world, player):
@ -1083,7 +1090,7 @@ def set_big_bomb_rules(world, player):
# returning via the eastern and southern teleporters needs the same items, so we use the southern teleporter for out routing. # returning via the eastern and southern teleporters needs the same items, so we use the southern teleporter for out routing.
# crossing preg bridge already requires hammer so we just add the gloves to the requirement # crossing preg bridge already requires hammer so we just add the gloves to the requirement
def southern_teleporter(state): def southern_teleporter(state):
return state.can_lift_rocks(player) and cross_peg_bridge(state) return can_lift_rocks(state, player) and cross_peg_bridge(state)
# the basic routes assume you can reach eastern light world with the bomb. # the basic routes assume you can reach eastern light world with the bomb.
# you can then use the southern teleporter, or (if you have beaten Aga1) the hyrule castle gate warp # you can then use the southern teleporter, or (if you have beaten Aga1) the hyrule castle gate warp
@ -1110,13 +1117,13 @@ def set_big_bomb_rules(world, player):
#1. Mirror and basic routes #1. Mirror and basic routes
#2. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl #2. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl
# -> (Mitts and CPB) or (M and BR) # -> (Mitts and CPB) or (M and BR)
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (state.has('Magic Mirror', player) and basic_routes(state))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (can_lift_heavy_rocks(state, player) and cross_peg_bridge(state)) or (state.has('Magic Mirror', player) and basic_routes(state)))
elif bombshop_entrance.name == 'Bumper Cave (Bottom)': elif bombshop_entrance.name == 'Bumper Cave (Bottom)':
#1. Mirror and Lift rock and basic_routes #1. Mirror and Lift rock and basic_routes
#2. Mirror and Flute and basic routes (can make difference if accessed via insanity or w/ mirror from connector, and then via hyrule castle gate, because no gloves are needed in that case) #2. Mirror and Flute and basic routes (can make difference if accessed via insanity or w/ mirror from connector, and then via hyrule castle gate, because no gloves are needed in that case)
#3. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl #3. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl
# -> (Mitts and CPB) or (((G or Flute) and M) and BR)) # -> (Mitts and CPB) or (((G or Flute) and M) and BR))
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (((state.can_lift_rocks(player) or state.has('Flute', player)) and state.has('Magic Mirror', player)) and basic_routes(state))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (can_lift_heavy_rocks(state, player) and cross_peg_bridge(state)) or (((can_lift_rocks(state, player) or state.has('Flute', player)) and state.has('Magic Mirror', player)) and basic_routes(state)))
elif bombshop_entrance.name in Southern_DW_entrances: elif bombshop_entrance.name in Southern_DW_entrances:
#1. Mirror and enter via gate: Need mirror and Aga1 #1. Mirror and enter via gate: Need mirror and Aga1
#2. cross peg bridge: Need hammer and moon pearl #2. cross peg bridge: Need hammer and moon pearl
@ -1144,7 +1151,7 @@ def set_big_bomb_rules(world, player):
elif bombshop_entrance.name == 'Fairy Ascension Cave (Bottom)': elif bombshop_entrance.name == 'Fairy Ascension Cave (Bottom)':
# Same as East_LW_DM_entrances except navigation without BR requires Mitts # Same as East_LW_DM_entrances except navigation without BR requires Mitts
# -> Flute and ((M and Hookshot and Mitts) or BR) # -> Flute and ((M and Hookshot and Mitts) or BR)
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) and ((state.has('Magic Mirror', player) and state.has('Hookshot', player) and state.can_lift_heavy_rocks(player)) or basic_routes(state))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) and ((state.has('Magic Mirror', player) and state.has('Hookshot', player) and can_lift_heavy_rocks(state, player)) or basic_routes(state)))
elif bombshop_entrance.name in Castle_ledge_entrances: elif bombshop_entrance.name in Castle_ledge_entrances:
# 1. mirror on pyramid to castle ledge, grab bomb, return through mirror spot: Needs mirror # 1. mirror on pyramid to castle ledge, grab bomb, return through mirror spot: Needs mirror
# 2. flute then basic routes # 2. flute then basic routes
@ -1160,7 +1167,7 @@ def set_big_bomb_rules(world, player):
# 1. Lift rock then basic_routes # 1. Lift rock then basic_routes
# 2. flute then basic_routes # 2. flute then basic_routes
# -> (Flute or G) and BR # -> (Flute or G) and BR
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or state.can_lift_rocks(player)) and basic_routes(state)) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or can_lift_rocks(state, player)) and basic_routes(state))
elif bombshop_entrance.name == 'Graveyard Cave': elif bombshop_entrance.name == 'Graveyard Cave':
# 1. flute then basic routes # 1. flute then basic routes
# 2. (has west dark world access) use existing mirror spot (required Pearl), mirror again off ledge # 2. (has west dark world access) use existing mirror spot (required Pearl), mirror again off ledge
@ -1176,13 +1183,13 @@ def set_big_bomb_rules(world, player):
# 2. walk down by hammering peg: needs hammer and pearl # 2. walk down by hammering peg: needs hammer and pearl
# 3. mirror and basic routes # 3. mirror and basic routes
# -> (P and (H or Gloves)) or (M and BR) # -> (P and (H or Gloves)) or (M and BR)
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Moon Pearl', player) and (state.has('Hammer', player) or state.can_lift_rocks(player))) or (state.has('Magic Mirror', player) and basic_routes(state))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Moon Pearl', player) and (state.has('Hammer', player) or can_lift_rocks(state, player))) or (state.has('Magic Mirror', player) and basic_routes(state)))
elif bombshop_entrance.name == 'Kings Grave': elif bombshop_entrance.name == 'Kings Grave':
# same as the Normal_LW_entrances case except that the pre-existing mirror is only possible if you have mitts # same as the Normal_LW_entrances case except that the pre-existing mirror is only possible if you have mitts
# (because otherwise mirror was used to reach the grave, so would cancel a pre-existing mirror spot) # (because otherwise mirror was used to reach the grave, so would cancel a pre-existing mirror spot)
# to account for insanity, must consider a way to escape without a cave for basic_routes # to account for insanity, must consider a way to escape without a cave for basic_routes
# -> (M and Mitts) or ((Mitts or Flute or (M and P and West Dark World access)) and BR) # -> (M and Mitts) or ((Mitts or Flute or (M and P and West Dark World access)) and BR)
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and state.has('Magic Mirror', player)) or ((state.can_lift_heavy_rocks(player) or state.has('Activated Flute', player) or (state.can_reach('West Dark World', 'Region', player) and state.has('Moon Pearl', player) and state.has('Magic Mirror', player))) and basic_routes(state))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (can_lift_heavy_rocks(state, player) and state.has('Magic Mirror', player)) or ((can_lift_heavy_rocks(state, player) or state.has('Activated Flute', player) or (state.can_reach('West Dark World', 'Region', player) and state.has('Moon Pearl', player) and state.has('Magic Mirror', player))) and basic_routes(state)))
elif bombshop_entrance.name == 'Waterfall of Wishing': elif bombshop_entrance.name == 'Waterfall of Wishing':
# same as the Normal_LW_entrances case except in insanity it's possible you could be here without Flippers which # same as the Normal_LW_entrances case except in insanity it's possible you could be here without Flippers which
# means you need an escape route of either Flippers or Flute # means you need an escape route of either Flippers or Flute
@ -1329,7 +1336,7 @@ def set_inverted_big_bomb_rules(world, player):
elif bombshop_entrance.name in Northern_DW_entrances: elif bombshop_entrance.name in Northern_DW_entrances:
# You can just fly with the Flute, you can take a long walk with Mitts and Hammer, # You can just fly with the Flute, you can take a long walk with Mitts and Hammer,
# or you can leave a Mirror portal nearby and then walk to the castle to Mirror again. # or you can leave a Mirror portal nearby and then walk to the castle to Mirror again.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (can_lift_heavy_rocks(state, player) and state.has('Hammer', player)) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player)))
elif bombshop_entrance.name in Southern_DW_entrances: elif bombshop_entrance.name in Southern_DW_entrances:
# This is the same as north DW without the Mitts rock present. # This is the same as north DW without the Mitts rock present.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Hammer', player) or state.has('Activated Flute', player) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Hammer', player) or state.has('Activated Flute', player) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player)))
@ -1341,22 +1348,22 @@ def set_inverted_big_bomb_rules(world, player):
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player)))
elif bombshop_entrance.name in LW_bush_entrances: elif bombshop_entrance.name in LW_bush_entrances:
# These entrances are behind bushes in LW so you need either Pearl or the tools to solve NDW bomb shop locations. # These entrances are behind bushes in LW so you need either Pearl or the tools to solve NDW bomb shop locations.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Magic Mirror', player) and (state.has('Activated Flute', player) or state.has('Moon Pearl', player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Magic Mirror', player) and (state.has('Activated Flute', player) or state.has('Moon Pearl', player) or (can_lift_heavy_rocks(state, player) and state.has('Hammer', player))))
elif bombshop_entrance.name == 'Village of Outcasts Shop': elif bombshop_entrance.name == 'Village of Outcasts Shop':
# This is mostly the same as NDW but the Mirror path requires the Pearl, or using the Hammer # This is mostly the same as NDW but the Mirror path requires the Pearl, or using the Hammer
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player) and (state.has('Moon Pearl', player) or state.has('Hammer', player)))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (can_lift_heavy_rocks(state, player) and state.has('Hammer', player)) or (state.has('Magic Mirror', player) and state.can_reach('Light World', 'Region', player) and (state.has('Moon Pearl', player) or state.has('Hammer', player))))
elif bombshop_entrance.name == 'Bumper Cave (Bottom)': elif bombshop_entrance.name == 'Bumper Cave (Bottom)':
# This is mostly the same as NDW but the Mirror path requires being able to lift a rock. # This is mostly the same as NDW but the Mirror path requires being able to lift a rock.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has('Magic Mirror', player) and state.can_lift_rocks(player) and state.can_reach('Light World', 'Region', player))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or (can_lift_heavy_rocks(state, player) and state.has('Hammer', player)) or (state.has('Magic Mirror', player) and can_lift_rocks(state, player) and state.can_reach('Light World', 'Region', player)))
elif bombshop_entrance.name == 'Old Man Cave (West)': elif bombshop_entrance.name == 'Old Man Cave (West)':
# The three paths back are Mirror and DW walk, Mirror and Flute, or LW walk and then Mirror. # The three paths back are Mirror and DW walk, Mirror and Flute, or LW walk and then Mirror.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Magic Mirror', player) and ((state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.can_lift_rocks(player) and state.has('Moon Pearl', player)) or state.has('Activated Flute', player))) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Magic Mirror', player) and ((can_lift_heavy_rocks(state, player) and state.has('Hammer', player)) or (can_lift_rocks(state, player) and state.has('Moon Pearl', player)) or state.has('Activated Flute', player)))
elif bombshop_entrance.name == 'Dark World Potion Shop': elif bombshop_entrance.name == 'Dark World Potion Shop':
# You either need to Flute to 5 or cross the rock/hammer choice pass to the south. # You either need to Flute to 5 or cross the rock/hammer choice pass to the south.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or state.has('Hammer', player) or state.can_lift_rocks(player)) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Activated Flute', player) or state.has('Hammer', player) or can_lift_rocks(state, player))
elif bombshop_entrance.name == 'Kings Grave': elif bombshop_entrance.name == 'Kings Grave':
# Either lift the rock and walk to the castle to Mirror or Mirror immediately and Flute. # Either lift the rock and walk to the castle to Mirror or Mirror immediately and Flute.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or state.can_lift_heavy_rocks(player)) and state.has('Magic Mirror', player)) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Activated Flute', player) or can_lift_heavy_rocks(state, player)) and state.has('Magic Mirror', player))
elif bombshop_entrance.name == 'Waterfall of Wishing': elif bombshop_entrance.name == 'Waterfall of Wishing':
# You absolutely must be able to swim to return it from here. # You absolutely must be able to swim to return it from here.
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player) and state.has('Magic Mirror', player)) add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) and state.has('Moon Pearl', player) and state.has('Magic Mirror', player))
@ -1421,7 +1428,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool):
if region.name == 'Swamp Palace (Entrance)': # Need to 0hp revive - not in logic if region.name == 'Swamp Palace (Entrance)': # Need to 0hp revive - not in logic
return lambda state: state.has('Moon Pearl', player) return lambda state: state.has('Moon Pearl', player)
if region.name == 'Tower of Hera (Bottom)': # Need to hit the crystal switch if region.name == 'Tower of Hera (Bottom)': # Need to hit the crystal switch
return lambda state: state.has('Magic Mirror', player) and state.has_sword(player) or state.has('Moon Pearl', player) return lambda state: state.has('Magic Mirror', player) and has_sword(state, player) or state.has('Moon Pearl', player)
if region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): if region.name in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
return lambda state: state.has('Magic Mirror', player) or state.has('Moon Pearl', player) return lambda state: state.has('Magic Mirror', player) or state.has('Moon Pearl', player)
if region.type == LTTPRegionType.Dungeon: if region.type == LTTPRegionType.Dungeon:
@ -1459,7 +1466,7 @@ def set_bunny_rules(world: MultiWorld, player: int, inverted: bool):
# For glitch rulesets, establish superbunny and revival rules. # For glitch rulesets, establish superbunny and revival rules.
if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons(): if world.logic[player] in ['minorglitches', 'owglitches', 'hybridglitches', 'nologic'] and entrance.name not in OverworldGlitchRules.get_invalid_bunny_revival_dungeons():
if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions(): if region.name in OverworldGlitchRules.get_sword_required_superbunny_mirror_regions():
possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has('Magic Mirror', player) and state.has_sword(player)) possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has('Magic Mirror', player) and has_sword(state, player))
elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions() elif (region.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_regions()
or location is not None and location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations()): or location is not None and location.name in OverworldGlitchRules.get_boots_required_superbunny_mirror_locations()):
possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has('Magic Mirror', player) and state.has('Pegasus Boots', player)) possible_options.append(lambda state: path_to_access_rule(new_path, entrance) and state.has('Magic Mirror', player) and state.has('Pegasus Boots', player))

View File

@ -0,0 +1,137 @@
from .SubClasses import LTTPRegion
from BaseClasses import CollectionState
def is_not_bunny(state: CollectionState, region: LTTPRegion, player: int) -> bool:
if state.has('Moon Pearl', player):
return True
return region.is_light_world if state.multiworld.mode[player] != 'inverted' else region.is_dark_world
def can_bomb_clip(state: CollectionState, region: LTTPRegion, player: int) -> bool:
return is_not_bunny(state, region, player) and state.has('Pegasus Boots', player)
def can_buy_unlimited(state: CollectionState, item: str, player: int) -> bool:
return any(shop.region.player == player and shop.has_unlimited(item) and shop.region.can_reach(state) for
shop in state.multiworld.shops)
def can_buy(state: CollectionState, item: str, player: int) -> bool:
return any(shop.region.player == player and shop.has(item) and shop.region.can_reach(state) for
shop in state.multiworld.shops)
def can_shoot_arrows(state: CollectionState, player: int) -> bool:
if state.multiworld.retro_bow[player]:
return (state.has('Bow', player) or state.has('Silver Bow', player)) and can_buy(state, 'Single Arrow', player)
return state.has('Bow', player) or state.has('Silver Bow', player)
def has_triforce_pieces(state: CollectionState, player: int) -> bool:
count = state.multiworld.treasure_hunt_count[player]
return state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= count
def has_crystals(state: CollectionState, count: int, player: int) -> bool:
found = state.count_group("Crystals", player)
return found >= count
def can_lift_rocks(state: CollectionState, player: int):
return state.has('Power Glove', player) or state.has('Titans Mitts', player)
def can_lift_heavy_rocks(state: CollectionState, player: int) -> bool:
return state.has('Titans Mitts', player)
def bottle_count(state: CollectionState, player: int) -> int:
return min(state.multiworld.difficulty_requirements[player].progressive_bottle_limit,
state.count_group("Bottles", player))
def has_hearts(state: CollectionState, player: int, count: int) -> int:
# Warning: This only considers items that are marked as advancement items
return heart_count(state, player) >= count
def heart_count(state: CollectionState, player: int) -> int:
# Warning: This only considers items that are marked as advancement items
diff = state.multiworld.difficulty_requirements[player]
return min(state.item_count('Boss Heart Container', player), diff.boss_heart_container_limit) \
+ state.item_count('Sanctuary Heart Container', player) \
+ min(state.item_count('Piece of Heart', player), diff.heart_piece_limit) // 4 \
+ 3 # starting hearts
def can_extend_magic(state: CollectionState, player: int, smallmagic: int = 16,
fullrefill: bool = False): # This reflects the total magic Link has, not the total extra he has.
basemagic = 8
if state.has('Magic Upgrade (1/4)', player):
basemagic = 32
elif state.has('Magic Upgrade (1/2)', player):
basemagic = 16
if can_buy_unlimited(state, 'Green Potion', player) or can_buy_unlimited(state, 'Blue Potion', player):
if state.multiworld.item_functionality[player] == 'hard' and not fullrefill:
basemagic = basemagic + int(basemagic * 0.5 * bottle_count(state, player))
elif state.multiworld.item_functionality[player] == 'expert' and not fullrefill:
basemagic = basemagic + int(basemagic * 0.25 * bottle_count(state, player))
else:
basemagic = basemagic + basemagic * bottle_count(state, player)
return basemagic >= smallmagic
def can_kill_most_things(state: CollectionState, player: int, enemies: int = 5) -> bool:
return (has_melee_weapon(state, player)
or state.has('Cane of Somaria', player)
or (state.has('Cane of Byrna', player) and (enemies < 6 or can_extend_magic(state, player)))
or can_shoot_arrows(state, player)
or state.has('Fire Rod', player)
or (state.has('Bombs (10)', player) and enemies < 6))
def can_get_good_bee(state: CollectionState, player: int) -> bool:
cave = state.multiworld.get_region('Good Bee Cave', player)
return (
state.has_group("Bottles", player) and
state.has('Bug Catching Net', player) and
(state.has('Pegasus Boots', player) or (has_sword(state, player) and state.has('Quake', player))) and
cave.can_reach(state) and
is_not_bunny(state, cave, player)
)
def can_retrieve_tablet(state: CollectionState, player: int) -> bool:
return state.has('Book of Mudora', player) and (has_beam_sword(state, player) or
(state.multiworld.swordless[player] and
state.has("Hammer", player)))
def has_sword(state: CollectionState, player: int) -> bool:
return state.has('Fighter Sword', player) \
or state.has('Master Sword', player) \
or state.has('Tempered Sword', player) \
or state.has('Golden Sword', player)
def has_beam_sword(state: CollectionState, player: int) -> bool:
return state.has('Master Sword', player) or state.has('Tempered Sword', player) or state.has('Golden Sword',
player)
def has_melee_weapon(state: CollectionState, player: int) -> bool:
return has_sword(state, player) or state.has('Hammer', player)
def has_fire_source(state: CollectionState, player: int) -> bool:
return state.has('Fire Rod', player) or state.has('Lamp', player)
def can_melt_things(state: CollectionState, player: int) -> bool:
return state.has('Fire Rod', player) or \
(state.has('Bombos', player) and
(state.multiworld.swordless[player] or
has_sword(state, player)))
def has_misery_mire_medallion(state: CollectionState, player: int) -> bool:
return state.has(state.multiworld.required_medallions[player][0], player)
def has_turtle_rock_medallion(state: CollectionState, player: int) -> bool:
return state.has(state.multiworld.required_medallions[player][1], player)
def can_boots_clip_lw(state: CollectionState, player: int) -> bool:
if state.multiworld.mode[player] == 'inverted':
return state.has('Pegasus Boots', player) and state.has('Moon Pearl', player)
return state.has('Pegasus Boots', player)
def can_boots_clip_dw(state: CollectionState, player: int) -> bool:
if state.multiworld.mode[player] != 'inverted':
return state.has('Pegasus Boots', player) and state.has('Moon Pearl', player)
return state.has('Pegasus Boots', player)
def can_get_glitched_speed_dw(state: CollectionState, player: int) -> bool:
rules = [state.has('Pegasus Boots', player), any([state.has('Hookshot', player), has_sword(state, player)])]
if state.multiworld.mode[player] != 'inverted':
rules.append(state.has('Moon Pearl', player))
return all(rules)

View File

@ -4,7 +4,6 @@ from enum import IntEnum
from BaseClasses import Location, Item, ItemClassification, Region, MultiWorld from BaseClasses import Location, Item, ItemClassification, Region, MultiWorld
class ALttPLocation(Location): class ALttPLocation(Location):
game: str = "A Link to the Past" game: str = "A Link to the Past"
crystal: bool crystal: bool
@ -81,6 +80,12 @@ class LTTPRegionType(IntEnum):
class LTTPRegion(Region): class LTTPRegion(Region):
type: LTTPRegionType type: LTTPRegionType
# will be set after making connections.
is_light_world: bool = False
is_dark_world: bool = False
shop: Optional = None
def __init__(self, name: str, type_: LTTPRegionType, hint: str, player: int, multiworld: MultiWorld): def __init__(self, name: str, type_: LTTPRegionType, hint: str, player: int, multiworld: MultiWorld):
super().__init__(name, player, multiworld, hint) super().__init__(name, player, multiworld, hint)
self.type = type_ self.type = type_

View File

@ -1,6 +1,8 @@
from BaseClasses import Entrance from BaseClasses import Entrance
from .SubClasses import LTTPRegion
from worlds.generic.Rules import set_rule, add_rule from worlds.generic.Rules import set_rule, add_rule
from .StateHelpers import can_bomb_clip, has_sword, has_beam_sword, has_fire_source, can_melt_things, has_misery_mire_medallion
# We actually need the logic to properly "mark" these regions as Light or Dark world. # We actually need the logic to properly "mark" these regions as Light or Dark world.
# Therefore we need to make these connections during the normal link_entrances stage, rather than during set_rules. # Therefore we need to make these connections during the normal link_entrances stage, rather than during set_rules.
@ -46,9 +48,9 @@ def dungeon_reentry_rules(world, player, clip: Entrance, dungeon_region: str, du
if dungeon_entrance.name == 'Skull Woods Final Section': if dungeon_entrance.name == 'Skull Woods Final Section':
set_rule(clip, lambda state: False) # entrance doesn't exist until you fire rod it from the other side set_rule(clip, lambda state: False) # entrance doesn't exist until you fire rod it from the other side
elif dungeon_entrance.name == 'Misery Mire': elif dungeon_entrance.name == 'Misery Mire':
add_rule(clip, lambda state: state.has_sword(player) and state.has_misery_mire_medallion(player)) # open the dungeon add_rule(clip, lambda state: has_sword(state, player) and has_misery_mire_medallion(state, player)) # open the dungeon
elif dungeon_entrance.name == 'Agahnims Tower': elif dungeon_entrance.name == 'Agahnims Tower':
add_rule(clip, lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # kill/bypass barrier add_rule(clip, lambda state: state.has('Cape', player) or has_beam_sword(state, player) or state.has('Beat Agahnim 1', player)) # kill/bypass barrier
# Then we set a restriction on exiting the dungeon, so you can't leave unless you got in normally. # Then we set a restriction on exiting the dungeon, so you can't leave unless you got in normally.
add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state)) add_rule(world.get_entrance(dungeon_exit, player), lambda state: dungeon_entrance.can_reach(state))
elif not fix_fake_worlds: # full, dungeonsfull; fixed dungeon exits, but no fake worlds fix elif not fix_fake_worlds: # full, dungeonsfull; fixed dungeon exits, but no fake worlds fix
@ -66,21 +68,21 @@ def underworld_glitches_rules(world, player):
# Ice Palace Entrance Clip # Ice Palace Entrance Clip
# This is the easiest one since it's a simple internal clip. Just need to also add melting to freezor chest since it's otherwise assumed. # This is the easiest one since it's a simple internal clip. Just need to also add melting to freezor chest since it's otherwise assumed.
add_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: state.can_bomb_clip(world.get_region('Ice Palace (Entrance)', player), player), combine='or') add_rule(world.get_entrance('Ice Palace Entrance Room', player), lambda state: can_bomb_clip(state, world.get_region('Ice Palace (Entrance)', player), player), combine='or')
add_rule(world.get_location('Ice Palace - Freezor Chest', player), lambda state: state.can_melt_things(player)) add_rule(world.get_location('Ice Palace - Freezor Chest', player), lambda state: can_melt_things(state, player))
# Kiki Skip # Kiki Skip
kikiskip = world.get_entrance('Kiki Skip', player) kikiskip = world.get_entrance('Kiki Skip', player)
set_rule(kikiskip, lambda state: state.can_bomb_clip(kikiskip.parent_region, player)) set_rule(kikiskip, lambda state: can_bomb_clip(state, kikiskip.parent_region, player))
dungeon_reentry_rules(world, player, kikiskip, 'Palace of Darkness (Entrance)', 'Palace of Darkness Exit') dungeon_reentry_rules(world, player, kikiskip, 'Palace of Darkness (Entrance)', 'Palace of Darkness Exit')
# Mire -> Hera -> Swamp # Mire -> Hera -> Swamp
# Using mire keys on other dungeon doors # Using mire keys on other dungeon doors
mire = world.get_region('Misery Mire (West)', player) mire = world.get_region('Misery Mire (West)', player)
mire_clip = lambda state: state.can_reach('Misery Mire (West)', 'Region', player) and state.can_bomb_clip(mire, player) and state.has_fire_source(player) mire_clip = lambda state: state.can_reach('Misery Mire (West)', 'Region', player) and can_bomb_clip(state, mire, player) and has_fire_source(state, player)
hera_clip = lambda state: state.can_reach('Tower of Hera (Top)', 'Region', player) and state.can_bomb_clip(world.get_region('Tower of Hera (Top)', player), player) hera_clip = lambda state: state.can_reach('Tower of Hera (Top)', 'Region', player) and can_bomb_clip(state, world.get_region('Tower of Hera (Top)', player), player)
add_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: mire_clip(state) and state.has('Big Key (Misery Mire)', player), combine='or') add_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: mire_clip(state) and state.has('Big Key (Misery Mire)', player), combine='or')
add_rule(world.get_entrance('Swamp Palace Small Key Door', player), lambda state: mire_clip(state), combine='or') add_rule(world.get_entrance('Swamp Palace Small Key Door', player), lambda state: mire_clip(state), combine='or')
add_rule(world.get_entrance('Swamp Palace (Center)', player), lambda state: mire_clip(state) or hera_clip(state), combine='or') add_rule(world.get_entrance('Swamp Palace (Center)', player), lambda state: mire_clip(state) or hera_clip(state), combine='or')

View File

@ -23,6 +23,7 @@ from .Rules import set_rules
from .Shops import create_shops, ShopSlotFill, ShopType, price_rate_display, price_type_display_name from .Shops import create_shops, ShopSlotFill, ShopType, price_rate_display, price_type_display_name
from .SubClasses import ALttPItem, LTTPRegionType from .SubClasses import ALttPItem, LTTPRegionType
from worlds.AutoWorld import World, WebWorld, LogicMixin from worlds.AutoWorld import World, WebWorld, LogicMixin
from .StateHelpers import can_buy_unlimited
lttp_logger = logging.getLogger("A Link to the Past") lttp_logger = logging.getLogger("A Link to the Past")
@ -673,5 +674,5 @@ class ALttPLogic(LogicMixin):
if self.multiworld.logic[player] == 'nologic': if self.multiworld.logic[player] == 'nologic':
return True return True
if self.multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal: if self.multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
return self.can_buy_unlimited('Small Key (Universal)', player) return can_buy_unlimited(self, 'Small Key (Universal)', player)
return self.prog_items[item, player] >= count return self.prog_items[item, player] >= count