diff --git a/BaseClasses.py b/BaseClasses.py index 25aebbb1..08ccdd93 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -87,6 +87,7 @@ class World(object): self.owedges = [] self._owedge_cache = {} self.owswaps = {} + self.owcrossededges = {} self.owwhirlpools = {} self.owflutespots = {} self.owsectors = {} @@ -114,6 +115,7 @@ class World(object): set_player_attr('_region_cache', {}) set_player_attr('player_names', []) set_player_attr('owswaps', [[],[],[]]) + set_player_attr('owcrossededges', []) set_player_attr('owwhirlpools', []) set_player_attr('owsectors', None) set_player_attr('remote_items', False) @@ -238,29 +240,16 @@ class World(object): raise RuntimeError('No such region %s for player %d' % (regionname, player)) def get_owedge(self, edgename, player): - if isinstance(edgename, OWEdge): - return edgename - try: - return self._owedge_cache[(edgename, player)] - except KeyError: - for edge in self.owedges: - if edge.name == edgename and edge.player == player: - self._owedge_cache[(edgename, player)] = edge - return edge + edge = self.check_for_owedge(edgename, player) + if edge is None: raise RuntimeError('No such edge %s for player %d' % (edgename, player)) + return edge def get_entrance(self, entrance, player): - if isinstance(entrance, Entrance): - return entrance - try: - return self._entrance_cache[(entrance, player)] - except KeyError: - for region in self.regions: - for exit in region.exits: - if exit.name == entrance and exit.player == player: - self._entrance_cache[(entrance, player)] = exit - return exit + ent = self.check_for_entrance(entrance, player) + if ent is None: raise RuntimeError('No such entrance %s for player %d' % (entrance, player)) + return ent def remove_entrance(self, entrance, player): if (entrance, player) in self._entrance_cache.keys(): @@ -294,16 +283,10 @@ class World(object): raise RuntimeError('No such dungeon %s for player %d' % (dungeonname, player)) def get_door(self, doorname, player): - if isinstance(doorname, Door): - return doorname - try: - return self._door_cache[(doorname, player)] - except KeyError: - for door in self.doors: - if door.name == doorname and door.player == player: - self._door_cache[(doorname, player)] = door - return door + door = self.check_for_door(doorname, player) + if door is None: raise RuntimeError('No such door %s for player %d' % (doorname, player)) + return door def get_portal(self, portal_name, player): if isinstance(portal_name, Portal): @@ -317,18 +300,6 @@ class World(object): return portal raise RuntimeError('No such portal %s for player %d' % (portal_name, player)) - def check_for_owedge(self, edgename, player): - if isinstance(edgename, OWEdge): - return edgename - try: - return self._owedge_cache[(edgename, player)] - except KeyError: - for edge in self.owedges: - if edge.name == edgename and edge.player == player: - self._owedge_cache[(edgename, player)] = edge - return edge - return None - def is_tile_swapped(self, owid, player): return (self.mode[player] == 'inverted') != (owid in self.owswaps[player][0] and self.owMixed[player]) @@ -354,6 +325,28 @@ class World(object): else: return False + def check_for_owedge(self, edgename, player): + if isinstance(edgename, OWEdge): + return edgename + try: + if edgename[-1] == '*': + edgename = edgename[:-1] + edge = self.check_for_owedge(edgename, player) + if self.is_tile_swapped(edge.owIndex, player): + from OverworldShuffle import parallel_links + if edgename in parallel_links.keys() or edgename in parallel_links.inverse.keys(): + edgename = parallel_links[edgename] if edgename in parallel_links.keys() else parallel_links.inverse[edgename][0] + return self.check_for_owedge(edgename, player) + else: + raise Exception("Edge notated with * doesn't have a parallel edge: %s" & edgename) + return self._owedge_cache[(edgename, player)] + except KeyError: + for edge in self.owedges: + if edge.name == edgename and edge.player == player: + self._owedge_cache[(edgename, player)] = edge + return edge + return None + def check_for_door(self, doorname, player): if isinstance(doorname, Door): return doorname @@ -2248,7 +2241,7 @@ class OWEdge(object): self.unknownX = 0x0 self.unknownY = 0x0 - if self.owIndex < 0x40 or self.owIndex >= 0x80: + if self.owIndex & 0x40 == 0: self.worldType = WorldType.Light else: self.worldType = WorldType.Dark @@ -2289,6 +2282,12 @@ class OWEdge(object): self.specialID = special_id return self + def is_tile_swapped(self, world): + return world.is_tile_swapped(self.owIndex, self.player) + + def is_lw(self, world): + return (self.worldType == WorldType.Light) != self.is_tile_swapped(world) + def __eq__(self, other): return isinstance(other, self.__class__) and self.name == other.name @@ -2784,6 +2783,7 @@ class Spoiler(object): self.world = world self.hashes = {} self.overworlds = {} + self.whirlpools = {} self.maps = {} self.entrances = {} self.doors = {} @@ -2808,6 +2808,12 @@ class Spoiler(object): else: self.overworlds[(entrance, direction, player)] = OrderedDict([('player', player), ('entrance', entrance), ('exit', exit), ('direction', direction)]) + def set_whirlpool(self, entrance, exit, direction, player): + if self.world.players == 1: + self.whirlpools[(entrance, direction, player)] = OrderedDict([('entrance', entrance), ('exit', exit), ('direction', direction)]) + else: + self.whirlpools[(entrance, direction, player)] = OrderedDict([('player', player), ('entrance', entrance), ('exit', exit), ('direction', direction)]) + def set_map(self, type, text, data, player): if self.world.players == 1: self.maps[(type, player)] = OrderedDict([('type', type), ('text', text), ('data', data)]) @@ -3010,6 +3016,7 @@ class Spoiler(object): self.parse_data() out = OrderedDict() out['Overworld'] = list(self.overworlds.values()) + out['Whirlpools'] = list(self.whirlpools.values()) out['Maps'] = list(self.maps.values()) out['Entrances'] = list(self.entrances.values()) out['Doors'] = list(self.doors.values()) @@ -3181,46 +3188,50 @@ class Spoiler(object): for fairy, bottle in self.bottles.items(): outfile.write(f'{fairy}: {bottle}\n') - if self.overworlds or self.maps: - outfile.write('\n\nOverworld:\n\n') - + if self.maps: # flute shuffle for player in range(1, self.world.players + 1): if ('flute', player) in self.maps: - outfile.write('Flute Spots:\n') + outfile.write('\n\nFlute Spots:\n\n') break for player in range(1, self.world.players + 1): if ('flute', player) in self.maps: if self.world.players > 1: outfile.write(str('(Player ' + str(player) + ')\n')) # player name - outfile.write(self.maps[('flute', player)]['text'] + '\n\n') + outfile.write(self.maps[('flute', player)]['text']) # overworld tile flips for player in range(1, self.world.players + 1): if ('swaps', player) in self.maps: - outfile.write('OW Tile Flips:\n') + outfile.write('\n\nOW Tile Flips:\n\n') break for player in range(1, self.world.players + 1): if ('swaps', player) in self.maps: if self.world.players > 1: outfile.write(str('(Player ' + str(player) + ')\n')) # player name - outfile.write(self.maps[('swaps', player)]['text'] + '\n\n') + outfile.write(self.maps[('swaps', player)]['text']) # crossed groups for player in range(1, self.world.players + 1): if ('groups', player) in self.maps: - outfile.write('OW Crossed Groups:\n') + outfile.write('\n\nOW Crossed Groups:\n\n') break for player in range(1, self.world.players + 1): if ('groups', player) in self.maps: if self.world.players > 1: outfile.write(str('(Player ' + str(player) + ')\n')) # player name - outfile.write(self.maps[('groups', player)]['text'] + '\n\n') + outfile.write(self.maps[('groups', player)]['text']) if self.overworlds: + outfile.write('\n\nOverworld Edges:\n\n') # overworld transitions outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta","overworlds",entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta","overworlds",entry['exit'])) for entry in self.overworlds.values()])) + if self.whirlpools: + outfile.write('\n\nWhirlpools:\n\n') + # whirlpools + outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta","whirlpools",entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta","whirlpools",entry['exit'])) for entry in self.whirlpools.values()])) + if self.entrances: # entrances: To/From overworld; Checking w/ & w/out "Exit" and translating accordingly outfile.write('\n\nEntrances:\n\n') @@ -3451,7 +3462,7 @@ boss_mode = {"none": 0, "simple": 1, "full": 2, "chaos": 3, 'random': 3, 'unique # byte 11: OOOT WCCC (OWR layout, free terrain, whirlpools, OWR crossed) or_mode = {"vanilla": 0, "parallel": 1, "full": 2} -orcrossed_mode = {"none": 0, "polar": 1, "grouped": 2, "limited": 3, "chaos": 4} +orcrossed_mode = {"none": 0, "polar": 1, "grouped": 2, "unrestricted": 4} # byte 12: KMB? FF?? (keep similar, mixed/tile flip, bonk drops, flute spots) flutespot_mode = {"vanilla": 0, "balanced": 1, "random": 2} diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f1c8fbb..041d2816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.3.3.0 +- Added Customizer support for all remaining OWR options +- Added several OWR preset yamls (many ideas are thanks to Catobat) +- Fixed issue with Mixed OWR + Flute Shuffle placing spots on large screens +- Removed Limited Crossed OWR and renamed Chaos Crossed to Unrestricted Crossed + ## 0.3.2.2 - Added Customizer support for Flute Shuffle (thanks Catobat) - Fixed bad Old Man rescue possibility in Swapped ER diff --git a/ItemList.py b/ItemList.py index c6462f62..fcbffadf 100644 --- a/ItemList.py +++ b/ItemList.py @@ -543,7 +543,7 @@ def set_up_take_anys(world, player, skip_adjustments=False): else: if world.shopsanity[player] and not skip_adjustments: world.itempool.append(ItemFactory('Rupees (300)', player)) - old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0, create_location=world.shopsanity[player]) + old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0, create_location=True) take_any_type = ShopType.Shop if world.shopsanity[player] else ShopType.TakeAny for num in range(4): @@ -558,7 +558,7 @@ def set_up_take_anys(world, player, skip_adjustments=False): take_any.shop = Shop(take_any, room_id, take_any_type, 0xE3, True, not world.shopsanity[player], 33 + num*2) world.shops[player].append(take_any.shop) take_any.shop.add_inventory(0, 'Blue Potion', 0, 0, create_location=world.shopsanity[player]) - take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0, create_location=world.shopsanity[player]) + take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0, create_location=True) if world.shopsanity[player] and not skip_adjustments: world.itempool.append(ItemFactory('Blue Potion', player)) world.itempool.append(ItemFactory('Boss Heart Container', player)) diff --git a/OWEdges.py b/OWEdges.py index f4da280e..751bd307 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -332,8 +332,8 @@ def create_owedge(player, name, owIndex, direction, terrain, edge_id, owSlotInde OWEdgeGroups = { - #(IsStandard, World, EdgeAxis, Terrain, HasParallel, NumberInGroup) - (St, LW, Vt, Ld, PL, 1): ( + #(IsStandard, World, EdgeAxis, Terrain, HasParallel, NumberInGroup, CustomizerGroup) + (St, LW, Vt, Ld, PL, 1, None): ( [ ['Hyrule Castle SW'], ['Hyrule Castle SE'] @@ -343,7 +343,7 @@ OWEdgeGroups = { ['Links House NE'] ] ), - (St, LW, Hz, Ld, PL, 3): ( + (St, LW, Hz, Ld, PL, 3, None): ( [ ['Central Bonk Rocks EN', 'Central Bonk Rocks EC', 'Central Bonk Rocks ES'] ], @@ -351,7 +351,7 @@ OWEdgeGroups = { ['Links House WN', 'Links House WC', 'Links House WS'] ] ), - (Op, LW, Hz, Ld, PL, 1): ( + (Op, LW, Hz, Ld, PL, 1, None): ( [ ['Lost Woods EN'], ['East Death Mountain EN'], @@ -391,7 +391,7 @@ OWEdgeGroups = { ['East Death Mountain WS'] ] ), - (Op, LW, Hz, Ld, NP, 1): ( + (Op, LW, Hz, Ld, NP, 1, None): ( [ ['Forgotten Forest ES'] ], @@ -399,7 +399,7 @@ OWEdgeGroups = { ['Hyrule Castle WN'] ] ), - (Op, LW, Vt, Ld, PL, 1): ( + (Op, LW, Vt, Ld, PL, 1, None): ( [ ['Lumberjack SW'], ['Mountain Pass SE'], @@ -439,7 +439,7 @@ OWEdgeGroups = { ['Octoballoon NE'] ] ), - (Op, LW, Vt, Ld, NP, 1): ( + (Op, LW, Vt, Ld, NP, 1, None): ( [ ['Master Sword Meadow SC'], ['Zoras Domain SW'] @@ -449,7 +449,7 @@ OWEdgeGroups = { ['Zora Waterfall NE'] ] ), - (Op, LW, Hz, Ld, PL, 2): ( + (Op, LW, Hz, Ld, PL, 2, None): ( [ ['Kakariko Fortune EN', 'Kakariko Fortune ES'], ['Kakariko Pond EN', 'Kakariko Pond ES'], @@ -465,7 +465,7 @@ OWEdgeGroups = { ['Statues WN', 'Statues WS'] ] ), - (Op, LW, Hz, Ld, NP, 2): ( + (Op, LW, Hz, Ld, NP, 2, None): ( [ ['Desert EC', 'Desert ES'] ], @@ -473,7 +473,7 @@ OWEdgeGroups = { ['Desert Pass WC', 'Desert Pass WS'] ] ), - (Op, LW, Vt, Ld, PL, 2): ( + (Op, LW, Vt, Ld, PL, 2, None): ( [ ['Lost Woods SW', 'Lost Woods SC'], ['Lost Woods Pass SW', 'Lost Woods Pass SE'], @@ -489,7 +489,7 @@ OWEdgeGroups = { ['Wooden Bridge NW', 'Wooden Bridge NE'] ] ), - (Op, LW, Hz, Wr, PL, 1): ( + (Op, LW, Hz, Wr, PL, 1, None): ( [ ['Potion Shop EN'], ['Lake Hylia EC'], @@ -505,7 +505,7 @@ OWEdgeGroups = { ['Statues WC'] ] ), - (Op, LW, Hz, Wr, NP, 1): ( + (Op, LW, Hz, Wr, NP, 1, None): ( [ ['Hobo EC'] ], @@ -513,7 +513,7 @@ OWEdgeGroups = { ['Stone Bridge WC'] ] ), - (Op, LW, Vt, Wr, PL, 1): ( + (Op, LW, Vt, Wr, PL, 1, None): ( [ ['Tree Line SC'], ['Ice Cave SW'], @@ -525,7 +525,7 @@ OWEdgeGroups = { ['Wooden Bridge NC'] ] ), - (Op, DW, Hz, Ld, PL, 1): ( + (Op, DW, Hz, Ld, PL, 1, None): ( [ ['Skull Woods EN'], ['East Dark Death Mountain EN'], @@ -563,7 +563,7 @@ OWEdgeGroups = { ['East Dark Death Mountain WS'] ] ), - (Op, DW, Vt, Ld, PL, 1): ( + (Op, DW, Vt, Ld, PL, 1, None): ( [ ['Dark Lumberjack SW'], ['Bumper Cave SE'], @@ -607,11 +607,11 @@ OWEdgeGroups = { ['Bomber Corner NE'] ] ), - (Op, DW, Hz, Ld, NP, 1): ( + (Op, DW, Hz, Ld, NP, 1, None): ( [ ], [ ] ), - (Op, DW, Hz, Ld, PL, 2): ( + (Op, DW, Hz, Ld, PL, 2, None): ( [ ['Dark Fortune EN', 'Dark Fortune ES'], ['Outcast Pond EN', 'Outcast Pond ES'], @@ -627,11 +627,11 @@ OWEdgeGroups = { ['Hype Cave WN', 'Hype Cave WS'] ] ), - (Op, DW, Vt, Ld, NP, 1): ( + (Op, DW, Vt, Ld, NP, 1, None): ( [ ], [ ] ), - (Op, DW, Hz, Ld, NP, 2): ( + (Op, DW, Hz, Ld, NP, 2, None): ( [ ['Dig Game EC', 'Dig Game ES'] ], @@ -639,7 +639,7 @@ OWEdgeGroups = { ['Frog WC', 'Frog WS'] ] ), - (Op, DW, Vt, Ld, PL, 2): ( + (Op, DW, Vt, Ld, PL, 2, None): ( [ ['Skull Woods SW', 'Skull Woods SC'], ['Skull Woods Pass SW', 'Skull Woods Pass SE'], @@ -655,7 +655,7 @@ OWEdgeGroups = { ['Broken Bridge NW', 'Broken Bridge NE'] ] ), - (Op, DW, Hz, Ld, PL, 3): ( + (Op, DW, Hz, Ld, PL, 3, None): ( [ ['Dark Bonk Rocks EN', 'Dark Bonk Rocks EC', 'Dark Bonk Rocks ES'] ], @@ -663,7 +663,7 @@ OWEdgeGroups = { ['Big Bomb Shop WN', 'Big Bomb Shop WC', 'Big Bomb Shop WS'] ] ), - (Op, DW, Hz, Wr, PL, 1): ( + (Op, DW, Hz, Wr, PL, 1, None): ( [ ['Dark Witch EN'], ['Ice Lake EC'], @@ -679,11 +679,11 @@ OWEdgeGroups = { ['Hype Cave WC'] ] ), - (Op, DW, Hz, Wr, NP, 1): ( + (Op, DW, Hz, Wr, NP, 1, None): ( [ ], [ ] ), - (Op, DW, Vt, Wr, PL, 1): ( + (Op, DW, Vt, Wr, PL, 1, None): ( [ ['Dark Tree Line SC'], ['Shopping Mall SW'], @@ -699,7 +699,7 @@ OWEdgeGroups = { OWEdgeGroupsTerrain = { #(IsStandard, World, EdgeAxis, Terrain, HasParallel, NumberInGroup) - (St, LW, Vt, None, PL, 1): ( + (St, LW, Vt, None, PL, 1, None): ( [ ['Hyrule Castle SW'], ['Hyrule Castle SE'] @@ -709,7 +709,7 @@ OWEdgeGroupsTerrain = { ['Links House NE'] ] ), - (St, LW, Hz, None, PL, 3): ( + (St, LW, Hz, None, PL, 3, None): ( [ ['Central Bonk Rocks EN', 'Central Bonk Rocks EC', 'Central Bonk Rocks ES'] ], @@ -717,7 +717,7 @@ OWEdgeGroupsTerrain = { ['Links House WN', 'Links House WC', 'Links House WS'] ] ), - (Op, LW, Hz, None, PL, 1): ( + (Op, LW, Hz, None, PL, 1, None): ( [ ['Lost Woods EN'], ['East Death Mountain EN'], @@ -751,7 +751,7 @@ OWEdgeGroupsTerrain = { ['East Death Mountain WS'] ] ), - (Op, LW, Hz, None, NP, 1): ( + (Op, LW, Hz, None, NP, 1, None): ( [ ['Forgotten Forest ES'], ['Hobo EC'] @@ -761,7 +761,7 @@ OWEdgeGroupsTerrain = { ['Stone Bridge WC'] ] ), - (Op, LW, Vt, None, PL, 1): ( + (Op, LW, Vt, None, PL, 1, None): ( [ ['Lumberjack SW'], ['Mountain Pass SE'], @@ -797,7 +797,7 @@ OWEdgeGroupsTerrain = { ['South Pass NC'] ] ), - (Op, LW, Vt, None, NP, 1): ( + (Op, LW, Vt, None, NP, 1, None): ( [ ['Master Sword Meadow SC'], ['Zoras Domain SW'] @@ -807,7 +807,7 @@ OWEdgeGroupsTerrain = { ['Zora Waterfall NE'] ] ), - (Op, LW, Hz, None, PL, 2): ( + (Op, LW, Hz, None, PL, 2, None): ( [ ['Kakariko Fortune EN', 'Kakariko Fortune ES'], ['Kakariko Pond EN', 'Kakariko Pond ES'], @@ -825,7 +825,7 @@ OWEdgeGroupsTerrain = { ['Tree Line WN', 'Tree Line WC'] ] ), - (Op, LW, Hz, None, NP, 2): ( + (Op, LW, Hz, None, NP, 2, None): ( [ ['Desert EC', 'Desert ES'] ], @@ -833,7 +833,7 @@ OWEdgeGroupsTerrain = { ['Desert Pass WC', 'Desert Pass WS'] ] ), - (Op, LW, Vt, None, PL, 2): ( + (Op, LW, Vt, None, PL, 2, None): ( [ ['Lost Woods SW', 'Lost Woods SC'], ['Lost Woods Pass SW', 'Lost Woods Pass SE'], @@ -851,7 +851,7 @@ OWEdgeGroupsTerrain = { ['Octoballoon NW', 'Octoballoon NE'] ] ), - (Op, LW, Hz, None, PL, 3): ( + (Op, LW, Hz, None, PL, 3, None): ( [ ['River Bend EN', 'River Bend EC', 'River Bend ES'], ['C Whirlpool EN', 'C Whirlpool EC', 'C Whirlpool ES'] @@ -861,7 +861,7 @@ OWEdgeGroupsTerrain = { ['Statues WN', 'Statues WC', 'Statues WS'] ] ), - (Op, LW, Vt, None, PL, 3): ( + (Op, LW, Vt, None, PL, 3, None): ( [ ['River Bend SW', 'River Bend SC', 'River Bend SE'] ], @@ -869,7 +869,7 @@ OWEdgeGroupsTerrain = { ['Wooden Bridge NW', 'Wooden Bridge NC', 'Wooden Bridge NE'] ] ), - (Op, DW, Hz, None, PL, 1): ( + (Op, DW, Hz, None, PL, 1, None): ( [ ['Skull Woods EN'], ['East Dark Death Mountain EN'], @@ -901,7 +901,7 @@ OWEdgeGroupsTerrain = { ['East Dark Death Mountain WS'] ] ), - (Op, DW, Vt, None, PL, 1): ( + (Op, DW, Vt, None, PL, 1, None): ( [ ['Dark Lumberjack SW'], ['Bumper Cave SE'], @@ -941,11 +941,11 @@ OWEdgeGroupsTerrain = { ['Dark South Pass NC'] ] ), - (Op, DW, Hz, None, NP, 1): ( + (Op, DW, Hz, None, NP, 1, None): ( [ ], [ ] ), - (Op, DW, Hz, None, PL, 2): ( + (Op, DW, Hz, None, PL, 2, None): ( [ ['Dark Fortune EN', 'Dark Fortune ES'], ['Outcast Pond EN', 'Outcast Pond ES'], @@ -963,11 +963,11 @@ OWEdgeGroupsTerrain = { ['Dark Tree Line WN', 'Dark Tree Line WC'] ] ), - (Op, DW, Vt, None, NP, 1): ( + (Op, DW, Vt, None, NP, 1, None): ( [ ], [ ] ), - (Op, DW, Hz, None, NP, 2): ( + (Op, DW, Hz, None, NP, 2, None): ( [ ['Dig Game EC', 'Dig Game ES'] ], @@ -975,7 +975,7 @@ OWEdgeGroupsTerrain = { ['Frog WC', 'Frog WS'] ] ), - (Op, DW, Vt, None, PL, 2): ( + (Op, DW, Vt, None, PL, 2, None): ( [ ['Skull Woods SW', 'Skull Woods SC'], ['Skull Woods Pass SW', 'Skull Woods Pass SE'], @@ -993,7 +993,7 @@ OWEdgeGroupsTerrain = { ['Bomber Corner NW', 'Bomber Corner NE'] ] ), - (Op, DW, Hz, None, PL, 3): ( + (Op, DW, Hz, None, PL, 3, None): ( [ ['Dark Bonk Rocks EN', 'Dark Bonk Rocks EC', 'Dark Bonk Rocks ES'], ['Qirn Jump EN', 'Qirn Jump EC', 'Qirn Jump ES'], @@ -1005,7 +1005,7 @@ OWEdgeGroupsTerrain = { ['Hype Cave WN', 'Hype Cave WC', 'Hype Cave WS'] ] ), - (Op, DW, Vt, None, PL, 3): ( + (Op, DW, Vt, None, PL, 3, None): ( [ ['Qirn Jump SW', 'Qirn Jump SC', 'Qirn Jump SE'] ], diff --git a/OverworldShuffle.py b/OverworldShuffle.py index d46ddac1..9ce4195d 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -3,27 +3,30 @@ from collections import OrderedDict, defaultdict from DungeonGenerator import GenerationException from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance from Regions import mark_light_dark_world_regions +from source.overworld.EntranceShuffle2 import connect_simple from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitTypes, OpenStd, parallel_links, IsParallel from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.3.2.2' +version_number = '0.3.3.0' # branch indicator is intentionally different across branches version_branch = '' __version__ = '%s%s' % (version_number, version_branch) +parallel_links_new = None # needs to be globally available, reset every new generation/player + def link_overworld(world, player): + global parallel_links_new + # setup mandatory connections for exitname, regionname in mandatory_connections: connect_simple(world, exitname, regionname, player) def performSwap(groups, swaps): def getParallel(edgename): - if edgename in parallel_links: - return parallel_links[edgename] - elif edgename in parallel_links.inverse: - return parallel_links.inverse[edgename][0] + if edgename in parallel_links_new: + return parallel_links_new[edgename] else: raise Exception('No parallel edge found for edge %s', edgename) @@ -57,7 +60,7 @@ def link_overworld(world, player): new_groups[group] = ([],[]) for group in groups.keys(): - (mode, wrld, dir, terrain, parallel, count) = group + (mode, wrld, dir, terrain, parallel, count, custom) = group for (forward_set, back_set) in zip(groups[group][0], groups[group][1]): anyF = any(edge in orig_swaps for edge in forward_set) anyB = any(edge in orig_swaps for edge in back_set) @@ -72,11 +75,11 @@ def link_overworld(world, player): if parallel == IsParallel.Yes and not (all(edge in orig_swaps for edge in map(getParallel, forward_set)) and all(edge in orig_swaps for edge in map(getParallel, back_set))): raise Exception('Cannot move a parallel edge without the other') new_mode = OpenStd.Open - if tuple((OpenStd.Open, WorldType((int(wrld) + 1) % 2), dir, terrain, parallel, count)) not in new_groups.keys(): + if tuple((OpenStd.Open, WorldType((int(wrld) + 1) % 2), dir, terrain, parallel, count, custom)) not in new_groups.keys(): # when Links House tile is flipped, the DW edges need to get put into existing Standard group new_mode = OpenStd.Standard - new_groups[(new_mode, WorldType((int(wrld) + 1) % 2), dir, terrain, parallel, count)][0].append(forward_set) - new_groups[(new_mode, WorldType((int(wrld) + 1) % 2), dir, terrain, parallel, count)][1].append(back_set) + new_groups[(new_mode, WorldType((int(wrld) + 1) % 2), dir, terrain, parallel, count, custom)][0].append(forward_set) + new_groups[(new_mode, WorldType((int(wrld) + 1) % 2), dir, terrain, parallel, count, custom)][1].append(back_set) for edge in forward_set: swaps.remove(edge) for edge in back_set: @@ -106,36 +109,39 @@ def link_overworld(world, player): raise NotImplementedError('Invalid OW Edge flip scenario') return new_groups - tile_groups = define_tile_groups(world, player, False) trimmed_groups = copy.deepcopy(OWEdgeGroupsTerrain if world.owTerrain[player] else OWEdgeGroups) swapped_edges = list() # restructure Maze Race/Suburb/Frog/Dig Game manually due to NP/P relationship + parallel_links_new = bidict(parallel_links) # shallow copy is enough (deep copy is broken) if world.owKeepSimilar[player]: + del parallel_links_new['Maze Race ES'] + del parallel_links_new['Kakariko Suburb WS'] for group in trimmed_groups.keys(): - (std, region, axis, terrain, parallel, _) = group + (std, region, axis, terrain, parallel, _, custom) = group if parallel == IsParallel.Yes: (forward_edges, back_edges) = trimmed_groups[group] if ['Maze Race ES'] in forward_edges: - forward_edges = list(filter((['Maze Race ES']).__ne__, forward_edges)) - trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][0].append(['Maze Race ES']) + forward_edges.remove(['Maze Race ES']) + trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1, custom)][0].append(['Maze Race ES']) if ['Kakariko Suburb WS'] in back_edges: - back_edges = list(filter((['Kakariko Suburb WS']).__ne__, back_edges)) - trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][1].append(['Kakariko Suburb WS']) + back_edges.remove(['Kakariko Suburb WS']) + trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1, custom)][1].append(['Kakariko Suburb WS']) trimmed_groups[group] = (forward_edges, back_edges) else: for group in trimmed_groups.keys(): - (std, region, axis, terrain, _, _) = group + (std, region, axis, terrain, _, _, custom) = group (forward_edges, back_edges) = trimmed_groups[group] if ['Dig Game EC', 'Dig Game ES'] in forward_edges: - forward_edges = list(filter((['Dig Game EC', 'Dig Game ES']).__ne__, forward_edges)) - trimmed_groups[(std, region, axis, terrain, IsParallel.Yes, 1)][0].append(['Dig Game ES']) - trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][0].append(['Dig Game EC']) + forward_edges.remove(['Dig Game EC', 'Dig Game ES']) + trimmed_groups[(std, region, axis, terrain, IsParallel.Yes, 1, custom)][0].append(['Dig Game ES']) + trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1, custom)][0].append(['Dig Game EC']) if ['Frog WC', 'Frog WS'] in back_edges: - back_edges = list(filter((['Frog WC', 'Frog WS']).__ne__, back_edges)) - trimmed_groups[(std, region, axis, terrain, IsParallel.Yes, 1)][1].append(['Frog WS']) - trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][1].append(['Frog WC']) + back_edges.remove(['Frog WC', 'Frog WS']) + trimmed_groups[(std, region, axis, terrain, IsParallel.Yes, 1, custom)][1].append(['Frog WS']) + trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1, custom)][1].append(['Frog WC']) trimmed_groups[group] = (forward_edges, back_edges) + parallel_links_new = {**dict(parallel_links_new), **dict({e:p[0] for e, p in parallel_links_new.inverse.items()})} connected_edges = [] if world.owShuffle[player] != 'vanilla': @@ -145,7 +151,8 @@ def link_overworld(world, player): # tile shuffle logging.getLogger('').debug('Flipping overworld tiles') if world.owMixed[player]: - swapped_edges = shuffle_tiles(world, tile_groups, world.owswaps[player], False, player) + tile_groups, force_flipped, force_nonflipped, undefined_chance = define_tile_groups(world, False, player) + swapped_edges = shuffle_tiles(world, tile_groups, world.owswaps[player], False, (force_flipped, force_nonflipped, undefined_chance), player) update_world_regions(world, player) @@ -198,77 +205,140 @@ def link_overworld(world, player): # crossed shuffle logging.getLogger('').debug('Crossing overworld edges') - crossed_edges = list() - # more Maze Race/Suburb/Frog/Dig Game fixes - parallel_links_new = bidict(parallel_links) # shallow copy is enough (deep copy is broken) - if world.owKeepSimilar[player]: - del parallel_links_new['Maze Race ES'] - del parallel_links_new['Kakariko Suburb WS'] + # customizer setup + force_crossed = set() + force_noncrossed = set() + count_crossed = 0 + limited_crossed = -1 + undefined_chance = 50 + if world.customizer: + custom_crossed = world.customizer.get_owcrossed() + if custom_crossed and player in custom_crossed: + custom_crossed = custom_crossed[player] + if 'force_crossed' in custom_crossed and len(custom_crossed['force_crossed']) > 0: + for edgename in custom_crossed['force_crossed']: + edge = world.get_owedge(edgename, player) + force_crossed.add(edge.name) + if 'force_noncrossed' in custom_crossed and len(custom_crossed['force_noncrossed']) > 0: + for edgename in custom_crossed['force_noncrossed']: + edge = world.get_owedge(edgename, player) + force_noncrossed.add(edge.name) + if 'limit_crossed' in custom_crossed: + limited_crossed = custom_crossed['limit_crossed'] + if 'undefined_chance' in custom_crossed: + undefined_chance = custom_crossed['undefined_chance'] - #TODO: Revisit with changes to Limited/Allowed - if world.owCrossed[player] not in ['none', 'grouped', 'polar', 'chaos']: + if limited_crossed > -1: + # connect forced crossed non-parallel edges based on previously determined tile flips for edge in swapped_edges: - if edge not in parallel_links_new and edge not in parallel_links_new.inverse: - crossed_edges.append(edge) - - if world.owCrossed[player] in ['grouped', 'limited'] or (world.owShuffle[player] == 'vanilla' and world.owCrossed[player] == 'chaos'): - if world.owCrossed[player] == 'grouped': - # the idea is to XOR the new flips with the ones from Mixed so that non-parallel edges still work - # Polar corresponds to Grouped with no flips in ow_crossed_tiles_mask - ow_crossed_tiles_mask = [[],[],[]] - crossed_edges = shuffle_tiles(world, define_tile_groups(world, player, True), ow_crossed_tiles_mask, True, player) - ow_crossed_tiles = [i for i in range(0x82) if (i in world.owswaps[player][0]) != (i in ow_crossed_tiles_mask[0])] + if edge not in parallel_links_new: + world.owcrossededges[player].append(edge) + count_crossed = count_crossed + 1 - # update spoiler - s = list(map(lambda x: 'O' if x not in ow_crossed_tiles else 'X', [i for i in range(0x40, 0x82)])) - text_output = tile_swap_spoiler_table.replace('s', '%s') % ( s[0x02], s[0x07], - s[0x00], s[0x03], s[0x05], - s[0x00], s[0x02],s[0x03], s[0x05], s[0x07], s[0x0a], s[0x0f], - s[0x0a], s[0x0f], - s[0x10],s[0x11],s[0x12],s[0x13],s[0x14],s[0x15],s[0x16],s[0x17], s[0x10],s[0x11],s[0x12],s[0x13],s[0x14],s[0x15],s[0x16],s[0x17], - s[0x18], s[0x1a],s[0x1b], s[0x1d],s[0x1e], - s[0x22], s[0x25], s[0x1a], s[0x1d], - s[0x28],s[0x29],s[0x2a],s[0x2b],s[0x2c],s[0x2d],s[0x2e],s[0x2f], s[0x18], s[0x1b], s[0x1e], - s[0x30], s[0x32],s[0x33],s[0x34],s[0x35], s[0x37], s[0x22], s[0x25], - s[0x3a],s[0x3b],s[0x3c], s[0x3f], - s[0x28],s[0x29],s[0x2a],s[0x2b],s[0x2c],s[0x2d],s[0x2e],s[0x2f], - s[0x40], s[0x32],s[0x33],s[0x34], s[0x37], - s[0x30], s[0x35], - s[0x41], s[0x3a],s[0x3b],s[0x3c], s[0x3f]) - world.spoiler.set_map('groups', text_output, ow_crossed_tiles, player) - else: - crossed_candidates = list() - for group in trimmed_groups.keys(): - (mode, wrld, dir, terrain, parallel, count) = group - if wrld == WorldType.Light and mode != OpenStd.Standard: - for (forward_set, back_set) in zip(trimmed_groups[group][0], trimmed_groups[group][1]): - if forward_set[0] in parallel_links_new or forward_set[0] in parallel_links_new.inverse: - if world.owKeepSimilar[player]: - if world.owCrossed[player] == 'chaos' and random.randint(0, 1): - for edge in forward_set: - crossed_edges.append(edge) - elif world.owCrossed[player] == 'limited': - crossed_candidates.append(forward_set) - else: - for edge in forward_set: - if world.owCrossed[player] == 'chaos' and random.randint(0, 1): - crossed_edges.append(edge) - elif world.owCrossed[player] == 'limited': - crossed_candidates.append([edge]) - if world.owCrossed[player] == 'limited': + if world.owCrossed[player] == 'grouped': + # the idea is to XOR the new flips with the ones from Mixed so that non-parallel edges still work + # Polar corresponds to Grouped with no flips in ow_crossed_tiles_mask + ow_crossed_tiles_mask = [[],[],[]] + tile_groups, force_flipped, force_nonflipped, undefined_chance = define_tile_groups(world, True, player) + world.owcrossededges[player] = shuffle_tiles(world, tile_groups, ow_crossed_tiles_mask, True, (force_flipped, force_nonflipped, undefined_chance), player) + ow_crossed_tiles = [i for i in range(0x82) if (i in world.owswaps[player][0]) != (i in ow_crossed_tiles_mask[0])] + + # update spoiler + s = list(map(lambda x: 'O' if x not in ow_crossed_tiles else 'X', [i for i in range(0x40, 0x82)])) + text_output = tile_swap_spoiler_table.replace('s', '%s') % ( s[0x02], s[0x07], + s[0x00], s[0x03], s[0x05], + s[0x00], s[0x02],s[0x03], s[0x05], s[0x07], s[0x0a], s[0x0f], + s[0x0a], s[0x0f], + s[0x10],s[0x11],s[0x12],s[0x13],s[0x14],s[0x15],s[0x16],s[0x17], s[0x10],s[0x11],s[0x12],s[0x13],s[0x14],s[0x15],s[0x16],s[0x17], + s[0x18], s[0x1a],s[0x1b], s[0x1d],s[0x1e], + s[0x22], s[0x25], s[0x1a], s[0x1d], + s[0x28],s[0x29],s[0x2a],s[0x2b],s[0x2c],s[0x2d],s[0x2e],s[0x2f], s[0x18], s[0x1b], s[0x1e], + s[0x30], s[0x32],s[0x33],s[0x34],s[0x35], s[0x37], s[0x22], s[0x25], + s[0x3a],s[0x3b],s[0x3c], s[0x3f], + s[0x28],s[0x29],s[0x2a],s[0x2b],s[0x2c],s[0x2d],s[0x2e],s[0x2f], + s[0x40], s[0x32],s[0x33],s[0x34], s[0x37], + s[0x30], s[0x35], + s[0x41], s[0x3a],s[0x3b],s[0x3c], s[0x3f]) + world.spoiler.set_map('groups', text_output, ow_crossed_tiles, player) + elif limited_crossed > -1 or (world.owShuffle[player] == 'vanilla' and world.owCrossed[player] == 'unrestricted'): + crossed_candidates = list() + for group in trimmed_groups.keys(): + (mode, wrld, dir, terrain, parallel, count, _) = group + if wrld == WorldType.Light and mode != OpenStd.Standard: + for (forward_set, back_set) in zip(trimmed_groups[group][0], trimmed_groups[group][1]): + if forward_set[0] in parallel_links_new: + forward_parallel = [parallel_links_new[e] for e in forward_set] + back_parallel = [parallel_links_new[e] for e in back_set] + forward_combine = forward_set+forward_parallel + back_combine = back_set+back_parallel + combine_set = forward_combine+back_combine + + skip_forward = False + if world.owShuffle[player] == 'vanilla': + if any(edge in force_crossed for edge in combine_set): + if not any(edge in force_noncrossed for edge in combine_set): + if any(edge in force_crossed for edge in forward_combine): + world.owcrossededges[player].extend(forward_set) + count_crossed = count_crossed + 1 + continue + else: + world.owcrossededges[player].extend(back_set) + count_crossed = count_crossed + 1 + continue + else: + raise GenerationException('Conflict detected in force_crossed and force_noncrossed') + if any(edge in list(force_noncrossed)+world.owcrossededges[player] for edge in combine_set): + continue + else: + skip_back = False + if any(edge in force_crossed for edge in forward_combine): + if not any(edge in force_noncrossed for edge in forward_combine): + world.owcrossededges[player].extend(forward_set) + count_crossed = count_crossed + 1 + skip_forward = True + else: + raise GenerationException('Conflict detected in force_crossed and force_noncrossed') + if any(edge in force_crossed for edge in back_combine): + if not any(edge in force_noncrossed for edge in back_combine): + world.owcrossededges[player].extend(back_set) + count_crossed = count_crossed + 1 + skip_back = True + else: + raise GenerationException('Conflict detected in force_crossed and force_noncrossed') + if any(edge in list(force_noncrossed)+world.owcrossededges[player] for edge in forward_combine): + skip_forward = True + if any(edge in list(force_noncrossed)+world.owcrossededges[player] for edge in back_combine): + skip_back = True + if not skip_back: + if limited_crossed > -1: + crossed_candidates.append(back_set) + elif random.randint(1, 100) <= undefined_chance: + world.owcrossededges[player].extend(back_set) + count_crossed = count_crossed + 1 + if not skip_forward: + if limited_crossed > -1: + crossed_candidates.append(forward_set) + elif random.randint(1, 100) <= undefined_chance: + world.owcrossededges[player].extend(forward_set) + count_crossed = count_crossed + 1 + assert len(world.owcrossededges[player]) == len(set(world.owcrossededges[player])), "Same edge added to crossed edges" + + if limited_crossed > -1: + limit = limited_crossed - count_crossed + if limit > 1: random.shuffle(crossed_candidates) - for edge_set in crossed_candidates[:9]: - for edge in edge_set: - crossed_edges.append(edge) - for edge in copy.deepcopy(crossed_edges): - if edge in parallel_links_new: - crossed_edges.append(parallel_links_new[edge]) - elif edge in parallel_links_new.inverse: - crossed_edges.append(parallel_links_new.inverse[edge][0]) + for edge_set in crossed_candidates[:limit]: + world.owcrossededges[player].extend(edge_set) + assert len(world.owcrossededges[player]) == len(set(world.owcrossededges[player])), "Same edge candidate added to crossed edges" + + for edge in copy.deepcopy(world.owcrossededges[player]): + if edge in parallel_links_new: + if parallel_links_new[edge] not in world.owcrossededges[player]: + world.owcrossededges[player].append(parallel_links_new[edge]) # after tile flip and crossed, determine edges that need to flip - edges_to_swap = [e for e in swapped_edges+crossed_edges if (e not in swapped_edges) or (e not in crossed_edges)] + edges_to_swap = [e for e in swapped_edges+world.owcrossededges[player] if (e not in swapped_edges) or (e not in world.owcrossededges[player])] # whirlpool shuffle logging.getLogger('').debug('Shuffling whirlpools') @@ -278,16 +348,24 @@ def link_overworld(world, player): connect_simple(world, from_whirlpool, to_region, player) connect_simple(world, to_whirlpool, from_region, player) else: + def connect_whirlpool(from_whirlpool, to_whirlpool): + (from_owid, from_name, from_region) = from_whirlpool + (to_owid, to_name, to_region) = to_whirlpool + connect_simple(world, from_name, to_region, player) + connect_simple(world, to_name, from_region, player) + world.owwhirlpools[player][next(i for i, v in enumerate(whirlpool_map) if v == to_owid)] = from_owid + world.owwhirlpools[player][next(i for i, v in enumerate(whirlpool_map) if v == from_owid)] = to_owid + connected_whirlpools.append(tuple((from_name, to_name))) + world.spoiler.set_whirlpool(from_name, to_name, 'both', player) + + whirlpool_map = [ 0x35, 0x0f, 0x15, 0x33, 0x12, 0x3f, 0x55, 0x7f ] whirlpool_candidates = [[],[]] + connected_whirlpools = [] world.owwhirlpools[player] = [None] * 8 for (from_owid, from_whirlpool, from_region), (to_owid, to_whirlpool, to_region) in default_whirlpool_connections: if world.owCrossed[player] == 'polar' and world.owMixed[player] and from_owid == 0x55: # connect the 2 DW whirlpools in Polar Mixed - connect_simple(world, from_whirlpool, to_region, player) - connect_simple(world, to_whirlpool, from_region, player) - world.owwhirlpools[player][7] = from_owid - world.owwhirlpools[player][6] = to_owid - world.spoiler.set_overworld(from_whirlpool, to_whirlpool, 'both', player) + connect_whirlpool((from_owid, from_whirlpool, from_region), (to_owid, to_whirlpool, to_region)) else: if ((world.owCrossed[player] == 'none' or (world.owCrossed[player] == 'polar' and not world.owMixed[player])) and (world.get_region(from_region, player).type == RegionType.LightWorld)) \ or world.owCrossed[player] not in ['none', 'polar', 'grouped'] \ @@ -304,19 +382,29 @@ def link_overworld(world, player): whirlpool_candidates[1].append(tuple((to_owid, to_whirlpool, to_region))) # shuffle happens here - whirlpool_map = [ 0x35, 0x0f, 0x15, 0x33, 0x12, 0x3f, 0x55, 0x7f ] + if world.customizer: + custom_whirlpools = world.customizer.get_whirlpools() + if custom_whirlpools and player in custom_whirlpools: + custom_whirlpools = custom_whirlpools[player] + if 'two-way' in custom_whirlpools and len(custom_whirlpools['two-way']) > 0: + for whirlpools in whirlpool_candidates: + for whirlname1, whirlname2 in custom_whirlpools['two-way'].items(): + whirl1 = next((w for w in whirlpools if w[1] == whirlname1), None) + whirl2 = next((w for w in whirlpools if w[1] == whirlname2), None) + if whirl1 and whirl2: + whirlpools.remove(whirl1) + whirlpools.remove(whirl2) + connect_whirlpool(whirl1, whirl2) + elif whirl1 != whirl2: + raise GenerationException('Attempting to connect whirlpools not in same pool: \'%s\' <-> \'%s\'', whirlname1, whirlname2) + elif any(w for w in connected_whirlpools if (whirlname1 in w) != (whirlname2 in w)): + raise GenerationException('Attempting to connect whirlpools already connected: \'%s\' <-> \'%s\'', whirlname1, whirlname2) for whirlpools in whirlpool_candidates: random.shuffle(whirlpools) while len(whirlpools): if len(whirlpools) % 2 == 1: x=0 - from_owid, from_whirlpool, from_region = whirlpools.pop() - to_owid, to_whirlpool, to_region = whirlpools.pop() - connect_simple(world, from_whirlpool, to_region, player) - connect_simple(world, to_whirlpool, from_region, player) - world.owwhirlpools[player][next(i for i, v in enumerate(whirlpool_map) if v == to_owid)] = from_owid - world.owwhirlpools[player][next(i for i, v in enumerate(whirlpool_map) if v == from_owid)] = to_owid - world.spoiler.set_overworld(from_whirlpool, to_whirlpool, 'both', player) + connect_whirlpool(whirlpools.pop(), whirlpools.pop()) # layout shuffle logging.getLogger('').debug('Shuffling overworld layout') @@ -337,64 +425,161 @@ def link_overworld(world, player): world.owsectors[player] = build_sectors(world, player) else: - if world.owKeepSimilar[player] and world.owShuffle[player] in ['vanilla', 'parallel']: + if world.owKeepSimilar[player] and world.owShuffle[player] == 'parallel': for exitname, destname in parallelsimilar_connections: connect_two_way(world, exitname, destname, player, connected_edges) #TODO: Remove, just for testing for exitname, destname in test_connections: connect_two_way(world, exitname, destname, player, connected_edges) - - connect_custom(world, connected_edges, player) - + # layout shuffle groups = adjust_edge_groups(world, trimmed_groups, edges_to_swap, player) + + connect_custom(world, connected_edges, groups, (force_crossed, force_noncrossed), player) tries = 100 valid_layout = False connected_edge_cache = connected_edges.copy() + groups_cache = copy.deepcopy(groups) while not valid_layout and tries > 0: + def connect_set(forward_set, back_set, connected_edges): + if forward_set is not None and back_set is not None: + 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) + elif forward_set is not None: + logging.getLogger('').warning("Edge '%s' could not find a valid connection" % forward_set[0]) + elif back_set is not None: + logging.getLogger('').warning("Edge '%s' could not find a valid connection" % back_set[0]) + connected_edges = connected_edge_cache.copy() + groups = copy.deepcopy(groups_cache) + groupKeys = list(groups.keys()) if world.mode[player] == 'standard': - random.shuffle(groups[2:]) # keep first 2 groups (Standard) first + subset = groupKeys[2:] + random.shuffle(subset) # keep first 2 groups (Standard) first + groupKeys[2:] = subset else: - random.shuffle(groups) + random.shuffle(groupKeys) - for (forward_edge_sets, back_edge_sets) in groups: - assert len(forward_edge_sets) == len(back_edge_sets) + for key in groupKeys: + (mode, wrld, dir, terrain, parallel, count, _) = key + (forward_edge_sets, back_edge_sets) = groups[key] + def remove_connected(): + deleted_edges = [] + s = 0 + while s < len(forward_edge_sets): + forward_set = forward_edge_sets[s] + if forward_set[0] in connected_edges: + deleted_edges.extend(forward_edge_sets[s]) + del forward_edge_sets[s] + continue + s += 1 + s = 0 + while s < len(back_edge_sets): + back_set = back_edge_sets[s] + if back_set[0] in connected_edges: + deleted_edges.extend(back_edge_sets[s]) + del back_edge_sets[s] + continue + s += 1 + if len(forward_edge_sets) != len(back_edge_sets): + x=', '.join(deleted_edges) + x=0 + assert len(forward_edge_sets) == len(back_edge_sets), "OW edge pool is uneven due to prior connections: " + ', '.join(deleted_edges) + + remove_connected() random.shuffle(forward_edge_sets) random.shuffle(back_edge_sets) - if len(forward_edge_sets) > 0: - f = 0 - b = 0 - while f < len(forward_edge_sets) and b < len(back_edge_sets): - forward_set = forward_edge_sets[f] - back_set = back_edge_sets[b] - while forward_set[0] in connected_edges: - f += 1 - if f < len(forward_edge_sets): - forward_set = forward_edge_sets[f] + if wrld is None and len(force_crossed) + len(force_noncrossed) > 0: + # divide forward/back sets into LW/DW + forward_lw_sets, forward_dw_sets = [], [] + back_lw_sets, back_dw_sets = [], [] + forward_parallel_lw_sets, forward_parallel_dw_sets = [], [] + back_parallel_lw_sets, back_parallel_dw_sets = [], [] + + for edge_set in forward_edge_sets: + if world.get_owedge(edge_set[0], player).is_lw(world): + forward_lw_sets.append(edge_set) + if parallel == IsParallel.Yes: + forward_parallel_lw_sets.append([parallel_links_new[e] for e in edge_set]) + else: + forward_dw_sets.append(edge_set) + if parallel == IsParallel.Yes: + forward_parallel_dw_sets.append([parallel_links_new[e] for e in edge_set]) + for edge_set in back_edge_sets: + if world.get_owedge(edge_set[0], player).is_lw(world): + back_lw_sets.append(edge_set) + if parallel == IsParallel.Yes: + back_parallel_lw_sets.append([parallel_links_new[e] for e in edge_set]) + else: + back_dw_sets.append(edge_set) + if parallel == IsParallel.Yes: + back_parallel_dw_sets.append([parallel_links_new[e] for e in edge_set]) + + crossed_sets = [] + noncrossed_sets = [] + def add_to_crossed_sets(sets, parallel_sets): + for i in range(0, len(sets)): + affected_edges = set(sets[i]+(parallel_sets[i] if parallel == IsParallel.Yes else [])) + if sets[i] not in crossed_sets and len(set.intersection(set(force_crossed), affected_edges)) > 0: + crossed_sets.append(sets[i]) + if sets not in noncrossed_sets and len(set.intersection(set(force_noncrossed), affected_edges)) > 0: + noncrossed_sets.append(sets[i]) + if sets[i] in crossed_sets and sets[i] in noncrossed_sets: + raise GenerationException('Conflict in force crossed/non-crossed definition') + add_to_crossed_sets(forward_lw_sets, forward_parallel_lw_sets) + add_to_crossed_sets(forward_dw_sets, forward_parallel_dw_sets) + add_to_crossed_sets(back_lw_sets, back_parallel_lw_sets) + add_to_crossed_sets(back_dw_sets, back_parallel_dw_sets) + + # random connect forced crossed/noncrossed + c = 0 + while c < len(noncrossed_sets): + if noncrossed_sets[c] in forward_edge_sets: + forward_set = noncrossed_sets[c] + if forward_set in forward_lw_sets: + back_set = next(s for s in back_lw_sets if s in back_edge_sets and s not in crossed_sets) else: - forward_set = None - break - f += 1 - while back_set[0] in connected_edges: - b += 1 - if b < len(back_edge_sets): - back_set = back_edge_sets[b] + back_set = next(s for s in back_dw_sets if s in back_edge_sets and s not in crossed_sets) + elif noncrossed_sets[c] in back_edge_sets: + back_set = noncrossed_sets[c] + if back_set in back_lw_sets: + forward_set = next(s for s in forward_lw_sets if s in forward_edge_sets and s not in crossed_sets) else: - back_set = None - break - b += 1 - if forward_set is not None and back_set is not None: - 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) - elif forward_set is not None: - logging.getLogger('').warning("Edge '%s' could not find a valid connection" % forward_set[0]) - elif back_set is not None: - logging.getLogger('').warning("Edge '%s' could not find a valid connection" % back_set[0]) + forward_set = next(s for s in forward_dw_sets if s in forward_edge_sets and s not in crossed_sets) + else: + c = c + 1 + continue + connect_set(forward_set, back_set, connected_edges) + remove_connected() + c = c + 1 + c = 0 + while c < len(crossed_sets): + if crossed_sets[c] in forward_edge_sets: + forward_set = crossed_sets[c] + if forward_set in forward_lw_sets: + back_set = next(s for s in back_dw_sets if s in back_edge_sets) + else: + back_set = next(s for s in back_lw_sets if s in back_edge_sets) + elif crossed_sets[c] in back_edge_sets: + back_set = crossed_sets[c] + if back_set in back_lw_sets: + forward_set = next(s for s in forward_dw_sets if s in forward_edge_sets) + else: + forward_set = next(s for s in forward_lw_sets if s in forward_edge_sets) + else: + c = c + 1 + continue + connect_set(forward_set, back_set, connected_edges) + remove_connected() + c = c + 1 + + while len(forward_edge_sets) > 0 and len(back_edge_sets) > 0: + connect_set(forward_edge_sets[0], back_edge_sets[0], connected_edges) + remove_connected() assert len(connected_edges) == len(default_connections) * 2, connected_edges world.owsectors[player] = build_sectors(world, player) @@ -564,32 +749,129 @@ def link_overworld(world, player): s[0x3a],s[0x3b],s[0x3c], s[0x3f]) world.spoiler.set_map('flute', text_output, new_spots, player) -def connect_custom(world, connected_edges, player): - if hasattr(world, 'custom_overworld') and world.custom_overworld[player]: - for edgename1, edgename2 in world.custom_overworld[player]: - if edgename1 in connected_edges or edgename2 in connected_edges: - owedge1 = world.check_for_owedge(edgename1, player) - owedge2 = world.check_for_owedge(edgename2, player) - if owedge1.dest is not None and owedge1.dest.name == owedge2.name: - continue # if attempting to connect a pair that was already connected earlier, allow it to continue - raise RuntimeError('Invalid plando connection: rule violation based on current settings') - connect_two_way(world, edgename1, edgename2, player, connected_edges) - if world.owKeepSimilar[player]: #TODO: If connecting an edge that belongs to a similar pair, the remaining edges need to get connected automatically +def connect_custom(world, connected_edges, groups, forced, player): + forced_crossed, forced_noncrossed = forced + def remove_pair_from_pool(edgename1, edgename2, is_crossed): + def add_to_unresolved(forward_set, back_set): + if len(forward_set) > 1: + if edgename1 in forward_set: + forward_set.remove(edgename1) + back_set.remove(edgename2) + else: + back_set.remove(edgename1) + forward_set.remove(edgename2) + unresolved_similars.append(tuple((forward_set, back_set, is_crossed))) + for forward_pool, back_pool in groups.values(): + if not len(forward_pool): continue + if len(forward_pool[0]) == 1: + if [edgename1] in forward_pool: + if [edgename2] in back_pool: + forward_pool.remove([edgename1]) + back_pool.remove([edgename2]) + return + else: + break + elif [edgename1] in back_pool: + if [edgename2] in forward_pool: + back_pool.remove([edgename1]) + forward_pool.remove([edgename2]) + return + else: + break + else: + forward_similar = next((x for x in forward_pool if edgename1 in x), None) + if forward_similar: + back_similar = next((x for x in back_pool if edgename2 in x), None) + if back_similar: + forward_pool.remove(forward_similar) + back_pool.remove(back_similar) + add_to_unresolved(forward_similar, back_similar) + return + else: + break + else: + back_similar = next((x for x in back_pool if edgename1 in x), None) + if back_similar: + forward_similar = next((x for x in forward_pool if edgename2 in x), None) + if forward_similar: + back_pool.remove(forward_similar) + forward_pool.remove(back_similar) + add_to_unresolved(forward_similar, back_similar) + return + else: + break + for pair in unresolved_similars: + forward_set, back_set, _ = pair + if edgename1 in forward_set: + if edgename2 in back_set: + unresolved_similars.remove(pair) + add_to_unresolved(forward_set, back_set) + return + else: + break + else: + if edgename1 in back_set: + if edgename2 in forward_set: + unresolved_similars.remove(pair) + add_to_unresolved(forward_set, back_set) + return + else: + break + raise GenerationException('Could not find both OW edges in same pool: \'%s\' <-> \'%s\'', edgename1, edgename2) -def connect_simple(world, exitname, regionname, player): - world.get_entrance(exitname, player).connect(world.get_region(regionname, player)) + if world.customizer: + custom_edges = world.customizer.get_owedges() + if custom_edges and player in custom_edges: + custom_edges = custom_edges[player] + if 'two-way' in custom_edges: + unresolved_similars = [] + def validate_crossed_allowed(edge1, edge2, is_crossed): + return not ((not is_crossed and (edge1 in forced_crossed or edge2 in forced_crossed)) + or (is_crossed and (edge1 in forced_noncrossed or edge2 in forced_noncrossed))) + for edgename1, edgename2 in custom_edges['two-way'].items(): + edge1 = world.get_owedge(edgename1, player) + edge2 = world.get_owedge(edgename2, player) + is_crossed = edge1.is_lw(world) != edge2.is_lw(world) + if not validate_crossed_allowed(edge1.name, edge2.name, is_crossed): + if edgename2[-1] == '*': + edge2 = world.get_owedge(edge2.name + '*', player) + is_crossed = not is_crossed + else: + raise GenerationException('Violation of force crossed rules: \'%s\' <-> \'%s\'', edgename1, edgename2) + if edge1.name not in connected_edges and edge2.name not in connected_edges: + # attempt connection + remove_pair_from_pool(edge1.name, edge2.name, is_crossed) + connect_two_way(world, edge1.name, edge2.name, player, connected_edges) + # resolve parallel + if world.owShuffle[player] == 'parallel' and edge1.name in parallel_links_new: + parallel_forward_edge = parallel_links_new[edge1.name] + parallel_back_edge = parallel_links_new[edge2.name] + if validate_crossed_allowed(parallel_forward_edge, parallel_back_edge, is_crossed): + remove_pair_from_pool(parallel_forward_edge, parallel_back_edge, is_crossed) + else: + raise GenerationException('Violation of force crossed rules on parallel connection: \'%s\' <-> \'%s\'', edgename1, edgename2) + elif not edge1.dest or not edge2.dest or edge1.dest.name != edge2.name or edge2.dest.name != edge1.name: + raise GenerationException('OW Edge already connected: \'%s\' <-> \'%s\'', edgename1, edgename2) + # connect leftover similars + for forward_pool, back_pool, is_crossed in unresolved_similars: + for (forward_edge, back_edge) in zip(forward_pool, back_pool): + if validate_crossed_allowed(forward_edge, back_edge, is_crossed): + connect_two_way(world, forward_edge, back_edge, player, connected_edges) + else: + raise GenerationException('Violation of force crossed rules on unresolved similars: \'%s\' <-> \'%s\'', forward_edge, back_edge) + if world.owShuffle[player] == 'parallel' and forward_edge in parallel_links_new: + parallel_forward_edge = parallel_links_new[forward_edge] + parallel_back_edge = parallel_links_new[back_edge] + if not validate_crossed_allowed(parallel_forward_edge, parallel_back_edge, is_crossed): + raise GenerationException('Violation of force crossed rules on parallel unresolved similars: \'%s\' <-> \'%s\'', forward_edge, back_edge) def connect_two_way(world, edgename1, edgename2, player, connected_edges=None): edge1 = world.get_entrance(edgename1, player) edge2 = world.get_entrance(edgename2, player) - x = world.check_for_owedge(edgename1, player) - y = world.check_for_owedge(edgename2, player) + x = world.get_owedge(edgename1, player) + y = world.get_owedge(edgename2, player) - if x is None: - raise Exception('%s is not a valid edge.', edgename1) - elif y is None: - raise Exception('%s is not a valid edge.', edgename2) if connected_edges is not None: if edgename1 in connected_edges or edgename2 in connected_edges: if (x.dest and x.dest.name == edgename2) and (y.dest and y.dest.name == edgename1): @@ -617,16 +899,110 @@ def connect_two_way(world, edgename1, edgename2, player, connected_edges=None): # connecting parallel connections if world.owShuffle[player] in ['vanilla', 'parallel']: - if (edgename1 in parallel_links.keys() or edgename1 in parallel_links.inverse.keys()): + if edgename1 in parallel_links_new: try: - parallel_forward_edge = parallel_links[edgename1] if edgename1 in parallel_links.keys() else parallel_links.inverse[edgename1][0] - parallel_back_edge = parallel_links[edgename2] if edgename2 in parallel_links.keys() else parallel_links.inverse[edgename2][0] + parallel_forward_edge = parallel_links_new[edgename1] + parallel_back_edge = parallel_links_new[edgename2] if not (parallel_forward_edge in connected_edges) and not (parallel_back_edge in connected_edges): connect_two_way(world, parallel_forward_edge, parallel_back_edge, player, connected_edges) except KeyError: raise KeyError('No parallel edge for edge %s' % edgename2) -def shuffle_tiles(world, groups, result_list, do_grouped, player): +def determine_forced_flips(world, tile_ow_groups, do_grouped, player): + undefined_chance = 50 + flipped_groups = list() + nonflipped_groups = list() + merged_owids = list() + if world.customizer: + if do_grouped: + custom_flips = world.customizer.get_owcrossed() + else: + custom_flips = world.customizer.get_owtileflips() + if custom_flips and player in custom_flips: + custom_flips = custom_flips[player] + forced_flips = list() + forced_nonflips = list() + if 'undefined_chance' in custom_flips: + undefined_chance = custom_flips['undefined_chance'] + if 'force_flip' in custom_flips: + forced_flips = custom_flips['force_flip'] + if 'force_no_flip' in custom_flips: + forced_nonflips = custom_flips['force_no_flip'] + if 'force_together' in custom_flips: + merged_owids = list(custom_flips['force_together'].values()) + + for group in tile_ow_groups: + if any(owid in group for owid in forced_nonflips): + nonflipped_groups.append(group) + if any(owid in group for owid in forced_flips): + flipped_groups.append(group) + + if undefined_chance == 0: + nonflipped_groups.extend([g for g in tile_ow_groups if g not in flipped_groups + nonflipped_groups]) + + # ensure any customized connections don't end up crossworld + if world.owCrossed[player] == 'none': + def should_merge_group(s1_owid, s2_owid): + flip_together = (s1_owid & 0x40) == (s2_owid & 0x40) + s1_nonflipped = any(g for g in nonflipped_groups if s1_owid in g) + s1_flipped = any(g for g in flipped_groups if s1_owid in g) + if s1_nonflipped or s1_flipped: + group = next(g for g in tile_ow_groups if s2_owid in g) + if s1_nonflipped == flip_together: + nonflipped_groups.append(group) + else: + flipped_groups.append(group) + else: + s2_nonflipped = any(g for g in nonflipped_groups if s2_owid in g) + s2_flipped = any(g for g in flipped_groups if s2_owid in g) + if s2_nonflipped or s2_flipped: + group = next(g for g in tile_ow_groups if s1_owid in g) + if s2_nonflipped == flip_together: + nonflipped_groups.append(group) + else: + flipped_groups.append(group) + else: + s1_group = next(g for g in tile_ow_groups if s1_owid in g) + s2_group = next(g for g in tile_ow_groups if s2_owid in g) + if not flip_together: + if random.randint(0, 1) > 0: + nonflipped_groups.append(s1_group) + flipped_groups.append(s2_group) + else: + flipped_groups.append(s1_group) + nonflipped_groups.append(s2_group) + else: + return True + return False + if world.owWhirlpoolShuffle[player]: + custom_whirlpools = world.customizer.get_whirlpools() + if custom_whirlpools and player in custom_whirlpools: + custom_whirlpools = custom_whirlpools[player] + if 'two-way' in custom_whirlpools and len(custom_whirlpools['two-way']) > 0: + custom_whirlpools = custom_whirlpools['two-way'] + whirlpool_map = {name:owid for wc in default_whirlpool_connections for (owid, name, _) in wc} + for whirl1, whirl2 in custom_whirlpools.items(): + if [whirlpool_map[whirl1], whirlpool_map[whirl2]] not in merged_owids and should_merge_group(whirlpool_map[whirl1], whirlpool_map[whirl2]): + merged_owids.append([whirlpool_map[whirl1], whirlpool_map[whirl2]]) + if world.owShuffle[player] != 'vanilla': + custom_edges = world.customizer.get_owedges() + if custom_edges and player in custom_edges: + custom_edges = custom_edges[player] + if 'two-way' in custom_edges and len(custom_edges['two-way']) > 0: + custom_edges = custom_edges['two-way'] + for edgename1, edgename2 in custom_edges.items(): + if edgename1[-1] != '*' and edgename2[-1] != '*': + edge1 = world.get_owedge(edgename1, player) + edge2 = world.get_owedge(edgename2, player) + if [edge1.owIndex, edge2.owIndex] not in merged_owids and should_merge_group(edge1.owIndex, edge2.owIndex): + merged_owids.append([edge1.owIndex, edge2.owIndex]) + # Check if there are any groups that appear in both sets + if any(group in flipped_groups for group in nonflipped_groups): + raise GenerationException('Conflict found when flipping tiles') + return flipped_groups, nonflipped_groups, undefined_chance, merged_owids + +def shuffle_tiles(world, groups, result_list, do_grouped, forced_flips, player): + (flipped_groups, nonflipped_groups, undefined_chance) = forced_flips swapped_edges = list() group_parity = {} for group_data in groups: @@ -683,54 +1059,19 @@ def shuffle_tiles(world, groups, result_list, do_grouped, player): parity[5] -= 1 group_parity[group[0]] = parity - # customizer adjustments - undefined_chance = 50 - flipped_groups = list() - always_removed = list() - if world.customizer: - if not do_grouped: - custom_flips = world.customizer.get_owtileflips() - if custom_flips and player in custom_flips: - custom_flips = custom_flips[player] - nonflipped_groups = list() - forced_flips = list() - forced_nonflips = list() - if 'undefined_chance' in custom_flips: - undefined_chance = custom_flips['undefined_chance'] - if 'force_flip' in custom_flips: - forced_flips = custom_flips['force_flip'] - if 'force_no_flip' in custom_flips: - forced_nonflips = custom_flips['force_no_flip'] - - for group in groups: - if any(owid in group[0] for owid in forced_nonflips): - nonflipped_groups.append(group) - if any(owid in group[0] for owid in forced_flips): - flipped_groups.append(group) - - # Check if there are any groups that appear in both sets - if any(group in flipped_groups for group in nonflipped_groups): - raise GenerationException('Conflict found when flipping tiles') - - for g in nonflipped_groups: - always_removed.append(g) - if undefined_chance == 0: - for g in [g for g in groups if g not in flipped_groups + always_removed]: - always_removed.append(g) - attempts = 1 if 0 < undefined_chance < 100: # do roughly 1000 attempts at a full list - attempts = len(groups) - len(always_removed) + attempts = len(groups) - len(nonflipped_groups) attempts = (attempts ** 1.9) + (attempts * 10) + 1 while True: if attempts == 0: # expected to only occur with custom flips raise GenerationException('Could not find valid tile flips') # tile shuffle happens here - removed = copy.deepcopy(always_removed) + removed = copy.deepcopy(nonflipped_groups) if 0 < undefined_chance < 100: - for group in [g for g in groups if g not in always_removed]: + for group in [g for g in groups if g not in nonflipped_groups]: if group not in flipped_groups and random.randint(1, 100) > undefined_chance: removed.append(group) @@ -770,7 +1111,7 @@ def shuffle_tiles(world, groups, result_list, do_grouped, player): exist_dw_regions.extend(new_results[2]) # replace LW edges with DW - if world.owCrossed[player] not in ['polar', 'grouped', 'chaos'] or do_grouped: + if world.owCrossed[player] == 'none' or do_grouped: # in polar, the actual edge connections remain vanilla def getSwappedEdges(world, lst, player): for regionname in lst: @@ -784,7 +1125,7 @@ def shuffle_tiles(world, groups, result_list, do_grouped, player): return swapped_edges -def define_tile_groups(world, player, do_grouped): +def define_tile_groups(world, do_grouped, player): groups = [[i, i + 0x40] for i in range(0x40)] def get_group(id): @@ -843,6 +1184,11 @@ def define_tile_groups(world, player, do_grouped): if not world.owWhirlpoolShuffle[player] and (world.owCrossed[player] == 'none' or do_grouped): merge_groups([[0x0f, 0x35], [0x12, 0x15, 0x33, 0x3f]]) + # customizer adjustments + flipped_groups, nonflipped_groups, undefined_chance, merged_owids = determine_forced_flips(world, groups, do_grouped, player) + for owids in merged_owids: + merge_groups([owids]) + tile_groups = [] for group in groups: if can_shuffle_group(group): @@ -852,7 +1198,7 @@ def define_tile_groups(world, player, do_grouped): (lw_regions if id < 0x40 or id >= 0x80 else dw_regions).extend(OWTileRegions.inverse[id]) tile_groups.append((group, lw_regions, dw_regions)) - return tile_groups + return tile_groups, flipped_groups, nonflipped_groups, undefined_chance def remove_reserved(world, groupedlist, connected_edges, player): new_grouping = {} @@ -915,24 +1261,49 @@ def reorganize_groups(world, groups, player): def adjust_edge_groups(world, trimmed_groups, edges_to_swap, player): groups = defaultdict(lambda: ([],[])) + limited_crossed = False + custom_groups = dict() + if world.customizer: + custom_crossed = world.customizer.get_owcrossed() + limited_crossed = custom_crossed and (player in custom_crossed) and ('limit_crossed' in custom_crossed[player]) + custom_edge_groups = world.customizer.get_owedges() + if custom_edge_groups and player in custom_edge_groups: + custom_edge_groups = custom_edge_groups[player] + if 'groups' in custom_edge_groups: + custom_groups = dict(custom_edge_groups['groups']) + for name, edges in custom_groups.items(): + custom_groups[name] = [world.get_owedge(e, player).name if e[-1] == '*' else e for e in edges] for (key, group) in trimmed_groups.items(): - (mode, wrld, dir, terrain, parallel, count) = key + (mode, wrld, dir, terrain, parallel, count, custom) = key if mode == OpenStd.Standard: groups[key] = group else: - if world.owCrossed[player] == 'chaos': - groups[(mode, None, dir, terrain, parallel, count)][0].extend(group[0]) - groups[(mode, None, dir, terrain, parallel, count)][1].extend(group[1]) + if world.owCrossed[player] == 'unrestricted' and not limited_crossed: + groups[(mode, None, dir, terrain, parallel, count, custom)][0].extend(group[0]) + groups[(mode, None, dir, terrain, parallel, count, custom)][1].extend(group[1]) else: for i in range(2): for edge_set in group[i]: new_world = int(wrld) if edge_set[0] in edges_to_swap: new_world += 1 - groups[(mode, WorldType(new_world % 2), dir, terrain, parallel, count)][i].append(edge_set) - return list(groups.values()) + groups[(mode, WorldType(new_world % 2), dir, terrain, parallel, count, custom)][i].append(edge_set) + for (key, group) in groups.copy().items(): + (mode, wrld, dir, terrain, parallel, count, custom) = key + if mode != OpenStd.Standard: + for group_name, edges in custom_groups.items(): + for i in range(0, 2): + matches = [s for s in groups[key][i] if any(e in s for e in edges)] + if len(matches) > 0: + for m in matches: + groups[key][i].remove(m) + groups[(mode, wrld, dir, terrain, parallel, count, group_name)][i].extend(matches) + return groups def create_flute_exits(world, player): + flute_in_pool = True if player not in world.customitemarray else any(i for i, n in world.customitemarray[player].items() if i == 'flute' and n > 0) + if not flute_in_pool: + return for region in (r for r in world.regions if r.player == player and r.terrain == Terrain.Land and r.name not in ['Zoras Domain', 'Master Sword Meadow', 'Hobo Bridge']): if region.type == (RegionType.LightWorld if world.mode[player] != 'inverted' else RegionType.DarkWorld): exitname = 'Flute From ' + region.name @@ -1024,7 +1395,7 @@ def can_reach_smith(world, player): for exit in region.exits: if not found and exit.connected_region is not None: if exit.spot_type == 'Flute': - if any(map(lambda i: i.name == 'Ocarina (Activated)', world.precollected_items)): + if any(map(lambda i: i.name == 'Ocarina (Activated)' and i.player == player, world.precollected_items)): for flutespot in exit.connected_region.exits: if flutespot.connected_region and flutespot.connected_region.name not in explored_regions: explore_region(flutespot.connected_region.name, flutespot.connected_region) @@ -1142,7 +1513,7 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F region = base_world.get_region(region_name, player) for exit in region.exits: if exit.connected_region is not None: - if any(map(lambda i: i.name == 'Ocarina (Activated)', base_world.precollected_items)) and exit.spot_type == 'Flute': + if any(map(lambda i: i.name == 'Ocarina (Activated)' and i.player == player, base_world.precollected_items)) and exit.spot_type == 'Flute': fluteregion = exit.connected_region for flutespot in fluteregion.exits: if flutespot.connected_region and flutespot.connected_region.name not in explored_regions: @@ -1208,7 +1579,8 @@ def validate_layout(world, player): item_entrances = list(zip(*default_item_connections))[0] shop_entrances = list(zip(*default_shop_connections))[0] drop_entrances = list(zip(*default_drop_connections + default_dropexit_connections))[0] - + flute_in_pool = True if player not in world.customitemarray else any(i for i, n in world.customitemarray[player].items() if i == 'flute' and n > 0) + def explore_region(region_name, region=None): if stack_size3a() > 500: raise GenerationException(f'Infinite loop detected for "{region_name}" located at \'validate_layout\'') @@ -1246,11 +1618,12 @@ def validate_layout(world, player): start_region = 'Dark Chapel Area' explore_region(start_region) - if not world.is_tile_swapped(0x30, player): - start_region = 'Desert Teleporter Ledge' - else: - start_region = 'Mire Teleporter Ledge' - explore_region(start_region) + if flute_in_pool: + if not world.is_tile_swapped(0x30, player): + start_region = 'Desert Teleporter Ledge' + else: + start_region = 'Mire Teleporter Ledge' + explore_region(start_region) if not world.is_tile_swapped(0x1b, player): start_region = 'Pyramid Area' @@ -1272,9 +1645,9 @@ def validate_layout(world, player): unreachable_count = len(unreachable_regions) for region_name in reversed(unreachable_regions): # check if can be accessed flute - if unreachable_regions[region_name].type == (RegionType.LightWorld if world.mode[player] != 'inverted' else RegionType.DarkWorld): + if flute_in_pool and unreachable_regions[region_name].type == (RegionType.LightWorld if world.mode[player] != 'inverted' else RegionType.DarkWorld): owid = OWTileRegions[region_name] - if owid < 0x80 and owid % 40 in flute_data and region_name in flute_data[owid][0]: + if owid < 0x80 and owid % 0x40 in flute_data and region_name in flute_data[owid % 0x40][0]: if world.owFluteShuffle[player] != 'vanilla' or owid % 0x40 in default_flute_connections: unreachable_regions.pop(region_name) explore_region(region_name) @@ -1297,7 +1670,11 @@ def validate_layout(world, player): break if unreachable_count != len(unreachable_regions): break - + + if not flute_in_pool: + unreachable_regions.pop('Desert Teleporter Ledge') + unreachable_regions.pop('Mire Teleporter Ledge') + if len(unreachable_regions): return False @@ -1967,7 +2344,8 @@ mirror_connections = { } parallelsimilar_connections = [('Maze Race ES', 'Kakariko Suburb WS'), - ('Dig Game EC', 'Frog WC') + ('Dig Game EC', 'Frog WC'), + ('Dig Game ES', 'Frog WS') ] # non shuffled overworld diff --git a/README.md b/README.md index 0bae614a..ad343b01 100644 --- a/README.md +++ b/README.md @@ -159,9 +159,9 @@ With OW Layout Shuffle, this allows land and water edges to be connected. This allows OW connections to be shuffled cross-world. There are 2 main methodologies of Crossed OWR: -- Grouped and Polar both are guaranteed to result in two separated planes of tiles, similar to that of vanilla. This means you cannot simply walk around and be able to visit all the tiles. To navigate to the other plane, you have the following methods: 1) Normal portals 2) Mirroring on DW tiles 3) Fluting to a tile that was previously unreachable +- `Grouped` and `Polar` both are guaranteed to result in two separated planes of tiles, similar to that of vanilla. This means you cannot simply walk around and be able to visit all the tiles. To navigate to the other plane, you have the following methods: 1) Normal portals 2) Mirroring on DW tiles 3) Fluting to a tile that was previously unreachable -- Limited and Chaos are not bound to follow a two-plane framework. This means that it could be possible to travel on foot to every tile without entering a normal portal. +- `Unrestricted` is not bound to follow a two-plane framework. This means that it could be possible to travel on foot to every tile without entering a normal portal. See each option to get more details on the differences. @@ -171,31 +171,23 @@ Transitions will remain same-world. ### Grouped -This option shuffles connections cross-world in the same manner as Tile Flip (Mixed), the connections coming in and going out of a Tile Group (see `Terminology` section above) are crossed (ie. meaning it is impossible to take a different path to a tile and end up in the opposite world, unlike Limited and Chaos). This is considered the simplest way to play Crossed OWR. +This option shuffles connections cross-world in the same manner as Tile Flip (Mixed), the connections coming in and going out of a Tile Group (see `Terminology` section above) are crossed (ie. meaning it is impossible to take a different path to a tile and end up in the opposite world, unlike `Unrestricted`). This is considered the simplest way to play Crossed OWR. ### Polar Only effective if Tile Flip (Mixed) is enabled. Polar follows the same principle as Grouped, except that it preserves the original/vanilla connections even when tiles are flipped/mixed. This results in a completely vanilla overworld, except that some tiles will transform Link to a Bunny. Even though these tiles give the appearance of your normal LW tile, due to how Tile Flip works, those LW tiles give DW properties (such as bunnying, ability to mirror, and prevents flute usage). This offers an interesting twist on Mixed where you have a pre-conditioned knowledge of the terrain you will encounter, but not necessarily be able to do what you need to do there, due to bunny state. (see `Tile Flip / Mixed` section for more details) -### Limited +### Unrestricted -Every transition is independently a candidate to be chosen as a cross-world connection, however only 9 total transitions become crossed (to/from each world). This option abides by the `Keep Similar Edges Together` option and will guarantee same effect on all edges in a Similar Edge group if enabled. If a Similar Edge group is chosen from the pool of candidates, it only counts as one portal, not multiple. +Every transition is independently a candidate to be chosen as a cross-world connection. This option abides by the `Keep Similar Edges Together` option and will guarantee same effect on all edges in a Similar Edge group if enabled. If a Similar Edge group is chosen from the pool of candidates, it only counts as one portal, not multiple. Each transition has an equal 50/50 chance of being a crossed connection. -Note: Only parallel connections (a connection that also exists in the opposite world) are considered for cross-world connections, which means that the same connection in the opposite world will also connect cross-world. - -Note: If Whirlpool Shuffle is enabled, those connections can be cross-world but do not count towards the 9 transitions that are crossed. - -Motive: Why 9 connections? To imitate the effect of the 9 existing standard portals. - -### Chaos - -Same as Limited, except that there is no limit to the number of cross-world connections that are made. Each transition has an equal 50/50 chance of being a crossed connection. +Note: If Whirlpool Shuffle is enabled, those connections can be cross-world. ## Keep Similar Edges Together (--ow_keepsimilar) This keeps similar edge transitions together. ie. The 2 west land edges of Potion Shop will be paired to another set of two similar edges, unless Free Terrain is also enabled, in which case these 2 edges together with the west water edge form a group of 3 similar edges. See `Terminology` section above for a more detailed explanation of Similar Edges. -Note: This affects OW Layout Shuffle mostly, but also affects Limited and Chaos modes in Crossed OW. +Note: This affects OW Layout Shuffle mostly, but also affects `Unrestricted` mode in Crossed OW. ## Tile Flip / Mixed Overworld (--ow_mixed) diff --git a/Rom.py b/Rom.py index 559ef2b8..27a1a38f 100644 --- a/Rom.py +++ b/Rom.py @@ -740,7 +740,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): elif world.owShuffle[player] == 'full': owMode = 2 - if world.owKeepSimilar[player] and (world.owShuffle[player] != 'vanilla' or world.owCrossed[player] in ['limited', 'chaos']): + if world.owKeepSimilar[player] and (world.owShuffle[player] != 'vanilla' or world.owCrossed[player] == 'unrestricted'): owMode |= 0x0100 if world.owCrossed[player] != 'none' and (world.owCrossed[player] != 'polar' or world.owMixed[player]): owMode |= 0x0200 diff --git a/TestSuiteStat.py b/TestSuiteStat.py index ecde323d..882f9ffb 100644 --- a/TestSuiteStat.py +++ b/TestSuiteStat.py @@ -49,7 +49,7 @@ SETTINGS = { 'ow_fluteshuffle': ['balanced'], 'ow_keepsimilar': [True, False], 'ow_mixed': [True, False], - 'ow_crossed': ['none', 'polar', 'grouped', 'limited'], + 'ow_crossed': ['none', 'polar', 'grouped', 'unrestricted'], 'accessibility': [True], 'difficulty': [False], 'shufflepots': [False], diff --git a/docs/Customizer.md b/docs/Customizer.md index 68687c23..872003c5 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -87,9 +87,62 @@ You may define an item, and a list of locations. The locations may be weighted i You may define an item and a list of locations that an item should not be placed at. This will apply to all items of that type. The logic is considered for this. If it is otherwise impossible, the item will be considered for the listed locations. This is important for small key layouts mostly, but it will try other locations first. +### ow-edges + +This must be defined by player. Each player number should be listed with the appropriate sections and each of these players MUST have either `ow_shuffle` or `ow_crossed` enabled in the `settings` section in order for any values here to take effect. This section has two primary subsections: `two-way` and `groups`. + +#### two-way + +`two-way` should be used for defining overworld edge transition connections. An asterisk `*` at the end of an edge name can be used on any parallel edge (an edge that exists in the same place in the opposite world), this will swap the defined edge with its parallel edge if the tile is flipped by Tile Flip. + +`Links House ES*: Stone Bridge WS*` The edge east of Links House will be vanilla, but if Links House screen gets flipped by Tile Flip, then Big Bomb Shop ES will connect to Stone Bridge. + +#### groups + +`groups` should be used for defining new pool divisions of overworld edge transitions. Each group must have some unique name with all the edges listed that are desired to exist in the pool. The name of a group can be anything as long as it is valid yaml syntax. These defined groups cannot break up edges that conflict with mode settings, like `Keep Similar Edges Together`. The asterisk `*` notation, described in the `ow-edges/two-way` section, can be used here. + +This example puts these 2 edges in their own pool, while the rest of the edges remain in their existing pools: +``` +someDescription: + - Links House ES* + - Stone Bridge WS* +``` + +### ow-crossed + +This must be defined by player. Each player number should be listed with the appropriate sections and each of these players MUST have `ow_crossed` enabled in the `settings` section in order for any values here to take effect. This section has four primary subsections: `force_crossed`, `force_noncrossed`, `limit_crossed`, and `undefined_chance`. There are also + +#### force_crossed / force_noncrossed + +`force_crossed` and `force_noncrossed` should be used to define specific overworld edge transitions you wish to be cross-world connected without needing to specify an exact destination. These sections are optional but must contain a list of edge names. The asterisk `*` notation, described in the `ow-edges/two-way` section, can be used here. + +#### limit_crossed + +`limit_crossed` should be used to limit how many overworld edge transitions end up connecting cross-world. This value can be set to any non-negative integer. A value of 0 means no edges will be cross-world, except for edges that are forced cross-world (either by the previous step or a result of some combination of OWR settings). This option only takes effect in `Unrestricted` Crossed setting. + +#### undefined_chance + +`undefined_chance` should be used to determine how to handle all the remaining overworld edge transitions that aren't explicitly defined in the earlier steps. This represents the percent chance an edge will be cross-world. This value can be set from 0 to 100 (default is 50). A value of 0 means there is a 0% chance it will be cross-world. This option only takes effect under two mode combinations: +- 1: `Unrestricted` Crossed with a `Vanilla` OW Layout +- 2: `Grouped` Crossed + +#### (Grouped specific options) + +All four options available in the `ow-tileflips` section below are also available for `Grouped`, but must be defined under the `ow-crossed` section. In addition to the previous `undefined_chance`, the three other subsections are: `force_flip`, `force_no_flip`, and `force_together`. For more information about these sections, see the `ow-tileflips` section below. + +### ow-whirlpools + +This must be defined by player. Each player number should be listed with the appropriate sections and each of these players MUST have `ow_whirlpool: true` in the `settings` section in order for any values here to take effect. This section has one primary subsection: `two-way`. + +#### two-way + +`two-way` should be used for defining whirlpool connections. + +`River Bend Whirlpool: Lake Hylia Whirlpool` The whirlpool west of Potion Shop will be connected to the whirlpool at Lake Hylia. + ### ow-tileflips -This must be defined by player. Each player number should be listed with the appropriate sections and each of these players MUST have `ow_mixed: true` in the `settings` section in order for any values here to take effect. This section has three primary subsections: `force_flip`, `force_no_flip`, and `undefined_chance`. +This must be defined by player. Each player number should be listed with the appropriate sections and each of these players MUST have `ow_mixed: true` in the `settings` section in order for any values here to take effect. This section has four primary subsections: `force_flip`, `force_no_flip`, `force_together`, and `undefined_chance`. #### force_flip / force_no_flip @@ -106,6 +159,17 @@ force_no_flip: - 0x13 ``` +#### force_together + +`force_together` should be used for defining tiles you want to force to flip as a group. Each group must have some unique name with all the OW Screen IDs listed that are desired to be grouped together. The name of a group can be anything as long as it is valid yaml syntax. + +Here is an example which forces Links House and Sanctuary screens to flip together: +``` +someGroup: + - 0x2c + - 0x13 +``` + #### undefined_chance `undefined_chance` should be used to determine how to handle all the remaining tiles that aren't explicitly defined in the earlier step. This represents the percent chance a tile will flip. This value can be set from 0 to 100 (default is 50). A value of 0 means there is a 0% chance it will be flipped. diff --git a/docs/customizer_example.yaml b/docs/customizer_example.yaml index ecf209b1..75c997bc 100644 --- a/docs/customizer_example.yaml +++ b/docs/customizer_example.yaml @@ -69,6 +69,36 @@ placements: Palace of Darkness - Big Chest: Hammer Capacity Upgrade - Left: Moon Pearl Turtle Rock - Pokey 2 Key Drop: Ice Rod +ow-edges: + 1: + two-way: + Kakariko Fortune ES*: Sanctuary WN* + Central Bonk Rocks EC: Potion Shop WN + Central Bonk Rocks ES: Potion Shop WC + groups: + someDescription: + - Tree Line SC* + - Lake Hylia NC* + - Dark Tree Line SC* + - Ice Lake NC* + 1234: + - Lake Hylia EC* + - Octoballoon WC* + - Ice Lake EC* + - Bomber Corner WC* +ow-crossed: + 1: + force_crossed: + - Links House ES* + - Kakariko Fortune ES* + force_noncrossed: + - Links House NE + limit_crossed: 9 # emulates Limited Crossed + undefined_chance: 25 +ow-whirlpools: + 1: + two-way: + River Bend Whirlpool: Lake Hylia Whirlpool ow-tileflips: 1: force_flip: @@ -76,6 +106,10 @@ ow-tileflips: force_no_flip: - 0x2c - 0x18 + force_together: + someDescription: + - 0x16 + - 0x2b undefined_chance: 50 ow-flutespots: 1: diff --git a/docs/presets/Swapkeys.yaml b/docs/presets/Swapkeys.yaml deleted file mode 100644 index 20b7e88b..00000000 --- a/docs/presets/Swapkeys.yaml +++ /dev/null @@ -1,22 +0,0 @@ -meta: - branch: OWR - seed_name: Swapkeys - seed_notes: Crosskeys but Swapped ER -settings: - 1: - mode: open - logic: noglitches - goal: crystals - crystals_gt: "7" - crystals_ganon: "7" - accessibility: locations - mapshuffle: 1 - compassshuffle: 1 - keyshuffle: wild - bigkeyshuffle: 1 - shuffle: swapped - shuffleganon: 1 - shufflelinks: 0 - shuffletavern: 1 - experimental: 0 - hints: 0 diff --git a/docs/presets/swapkeys.yml b/docs/presets/swapkeys.yml deleted file mode 100644 index e71e4521..00000000 --- a/docs/presets/swapkeys.yml +++ /dev/null @@ -1,17 +0,0 @@ -settings: - 1: - description: Swapkeys - glitches_required: none - mode: open - goal: crystals - crystals_gt: "7" - crystals_ganon: "7" - weapons: randomized - accessibility: locations - entrance_shuffle: swapped - shufflelinks: off - shuffletavern: on - mapshuffle: on - compassshuffle: on - keyshuffle: wild - bigkeyshuffle: on diff --git a/docs/vanilla_multi_lobbies.yaml b/docs/vanilla_multi_lobbies.yaml deleted file mode 100644 index 06eaf835..00000000 --- a/docs/vanilla_multi_lobbies.yaml +++ /dev/null @@ -1,28 +0,0 @@ -doors: - 1: - lobbies: - #Agahnims Tower: Tower Lobby S - Desert Back: Desert Back Lobby S - Desert East: Desert East Lobby S - Desert South: Desert Main Lobby S - Desert West: Desert West S - #Eastern: Eastern Lobby S - #Ganons Tower: GT Lobby S - #Hera: Hera Lobby S - Hyrule Castle East: Hyrule Castle East Lobby S - Hyrule Castle South: Hyrule Castle Lobby S - Hyrule Castle West: Hyrule Castle West Lobby S - #Ice: Ice Lobby SE - #Mire: Mire Lobby S - #Palace of Darkness: PoD Lobby S - #Sanctuary: Sanctuary S - #Skull 1: Skull 1 Lobby S - #Skull 2 East: Skull 2 East Lobby SW - #Skull 2 West: Skull 2 West Lobby S - #Skull 3: Skull 3 Lobby SW - #Swamp: Swamp Lobby S - #Thieves Town: Thieves Lobby S - Turtle Rock Chest: TR Big Chest Entrance SE - Turtle Rock Eye Bridge: TR Eye Bridge SW - Turtle Rock Lazy Eyes: TR Lazy Eyes SE - Turtle Rock Main: TR Main Lobby SE diff --git a/mystery_example.yml b/mystery_example.yml index 3e65a483..dbb455d7 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -10,8 +10,7 @@ none: 4 polar: 1 grouped: 1 - limited: 1 - chaos: 1 + unrestricted: 1 overworld_keepsimilar: on: 1 off: 1 diff --git a/presets/world/owr_crossed-limited.yaml b/presets/world/owr_crossed-limited.yaml new file mode 100644 index 00000000..54d07a32 --- /dev/null +++ b/presets/world/owr_crossed-limited.yaml @@ -0,0 +1,6 @@ +settings: + 1: + ow_crossed: unrestricted +ow-crossed: + 1: + limit_crossed: 9 \ No newline at end of file diff --git a/presets/world/owr_crossed-max.yaml b/presets/world/owr_crossed-max.yaml new file mode 100644 index 00000000..63409850 --- /dev/null +++ b/presets/world/owr_crossed-max.yaml @@ -0,0 +1,7 @@ +settings: + 1: + ow_crossed: unrestricted +ow-crossed: + 1: + limit_crossed: 9999 + undefined_chance: 100 \ No newline at end of file diff --git a/presets/world/owr_districtshuffle-full.yaml b/presets/world/owr_districtshuffle-full.yaml new file mode 100644 index 00000000..6ce0ac7a --- /dev/null +++ b/presets/world/owr_districtshuffle-full.yaml @@ -0,0 +1,286 @@ +settings: + 1: + ow_shuffle: full + ow_keepsimilar: false +ow-edges: + 1: + groups: + NorthwestHyrule: + - Lost Woods NW + - Master Sword Meadow SC + - Lost Woods EN* + - Lumberjack WN* + - Lost Woods SW* + - Lost Woods Pass NW* + - Lost Woods SC* + - Lost Woods Pass NE* + - Lost Woods SE* + - Kakariko Fortune NE* + - Lumberjack SW* + - Mountain Pass NW* + - Mountain Pass SE* + - Kakariko Pond NE* + - Kakariko Fortune EN* + - Kakariko Pond WN* + - Kakariko Fortune ES* + - Kakariko Pond WS* + - Kakariko Pond EN* + - Sanctuary WN* + - Kakariko Pond ES* + - Sanctuary WS* + - Kakariko Pond SW* + - Forgotten Forest NW* + - Kakariko Pond SE* + - Forgotten Forest NE* + - Sanctuary EC* + - Graveyard WC* + - Graveyard EC* + - River Bend WC* + DeathMountain: + - West Death Mountain EN* + - East Death Mountain WN* + - West Death Mountain ES* + - East Death Mountain WS* + - East Death Mountain EN* + - Death Mountain TR Pegs WN* + EasternHyrule: + - Zora Waterfall NE + - Zoras Domain SW + - Zora Waterfall SE* + - Zora Approach NE* + - River Bend EN* + - Potion Shop WN* + - River Bend EC* + - Potion Shop WC* + - River Bend ES* + - Potion Shop WS* + - River Bend SC* + - Wooden Bridge NC* + - River Bend SE* + - Wooden Bridge NE* + - Potion Shop EN* + - Zora Approach WN* + - Potion Shop EC* + - Zora Approach WC* + - Wooden Bridge SW* + - Sand Dunes NW* + - Eastern Palace SW* + - Tree Line NW* + - Eastern Palace SE* + - Eastern Nook NE* + - Sand Dunes SC* + - Stone Bridge NC* + - Stone Bridge EN* + - Tree Line WN* + Kakariko: + - Kakariko ES* + - Blacksmith WS* + - Kakariko SE* + - Kakariko Suburb NE* + - Maze Race ES* + - Kakariko Suburb WS* + CentralHyrule: + - Hyrule Castle SW* + - Central Bonk Rocks NW* + - Hyrule Castle SE* + - Links House NE* + - Flute Boy SW* + - Flute Boy Approach NW* + - Flute Boy SC* + - Flute Boy Approach NC* + - Central Bonk Rocks EN* + - Links House WN* + - Central Bonk Rocks EC* + - Links House WC* + - Central Bonk Rocks ES* + - Links House WS* + - Central Bonk Rocks SW* + - C Whirlpool NW* + - Links House SC* + - Statues NC* + - Flute Boy Approach EC* + - C Whirlpool WC* + - C Whirlpool EN* + - Statues WN* + - C Whirlpool EC* + - Statues WC* + - C Whirlpool ES* + - Statues WS* + - C Whirlpool SC* + - Dam NC* + - Statues SC* + - South Pass NC* + - Dam EC* + - South Pass WC* + LakeHylia: + - Stone Bridge WC + - Hobo EC + - Stone Bridge EC* + - Tree Line WC* + - Stone Bridge SC* + - Lake Hylia NW* + - Tree Line SC* + - Lake Hylia NC* + - Lake Hylia WS* + - South Pass ES* + - Lake Hylia EC* + - Octoballoon WC* + - Lake Hylia ES* + - Octoballoon WS* + - Ice Cave SW* + - Octoballoon NW* + - Ice Cave SE* + - Octoballoon NE* + Desert: + - Desert EC + - Desert Pass WC + - Desert ES + - Desert Pass WS + NorthwestDarkWorld: + - Skull Woods EN* + - Dark Lumberjack WN* + - Skull Woods SW* + - Skull Woods Pass NW* + - Skull Woods SC* + - Skull Woods Pass NE* + - Skull Woods SE* + - Dark Fortune NE* + - Dark Lumberjack SW* + - Bumper Cave NW* + - Bumper Cave SE* + - Outcast Pond NE* + - Skull Woods Pass SW* + - Village of Outcasts NW* + - Skull Woods Pass SE* + - Village of Outcasts NC* + - Dark Fortune EN* + - Outcast Pond WN* + - Dark Fortune ES* + - Outcast Pond WS* + - Dark Fortune SC* + - Village of Outcasts NE* + - Outcast Pond EN* + - Dark Chapel WN* + - Outcast Pond ES* + - Dark Chapel WS* + - Outcast Pond SW* + - Shield Shop NW* + - Outcast Pond SE* + - Shield Shop NE* + - Dark Chapel EC* + - Dark Graveyard WC* + - Dark Graveyard EC* + - Qirn Jump WC* + - Village of Outcasts ES* + - Hammer Pegs WS* + DarkDeathMountain: + - West Dark Death Mountain EN* + - East Dark Death Mountain WN* + - West Dark Death Mountain ES* + - East Dark Death Mountain WS* + - East Dark Death Mountain EN* + - Turtle Rock WN* + EastDarkWorld: + - Catfish SE* + - Catfish Approach NE* + - Dark Witch EN* + - Catfish Approach WN* + - Dark Witch EC* + - Catfish Approach WC* + - Qirn Jump EN* + - Dark Witch WN* + - Qirn Jump EC* + - Dark Witch WC* + - Qirn Jump ES* + - Dark Witch WS* + - Qirn Jump SC* + - Broken Bridge NC* + - Qirn Jump SE* + - Broken Bridge NE* + - Broken Bridge SW* + - Dark Dunes NW* + - Pyramid ES* + - Dark Dunes WN* + - Dark Dunes SC* + - Hammer Bridge NC* + - Palace of Darkness SW* + - Dark Tree Line NW* + - Palace of Darkness SE* + - Palace of Darkness Nook NE* + - Hammer Bridge EN* + - Dark Tree Line WN* + SouthDarkWorld: + - Dig Game EC + - Frog WC + - Dig Game ES* + - Frog WS* + - Frog ES* + - Stumpy WS* + - Stumpy SW* + - Stumpy Approach NW* + - Stumpy SC* + - Stumpy Approach NC* + - Dark Bonk Rocks EN* + - Big Bomb Shop WN* + - Dark Bonk Rocks EC* + - Big Bomb Shop WC* + - Dark Bonk Rocks ES* + - Big Bomb Shop WS* + - Dark Bonk Rocks SW* + - Dark C Whirlpool NW* + - Big Bomb Shop SC* + - Hype Cave NC* + - Big Bomb Shop ES* + - Hammer Bridge WS* + - Hammer Bridge EC* + - Dark Tree Line WC* + - Hammer Bridge SC* + - Ice Lake NW* + - Dark Tree Line SC* + - Ice Lake NC* + - Stumpy Approach EC* + - Dark C Whirlpool WC* + - Dark C Whirlpool EN* + - Hype Cave WN* + - Dark C Whirlpool EC* + - Hype Cave WC* + - Dark C Whirlpool ES* + - Hype Cave WS* + - Dark C Whirlpool SC* + - Swamp NC* + - Hype Cave SC* + - Dark South Pass NC* + - Ice Lake WS* + - Dark South Pass ES* + - Ice Lake EC* + - Bomber Corner WC* + - Ice Lake ES* + - Bomber Corner WS* + - Shopping Mall SW* + - Bomber Corner NW* + - Shopping Mall SE* + - Bomber Corner NE* + - Swamp Nook EC* + - Swamp WC* + - Swamp Nook ES* + - Swamp WS* + - Swamp EC* + - Dark South Pass WC* +ow-tileflips: + 1: + force_no_flips: + - 0x30 + - 0x3a + force_together: + LostWoodsPedestal: + - 0x00 + - 0x80 + ZoraWaterfall: + - 0x0f + - 0x81 + MazeRaceSuburb: + - 0x28 + - 0x29 + HyruleCastleWest: + - 0x1a + - 0x1b \ No newline at end of file diff --git a/presets/world/owr_districtshuffle-pangea.yaml b/presets/world/owr_districtshuffle-pangea.yaml new file mode 100644 index 00000000..e4d1ff3c --- /dev/null +++ b/presets/world/owr_districtshuffle-pangea.yaml @@ -0,0 +1,151 @@ +settings: + 1: + ow_shuffle: full + ow_keepsimilar: false +ow-edges: + 1: + two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods EN*: Lumberjack WN* + Lost Woods SW*: Lost Woods Pass NW* + Lost Woods SC*: Lost Woods Pass NE* + Lost Woods SE*: Kakariko Fortune NE* + Lumberjack SW*: Mountain Pass NW* + Mountain Pass SE*: Kakariko Pond NE* + Kakariko Fortune EN*: Kakariko Pond WN* + Kakariko Fortune ES*: Kakariko Pond WS* + Kakariko Pond EN*: Sanctuary WN* + Kakariko Pond ES*: Sanctuary WS* + Kakariko Pond SW*: Forgotten Forest NW* + Kakariko Pond SE*: Forgotten Forest NE* + Sanctuary EC*: Graveyard WC* + Graveyard EC*: River Bend WC* + + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + + Zora Waterfall NE: Zoras Domain SW + Zora Waterfall SE*: Zora Approach NE* + River Bend EN*: Potion Shop WN* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WS* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NE* + Potion Shop EN*: Zora Approach WN* + Potion Shop EC*: Zora Approach WC* + Wooden Bridge SW*: Sand Dunes NW* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Sand Dunes SC*: Stone Bridge NC* + Stone Bridge EN*: Tree Line WN* + + Kakariko ES*: Blacksmith WS* + Kakariko SE*: Kakariko Suburb NE* + Maze Race ES*: Kakariko Suburb WS* + + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Flute Boy SW*: Flute Boy Approach NW* + Flute Boy SC*: Flute Boy Approach NC* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Central Bonk Rocks SW*: C Whirlpool NW* + Links House SC*: Statues NC* + Flute Boy Approach EC*: C Whirlpool WC* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + C Whirlpool SC*: Dam NC* + Statues SC*: South Pass NC* + Dam EC*: South Pass WC* + + Stone Bridge WC: Hobo EC + Stone Bridge EC*: Tree Line WC* + Stone Bridge SC*: Lake Hylia NW* + Tree Line SC*: Lake Hylia NC* + Lake Hylia WS*: South Pass ES* + Lake Hylia EC*: Octoballoon WC* + Lake Hylia ES*: Octoballoon WS* + Ice Cave SW*: Octoballoon NW* + Ice Cave SE*: Octoballoon NE* + + Desert EC: Desert Pass WC + Desert ES: Desert Pass WS + + Skull Woods EN*: Dark Lumberjack WN* + Skull Woods SW*: Skull Woods Pass NW* + Skull Woods SC*: Skull Woods Pass NE* + Skull Woods SE*: Dark Fortune NE* + Dark Lumberjack SW*: Bumper Cave NW* + Bumper Cave SE*: Outcast Pond NE* + Skull Woods Pass SW*: Village of Outcasts NW* + Skull Woods Pass SE*: Village of Outcasts NC* + Dark Fortune EN*: Outcast Pond WN* + Dark Fortune ES*: Outcast Pond WS* + Dark Fortune SC*: Village of Outcasts NE* + Outcast Pond EN*: Dark Chapel WN* + Outcast Pond ES*: Dark Chapel WS* + Outcast Pond SW*: Shield Shop NW* + Outcast Pond SE*: Shield Shop NE* + Dark Chapel EC*: Dark Graveyard WC* + Dark Graveyard EC*: Qirn Jump WC* + Village of Outcasts ES*: Hammer Pegs WS* + + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Dark Death Mountain EN*: Turtle Rock WN* + + Catfish SE*: Catfish Approach NE* + Dark Witch EN*: Catfish Approach WN* + Dark Witch EC*: Catfish Approach WC* + Qirn Jump EN*: Dark Witch WN* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WS* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NE* + Broken Bridge SW*: Dark Dunes NW* + Pyramid ES*: Dark Dunes WN* + Dark Dunes SC*: Hammer Bridge NC* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* + Hammer Bridge EN*: Dark Tree Line WN* + + Dig Game EC: Frog WC + Dig Game ES*: Frog WS* + Frog ES*: Stumpy WS* + Stumpy SW*: Stumpy Approach NW* + Stumpy SC*: Stumpy Approach NC* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Big Bomb Shop SC*: Hype Cave NC* + Big Bomb Shop ES*: Hammer Bridge WS* + Hammer Bridge EC*: Dark Tree Line WC* + Hammer Bridge SC*: Ice Lake NW* + Dark Tree Line SC*: Ice Lake NC* + Stumpy Approach EC*: Dark C Whirlpool WC* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Dark C Whirlpool SC*: Swamp NC* + Hype Cave SC*: Dark South Pass NC* + Ice Lake WS*: Dark South Pass ES* + Ice Lake EC*: Bomber Corner WC* + Ice Lake ES*: Bomber Corner WS* + Shopping Mall SW*: Bomber Corner NW* + Shopping Mall SE*: Bomber Corner NE* + Swamp Nook EC*: Swamp WC* + Swamp Nook ES*: Swamp WS* + Swamp EC*: Dark South Pass WC* +ow-tileflips: + 1: + force_no_flips: + - 0x30 + - 0x3a + force_together: + HyruleCastleWest: + - 0x1a + - 0x1b \ No newline at end of file diff --git a/presets/world/owr_districtshuffle-vanillaborders.yaml b/presets/world/owr_districtshuffle-vanillaborders.yaml new file mode 100644 index 00000000..6e622648 --- /dev/null +++ b/presets/world/owr_districtshuffle-vanillaborders.yaml @@ -0,0 +1,300 @@ +settings: + 1: + ow_shuffle: full + ow_keepsimilar: false +ow-edges: + 1: + two-way: + Lost Woods Pass SW*: Kakariko NW* + Lost Woods Pass SE*: Kakariko NC* + Kakariko Fortune SC*: Kakariko NE* + River Bend SW*: Wooden Bridge NW* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle ES*: Sand Dunes WN* + Kakariko Suburb ES*: Flute Boy WS* + Links House ES*: Stone Bridge WS* + Tree Line SE*: Lake Hylia NE* + Desert Pass EC*: Dam WC* + Desert Pass ES*: Dam WS* + Qirn Jump SW*: Broken Bridge NW* + Village of Outcasts SE*: Frog NE* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Dark Tree Line SE*: Ice Lake NE* + groups: + NorthwestHyrule: + - Lost Woods NW + - Master Sword Meadow SC + - Lost Woods EN* + - Lumberjack WN* + - Lost Woods SW* + - Lost Woods Pass NW* + - Lost Woods SC* + - Lost Woods Pass NE* + - Lost Woods SE* + - Kakariko Fortune NE* + - Lumberjack SW* + - Mountain Pass NW* + - Mountain Pass SE* + - Kakariko Pond NE* + - Kakariko Fortune EN* + - Kakariko Pond WN* + - Kakariko Fortune ES* + - Kakariko Pond WS* + - Kakariko Pond EN* + - Sanctuary WN* + - Kakariko Pond ES* + - Sanctuary WS* + - Kakariko Pond SW* + - Forgotten Forest NW* + - Kakariko Pond SE* + - Forgotten Forest NE* + - Sanctuary EC* + - Graveyard WC* + - Graveyard EC* + - River Bend WC* + DeathMountain: + - West Death Mountain EN* + - East Death Mountain WN* + - West Death Mountain ES* + - East Death Mountain WS* + - East Death Mountain EN* + - Death Mountain TR Pegs WN* + EasternHyrule: + - Zora Waterfall NE + - Zoras Domain SW + - Zora Waterfall SE* + - Zora Approach NE* + - River Bend EN* + - Potion Shop WN* + - River Bend EC* + - Potion Shop WC* + - River Bend ES* + - Potion Shop WS* + - River Bend SC* + - Wooden Bridge NC* + - River Bend SE* + - Wooden Bridge NE* + - Potion Shop EN* + - Zora Approach WN* + - Potion Shop EC* + - Zora Approach WC* + - Wooden Bridge SW* + - Sand Dunes NW* + - Eastern Palace SW* + - Tree Line NW* + - Eastern Palace SE* + - Eastern Nook NE* + - Sand Dunes SC* + - Stone Bridge NC* + - Stone Bridge EN* + - Tree Line WN* + Kakariko: + - Kakariko ES* + - Blacksmith WS* + - Kakariko SE* + - Kakariko Suburb NE* + - Maze Race ES* + - Kakariko Suburb WS* + CentralHyrule: + - Hyrule Castle SW* + - Central Bonk Rocks NW* + - Hyrule Castle SE* + - Links House NE* + - Flute Boy SW* + - Flute Boy Approach NW* + - Flute Boy SC* + - Flute Boy Approach NC* + - Central Bonk Rocks EN* + - Links House WN* + - Central Bonk Rocks EC* + - Links House WC* + - Central Bonk Rocks ES* + - Links House WS* + - Central Bonk Rocks SW* + - C Whirlpool NW* + - Links House SC* + - Statues NC* + - Flute Boy Approach EC* + - C Whirlpool WC* + - C Whirlpool EN* + - Statues WN* + - C Whirlpool EC* + - Statues WC* + - C Whirlpool ES* + - Statues WS* + - C Whirlpool SC* + - Dam NC* + - Statues SC* + - South Pass NC* + - Dam EC* + - South Pass WC* + LakeHylia: + - Stone Bridge WC + - Hobo EC + - Stone Bridge EC* + - Tree Line WC* + - Stone Bridge SC* + - Lake Hylia NW* + - Tree Line SC* + - Lake Hylia NC* + - Lake Hylia WS* + - South Pass ES* + - Lake Hylia EC* + - Octoballoon WC* + - Lake Hylia ES* + - Octoballoon WS* + - Ice Cave SW* + - Octoballoon NW* + - Ice Cave SE* + - Octoballoon NE* + Desert: + - Desert EC + - Desert Pass WC + - Desert ES + - Desert Pass WS + NorthwestDarkWorld: + - Skull Woods EN* + - Dark Lumberjack WN* + - Skull Woods SW* + - Skull Woods Pass NW* + - Skull Woods SC* + - Skull Woods Pass NE* + - Skull Woods SE* + - Dark Fortune NE* + - Dark Lumberjack SW* + - Bumper Cave NW* + - Bumper Cave SE* + - Outcast Pond NE* + - Skull Woods Pass SW* + - Village of Outcasts NW* + - Skull Woods Pass SE* + - Village of Outcasts NC* + - Dark Fortune EN* + - Outcast Pond WN* + - Dark Fortune ES* + - Outcast Pond WS* + - Dark Fortune SC* + - Village of Outcasts NE* + - Outcast Pond EN* + - Dark Chapel WN* + - Outcast Pond ES* + - Dark Chapel WS* + - Outcast Pond SW* + - Shield Shop NW* + - Outcast Pond SE* + - Shield Shop NE* + - Dark Chapel EC* + - Dark Graveyard WC* + - Dark Graveyard EC* + - Qirn Jump WC* + - Village of Outcasts ES* + - Hammer Pegs WS* + DarkDeathMountain: + - West Dark Death Mountain EN* + - East Dark Death Mountain WN* + - West Dark Death Mountain ES* + - East Dark Death Mountain WS* + - East Dark Death Mountain EN* + - Turtle Rock WN* + EastDarkWorld: + - Catfish SE* + - Catfish Approach NE* + - Dark Witch EN* + - Catfish Approach WN* + - Dark Witch EC* + - Catfish Approach WC* + - Qirn Jump EN* + - Dark Witch WN* + - Qirn Jump EC* + - Dark Witch WC* + - Qirn Jump ES* + - Dark Witch WS* + - Qirn Jump SC* + - Broken Bridge NC* + - Qirn Jump SE* + - Broken Bridge NE* + - Broken Bridge SW* + - Dark Dunes NW* + - Pyramid ES* + - Dark Dunes WN* + - Dark Dunes SC* + - Hammer Bridge NC* + - Palace of Darkness SW* + - Dark Tree Line NW* + - Palace of Darkness SE* + - Palace of Darkness Nook NE* + - Hammer Bridge EN* + - Dark Tree Line WN* + SouthDarkWorld: + - Dig Game EC + - Frog WC + - Dig Game ES* + - Frog WS* + - Frog ES* + - Stumpy WS* + - Stumpy SW* + - Stumpy Approach NW* + - Stumpy SC* + - Stumpy Approach NC* + - Dark Bonk Rocks EN* + - Big Bomb Shop WN* + - Dark Bonk Rocks EC* + - Big Bomb Shop WC* + - Dark Bonk Rocks ES* + - Big Bomb Shop WS* + - Dark Bonk Rocks SW* + - Dark C Whirlpool NW* + - Big Bomb Shop SC* + - Hype Cave NC* + - Big Bomb Shop ES* + - Hammer Bridge WS* + - Hammer Bridge EC* + - Dark Tree Line WC* + - Hammer Bridge SC* + - Ice Lake NW* + - Dark Tree Line SC* + - Ice Lake NC* + - Stumpy Approach EC* + - Dark C Whirlpool WC* + - Dark C Whirlpool EN* + - Hype Cave WN* + - Dark C Whirlpool EC* + - Hype Cave WC* + - Dark C Whirlpool ES* + - Hype Cave WS* + - Dark C Whirlpool SC* + - Swamp NC* + - Hype Cave SC* + - Dark South Pass NC* + - Ice Lake WS* + - Dark South Pass ES* + - Ice Lake EC* + - Bomber Corner WC* + - Ice Lake ES* + - Bomber Corner WS* + - Shopping Mall SW* + - Bomber Corner NW* + - Shopping Mall SE* + - Bomber Corner NE* + - Swamp Nook EC* + - Swamp WC* + - Swamp Nook ES* + - Swamp WS* + - Swamp EC* + - Dark South Pass WC* +ow-tileflips: + 1: + force_no_flips: + - 0x30 + - 0x3a + force_together: + LostWoodsPedestal: + - 0x00 + - 0x80 + ZoraWaterfall: + - 0x0f + - 0x81 + MazeRaceSuburb: + - 0x28 + - 0x29 \ No newline at end of file diff --git a/presets/world/owr_quadrantshuffle-full.yaml b/presets/world/owr_quadrantshuffle-full.yaml new file mode 100644 index 00000000..8538f709 --- /dev/null +++ b/presets/world/owr_quadrantshuffle-full.yaml @@ -0,0 +1,298 @@ +ow-edges: + 1: + groups: + northwest: + - Lost Woods NW + - Lost Woods EN + - Lost Woods SW + - Lost Woods SC + - Lost Woods SE + - Skull Woods EN + - Skull Woods SW + - Skull Woods SC + - Skull Woods SE + - Lumberjack WN + - Lumberjack SW + - Dark Lumberjack WN + - Dark Lumberjack SW + - Mountain Pass NW + - Mountain Pass SE + - Bumper Cave NW + - Bumper Cave SE + - Lost Woods Pass NW + - Lost Woods Pass NE + - Lost Woods Pass SW + - Lost Woods Pass SE + - Skull Woods Pass NW + - Skull Woods Pass NE + - Skull Woods Pass SW + - Skull Woods Pass SE + - Kakariko Fortune NE + - Kakariko Fortune EN + - Kakariko Fortune ES + - Kakariko Fortune SC + - Dark Fortune NE + - Dark Fortune EN + - Dark Fortune ES + - Dark Fortune SC + - Kakariko Pond NE + - Kakariko Pond WN + - Kakariko Pond WS + - Kakariko Pond EN + - Kakariko Pond ES + - Kakariko Pond SW + - Kakariko Pond SE + - Outcast Pond NE + - Outcast Pond WN + - Outcast Pond WS + - Outcast Pond EN + - Outcast Pond ES + - Outcast Pond SW + - Outcast Pond SE + - Sanctuary WN + - Sanctuary WS + - Kakariko NW + - Kakariko NC + - Kakariko NE + - Dark Chapel WN + - Dark Chapel WS + - Village of Outcasts NW + - Village of Outcasts NC + - Village of Outcasts NE + - Forgotten Forest NW + - Forgotten Forest NE + - Forgotten Forest ES + - Shield Shop NW + - Shield Shop NE + - Hyrule Castle WN + - Master Sword Meadow SC + northeast: + - West Death Mountain EN + - West Death Mountain ES + - West Dark Death Mountain EN + - West Dark Death Mountain ES + - East Death Mountain WN + - East Death Mountain WS + - East Death Mountain EN + - East Dark Death Mountain WN + - East Dark Death Mountain WS + - East Dark Death Mountain EN + - Death Mountain TR Pegs WN + - Turtle Rock WN + - Zora Waterfall NE + - Zora Waterfall SE + - Catfish SE + - Graveyard EC + - Dark Graveyard EC + - River Bend WC + - River Bend EN + - River Bend EC + - River Bend ES + - River Bend SW + - River Bend SC + - River Bend SE + - Qirn Jump WC + - Qirn Jump EN + - Qirn Jump EC + - Qirn Jump ES + - Qirn Jump SW + - Qirn Jump SC + - Qirn Jump SE + - Potion Shop WN + - Potion Shop WC + - Potion Shop WS + - Potion Shop EN + - Potion Shop EC + - Dark Witch WN + - Dark Witch WC + - Dark Witch WS + - Dark Witch EN + - Dark Witch EC + - Zora Approach NE + - Zora Approach WN + - Zora Approach WC + - Catfish Approach NE + - Catfish Approach WN + - Catfish Approach WC + - Wooden Bridge NW + - Wooden Bridge NC + - Wooden Bridge NE + - Broken Bridge NW + - Broken Bridge NC + - Broken Bridge NE + - Zoras Domain SW + southwest: + - Kakariko ES + - Kakariko SE + - Village of Outcasts ES + - Village of Outcasts SE + - Hyrule Castle SW + - Pyramid SW + - Blacksmith WS + - Hammer Pegs WS + - Maze Race ES + - Dig Game EC + - Dig Game ES + - Kakariko Suburb NE + - Kakariko Suburb WS + - Kakariko Suburb ES + - Frog NE + - Frog WC + - Frog WS + - Frog ES + - Flute Boy WS + - Flute Boy SW + - Flute Boy SC + - Stumpy WS + - Stumpy SW + - Stumpy SC + - Central Bonk Rocks NW + - Central Bonk Rocks SW + - Dark Bonk Rocks NW + - Dark Bonk Rocks SW + - Desert EC + - Desert ES + - Flute Boy Approach NW + - Flute Boy Approach NC + - Flute Boy Approach EC + - Stumpy Approach NW + - Stumpy Approach NC + - Stumpy Approach EC + - C Whirlpool NW + - C Whirlpool WC + - C Whirlpool SC + - Dark C Whirlpool NW + - Dark C Whirlpool WC + - Dark C Whirlpool SC + - Desert Pass WC + - Desert Pass WS + - Desert Pass EC + - Desert Pass ES + - Swamp Nook EC + - Swamp Nook ES + - Dam NC + - Dam WC + - Dam WS + - Swamp NC + - Swamp WC + - Swamp WS + southeast: + - Hyrule Castle ES + - Hyrule Castle SE + - Pyramid ES + - Pyramid SE + - Eastern Palace SW + - Eastern Palace SE + - Palace of Darkness SW + - Palace of Darkness SE + - Sand Dunes WN + - Sand Dunes SC + - Dark Dunes WN + - Dark Dunes SC + - Links House NE + - Links House SC + - Links House ES + - Big Bomb Shop NE + - Big Bomb Shop SC + - Big Bomb Shop ES + - Stone Bridge NC + - Stone Bridge WC + - Stone Bridge WS + - Stone Bridge EN + - Stone Bridge EC + - Stone Bridge SC + - Hammer Bridge NC + - Hammer Bridge WS + - Hammer Bridge EN + - Hammer Bridge EC + - Hammer Bridge SC + - Tree Line NW + - Tree Line WN + - Tree Line WC + - Tree Line SC + - Tree Line SE + - Dark Tree Line NW + - Dark Tree Line WN + - Dark Tree Line WC + - Dark Tree Line SC + - Dark Tree Line SE + - Eastern Nook NE + - Palace of Darkness Nook NE + - Statues NC + - Statues SC + - Hype Cave NC + - Hype Cave SC + - Lake Hylia NW + - Lake Hylia NC + - Lake Hylia NE + - Lake Hylia WS + - Lake Hylia EC + - Lake Hylia ES + - Ice Lake NW + - Ice Lake NC + - Ice Lake NE + - Ice Lake WS + - Ice Lake EC + - Ice Lake ES + - Ice Cave SW + - Ice Cave SE + - Shopping Mall SW + - Shopping Mall SE + - South Pass NC + - South Pass ES + - Dark South Pass NC + - Dark South Pass ES + - Octoballoon NW + - Octoballoon NE + - Octoballoon WC + - Octoballoon WS + - Bomber Corner NW + - Bomber Corner NE + - Bomber Corner WC + - Bomber Corner WS + - Hobo EC + borders: + - Zora Whirlpool + - Kakariko Pond Whirlpool + - Sanctuary EC + - Dark Chapel EC + - Graveyard WC + - Dark Graveyard WC + - River Bend Whirlpool + - Qirn Jump Whirlpool + - Wooden Bridge SW + - Broken Bridge SW + - Sand Dunes NW + - Dark Dunes NW + - Central Bonk Rocks EN + - Central Bonk Rocks EC + - Central Bonk Rocks ES + - Dark Bonk Rocks EN + - Dark Bonk Rocks EC + - Dark Bonk Rocks ES + - Links House WN + - Links House WC + - Links House WS + - Big Bomb Shop WN + - Big Bomb Shop WC + - Big Bomb Shop WS + - C Whirlpool EN + - C Whirlpool EC + - C Whirlpool ES + - C Whirlpool + - Dark C Whirlpool EN + - Dark C Whirlpool EC + - Dark C Whirlpool ES + - Statues WN + - Statues WC + - Statues WS + - Hype Cave WN + - Hype Cave WC + - Hype Cave WS + - Lake Hylia Whirlpool + - Dam EC + - Swamp EC + - South Pass WC + - Dark South Pass WC + - Octoballoon Whirlpool + - Bomber Corner Whirlpool diff --git a/presets/world/owr_quadrantshuffle-vanillaborders.yaml b/presets/world/owr_quadrantshuffle-vanillaborders.yaml new file mode 100644 index 00000000..f446011c --- /dev/null +++ b/presets/world/owr_quadrantshuffle-vanillaborders.yaml @@ -0,0 +1,275 @@ +settings: + 1: + ow_whirlpool: false +ow-edges: + 1: + two-way: + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Dam EC*: South Pass WC* + Swamp EC*: Dark South Pass WC* + groups: + northwest: + - Lost Woods NW + - Lost Woods EN + - Lost Woods SW + - Lost Woods SC + - Lost Woods SE + - Skull Woods EN + - Skull Woods SW + - Skull Woods SC + - Skull Woods SE + - Lumberjack WN + - Lumberjack SW + - Dark Lumberjack WN + - Dark Lumberjack SW + - Mountain Pass NW + - Mountain Pass SE + - Bumper Cave NW + - Bumper Cave SE + - Lost Woods Pass NW + - Lost Woods Pass NE + - Lost Woods Pass SW + - Lost Woods Pass SE + - Skull Woods Pass NW + - Skull Woods Pass NE + - Skull Woods Pass SW + - Skull Woods Pass SE + - Kakariko Fortune NE + - Kakariko Fortune EN + - Kakariko Fortune ES + - Kakariko Fortune SC + - Dark Fortune NE + - Dark Fortune EN + - Dark Fortune ES + - Dark Fortune SC + - Kakariko Pond NE + - Kakariko Pond WN + - Kakariko Pond WS + - Kakariko Pond EN + - Kakariko Pond ES + - Kakariko Pond SW + - Kakariko Pond SE + - Outcast Pond NE + - Outcast Pond WN + - Outcast Pond WS + - Outcast Pond EN + - Outcast Pond ES + - Outcast Pond SW + - Outcast Pond SE + - Sanctuary WN + - Sanctuary WS + - Kakariko NW + - Kakariko NC + - Kakariko NE + - Dark Chapel WN + - Dark Chapel WS + - Village of Outcasts NW + - Village of Outcasts NC + - Village of Outcasts NE + - Forgotten Forest NW + - Forgotten Forest NE + - Forgotten Forest ES + - Shield Shop NW + - Shield Shop NE + - Hyrule Castle WN + - Master Sword Meadow SC + northeast: + - West Death Mountain EN + - West Death Mountain ES + - West Dark Death Mountain EN + - West Dark Death Mountain ES + - East Death Mountain WN + - East Death Mountain WS + - East Death Mountain EN + - East Dark Death Mountain WN + - East Dark Death Mountain WS + - East Dark Death Mountain EN + - Death Mountain TR Pegs WN + - Turtle Rock WN + - Zora Waterfall NE + - Zora Waterfall SE + - Catfish SE + - Graveyard EC + - Dark Graveyard EC + - River Bend WC + - River Bend EN + - River Bend EC + - River Bend ES + - River Bend SW + - River Bend SC + - River Bend SE + - Qirn Jump WC + - Qirn Jump EN + - Qirn Jump EC + - Qirn Jump ES + - Qirn Jump SW + - Qirn Jump SC + - Qirn Jump SE + - Potion Shop WN + - Potion Shop WC + - Potion Shop WS + - Potion Shop EN + - Potion Shop EC + - Dark Witch WN + - Dark Witch WC + - Dark Witch WS + - Dark Witch EN + - Dark Witch EC + - Zora Approach NE + - Zora Approach WN + - Zora Approach WC + - Catfish Approach NE + - Catfish Approach WN + - Catfish Approach WC + - Wooden Bridge NW + - Wooden Bridge NC + - Wooden Bridge NE + - Broken Bridge NW + - Broken Bridge NC + - Broken Bridge NE + - Zoras Domain SW + southwest: + - Kakariko ES + - Kakariko SE + - Village of Outcasts ES + - Village of Outcasts SE + - Hyrule Castle SW + - Pyramid SW + - Blacksmith WS + - Hammer Pegs WS + - Maze Race ES + - Dig Game EC + - Dig Game ES + - Kakariko Suburb NE + - Kakariko Suburb WS + - Kakariko Suburb ES + - Frog NE + - Frog WC + - Frog WS + - Frog ES + - Flute Boy WS + - Flute Boy SW + - Flute Boy SC + - Stumpy WS + - Stumpy SW + - Stumpy SC + - Central Bonk Rocks NW + - Central Bonk Rocks SW + - Dark Bonk Rocks NW + - Dark Bonk Rocks SW + - Desert EC + - Desert ES + - Flute Boy Approach NW + - Flute Boy Approach NC + - Flute Boy Approach EC + - Stumpy Approach NW + - Stumpy Approach NC + - Stumpy Approach EC + - C Whirlpool NW + - C Whirlpool WC + - C Whirlpool SC + - Dark C Whirlpool NW + - Dark C Whirlpool WC + - Dark C Whirlpool SC + - Desert Pass WC + - Desert Pass WS + - Desert Pass EC + - Desert Pass ES + - Swamp Nook EC + - Swamp Nook ES + - Dam NC + - Dam WC + - Dam WS + - Swamp NC + - Swamp WC + - Swamp WS + southeast: + - Hyrule Castle ES + - Hyrule Castle SE + - Pyramid ES + - Pyramid SE + - Eastern Palace SW + - Eastern Palace SE + - Palace of Darkness SW + - Palace of Darkness SE + - Sand Dunes WN + - Sand Dunes SC + - Dark Dunes WN + - Dark Dunes SC + - Links House NE + - Links House SC + - Links House ES + - Big Bomb Shop NE + - Big Bomb Shop SC + - Big Bomb Shop ES + - Stone Bridge NC + - Stone Bridge WC + - Stone Bridge WS + - Stone Bridge EN + - Stone Bridge EC + - Stone Bridge SC + - Hammer Bridge NC + - Hammer Bridge WS + - Hammer Bridge EN + - Hammer Bridge EC + - Hammer Bridge SC + - Tree Line NW + - Tree Line WN + - Tree Line WC + - Tree Line SC + - Tree Line SE + - Dark Tree Line NW + - Dark Tree Line WN + - Dark Tree Line WC + - Dark Tree Line SC + - Dark Tree Line SE + - Eastern Nook NE + - Palace of Darkness Nook NE + - Statues NC + - Statues SC + - Hype Cave NC + - Hype Cave SC + - Lake Hylia NW + - Lake Hylia NC + - Lake Hylia NE + - Lake Hylia WS + - Lake Hylia EC + - Lake Hylia ES + - Ice Lake NW + - Ice Lake NC + - Ice Lake NE + - Ice Lake WS + - Ice Lake EC + - Ice Lake ES + - Ice Cave SW + - Ice Cave SE + - Shopping Mall SW + - Shopping Mall SE + - South Pass NC + - South Pass ES + - Dark South Pass NC + - Dark South Pass ES + - Octoballoon NW + - Octoballoon NE + - Octoballoon WC + - Octoballoon WS + - Bomber Corner NW + - Bomber Corner NE + - Bomber Corner WC + - Bomber Corner WS + - Hobo EC \ No newline at end of file diff --git a/presets/world/owr_shuffle-dark.yaml b/presets/world/owr_shuffle-dark.yaml new file mode 100644 index 00000000..3b27e6d2 --- /dev/null +++ b/presets/world/owr_shuffle-dark.yaml @@ -0,0 +1,94 @@ +settings: + 1: + ow_whirlpool: false +ow-edges: + 1: + two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods EN*: Lumberjack WN* + Lost Woods SW*: Lost Woods Pass NW* + Lost Woods SC*: Lost Woods Pass NE* + Lost Woods SE*: Kakariko Fortune NE* + Lumberjack SW*: Mountain Pass NW* + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + Mountain Pass SE*: Kakariko Pond NE* + Zora Waterfall NE*: Zoras Domain SW* + Zora Waterfall SE*: Zora Approach NE* + Lost Woods Pass SW*: Kakariko NW* + Lost Woods Pass SE*: Kakariko NC* + Kakariko Fortune EN*: Kakariko Pond WN* + Kakariko Fortune ES*: Kakariko Pond WS* + Kakariko Fortune SC*: Kakariko NE* + Kakariko Pond EN*: Sanctuary WN* + Kakariko Pond ES*: Sanctuary WS* + Kakariko Pond SW*: Forgotten Forest NW* + Kakariko Pond SE*: Forgotten Forest NE* + Sanctuary EC*: Graveyard WC* + Graveyard EC*: River Bend WC* + River Bend EN*: Potion Shop WN* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WS* + River Bend SW*: Wooden Bridge NW* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NE* + Potion Shop EN*: Zora Approach WN* + Potion Shop EC*: Zora Approach WC* + Kakariko ES*: Blacksmith WS* + Kakariko SE*: Kakariko Suburb NE* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle ES*: Sand Dunes WN* + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Wooden Bridge SW*: Sand Dunes NW* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Sand Dunes SC*: Stone Bridge NC* + Maze Race ES*: Kakariko Suburb WS* + Kakariko Suburb ES*: Flute Boy WS* + Flute Boy SW*: Flute Boy Approach NW* + Flute Boy SC*: Flute Boy Approach NC* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Central Bonk Rocks SW*: C Whirlpool NW* + Links House SC*: Statues NC* + Links House ES*: Stone Bridge WS* + Stone Bridge WC: Hobo EC + Stone Bridge EN*: Tree Line WN* + Stone Bridge EC*: Tree Line WC* + Stone Bridge SC*: Lake Hylia NW* + Tree Line SC*: Lake Hylia NC* + Tree Line SE*: Lake Hylia NE* + Desert EC: Desert Pass WC + Desert ES: Desert Pass WS + Flute Boy Approach EC*: C Whirlpool WC* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + C Whirlpool SC*: Dam NC* + Statues SC*: South Pass NC* + Lake Hylia WS*: South Pass ES* + Lake Hylia EC*: Octoballoon WC* + Lake Hylia ES*: Octoballoon WS* + Ice Cave SW*: Octoballoon NW* + Ice Cave SE*: Octoballoon NE* + Desert Pass EC*: Dam WC* + Desert Pass ES*: Dam WS* + Dam EC*: South Pass WC* +ow-whirlpools: + 1: + two-way: + Zora Whirlpool: Lake Hylia Whirlpool + Kakariko Pond Whirlpool: Octoballoon Whirlpool + River Bend Whirlpool: C Whirlpool +ow-tileflips: + 1: + force_no_flip: + - 0x0f + - 0x12 + - 0x15 + - 0x33 + - 0x35 + - 0x3f \ No newline at end of file diff --git a/presets/world/owr_shuffle-horizontal.yaml b/presets/world/owr_shuffle-horizontal.yaml new file mode 100644 index 00000000..9eba3118 --- /dev/null +++ b/presets/world/owr_shuffle-horizontal.yaml @@ -0,0 +1,76 @@ +ow-edges: + 1: + two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods SW*: Lost Woods Pass NW* + Lost Woods SC*: Lost Woods Pass NE* + Lost Woods SE*: Kakariko Fortune NE* + Skull Woods SW*: Skull Woods Pass NW* + Skull Woods SC*: Skull Woods Pass NE* + Skull Woods SE*: Dark Fortune NE* + Lumberjack SW*: Mountain Pass NW* + Dark Lumberjack SW*: Bumper Cave NW* + Mountain Pass SE*: Kakariko Pond NE* + Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall NE: Zoras Domain SW + Zora Waterfall SE*: Zora Approach NE* + Catfish SE*: Catfish Approach NE* + Lost Woods Pass SW*: Kakariko NW* + Lost Woods Pass SE*: Kakariko NC* + Skull Woods Pass SW*: Village of Outcasts NW* + Skull Woods Pass SE*: Village of Outcasts NC* + Kakariko Fortune SC*: Kakariko NE* + Dark Fortune SC*: Village of Outcasts NE* + Kakariko Pond SW*: Forgotten Forest NW* + Kakariko Pond SE*: Forgotten Forest NE* + Outcast Pond SW*: Shield Shop NW* + Outcast Pond SE*: Shield Shop NE* + River Bend SW*: Wooden Bridge NW* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NE* + Qirn Jump SW*: Broken Bridge NW* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NE* + Kakariko SE*: Kakariko Suburb NE* + Village of Outcasts SE*: Frog NE* + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* + Sand Dunes SC*: Stone Bridge NC* + Dark Dunes SC*: Hammer Bridge NC* + Flute Boy SW*: Flute Boy Approach NW* + Flute Boy SC*: Flute Boy Approach NC* + Stumpy SW*: Stumpy Approach NW* + Stumpy SC*: Stumpy Approach NC* + Central Bonk Rocks SW*: C Whirlpool NW* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Links House SC*: Statues NC* + Big Bomb Shop SC*: Hype Cave NC* + Stone Bridge SC*: Lake Hylia NW* + Hammer Bridge SC*: Ice Lake NW* + Tree Line SC*: Lake Hylia NC* + Tree Line SE*: Lake Hylia NE* + Dark Tree Line SC*: Ice Lake NC* + Dark Tree Line SE*: Ice Lake NE* + C Whirlpool SC*: Dam NC* + Dark C Whirlpool SC*: Swamp NC* + Statues SC*: South Pass NC* + Hype Cave SC*: Dark South Pass NC* + Ice Cave SW*: Octoballoon NW* + Ice Cave SE*: Octoballoon NE* + Shopping Mall SW*: Bomber Corner NW* + Shopping Mall SE*: Bomber Corner NE* + +ow-tileflips: + 1: + force_together: + Hobo: + - 0x2d + - 0x80 \ No newline at end of file diff --git a/presets/world/owr_shuffle-horizontalbycolumns.yaml b/presets/world/owr_shuffle-horizontalbycolumns.yaml new file mode 100644 index 00000000..117b81d5 --- /dev/null +++ b/presets/world/owr_shuffle-horizontalbycolumns.yaml @@ -0,0 +1,233 @@ +ow-edges: + 1: + two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods SW*: Lost Woods Pass NW* + Lost Woods SC*: Lost Woods Pass NE* + Lost Woods SE*: Kakariko Fortune NE* + Skull Woods SW*: Skull Woods Pass NW* + Skull Woods SC*: Skull Woods Pass NE* + Skull Woods SE*: Dark Fortune NE* + Lumberjack SW*: Mountain Pass NW* + Dark Lumberjack SW*: Bumper Cave NW* + Mountain Pass SE*: Kakariko Pond NE* + Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall NE: Zoras Domain SW + Zora Waterfall SE*: Zora Approach NE* + Catfish SE*: Catfish Approach NE* + Lost Woods Pass SW*: Kakariko NW* + Lost Woods Pass SE*: Kakariko NC* + Skull Woods Pass SW*: Village of Outcasts NW* + Skull Woods Pass SE*: Village of Outcasts NC* + Kakariko Fortune SC*: Kakariko NE* + Dark Fortune SC*: Village of Outcasts NE* + Kakariko Pond SW*: Forgotten Forest NW* + Kakariko Pond SE*: Forgotten Forest NE* + Outcast Pond SW*: Shield Shop NW* + Outcast Pond SE*: Shield Shop NE* + River Bend SW*: Wooden Bridge NW* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NE* + Qirn Jump SW*: Broken Bridge NW* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NE* + Kakariko SE*: Kakariko Suburb NE* + Village of Outcasts SE*: Frog NE* + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* + Sand Dunes SC*: Stone Bridge NC* + Dark Dunes SC*: Hammer Bridge NC* + Flute Boy SW*: Flute Boy Approach NW* + Flute Boy SC*: Flute Boy Approach NC* + Stumpy SW*: Stumpy Approach NW* + Stumpy SC*: Stumpy Approach NC* + Central Bonk Rocks SW*: C Whirlpool NW* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Links House SC*: Statues NC* + Big Bomb Shop SC*: Hype Cave NC* + Stone Bridge SC*: Lake Hylia NW* + Hammer Bridge SC*: Ice Lake NW* + Tree Line SC*: Lake Hylia NC* + Tree Line SE*: Lake Hylia NE* + Dark Tree Line SC*: Ice Lake NC* + Dark Tree Line SE*: Ice Lake NE* + C Whirlpool SC*: Dam NC* + Dark C Whirlpool SC*: Swamp NC* + Statues SC*: South Pass NC* + Hype Cave SC*: Dark South Pass NC* + Ice Cave SW*: Octoballoon NW* + Ice Cave SE*: Octoballoon NE* + Shopping Mall SW*: Bomber Corner NW* + Shopping Mall SE*: Bomber Corner NE* + groups: + Column1: + - Maze Race ES + - Kakariko Suburb WS + - Dig Game EC + - Frog WC + - Dig Game ES + - Frog WS + Column2: + - Lost Woods EN + - Lumberjack WN + - Skull Woods EN + - Dark Lumberjack WN + - Kakariko Fortune EN + - Kakariko Pond WN + - Kakariko Fortune ES + - Kakariko Pond WS + - Dark Fortune EN + - Outcast Pond WN + - Dark Fortune ES + - Outcast Pond WS + - Kakariko ES + - Blacksmith WS + - Village of Outcasts ES + - Hammer Pegs WS + - Kakariko Suburb ES + - Flute Boy WS + - Frog ES + - Stumpy WS + - Desert EC + - Desert Pass WC + - Desert ES + - Desert Pass WS + Column3: + - Kakariko Pond EN + - Sanctuary WN + - Kakariko Pond ES + - Sanctuary WS + - Outcast Pond EN + - Dark Chapel WN + - Outcast Pond ES + - Dark Chapel WS + - Forgotten Forest ES + - Hyrule Castle WN + - Flute Boy Approach EC + - C Whirlpool WC + - Stumpy Approach EC + - Dark C Whirlpool WC + - Desert Pass EC + - Dam WC + - Desert Pass ES + - Dam WS + - Swamp Nook EC + - Swamp WC + - Swamp Nook ES + - Swamp WS + Column4: + - Sanctuary EC + - Graveyard WC + - Dark Chapel EC + - Dark Graveyard WC + - Central Bonk Rocks EN + - Links House WN + - Central Bonk Rocks EC + - Links House WC + - Central Bonk Rocks ES + - Links House WS + - Dark Bonk Rocks EN + - Big Bomb Shop WN + - Dark Bonk Rocks EC + - Big Bomb Shop WC + - Dark Bonk Rocks ES + - Big Bomb Shop WS + - C Whirlpool EN + - Statues WN + - C Whirlpool EC + - Statues WC + - C Whirlpool ES + - Statues WS + - Dark C Whirlpool EN + - Hype Cave WN + - Dark C Whirlpool EC + - Hype Cave WC + - Dark C Whirlpool ES + - Hype Cave WS + - Dam EC + - South Pass WC + - Swamp EC + - Dark South Pass WC + Column5: + - West Death Mountain EN + - East Death Mountain WN + - West Death Mountain ES + - East Death Mountain WS + - West Dark Death Mountain EN + - East Dark Death Mountain WN + - West Dark Death Mountain ES + - East Dark Death Mountain WS + - Graveyard EC + - River Bend WC + - Dark Graveyard EC + - Qirn Jump WC + - Hyrule Castle ES + - Sand Dunes WN + - Pyramid ES + - Dark Dunes WN + - Links House ES + - Stone Bridge WS + - Big Bomb Shop ES + - Hammer Bridge WS + - Lake Hylia WS + - South Pass ES + - Ice Lake WS + - Dark South Pass ES + Column6: + - River Bend EN + - Potion Shop WN + - River Bend EC + - Potion Shop WC + - River Bend ES + - Potion Shop WS + - Qirn Jump EN + - Dark Witch WN + - Qirn Jump EC + - Dark Witch WC + - Qirn Jump ES + - Dark Witch WS + - Stone Bridge EN + - Tree Line WN + - Stone Bridge EC + - Tree Line WC + - Hammer Bridge EN + - Dark Tree Line WN + - Hammer Bridge EC + - Dark Tree Line WC + - Stone Bridge WC + - Hobo EC + Column7: + - East Death Mountain EN + - Death Mountain TR Pegs WN + - East Dark Death Mountain EN + - Turtle Rock WN + - Potion Shop EN + - Zora Approach WN + - Potion Shop EC + - Zora Approach WC + - Dark Witch EN + - Catfish Approach WN + - Dark Witch EC + - Catfish Approach WC + - Lake Hylia EC + - Octoballoon WC + - Lake Hylia ES + - Octoballoon WS + - Ice Lake EC + - Bomber Corner WC + - Ice Lake ES + - Bomber Corner WS +ow-tileflips: + 1: + force_together: + Hobo: + - 0x2d + - 0x80 \ No newline at end of file diff --git a/presets/world/owr_shuffle-largescreens.yaml b/presets/world/owr_shuffle-largescreens.yaml new file mode 100644 index 00000000..6c54658c --- /dev/null +++ b/presets/world/owr_shuffle-largescreens.yaml @@ -0,0 +1,210 @@ +settings: + 1: + ow_whirlpool: false +ow-edges: + 1: + two-way: + Lumberjack SW*: Mountain Pass NW* + Dark Lumberjack SW*: Bumper Cave NW* + Mountain Pass SE*: Kakariko Pond NE* + Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall SE*: Zora Approach NE* + Catfish SE*: Catfish Approach NE* + Kakariko Fortune EN*: Kakariko Pond WN* + Kakariko Fortune ES*: Kakariko Pond WS* + Dark Fortune EN*: Outcast Pond WN* + Dark Fortune ES*: Outcast Pond WS* + Kakariko Pond EN*: Sanctuary WN* + Kakariko Pond ES*: Sanctuary WS* + Kakariko Pond SW*: Forgotten Forest NW* + Kakariko Pond SE*: Forgotten Forest NE* + Outcast Pond EN*: Dark Chapel WN* + Outcast Pond ES*: Dark Chapel WS* + Outcast Pond SW*: Shield Shop NW* + Outcast Pond SE*: Shield Shop NE* + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Graveyard EC*: River Bend WC* + Dark Graveyard EC*: Qirn Jump WC* + River Bend EN*: Potion Shop WN* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WS* + River Bend SW*: Wooden Bridge NW* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NE* + Qirn Jump EN*: Dark Witch WN* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WS* + Qirn Jump SW*: Broken Bridge NW* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NE* + Potion Shop EN*: Zora Approach WN* + Potion Shop EC*: Zora Approach WC* + Dark Witch EN*: Catfish Approach WN* + Dark Witch EC*: Catfish Approach WC* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Sand Dunes SC*: Stone Bridge NC* + Dark Dunes SC*: Hammer Bridge NC* + Maze Race ES*: Kakariko Suburb WS* + Dig Game EC: Frog WC + Dig Game ES*: Frog WS* + Kakariko Suburb ES*: Flute Boy WS* + Frog ES*: Stumpy WS* + Flute Boy SW*: Flute Boy Approach NW* + Flute Boy SC*: Flute Boy Approach NC* + Stumpy SW*: Stumpy Approach NW* + Stumpy SC*: Stumpy Approach NC* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Central Bonk Rocks SW*: C Whirlpool NW* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Links House SC*: Statues NC* + Links House ES*: Stone Bridge WS* + Big Bomb Shop SC*: Hype Cave NC* + Big Bomb Shop ES*: Hammer Bridge WS* + Stone Bridge WC: Hobo EC + Stone Bridge EN*: Tree Line WN* + Stone Bridge EC*: Tree Line WC* + Hammer Bridge EN*: Dark Tree Line WN* + Hammer Bridge EC*: Dark Tree Line WC* + Flute Boy Approach EC*: C Whirlpool WC* + Stumpy Approach EC*: Dark C Whirlpool WC* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + C Whirlpool SC*: Dam NC* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Dark C Whirlpool SC*: Swamp NC* + Statues SC*: South Pass NC* + Hype Cave SC*: Dark South Pass NC* + Ice Cave SW*: Octoballoon NW* + Ice Cave SE*: Octoballoon NE* + Shopping Mall SW*: Bomber Corner NW* + Shopping Mall SE*: Bomber Corner NE* + Desert Pass EC*: Dam WC* + Desert Pass ES*: Dam WS* + Swamp Nook EC*: Swamp WC* + Swamp Nook ES*: Swamp WS* + Dam EC*: South Pass WC* + Swamp EC*: Dark South Pass WC* + groups: + 1: + - Lost Woods NW + - Master Sword Meadow SC + - Lost Woods EN + - Lumberjack WN + - Skull Woods EN + - Dark Lumberjack WN + - East Death Mountain EN + - Death Mountain TR Pegs WN + - East Dark Death Mountain EN + - Turtle Rock WN + - Lost Woods Pass SW + - Kakariko NW + - Lost Woods Pass SE + - Kakariko NC + - Skull Woods Pass SW + - Village of Outcasts NW + - Skull Woods Pass SE + - Village of Outcasts NC + - Kakariko Fortune SC + - Kakariko NE + - Dark Fortune SC + - Village of Outcasts NE + - Kakariko ES + - Blacksmith WS + - Village of Outcasts ES + - Hammer Pegs WS + - Hyrule Castle ES + - Sand Dunes WN + - Pyramid ES + - Dark Dunes WN + - Stone Bridge SC + - Lake Hylia NW + - Hammer Bridge SC + - Ice Lake NW + - Tree Line SC + - Lake Hylia NC + - Tree Line SE + - Lake Hylia NE + - Dark Tree Line SC + - Ice Lake NC + - Dark Tree Line SE + - Ice Lake NE + - Desert EC + - Desert Pass WC + - Desert ES + - Desert Pass WS + - Lake Hylia EC + - Octoballoon WC + - Lake Hylia ES + - Octoballoon WS + - Ice Lake EC + - Bomber Corner WC + - Ice Lake ES + - Bomber Corner WS + 2: + - Lost Woods SW + - Lost Woods Pass NW + - Lost Woods SC + - Lost Woods Pass NE + - Lost Woods SE + - Kakariko Fortune NE + - Skull Woods SW + - Skull Woods Pass NW + - Skull Woods SC + - Skull Woods Pass NE + - Skull Woods SE + - Dark Fortune NE + - Zora Waterfall NE + - Zoras Domain SW + - Kakariko SE + - Kakariko Suburb NE + - Village of Outcasts SE + - Frog NE + - Forgotten Forest ES + - Hyrule Castle WN + - Hyrule Castle SW + - Central Bonk Rocks NW + - Hyrule Castle SE + - Links House NE + - Pyramid SW + - Dark Bonk Rocks NW + - Pyramid SE + - Big Bomb Shop NE + - Eastern Palace SW + - Tree Line NW + - Eastern Palace SE + - Eastern Nook NE + - Palace of Darkness SW + - Dark Tree Line NW + - Palace of Darkness SE + - Palace of Darkness Nook NE + - Lake Hylia WS + - South Pass ES + - Ice Lake WS + - Dark South Pass ES + - West Death Mountain EN + - East Death Mountain WN + - West Death Mountain ES + - East Death Mountain WS + - West Dark Death Mountain EN + - East Dark Death Mountain WN + - West Dark Death Mountain ES + - East Dark Death Mountain WS +ow-tileflips: + 1: + force_together: + 1: + - 0x00 + - 0x80 + 2: + - 0x0f + - 0x81 \ No newline at end of file diff --git a/presets/world/owr_shuffle-light.yaml b/presets/world/owr_shuffle-light.yaml new file mode 100644 index 00000000..4feaa75e --- /dev/null +++ b/presets/world/owr_shuffle-light.yaml @@ -0,0 +1,84 @@ +ow-edges: + 1: + two-way: + Skull Woods EN*: Dark Lumberjack WN* + Skull Woods SW*: Skull Woods Pass NW* + Skull Woods SC*: Skull Woods Pass NE* + Skull Woods SE*: Dark Fortune NE* + Dark Lumberjack SW*: Bumper Cave NW* + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Dark Death Mountain EN*: Turtle Rock WN* + Bumper Cave SE*: Outcast Pond NE* + Catfish SE*: Catfish Approach NE* + Skull Woods Pass SW*: Village of Outcasts NW* + Skull Woods Pass SE*: Village of Outcasts NC* + Dark Fortune EN*: Outcast Pond WN* + Dark Fortune ES*: Outcast Pond WS* + Dark Fortune SC*: Village of Outcasts NE* + Outcast Pond EN*: Dark Chapel WN* + Outcast Pond ES*: Dark Chapel WS* + Outcast Pond SW*: Shield Shop NW* + Outcast Pond SE*: Shield Shop NE* + Dark Chapel EC*: Dark Graveyard WC* + Dark Graveyard EC*: Qirn Jump WC* + Qirn Jump EN*: Dark Witch WN* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WS* + Qirn Jump SW*: Broken Bridge NW* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NE* + Dark Witch EN*: Catfish Approach WN* + Dark Witch EC*: Catfish Approach WC* + Village of Outcasts ES*: Hammer Pegs WS* + Village of Outcasts SE*: Frog NE* + Pyramid ES*: Dark Dunes WN* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Broken Bridge SW*: Dark Dunes NW* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* + Dark Dunes SC*: Hammer Bridge NC* + Dig Game EC: Frog WC + Dig Game ES*: Frog WS* + Frog ES*: Stumpy WS* + Stumpy SW*: Stumpy Approach NW* + Stumpy SC*: Stumpy Approach NC* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Big Bomb Shop SC*: Hype Cave NC* + Big Bomb Shop ES*: Hammer Bridge WS* + Hammer Bridge EN*: Dark Tree Line WN* + Hammer Bridge EC*: Dark Tree Line WC* + Hammer Bridge SC*: Ice Lake NW* + Dark Tree Line SC*: Ice Lake NC* + Dark Tree Line SE*: Ice Lake NE* + Stumpy Approach EC*: Dark C Whirlpool WC* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Dark C Whirlpool SC*: Swamp NC* + Hype Cave SC*: Dark South Pass NC* + Ice Lake WS*: Dark South Pass ES* + Ice Lake EC*: Bomber Corner WC* + Ice Lake ES*: Bomber Corner WS* + Shopping Mall SW*: Bomber Corner NW* + Shopping Mall SE*: Bomber Corner NE* + Swamp Nook EC*: Swamp WC* + Swamp Nook ES*: Swamp WS* + Swamp EC*: Dark South Pass WC* +ow-whirlpools: + 1: + two-way: + Qirn Jump Whirlpool: Bomber Corner Whirlpool +ow-tileflips: + 1: + force_no_flip: + - 0x0f + - 0x12 + - 0x15 + - 0x33 + - 0x35 + - 0x3f \ No newline at end of file diff --git a/presets/world/owr_shuffle-separatemountain.yaml b/presets/world/owr_shuffle-separatemountain.yaml new file mode 100644 index 00000000..b1078849 --- /dev/null +++ b/presets/world/owr_shuffle-separatemountain.yaml @@ -0,0 +1,16 @@ +ow-edges: + 1: + groups: + mountain: + - West Death Mountain EN + - West Death Mountain ES + - West Dark Death Mountain EN + - West Dark Death Mountain ES + - East Death Mountain WN + - East Death Mountain WS + - East Death Mountain EN + - East Dark Death Mountain WN + - East Dark Death Mountain WS + - East Dark Death Mountain EN + - Death Mountain TR Pegs WN + - Turtle Rock WN diff --git a/presets/world/owr_shuffle-smallscreens.yaml b/presets/world/owr_shuffle-smallscreens.yaml new file mode 100644 index 00000000..a12ad95d --- /dev/null +++ b/presets/world/owr_shuffle-smallscreens.yaml @@ -0,0 +1,58 @@ +ow-edges: + 1: + two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods EN*: Lumberjack WN* + Lost Woods SW*: Lost Woods Pass NW* + Lost Woods SC*: Lost Woods Pass NE* + Lost Woods SE*: Kakariko Fortune NE* + Skull Woods EN*: Dark Lumberjack WN* + Skull Woods SW*: Skull Woods Pass NW* + Skull Woods SC*: Skull Woods Pass NE* + Skull Woods SE*: Dark Fortune NE* + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + East Dark Death Mountain EN*: Turtle Rock WN* + Zora Waterfall NE: Zoras Domain SW + Lost Woods Pass SW*: Kakariko NW* + Lost Woods Pass SE*: Kakariko NC* + Skull Woods Pass SW*: Village of Outcasts NW* + Skull Woods Pass SE*: Village of Outcasts NC* + Kakariko Fortune SC*: Kakariko NE* + Dark Fortune SC*: Village of Outcasts NE* + Kakariko ES*: Blacksmith WS* + Kakariko SE*: Kakariko Suburb NE* + Village of Outcasts ES*: Hammer Pegs WS* + Village of Outcasts SE*: Frog NE* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle ES*: Sand Dunes WN* + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Pyramid ES*: Dark Dunes WN* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* + Stone Bridge SC*: Lake Hylia NW* + Hammer Bridge SC*: Ice Lake NW* + Tree Line SC*: Lake Hylia NC* + Tree Line SE*: Lake Hylia NE* + Dark Tree Line SC*: Ice Lake NC* + Dark Tree Line SE*: Ice Lake NE* + Desert EC: Desert Pass WC + Desert ES: Desert Pass WS + Lake Hylia WS*: South Pass ES* + Lake Hylia EC*: Octoballoon WC* + Lake Hylia ES*: Octoballoon WS* + Ice Lake WS*: Dark South Pass ES* + Ice Lake EC*: Bomber Corner WC* + Ice Lake ES*: Bomber Corner WS* +ow-whirlpools: + 1: + two-way: + Zora Whirlpool: Lake Hylia Whirlpool \ No newline at end of file diff --git a/presets/world/owr_shuffle-vanillaloop.yaml b/presets/world/owr_shuffle-vanillaloop.yaml new file mode 100644 index 00000000..bc4223fb --- /dev/null +++ b/presets/world/owr_shuffle-vanillaloop.yaml @@ -0,0 +1,41 @@ +ow-edges: + 1: + two-way: + Lost Woods EN*: Lumberjack WN* + Lost Woods SW*: Lost Woods Pass NW* + Skull Woods EN*: Dark Lumberjack WN* + Skull Woods SW*: Skull Woods Pass NW* + Lumberjack SW*: Mountain Pass NW* + Dark Lumberjack SW*: Bumper Cave NW* + Mountain Pass SE*: Kakariko Pond NE* + Bumper Cave SE*: Outcast Pond NE* + Lost Woods Pass SW*: Kakariko NW* + Skull Woods Pass SW*: Village of Outcasts NW* + Kakariko Pond ES*: Sanctuary WS* + Outcast Pond ES*: Dark Chapel WS* + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Graveyard EC*: River Bend WC* + Dark Graveyard EC*: Qirn Jump WC* + River Bend SW*: Wooden Bridge NW* + Qirn Jump SW*: Broken Bridge NW* + Kakariko SE*: Kakariko Suburb NE* + Village of Outcasts SE*: Frog NE* + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Sand Dunes SC*: Stone Bridge NC* + Dark Dunes SC*: Hammer Bridge NC* + Kakariko Suburb ES*: Flute Boy WS* + Frog ES*: Stumpy WS* + Flute Boy SW*: Flute Boy Approach NW* + Stumpy SW*: Stumpy Approach NW* + Central Bonk Rocks SW*: C Whirlpool NW* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Links House ES*: Stone Bridge WS* + Big Bomb Shop ES*: Hammer Bridge WS* + Flute Boy Approach EC*: C Whirlpool WC* + Stumpy Approach EC*: Dark C Whirlpool WC* diff --git a/presets/world/owr_shuffle-vertical.yaml b/presets/world/owr_shuffle-vertical.yaml new file mode 100644 index 00000000..222834c9 --- /dev/null +++ b/presets/world/owr_shuffle-vertical.yaml @@ -0,0 +1,87 @@ +ow-edges: + 1: + two-way: + Lost Woods EN*: Lumberjack WN* + Skull Woods EN*: Dark Lumberjack WN* + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + East Dark Death Mountain EN*: Turtle Rock WN* + Kakariko Fortune EN*: Kakariko Pond WN* + Kakariko Fortune ES*: Kakariko Pond WS* + Dark Fortune EN*: Outcast Pond WN* + Dark Fortune ES*: Outcast Pond WS* + Kakariko Pond EN*: Sanctuary WN* + Kakariko Pond ES*: Sanctuary WS* + Outcast Pond EN*: Dark Chapel WN* + Outcast Pond ES*: Dark Chapel WS* + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Graveyard EC*: River Bend WC* + Dark Graveyard EC*: Qirn Jump WC* + River Bend EN*: Potion Shop WN* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WS* + Qirn Jump EN*: Dark Witch WN* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WS* + Potion Shop EN*: Zora Approach WN* + Potion Shop EC*: Zora Approach WC* + Dark Witch EN*: Catfish Approach WN* + Dark Witch EC*: Catfish Approach WC* + Kakariko ES*: Blacksmith WS* + Village of Outcasts ES*: Hammer Pegs WS* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle ES*: Sand Dunes WN* + Pyramid ES*: Dark Dunes WN* + Maze Race ES*: Kakariko Suburb WS* + Dig Game EC: Frog WC + Dig Game ES*: Frog WS* + Kakariko Suburb ES*: Flute Boy WS* + Frog ES*: Stumpy WS* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + Links House ES*: Stone Bridge WS* + Big Bomb Shop ES*: Hammer Bridge WS* + Stone Bridge WC: Hobo EC + Stone Bridge EN*: Tree Line WN* + Stone Bridge EC*: Tree Line WC* + Hammer Bridge EN*: Dark Tree Line WN* + Hammer Bridge EC*: Dark Tree Line WC* + Desert EC: Desert Pass WC + Desert ES: Desert Pass WS + Flute Boy Approach EC*: C Whirlpool WC* + Stumpy Approach EC*: Dark C Whirlpool WC* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Lake Hylia WS*: South Pass ES* + Lake Hylia EC*: Octoballoon WC* + Lake Hylia ES*: Octoballoon WS* + Ice Lake WS*: Dark South Pass ES* + Ice Lake EC*: Bomber Corner WC* + Ice Lake ES*: Bomber Corner WS* + Desert Pass EC*: Dam WC* + Desert Pass ES*: Dam WS* + Swamp Nook EC*: Swamp WC* + Swamp Nook ES*: Swamp WS* + Dam EC*: South Pass WC* + Swamp EC*: Dark South Pass WC* +ow-tileflips: + 1: + force_together: + 1: + - 0x00 + - 0x80 + 2: + - 0x0f + - 0x81 \ No newline at end of file diff --git a/presets/world/owr_shuffle-verticalbyrows.yaml b/presets/world/owr_shuffle-verticalbyrows.yaml new file mode 100644 index 00000000..0799a25b --- /dev/null +++ b/presets/world/owr_shuffle-verticalbyrows.yaml @@ -0,0 +1,227 @@ +ow-edges: + 1: + two-way: + Lost Woods EN*: Lumberjack WN* + Skull Woods EN*: Dark Lumberjack WN* + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + East Dark Death Mountain EN*: Turtle Rock WN* + Kakariko Fortune EN*: Kakariko Pond WN* + Kakariko Fortune ES*: Kakariko Pond WS* + Dark Fortune EN*: Outcast Pond WN* + Dark Fortune ES*: Outcast Pond WS* + Kakariko Pond EN*: Sanctuary WN* + Kakariko Pond ES*: Sanctuary WS* + Outcast Pond EN*: Dark Chapel WN* + Outcast Pond ES*: Dark Chapel WS* + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Graveyard EC*: River Bend WC* + Dark Graveyard EC*: Qirn Jump WC* + River Bend EN*: Potion Shop WN* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WS* + Qirn Jump EN*: Dark Witch WN* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WS* + Potion Shop EN*: Zora Approach WN* + Potion Shop EC*: Zora Approach WC* + Dark Witch EN*: Catfish Approach WN* + Dark Witch EC*: Catfish Approach WC* + Kakariko ES*: Blacksmith WS* + Village of Outcasts ES*: Hammer Pegs WS* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle ES*: Sand Dunes WN* + Pyramid ES*: Dark Dunes WN* + Maze Race ES*: Kakariko Suburb WS* + Dig Game EC: Frog WC + Dig Game ES*: Frog WS* + Kakariko Suburb ES*: Flute Boy WS* + Frog ES*: Stumpy WS* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + Links House ES*: Stone Bridge WS* + Big Bomb Shop ES*: Hammer Bridge WS* + Stone Bridge WC: Hobo EC + Stone Bridge EN*: Tree Line WN* + Stone Bridge EC*: Tree Line WC* + Hammer Bridge EN*: Dark Tree Line WN* + Hammer Bridge EC*: Dark Tree Line WC* + Desert EC: Desert Pass WC + Desert ES: Desert Pass WS + Flute Boy Approach EC*: C Whirlpool WC* + Stumpy Approach EC*: Dark C Whirlpool WC* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Lake Hylia WS*: South Pass ES* + Lake Hylia EC*: Octoballoon WC* + Lake Hylia ES*: Octoballoon WS* + Ice Lake WS*: Dark South Pass ES* + Ice Lake EC*: Bomber Corner WC* + Ice Lake ES*: Bomber Corner WS* + Desert Pass EC*: Dam WC* + Desert Pass ES*: Dam WS* + Swamp Nook EC*: Swamp WC* + Swamp Nook ES*: Swamp WS* + Dam EC*: South Pass WC* + Swamp EC*: Dark South Pass WC* + groups: + Row1/Special: + - Lost Woods NW + - Master Sword Meadow SC + - Lumberjack SW + - Mountain Pass NW + - Dark Lumberjack SW + - Bumper Cave NW + - Zora Waterfall NE + - Zoras Domain SW + Row2: + - Lost Woods SW + - Lost Woods Pass NW + - Lost Woods SC + - Lost Woods Pass NE + - Lost Woods SE + - Kakariko Fortune NE + - Skull Woods SW + - Skull Woods Pass NW + - Skull Woods SC + - Skull Woods Pass NE + - Skull Woods SE + - Dark Fortune NE + - Mountain Pass SE + - Kakariko Pond NE + - Bumper Cave SE + - Outcast Pond NE + - Zora Waterfall SE + - Zora Approach NE + - Catfish SE + - Catfish Approach NE + Row3: + - Lost Woods Pass SW + - Kakariko NW + - Lost Woods Pass SE + - Kakariko NC + - Skull Woods Pass SW + - Village of Outcasts NW + - Skull Woods Pass SE + - Village of Outcasts NC + - Kakariko Fortune SC + - Kakariko NE + - Dark Fortune SC + - Village of Outcasts NE + - Kakariko Pond SW + - Forgotten Forest NW + - Kakariko Pond SE + - Forgotten Forest NE + - Outcast Pond SW + - Shield Shop NW + - Outcast Pond SE + - Shield Shop NE + - River Bend SW + - Wooden Bridge NW + - River Bend SC + - Wooden Bridge NC + - River Bend SE + - Wooden Bridge NE + - Qirn Jump SW + - Broken Bridge NW + - Qirn Jump SC + - Broken Bridge NC + - Qirn Jump SE + - Broken Bridge NE + Row4: + - Wooden Bridge SW + - Sand Dunes NW + - Broken Bridge SW + - Dark Dunes NW + Row5: + - Kakariko SE + - Kakariko Suburb NE + - Village of Outcasts SE + - Frog NE + - Hyrule Castle SW + - Central Bonk Rocks NW + - Hyrule Castle SE + - Links House NE + - Pyramid SW + - Dark Bonk Rocks NW + - Pyramid SE + - Big Bomb Shop NE + - Sand Dunes SC + - Stone Bridge NC + - Dark Dunes SC + - Hammer Bridge NC + - Eastern Palace SW + - Tree Line NW + - Eastern Palace SE + - Eastern Nook NE + - Palace of Darkness SW + - Dark Tree Line NW + - Palace of Darkness SE + - Palace of Darkness Nook NE + Row6: + - Flute Boy SW + - Flute Boy Approach NW + - Flute Boy SC + - Flute Boy Approach NC + - Stumpy SW + - Stumpy Approach NW + - Stumpy SC + - Stumpy Approach NC + - Central Bonk Rocks SW + - C Whirlpool NW + - Dark Bonk Rocks SW + - Dark C Whirlpool NW + - Links House SC + - Statues NC + - Big Bomb Shop SC + - Hype Cave NC + - Stone Bridge SC + - Lake Hylia NW + - Hammer Bridge SC + - Ice Lake NW + - Tree Line SC + - Lake Hylia NC + - Tree Line SE + - Lake Hylia NE + - Dark Tree Line SC + - Ice Lake NC + - Dark Tree Line SE + - Ice Lake NE + Row7: + - C Whirlpool SC + - Dam NC + - Dark C Whirlpool SC + - Swamp NC + - Statues SC + - South Pass NC + - Hype Cave SC + - Dark South Pass NC + - Ice Cave SW + - Octoballoon NW + - Ice Cave SE + - Octoballoon NE + - Shopping Mall SW + - Bomber Corner NW + - Shopping Mall SE + - Bomber Corner NE +ow-tileflips: + 1: + force_together: + 1: + - 0x00 + - 0x80 + 2: + - 0x0f + - 0x81 \ No newline at end of file diff --git a/presets/world/owr_vanilla-mirroredsimilar.yaml b/presets/world/owr_vanilla-mirroredsimilar.yaml new file mode 100644 index 00000000..f9411f08 --- /dev/null +++ b/presets/world/owr_vanilla-mirroredsimilar.yaml @@ -0,0 +1,148 @@ +settings: + 1: + ow_shuffle: full + ow_terrain: true +ow-edges: + 1: + two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods EN*: Lumberjack WN* + Lost Woods SW*: Lost Woods Pass NE* + Lost Woods SC*: Lost Woods Pass NW* + Lost Woods SE*: Kakariko Fortune NE* + Skull Woods EN*: Dark Lumberjack WN* + Skull Woods SW*: Skull Woods Pass NE* + Skull Woods SC*: Skull Woods Pass NW* + Skull Woods SE*: Dark Fortune NE* + Lumberjack SW*: Mountain Pass NW* + Dark Lumberjack SW*: Bumper Cave NW* + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + East Dark Death Mountain EN*: Turtle Rock WN* + Mountain Pass SE*: Kakariko Pond NE* + Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall NE: Zoras Domain SW + Zora Waterfall SE*: Zora Approach NE* + Catfish SE*: Catfish Approach NE* + Lost Woods Pass SW*: Kakariko NC* + Lost Woods Pass SE*: Kakariko NW* + Skull Woods Pass SW*: Village of Outcasts NC* + Skull Woods Pass SE*: Village of Outcasts NW* + Kakariko Fortune EN*: Kakariko Pond WS* + Kakariko Fortune ES*: Kakariko Pond WN* + Kakariko Fortune SC*: Kakariko NE* + Dark Fortune EN*: Outcast Pond WS* + Dark Fortune ES*: Outcast Pond WN* + Dark Fortune SC*: Village of Outcasts NE* + Kakariko Pond EN*: Sanctuary WS* + Kakariko Pond ES*: Sanctuary WN* + Kakariko Pond SW*: Forgotten Forest NE* + Kakariko Pond SE*: Forgotten Forest NW* + Outcast Pond EN*: Dark Chapel WS* + Outcast Pond ES*: Dark Chapel WN* + Outcast Pond SW*: Shield Shop NE* + Outcast Pond SE*: Shield Shop NW* + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Graveyard EC*: River Bend WC* + Dark Graveyard EC*: Qirn Jump WC* + River Bend EN*: Potion Shop WS* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WN* + River Bend SW*: Wooden Bridge NE* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NW* + Qirn Jump EN*: Dark Witch WS* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WN* + Qirn Jump SW*: Broken Bridge NE* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NW* + Potion Shop EN*: Zora Approach WC* + Potion Shop EC*: Zora Approach WN* + Dark Witch EN*: Catfish Approach WC* + Dark Witch EC*: Catfish Approach WN* + Kakariko ES*: Blacksmith WS* + Kakariko SE*: Kakariko Suburb NE* + Village of Outcasts ES*: Hammer Pegs WS* + Village of Outcasts SE*: Frog NE* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle ES*: Sand Dunes WN* + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Pyramid ES*: Dark Dunes WN* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* + Sand Dunes SC*: Stone Bridge NC* + Dark Dunes SC*: Hammer Bridge NC* + Maze Race ES*: Kakariko Suburb WS* + Dig Game EC: Frog WS + Dig Game ES*: Frog WC* + Kakariko Suburb ES*: Flute Boy WS* + Frog ES*: Stumpy WS* + Flute Boy SW*: Flute Boy Approach NC* + Flute Boy SC*: Flute Boy Approach NW* + Stumpy SW*: Stumpy Approach NC* + Stumpy SC*: Stumpy Approach NW* + Central Bonk Rocks EN*: Links House WS* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WN* + Central Bonk Rocks SW*: C Whirlpool NW* + Dark Bonk Rocks EN*: Big Bomb Shop WS* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WN* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Links House SC*: Statues NC* + Links House ES*: Stone Bridge WS* + Big Bomb Shop SC*: Hype Cave NC* + Big Bomb Shop ES*: Hammer Bridge WS* + Stone Bridge WC: Hobo EC + Stone Bridge EN*: Tree Line WC* + Stone Bridge EC*: Tree Line WN* + Stone Bridge SC*: Lake Hylia NW* + Hammer Bridge EN*: Dark Tree Line WC* + Hammer Bridge EC*: Dark Tree Line WN* + Hammer Bridge SC*: Ice Lake NW* + Tree Line SC*: Lake Hylia NE* + Tree Line SE*: Lake Hylia NC* + Dark Tree Line SC*: Ice Lake NE* + Dark Tree Line SE*: Ice Lake NC* + Desert EC: Desert Pass WS + Desert ES: Desert Pass WC + Flute Boy Approach EC*: C Whirlpool WC* + Stumpy Approach EC*: Dark C Whirlpool WC* + C Whirlpool EN*: Statues WS* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WN* + C Whirlpool SC*: Dam NC* + Dark C Whirlpool EN*: Hype Cave WS* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WN* + Dark C Whirlpool SC*: Swamp NC* + Statues SC*: South Pass NC* + Hype Cave SC*: Dark South Pass NC* + Lake Hylia WS*: South Pass ES* + Lake Hylia EC*: Octoballoon WS* + Lake Hylia ES*: Octoballoon WC* + Ice Lake WS*: Dark South Pass ES* + Ice Lake EC*: Bomber Corner WS* + Ice Lake ES*: Bomber Corner WC* + Ice Cave SW*: Octoballoon NE* + Ice Cave SE*: Octoballoon NW* + Shopping Mall SW*: Bomber Corner NE* + Shopping Mall SE*: Bomber Corner NW* + Desert Pass EC*: Dam WS* + Desert Pass ES*: Dam WC* + Swamp Nook EC*: Swamp WS* + Swamp Nook ES*: Swamp WC* + Dam EC*: South Pass WC* + Swamp EC*: Dark South Pass WC \ No newline at end of file diff --git a/presets/world/owr_vanilla.yaml b/presets/world/owr_vanilla.yaml new file mode 100644 index 00000000..d26bb8fa --- /dev/null +++ b/presets/world/owr_vanilla.yaml @@ -0,0 +1,190 @@ +ow-edges: + 1: + two-way: + Lumberjack SW*: Mountain Pass NW* + Dark Lumberjack SW*: Bumper Cave NW* + Mountain Pass SE*: Kakariko Pond NE* + Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall SE*: Zora Approach NE* + Catfish SE*: Catfish Approach NE* + Kakariko Fortune EN*: Kakariko Pond WN* + Kakariko Fortune ES*: Kakariko Pond WS* + Dark Fortune EN*: Outcast Pond WN* + Dark Fortune ES*: Outcast Pond WS* + Kakariko Pond EN*: Sanctuary WN* + Kakariko Pond ES*: Sanctuary WS* + Kakariko Pond SW*: Forgotten Forest NW* + Kakariko Pond SE*: Forgotten Forest NE* + Outcast Pond EN*: Dark Chapel WN* + Outcast Pond ES*: Dark Chapel WS* + Outcast Pond SW*: Shield Shop NW* + Outcast Pond SE*: Shield Shop NE* + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Graveyard EC*: River Bend WC* + Dark Graveyard EC*: Qirn Jump WC* + River Bend EN*: Potion Shop WN* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WS* + River Bend SW*: Wooden Bridge NW* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NE* + Qirn Jump EN*: Dark Witch WN* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WS* + Qirn Jump SW*: Broken Bridge NW* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NE* + Potion Shop EN*: Zora Approach WN* + Potion Shop EC*: Zora Approach WC* + Dark Witch EN*: Catfish Approach WN* + Dark Witch EC*: Catfish Approach WC* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Sand Dunes SC*: Stone Bridge NC* + Dark Dunes SC*: Hammer Bridge NC* + Maze Race ES*: Kakariko Suburb WS* + Dig Game EC: Frog WC + Dig Game ES*: Frog WS* + Kakariko Suburb ES*: Flute Boy WS* + Frog ES*: Stumpy WS* + Flute Boy SW*: Flute Boy Approach NW* + Flute Boy SC*: Flute Boy Approach NC* + Stumpy SW*: Stumpy Approach NW* + Stumpy SC*: Stumpy Approach NC* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Central Bonk Rocks SW*: C Whirlpool NW* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Links House SC*: Statues NC* + Links House ES*: Stone Bridge WS* + Big Bomb Shop SC*: Hype Cave NC* + Big Bomb Shop ES*: Hammer Bridge WS* + Stone Bridge WC: Hobo EC + Stone Bridge EN*: Tree Line WN* + Stone Bridge EC*: Tree Line WC* + Hammer Bridge EN*: Dark Tree Line WN* + Hammer Bridge EC*: Dark Tree Line WC* + Flute Boy Approach EC*: C Whirlpool WC* + Stumpy Approach EC*: Dark C Whirlpool WC* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + C Whirlpool SC*: Dam NC* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Dark C Whirlpool SC*: Swamp NC* + Statues SC*: South Pass NC* + Hype Cave SC*: Dark South Pass NC* + Ice Cave SW*: Octoballoon NW* + Ice Cave SE*: Octoballoon NE* + Shopping Mall SW*: Bomber Corner NW* + Shopping Mall SE*: Bomber Corner NE* + Desert Pass EC*: Dam WC* + Desert Pass ES*: Dam WS* + Swamp Nook EC*: Swamp WC* + Swamp Nook ES*: Swamp WS* + Dam EC*: South Pass WC* + Swamp EC*: Dark South Pass WC* + Lumberjack SW*: Mountain Pass NW* + Dark Lumberjack SW*: Bumper Cave NW* + Mountain Pass SE*: Kakariko Pond NE* + Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall SE*: Zora Approach NE* + Catfish SE*: Catfish Approach NE* + Kakariko Fortune EN*: Kakariko Pond WN* + Kakariko Fortune ES*: Kakariko Pond WS* + Dark Fortune EN*: Outcast Pond WN* + Dark Fortune ES*: Outcast Pond WS* + Kakariko Pond EN*: Sanctuary WN* + Kakariko Pond ES*: Sanctuary WS* + Kakariko Pond SW*: Forgotten Forest NW* + Kakariko Pond SE*: Forgotten Forest NE* + Outcast Pond EN*: Dark Chapel WN* + Outcast Pond ES*: Dark Chapel WS* + Outcast Pond SW*: Shield Shop NW* + Outcast Pond SE*: Shield Shop NE* + Sanctuary EC*: Graveyard WC* + Dark Chapel EC*: Dark Graveyard WC* + Graveyard EC*: River Bend WC* + Dark Graveyard EC*: Qirn Jump WC* + River Bend EN*: Potion Shop WN* + River Bend EC*: Potion Shop WC* + River Bend ES*: Potion Shop WS* + River Bend SW*: Wooden Bridge NW* + River Bend SC*: Wooden Bridge NC* + River Bend SE*: Wooden Bridge NE* + Qirn Jump EN*: Dark Witch WN* + Qirn Jump EC*: Dark Witch WC* + Qirn Jump ES*: Dark Witch WS* + Qirn Jump SW*: Broken Bridge NW* + Qirn Jump SC*: Broken Bridge NC* + Qirn Jump SE*: Broken Bridge NE* + Potion Shop EN*: Zora Approach WN* + Potion Shop EC*: Zora Approach WC* + Dark Witch EN*: Catfish Approach WN* + Dark Witch EC*: Catfish Approach WC* + Wooden Bridge SW*: Sand Dunes NW* + Broken Bridge SW*: Dark Dunes NW* + Sand Dunes SC*: Stone Bridge NC* + Dark Dunes SC*: Hammer Bridge NC* + Maze Race ES*: Kakariko Suburb WS* + Dig Game EC: Frog WC + Dig Game ES*: Frog WS* + Kakariko Suburb ES*: Flute Boy WS* + Frog ES*: Stumpy WS* + Flute Boy SW*: Flute Boy Approach NW* + Flute Boy SC*: Flute Boy Approach NC* + Stumpy SW*: Stumpy Approach NW* + Stumpy SC*: Stumpy Approach NC* + Central Bonk Rocks EN*: Links House WN* + Central Bonk Rocks EC*: Links House WC* + Central Bonk Rocks ES*: Links House WS* + Central Bonk Rocks SW*: C Whirlpool NW* + Dark Bonk Rocks EN*: Big Bomb Shop WN* + Dark Bonk Rocks EC*: Big Bomb Shop WC* + Dark Bonk Rocks ES*: Big Bomb Shop WS* + Dark Bonk Rocks SW*: Dark C Whirlpool NW* + Links House SC*: Statues NC* + Links House ES*: Stone Bridge WS* + Big Bomb Shop SC*: Hype Cave NC* + Big Bomb Shop ES*: Hammer Bridge WS* + Stone Bridge WC: Hobo EC + Stone Bridge EN*: Tree Line WN* + Stone Bridge EC*: Tree Line WC* + Hammer Bridge EN*: Dark Tree Line WN* + Hammer Bridge EC*: Dark Tree Line WC* + Flute Boy Approach EC*: C Whirlpool WC* + Stumpy Approach EC*: Dark C Whirlpool WC* + C Whirlpool EN*: Statues WN* + C Whirlpool EC*: Statues WC* + C Whirlpool ES*: Statues WS* + C Whirlpool SC*: Dam NC* + Dark C Whirlpool EN*: Hype Cave WN* + Dark C Whirlpool EC*: Hype Cave WC* + Dark C Whirlpool ES*: Hype Cave WS* + Dark C Whirlpool SC*: Swamp NC* + Statues SC*: South Pass NC* + Hype Cave SC*: Dark South Pass NC* + Ice Cave SW*: Octoballoon NW* + Ice Cave SE*: Octoballoon NE* + Shopping Mall SW*: Bomber Corner NW* + Shopping Mall SE*: Bomber Corner NE* + Desert Pass EC*: Dam WC* + Desert Pass ES*: Dam WS* + Swamp Nook EC*: Swamp WC* + Swamp Nook ES*: Swamp WS* + Dam EC*: South Pass WC* + Swamp EC*: Dark South Pass WC* +ow-whirlpools: + 1: + two-way: + Zora Whirlpool: Lake Hylia Whirlpool + Kakariko Pond Whirlpool: Octoballoon Whirlpool + River Bend Whirlpool: C Whirlpool + Qirn Jump Whirlpool: Bomber Corner Whirlpool \ No newline at end of file diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 7ab56184..52edf0cd 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -174,8 +174,7 @@ "none", "grouped", "polar", - "limited", - "chaos" + "unrestricted" ] }, "ow_keepsimilar": { diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index 20dce34c..6d41b23d 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -239,9 +239,7 @@ " walk around and access the other plane version by walking.", "Polar: Only used when Tile Flip is enabled. This retains original", " connections even when overworld tiles are flipped.", - "Limited: Exactly nine transitions are randomly chosen as", - " cross-world connections (to emulate the nine portals).", - "Chaos: Every transition has a 50/50 chance to become a", + "Unrestricted: Every transition has a 50/50 chance to become a", " crossworld connection." ], "ow_keepsimilar": [ @@ -377,6 +375,7 @@ "Random: Take any caves can replace a random set of un-interesting caves. See documentation for full list", "Fixed: Take any caves will replace certain location. See documentation for full list" ], + "collection_rate": [ "Display collection rate (default: %(default)s)" ], "pseudoboots": [ " Start with pseudo boots that allow dashing but no item checks (default: %(default)s)"], "bombbag": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ], "startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ], @@ -427,7 +426,6 @@ "reduce_flashing": [ "Reduce some in-game flashing (default: %(default)s)" ], "shuffle_sfx": [ "Shuffle sounds effects (default: %(default)s)" ], "msu_resume": [ "Enable MSU Resume (default: %(default)s)" ], - "collection_rate": [ "Display collection rate (default: %(default)s)" ], "create_rom": [ "Create an output rom file. (default: %(default)s)" ], "gui": [ "Launch the GUI. (default: %(default)s)" ], "jsonout": [ diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 187f3c53..66aefd98 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -147,8 +147,7 @@ "randomizer.overworld.crossed.none": "None", "randomizer.overworld.crossed.grouped": "Grouped", "randomizer.overworld.crossed.polar": "Polar", - "randomizer.overworld.crossed.limited": "Limited", - "randomizer.overworld.crossed.chaos": "Chaos", + "randomizer.overworld.crossed.unrestricted": "Unrestricted", "randomizer.overworld.keepsimilar": "Keep Similar Edges Together", @@ -192,7 +191,6 @@ "randomizer.gameoptions.reduce_flashing": "Reduce Flashing", "randomizer.gameoptions.shuffle_sfx": "Shuffle Sound Effects", "randomizer.gameoptions.msu_resume": "MSU Resume", - "randomizer.gameoptions.collection_rate": "Display Collection Rate", "randomizer.gameoptions.heartcolor": "Heart Color", "randomizer.gameoptions.heartcolor.red": "Red", @@ -250,6 +248,7 @@ "randomizer.item.race": "Generate \"Race\" ROM", "randomizer.item.retro": "Retro mode", "randomizer.item.pseudoboots": "Pseudoboots", + "randomizer.item.collection_rate": "Display Collection Rate", "randomizer.item.worldstate": "World State", "randomizer.item.worldstate.standard": "Standard", diff --git a/resources/app/gui/randomize/gameoptions/widgets.json b/resources/app/gui/randomize/gameoptions/widgets.json index 7b84b8a9..5d8faeba 100644 --- a/resources/app/gui/randomize/gameoptions/widgets.json +++ b/resources/app/gui/randomize/gameoptions/widgets.json @@ -2,7 +2,6 @@ "checkboxes": { "nobgm": { "type": "checkbox" }, "msu_resume": { "type": "checkbox" }, - "collection_rate": {"type": "checkbox"}, "quickswap": { "type": "checkbox" }, "reduce_flashing": { "type": "checkbox" }, "shuffle_sfx": { "type": "checkbox" } diff --git a/resources/app/gui/randomize/item/widgets.json b/resources/app/gui/randomize/item/widgets.json index 21d95b94..652554ab 100644 --- a/resources/app/gui/randomize/item/widgets.json +++ b/resources/app/gui/randomize/item/widgets.json @@ -2,6 +2,7 @@ "checkboxes": { "hints": { "type": "checkbox" }, "pseudoboots": { "type": "checkbox" }, + "collection_rate": {"type": "checkbox"}, "race": { "type": "checkbox" } }, "leftItemFrame": { diff --git a/resources/app/gui/randomize/overworld/widgets.json b/resources/app/gui/randomize/overworld/widgets.json index c9438deb..c3c49c94 100644 --- a/resources/app/gui/randomize/overworld/widgets.json +++ b/resources/app/gui/randomize/overworld/widgets.json @@ -17,8 +17,7 @@ "none", "grouped", "polar", - "limited", - "chaos" + "unrestricted" ] }, "mixed": { diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 7eb8a31c..5ec40409 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -79,6 +79,10 @@ class CustomSettings(object): args.ow_shuffle[p] = get_setting(settings['ow_shuffle'], args.ow_shuffle[p]) args.ow_terrain[p] = get_setting(settings['ow_terrain'], args.ow_terrain[p]) args.ow_crossed[p] = get_setting(settings['ow_crossed'], args.ow_crossed[p]) + if args.ow_crossed[p] == 'chaos': + import logging + logging.getLogger('').info("Crossed OWR option 'chaos' is deprecated. Use 'unrestricted' instead.") + args.ow_crossed[p] = 'unrestricted' args.ow_keepsimilar[p] = get_setting(settings['ow_keepsimilar'], args.ow_keepsimilar[p]) args.ow_mixed[p] = get_setting(settings['ow_mixed'], args.ow_mixed[p]) args.ow_whirlpool[p] = get_setting(settings['ow_whirlpool'], args.ow_whirlpool[p]) @@ -196,6 +200,21 @@ class CustomSettings(object): return self.file_source['advanced_placements'] return None + def get_owedges(self): + if 'ow-edges' in self.file_source: + return self.file_source['ow-edges'] + return None + + def get_owcrossed(self): + if 'ow-crossed' in self.file_source: + return self.file_source['ow-crossed'] + return None + + def get_whirlpools(self): + if 'ow-whirlpools' in self.file_source: + return self.file_source['ow-whirlpools'] + return None + def get_owtileflips(self): if 'ow-tileflips' in self.file_source: return self.file_source['ow-tileflips'] @@ -355,21 +374,40 @@ class CustomSettings(object): placements[location.player][location.name] = location.item.name def record_overworld(self, world): + self.world_rep['ow-edges'] = edges = {} + self.world_rep['ow-whirlpools'] = whirlpools = {} self.world_rep['ow-tileflips'] = flips = {} - for p in self.player_range: - if p in world.owswaps and len(world.owswaps[p][0]) > 0: - flips[p] = {} - flips[p]['force_flip'] = list(HexInt(f) for f in world.owswaps[p][0] if f < 0x40 or f >= 0x80) - flips[p]['force_flip'].sort() - flips[p]['undefined_chance'] = 0 self.world_rep['ow-flutespots'] = flute = {} for p in self.player_range: + connections = edges[p] = {} + connections['two-way'] = {} + connections['one-way'] = {} + whirlconnects = whirlpools[p] = {} + whirlconnects['two-way'] = {} + whirlconnects['one-way'] = {} + # tile flips + if p in world.owswaps and len(world.owswaps[p][0]) > 0: + flips[p] = {} + flips[p]['force_flip'] = list(HexInt(f) for f in world.owswaps[p][0] if f & 0x40 == 0) + flips[p]['force_flip'].sort() + flips[p]['undefined_chance'] = 0 + # flute spots flute[p] = {} if p in world.owflutespots: flute[p]['force'] = list(HexInt(id) for id in sorted(world.owflutespots[p])) else: flute[p]['force'] = list(HexInt(id) for id in sorted(default_flute_connections)) flute[p]['forbid'] = [] + for key, data in world.spoiler.overworlds.items(): + player = data['player'] if 'player' in data else 1 + connections = edges[player] + sub = 'two-way' if data['direction'] == 'both' else 'one-way' + connections[sub][data['entrance']] = data['exit'] + for key, data in world.spoiler.whirlpools.items(): + player = data['player'] if 'player' in data else 1 + whirlconnects = whirlconnects[player] + sub = 'two-way' if data['direction'] == 'both' else 'one-way' + whirlconnects[sub][data['entrance']] = data['exit'] def record_entrances(self, world): self.world_rep['entrances'] = entrances = {} diff --git a/source/classes/constants.py b/source/classes/constants.py index 69831169..b41d03a6 100644 --- a/source/classes/constants.py +++ b/source/classes/constants.py @@ -57,6 +57,7 @@ SETTINGSTOPROCESS = { "item": { "hints": "hints", "pseudoboots": "pseudoboots", + 'collection_rate': 'collection_rate', "race": "race", "worldstate": "mode", @@ -139,7 +140,6 @@ SETTINGSTOPROCESS = { "reduce_flashing": "reduce_flashing", "shuffle_sfx": "shuffle_sfx", 'msu_resume': 'msu_resume', - 'collection_rate': 'collection_rate', }, "generation": { "bps": "bps", diff --git a/source/tools/MysteryUtils.py b/source/tools/MysteryUtils.py index 0473e2c1..12266f22 100644 --- a/source/tools/MysteryUtils.py +++ b/source/tools/MysteryUtils.py @@ -78,9 +78,9 @@ def roll_settings(weights): overworld_shuffle = get_choice('overworld_shuffle') ret.ow_shuffle = overworld_shuffle if overworld_shuffle != 'none' else 'vanilla' ret.ow_terrain = get_choice('overworld_terrain') == 'on' - valid_options = {'none', 'polar', 'grouped', 'limited', 'chaos'} + valid_options = {'none': 'none', 'polar': 'polar', 'grouped': 'polar', 'chaos': 'unrestricted', 'unrestricted': 'unrestricted'} ret.ow_crossed = get_choice('overworld_crossed') - ret.ow_crossed = ret.ow_crossed if ret.ow_crossed in valid_options else 'none' + ret.ow_crossed = valid_options[ret.ow_crossed] if ret.ow_crossed in valid_options else 'none' ret.ow_keepsimilar = get_choice('overworld_keepsimilar') == 'on' ret.ow_mixed = get_choice('overworld_swap') == 'on' ret.ow_whirlpool = get_choice('whirlpool_shuffle') == 'on'