Initial Tile Shuffle Implementation

This commit is contained in:
codemann8
2021-06-23 03:09:27 -05:00
parent 3e9a72e5b7
commit 6cd6dca6a3
10 changed files with 1781 additions and 987 deletions

View File

@@ -3,7 +3,7 @@ import copy
import json
import logging
from collections import OrderedDict, Counter, deque, defaultdict
from enum import Enum, unique
from enum import Enum, IntEnum, unique
try:
from fast_enum import FastEnum
@@ -73,6 +73,7 @@ class World(object):
self.dynamic_locations = []
self.spoiler = Spoiler(self)
self.lamps_needed_for_dark_rooms = 1
self.owswaps = {}
self.owedges = []
self._owedge_cache = {}
self.doors = []
@@ -142,6 +143,7 @@ class World(object):
set_player_attr('mixed_travel', 'prevent')
set_player_attr('standardize_palettes', 'standardize')
set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False})
set_player_attr('owswaps', [[],[],[]])
def get_name_string_for_object(self, obj):
return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'
@@ -1503,7 +1505,7 @@ class Door(object):
@unique
class WorldType(Enum):
class WorldType(IntEnum):
Light = 0
Dark = 1
Special = 2

View File

@@ -211,7 +211,7 @@ def vanilla_key_logic(world, player):
analyze_dungeon(key_layout, world, player)
world.key_logic[player][builder.name] = key_layout.key_logic
log_key_logic(builder.name, key_layout.key_logic)
if world.shuffle[player] == 'vanilla' and world.owShuffle[player] == 'vanilla' and world.accessibility[player] == 'items' and not world.retro[player] and not world.keydropshuffle[player]:
if world.shuffle[player] == 'vanilla' and world.owShuffle[player] == 'vanilla' and world.owSwap[player] == 'vanilla' and world.accessibility[player] == 'items' and not world.retro[player] and not world.keydropshuffle[player]:
validate_vanilla_key_logic(world, player)

View File

@@ -245,7 +245,7 @@ def main(args, seed=None, fish=None):
customize_shops(world, player)
balance_money_progression(world)
if world.owShuffle[1] != 'vanilla':
if world.owShuffle[1] != 'vanilla' or world.owSwap[1] != 'vanilla':
outfilebase = f'OR_{args.outputname if args.outputname else world.seed}'
else:
outfilebase = f'DR_{args.outputname if args.outputname else world.seed}'

View File

@@ -583,6 +583,10 @@ OWEdgeGroups = {
['Bomber Corner NE']
]
),
(Op, DW, Hz, Ld, NP, 1): (
[ ],
[ ]
),
(Op, DW, Hz, Ld, PL, 2): (
[
['Dark Fortune EN', 'Dark Fortune ES'],
@@ -657,6 +661,490 @@ OWEdgeGroups = {
)
}
OWTileGroups = {
("Woods", "Regular"): (
[
0x00, 0x40, 0x80
],
[
'Master Sword Meadow',
'Lost Woods West Area',
'Lost Woods East Area'
],
[
'Skull Woods Forest',
'Skull Woods Portal Entry',
'Skull Woods Forest (West)',
'Skull Woods Forgotten Path (Southwest)',
'Skull Woods Forgotten Path (Northeast)'
]
),
("Lumberjack", "Regular"): (
[
0x02, 0x42
],
[
'Lumberjack Area'
],
[
'Dark Lumberjack Area'
]
),
("West Mountain", "Regular"): (
[
0x03, 0x43
],
[
'West Death Mountain (Top)',
'Spectacle Rock Ledge',
'West Death Mountain (Bottom)'
],
[
'West Dark Death Mountain (Top)',
'GT Approach',
'West Dark Death Mountain (Bottom)'
]
),
("East Mountain", "Regular"): (
[
0x05, 0x45
],
[
'Death Mountain Floating Island',
'East Death Mountain (Top West)',
'East Death Mountain (Top East)',
'Spiral Cave Ledge',
'Mimic Cave Ledge',
'Fairy Ascension Ledge',
'Fairy Ascension Plateau',
'East Death Mountain (Bottom Left)',
'East Death Mountain (Bottom)'
],
[
'East Dark Death Mountain (Top)',
'East Dark Death Mountain (Bottom)',
'East Dark Death Mountain (Bottom Left)'
]
),
("East Mountain", "Entrance"): (
[
0x07, 0x47
],
[
'Death Mountain TR Pegs',
'Death Mountain TR Pegs Ledge'
],
[
'Turtle Rock Area',
'Turtle Rock Ledge'
]
),
("Lake", "Regular"): (
[
0x0f, 0x35, 0x4f, 0x75, 0x81
],
[
'Zora Waterfall Area',
'Zora Waterfall Water',
'Waterfall of Wishing Cave',
'Zoras Domain',
'Lake Hylia Area',
'Lake Hylia South Shore',
'Lake Hylia Northeast Bank',
'Lake Hylia Central Island',
'Lake Hylia Island',
'Lake Hylia Water'
],
[
'Catfish Area',
'Ice Lake Area',
'Ice Lake Northeast Bank',
'Ice Lake Ledge (West)',
'Ice Lake Ledge (East)',
'Ice Lake Water',
'Ice Lake Moat',
'Ice Palace Area'
]
),
("West Mountain", "Entrance"): (
[
0x0a, 0x4a
],
[
'Mountain Entry Area',
'Mountain Entry Entrance',
'Mountain Entry Ledge'
],
[
'Bumper Cave Area',
'Bumper Cave Entrance',
'Bumper Cave Ledge'
]
),
("Woods Pass", "Regular"): (
[
0x10, 0x50
],
[
'Lost Woods Pass West Area',
'Lost Woods Pass East Top Area',
'Lost Woods Pass East Bottom Area'
],
[
'Skull Woods Pass West Area',
'Skull Woods Pass East Top Area',
'Skull Woods Pass East Bottom Area'
]
),
("Fortune", "Regular"): (
[
0x11, 0x51
],
[
'Kakariko Fortune Area'
],
[
'Dark Fortune Area'
]
),
("Whirlpools", "Regular"): (
[
0x12, 0x15, 0x33, 0x3f, 0x52, 0x55, 0x73, 0x7f
],
[
'Kakariko Pond Area',
'River Bend Area',
'River Bend East Bank',
'River Bend Water',
'C Whirlpool Area',
'C Whirlpool Water',
'C Whirlpool Outer Area',
'Octoballoon Area',
'Octoballoon Water',
'Octoballoon Water Ledge'
],
[
'Outcast Pond Area',
'Qirn Jump Area',
'Qirn Jump East Bank',
'Qirn Jump Water',
'Dark C Whirlpool Area',
'Dark C Whirlpool Water',
'Dark C Whirlpool Outer Area',
'Bomber Corner Area',
'Bomber Corner Water',
'Bomber Corner Water Ledge'
]
),
("Castle", "Entrance"): (
[
0x13, 0x14, 0x53, 0x54
],
[
'Sanctuary Area',
'Bonk Rock Ledge',
'Graveyard Area',
'Graveyard Ledge',
'Kings Grave Area'
],
[
'Dark Chapel Area',
'Dark Graveyard Area'
]
),
("Castle", "Regular"): (
[
0x1a, 0x1b, 0x5a, 0x5b
],
[
'Forgotten Forest Area',
'Hyrule Castle Area',
'Hyrule Castle Southwest',
'Hyrule Castle Courtyard',
'Hyrule Castle Courtyard Northeast',
'Hyrule Castle Ledge',
'Hyrule Castle East Entry'
],
[
'Shield Shop Area',
'Shield Shop Fence',
'Pyramid Area',
'Pyramid Exit Ledge',
'Pyramid Pass'
]
),
("Witch", "Regular"): (
[
0x16, 0x56
],
[
'Potion Shop Area',
'Potion Shop Northeast',
'Potion Shop Water'
],
[
'Dark Witch Area',
'Dark Witch Northeast',
'Dark Witch Water'
]
),
("Water Approach", "Regular"): (
[
0x17, 0x57
],
[
'Zora Approach Area',
'Zora Approach Ledge',
'Zora Approach Water'
],
[
'Catfish Approach Area',
'Catfish Approach Ledge',
'Catfish Approach Water'
]
),
("Village", "Regular"): (
[
0x18, 0x58
],
[
'Kakariko Area',
'Kakariko Southwest',
'Kakariko Grass Yard'
],
[
'Village of Outcasts Area',
'Dark Grassy Lawn'
]
),
("Wooden Bridge", "Regular"): (
[
0x1d, 0x5d
],
[
'Wooden Bridge Area',
'Wooden Bridge Northeast',
'Wooden Bridge Water'
],
[
'Broken Bridge Area',
'Broken Bridge Northeast',
'Broken Bridge West',
'Broken Bridge Water'
]
),
("Eastern", "Regular"): (
[
0x1e, 0x5e
],
[
'Eastern Palace Area'
],
[
'Palace of Darkness Area'
]
),
# ("Blacksmith", "Regular"): (
# [
# 0x22, 0x62
# ],
# [
# 'Blacksmith Area',
# 'Bat Cave Ledge'
# ],
# [
# 'Hammer Pegs Area',
# 'Hammer Pegs Entry'
# ]
# ),
("Dunes", "Regular"): (
[
0x25, 0x65
],
[
'Sand Dunes Area'
],
[
'Dark Dunes Area'
]
),
("Game", "Regular"): (
[
0x28, 0x29, 0x68, 0x69
],
[
'Maze Race Area',
'Maze Race Ledge',
'Maze Race Prize',
'Kakariko Suburb Area'
],
[
'Dig Game Area',
'Dig Game Ledge',
'Frog Area',
'Frog Prison',
'Archery Game Area'
]
),
("Grove", "Regular"): (
[
0x2a, 0x6a
],
[
'Flute Boy Area',
'Flute Boy Pass'
],
[
'Stumpy Area',
'Stumpy Pass'
]
),
("Central Bonk Rocks", "Regular"): (
[
0x2b, 0x6b
],
[
'Central Bonk Rocks Area'
],
[
'Dark Bonk Rocks Area'
]
),
# ("Links", "Regular"): (
# [
# 0x2c, 0x6c
# ],
# [
# 'Links House Area'
# ],
# [
# 'Big Bomb Shop Area'
# ]
# ),
("Bridge", "Regular"): (
[
0x2d, 0x6d, 0x80
],
[
'Stone Bridge Area',
'Stone Bridge Water',
'Hobo Bridge'
],
[
'Hammer Bridge North Area',
'Hammer Bridge South Area',
'Hammer Bridge Water'
]
),
("Tree Line", "Regular"): (
[
0x2e, 0x6e
],
[
'Tree Line Area',
'Tree Line Water'
],
[
'Dark Tree Line Area',
'Dark Tree Line Water'
]
),
("Nook", "Regular"): (
[
0x2f, 0x6f
],
[
'Eastern Nook Area'
],
[
'Palace of Darkness Nook Area'
]
),
("Desert", "Regular"): (
[
0x30, 0x3a, 0x70, 0x7a
],
[
'Desert Area',
'Desert Ledge',
'Desert Palace Entrance (North) Spot',
'Desert Checkerboard Ledge',
'Desert Palace Stairs',
'Desert Palace Mouth',
'Desert Palace Teleporter Ledge',
'Bombos Tablet Ledge',
'Desert Pass Area',
'Desert Pass Southeast',
'Desert Pass Ledge'
],
[
'Misery Mire Area',
'Misery Mire Teleporter Ledge',
'Swamp Nook Area'
]
),
("Grove Approach", "Regular"): (
[
0x32, 0x72
],
[
'Flute Boy Approach Area',
'Flute Boy Bush Entry',
'Cave 45 Ledge'
],
[
'Stumpy Approach Area',
'Stumpy Approach Bush Entry'
]
),
("Hype", "Regular"): (
[
0x34, 0x74
],
[
'Statues Area',
'Statues Water'
],
[
'Hype Cave Area',
'Hype Cave Water'
]
),
("Shopping Mall", "Regular"): (
[
0x37, 0x77
],
[
'Ice Cave Area'
],
[
'Shopping Mall Area'
]
),
("Swamp", "Regular"): (
[
0x3b, 0x7b
],
[
'Dam Area'
],
[
'Swamp Area'
]
),
("South Pass", "Regular"): (
[
0x3c, 0x7c
],
[
'South Pass Area'
],
[
'Dark South Pass Area'
]
)
}
parallel_links = bidict({'Lost Woods SW': 'Skull Woods SW',
'Lost Woods SC': 'Skull Woods SC',
'Lost Woods SE': 'Skull Woods SE',

View File

@@ -1,6 +1,6 @@
import random, logging
from BaseClasses import OWEdge, WorldType, Direction, Terrain
from OWEdges import OWEdgeGroups, parallel_links, IsParallel
import random, logging, copy
from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain
from OWEdges import OWTileGroups, OWEdgeGroups, parallel_links, IsParallel
__version__ = '0.1.4.3-u'
@@ -11,21 +11,154 @@ def link_overworld(world, player):
for exitname, destname in temporary_mandatory_connections:
connect_two_way(world, exitname, destname, player)
if world.mode[player] != 'inverted':
for exitname, regionname in open_connections:
# tile shuffle
trimmed_groups = copy.deepcopy(OWEdgeGroups)
if world.owSwap[player] != 'vanilla':
tile_groups = {}
for (name, groupType) in OWTileGroups.keys():
if world.mode[player] != 'standard' or name not in ['Castle', 'Links']:
if world.shuffle[player] in ['vanilla', 'simple', 'dungeonssimple']:
tile_groups[(name,)] = ([], [], [])
else:
tile_groups[(name, groupType)] = ([], [], [])
for (name, groupType) in OWTileGroups.keys():
if world.mode[player] != 'standard' or name not in ['Castle', 'Links']:
(owids, lw_regions, dw_regions) = OWTileGroups[(name, groupType,)]
if world.shuffle[player] in ['vanilla', 'simple', 'dungeonssimple']:
(exist_owids, exist_lw_regions, exist_dw_regions) = tile_groups[(name,)]
exist_owids.extend(owids)
exist_lw_regions.extend(lw_regions)
exist_dw_regions.extend(dw_regions)
tile_groups[(name,)] = (exist_owids, exist_lw_regions, exist_dw_regions)
else:
(exist_owids, exist_lw_regions, exist_dw_regions) = tile_groups[(name, groupType)]
exist_owids.extend(owids)
exist_lw_regions.extend(lw_regions)
exist_dw_regions.extend(dw_regions)
tile_groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions)
#tile shuffle happens here, the groups that remain in the list are the tiles that get swapped
removed = list()
for group in tile_groups.keys():
if random.randint(0, 1):
removed.append(group)
for group in removed:
tile_groups.pop(group, None)
#save shuffled tiles to world object
for group in tile_groups.keys():
(owids, lw_regions, dw_regions) = tile_groups[group]
(exist_owids, exist_lw_regions, exist_dw_regions) = world.owswaps[player]
exist_owids.extend(owids)
exist_lw_regions.extend(lw_regions)
exist_dw_regions.extend(dw_regions)
world.owswaps[player] = [exist_owids, exist_lw_regions, exist_dw_regions]
#dont perform moon pearl check unless both hobo and ped are swapped
if 0x80 in world.owswaps[player][0]:
world.owswaps[player][0].remove(0x80)
#replace LW edges with DW
ignore_list = list() #TODO: Remove ignore_list when special OW areas are included in pool
for edgeset in temporary_mandatory_connections:
for edge in edgeset:
ignore_list.append(edge)
swapped_edges = list()
def getSwappedEdges(world, lst, player):
for regionname in lst:
region = world.get_region(regionname, player)
for exit in region.exits:
if exit.spot_type == 'OWEdge' and exit.name not in ignore_list:
swapped_edges.append(exit.name)
getSwappedEdges(world, world.owswaps[player][1], player)
getSwappedEdges(world, world.owswaps[player][2], player)
def performSwap(groups, swaps):
try:
for group in groups.keys():
(mode, wrld, dir, terrain, parallel, count) = group
for p in range(0, len(groups[group])):
edgepool = groups[group][p]
for s in range(0, len(edgepool)):
if s <= len(edgepool):
for e in range(0, len(edgepool[s])):
if len(edgepool) > 0 and edgepool[s][e] in swaps:
if parallel == IsParallel.Yes:
if wrld == WorldType.Light and edgepool[s][e] in parallel_links:
logging.getLogger('').debug('%s was moved', edgepool[s][e])
swaps.remove(edgepool[s][e])
groups[group][p][s][e] = parallel_links[edgepool[s][e]]
elif wrld == WorldType.Dark and edgepool[s][e] in parallel_links.inverse:
logging.getLogger('').debug('%s was moved', edgepool[s][e])
swaps.remove(edgepool[s][e])
groups[group][p][s][e] = parallel_links.inverse[edgepool[s][e]][0]
else:
for edge in edgepool[s]:
logging.getLogger('').debug('%s was moved', edge)
swaps.remove(edge)
groups[(mode, WorldType((int(wrld) + 1) % 2), dir, terrain, parallel, count)][p].append(edgepool[s])
groups[group][p].remove(edgepool[s])
except IndexError:
#TODO: Figure out a way to handle index changes on the fly when removing items
logging.getLogger('').warning('OW Tile Swap encountered minor IndexError... retrying')
tries = 5
while tries > 0:
performSwap(trimmed_groups, swapped_edges)
if len(swapped_edges) == 0:
tries = 0
continue
tries -= 1
assert len(swapped_edges) == 0
#move swapped regions to other world
if world.owSwap[player] == 'mixed':
for name in world.owswaps[player][1]:
region = world.get_region(name, player)
region.type = RegionType.DarkWorld
for name in world.owswaps[player][2]:
region = world.get_region(name, player)
region.type = RegionType.LightWorld
#make new connections
for owid in flute_connections.keys():
(spot, dest) = flute_connections[owid]
if (world.mode[player] == 'inverted') == (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
connect_simple(world, spot, dest[0], player)
else:
connect_simple(world, spot, dest[1], player)
for owid in ow_connections.keys():
if (world.mode[player] == 'inverted') == (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
for (exitname, regionname) in ow_connections[owid][0]:
connect_simple(world, exitname, regionname, player)
else:
for exitname, regionname in inverted_connections:
for (exitname, regionname) in ow_connections[owid][1]:
connect_simple(world, exitname, regionname, player)
connected_edges = []
connect_custom(world, connected_edges, player)
# if we do not shuffle, set default connections
# layout shuffle
if world.owShuffle[player] == 'vanilla':
for exitname, destname in default_connections:
connect_two_way(world, exitname, destname, player)
#for exitname, destname in default_connections:
# connect_two_way(world, exitname, destname, player)
for grouping in (trimmed_groups,):
groups = list(trimmed_groups.values())
for (forward_edge_sets, back_edge_sets) in groups:
assert len(forward_edge_sets) == len(back_edge_sets)
for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets):
assert len(forward_set) == len(back_set)
for (forward_edge, back_edge) in zip(forward_set, back_set):
connect_two_way(world, forward_edge, back_edge, player)
connected_edges.append(forward_edge)
connected_edges.append(back_edge)
assert len(connected_edges) == len(default_connections) * 2, connected_edges
else:
if world.owKeepSimilar[player] and world.owShuffle[player] == 'parallel':
for exitname, destname in parallelsimilar_connections:
@@ -39,7 +172,7 @@ def link_overworld(world, player):
connected_edges.append(exitname)
connected_edges.append(destname)
trimmed_groups = remove_reserved(world, OWEdgeGroups, connected_edges, player)
trimmed_groups = remove_reserved(world, trimmed_groups, connected_edges, player)
groups = reorganize_groups(world, trimmed_groups, player)
@@ -54,10 +187,13 @@ def link_overworld(world, player):
connect_two_way(world, forward_edge, back_edge, player)
connected_edges.append(forward_edge)
connected_edges.append(back_edge)
if world.owShuffle[player] == 'parallel' and forward_edge in parallel_links.keys():
connect_two_way(world, parallel_links[forward_edge], parallel_links[back_edge], player)
connected_edges.append(parallel_links[forward_edge])
connected_edges.append(parallel_links[back_edge])
if world.owShuffle[player] == 'parallel':
if forward_edge in parallel_links.keys() or forward_edge in parallel_links.inverse.keys():
parallel_forward_edge = parallel_links[forward_edge] if forward_edge in parallel_links.keys() else parallel_links.inverse[forward_edge][0]
parallel_back_edge = parallel_links[back_edge] if back_edge in parallel_links.keys() else parallel_links.inverse[back_edge][0]
connect_two_way(world, parallel_forward_edge, parallel_back_edge, player)
connected_edges.append(parallel_forward_edge)
connected_edges.append(parallel_back_edge)
assert len(connected_edges) == len(default_connections) * 2, connected_edges
@@ -93,7 +229,7 @@ def connect_two_way(world, edgename1, edgename2, player):
x.dest = y
y.dest = x
if world.owShuffle[player] != 'vanilla':
if world.owShuffle[player] != 'vanilla' or world.owSwap[player] != 'vanilla':
world.spoiler.set_overworld(edgename2, edgename1, 'both', player)
def remove_reserved(world, groupedlist, connected_edges, player):
@@ -113,6 +249,9 @@ def remove_reserved(world, groupedlist, connected_edges, player):
for edge in parallel_links:
forward_edges = list(list(filter((parallel_links[edge]).__ne__, i)) for i in forward_edges)
back_edges = list(list(filter((parallel_links[edge]).__ne__, i)) for i in back_edges)
for edge in parallel_links.inverse:
forward_edges = list(list(filter((parallel_links.inverse[edge][0]).__ne__, i)) for i in forward_edges)
back_edges = list(list(filter((parallel_links.inverse[edge][0]).__ne__, i)) for i in back_edges)
forward_edges = list(filter(([]).__ne__, forward_edges))
back_edges = list(filter(([]).__ne__, back_edges))
@@ -133,8 +272,7 @@ def reorganize_groups(world, groups, player):
if world.owKeepSimilar[player]:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,_,F)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
@@ -152,8 +290,7 @@ def reorganize_groups(world, groups, player):
return list(new_grouping.values())
else:
#tuple goes to (_,B,C,D,_,F)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
@@ -172,8 +309,7 @@ def reorganize_groups(world, groups, player):
else:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,_,_)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
@@ -194,8 +330,7 @@ def reorganize_groups(world, groups, player):
return list(new_grouping.values())
else:
#tuple goes to (_,B,C,D,_,_)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
@@ -219,13 +354,11 @@ def reorganize_groups(world, groups, player):
if world.owKeepSimilar[player]:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,E,F)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
return list(grouping.values())
else:
#tuple goes to (_,B,C,D,E,F)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
@@ -244,8 +377,7 @@ def reorganize_groups(world, groups, player):
else:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,E,_)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
@@ -266,8 +398,7 @@ def reorganize_groups(world, groups, player):
return list(new_grouping.values())
else:
#tuple goes to (_,B,C,D,E,_)
for grouping in (groups, None):
if grouping is not None: #TODO: Figure out why ^ has to be a tuple for this to work
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
@@ -535,25 +666,52 @@ mandatory_connections = [('Flute Away', 'Flute Sky'),
('Dark Tree Line WC Cliff Water Drop', 'Dark Tree Line Water') #fake flipper
]
open_connections = [('Flute Spot 1', 'West Death Mountain (Bottom)'),
('Flute Spot 2', 'Potion Shop Area'),
('Flute Spot 3', 'Kakariko Area'),
('Flute Spot 4', 'Links House Area'),
('Flute Spot 5', 'Eastern Nook Area'),
('Flute Spot 6', 'Desert Palace Teleporter Ledge'),
('Flute Spot 7', 'Dam Area'),
('Flute Spot 8', 'Octoballoon Area'),
flute_connections = {0x03: ('Flute Spot 1', ['West Death Mountain (Bottom)', 'West Dark Death Mountain (Bottom)']),
0x16: ('Flute Spot 2', ['Potion Shop Area', 'Dark Witch Area']),
0x18: ('Flute Spot 3', ['Kakariko Area', 'Village of Outcasts Area']),
0x2c: ('Flute Spot 4', ['Links House Area', 'Big Bomb Shop Area']),
0x2f: ('Flute Spot 5', ['Eastern Nook Area', 'Palace of Darkness Nook Area']),
0x30: ('Flute Spot 6', ['Desert Palace Teleporter Ledge', 'Misery Mire Teleporter Ledge']),
0x33: ('Flute Spot 7', ['Dam Area', 'Swamp Area']),
0x3f: ('Flute Spot 8', ['Octoballoon Area', 'Bomber Corner Area'])
}
# Mirror Connections
ow_connections = {
0x00: ([
('Lost Woods East Mirror Spot', 'Lost Woods East Area'),
('Lost Woods Entry Mirror Spot', 'Lost Woods West Area'),
('Lost Woods Pedestal Mirror Spot', 'Lost Woods West Area'),
('Lost Woods Southwest Mirror Spot', 'Lost Woods West Area'),
('Lost Woods East (Forgotten) Mirror Spot', 'Lost Woods East Area'),
('Lost Woods West (Forgotten) Mirror Spot', 'Lost Woods West Area'),
('Lumberjack Mirror Spot', 'Lumberjack Area'),
('Lost Woods West (Forgotten) Mirror Spot', 'Lost Woods West Area')
], [
('Skull Woods Back Mirror Spot', 'Skull Woods Forest (West)'),
('Skull Woods Forgotten (West) Mirror Spot', 'Skull Woods Forgotten Path (Southwest)'),
('Skull Woods Forgotten (East) Mirror Spot', 'Skull Woods Forgotten Path (Northeast)'),
('Skull Woods Portal Entry Mirror Spot', 'Skull Woods Portal Entry'),
('Skull Woods Forgotten (Middle) Mirror Spot', 'Skull Woods Forgotten Path (Northeast)'),
('Skull Woods Front Mirror Spot', 'Skull Woods Forest')
]),
0x02: ([
('Lumberjack Mirror Spot', 'Lumberjack Area')
], [
('Dark Lumberjack Mirror Spot', 'Dark Lumberjack Area')
]),
0x03: ([
('Spectacle Rock Mirror Spot', 'Spectacle Rock Ledge'),
('West Death Mountain (Top) Mirror Spot', 'West Death Mountain (Top)'),
('West Death Mountain Teleporter', 'West Dark Death Mountain (Bottom)')
], [
('Spectacle Rock Leave', 'West Death Mountain (Top)'),
('Spectacle Rock Approach', 'Spectacle Rock Ledge'),
('Dark Death Mountain Ladder (North)', 'West Dark Death Mountain (Bottom)'),
('Dark Death Mountain Ladder (South)', 'West Dark Death Mountain (Top)'),
('West Dark Death Mountain (Top) Mirror Spot', 'West Dark Death Mountain (Top)'),
('Bubble Boy Mirror Spot', 'West Dark Death Mountain (Bottom)'),
('West Dark Death Mountain (Bottom) Mirror Spot', 'West Dark Death Mountain (Bottom)'),
('Dark Death Mountain Teleporter (West)', 'West Death Mountain (Bottom)')
]),
0x05: ([
('East Death Mountain (Top West) Mirror Spot', 'East Death Mountain (Top West)'),
('East Death Mountain (Top East) Mirror Spot', 'East Death Mountain (Top East)'),
('Spiral Cave Mirror Spot', 'Spiral Cave Ledge'),
@@ -562,136 +720,12 @@ open_connections = [('Flute Spot 1', 'West Death Mountain (Bottom)'),
('Fairy Ascension Mirror Spot', 'Fairy Ascension Plateau'),
('Death Mountain Bridge Mirror Spot', 'East Death Mountain (Bottom Left)'),
('Floating Island Mirror Spot', 'Death Mountain Floating Island'),
('TR Pegs Area Mirror Spot', 'Death Mountain TR Pegs'),
('Mountain Entry Mirror Spot', 'Mountain Entry Area'),
('Mountain Entry Entrance Mirror Spot', 'Mountain Entry Entrance'),
('Mountain Entry Ledge Mirror Spot', 'Mountain Entry Ledge'),
('Zora Waterfall Mirror Spot', 'Zora Waterfall Area'),
('Lost Woods Pass West Mirror Spot', 'Lost Woods Pass West Area'),
('Lost Woods Pass East Top Mirror Spot', 'Lost Woods Pass East Top Area'),
('Lost Woods Pass East Bottom Mirror Spot', 'Lost Woods Pass East Bottom Area'),
('Kakariko Fortune Mirror Spot', 'Kakariko Fortune Area'),
('Kakariko Pond Mirror Spot', 'Kakariko Pond Area'),
('Forgotton Forest Mirror Spot', 'Forgotten Forest Area'),
('Forgotton Forest Fence Mirror Spot', 'Forgotten Forest Area'),
('Bonk Rock Ledge Mirror Spot', 'Bonk Rock Ledge'),
('Graveyard Ledge Mirror Spot', 'Graveyard Ledge'),
('Kings Grave Mirror Spot', 'Kings Grave Area'),
('River Bend Mirror Spot', 'River Bend Area'),
('River Bend East Mirror Spot', 'River Bend East Bank'),
('Potion Shop Mirror Spot', 'Potion Shop Area'),
('Potion Shop Northeast Mirror Spot', 'Potion Shop Northeast'),
('Zora Approach Mirror Spot', 'Zora Approach Area'),
('Zora Approach Ledge Mirror Spot', 'Zora Approach Ledge'),
('Kakariko Mirror Spot', 'Kakariko Area'),
('Kakariko Grass Mirror Spot', 'Kakariko Area'),
('HC Ledge Mirror Spot', 'Hyrule Castle Ledge'),
('HC Courtyard Mirror Spot', 'Hyrule Castle Courtyard'),
('HC Area Mirror Spot', 'Hyrule Castle Area'),
('HC Area South Mirror Spot', 'Hyrule Castle Area'),
('HC East Entry Mirror Spot', 'Hyrule Castle East Entry'),
('Wooden Bridge Mirror Spot', 'Wooden Bridge Area'),
('Wooden Bridge Northeast Mirror Spot', 'Wooden Bridge Area'),
('Wooden Bridge West Mirror Spot', 'Wooden Bridge Area'),
('Eastern Palace Mirror Spot', 'Eastern Palace Area'),
('Blacksmith Mirror Spot', 'Blacksmith Area'),
('Blacksmith Entry Mirror Spot', 'Blacksmith Area'),
('Bat Cave Ledge Mirror Spot', 'Bat Cave Ledge'),
('Sand Dunes Mirror Spot', 'Sand Dunes Area'),
('Maze Race Mirror Spot', 'Maze Race Ledge'),
('Maze Race Ledge Mirror Spot', 'Maze Race Ledge'),
('Kakariko Suburb Mirror Spot', 'Kakariko Suburb Area'),
('Kakariko Suburb South Mirror Spot', 'Kakariko Suburb Area'),
('Flute Boy Mirror Spot', 'Flute Boy Area'),
('Flute Boy Pass Mirror Spot', 'Flute Boy Pass'),
('Central Bonk Rocks Mirror Spot', 'Central Bonk Rocks Area'),
('Links House Mirror Spot', 'Links House Area'),
('Stone Bridge Mirror Spot', 'Stone Bridge Area'),
('Stone Bridge South Mirror Spot', 'Stone Bridge Area'),
('Hobo Mirror Spot', 'Stone Bridge Water'),
('Tree Line Mirror Spot', 'Tree Line Area'),
('Eastern Nook Mirror Spot', 'Eastern Nook Area'),
('Desert Mirror Spot', 'Desert Area'),
('Desert Ledge Mirror Spot', 'Desert Ledge'),
('Checkerboard Mirror Spot', 'Desert Checkerboard Ledge'),
('DP Stairs Mirror Spot', 'Desert Palace Stairs'),
('DP Entrance (North) Mirror Spot', 'Desert Palace Entrance (North) Spot'),
('Bombos Tablet Ledge Mirror Spot', 'Bombos Tablet Ledge'),
('Flute Boy Entry Mirror Spot', 'Flute Boy Bush Entry'),
('Cave 45 Mirror Spot', 'Cave 45 Ledge'),
('C Whirlpool Mirror Spot', 'C Whirlpool Area'),
('C Whirlpool Outer Mirror Spot', 'C Whirlpool Outer Area'),
('Desert Pass Ledge Mirror Spot', 'Desert Pass Ledge'),
('Desert Pass Mirror Spot', 'Desert Pass Area'),
('Dam Mirror Spot', 'Dam Area'),
('Statues Mirror Spot', 'Statues Area'),
('South Pass Mirror Spot', 'South Pass Area'),
('Lake Hylia Mirror Spot', 'Lake Hylia Area'),
('Lake Hylia Northeast Mirror Spot', 'Lake Hylia Northeast Bank'),
('South Shore Mirror Spot', 'Lake Hylia South Shore'),
('South Shore East Mirror Spot', 'Lake Hylia South Shore'),
('Lake Hylia Island Mirror Spot', 'Lake Hylia Island'),
('Lake Hylia Central Island Mirror Spot', 'Lake Hylia Central Island'),
('Lake Hylia Water Mirror Spot', 'Lake Hylia Water'),
('Octoballoon Mirror Spot', 'Octoballoon Area'),
('Ice Cave Mirror Spot', 'Ice Cave Area'),
# Portal Connections
('Kakariko Teleporter (Hammer)', 'Skull Woods Pass East Top Area'),
('Kakariko Teleporter (Rock)', 'Skull Woods Pass East Top Area'),
('Top of Pyramid', 'Pyramid Area'),
('Top of Pyramid (Inner)', 'Pyramid Area'),
('East Hyrule Teleporter', 'Palace of Darkness Nook Area'),
('South Hyrule Teleporter', 'Dark C Whirlpool Area'),
('Desert Teleporter', 'Misery Mire Teleporter Ledge'),
('Lake Hylia Teleporter', 'Ice Palace Area'),
('West Death Mountain Teleporter', 'West Dark Death Mountain (Bottom)'),
('East Death Mountain Teleporter', 'East Dark Death Mountain (Bottom)'),
('TR Pegs Teleporter', 'Turtle Rock Ledge')
]
inverted_connections = [('Flute Spot 1', 'West Dark Death Mountain (Bottom)'),
('Flute Spot 2', 'Dark Witch Area'),
('Flute Spot 3', 'Village of Outcasts Area'),
('Flute Spot 4', 'Big Bomb Shop Area'),
('Flute Spot 5', 'Palace of Darkness Nook Area'),
('Flute Spot 6', 'Misery Mire Teleporter Ledge'),
('Flute Spot 7', 'Swamp Area'),
('Flute Spot 8', 'Bomber Corner Area'),
('Spectacle Rock Leave', 'West Death Mountain (Top)'),
('Spectacle Rock Approach', 'Spectacle Rock Ledge'),
('East Death Mountain Teleporter', 'East Dark Death Mountain (Bottom)')
], [
('Floating Island Bridge (West)', 'East Death Mountain (Top East)'),
('Floating Island Bridge (East)', 'Death Mountain Floating Island'),
('East Death Mountain Mimic Ledge Drop', 'Mimic Cave Ledge'),
('Mimic Ledge Drop', 'East Death Mountain (Bottom)'),
('Graveyard Ladder (Top)', 'Graveyard Area'),
('Graveyard Ladder (Bottom)', 'Graveyard Ledge'),
('Checkerboard Ledge Approach', 'Desert Checkerboard Ledge'),
('Checkerboard Ledge Leave', 'Desert Area'),
('Cave 45 Inverted Leave', 'Flute Boy Approach Area'),
('Cave 45 Inverted Approach', 'Cave 45 Ledge'),
('Lake Hylia Island Pier', 'Lake Hylia Island'),
('Desert Pass Ladder (North)', 'Desert Pass Area'),
('Desert Pass Ladder (South)', 'Desert Pass Ledge'),
('Dark Death Mountain Ladder (North)', 'West Dark Death Mountain (Bottom)'),
('Dark Death Mountain Ladder (South)', 'West Dark Death Mountain (Top)'),
('Dark South Teleporter Cliff Ledge Drop', 'Central Cliffs'), #OWG only, needs glove
('Turtle Rock Tail Ledge Drop', 'Turtle Rock Ledge'),
('Ice Palace Approach', 'Ice Palace Area'),
('Ice Palace Leave', 'Ice Lake Moat'),
# Mirror Connections
('Skull Woods Back Mirror Spot', 'Skull Woods Forest (West)'),
('Skull Woods Forgotten (West) Mirror Spot', 'Skull Woods Forgotten Path (Southwest)'),
('Skull Woods Forgotten (East) Mirror Spot', 'Skull Woods Forgotten Path (Northeast)'),
('Skull Woods Portal Entry Mirror Spot', 'Skull Woods Portal Entry'),
('Skull Woods Forgotten (Middle) Mirror Spot', 'Skull Woods Forgotten Path (Northeast)'),
('Skull Woods Front Mirror Spot', 'Skull Woods Forest'),
('Dark Lumberjack Mirror Spot', 'Dark Lumberjack Area'),
('West Dark Death Mountain (Top) Mirror Spot', 'West Dark Death Mountain (Top)'),
('Bubble Boy Mirror Spot', 'West Dark Death Mountain (Bottom)'),
('West Dark Death Mountain (Bottom) Mirror Spot', 'West Dark Death Mountain (Bottom)'),
('East Dark Death Mountain (Top West) Mirror Spot', 'East Dark Death Mountain (Top)'),
('East Dark Death Mountain (Top East) Mirror Spot', 'East Dark Death Mountain (Top)'),
('TR Ledge (West) Mirror Spot', 'Dark Death Mountain Ledge'),
@@ -701,93 +735,295 @@ inverted_connections = [('Flute Spot 1', 'West Dark Death Mountain (Bottom)'),
('East Dark Death Mountain (Bottom Left) Mirror Spot', 'East Dark Death Mountain (Bottom Left)'),
('East Dark Death Mountain (Bottom) Mirror Spot', 'East Dark Death Mountain (Bottom)'),
('Dark Floating Island Mirror Spot', 'Dark Death Mountain Floating Island'),
('Dark Death Mountain Teleporter (East)', 'East Death Mountain (Bottom)')
]),
0x07: ([
('TR Pegs Area Mirror Spot', 'Death Mountain TR Pegs'),
('TR Pegs Teleporter', 'Turtle Rock Ledge')
], [
('Turtle Rock Tail Ledge Drop', 'Turtle Rock Ledge'),
('Turtle Rock Mirror Spot', 'Turtle Rock Area'),
('Turtle Rock Ledge Mirror Spot', 'Turtle Rock Ledge'),
('Turtle Rock Teleporter', 'Death Mountain TR Pegs Ledge')
]),
0x0a: ([
('Mountain Entry Mirror Spot', 'Mountain Entry Area'),
('Mountain Entry Entrance Mirror Spot', 'Mountain Entry Entrance'),
('Mountain Entry Ledge Mirror Spot', 'Mountain Entry Ledge')
], [
('Bumper Cave Area Mirror Spot', 'Bumper Cave Area'),
('Bumper Cave Entry Mirror Spot', 'Bumper Cave Entrance'),
('Bumper Cave Ledge Mirror Spot', 'Bumper Cave Ledge'),
('Catfish Mirror Spot', 'Catfish Area'),
('Bumper Cave Ledge Mirror Spot', 'Bumper Cave Ledge')
]),
0x0f: ([
('Zora Waterfall Mirror Spot', 'Zora Waterfall Area')
], [
('Catfish Mirror Spot', 'Catfish Area')
]),
0x10: ([
('Lost Woods Pass West Mirror Spot', 'Lost Woods Pass West Area'),
('Lost Woods Pass East Top Mirror Spot', 'Lost Woods Pass East Top Area'),
('Lost Woods Pass East Bottom Mirror Spot', 'Lost Woods Pass East Bottom Area'),
('Kakariko Teleporter (Hammer)', 'Skull Woods Pass East Top Area'),
('Kakariko Teleporter (Rock)', 'Skull Woods Pass East Top Area')
], [
('Skull Woods Pass West Mirror Spot', 'Skull Woods Pass West Area'),
('Skull Woods Pass East Top Mirror Spot', 'Skull Woods Pass East Top Area'),
('Skull Woods Pass East Bottom Mirror Spot', 'Skull Woods Pass East Bottom Area'),
('Outcast Fortune Mirror Spot', 'Dark Fortune Area'),
('Outcast Pond Mirror Spot', 'Outcast Pond Area'),
('West Dark World Teleporter (Hammer)', 'Lost Woods Pass East Top Area'),
('West Dark World Teleporter (Rock)', 'Lost Woods Pass East Bottom Area')
]),
0x11: ([
('Kakariko Fortune Mirror Spot', 'Kakariko Fortune Area')
], [
('Outcast Fortune Mirror Spot', 'Dark Fortune Area')
]),
0x12: ([
('Kakariko Pond Mirror Spot', 'Kakariko Pond Area')
], [
('Outcast Pond Mirror Spot', 'Outcast Pond Area')
]),
0x13: ([
('Sanctuary Mirror Spot', 'Sanctuary Area'),
('Bonk Rock Ledge Mirror Spot', 'Bonk Rock Ledge')
], [
('Dark Chapel Mirror Spot', 'Dark Chapel Area'),
('Dark Chapel Ledge Mirror Spot', 'Dark Chapel Area'),
('Dark Chapel Ledge Mirror Spot', 'Dark Chapel Area')
]),
0x14: ([
('Graveyard Ledge Mirror Spot', 'Graveyard Ledge'),
('Kings Grave Mirror Spot', 'Kings Grave Area')
], [
('Graveyard Ladder (Top)', 'Graveyard Area'),
('Graveyard Ladder (Bottom)', 'Graveyard Ledge'),
('Dark Graveyard Mirror Spot', 'Dark Graveyard Area'),
('Dark Graveyard Ledge Mirror Spot', 'Dark Graveyard Area'),
('Dark Graveyard Grave Mirror Spot', 'Dark Graveyard Area'),
('Dark Graveyard Grave Mirror Spot', 'Dark Graveyard Area')
]),
0x15: ([
('River Bend Mirror Spot', 'River Bend Area'),
('River Bend East Mirror Spot', 'River Bend East Bank')
], [
('Qirn Jump Mirror Spot', 'Qirn Jump Area'),
('Qirn Jump East Mirror Spot', 'Qirn Jump East Bank'),
('Qirn Jump East Mirror Spot', 'Qirn Jump East Bank')
]),
0x16: ([
('Potion Shop Mirror Spot', 'Potion Shop Area'),
('Potion Shop Northeast Mirror Spot', 'Potion Shop Northeast')
], [
('Dark Witch Mirror Spot', 'Dark Witch Area'),
('Dark Witch Northeast Mirror Spot', 'Dark Witch Northeast'),
('Dark Witch Northeast Mirror Spot', 'Dark Witch Northeast')
]),
0x17: ([
('Zora Approach Mirror Spot', 'Zora Approach Area'),
('Zora Approach Ledge Mirror Spot', 'Zora Approach Ledge')
], [
('Catfish Approach Mirror Spot', 'Catfish Approach Area'),
('Catfish Approach Ledge Mirror Spot', 'Catfish Approach Ledge'),
('Catfish Approach Ledge Mirror Spot', 'Catfish Approach Ledge')
]),
0x18: ([
('Kakariko Mirror Spot', 'Kakariko Area'),
('Kakariko Grass Mirror Spot', 'Kakariko Area')
], [
('Village of Outcasts Mirror Spot', 'Village of Outcasts Area'),
('Village of Outcasts Southwest Mirror Spot', 'Village of Outcasts Area'),
('Hammer House Mirror Spot', 'Dark Grassy Lawn'),
('Shield Shop Mirror Spot', 'Shield Shop Area'),
('Hammer House Mirror Spot', 'Dark Grassy Lawn')
]),
0x1a: ([
('Forgotton Forest Mirror Spot', 'Forgotten Forest Area'),
('Forgotton Forest Fence Mirror Spot', 'Forgotten Forest Area')
], [
('Shield Shop Mirror Spot', 'Shield Shop Area')
]),
0x1b: ([
('HC Ledge Mirror Spot', 'Hyrule Castle Ledge'),
('HC Courtyard Mirror Spot', 'Hyrule Castle Courtyard'),
('HC Area Mirror Spot', 'Hyrule Castle Area'),
('HC Area South Mirror Spot', 'Hyrule Castle Area'),
('HC East Entry Mirror Spot', 'Hyrule Castle East Entry'),
('Top of Pyramid', 'Pyramid Area'),
('Top of Pyramid (Inner)', 'Pyramid Area')
], [
('Pyramid Mirror Spot', 'Pyramid Area'),
('Pyramid Pass Mirror Spot', 'Pyramid Pass'),
('Pyramid Courtyard Mirror Spot', 'Pyramid Area'),
('Pyramid Uncle Mirror Spot', 'Pyramid Area'),
('Pyramid From Ledge Mirror Spot', 'Pyramid Area'),
('Pyramid Entry Mirror Spot', 'Pyramid Area'),
('Post Aga Inverted Teleporter', 'Hyrule Castle Area')
]),
0x1d: ([
('Wooden Bridge Mirror Spot', 'Wooden Bridge Area'),
('Wooden Bridge Northeast Mirror Spot', 'Wooden Bridge Area'),
('Wooden Bridge West Mirror Spot', 'Wooden Bridge Area')
], [
('Broken Bridge West Mirror Spot', 'Broken Bridge West'),
('Broken Bridge East Mirror Spot', 'Broken Bridge Area'),
('Broken Bridge Northeast Mirror Spot', 'Broken Bridge Northeast'),
('Palace of Darkness Mirror Spot', 'Palace of Darkness Area'),
('Broken Bridge Northeast Mirror Spot', 'Broken Bridge Northeast')
]),
0x1e: ([
('Eastern Palace Mirror Spot', 'Eastern Palace Area')
], [
('Palace of Darkness Mirror Spot', 'Palace of Darkness Area')
]),
0x22: ([
('Blacksmith Mirror Spot', 'Blacksmith Area'),
('Blacksmith Entry Mirror Spot', 'Blacksmith Area'),
('Bat Cave Ledge Mirror Spot', 'Bat Cave Ledge')
], [
('Hammer Pegs Mirror Spot', 'Hammer Peg Area'),
('Hammer Pegs Entry Mirror Spot', 'Hammer Peg Entry'),
('Dark Dunes Mirror Spot', 'Dark Dunes Area'),
('Hammer Pegs Entry Mirror Spot', 'Hammer Peg Entry')
]),
0x25: ([
('Sand Dunes Mirror Spot', 'Sand Dunes Area')
], [
('Dark Dunes Mirror Spot', 'Dark Dunes Area')
]),
0x28: ([
('Maze Race Mirror Spot', 'Maze Race Ledge'),
('Maze Race Ledge Mirror Spot', 'Maze Race Ledge')
], [
('Dig Game Mirror Spot', 'Dig Game Area'),
('Dig Game Ledge Mirror Spot', 'Dig Game Ledge'),
('Dig Game Ledge Mirror Spot', 'Dig Game Ledge')
]),
0x29: ([
('Kakariko Suburb Mirror Spot', 'Kakariko Suburb Area'),
('Kakariko Suburb South Mirror Spot', 'Kakariko Suburb Area')
], [
('Frog Mirror Spot', 'Frog Area'),
('Frog Prison Mirror Spot', 'Frog Prison'),
('Archery Game Mirror Spot', 'Archery Game Area'),
('Archery Game Mirror Spot', 'Archery Game Area')
]),
0x2a: ([
('Flute Boy Mirror Spot', 'Flute Boy Area'),
('Flute Boy Pass Mirror Spot', 'Flute Boy Pass')
], [
('Stumpy Mirror Spot', 'Stumpy Area'),
('Stumpy Pass Mirror Spot', 'Stumpy Pass'),
('Dark Bonk Rocks Mirror Spot', 'Dark Bonk Rocks Area'),
('Big Bomb Shop Mirror Spot', 'Big Bomb Shop Area'),
('Stumpy Pass Mirror Spot', 'Stumpy Pass')
]),
0x2b: ([
('Central Bonk Rocks Mirror Spot', 'Central Bonk Rocks Area')
], [
('Dark Bonk Rocks Mirror Spot', 'Dark Bonk Rocks Area')
]),
0x2c: ([
('Links House Mirror Spot', 'Links House Area')
], [
('Big Bomb Shop Mirror Spot', 'Big Bomb Shop Area')
]),
0x2d: ([
('Stone Bridge Mirror Spot', 'Stone Bridge Area'),
('Stone Bridge South Mirror Spot', 'Stone Bridge Area'),
('Hobo Mirror Spot', 'Stone Bridge Water')
], [
('Hammer Bridge North Mirror Spot', 'Hammer Bridge North Area'),
('Hammer Bridge South Mirror Spot', 'Hammer Bridge South Area'),
('Dark Hobo Mirror Spot', 'Hammer Bridge Water'),
('Dark Tree Line Mirror Spot', 'Dark Tree Line Area'),
('Dark Hobo Mirror Spot', 'Hammer Bridge Water')
]),
0x2e: ([
('Tree Line Mirror Spot', 'Tree Line Area')
], [
('Dark Tree Line Mirror Spot', 'Dark Tree Line Area')
]),
0x2f: ([
('Eastern Nook Mirror Spot', 'Eastern Nook Area'),
('East Hyrule Teleporter', 'Palace of Darkness Nook Area')
], [
('Darkness Nook Mirror Spot', 'Palace of Darkness Nook Area'),
('East Dark World Teleporter', 'Eastern Nook Area')
]),
0x30: ([
('Desert Mirror Spot', 'Desert Area'),
('Desert Ledge Mirror Spot', 'Desert Ledge'),
('Checkerboard Mirror Spot', 'Desert Checkerboard Ledge'),
('DP Stairs Mirror Spot', 'Desert Palace Stairs'),
('DP Entrance (North) Mirror Spot', 'Desert Palace Entrance (North) Spot'),
('Bombos Tablet Ledge Mirror Spot', 'Bombos Tablet Ledge'),
('Desert Teleporter', 'Misery Mire Teleporter Ledge')
], [
('Checkerboard Ledge Approach', 'Desert Checkerboard Ledge'),
('Checkerboard Ledge Leave', 'Desert Area'),
('Misery Mire Mirror Spot', 'Misery Mire Area'),
('Misery Mire Ledge Mirror Spot', 'Misery Mire Area'),
('Misery Mire Blocked Mirror Spot', 'Misery Mire Area'),
('Misery Mire Main Mirror Spot', 'Misery Mire Area'),
('Misery Mire Teleporter', 'Desert Palace Teleporter Ledge')
]),
0x32: ([
('Flute Boy Entry Mirror Spot', 'Flute Boy Bush Entry'),
('Cave 45 Mirror Spot', 'Cave 45 Ledge')
], [
('Cave 45 Inverted Leave', 'Flute Boy Approach Area'),
('Cave 45 Inverted Approach', 'Cave 45 Ledge'),
('Stumpy Approach Mirror Spot', 'Stumpy Approach Area'),
('Stumpy Bush Entry Mirror Spot', 'Stumpy Approach Bush Entry'),
('Stumpy Bush Entry Mirror Spot', 'Stumpy Approach Bush Entry')
]),
0x33: ([
('C Whirlpool Mirror Spot', 'C Whirlpool Area'),
('C Whirlpool Outer Mirror Spot', 'C Whirlpool Outer Area'),
('South Hyrule Teleporter', 'Dark C Whirlpool Area')
], [
('Dark C Whirlpool Mirror Spot', 'Dark C Whirlpool Area'),
('Dark C Whirlpool Outer Mirror Spot', 'Dark C Whirlpool Outer Area'),
('Hype Cave Mirror Spot', 'Hype Cave Area'),
('South Dark World Teleporter', 'C Whirlpool Area'),
('Dark South Teleporter Cliff Ledge Drop', 'Central Cliffs') #OWG only, needs glove
]),
0x34: ([
('Statues Mirror Spot', 'Statues Area')
], [
('Hype Cave Mirror Spot', 'Hype Cave Area')
]),
0x35: ([
('Lake Hylia Mirror Spot', 'Lake Hylia Area'),
('Lake Hylia Northeast Mirror Spot', 'Lake Hylia Northeast Bank'),
('South Shore Mirror Spot', 'Lake Hylia South Shore'),
('South Shore East Mirror Spot', 'Lake Hylia South Shore'),
('Lake Hylia Island Mirror Spot', 'Lake Hylia Island'),
('Lake Hylia Central Island Mirror Spot', 'Lake Hylia Central Island'),
('Lake Hylia Water Mirror Spot', 'Lake Hylia Water'),
('Lake Hylia Teleporter', 'Ice Palace Area')
], [
('Lake Hylia Island Pier', 'Lake Hylia Island'),
('Ice Palace Approach', 'Ice Palace Area'),
('Ice Palace Leave', 'Ice Lake Moat'),
('Ice Lake Mirror Spot', 'Ice Lake Area'),
('Ice Lake Southwest Mirror Spot', 'Ice Lake Ledge (West)'),
('Ice Lake Southeast Mirror Spot', 'Ice Lake Ledge (East)'),
('Ice Lake Northeast Mirror Spot', 'Ice Lake Northeast Bank'),
('Ice Palace Mirror Spot', 'Ice Palace Area'),
('Shopping Mall Mirror Spot', 'Shopping Mall Area'),
('Swmap Nook Mirror Spot', 'Swamp Nook Area'),
('Ice Palace Teleporter', 'Lake Hylia Central Island')
]),
0x37: ([
('Ice Cave Mirror Spot', 'Ice Cave Area')
], [
('Shopping Mall Mirror Spot', 'Shopping Mall Area')
]),
0x3a: ([
('Desert Pass Ledge Mirror Spot', 'Desert Pass Ledge'),
('Desert Pass Mirror Spot', 'Desert Pass Area')
], [
('Desert Pass Ladder (North)', 'Desert Pass Area'),
('Desert Pass Ladder (South)', 'Desert Pass Ledge'),
('Swamp Nook Mirror Spot', 'Swamp Nook Area'),
('Swamp Nook Southeast Mirror Spot', 'Swamp Nook Area'),
('Swamp Nook Pegs Mirror Spot', 'Swamp Nook Area'),
('Swamp Mirror Spot', 'Swamp Area'),
('Dark South Pass Mirror Spot', 'Dark South Pass Area'),
('Bomber Corner Mirror Spot', 'Bomber Corner Area'),
# Portal Connections
('Post Aga Inverted Teleporter', 'Hyrule Castle Area'),
('Ice Palace Teleporter', 'Lake Hylia Central Island'),
('Misery Mire Teleporter', 'Desert Palace Teleporter Ledge'),
('East Dark World Teleporter', 'Eastern Nook Area'),
('South Dark World Teleporter', 'C Whirlpool Area'),
('West Dark World Teleporter (Hammer)', 'Lost Woods Pass East Top Area'),
('West Dark World Teleporter (Rock)', 'Lost Woods Pass East Bottom Area'),
('Dark Death Mountain Teleporter (West)', 'West Death Mountain (Bottom)'),
('Dark Death Mountain Teleporter (East)', 'East Death Mountain (Bottom)'),
('Turtle Rock Teleporter', 'Death Mountain TR Pegs Ledge')
]
('Swamp Nook Pegs Mirror Spot', 'Swamp Nook Area')
]),
0x3b: ([
('Dam Mirror Spot', 'Dam Area')
], [
('Swamp Mirror Spot', 'Swamp Area')
]),
0x3c: ([
('South Pass Mirror Spot', 'South Pass Area')
], [
('Dark South Pass Mirror Spot', 'Dark South Pass Area')
]),
0x3f: ([
('Octoballoon Mirror Spot', 'Octoballoon Area')
], [
('Bomber Corner Mirror Spot', 'Bomber Corner Area')
])
}
parallelsimilar_connections = [('Maze Race ES', 'Kakariko Suburb WS'),
('Dig Game EC', 'Frog WC'),

View File

@@ -111,7 +111,7 @@ def create_regions(world, player):
create_lw_region(player, 'Lake Hylia Island', ['Lake Hylia Island'], ['Lake Hylia Island Water Drop']),
create_lw_region(player, 'Lake Hylia Water', None, ['Lake Hylia Central Island Pier', 'Lake Hylia Island Pier', 'Lake Hylia West Pier', 'Lake Hylia East Pier', 'Lake Hylia NC', 'Lake Hylia EC', 'Lake Hylia Whirlpool']),
create_lw_region(player, 'Ice Cave Area', None, ['Ice Rod Cave', 'Good Bee Cave', '20 Rupee Cave', 'Shopping Mall Mirror Spot', 'Ice Cave SE', 'Ice Cave SW']),
create_lw_region(player, 'Desert Pass Area', ['Purple Chest'], ['Desert Pass Ladder (South)', 'Desert Fairy', '50 Rupee Cave', 'Swmap Nook Mirror Spot', 'Desert Pass WS', 'Desert Pass EC', 'Desert Pass Rocks (North)']),
create_lw_region(player, 'Desert Pass Area', ['Purple Chest'], ['Desert Pass Ladder (South)', 'Desert Fairy', '50 Rupee Cave', 'Swamp Nook Mirror Spot', 'Desert Pass WS', 'Desert Pass EC', 'Desert Pass Rocks (North)']),
create_lw_region(player, 'Desert Pass Southeast', None, ['Desert Pass Rocks (South)', 'Swamp Nook Southeast Mirror Spot', 'Desert Pass ES']),
create_lw_region(player, 'Desert Pass Ledge', None, ['Desert Pass Ladder (North)', 'Desert Pass Ledge Drop', 'Swamp Nook Pegs Mirror Spot', 'Desert Pass WC']),
create_lw_region(player, 'Dam Area', ['Sunken Treasure'], ['Dam', 'Swamp Mirror Spot', 'Dam WC', 'Dam WS', 'Dam NC', 'Dam EC']),
@@ -147,7 +147,7 @@ def create_regions(world, player):
create_dw_region(player, 'Skull Woods Pass East Bottom Area', None, ['Skull Woods Pass Rock (Bottom)', 'Lost Woods Pass East Bottom Mirror Spot', 'Skull Woods Pass SE']),
create_dw_region(player, 'Dark Fortune Area', None, ['Fortune Teller (Dark)', 'Kakariko Fortune Mirror Spot', 'Dark Fortune NE', 'Dark Fortune EN', 'Dark Fortune ES', 'Dark Fortune SC']),
create_dw_region(player, 'Outcast Pond Area', None, ['Kakariko Pond Mirror Spot', 'Outcast Pond NE', 'Outcast Pond WN', 'Outcast Pond WS', 'Outcast Pond SW', 'Outcast Pond SE', 'Outcast Pond EN', 'Outcast Pond ES']),
create_dw_region(player, 'Dark Chapel Area', None, ['Dark Sanctuary Hint', 'Bonk Rock Ledge Mirror Spot', 'Dark Chapel WN', 'Dark Chapel WS', 'Dark Chapel EC']),
create_dw_region(player, 'Dark Chapel Area', None, ['Dark Sanctuary Hint', 'Sanctuary Mirror Spot', 'Bonk Rock Ledge Mirror Spot', 'Dark Chapel WN', 'Dark Chapel WS', 'Dark Chapel EC']),
create_dw_region(player, 'Dark Graveyard Area', None, ['Graveyard Ledge Mirror Spot', 'Kings Grave Mirror Spot', 'Dark Graveyard WC', 'Dark Graveyard EC']),
create_dw_region(player, 'Qirn Jump Area', None, ['Qirn Jump Water Drop', 'River Bend Mirror Spot', 'Qirn Jump WC', 'Qirn Jump SW']),
create_dw_region(player, 'Qirn Jump East Bank', None, ['Qirn Jump East Water Drop', 'River Bend East Mirror Spot', 'Qirn Jump SE', 'Qirn Jump EC', 'Qirn Jump ES']),

269
Rom.py
View File

@@ -27,7 +27,7 @@ from EntranceShuffle import door_addresses, exit_ids
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '2f83a44f0ac2720b489d50bfa8e56837'
RANDOMIZERBASEHASH = '03a63945398191337e896e5771f77173'
class JsonRom(object):
@@ -592,7 +592,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
write_pots_to_rom(rom, world.pot_contents[player])
# patch overworld edges
if world.owShuffle[player] != 'vanilla':
if world.owShuffle[player] != 'vanilla' or world.owSwap[player] != 'vanilla':
rom.write_byte(0x18004C, 0x01) #patch for allowing Frogsmith to enter multi-entrance caves
#patches map data specific for OW Shuffle
rom.buffer[0x153B03] = rom.buffer[0x153B03] | 0x2 #convenient portal on WDM
@@ -606,18 +606,39 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.buffer[0x153B62] = rom.buffer[0x153B62] | 0x2 #rocks added to prevent OWG hardlock
rom.buffer[0x153B7F] = rom.buffer[0x153B7F] | 0x2 #added C to terrain
owMode = 0
if world.owShuffle[player] == 'parallel':
owMode = 1
elif world.owShuffle[player] == 'full':
owMode = 2
rom.write_byte(0x150002, owMode)
if world.owSwap[player] == 'mixed':
owMode |= 0x100
world.fix_fake_world[player] = True
elif world.owSwap[player] == 'crossed':
owMode |= 0x200
world.fix_fake_world[player] = True
write_int16(rom, 0x150002, owMode)
owFlags = 0
if world.owKeepSimilar[player]:
owFlags += 0x1
owFlags |= 0x1
write_int16(rom, 0x150003, owFlags)
write_int16(rom, 0x150004, owFlags)
if world.owSwap[player] == 'mixed':
for b in world.owswaps[player][0]:
# load inverted maps
v = rom.buffer[0x153B00 + b]
v = (v & 0xFE) | ((v + 1) % 2)
rom.buffer[0x153B00 + b] = v
# set world flag
v = rom.buffer[0x153A00 + b]
v = (v & 0xBF) | ((((v >> 6) + 1) % 2) << 6)
rom.buffer[0x153A00 + b] = v
for edge in world.owedges:
if edge.dest is not None and isinstance(edge.dest, OWEdge) and edge.player == player:
@@ -895,11 +916,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
# set open mode:
if world.mode[player] in ['open', 'inverted']:
rom.write_byte(0x180032, 0x01) # open mode
if world.mode[player] == 'inverted':
set_inverted_mode(world, player, rom)
elif world.mode[player] == 'standard':
rom.write_byte(0x180032, 0x00) # standard mode
set_inverted_mode(world, player, rom)
uncle_location = world.get_location('Link\'s Uncle', player)
if uncle_location.item is None or uncle_location.item.name not in ['Master Sword', 'Tempered Sword', 'Fighter Sword', 'Golden Sword', 'Progressive Sword']:
# disable sword sprite from uncle
@@ -2221,70 +2242,24 @@ def write_strings(rom, world, player, team):
rom.write_bytes(0x76CC0, [byte for p in pointers for byte in [p & 0xFF, p >> 8 & 0xFF]])
def set_inverted_mode(world, player, rom):
# flip inverted map flags
for b in range(0x00, 0x80):
if world.mode[player] == 'inverted':
# load inverted maps
for b in range(0x00, 0x82):
v = rom.buffer[0x153B00 + b]
rom.buffer[0x153B00 + b] = (v & 0xFE) | ((v + 1) % 2)
rom.write_byte(snes_to_pc(0x0283E0), 0xF0) # residual portals
rom.write_byte(snes_to_pc(0x02B34D), 0xF0)
rom.write_byte(snes_to_pc(0x06DB78), 0x8B)
rom.write_byte(snes_to_pc(0x05AF79), 0xF0)
rom.write_byte(snes_to_pc(0x0DB3C5), 0xC6)
rom.write_byte(snes_to_pc(0x06DB78), 0x8B) # dark-style portal
rom.write_byte(snes_to_pc(0x0DB3C5), 0xC6) #vortex
rom.write_byte(snes_to_pc(0x07A3F4), 0xF0) # duck
write_int16s(rom, snes_to_pc(0x02E849), [0x0043, 0x0056, 0x0058, 0x006C, 0x006F, 0x0070, 0x007B, 0x007F, 0x001B]) # dw flute
write_int16(rom, snes_to_pc(0x02E8D5), 0x07C8)
write_int16(rom, snes_to_pc(0x02E8F7), 0x01F8)
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof
# the following bytes should only be written in vanilla
# or they'll overwrite the randomizer's shuffles
if world.shuffle[player] == 'vanilla':
rom.write_byte(0xDBB73 + 0x23, 0x37) # switch AT and GT
rom.write_byte(0xDBB73 + 0x36, 0x24)
if world.doorShuffle[player] == 'vanilla' or world.intensity[player] < 3:
write_int16(rom, 0x15AEE + 2*0x38, 0x00E0)
write_int16(rom, 0x15AEE + 2*0x25, 0x000C)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
rom.write_byte(0x15B8C, 0x6C)
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house
rom.write_byte(0xDBB73 + 0x52, 0x01)
rom.write_byte(0xDBB73 + 0x15, 0x06) # bumper and old man cave
write_int16(rom, 0x15AEE + 2*0x17, 0x00F0)
rom.write_byte(0xDBB73 + 0x05, 0x16)
write_int16(rom, 0x15AEE + 2*0x07, 0x00FB)
rom.write_byte(0xDBB73 + 0x2D, 0x17)
write_int16(rom, 0x15AEE + 2*0x2F, 0x00EB)
rom.write_byte(0xDBB73 + 0x06, 0x2E)
write_int16(rom, 0x15AEE + 2*0x08, 0x00E6)
rom.write_byte(0xDBB73 + 0x16, 0x5E)
rom.write_byte(0xDBB73 + 0x6F, 0x07) # DDM fairy to old man cave
write_int16(rom, 0x15AEE + 2*0x18, 0x00F1)
rom.write_byte(0x15B8C + 0x18, 0x43)
write_int16(rom, 0x15BDB + 2 * 0x18, 0x1400)
write_int16(rom, 0x15C79 + 2 * 0x18, 0x0294)
write_int16(rom, 0x15D17 + 2 * 0x18, 0x0600)
write_int16(rom, 0x15DB5 + 2 * 0x18, 0x02E8)
write_int16(rom, 0x15E53 + 2 * 0x18, 0x0678)
write_int16(rom, 0x15EF1 + 2 * 0x18, 0x0303)
write_int16(rom, 0x15F8F + 2 * 0x18, 0x0685)
rom.write_byte(0x1602D + 0x18, 0x0A)
rom.write_byte(0x1607C + 0x18, 0xF6)
write_int16(rom, 0x160CB + 2 * 0x18, 0x0000)
write_int16(rom, 0x16169 + 2 * 0x18, 0x0000)
write_int16(rom, 0x15AEE + 2 * 0x3D, 0x0003) # pyramid exit and houlihan
rom.write_byte(0x15B8C + 0x3D, 0x5B)
write_int16(rom, 0x15BDB + 2 * 0x3D, 0x0B0E)
write_int16(rom, 0x15C79 + 2 * 0x3D, 0x075A)
write_int16(rom, 0x15D17 + 2 * 0x3D, 0x0674)
write_int16(rom, 0x15DB5 + 2 * 0x3D, 0x07A8)
write_int16(rom, 0x15E53 + 2 * 0x3D, 0x06E8)
write_int16(rom, 0x15EF1 + 2 * 0x3D, 0x07C7)
write_int16(rom, 0x15F8F + 2 * 0x3D, 0x06F3)
rom.write_byte(0x1602D + 0x3D, 0x06)
rom.write_byte(0x1607C + 0x3D, 0xFA)
write_int16(rom, 0x160CB + 2 * 0x3D, 0x0000)
write_int16(rom, 0x16169 + 2 * 0x3D, 0x0000)
write_int16(rom, snes_to_pc(0x02D8D4), 0x112) # change sactuary spawn point to dark sanc
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph poof
rom.write_byte(snes_to_pc(0x0ABFBB), 0x90) # move mirror portal indicator to correct map (0xB0 normally)
rom.write_byte(snes_to_pc(0x0280A6), 0xD0) # use starting point prompt instead of start at pyramid
write_int16(rom, snes_to_pc(0x02D8D4), 0x112) # change sanctuary spawn point to dark sanc
rom.write_bytes(snes_to_pc(0x02D8E8), [0x22, 0x22, 0x22, 0x23, 0x04, 0x04, 0x04, 0x05])
write_int16(rom, snes_to_pc(0x02D91A), 0x0400)
write_int16(rom, snes_to_pc(0x02D928), 0x222E)
@@ -2301,10 +2276,20 @@ def set_inverted_mode(world, player, rom):
write_int16(rom, snes_to_pc(0x02D998), 0x0000)
write_int16(rom, snes_to_pc(0x02D9A6), 0x005A)
rom.write_byte(snes_to_pc(0x02D9B3), 0x12)
# keep the old man spawn point at old man house unless shuffle is vanilla
if world.shuffle[player] == 'vanilla':
rom.write_byte(0xDBB73 + 0x23, 0x37) # switch AT and GT
rom.write_byte(0xDBB73 + 0x36, 0x24)
if world.doorShuffle[player] == 'vanilla' or world.intensity[player] < 3:
write_int16(rom, 0x15AEE + 2*0x38, 0x00E0)
write_int16(rom, 0x15AEE + 2*0x25, 0x000C)
if (world.mode[player] == 'inverted') != (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E849), 0x0043) #flute spot
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple']:
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01])
write_int16(rom, snes_to_pc(0x02D8DE), 0x00F1)
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01]) # mountain cave starts on OW
write_int16(rom, snes_to_pc(0x02D8DE), 0x00F1) # change mountain cave spawn point to just outside old man cave
rom.write_bytes(snes_to_pc(0x02D910), [0x1F, 0x1E, 0x1F, 0x1F, 0x03, 0x02, 0x03, 0x03])
write_int16(rom, snes_to_pc(0x02D924), 0x0300)
write_int16(rom, snes_to_pc(0x02D932), 0x1F10)
@@ -2321,7 +2306,59 @@ def set_inverted_mode(world, player, rom):
write_int16(rom, snes_to_pc(0x02D9A2), 0x0000)
write_int16(rom, snes_to_pc(0x02D9B0), 0x0007)
rom.write_byte(snes_to_pc(0x02D9B8), 0x12)
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00])
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00]) #indicates the overworld door being used for the single entrance spawn point
rom.write_byte(0xDBB73 + 0x6F, 0x07) # DDM fairy entrance to old man fetch east UW
write_int16(rom, 0x15AEE + 2*0x18, 0x00F1) # old man fetch UW to DDM fairy entrance
rom.write_byte(0x15B8C + 0x18, 0x43)
write_int16(rom, 0x15BDB + 2 * 0x18, 0x1400)
write_int16(rom, 0x15C79 + 2 * 0x18, 0x0294)
write_int16(rom, 0x15D17 + 2 * 0x18, 0x0600)
write_int16(rom, 0x15DB5 + 2 * 0x18, 0x02E8)
write_int16(rom, 0x15E53 + 2 * 0x18, 0x0678)
write_int16(rom, 0x15EF1 + 2 * 0x18, 0x0303)
write_int16(rom, 0x15F8F + 2 * 0x18, 0x0685)
rom.write_byte(0x1602D + 0x18, 0x0A)
rom.write_byte(0x1607C + 0x18, 0xF6)
write_int16(rom, 0x160CB + 2 * 0x18, 0x0000)
write_int16(rom, 0x16169 + 2 * 0x18, 0x0000)
rom.write_byte(0xDBB73 + 0x06, 0x2E) # old man fetch east entrance to DMD west UW
write_int16(rom, 0x15AEE + 2*0x08, 0x00E6) # DMD west UW to old man fetch east entrance
if (world.mode[player] == 'inverted') != (0x0A in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_byte(0xDBB73 + 0x16, 0x5E) # bumper cave top entrance to DDM Fairy UW
else:
rom.write_byte(0xDBB73 + 0x2D, 0x5E) # DMD west entrance to DDM Fairy
if (world.mode[player] == 'inverted') != (0x05 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_bytes(snes_to_pc(0x1BC655), [0x4A, 0x1D, 0x82]) # add warp under rock
if (world.mode[player] == 'inverted') != (0x07 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_bytes(snes_to_pc(0x1BC387), [0xDD, 0xD1]) # add warps under rocks
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF]) # add warps under rocks
rom.write_byte(0x180089, 0x01) # open TR after exit
rom.write_bytes(0x0086E, [0x5C, 0x00, 0xA0, 0xA1]) # TR tail
if world.shuffle[player] in ['vanilla']:
world.fix_trock_doors[player] = True
if (world.mode[player] == 'inverted') != (0x0A in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
rom.write_byte(0xDBB73 + 0x15, 0x06) # bumper cave bottom entrance to old man fetch west UW
write_int16(rom, 0x15AEE + 2*0x17, 0x00F0) # old man fetch west UW to bumper cave bottom entrance
rom.write_byte(0xDBB73 + 0x05, 0x16) # old man fetch west entrance to bumper cave bottom UW
write_int16(rom, 0x15AEE + 2*0x07, 0x00FB) # bumper cave bottom UW to old man fetch west entrance
rom.write_byte(0xDBB73 + 0x2D, 0x17) # DMD west entrance to bumper cave top UW
write_int16(rom, 0x15AEE + 2*0x2F, 0x00EB) # bumper cave top UW to DMD west entrance
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_byte(0xDBB73 + 0x16, 0x2E) # bumper cave top entrance to DMD west UW
write_int16(rom, 0x15AEE + 2*0x18, 0x00E6) # DMD west UW to bumper cave top entrance
if (world.mode[player] == 'inverted') != (0x10 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_bytes(snes_to_pc(0x1BC67A), [0x2E, 0x0B, 0x82]) # add warp under rock
if (world.mode[player] == 'inverted') != (0x16 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E84B), 0x0056) #flute spot
if (world.mode[player] == 'inverted') != (0x18 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E84D), 0x0058) #flute spot
write_int16(rom, snes_to_pc(0x02E8D5), 0x07C8) #flute spot
write_int16(rom, snes_to_pc(0x02E8F7), 0x01F8) #flute spot
if (world.mode[player] == 'inverted') != (0x1B in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, 0x15AEE + 2 * 0x06, 0x0020) # post aga hyrule castle spawn
rom.write_byte(0x15B8C + 0x06, 0x1B)
write_int16(rom, 0x15BDB + 2 * 0x06, 0x00AE)
@@ -2335,7 +2372,9 @@ def set_inverted_mode(world, player, rom):
rom.write_byte(0x1607C + 0x06, 0xF2)
write_int16(rom, 0x160CB + 2 * 0x06, 0x0000)
write_int16(rom, 0x16169 + 2 * 0x06, 0x0000)
write_int16(rom, snes_to_pc(0x02E87B), 0x00AE) # move flute splot 9
write_int16(rom, snes_to_pc(0x02E859), 0x001B) # move flute spot 9
write_int16(rom, snes_to_pc(0x02E87B), 0x00AE)
write_int16(rom, snes_to_pc(0x02E89D), 0x0610)
write_int16(rom, snes_to_pc(0x02E8BF), 0x077E)
write_int16(rom, snes_to_pc(0x02E8E1), 0x0672)
@@ -2344,13 +2383,20 @@ def set_inverted_mode(world, player, rom):
write_int16(rom, snes_to_pc(0x02E947), 0x0803)
write_int16(rom, snes_to_pc(0x02E969), 0x0000)
write_int16(rom, snes_to_pc(0x02E98B), 0xFFF2)
rom.write_byte(snes_to_pc(0x1AF696), 0xF0) # bat sprite retreat
rom.write_byte(snes_to_pc(0x1AF6B2), 0x33)
#new pyramid hole mask position
rom.write_bytes(snes_to_pc(0x1AF730), [0x6A, 0x9E, 0x0C, 0x00, 0x7A, 0x9E, 0x0C,
0x00, 0x8A, 0x9E, 0x0C, 0x00, 0x6A, 0xAE,
0x0C, 0x00, 0x7A, 0xAE, 0x0C, 0x00, 0x8A,
0xAE, 0x0C, 0x00, 0x67, 0x97, 0x0C, 0x00,
0x8D, 0x97, 0x0C, 0x00])
rom.write_byte(snes_to_pc(0x00D009), 0x31) # castle hole graphics
rom.write_byte(snes_to_pc(0x00D0E8), 0xE0)
rom.write_byte(snes_to_pc(0x00D1C7), 0x00)
write_int16(rom, snes_to_pc(0x1BE8DA), 0x39AD) # add color for shading for castle hole
#castle hole map16 data
write_int16s(rom, snes_to_pc(0x0FF1C8), [0x190F, 0x190F, 0x190F, 0x194C, 0x190F,
0x194B, 0x190F, 0x195C, 0x594B, 0x194C,
0x19EE, 0x19EE, 0x194B, 0x19EE, 0x19EE,
@@ -2361,13 +2407,22 @@ def set_inverted_mode(world, player, rom):
0x190F])
write_int16s(rom, snes_to_pc(0x0FA480), [0x190F, 0x196B, 0x9D04, 0x9D04, 0x196B,
0x190F, 0x9D04, 0x9D04])
write_int16s(rom, snes_to_pc(0x1bb810), [0x00BE, 0x00C0, 0x013E])
write_int16s(rom, snes_to_pc(0x1bb836), [0x001B, 0x001B, 0x001B])
write_int16(rom, snes_to_pc(0x308300), 0x0140) # new pyramid hole entrance
write_int16s(rom, snes_to_pc(0x1BB810), [0x00BE, 0x00C0, 0x013E]) # update pyramid hole entrance
write_int16s(rom, snes_to_pc(0x1BB836), [0x001B, 0x001B, 0x001B])
write_int16(rom, snes_to_pc(0x308300), 0x0140) #add extra pyramid hole
write_int16(rom, snes_to_pc(0x308320), 0x001B)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
rom.write_byte(snes_to_pc(0x308340), 0x7B)
write_int16(rom, snes_to_pc(0x1af504), 0x148B)
rom.write_byte(snes_to_pc(0x00DB9D), 0x1A) # make retreat bat gfx available in HC area
rom.write_byte(snes_to_pc(0x00DC09), 0x1A)
rom.write_byte(snes_to_pc(0x1AF696), 0xF0) # bat sprite retreat : bat X position
rom.write_byte(snes_to_pc(0x1AF6B2), 0x33) # bat sprite retreat : bat delay
write_int16(rom, snes_to_pc(0x1af504), 0x148B) # prioritize retreat Bat and use 3rd sprite group
write_int16(rom, snes_to_pc(0x1af50c), 0x149B)
write_int16(rom, snes_to_pc(0x1af514), 0x14A4)
write_int16(rom, snes_to_pc(0x1af51c), 0x1489)
@@ -2385,26 +2440,15 @@ def set_inverted_mode(world, player, rom):
write_int16(rom, snes_to_pc(0x1af57c), 0x548E)
write_int16(rom, snes_to_pc(0x1af584), 0x14AE)
write_int16(rom, snes_to_pc(0x1af58c), 0x54AE)
rom.write_byte(snes_to_pc(0x00DB9D), 0x1A) # castle hole graphics
rom.write_byte(snes_to_pc(0x00DC09), 0x1A)
rom.write_byte(snes_to_pc(0x00D009), 0x31)
rom.write_byte(snes_to_pc(0x00D0e8), 0xE0)
rom.write_byte(snes_to_pc(0x00D1c7), 0x00)
write_int16(rom, snes_to_pc(0x1BE8DA), 0x39AD)
rom.write_byte(0xF6E58, 0x80) # no whirlpool under castle gate
rom.write_bytes(0x0086E, [0x5C, 0x00, 0xA0, 0xA1]) # TR tail
rom.write_bytes(snes_to_pc(0x1BC67A), [0x2E, 0x0B, 0x82]) # add warps under rocks
rom.write_bytes(snes_to_pc(0x1BC81E), [0x94, 0x1D, 0x82])
rom.write_bytes(snes_to_pc(0x1BC655), [0x4A, 0x1D, 0x82])
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82])
rom.write_bytes(snes_to_pc(0x1BC3DF), [0xD8, 0xD1])
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF])
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82])
rom.write_byte(snes_to_pc(0x09D436), 0xF3) # replace whirlpool with harmless sprite
write_int16(rom, 0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door
write_int16(rom, 0xDBA71 + 2 * 0x35, 0x011C)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
rom.write_byte(0xDBB73 + 0x35, 0x36)
rom.write_byte(snes_to_pc(0x09D436), 0xF3) # remove castle gate warp
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
write_int16(rom, 0x15AEE + 2 * 0x37, 0x0010) # pyramid exit to new hc area
rom.write_byte(0x15B8C + 0x37, 0x1B)
@@ -2419,12 +2463,43 @@ def set_inverted_mode(world, player, rom):
rom.write_byte(0x1607C + 0x37, 0x0A)
write_int16(rom, 0x160CB + 2 * 0x37, 0x0000)
write_int16(rom, 0x16169 + 2 * 0x37, 0x811c)
rom.write_bytes(snes_to_pc(0x1BC387), [0xDD, 0xD1])
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF])
rom.write_byte(0x180089, 0x01) # open TR after exit
rom.write_byte(snes_to_pc(0x0ABFBB), 0x90)
rom.write_byte(snes_to_pc(0x0280A6), 0xD0)
rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05])
if (world.mode[player] == 'inverted') != (0x29 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05]) #frog pickup on contact
if (world.mode[player] == 'inverted') != (0x2C in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E84F), 0x006C) #flute spot
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
rom.write_byte(0x15B8C, 0x6C) #exit links at bomb shop area
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house
rom.write_byte(0xDBB73 + 0x52, 0x01)
if (world.mode[player] == 'inverted') != (0x2F in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E851), 0x006F) #flute spot
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82]) # add warp under rock
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E853), 0x0070) #flute spot
rom.write_bytes(snes_to_pc(0x1BC81E), [0x94, 0x1D, 0x82]) # add warp under rock
if (world.mode[player] == 'inverted') != (0x33 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_bytes(snes_to_pc(0x1BC3DF), [0xD8, 0xD1]) # add warp under rock
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF]) # add warp under rock
if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82]) # add warp under rock
if (world.mode[player] == 'inverted') != (0x3B in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E855), 0x007B) #flute spot
if (world.mode[player] == 'inverted') != (0x3F in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
write_int16(rom, snes_to_pc(0x02E857), 0x007F) #flute spot
if world.mode[player] == 'inverted':
rom.write_byte(0x15B8C + 0x3D, rom.buffer[0x15B8C]) # houlihan exit
write_int16(rom, 0x15BDB + 2 * 0x3D, rom.buffer[0x15BDB] + (rom.buffer[0x15BDC] << 8))
write_int16(rom, 0x15C79 + 2 * 0x3D, rom.buffer[0x15C79] + (rom.buffer[0x15C7A] << 8))
write_int16(rom, 0x15D17 + 2 * 0x3D, rom.buffer[0x15D17] + (rom.buffer[0x15D18] << 8))
write_int16(rom, 0x15DB5 + 2 * 0x3D, rom.buffer[0x15DB5] + (rom.buffer[0x15DB6] << 8))
write_int16(rom, 0x15E53 + 2 * 0x3D, rom.buffer[0x15E53] + (rom.buffer[0x15E54] << 8))
write_int16(rom, 0x15EF1 + 2 * 0x3D, rom.buffer[0x15EF1] + (rom.buffer[0x15EF2] << 8))
write_int16(rom, 0x15F8F + 2 * 0x3D, rom.buffer[0x15F8F] + (rom.buffer[0x15F90] << 8))
rom.write_byte(0x1602D + 0x3D, rom.buffer[0x1602D])
rom.write_byte(0x1607C + 0x3D, rom.buffer[0x1607C])
write_int16(rom, 0x160CB + 2 * 0x3D, rom.buffer[0x160CB] + (rom.buffer[0x160CC] << 8))
write_int16(rom, 0x16169 + 2 * 0x3D, rom.buffer[0x16169] + (rom.buffer[0x1616A] << 8))
def patch_shuffled_dark_sanc(world, rom, player):
dark_sanc = world.get_region('Dark Sanctuary Hint', player)

532
Rules.py
View File

@@ -19,11 +19,7 @@ def set_rules(world, player):
global_rules(world, player)
default_rules(world, player)
if world.mode[player] != 'inverted':
ow_open_rules(world, player)
else:
ow_inverted_rules(world, player)
ow_rules(world, player)
ow_bunny_rules(world, player)
@@ -76,6 +72,13 @@ def set_rules(world, player):
set_bunny_rules(world, player, world.mode[player] == 'inverted')
# TODO: Remove these rules when these scenarios aren't a problem
if world.owSwap[player] == 'mixed':
if 'Frog Area' in world.owswaps[player][2]:
set_rule(world.get_location('Frog', player), lambda state: False)
if 'Stumpy Area' in world.owswaps[player][2]:
set_rule(world.get_location('Stumpy', player), lambda state: False)
def mirrorless_path_to_location(world, startName, targetName, player):
# If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch.
@@ -839,16 +842,39 @@ def default_rules(world, player):
swordless_rules(world, player)
def ow_open_rules(world, player):
def ow_rules(world, player):
if (world.mode[player] == 'inverted') == (0x00 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Lost Woods East Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pedestal Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Southwest Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods East (Forgotten) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods West (Forgotten) Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Skull Woods Back Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Forgotten (West) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Forgotten (East) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Portal Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Forgotten (Middle) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Front Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x02 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dark Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('GT Entry Approach', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'crossed', 'insanity'))
set_rule(world.get_entrance('West Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Spectacle Rock Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('West Dark Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bubble Boy Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('West Dark Death Mountain (Bottom) Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x05 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('East Death Mountain (Top West) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('East Death Mountain (Top East) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mimic Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -857,115 +883,8 @@ def ow_open_rules(world, player):
set_rule(world.get_entrance('Isolated Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Death Mountain Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('TR Pegs Area Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mountain Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mountain Entry Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mountain Entry Entrance Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Zora Waterfall Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pass West Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pass East Top Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pass East Bottom Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Fortune Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Pond Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bonk Rock Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
set_rule(world.get_entrance('River Bend Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('River Bend East Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Potion Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Potion Shop Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Zora Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Zora Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Grass Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Forgotton Forest Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Forgotton Forest Fence Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Area Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Courtyard Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC East Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Area South Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Wooden Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Wooden Bridge Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Wooden Bridge West Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Eastern Palace Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Blacksmith Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Blacksmith Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bat Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Sand Dunes Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Maze Race Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Maze Race Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Suburb Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Suburb South Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Flute Boy Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Flute Boy Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Central Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Links House Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Stone Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Stone Bridge South Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hobo Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
set_rule(world.get_entrance('Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Eastern Nook Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Checkerboard Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('DP Stairs Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('DP Entrance (North) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bombos Tablet Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Cave 45 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Flute Boy Entry Mirror Spot', player), lambda state: state.has_Mirror(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('Statues Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Water Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Shore Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Shore East Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Ice Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Pass Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dam Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Octoballoon Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Teleporter (Hammer)', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot lift bushes
set_rule(world.get_entrance('Kakariko Teleporter (Rock)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) # bunny cannot lift bushes
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 (Inner)', player), lambda state: state.has('Beat Agahnim 1', 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_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_Pearl(player)) # bunny cannot use hammer
set_rule(world.get_entrance('South Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) # OWG only, can bomb clip out
set_rule(world.get_entrance('Desert Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
set_rule(world.get_entrance('Lake Hylia Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
set_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
set_rule(world.get_entrance('TR Pegs Teleporter', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: False)
set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False)
set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[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('GT Entry Approach', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'crossed', 'insanity'))
def ow_inverted_rules(world, player):
set_rule(world.get_entrance('Graveyard Ladder (Top)', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Graveyard Ladder (Bottom)', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Pyramid Exit Ledge Drop', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Skull Woods Back Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Forgotten (West) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Forgotten (East) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Portal Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Forgotten (Middle) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Front Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('West Dark Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bubble Boy Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('West Dark Death Mountain (Bottom) Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('East Dark Death Mountain (Top West) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('East Dark Death Mountain (Top East) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('TR Ledge (West) Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -975,246 +894,296 @@ def ow_inverted_rules(world, player):
set_rule(world.get_entrance('East Dark Death Mountain (Bottom Left) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('East Dark Death Mountain (Bottom) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Floating Island Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Death Mountain Teleporter (East)', player), lambda state: state.can_lift_heavy_rocks(player))
if (world.mode[player] == 'inverted') == (0x07 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('TR Pegs Area Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('TR Pegs Teleporter', player), lambda state: state.has('Hammer', player))
else:
set_rule(world.get_entrance('Turtle Rock Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Turtle Rock Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player))
if (world.mode[player] == 'inverted') == (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Mountain Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mountain Entry Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mountain Entry Entrance Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Bumper Cave Area Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bumper Cave Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x0f in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Zora Waterfall Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Catfish Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x10 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Lost Woods Pass West Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pass East Top Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pass East Bottom Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Teleporter (Hammer)', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot lift bushes
set_rule(world.get_entrance('Kakariko Teleporter (Rock)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) # bunny cannot lift bushes
else:
set_rule(world.get_entrance('Skull Woods Pass West Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Pass East Top Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Pass East Bottom Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('West Dark World Teleporter (Hammer)', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player))
set_rule(world.get_entrance('West Dark World Teleporter (Rock)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) # bunny cannot lift bushes
if (world.mode[player] == 'inverted') == (0x11 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Kakariko Fortune Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Outcast Fortune Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x12 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Kakariko Pond Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Outcast Pond Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x13 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Sanctuary Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bonk Rock Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dark Chapel Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Chapel Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x14 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
else:
set_rule(world.get_entrance('Graveyard Ladder (Top)', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Graveyard Ladder (Bottom)', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Dark Graveyard Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Graveyard Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Graveyard Grave Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x15 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('River Bend Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('River Bend East Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Qirn Jump Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Qirn Jump East Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x16 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Potion Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Potion Shop Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dark Witch Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Witch Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x17 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Zora Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Zora Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Catfish Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Catfish Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x18 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Kakariko Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Grass Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Village of Outcasts Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Village of Outcasts Southwest Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hammer House Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x1a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Forgotton Forest Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Forgotton Forest Fence Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Shield Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: False)
set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False)
set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[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('HC Area Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Courtyard Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC East Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Area South Mirror Spot', player), lambda state: state.has_Mirror(player))
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 (Inner)', player), lambda state: state.has('Beat Agahnim 1', player))
else:
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player])
add_rule(world.get_entrance('Pyramid Hole', player), lambda state: False)
set_rule(world.get_entrance('Pyramid Entrance', player), lambda state: False)
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
set_rule(world.get_entrance('Pyramid Exit Ledge Drop', player), lambda state: state.has('Hammer', player))
set_rule(world.get_entrance('Pyramid Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Pyramid Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Pyramid Courtyard Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Pyramid Uncle Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Pyramid From Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Pyramid Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Post Aga Inverted Teleporter', player), lambda state: state.has('Beat Agahnim 1', player))
if (world.mode[player] == 'inverted') == (0x1d in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Wooden Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Wooden Bridge Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Wooden Bridge West Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Broken Bridge West Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Broken Bridge East Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Broken Bridge Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x1e in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Eastern Palace Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Palace of Darkness Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x22 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Blacksmith Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Blacksmith Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bat Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Hammer Pegs Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hammer Pegs Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x25 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Sand Dunes Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dark Dunes Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x28 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Maze Race Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Maze Race Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dig Game Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dig Game Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x29 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Kakariko Suburb Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Suburb South Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Frog Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Frog Prison Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Archery Game Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x2a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Flute Boy Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Flute Boy Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Stumpy Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Stumpy Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x2b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Central Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dark Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x2c in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Links House Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Big Bomb Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x2d in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Stone Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Stone Bridge South Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hobo Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
else:
set_rule(world.get_entrance('Hammer Bridge North Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hammer Bridge South Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Hobo Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
if (world.mode[player] == 'inverted') == (0x2e in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dark Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x2f in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Eastern Nook Mirror Spot', player), lambda state: state.has_Mirror(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_Pearl(player)) # bunny cannot use hammer
else:
set_rule(world.get_entrance('Darkness Nook Mirror Spot', player), lambda state: state.has_Mirror(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_Pearl(player))
if (world.mode[player] == 'inverted') == (0x30 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Checkerboard Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('DP Stairs Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('DP Entrance (North) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bombos Tablet Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
else:
set_rule(world.get_entrance('Misery Mire Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Misery Mire Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Misery Mire Blocked Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Misery Mire Main Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Misery Mire Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
if (world.mode[player] == 'inverted') == (0x32 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Cave 45 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Flute Boy Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Stumpy Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Stumpy Bush Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x33 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
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 Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) # OWG only, can bomb clip out
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 Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
if (world.mode[player] == 'inverted') == (0x34 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Statues Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Hype Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x35 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Lake Hylia Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Water Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Shore Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Shore East Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
else:
set_rule(world.get_entrance('Ice Lake Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Ice Lake Southwest Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Ice Lake Southeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Ice Lake Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Ice Palace Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Ice Palace Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
if (world.mode[player] == 'inverted') == (0x37 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Ice Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Shopping Mall Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Swmap Nook Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x3a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Desert Pass Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Swamp Nook Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Swamp Nook Southeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Swamp Nook Pegs Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x3b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Dam Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Swamp Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x3c in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('South Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Dark South Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x3f in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
set_rule(world.get_entrance('Octoballoon Mirror Spot', player), lambda state: state.has_Mirror(player))
else:
set_rule(world.get_entrance('Bomber Corner Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('West Dark World Teleporter (Hammer)', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player))
set_rule(world.get_entrance('West Dark World Teleporter (Rock)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) # bunny cannot lift bushes
set_rule(world.get_entrance('Post Aga Inverted Teleporter', player), lambda state: state.has('Beat Agahnim 1', 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_Pearl(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 Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Misery Mire Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
set_rule(world.get_entrance('Ice Palace Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
set_rule(world.get_entrance('Dark Death Mountain Teleporter (East)', player), lambda state: state.can_lift_heavy_rocks(player))
set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player))
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player])
add_rule(world.get_entrance('Pyramid Hole', player), lambda state: False)
set_rule(world.get_entrance('Pyramid Entrance', player), lambda state: False)
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
def old_inverted_rules(world, player):
# s&q regions. link's house entrance is set to true so the filler knows the chest inside can always be reached
# overworld requirements
set_rule(world.get_location('Ice Rod Cave', player), lambda state: state.has_Pearl(player))
set_rule(world.get_location('Maze Race', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Mini Moldorm Cave', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Ice Rod Cave', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Light Hype Fairy', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Potion Shop Pier', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player))
set_rule(world.get_entrance('Light World Pier', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player))
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Kings Grave Outer Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Kings Grave Inner Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Potion Shop Inner Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Potion Shop Outer Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Potion Shop Outer Rock', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Potion Shop Inner Rock', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Graveyard Cave Inner Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Graveyard Cave Outer Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Secret Passage Inner Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Secret Passage Outer Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has_Boots(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Bat Cave Drop Ledge', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player))
set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has_Pearl(player) and state.has('Beat Agahnim 1', player))
set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player) and state.has_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('Sanctuary Grave', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('20 Rupee Cave', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('50 Rupee Cave', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Death Mountain Entrance Rock', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Bumper Cave Entrance Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Central Island Mirror Spot', player), lambda state: state.has_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 Desert Teleporter', player), lambda state: state.can_flute(player) and state.can_lift_heavy_rocks(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_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_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_Pearl(player))
set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player) and state.has_Pearl(player))
set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player))
set_rule(world.get_entrance('Waterfall of Wishing Cave', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player))
set_rule(world.get_entrance('Northeast Light World Return', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player))
set_rule(world.get_location('Frog', player), lambda state: state.can_lift_heavy_rocks(player) and
(state.has_Pearl(player) or state.has('Beat Agahnim 1', player)) or (state.can_reach('Light World', 'Region', player)
and state.has_Mirror(player))) # Need LW access using Mirror or Portal
set_rule(world.get_location('Mushroom', player), lambda state: state.has_Pearl(player)) # need pearl to pick up bushes
set_rule(world.get_entrance('Bush Covered Lawn Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bush Covered Lawn Inner Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Bush Covered Lawn Outer Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Bomb Hut Inner Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Bomb Hut Outer Bushes', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Light World Bomb Hut', player), lambda state: state.has_Pearl(player)) # need bomb
set_rule(world.get_entrance('North Fairy Cave Drop', player), lambda state: state.has_Pearl(player))
set_rule(world.get_entrance('Lost Woods Hideout Drop', player), lambda state: state.has_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_entrance('Desert Palace Entrance (North) Rocks', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('Desert Ledge Return Rocks', player), lambda state: state.can_lift_rocks(player) and state.has_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_Pearl(player))
set_rule(world.get_entrance('Hyrule Castle Secret Entrance Drop', player), lambda state: state.has_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('Broken Bridge (West)', player), lambda state: state.has('Hookshot', player) and state.has_Pearl(player))
set_rule(world.get_entrance('Broken Bridge (East)', player), lambda state: state.has('Hookshot', player) and state.has_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('Fairy Ascension Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_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('Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has_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_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_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('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('East Dark World Broken Bridge Pass', player), lambda state: (state.can_lift_rocks(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('Bonk Fairy (Dark)', player), lambda state: state.has_Boots(player))
set_rule(world.get_entrance('West Dark World Gap', player), lambda state: state.has('Hookshot', player))
set_rule(world.get_entrance('Ice Lake Drop (East)', player), lambda state: state.has('Flippers', 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_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 Spike Cave', player), lambda state: state.can_lift_rocks(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 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('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_Mirror(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 Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hammer Peg Area Mirror Spot', player), lambda state: state.has_Mirror(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('Peg Area Rocks', player), lambda state: state.can_lift_heavy_rocks(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('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('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('Hookshot Cave', player), lambda state: state.can_lift_rocks(player))
set_rule(world.get_entrance('East Death Mountain Mirror Spot (Top)', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('East Death Mountain Mirror Spot (Bottom)', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Death Mountain Ledge Mirror Spot (East)', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Death Mountain Ledge Mirror Spot (West)', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Laser Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Floating Island Mirror Spot', player), lambda state: state.has_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 (!)
# 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('Mire Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Palace Stairs Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Death Mountain Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('East Dark World Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('West Dark World Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Dark World Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Catfish Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Potion Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Shopping Mall Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Maze Race Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Palace North Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Graveyard Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bomb Hut Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Mirror Spot', player), lambda state: state.has_Mirror(player))
# inverted flute spots
set_rule(world.get_entrance('DDM Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('NEDW Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('WDW Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('SDW Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('EDW Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('DLHL Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('DD Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('EDDM Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('Dark Grassy Lawn Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('Hammer Peg Area Flute', player), lambda state: state.can_flute(player))
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player])
if world.swords[player] == 'swordless':
swordless_rules(world, player)
set_rule(world.get_entrance('Ganons Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
def ow_bunny_rules(world, player):
add_bunny_rule(world.get_location('Mushroom', player), player)
@@ -1625,6 +1594,7 @@ def standard_rules(world, player):
add_rule(world.get_entrance('Hyrule Castle ES', player), lambda state: state.has('Zelda Delivered', player))
add_rule(world.get_entrance('Hyrule Castle Main Gate (South)', player), lambda state: state.has('Zelda Delivered', player))
add_rule(world.get_entrance('Hyrule Castle Main Gate (North)', player), lambda state: state.has('Zelda Delivered', player))
add_rule(world.get_entrance('Hyrule Castle Ledge Drop', player), lambda state: state.has('Zelda Delivered', player))
def find_rules_for_zelda_delivery(world, player):
@@ -2082,7 +2052,7 @@ def set_inverted_big_bomb_rules(world, player):
else:
raise Exception('No logic found for routing from %s to the pyramid.' % bombshop_entrance.name)
if world.owShuffle[player] != 'vanilla':
if world.owShuffle[player] != 'vanilla' or world.owSwap[player] != 'vanilla':
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: False) #temp disable progression until routing to Pyramid get be guaranteed

View File

@@ -27,7 +27,7 @@ org $02c40a ; < ? - Bank02.asm 10547 ()
jsl.l OWWorldCheck
org $05afd9 ; < ? - sprite_warp_vortex.asm 60 ()
jsl.l OWWorldCheck
org $07a3f0 ; < ? - Bank07.asm 5772 ()
org $07a3f0 ; < ? - Bank07.asm 5772 () ; flute activation/use
jsl.l OWWorldCheck
org $07a967 ; < ? - Bank07.asm 6578 ()
jsl.l OWWorldCheck
@@ -54,6 +54,9 @@ jsl.l OWWorldCheck16 : nop
org $1bed95 ; < ? - palettes.asm 748 ()
jsl.l OWWorldCheck16 : nop
org $02b16e ; AND #$3F : ORA 7EF3CA
and #$7f : eor #$40 : nop #2 ; something to do with mirroring and simply toggling world to opposite one: TODO: better comment
;Code
org $aa8800
OWCoordIndex: ; Horizontal 1st
@@ -94,7 +97,7 @@ org $aa9000
OWEdgeTransition:
{
php : phy
lda.l OWMode : beq +
lda.l OWMode : ora.l OWMode+1 : beq +
jsl OWShuffle : bra .return
+ jsl OWVanilla
.return
@@ -270,7 +273,27 @@ OWNewDestination:
lda $418 : asl : tax : lda $610,x : !add 1,s : sta $610,x : pla
sep #$30 : lda OWOppSlotOffset,y : !add $04 : asl : and #$7f : sta $700
sep #$20 : lda $05 : sta $8a ;: and #$40 : sta.l $7ef3ca ;removed setting DW flag
lda.l OWMode+1 : and #$ff : cmp #$02 : bne .return
ldx $05 : lda.l OWTileWorldAssoc,x : sta.l $7ef3ca ; change world
; toggle bunny mode
lda $7ef357 : bne .nobunny
lda.l InvertedMode : bne .inverted
lda $7ef3ca : and.b #$40 : bra +
.inverted lda $7ef3ca : and.b #$40 : eor #$40
++ cmp #$40 : bne .nobunny
; turn into bunny
lda $5d : cmp #$17 : beq .return
lda #$17 : sta $5d
lda #$01 : sta $02e0
bra .return
.nobunny
lda $5d : cmp #$17 : bne .return
stz $5d : stz $2e0
.return
lda $05 : sta $8a
rep #$30 : rts
}

Binary file not shown.