diff --git a/BaseClasses.py b/BaseClasses.py index 4721ef85..1ed73865 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -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 diff --git a/DoorShuffle.py b/DoorShuffle.py index 55e481b4..3478d027 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -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) diff --git a/Main.py b/Main.py index f4f9c371..96fbe6c2 100644 --- a/Main.py +++ b/Main.py @@ -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}' diff --git a/OWEdges.py b/OWEdges.py index 2a912280..671f3609 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -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', diff --git a/OverworldShuffle.py b/OverworldShuffle.py index c6ad8310..f8467346 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -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' @@ -10,22 +10,155 @@ def link_overworld(world, player): connect_simple(world, exitname, regionname, player) for exitname, destname in temporary_mandatory_connections: connect_two_way(world, exitname, destname, player) + + # 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 - if world.mode[player] != 'inverted': - for exitname, regionname in open_connections: - connect_simple(world, exitname, regionname, player) - else: - for exitname, regionname in inverted_connections: - connect_simple(world, exitname, regionname, player) + #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 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,11 +187,14 @@ 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 def connect_custom(world, connected_edges, player): @@ -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,159 +272,151 @@ 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 - new_grouping = {} + for grouping in (groups,): + new_grouping = {} - for group in grouping.keys(): - (std, region, axis, terrain, _, count) = group - new_grouping[(std, region, axis, terrain, count)] = ([], []) - - for group in grouping.keys(): - (std, region, axis, terrain, _, count) = group - (forward_edges, back_edges) = grouping[group] - (exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, count)] - exist_forward_edges.extend(forward_edges) - exist_back_edges.extend(back_edges) - new_grouping[(std, region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges) + for group in grouping.keys(): + (std, region, axis, terrain, _, count) = group + new_grouping[(std, region, axis, terrain, count)] = ([], []) + + for group in grouping.keys(): + (std, region, axis, terrain, _, count) = group + (forward_edges, back_edges) = grouping[group] + (exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, count)] + exist_forward_edges.extend(forward_edges) + exist_back_edges.extend(back_edges) + new_grouping[(std, region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges) - return list(new_grouping.values()) + 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 - new_grouping = {} + for grouping in (groups,): + new_grouping = {} - for group in grouping.keys(): - (_, region, axis, terrain, _, count) = group - new_grouping[(region, axis, terrain, count)] = ([], []) - - for group in grouping.keys(): - (_, region, axis, terrain, _, count) = group - (forward_edges, back_edges) = grouping[group] - (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, count)] - exist_forward_edges.extend(forward_edges) - exist_back_edges.extend(back_edges) - new_grouping[(region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges) + for group in grouping.keys(): + (_, region, axis, terrain, _, count) = group + new_grouping[(region, axis, terrain, count)] = ([], []) + + for group in grouping.keys(): + (_, region, axis, terrain, _, count) = group + (forward_edges, back_edges) = grouping[group] + (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, count)] + exist_forward_edges.extend(forward_edges) + exist_back_edges.extend(back_edges) + new_grouping[(region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges) - return list(new_grouping.values()) + return list(new_grouping.values()) 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 - new_grouping = {} + for grouping in (groups,): + new_grouping = {} - for group in grouping.keys(): - (std, region, axis, terrain, _, _) = group - new_grouping[(std, region, axis, terrain)] = ([], []) + for group in grouping.keys(): + (std, region, axis, terrain, _, _) = group + new_grouping[(std, region, axis, terrain)] = ([], []) + + for group in grouping.keys(): + (std, region, axis, terrain, _, _) = group + (forward_edges, back_edges) = grouping[group] + forward_edges = [[i] for l in forward_edges for i in l] + back_edges = [[i] for l in back_edges for i in l] - for group in grouping.keys(): - (std, region, axis, terrain, _, _) = group - (forward_edges, back_edges) = grouping[group] - forward_edges = [[i] for l in forward_edges for i in l] - back_edges = [[i] for l in back_edges for i in l] - - (exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain)] - exist_forward_edges.extend(forward_edges) - exist_back_edges.extend(back_edges) - new_grouping[(std, region, axis, terrain)] = (exist_forward_edges, exist_back_edges) + (exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain)] + exist_forward_edges.extend(forward_edges) + exist_back_edges.extend(back_edges) + new_grouping[(std, region, axis, terrain)] = (exist_forward_edges, exist_back_edges) - return list(new_grouping.values()) + 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 - new_grouping = {} + for grouping in (groups,): + new_grouping = {} - for group in grouping.keys(): - (_, region, axis, terrain, _, _) = group - new_grouping[(region, axis, terrain)] = ([], []) + for group in grouping.keys(): + (_, region, axis, terrain, _, _) = group + new_grouping[(region, axis, terrain)] = ([], []) + + for group in grouping.keys(): + (_, region, axis, terrain, _, _) = group + (forward_edges, back_edges) = grouping[group] + forward_edges = [[i] for l in forward_edges for i in l] + back_edges = [[i] for l in back_edges for i in l] - for group in grouping.keys(): - (_, region, axis, terrain, _, _) = group - (forward_edges, back_edges) = grouping[group] - forward_edges = [[i] for l in forward_edges for i in l] - back_edges = [[i] for l in back_edges for i in l] - - (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain)] - exist_forward_edges.extend(forward_edges) - exist_back_edges.extend(back_edges) - new_grouping[(region, axis, terrain)] = (exist_forward_edges, exist_back_edges) + (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain)] + exist_forward_edges.extend(forward_edges) + exist_back_edges.extend(back_edges) + new_grouping[(region, axis, terrain)] = (exist_forward_edges, exist_back_edges) - return list(new_grouping.values()) + return list(new_grouping.values()) elif world.owShuffle[player] == 'parallel': #predefined shuffle groups get reorganized here 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 - return list(grouping.values()) + 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 - new_grouping = {} + for grouping in (groups,): + new_grouping = {} - for group in grouping.keys(): - (_, region, axis, terrain, parallel, count) = group - new_grouping[(region, axis, terrain, parallel, count)] = ([], []) - - for group in grouping.keys(): - (_, region, axis, terrain, parallel, count) = group - (forward_edges, back_edges) = grouping[group] - (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel, count)] - exist_forward_edges.extend(forward_edges) - exist_back_edges.extend(back_edges) - new_grouping[(region, axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges) + for group in grouping.keys(): + (_, region, axis, terrain, parallel, count) = group + new_grouping[(region, axis, terrain, parallel, count)] = ([], []) + + for group in grouping.keys(): + (_, region, axis, terrain, parallel, count) = group + (forward_edges, back_edges) = grouping[group] + (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel, count)] + exist_forward_edges.extend(forward_edges) + exist_back_edges.extend(back_edges) + new_grouping[(region, axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges) - return list(new_grouping.values()) + return list(new_grouping.values()) 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 - new_grouping = {} + for grouping in (groups,): + new_grouping = {} - for group in grouping.keys(): - (std, region, axis, terrain, parallel, _) = group - new_grouping[(std, region, axis, terrain, parallel)] = ([], []) + for group in grouping.keys(): + (std, region, axis, terrain, parallel, _) = group + new_grouping[(std, region, axis, terrain, parallel)] = ([], []) + + for group in grouping.keys(): + (std, region, axis, terrain, parallel, _) = group + (forward_edges, back_edges) = grouping[group] + forward_edges = [[i] for l in forward_edges for i in l] + back_edges = [[i] for l in back_edges for i in l] - for group in grouping.keys(): - (std, region, axis, terrain, parallel, _) = group - (forward_edges, back_edges) = grouping[group] - forward_edges = [[i] for l in forward_edges for i in l] - back_edges = [[i] for l in back_edges for i in l] - - (exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, parallel)] - exist_forward_edges.extend(forward_edges) - exist_back_edges.extend(back_edges) - new_grouping[(std, region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges) + (exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, parallel)] + exist_forward_edges.extend(forward_edges) + exist_back_edges.extend(back_edges) + new_grouping[(std, region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges) - return list(new_grouping.values()) + 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 - new_grouping = {} + for grouping in (groups,): + new_grouping = {} - for group in grouping.keys(): - (_, region, axis, terrain, parallel, _) = group - new_grouping[(region, axis, terrain, parallel)] = ([], []) + for group in grouping.keys(): + (_, region, axis, terrain, parallel, _) = group + new_grouping[(region, axis, terrain, parallel)] = ([], []) + + for group in grouping.keys(): + (_, region, axis, terrain, parallel, _) = group + (forward_edges, back_edges) = grouping[group] + forward_edges = [[i] for l in forward_edges for i in l] + back_edges = [[i] for l in back_edges for i in l] - for group in grouping.keys(): - (_, region, axis, terrain, parallel, _) = group - (forward_edges, back_edges) = grouping[group] - forward_edges = [[i] for l in forward_edges for i in l] - back_edges = [[i] for l in back_edges for i in l] - - (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel)] - exist_forward_edges.extend(forward_edges) - exist_back_edges.extend(back_edges) - new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges) + (exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel)] + exist_forward_edges.extend(forward_edges) + exist_back_edges.extend(back_edges) + new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges) - return list(new_grouping.values()) + return list(new_grouping.values()) else: raise NotImplementedError('Shuffling not supported yet') @@ -535,259 +666,364 @@ 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'), - - # Mirror Connections - ('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'), - ('Spectacle Rock Mirror Spot', 'Spectacle Rock Ledge'), - ('West Death Mountain (Top) Mirror Spot', 'West Death Mountain (Top)'), - ('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'), - ('Mimic Cave Mirror Spot', 'Mimic Cave Ledge'), - ('Isolated Ledge Mirror Spot', 'Fairy Ascension Ledge'), - ('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'), +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']) + } - # 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'), - ('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'), - ('TR Ledge (East) Mirror Spot', 'Dark Death Mountain Ledge'), - ('TR Isolated Mirror Spot', 'Dark Death Mountain Isolated Ledge'), - ('East Dark Death Mountain (Bottom Plateau) Mirror Spot', 'East 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'), - ('Turtle Rock Mirror Spot', 'Turtle Rock Area'), - ('Turtle Rock Ledge Mirror Spot', 'Turtle Rock 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'), - ('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'), - ('Dark Chapel Mirror Spot', 'Dark Chapel Area'), - ('Dark Chapel Ledge Mirror Spot', 'Dark Chapel Area'), - ('Dark Graveyard Mirror Spot', 'Dark Graveyard Area'), - ('Dark Graveyard Ledge Mirror Spot', 'Dark Graveyard Area'), - ('Dark Graveyard Grave Mirror Spot', 'Dark Graveyard Area'), - ('Qirn Jump Mirror Spot', 'Qirn Jump Area'), - ('Qirn Jump East Mirror Spot', 'Qirn Jump East Bank'), - ('Dark Witch Mirror Spot', 'Dark Witch Area'), - ('Dark Witch Northeast Mirror Spot', 'Dark Witch Northeast'), - ('Catfish Approach Mirror Spot', 'Catfish Approach Area'), - ('Catfish Approach Ledge Mirror Spot', 'Catfish Approach Ledge'), - ('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'), - ('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'), - ('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'), - ('Hammer Pegs Mirror Spot', 'Hammer Peg Area'), - ('Hammer Pegs Entry Mirror Spot', 'Hammer Peg Entry'), - ('Dark Dunes Mirror Spot', 'Dark Dunes Area'), - ('Dig Game Mirror Spot', 'Dig Game Area'), - ('Dig Game Ledge Mirror Spot', 'Dig Game Ledge'), - ('Frog Mirror Spot', 'Frog Area'), - ('Frog Prison Mirror Spot', 'Frog Prison'), - ('Archery Game Mirror Spot', 'Archery Game Area'), - ('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'), - ('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'), - ('Darkness Nook Mirror Spot', 'Palace of Darkness Nook 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'), - ('Stumpy Approach Mirror Spot', 'Stumpy Approach Area'), - ('Stumpy Bush Entry Mirror Spot', 'Stumpy Approach Bush Entry'), - ('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'), - ('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'), - ('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') - ] +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') + ], [ + ('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'), + ('Mimic Cave Mirror Spot', 'Mimic Cave Ledge'), + ('Isolated Ledge Mirror Spot', 'Fairy Ascension Ledge'), + ('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'), + ('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)'), + ('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'), + ('TR Ledge (East) Mirror Spot', 'Dark Death Mountain Ledge'), + ('TR Isolated Mirror Spot', 'Dark Death Mountain Isolated Ledge'), + ('East Dark Death Mountain (Bottom Plateau) Mirror Spot', 'East 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') + ]), + 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'), + ('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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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') + ]), + 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'), + ('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'), + ('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') + ]), + 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'), diff --git a/Regions.py b/Regions.py index f0315796..bbec1ca0 100644 --- a/Regions.py +++ b/Regions.py @@ -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']), diff --git a/Rom.py b/Rom.py index 9f5ba574..fdc5a39a 100644 --- a/Rom.py +++ b/Rom.py @@ -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,211 +2242,265 @@ 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): - v = rom.buffer[0x153B00 + b] - rom.buffer[0x153B00 + b] = (v & 0xFE) | ((v + 1) % 2) + 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(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_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) - write_int16(rom, snes_to_pc(0x02D936), 0x229A) - write_int16(rom, snes_to_pc(0x02D944), 0x0480) - write_int16(rom, snes_to_pc(0x02D952), 0x00A5) - write_int16(rom, snes_to_pc(0x02D960), 0x007F) - rom.write_byte(snes_to_pc(0x02D96D), 0x14) - rom.write_byte(snes_to_pc(0x02D974), 0x00) - rom.write_byte(snes_to_pc(0x02D97B), 0xFF) - rom.write_byte(snes_to_pc(0x02D982), 0x00) - rom.write_byte(snes_to_pc(0x02D989), 0x02) - rom.write_byte(snes_to_pc(0x02D990), 0x00) - 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] 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(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) - write_int16(rom, snes_to_pc(0x02D940), 0x1FC0) - write_int16(rom, snes_to_pc(0x02D94E), 0x0378) - write_int16(rom, snes_to_pc(0x02D95C), 0x0187) - write_int16(rom, snes_to_pc(0x02D96A), 0x017F) - rom.write_byte(snes_to_pc(0x02D972), 0x06) - rom.write_byte(snes_to_pc(0x02D979), 0x00) - rom.write_byte(snes_to_pc(0x02D980), 0xFF) - rom.write_byte(snes_to_pc(0x02D987), 0x00) - rom.write_byte(snes_to_pc(0x02D98E), 0x22) - rom.write_byte(snes_to_pc(0x02D995), 0x12) - 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]) - 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) - write_int16(rom, 0x15C79 + 2 * 0x06, 0x0610) - write_int16(rom, 0x15D17 + 2 * 0x06, 0x077E) - write_int16(rom, 0x15DB5 + 2 * 0x06, 0x0672) - write_int16(rom, 0x15E53 + 2 * 0x06, 0x07F8) - write_int16(rom, 0x15EF1 + 2 * 0x06, 0x067D) - write_int16(rom, 0x15F8F + 2 * 0x06, 0x0803) - rom.write_byte(0x1602D + 0x06, 0x00) - 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(0x02E89D), 0x0610) - write_int16(rom, snes_to_pc(0x02E8BF), 0x077E) - write_int16(rom, snes_to_pc(0x02E8E1), 0x0672) - write_int16(rom, snes_to_pc(0x02E903), 0x07F8) - write_int16(rom, snes_to_pc(0x02E925), 0x067D) - 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) - 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]) - write_int16s(rom, snes_to_pc(0x0FF1C8), [0x190F, 0x190F, 0x190F, 0x194C, 0x190F, - 0x194B, 0x190F, 0x195C, 0x594B, 0x194C, - 0x19EE, 0x19EE, 0x194B, 0x19EE, 0x19EE, - 0x19EE, 0x594B, 0x190F, 0x595C, 0x190F, - 0x190F, 0x195B, 0x190F, 0x190F, 0x19EE, - 0x19EE, 0x195C, 0x19EE, 0x19EE, 0x19EE, - 0x19EE, 0x595C, 0x595B, 0x190F, 0x190F, - 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_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) - write_int16(rom, snes_to_pc(0x1af50c), 0x149B) - write_int16(rom, snes_to_pc(0x1af514), 0x14A4) - write_int16(rom, snes_to_pc(0x1af51c), 0x1489) - write_int16(rom, snes_to_pc(0x1af524), 0x14AC) - write_int16(rom, snes_to_pc(0x1af52c), 0x54AC) - write_int16(rom, snes_to_pc(0x1af534), 0x148C) - write_int16(rom, snes_to_pc(0x1af53c), 0x548C) - write_int16(rom, snes_to_pc(0x1af544), 0x1484) - write_int16(rom, snes_to_pc(0x1af54c), 0x5484) - write_int16(rom, snes_to_pc(0x1af554), 0x14A2) - write_int16(rom, snes_to_pc(0x1af55c), 0x54A2) - write_int16(rom, snes_to_pc(0x1af564), 0x14A0) - write_int16(rom, snes_to_pc(0x1af56c), 0x54A0) - write_int16(rom, snes_to_pc(0x1af574), 0x148E) - 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]) - 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) - write_int16(rom, 0x15BDB + 2 * 0x37, 0x000E) - write_int16(rom, 0x15C79 + 2 * 0x37, 0x0600) - write_int16(rom, 0x15D17 + 2 * 0x37, 0x0676) - write_int16(rom, 0x15DB5 + 2 * 0x37, 0x0604) - write_int16(rom, 0x15E53 + 2 * 0x37, 0x06E8) - write_int16(rom, 0x15EF1 + 2 * 0x37, 0x066D) - write_int16(rom, 0x15F8F + 2 * 0x37, 0x06F3) - rom.write_byte(0x1602D + 0x37, 0x00) - 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]) + 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) # dark-style portal + rom.write_byte(snes_to_pc(0x0DB3C5), 0xC6) #vortex + + rom.write_byte(snes_to_pc(0x07A3F4), 0xF0) # duck + 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) + write_int16(rom, snes_to_pc(0x02D936), 0x229A) + write_int16(rom, snes_to_pc(0x02D944), 0x0480) + write_int16(rom, snes_to_pc(0x02D952), 0x00A5) + write_int16(rom, snes_to_pc(0x02D960), 0x007F) + rom.write_byte(snes_to_pc(0x02D96D), 0x14) + rom.write_byte(snes_to_pc(0x02D974), 0x00) + rom.write_byte(snes_to_pc(0x02D97B), 0xFF) + rom.write_byte(snes_to_pc(0x02D982), 0x00) + rom.write_byte(snes_to_pc(0x02D989), 0x02) + rom.write_byte(snes_to_pc(0x02D990), 0x00) + write_int16(rom, snes_to_pc(0x02D998), 0x0000) + write_int16(rom, snes_to_pc(0x02D9A6), 0x005A) + rom.write_byte(snes_to_pc(0x02D9B3), 0x12) + + 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]) # 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) + write_int16(rom, snes_to_pc(0x02D940), 0x1FC0) + write_int16(rom, snes_to_pc(0x02D94E), 0x0378) + write_int16(rom, snes_to_pc(0x02D95C), 0x0187) + write_int16(rom, snes_to_pc(0x02D96A), 0x017F) + rom.write_byte(snes_to_pc(0x02D972), 0x06) + rom.write_byte(snes_to_pc(0x02D979), 0x00) + rom.write_byte(snes_to_pc(0x02D980), 0xFF) + rom.write_byte(snes_to_pc(0x02D987), 0x00) + rom.write_byte(snes_to_pc(0x02D98E), 0x22) + rom.write_byte(snes_to_pc(0x02D995), 0x12) + 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]) #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) + write_int16(rom, 0x15C79 + 2 * 0x06, 0x0610) + write_int16(rom, 0x15D17 + 2 * 0x06, 0x077E) + write_int16(rom, 0x15DB5 + 2 * 0x06, 0x0672) + write_int16(rom, 0x15E53 + 2 * 0x06, 0x07F8) + write_int16(rom, 0x15EF1 + 2 * 0x06, 0x067D) + write_int16(rom, 0x15F8F + 2 * 0x06, 0x0803) + rom.write_byte(0x1602D + 0x06, 0x00) + 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(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) + write_int16(rom, snes_to_pc(0x02E903), 0x07F8) + write_int16(rom, snes_to_pc(0x02E925), 0x067D) + write_int16(rom, snes_to_pc(0x02E947), 0x0803) + write_int16(rom, snes_to_pc(0x02E969), 0x0000) + write_int16(rom, snes_to_pc(0x02E98B), 0xFFF2) + + #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, + 0x19EE, 0x594B, 0x190F, 0x595C, 0x190F, + 0x190F, 0x195B, 0x190F, 0x190F, 0x19EE, + 0x19EE, 0x195C, 0x19EE, 0x19EE, 0x19EE, + 0x19EE, 0x595C, 0x595B, 0x190F, 0x190F, + 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]) # 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) + + 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) + write_int16(rom, snes_to_pc(0x1af524), 0x14AC) + write_int16(rom, snes_to_pc(0x1af52c), 0x54AC) + write_int16(rom, snes_to_pc(0x1af534), 0x148C) + write_int16(rom, snes_to_pc(0x1af53c), 0x548C) + write_int16(rom, snes_to_pc(0x1af544), 0x1484) + write_int16(rom, snes_to_pc(0x1af54c), 0x5484) + write_int16(rom, snes_to_pc(0x1af554), 0x14A2) + write_int16(rom, snes_to_pc(0x1af55c), 0x54A2) + write_int16(rom, snes_to_pc(0x1af564), 0x14A0) + write_int16(rom, snes_to_pc(0x1af56c), 0x54A0) + write_int16(rom, snes_to_pc(0x1af574), 0x148E) + 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(0xF6E58, 0x80) # no whirlpool under castle gate + 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) + + 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) + write_int16(rom, 0x15BDB + 2 * 0x37, 0x000E) + write_int16(rom, 0x15C79 + 2 * 0x37, 0x0600) + write_int16(rom, 0x15D17 + 2 * 0x37, 0x0676) + write_int16(rom, 0x15DB5 + 2 * 0x37, 0x0604) + write_int16(rom, 0x15E53 + 2 * 0x37, 0x06E8) + write_int16(rom, 0x15EF1 + 2 * 0x37, 0x066D) + write_int16(rom, 0x15F8F + 2 * 0x37, 0x06F3) + rom.write_byte(0x1602D + 0x37, 0x00) + rom.write_byte(0x1607C + 0x37, 0x0A) + write_int16(rom, 0x160CB + 2 * 0x37, 0x0000) + write_int16(rom, 0x16169 + 2 * 0x37, 0x811c) + 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) dark_sanc_entrance = str([i for i in dark_sanc.entrances if i.parent_region.name != 'Menu'][0].name) diff --git a/Rules.py b/Rules.py index 3c03f045..a87a2493 100644 --- a/Rules.py +++ b/Rules.py @@ -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,382 +842,348 @@ def default_rules(world, player): swordless_rules(world, player) -def ow_open_rules(world, player): - 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)) - set_rule(world.get_entrance('Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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)) - 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)) - set_rule(world.get_entrance('Spiral Cave Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Fairy Ascension Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player)) # need to lift flowers - 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)) +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)) + set_rule(world.get_entrance('Spiral Cave Mirror Spot', player), lambda state: state.has_Mirror(player)) + set_rule(world.get_entrance('Fairy Ascension Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player)) # need to lift flowers + 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('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(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)) + set_rule(world.get_entrance('TR Ledge (East) Mirror Spot', player), lambda state: state.has_Mirror(player)) + set_rule(world.get_entrance('TR Isolated Mirror Spot', player), lambda state: state.has_Mirror(player)) + set_rule(world.get_entrance('East Dark Death Mountain (Bottom Plateau) Mirror Spot', player), lambda state: state.has_Mirror(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)) + + 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('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)) - 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)) - set_rule(world.get_entrance('TR Ledge (East) Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('TR Isolated Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('East Dark Death Mountain (Bottom Plateau) Mirror Spot', player), lambda state: state.has_Mirror(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('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('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)) - set_rule(world.get_entrance('Catfish Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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('Outcast Fortune Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Outcast Pond Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - set_rule(world.get_entrance('Shield Shop Mirror Spot', player), lambda state: state.has_Mirror(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('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)) - set_rule(world.get_entrance('Palace of Darkness Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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)) - set_rule(world.get_entrance('Dark Dunes Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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)) - 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)) - 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)) - set_rule(world.get_entrance('Dark Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Big Bomb Shop Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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)) - set_rule(world.get_entrance('Dark Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Darkness Nook Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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('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)) - 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('Hype Cave Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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('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)) - 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)) - set_rule(world.get_entrance('Swamp Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Dark South Pass Mirror Spot', player), lambda state: state.has_Mirror(player)) - 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 diff --git a/asm/owrando.asm b/asm/owrando.asm index 962ed005..2147a544 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -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 } diff --git a/data/base2current.bps b/data/base2current.bps index 923e8960..eacabeae 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ