Merge branch 'OverworldShuffleDev' into OverworldShuffle

This commit is contained in:
codemann8
2022-11-28 16:27:32 -06:00
11 changed files with 187 additions and 176 deletions

View File

@@ -316,6 +316,9 @@ class World(object):
def is_tile_swapped(self, owid, player):
return (self.mode[player] == 'inverted') != (owid in self.owswaps[player][0] and self.owMixed[player])
def is_tile_lw_like(self, owid, player):
return (owid >= 0x40 and owid < 0x80) == self.is_tile_swapped(owid, player)
def is_atgt_swapped(self, player):
return self.is_tile_swapped(0x03, player) and self.is_tile_swapped(0x1b, player)
@@ -641,15 +644,6 @@ class CollectionState(object):
queue.append((conn, new_crystal_state))
self.path[new_region] = (new_region.name, self.path.get(connection, None))
# Retry connections if the new region can unblock them
from EntranceShuffle import indirect_connections
if new_region.name in indirect_connections:
new_entrance = self.world.get_entrance(indirect_connections[new_region.name], player)
if new_entrance in bc and new_entrance.parent_region in rrp:
new_crystal_state = rrp[new_entrance.parent_region]
if (new_entrance, new_crystal_state) not in queue:
queue.append((new_entrance, new_crystal_state))
# else those connections that are not accessible yet
if self.is_small_door(connection):
door = connection.door if connection.door.smallKey else connection.door.controller
@@ -1544,7 +1538,7 @@ class Entrance(object):
def can_reach(self, state):
# Destination Pickup OW Only No Ledges Can S&Q Allow Mirror
multi_step_locations = { 'Pyramid Crack': ('Big Bomb', True, True, False, True),
multi_step_locations = { 'Pyramid Area': ('Big Bomb', True, True, False, True),
'Missing Smith': ('Frog', True, False, True, True),
'Middle Aged Man': ('Dark Blacksmith Ruins', True, False, True, True),
'Old Man Drop Off': ('Lost Old Man', True, False, False, False),

View File

@@ -1,5 +1,10 @@
# Changelog
## 0.2.11.4
- Fixed broken OWG logic issues
- Gave chickens a base price for shopsanity
- Modeled TR entrance opening to use a logical pseudo-item
## 0.2.11.3
- Fixed error during multiworld generation
- Added proper Old Man pathing to the logic and spoiler playthru

View File

@@ -2296,30 +2296,6 @@ one_way_ledges = {
'Ice Lake Ledge (West)',
'Ice Lake Ledge (East)'}
}
indirect_connections = {
'Turtle Rock Ledge': 'Turtle Rock',
'Big Bomb Shop': 'Pyramid Crack',
#'East Dark World': 'Pyramid Fairy',
'Pyramid Area': 'Pyramid Crack', # HC Ledge/Courtyard
#'Dark Desert': 'Pyramid Fairy',
#'Misery Mire Area': 'Pyramid Fairy', # Desert/Checkerboard Ledge
#'West Dark World': 'Pyramid Fairy',
#'Dark Chapel Area': 'Pyramid Fairy', # Bonk Rocks
#'Dark Graveyard North': 'Pyramid Fairy', # Graveyard Ledge/Kings Tomb
#'South Dark World': 'Pyramid Fairy',
#'Dig Game Ledge': 'Pyramid Fairy', # Brother House Left
#'Stumpy Approach Area': 'Pyramid Fairy', # Cave 45
# Inverted Cases
#'Light World': 'Pyramid Fairy',
#'Lost Woods West Area': 'Pyramid Fairy', # Skull Woods Back
#'East Death Mountain (Top East)': 'Pyramid Fairy', # Floating Island
#'Blacksmith Area': 'Pyramid Fairy', # Hammerpegs
#'Forgotten Forest Area': 'Pyramid Fairy', # Shield Shop
#'Desert Area': 'Pyramid Fairy', # Mire Area
'Old Man Drop Off': 'Old Man S&Q',
'Old Man Cave': 'Old Man S&Q'
}
# format:
# Key=Name
# addr = (door_index, exitdata, ow_flag) # multiexit

View File

@@ -252,6 +252,9 @@ def generate_itempool(world, player):
world.push_item(world.get_location('Swamp Drain', player), ItemFactory('Drained Swamp', player), False)
world.get_location('Swamp Drain', player).event = True
world.get_location('Swamp Drain', player).locked = True
world.push_item(world.get_location('Turtle Medallion Pad', player), ItemFactory('Turtle Opened', player), False)
world.get_location('Turtle Medallion Pad', player).event = True
world.get_location('Turtle Medallion Pad', player).locked = True
world.push_item(world.get_location('Attic Cracked Floor', player), ItemFactory('Shining Light', player), False)
world.get_location('Attic Cracked Floor', player).event = True
world.get_location('Attic Cracked Floor', player).locked = True

View File

@@ -84,7 +84,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
'Arrows (5)': (False, False, None, 0xB5, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'),
'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'),
'Big Magic': (False, False, None, 0xB4, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'),
'Chicken': (False, False, None, 0xB3, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'),
'Chicken': (False, False, None, 0xB3, 5, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'),
'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'Increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
@@ -191,6 +191,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
'Trench 1 Filled': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Trench 2 Filled': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Drained Swamp': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Turtle Opened': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Shining Light': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Maiden Rescued': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Maiden Unmasked': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),

View File

@@ -1137,6 +1137,7 @@ OWTileRegions = bidict({
'Cave 45 Ledge': 0x32,
'C Whirlpool Area': 0x33,
'C Whirlpool Portal Area': 0x33,
'C Whirlpool Water': 0x33,
'C Whirlpool Outer Area': 0x33,
@@ -1274,6 +1275,7 @@ OWTileRegions = bidict({
'Stumpy Approach Bush Entry': 0x72,
'Dark C Whirlpool Area': 0x73,
'Dark C Whirlpool Portal Area': 0x73,
'Dark C Whirlpool Water': 0x73,
'Dark C Whirlpool Outer Area': 0x73,
@@ -1483,6 +1485,7 @@ OWExitTypes = {
'Tree Line WC Cliff Water Drop',
'C Whirlpool Outer Cliff Ledge Drop',
'C Whirlpool Cliff Ledge Drop',
'C Whirlpool Portal Cliff Ledge Drop',
'Statues Cliff Ledge Drop',
'Desert Ledge Drop',
'Checkerboard Ledge Drop',
@@ -1538,6 +1541,7 @@ OWExitTypes = {
'Dark Tree Line WC Cliff Water Drop',
'Dark C Whirlpool Outer Cliff Ledge Drop',
'Dark C Whirlpool Cliff Ledge Drop',
'Dark C Whirlpool Portal Cliff Ledge Drop',
'Hype Cliff Ledge Drop',
'Misery Mire Teleporter Ledge Drop',
'Mire Cliff Ledge Drop',
@@ -1622,9 +1626,11 @@ OWExitTypes = {
'Flute Boy Bush (North)',
'Cave 45 Inverted Leave',
'C Whirlpool Rock (Bottom)',
'C Whirlpool Rock (Top)',
'C Whirlpool Pegs (Right)',
'C Whirlpool Pegs (Left)',
'C Whirlpool Water Entry',
'C Whirlpool Landing',
'C Whirlpool Rock (Top)',
'Statues Water Entry',
'Statues Landing',
'Lake Hylia Central Water Drop',
@@ -1684,9 +1690,11 @@ OWExitTypes = {
'Stumpy Approach Bush (South)',
'Stumpy Approach Bush (North)',
'Dark C Whirlpool Rock (Bottom)',
'Dark C Whirlpool Rock (Top)',
'Dark C Whirlpool Pegs (Right)',
'Dark C Whirlpool Pegs (Left)',
'Dark C Whirlpool Water Entry',
'Dark C Whirlpool Landing',
'Dark C Whirlpool Rock (Top)',
'Hype Cave Water Entry',
'Hype Cave Landing',
'Ice Lake Northeast Water Drop',

View File

@@ -142,21 +142,15 @@ def get_boots_clip_exits_lw(world, player):
"""
for name, parent_region, target_region in boots_clips_local:
if not world.is_tile_swapped(OWTileRegions[parent_region], player):
if world.is_tile_lw_like(OWTileRegions[parent_region], player):
yield(name, parent_region, target_region)
for name, parent_region, target_region in boots_clips:
parent_swapped, target_swapped = get_swapped_status(world, player, parent_region, target_region)
if parent_region[0] and not parent_swapped:
if target_region[0] and not target_swapped:
yield(name[0], parent_region[0], target_region[0])
elif target_region[1]:
yield(name[0], parent_region[0], target_region[1])
elif parent_region[1]:
if target_region[0] and not target_swapped:
yield(name[1], parent_region[1], target_region[0])
elif target_region[1]:
yield(name[1], parent_region[1], target_region[1])
for names, parent_regions, target_regions in boots_clips:
region_pair = get_world_pair(world, player, get_region_pairs(world, player, names, parent_regions, target_regions), True)
if region_pair and region_pair[2]:
assert(region_pair[0], f'Exit name missing in OWG pairing from {region_pair[1]} to {region_pair[2]}')
yield(region_pair[0], region_pair[1], region_pair[2])
def get_boots_clip_exits_dw(world, player):
"""
@@ -164,21 +158,14 @@ def get_boots_clip_exits_dw(world, player):
"""
for name, parent_region, target_region in boots_clips_local:
if world.is_tile_swapped(OWTileRegions[parent_region], player):
if not world.is_tile_lw_like(OWTileRegions[parent_region], player):
yield(name, parent_region, target_region)
for name, parent_region, target_region in boots_clips:
parent_swapped, target_swapped = get_swapped_status(world, player, parent_region, target_region)
if parent_region[0] and parent_swapped:
if target_region[0] and target_swapped:
yield(name[0], parent_region[0], target_region[0])
elif target_region[1]:
yield(name[0], parent_region[0], target_region[1])
elif parent_region[1]:
if target_region[0] and target_swapped:
yield(name[1], parent_region[1], target_region[0])
elif target_region[1]:
yield(name[1], parent_region[1], target_region[1])
for names, parent_regions, target_regions in boots_clips:
region_pair = get_world_pair(world, player, get_region_pairs(world, player, names, parent_regions, target_regions), False)
if region_pair and region_pair[2]:
assert(region_pair[0], f'Exit name missing in OWG pairing from {region_pair[1]} to {region_pair[2]}')
yield(region_pair[0], region_pair[1], region_pair[2])
def get_glitched_speed_drops_lw(world, player):
@@ -198,21 +185,14 @@ def get_mirror_clip_spots(world, player):
"""
for name, parent_region, target_region in mirror_clips_local:
if not world.is_tile_swapped(OWTileRegions[parent_region], player):
if not world.is_tile_lw_like(OWTileRegions[parent_region], player):
yield(name, parent_region, target_region)
for name, parent_region, target_region in mirror_clips:
parent_swapped, target_swapped = get_swapped_status(world, player, parent_region, target_region)
if parent_region[0] and not parent_swapped:
if target_region[0] and not target_region:
yield(name[0], parent_region[0], target_region[0])
elif target_region[1]:
yield(name[0], parent_region[0], target_region[1])
elif parent_region[1]:
if target_region[0] and not target_region:
yield(name[1], parent_region[1], target_region[0])
elif target_region[1]:
yield(name[1], parent_region[1], target_region[1])
for names, parent_regions, target_regions in mirror_clips:
region_pair = get_world_pair(world, player, get_region_pairs(world, player, names, parent_regions, target_regions), False)
if region_pair and region_pair[2] and not world.is_tile_lw_like(OWTileRegions[region_pair[1]], player):
assert(region_pair[0], f'Exit name missing in OWG pairing from {region_pair[1]} to {region_pair[2]}')
yield(region_pair[0], region_pair[1], region_pair[2])
def get_mirror_offset_spots(world, player):
@@ -222,19 +202,11 @@ def get_mirror_offset_spots(world, player):
# TODO: These really should check to see if there is a mirrorless path to the mirror portal
# but being that OWG is very very open, it's very unlikely there isn't a path, but possible
for name, parent_region, target_region, path_to in mirror_offsets:
parent_swapped, target_swapped = get_swapped_status(world, player, parent_region, target_region)
if parent_region[0] and not parent_swapped:
if target_region[0] and not target_region:
yield(name[0], parent_region[0], target_region[0])
elif target_region[1]:
yield(name[0], parent_region[0], target_region[1])
elif parent_region[1]:
if target_region[0] and not target_region:
yield(name[1], parent_region[1], target_region[0])
elif target_region[1]:
yield(name[1], parent_region[1], target_region[1])
for names, parent_regions, target_regions, path_to in mirror_offsets:
region_pair = get_world_pair(world, player, get_region_pairs(world, player, names, parent_regions, target_regions, path_to), False)
if region_pair and region_pair[2] and not world.is_tile_lw_like(OWTileRegions[region_pair[1]], player):
assert(region_pair[0], f'Exit name missing in OWG pairing from {region_pair[1]} to {region_pair[2]}')
yield(region_pair[0], region_pair[1], region_pair[2], region_pair[3])
def get_swapped_status(world, player, parents, targets):
@@ -254,6 +226,46 @@ def get_swapped_status(world, player, parents, targets):
return parent_swapped, target_swapped
def get_region_pairs(world, player, names, parent_regions, target_regions, path_regions=None):
# this pairs the source region to the proper destination
region_pairs = [None, None]
parent_swapped, target_swapped = get_swapped_status(world, player, parent_regions, target_regions)
if parent_regions[0]:
region_pairs[0] = [names[0], parent_regions[0]]
if parent_swapped == target_swapped:
region_pairs[0].append(target_regions[0])
if path_regions:
region_pairs[0].append(path_regions[0])
else:
region_pairs[0].append(target_regions[1])
if path_regions:
region_pairs[0][3] = path_regions[1]
if parent_regions[1]:
region_pairs[1] = [names[1], parent_regions[1]]
if parent_swapped == target_swapped:
region_pairs[1].append(target_regions[1])
if path_regions:
region_pairs[1].append(path_regions[1])
else:
region_pairs[1].append(target_regions[0])
if path_regions:
region_pairs[1].append(path_regions[0])
return region_pairs
def get_world_pair(world, player, region_pairs, get_light_world):
# this chooses the region pair that is in the right world
if region_pairs[0]:
is_lw = world.is_tile_lw_like(OWTileRegions[region_pairs[0][1]], player)
else:
is_lw = not world.is_tile_lw_like(OWTileRegions[region_pairs[1][1]], player)
if is_lw == get_light_world:
return region_pairs[0]
else:
return region_pairs[1]
def create_owg_connections(world, player):
"""
Add OWG transitions to player's world without logic
@@ -267,7 +279,10 @@ def create_owg_connections(world, player):
# Mirror clip spots.
create_no_logic_connections(player, world, get_mirror_clip_spots(world, player))
create_no_logic_connections(player, world, get_mirror_offset_spots(world, player))
# Mirror offset spots.
for data in get_mirror_offset_spots(world, player):
create_no_logic_connections(player, world, [data[0:3]])
def overworld_glitches_rules(world, player):
@@ -281,7 +296,10 @@ def overworld_glitches_rules(world, player):
# Mirror clip spots.
set_owg_rules(player, world, get_mirror_clip_spots(world, player), lambda state: state.has_Mirror(player))
set_owg_rules(player, world, get_mirror_offset_spots(world, player), lambda state: state.has_Mirror(player) and state.can_boots_clip_lw(player))
# Mirror offset spots.
for data in get_mirror_offset_spots(world, player):
set_owg_rules(player, world, [data[0:3]], lambda state: state.has_Mirror(player) and state.can_boots_clip_lw(player) and state.can_reach(data[3], None, player))
# Regions that require the boots and some other stuff.
# TODO: Revisit below when we can guarantee water walk
@@ -297,12 +315,7 @@ def overworld_glitches_rules(world, player):
add_additional_rule(world.get_entrance('VoO To Dig Game Hook Clip', player), lambda state: state.has('Hookshot', player))
add_additional_rule(world.get_entrance('Tree Line Water Clip', player), lambda state: state.has('Flippers', player))
add_additional_rule(world.get_entrance('Dark Tree Line Water Clip', player), lambda state: state.has('Flippers', player))
if not world.is_tile_swapped(0x33, player):
add_additional_rule(world.get_entrance('South Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
world.get_entrance('Dark South Teleporter Cliff Ledge Drop', player).access_rule = lambda state: False
else:
add_additional_rule(world.get_entrance('Dark South Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
world.get_entrance('South Teleporter Cliff Ledge Drop', player).access_rule = lambda state: False
def add_alternate_rule(entrance, rule):
old_rule = entrance.access_rule
@@ -315,7 +328,7 @@ def add_additional_rule(entrance, rule):
def create_no_logic_connections(player, world, connections):
for entrance, parent_region, target_region, *rule_override in connections:
for entrance, parent_region, target_region, *_ in connections:
parent = world.get_region(parent_region, player)
target = world.get_region(target_region, player)
connection = Entrance(player, entrance, parent)
@@ -325,7 +338,7 @@ def create_no_logic_connections(player, world, connections):
def set_owg_rules(player, world, connections, default_rule):
for entrance, parent_region, target_region, *rule_override in connections:
for entrance, _, _, *rule_override in connections:
connection = world.get_entrance(entrance, player)
rule = rule_override[0] if len(rule_override) > 0 else default_rule
connection.access_rule = rule
@@ -463,7 +476,7 @@ boots_clips = [
(['C Whirlpool To Cliff Clip', 'Dark C Whirlpool To Cliff Clip'], ['C Whirlpool Area', 'Dark C Whirlpool Area'], ['Central Cliffs', 'Dark Central Cliffs']),
(['C Whirlpool Outer To Cliff Clip', 'Dark C Whirlpool Outer To Cliff Clip'], ['C Whirlpool Outer Area', 'Dark C Whirlpool Outer Area'], ['Central Cliffs', 'Dark Central Cliffs']),
(['South Teleporter Cliff Ledge Drop', 'Dark South Teleporter Cliff Ledge Drop'], ['C Whirlpool Area', 'Dark C Whirlpool Area'], ['Dark Central Cliffs', 'Central Cliffs']), # glove/pearl
(['C Whirlpool Portal Bomb Clip', 'Dark C Whirlpool Portal Bomb Clip'], ['C Whirlpool Portal Area', 'Dark C Whirlpool Portal Area'], ['Central Cliffs', 'Dark Central Cliffs']), # bomb TODO: bombbag not considered
(['Statues To Cliff Clip', 'Hype To Cliff Clip'], ['Statues Area', 'Hype Cave Area'], ['Central Cliffs', 'Dark Central Cliffs']),
@@ -495,6 +508,6 @@ mirror_clips = [
]
mirror_offsets = [
(['DM Offset Mirror', 'DDM Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Courtyard', 'Pyramid Area'], ['Pyramid Area', 'Hyrule Castle Courtyard']),
(['DM To HC Ledge Offset Mirror', 'DDM To HC Ledge Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Ledge', None], ['Pyramid Area', None])
(['DM Offset Mirror', 'DDM Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Ledge', 'Pyramid Crack'], ['Pyramid Area', 'Hyrule Castle Courtyard'])
#(['DM To HC Ledge Offset Mirror', 'DDM To HC Ledge Offset Mirror'], ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)'], ['Hyrule Castle Ledge', None], ['Pyramid Area', None])
]

View File

@@ -7,7 +7,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType
from OverworldGlitchRules import create_owg_connections
from Utils import bidict
version_number = '0.2.11.3'
version_number = '0.2.11.4'
# branch indicator is intentionally different across branches
version_branch = ''
@@ -1236,6 +1236,8 @@ mandatory_connections = [# Intra-tile OW Connections
('C Whirlpool Landing', 'C Whirlpool Area'),
('C Whirlpool Rock (Bottom)', 'C Whirlpool Outer Area'), #glove
('C Whirlpool Rock (Top)', 'C Whirlpool Area'), #glove
('C Whirlpool Pegs (Right)', 'C Whirlpool Portal Area'), #hammer
('C Whirlpool Pegs (Left)', 'C Whirlpool Area'), #hammer
('Statues Water Entry', 'Statues Water'), #flippers
('Statues Landing', 'Statues Area'),
('Lake Hylia Water Drop', 'Lake Hylia Water'), #flippers
@@ -1321,6 +1323,8 @@ mandatory_connections = [# Intra-tile OW Connections
('Dark C Whirlpool Landing', 'Dark C Whirlpool Area'),
('Dark C Whirlpool Rock (Bottom)', 'Dark C Whirlpool Outer Area'), #glove
('Dark C Whirlpool Rock (Top)', 'Dark C Whirlpool Area'), #glove
('Dark C Whirlpool Pegs (Right)', 'Dark C Whirlpool Portal Area'), #hammer
('Dark C Whirlpool Pegs (Left)', 'Dark C Whirlpool Area'), #hammer
('Hype Cave Water Entry', 'Hype Cave Water'), #flippers
('Hype Cave Landing', 'Hype Cave Area'),
('Ice Lake Water Drop', 'Ice Lake Water'), #flippers
@@ -1686,21 +1690,25 @@ ow_connections = {
0x33: ([
('C Whirlpool Mirror Spot', 'C Whirlpool Area'),
('C Whirlpool Outer Mirror Spot', 'C Whirlpool Outer Area'),
('South Hyrule Teleporter', 'Dark C Whirlpool Area'),
('South Hyrule Teleporter', 'Dark C Whirlpool Portal Area'),
('C Whirlpool Cliff Ledge Drop', 'C Whirlpool Area'), # OWG
('Dark C Whirlpool Cliff Ledge Drop', 'Dark C Whirlpool Area'), # OWG
('C Whirlpool Outer Cliff Ledge Drop', 'C Whirlpool Outer Area'), # OWG
('Dark C Whirlpool Outer Cliff Ledge Drop', 'Dark C Whirlpool Outer Area'), # OWG
('C Whirlpool Portal Cliff Ledge Drop', 'C Whirlpool Portal Area'), #OWG
('Dark C Whirlpool Portal Cliff Ledge Drop', 'Dark C Whirlpool Portal Area'), #OWG
('Desert C Whirlpool Cliff Ledge Drop', 'C Whirlpool Outer Area'), # OWG
('Mire C Whirlpool Cliff Ledge Drop', 'Dark C Whirlpool Outer Area') # OWG
], [
('Dark C Whirlpool Mirror Spot', 'Dark C Whirlpool Area'),
('Dark C Whirlpool Outer Mirror Spot', 'Dark C Whirlpool Outer Area'),
('South Dark World Teleporter', 'C Whirlpool Area'),
('South Dark World Teleporter', 'C Whirlpool Portal Area'),
('C Whirlpool Cliff Ledge Drop', 'Dark C Whirlpool Area'), # OWG
('Dark C Whirlpool Cliff Ledge Drop', 'C Whirlpool Area'), # OWG
('C Whirlpool Outer Cliff Ledge Drop', 'Dark C Whirlpool Outer Area'), # OWG
('Dark C Whirlpool Outer Cliff Ledge Drop', 'C Whirlpool Outer Area'), # OWG
('C Whirlpool Portal Cliff Ledge Drop', 'Dark C Whirlpool Portal Area'), #OWG
('Dark C Whirlpool Portal Cliff Ledge Drop', 'C Whirlpool Portal Area'), #OWG
('Desert C Whirlpool Cliff Ledge Drop', 'Dark C Whirlpool Outer Area'), # OWG
('Mire C Whirlpool Cliff Ledge Drop', 'C Whirlpool Outer Area') # OWG
]),

View File

@@ -30,15 +30,18 @@ All feedback and dev conversation happens in the #ow-rando channel on the [ALTTP
# Installation from Source
1) Download the source code from the repository directly and put it in a folder of your choosing.
1. Download the source code from the repository directly and put it in a folder of your choosing. Any method of grabbing the source code is fine, but due to some changes on GitHub's site, some of the other alternatives might be better options for some people.
- Use [GitHub Desktop](https://desktop.github.com) to clone this repository to a folder on your computer. Once a repository is established, you can click `Fetch origin` or `Pull` to re-download whenever you want to grab the latest version. This is the best option for a simple one-click solution.
- Download the [source code](https://github.com/codemann8/ALttPDoorRandomizer/archive/refs/heads/OverworldShuffle.zip) from GitHub manually.
2) You must have Python installed (version 3.7 - 3.10 supported), and ensure PATH is included during the installation.
2. You must have [Python](https://www.python.org/downloads) installed (version 3.7 - 3.10 supported), and ensure PATH is included during the installation.
- A common issue with users is that there are multiple instances of Python installed on the same computer. This causes the computer to be confused with which Python instance it uses. Ensure that any older Python installations have been removed.
3) This program requires all python dependencies that are necessary to run OW Randomizer. There are multiple ways to install them:
3. This program requires all python dependencies that are necessary to run OW Randomizer. There are multiple ways to install them:
- Try running ```pip install missingdependency``` or ```python -m pip install missingdependency``` on the command line (replace ```missingdependency``` with the specific package that is missing) to install the dependency.
- The simpler method, run (double-click) ```resources/ci/common/local_install.py``` to install all the missing dependencies as well.
4) Once installed, you should be able to run (double-click) ```Gui.py``` and the OWR program will appear, where you can select your desired settings.
4. Once installed, you should be able to run (double-click) ```Gui.py``` and the OWR program will appear, where you can select your desired settings.
See the following link if you have additional trouble: https://github.com/codemann8/ALttPDoorRandomizer/blob/OverworldShuffle/docs/BUILDING.md

View File

@@ -89,7 +89,7 @@ def create_regions(world, player):
create_lw_region(player, 'Stone Bridge South Area', None, ['Stone Bridge Northbound', 'Hammer Bridge South Mirror Spot', 'Stone Bridge WS', 'Stone Bridge SC']),
create_lw_region(player, 'Stone Bridge Water', None, ['Dark Hobo Mirror Spot', 'Stone Bridge WC', 'Stone Bridge EC'], 'Light World', Terrain.Water),
create_lw_region(player, 'Hobo Bridge', ['Hobo'], ['Hobo EC'], 'Light World', Terrain.Water),
create_lw_region(player, 'Central Cliffs', None, ['Central Bonk Rocks Cliff Ledge Drop', 'Links House Cliff Ledge Drop', 'Stone Bridge Cliff Ledge Drop', 'Lake Hylia Area Cliff Ledge Drop', 'Lake Hylia Island FAWT Ledge Drop', 'Stone Bridge EC Cliff Water Drop', 'Tree Line WC Cliff Water Drop', 'C Whirlpool Outer Cliff Ledge Drop', 'C Whirlpool Cliff Ledge Drop', 'Statues Cliff Ledge Drop']),
create_lw_region(player, 'Central Cliffs', None, ['Central Bonk Rocks Cliff Ledge Drop', 'Links House Cliff Ledge Drop', 'Stone Bridge Cliff Ledge Drop', 'Lake Hylia Area Cliff Ledge Drop', 'Lake Hylia Island FAWT Ledge Drop', 'Stone Bridge EC Cliff Water Drop', 'Tree Line WC Cliff Water Drop', 'C Whirlpool Outer Cliff Ledge Drop', 'C Whirlpool Cliff Ledge Drop', 'C Whirlpool Portal Cliff Ledge Drop', 'Statues Cliff Ledge Drop']),
create_lw_region(player, 'Tree Line Area', None, ['Lake Hylia Fairy', 'Dark Tree Line Mirror Spot', 'Tree Line WN', 'Tree Line NW', 'Tree Line SE']),
create_lw_region(player, 'Tree Line Water', None, ['Tree Line WC', 'Tree Line SC'], 'Light World', Terrain.Water),
create_lw_region(player, 'Eastern Nook Area', None, ['Long Fairy Cave', 'Darkness Nook Mirror Spot', 'East Hyrule Teleporter', 'Eastern Nook NE']),
@@ -105,7 +105,8 @@ def create_regions(world, player):
create_lw_region(player, 'Flute Boy Approach Area', None, ['Flute Boy Bush (South)', 'Cave 45 Inverted Approach', 'Stumpy Approach Mirror Spot', 'Flute Boy Approach NW', 'Flute Boy Approach EC']),
create_lw_region(player, 'Flute Boy Bush Entry', None, ['Flute Boy Bush (North)', 'Stumpy Bush Entry Mirror Spot', 'Flute Boy Approach NC']),
create_lw_region(player, 'Cave 45 Ledge', None, ['Cave 45 Inverted Leave', 'Cave 45 Ledge Drop', 'Cave 45']),
create_lw_region(player, 'C Whirlpool Area', None, ['C Whirlpool Rock (Bottom)', 'C Whirlpool Water Entry', 'Dark C Whirlpool Mirror Spot', 'South Hyrule Teleporter', 'C Whirlpool EN', 'C Whirlpool ES', 'C Whirlpool SC']),
create_lw_region(player, 'C Whirlpool Area', None, ['C Whirlpool Rock (Bottom)', 'C Whirlpool Pegs (Right)', 'C Whirlpool Water Entry', 'Dark C Whirlpool Mirror Spot', 'C Whirlpool EN', 'C Whirlpool ES', 'C Whirlpool SC']),
create_lw_region(player, 'C Whirlpool Portal Area', None, ['C Whirlpool Pegs (Left)', 'South Hyrule Teleporter']),
create_lw_region(player, 'C Whirlpool Water', None, ['C Whirlpool Landing', 'C Whirlpool', 'C Whirlpool EC'], 'Light World', Terrain.Water),
create_lw_region(player, 'C Whirlpool Outer Area', None, ['C Whirlpool Rock (Top)', 'Dark C Whirlpool Outer Mirror Spot', 'C Whirlpool WC', 'C Whirlpool NW']),
create_lw_region(player, 'Statues Area', None, ['Statues Water Entry', 'Light Hype Fairy', 'Hype Cave Mirror Spot', 'Statues NC', 'Statues WN', 'Statues WS', 'Statues SC']),
@@ -145,7 +146,7 @@ def create_regions(world, player):
create_dw_region(player, 'Dark Death Mountain Isolated Ledge', None, ['Turtle Rock Isolated Ledge Entrance', 'Isolated Ledge Mirror Spot'], 'a dark vista'),
create_dw_region(player, 'Dark Death Mountain Floating Island', None, ['Floating Island Drop', 'Hookshot Cave Back Entrance', 'Floating Island Mirror Spot'], 'a dark floating island'),
create_dw_region(player, 'Turtle Rock Area', None, ['Turtle Rock Tail Ledge Drop', 'Turtle Rock', 'TR Pegs Area Mirror Spot', 'Turtle Rock WN']),
create_dw_region(player, 'Turtle Rock Ledge', None, ['Turtle Rock Ledge Drop', 'Turtle Rock Teleporter']),
create_dw_region(player, 'Turtle Rock Ledge', ['Turtle Medallion Pad'], ['Turtle Rock Ledge Drop', 'Turtle Rock Teleporter']),
create_dw_region(player, 'Bumper Cave Area', None, ['Bumper Cave Entrance Rock', 'Mountain Entry Mirror Spot', 'Bumper Cave NW', 'Bumper Cave SE']),
create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave Ledge Drop', 'Bumper Cave (Bottom)', 'Mountain Entry Entrance Mirror Spot']),
create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Entrance Drop', 'Bumper Cave (Top)', 'Mountain Entry Ledge Mirror Spot'], 'a ledge with an item'),
@@ -172,8 +173,8 @@ def create_regions(world, player):
create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop', 'Kakariko Grass Mirror Spot']),
create_dw_region(player, 'Shield Shop Area', None, ['Shield Shop Fence (Outer) Ledge Drop', 'Forgotton Forest Mirror Spot', 'Shield Shop NW', 'Shield Shop NE']),
create_dw_region(player, 'Shield Shop Fence', None, ['Shield Shop Fence (Inner) Ledge Drop', 'Red Shield Shop', 'Forgotton Forest Fence Mirror Spot']),
create_dw_region(player, 'Pyramid Area', ['Pyramid'], ['Pyramid Fairy', 'Pyramid Crack', 'Pyramid Hole', 'HC Ledge Mirror Spot', 'HC Courtyard Mirror Spot', 'HC Area Mirror Spot', 'HC East Entry Mirror Spot', 'Pyramid ES']),
create_dw_region(player, 'Pyramid Crack', ['Pyramid Crack'], None),
create_dw_region(player, 'Pyramid Area', ['Pyramid Crack', 'Pyramid'], ['Pyramid Crack', 'Pyramid Hole', 'HC Ledge Mirror Spot', 'HC Courtyard Mirror Spot', 'HC Area Mirror Spot', 'HC East Entry Mirror Spot', 'Pyramid ES']),
create_dw_region(player, 'Pyramid Crack', None, ['Pyramid Fairy']),
create_dw_region(player, 'Pyramid Exit Ledge', None, ['Pyramid Exit Ledge Drop', 'HC Courtyard Left Mirror Spot', 'Pyramid Entrance']),
create_dw_region(player, 'Pyramid Pass', None, ['Post Aga Inverted Teleporter', 'HC Area South Mirror Spot', 'Pyramid SW', 'Pyramid SE']),
create_dw_region(player, 'Pyramid Water', None, ['Hammerpegs Water Exit', 'Big Bomb Shop Water Exit'], 'Dark World', Terrain.Water),
@@ -199,7 +200,7 @@ def create_regions(world, player):
create_dw_region(player, 'Hammer Bridge South Area', None, ['Hammer Bridge Pegs (South)', 'Stone Bridge South Mirror Spot', 'Hammer Bridge WS', 'Hammer Bridge SC']),
create_dw_region(player, 'Hammer Bridge Water', None, ['Hammer Bridge Pier', 'Hobo Mirror Spot', 'Hammer Bridge EC'], 'Dark World', Terrain.Water),
create_dw_region(player, 'Dark Central Cliffs', None, ['Dark Bonk Rocks Cliff Ledge Drop', 'Bomb Shop Cliff Ledge Drop', 'Hammer Bridge South Cliff Ledge Drop', 'Ice Lake Area Cliff Ledge Drop', 'Ice Palace Island FAWT Ledge Drop',
'Hammer Bridge EC Cliff Water Drop', 'Dark Tree Line WC Cliff Water Drop', 'Dark C Whirlpool Outer Cliff Ledge Drop', 'Dark C Whirlpool Cliff Ledge Drop', 'Hype Cliff Ledge Drop']),
'Hammer Bridge EC Cliff Water Drop', 'Dark Tree Line WC Cliff Water Drop', 'Dark C Whirlpool Outer Cliff Ledge Drop', 'Dark C Whirlpool Cliff Ledge Drop', 'Dark C Whirlpool Portal Cliff Ledge Drop', 'Hype Cliff Ledge Drop']),
create_dw_region(player, 'Dark Tree Line Area', None, ['Dark Lake Hylia Fairy', 'Tree Line Mirror Spot', 'Dark Tree Line WN', 'Dark Tree Line NW', 'Dark Tree Line SE']),
create_dw_region(player, 'Dark Tree Line Water', None, ['Dark Tree Line WC', 'Dark Tree Line SC'], 'Dark World', Terrain.Water),
create_dw_region(player, 'Palace of Darkness Nook Area', None, ['East Dark World Hint', 'East Dark World Teleporter', 'Eastern Nook Mirror Spot', 'Palace of Darkness Nook NE']),
@@ -208,7 +209,8 @@ def create_regions(world, player):
create_dw_region(player, 'Mire Northeast Cliffs', None, ['Mire Cliff Ledge Drop', 'Dark Checkerboard Cliff Ledge Drop', 'Archery Game Cliff Ledge Drop', 'Stumpy Approach Cliff Ledge Drop', 'Mire C Whirlpool Cliff Ledge Drop', 'Swamp Nook Cliff Ledge Drop', 'Swamp Cliff Ledge Drop', 'Bombos Tablet Ledge Mirror Spot']),
create_dw_region(player, 'Stumpy Approach Area', None, ['Stumpy Approach Bush (South)', 'Cave 45 Mirror Spot', 'Stumpy Approach NW', 'Stumpy Approach EC']),
create_dw_region(player, 'Stumpy Approach Bush Entry', None, ['Stumpy Approach Bush (North)', 'Flute Boy Entry Mirror Spot', 'Stumpy Approach NC']),
create_dw_region(player, 'Dark C Whirlpool Area', None, ['Dark C Whirlpool Rock (Bottom)', 'South Dark World Teleporter', 'C Whirlpool Mirror Spot', 'Dark C Whirlpool Water Entry', 'Dark C Whirlpool EN', 'Dark C Whirlpool ES', 'Dark C Whirlpool SC']),
create_dw_region(player, 'Dark C Whirlpool Area', None, ['Dark C Whirlpool Rock (Bottom)', 'Dark C Whirlpool Pegs (Right)', 'C Whirlpool Mirror Spot', 'Dark C Whirlpool Water Entry', 'Dark C Whirlpool EN', 'Dark C Whirlpool ES', 'Dark C Whirlpool SC']),
create_dw_region(player, 'Dark C Whirlpool Portal Area', None, ['Dark C Whirlpool Pegs (Left)', 'South Dark World Teleporter']),
create_dw_region(player, 'Dark C Whirlpool Water', None, ['Dark C Whirlpool Landing', 'Dark C Whirlpool EC'], 'Dark World', Terrain.Water),
create_dw_region(player, 'Dark C Whirlpool Outer Area', None, ['Dark C Whirlpool Rock (Top)', 'C Whirlpool Outer Mirror Spot', 'Dark C Whirlpool WC', 'Dark C Whirlpool NW']),
create_dw_region(player, 'Hype Cave Area', None, ['Hype Cave Water Entry', 'Hype Cave', 'Statues Mirror Spot', 'Hype Cave NC', 'Hype Cave WN', 'Hype Cave WS', 'Hype Cave SC']),
@@ -1198,8 +1200,8 @@ def adjust_locations(world, player):
# player address? it is in the shop table
index += 1
# unreal events:
for l in ['Ganon', 'Agahnim 1', 'Agahnim 2', 'Dark Blacksmith Ruins', 'Middle Aged Man',
'Frog', 'Missing Smith', 'Floodgate', 'Trench 1 Switch', 'Trench 2 Switch', 'Swamp Drain',
for l in ['Ganon', 'Agahnim 1', 'Agahnim 2', 'Frog', 'Missing Smith', 'Dark Blacksmith Ruins', 'Middle Aged Man',
'Floodgate', 'Trench 1 Switch', 'Trench 2 Switch', 'Swamp Drain', 'Turtle Medallion Pad',
'Attic Cracked Floor', 'Suspicious Maiden', 'Revealing Light', 'Big Bomb', 'Pyramid Crack',
'Ice Block Drop', 'Lost Old Man', 'Old Man Drop Off', 'Zelda Pickup', 'Zelda Drop Off', 'Skull Star Tile']:
location = world.get_location_unsafe(l, player)
@@ -1598,6 +1600,7 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'),
'Trench 1 Switch': (None, None, False, None),
'Trench 2 Switch': (None, None, False, None),
'Swamp Drain': (None, None, False, None),
'Turtle Medallion Pad': (None, None, False, None),
'Attic Cracked Floor': (None, None, False, None),
'Suspicious Maiden': (None, None, False, None),
'Revealing Light': (None, None, False, None),

View File

@@ -199,7 +199,7 @@ def global_rules(world, player):
set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Deliver Purple Chest', player)) # Can S&Q with chest
set_rule(world.get_location('Big Bomb', player), lambda state: state.has('Crystal 5', player) and state.has('Crystal 6', player))
set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player))
set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Detonate Big Bomb', player))
set_rule(world.get_entrance('Pyramid Crack', player), lambda state: state.has('Detonate Big Bomb', 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))
@@ -830,6 +830,7 @@ def default_rules(world, player):
set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player))
set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player))
set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player))
set_rule(world.get_location('Turtle Medallion Pad', player), lambda state: state.has_sword(player) and state.has_turtle_rock_medallion(player)) # sword required to cast magic (!)
# Bonk Item Access
if world.shuffle_bonk_drops[player]:
@@ -854,7 +855,7 @@ def default_rules(world, player):
set_rule(world.get_entrance('20 Rupee Cave', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('Skull Woods Final Section', player), lambda state: state.has('Fire Rod', player))
set_rule(world.get_entrance('Hookshot Cave', player), lambda state: state.can_lift_rocks(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 Ledge', 'Region', player)) # sword required to cast magic (!)
set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has('Turtle Opened', player))
set_rule(world.get_entrance('Dark World Hammer Peg Cave', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Bonk Fairy (Dark)', player), lambda state: state.has_Boots(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 (!)
@@ -890,6 +891,8 @@ def default_rules(world, player):
set_rule(world.get_entrance('Desert Ledge Inner Rocks', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('C Whirlpool Rock (Bottom)', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('C Whirlpool Rock (Top)', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('C Whirlpool Pegs (Left)', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('C Whirlpool Pegs (Right)', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Desert Pass Rocks (North)', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('Desert Pass Rocks (South)', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('Skull Woods Bush Rock (West)', player), lambda state: state.can_lift_rocks(player))
@@ -917,6 +920,8 @@ def default_rules(world, player):
set_rule(world.get_entrance('Hammer Bridge Pegs (South)', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Dark C Whirlpool Rock (Bottom)', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('Dark C Whirlpool Rock (Top)', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('Dark C Whirlpool Pegs (Left)', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Dark C Whirlpool Pegs (Right)', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Zora Waterfall Water Drop', player), lambda state: state.has('Flippers', player))
set_rule(world.get_entrance('Zora Waterfall Water Entry', player), lambda state: state.has('Flippers', player))
@@ -1261,11 +1266,11 @@ def ow_inverted_rules(world, player):
if not world.is_tile_swapped(0x33, player):
set_rule(world.get_entrance('C Whirlpool Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('C Whirlpool Outer Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer
set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.can_lift_rocks(player))
else:
set_rule(world.get_entrance('Dark C Whirlpool Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark C Whirlpool Outer Mirror Spot', player), lambda state: state.has_Mirror(player))
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_Pearl(player))
set_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.can_lift_rocks(player))
if not world.is_tile_swapped(0x34, player):
set_rule(world.get_entrance('Statues Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -1327,6 +1332,7 @@ def ow_bunny_rules(world, player):
add_bunny_rule(world.get_location('Zora\'s Ledge', player), player)
add_bunny_rule(world.get_location('Maze Race', player), player)
add_bunny_rule(world.get_location('Flute Spot', player), player)
add_bunny_rule(world.get_location('Turtle Medallion Pad', player), player)
add_bunny_rule(world.get_location('Catfish', player), player)
add_bunny_rule(world.get_entrance('Lost Woods Hideout Drop', player), player)
@@ -1345,7 +1351,6 @@ def ow_bunny_rules(world, player):
add_bunny_rule(world.get_entrance('Skull Woods Second Section Hole', player), player) # bunny cannot lift bush
add_bunny_rule(world.get_entrance('Skull Woods Final Section', player), player) # bunny cannot use fire rod
add_bunny_rule(world.get_entrance('Hookshot Cave', player), player)
add_bunny_rule(world.get_entrance('Turtle Rock', player), player)
add_bunny_rule(world.get_entrance('Thieves Town', player), player) # bunny cannot pull
add_bunny_rule(world.get_entrance('Brewery', player), player) # bomb required
add_bunny_rule(world.get_entrance('Palace of Darkness', player), player) # kiki needs pearl
@@ -1397,6 +1402,8 @@ def ow_bunny_rules(world, player):
add_bunny_rule(world.get_entrance('Flute Boy Bush (South)', player), player)
add_bunny_rule(world.get_entrance('C Whirlpool Rock (Bottom)', player), player)
add_bunny_rule(world.get_entrance('C Whirlpool Rock (Top)', player), player)
add_bunny_rule(world.get_entrance('C Whirlpool Pegs (Left)', player), player)
add_bunny_rule(world.get_entrance('C Whirlpool Pegs (Right)', player), player)
add_bunny_rule(world.get_entrance('Desert Pass Rocks (North)', player), player)
add_bunny_rule(world.get_entrance('Desert Pass Rocks (South)', player), player)
add_bunny_rule(world.get_entrance('Skull Woods Bush Rock (West)', player), player)
@@ -1435,6 +1442,8 @@ def ow_bunny_rules(world, player):
add_bunny_rule(world.get_entrance('Stumpy Approach Bush (South)', player), player)
add_bunny_rule(world.get_entrance('Dark C Whirlpool Rock (Bottom)', player), player)
add_bunny_rule(world.get_entrance('Dark C Whirlpool Rock (Top)', player), player)
add_bunny_rule(world.get_entrance('Dark C Whirlpool Pegs (Left)', player), player)
add_bunny_rule(world.get_entrance('Dark C Whirlpool Pegs (Right)', player), player)
add_bunny_rule(world.get_entrance('Zora Waterfall Water Drop', player), player)
add_bunny_rule(world.get_entrance('Zora Waterfall Water Entry', player), player)
@@ -1553,24 +1562,12 @@ def forbid_bomb_jump_requirements(world, player):
add_rule(world.get_location(location, player), lambda state: state.has('Hookshot', player))
set_rule(world.get_entrance('Paradox Cave Bomb Jump', player), lambda state: False)
# Light cones in standard depend on which world we actually are in, not which one the location would normally be
# We add Lamp requirements only to those locations which lie in the dark world (or everything if open
DW_Entrances = ['Bumper Cave (Bottom)', 'Superbunny Cave (Top)', 'Superbunny Cave (Bottom)', 'Hookshot Cave', 'Bumper Cave (Top)', 'Hookshot Cave Back Entrance', 'Dark Death Mountain Ledge (East)',
'Turtle Rock Isolated Ledge Entrance', 'Thieves Town', 'Skull Woods Final Section', 'Ice Palace', 'Misery Mire', 'Palace of Darkness', 'Swamp Palace', 'Turtle Rock', 'Dark Death Mountain Ledge (West)']
def check_is_dark_world(region):
for entrance in region.entrances:
if entrance.name in DW_Entrances:
return True
return False
def add_conditional_lamps(world, player):
def add_conditional_lamp(spot, region, spottype='Location'):
def add_conditional_lamp(spot, spottype='Location'):
if spottype == 'Location':
spot = world.get_location(spot, player)
else:
spot = world.get_entrance(spot, player)
if (not world.dark_world_light_cone and check_is_dark_world(world.get_region(region, player))) or (not world.light_world_light_cone and not check_is_dark_world(world.get_region(region, player))):
add_lamp_requirement(spot, player)
dark_rooms = {
@@ -1627,13 +1624,13 @@ def add_conditional_lamps(world, player):
if is_dark:
dark_debug_set.add(region)
for ent in info['entrances']:
add_conditional_lamp(ent, region, 'Entrance')
add_conditional_lamp(ent, 'Entrance')
r = world.get_region(region, player)
for loc in r.locations:
add_conditional_lamp(loc, region, 'Location')
add_conditional_lamp(loc, 'Location')
logging.getLogger('').debug('Non Dark Regions: ' + ', '.join(set(dark_rooms.keys()).difference(dark_debug_set)))
add_conditional_lamp('Old Man House Front to Back', 'Old Man House', 'Entrance')
add_conditional_lamp('Old Man House Front to Back', 'Entrance')
def open_rules(world, player):
# softlock protection as you can reach the sewers small key door with a guard drop key
@@ -1656,9 +1653,9 @@ def swordless_rules(world, player):
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has('Hammer', player) or state.has_beaten_aga(player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle
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('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword not required to use medallion for opening in swordless (!)
set_rule(world.get_location('Turtle Medallion Pad', player), lambda state: state.has_turtle_rock_medallion(player)) # sword not required to use medallion for opening in swordless (!)
add_bunny_rule(world.get_entrance('Misery Mire', player), player)
add_bunny_rule(world.get_entrance('Turtle Rock', player), player)
add_bunny_rule(world.get_location('Turtle Medallion Pad', player), player)
std_kill_rooms = {
'Hyrule Dungeon Armory Main': ['Hyrule Dungeon Armory S', 'Hyrule Dungeon Armory ES'], # One green guard