From 26727fbfca0c1a8760513c3f16eb83618cc033d3 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 25 Aug 2023 11:18:21 -0500 Subject: [PATCH 01/30] Added Customizer support for OWR Layout and Whirlpool Shuffle --- BaseClasses.py | 14 ++- OverworldShuffle.py | 154 +++++++++++++++++++++++++------ source/classes/CustomSettings.py | 33 ++++++- 3 files changed, 169 insertions(+), 32 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 25aebbb1..3615d0e9 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2784,6 +2784,7 @@ class Spoiler(object): self.world = world self.hashes = {} self.overworlds = {} + self.whirlpools = {} self.maps = {} self.entrances = {} self.doors = {} @@ -2808,6 +2809,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 +3017,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,7 +3189,7 @@ class Spoiler(object): for fairy, bottle in self.bottles.items(): outfile.write(f'{fairy}: {bottle}\n') - if self.overworlds or self.maps: + if self.overworlds or self.whirlpools or self.maps: outfile.write('\n\nOverworld:\n\n') # flute shuffle @@ -3217,6 +3225,10 @@ class Spoiler(object): outfile.write(str('(Player ' + str(player) + ')\n')) # player name outfile.write(self.maps[('groups', player)]['text'] + '\n\n') + if self.whirlpools: + # 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.overworlds: # 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()])) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index f1752dbd..8d242d2a 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -3,6 +3,7 @@ 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 @@ -278,16 +279,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 +313,27 @@ 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: + 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 or not any(w for w in connected_whirlpools if (whirlname1 in w) and (whirlname2 in w)): + raise GenerationException('Attempting to connect whirlpools not in same pool: \'%s\' <-> \'%s\'', whirl1, whirl2) 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,7 +354,7 @@ 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) @@ -345,10 +362,10 @@ def link_overworld(world, player): 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, player) tries = 100 valid_layout = False @@ -564,21 +581,100 @@ 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, player): + def remove_pair_from_pool(edgename1, edgename2): + 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))) + for forward_pool, back_pool in groups: 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 = [] + for edgename1, edgename2 in custom_edges['two-way'].items(): + edge1 = world.check_for_owedge(edgename1, player) + edge2 = world.check_for_owedge(edgename2, player) + if edgename1 not in connected_edges and edgename2 not in connected_edges: + # attempt connection + remove_pair_from_pool(edgename1, edgename2) + connect_two_way(world, edgename1, edgename2, player, connected_edges) + # resolve parallel + if (world.owShuffle[player] == 'parallel' and + (edgename1 in parallel_links.keys() or edgename1 in parallel_links.inverse.keys())): + 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] + remove_pair_from_pool(parallel_forward_edge, parallel_back_edge) + elif not edge1.dest or not edge2.dest or edge1.dest.name != edgename2 or edge2.dest.name != edgename1: + raise GenerationException('OW Edge already connected: \'%s\' <-> \'%s\'', edgename1, edgename2) + # connect leftover similars + for forward_pool, back_pool in unresolved_similars: + for (forward_edge, back_edge) in zip(forward_pool, back_pool): + connect_two_way(world, forward_edge, back_edge, player, connected_edges) def connect_two_way(world, edgename1, edgename2, player, connected_edges=None): edge1 = world.get_entrance(edgename1, player) diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 7eb8a31c..58c9494b 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -196,6 +196,16 @@ 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_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 +365,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 = {} + 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 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: + # 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 = {} From e8193463b46138be402b35aee6c18ddf9f34afdf Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 25 Aug 2023 11:19:43 -0500 Subject: [PATCH 02/30] Fixed error with Mixed OWR + Flute Shuffle --- OverworldShuffle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 8d242d2a..0ff042b9 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -361,7 +361,7 @@ def link_overworld(world, player): #TODO: Remove, just for testing for exitname, destname in test_connections: connect_two_way(world, exitname, destname, player, connected_edges) - + # layout shuffle groups = adjust_edge_groups(world, trimmed_groups, edges_to_swap, player) @@ -1370,7 +1370,7 @@ def validate_layout(world, player): # check if can be accessed flute if 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 % 40 in flute_data and region_name in flute_data[owid % 40][0]: if world.owFluteShuffle[player] != 'vanilla' or owid % 0x40 in default_flute_connections: unreachable_regions.pop(region_name) explore_region(region_name) From 3cc166bd28cb7b87d6abc45617aec16fefd6092b Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 25 Aug 2023 11:19:43 -0500 Subject: [PATCH 03/30] Fixed error with Mixed OWR + Flute Shuffle --- OverworldShuffle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 8d242d2a..b25051ee 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -361,7 +361,7 @@ def link_overworld(world, player): #TODO: Remove, just for testing for exitname, destname in test_connections: connect_two_way(world, exitname, destname, player, connected_edges) - + # layout shuffle groups = adjust_edge_groups(world, trimmed_groups, edges_to_swap, player) @@ -1370,7 +1370,7 @@ def validate_layout(world, player): # check if can be accessed flute if 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 % 40 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) From 2f2764adb4e2c185e544a9b7c3d4765abff8ecc6 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 25 Aug 2023 13:20:24 -0500 Subject: [PATCH 04/30] Fixed error with Mixed OWR + Flute Shuffle --- OverworldShuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index b25051ee..a9c26f57 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -1370,7 +1370,7 @@ def validate_layout(world, player): # check if can be accessed flute if 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 % 0x40][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) From b68438bc351fc9985c5a70a4b416e4ed71108337 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 25 Aug 2023 14:14:03 -0500 Subject: [PATCH 05/30] Added Customizer support for OWR Layout and Whirlpool Shuffle --- OverworldShuffle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index a9c26f57..d251e157 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -593,6 +593,7 @@ def connect_custom(world, connected_edges, groups, player): forward_set.remove(edgename2) unresolved_similars.append(tuple((forward_set, back_set))) for forward_pool, back_pool in groups: + if not len(forward_pool): continue if len(forward_pool[0]) == 1: if [edgename1] in forward_pool: From 59d446aac2b915617d43e9df858dc242e216ec7d Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 25 Aug 2023 14:15:33 -0500 Subject: [PATCH 06/30] Adding consideration when flute is removed entirely from item pool --- OverworldShuffle.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index d251e157..8274f2d1 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -1030,6 +1030,9 @@ def adjust_edge_groups(world, trimmed_groups, edges_to_swap, player): return list(groups.values()) 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 @@ -1121,7 +1124,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) @@ -1239,7 +1242,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: @@ -1305,7 +1308,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\'') @@ -1343,11 +1347,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' @@ -1369,7 +1374,7 @@ 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 % 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: @@ -1394,7 +1399,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 From 179e605253244e5d05fcec7cf6e06644b920cf6d Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 27 Aug 2023 08:19:02 -0500 Subject: [PATCH 07/30] Added Customizer support for OWR Layout and Whirlpool Shuffle --- OverworldShuffle.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 8274f2d1..d70ae9f5 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -326,8 +326,10 @@ def link_overworld(world, player): whirlpools.remove(whirl1) whirlpools.remove(whirl2) connect_whirlpool(whirl1, whirl2) - elif whirl1 != whirl2 or not any(w for w in connected_whirlpools if (whirlname1 in w) and (whirlname2 in w)): - raise GenerationException('Attempting to connect whirlpools not in same pool: \'%s\' <-> \'%s\'', 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): From 712188251d4c16dba541d9caa514a4c94a2236cd Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 4 Sep 2023 19:32:34 -0500 Subject: [PATCH 08/30] Restructuring parallel_links in OWR --- OverworldShuffle.py | 48 +++++++-------- docs/ideas/shufflehorizontal.yaml | 72 ++++++++++++++++++++++ docs/ideas/shufflelargescreens.yaml | 96 +++++++++++++++++++++++++++++ docs/ideas/shufflelight.yaml | 90 +++++++++++++++++++++++++++ docs/ideas/shufflesmallscreens.yaml | 58 +++++++++++++++++ docs/ideas/shufflevertical.yaml | 81 ++++++++++++++++++++++++ 6 files changed, 421 insertions(+), 24 deletions(-) create mode 100644 docs/ideas/shufflehorizontal.yaml create mode 100644 docs/ideas/shufflelargescreens.yaml create mode 100644 docs/ideas/shufflelight.yaml create mode 100644 docs/ideas/shufflesmallscreens.yaml create mode 100644 docs/ideas/shufflevertical.yaml diff --git a/OverworldShuffle.py b/OverworldShuffle.py index d70ae9f5..59a610ee 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -14,17 +14,19 @@ version_branch = '-u' __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) @@ -112,16 +114,19 @@ def link_overworld(world, player): 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 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)) + forward_edges.remove(['Maze Race ES']) trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][0].append(['Maze Race ES']) if ['Kakariko Suburb WS'] in back_edges: - back_edges = list(filter((['Kakariko Suburb WS']).__ne__, back_edges)) + back_edges.remove(['Kakariko Suburb WS']) trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][1].append(['Kakariko Suburb WS']) trimmed_groups[group] = (forward_edges, back_edges) else: @@ -129,14 +134,15 @@ def link_overworld(world, player): (std, region, axis, terrain, _, _) = 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)) + forward_edges.remove(['Dig Game EC', 'Dig Game ES']) 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']) if ['Frog WC', 'Frog WS'] in back_edges: - back_edges = list(filter((['Frog WC', 'Frog WS']).__ne__, back_edges)) + back_edges.remove(['Frog WC', 'Frog WS']) 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']) 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': @@ -201,19 +207,13 @@ def link_overworld(world, player): 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'] - #TODO: Revisit with changes to Limited/Allowed if world.owCrossed[player] not in ['none', 'grouped', 'polar', 'chaos']: 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 edge not in parallel_links_new: 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 @@ -244,13 +244,13 @@ def link_overworld(world, player): (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) + if forward_set[0] in parallel_links_new: else: for edge in forward_set: if world.owCrossed[player] == 'chaos' and random.randint(0, 1): @@ -667,12 +667,11 @@ def connect_custom(world, connected_edges, groups, player): remove_pair_from_pool(edgename1, edgename2) connect_two_way(world, edgename1, edgename2, player, connected_edges) # resolve parallel - if (world.owShuffle[player] == 'parallel' and - (edgename1 in parallel_links.keys() or edgename1 in parallel_links.inverse.keys())): - 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] remove_pair_from_pool(parallel_forward_edge, parallel_back_edge) elif not edge1.dest or not edge2.dest or edge1.dest.name != edgename2 or edge2.dest.name != edgename1: + 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] raise GenerationException('OW Edge already connected: \'%s\' <-> \'%s\'', edgename1, edgename2) # connect leftover similars for forward_pool, back_pool in unresolved_similars: @@ -716,10 +715,10 @@ 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: @@ -2075,7 +2074,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/docs/ideas/shufflehorizontal.yaml b/docs/ideas/shufflehorizontal.yaml new file mode 100644 index 00000000..63246b32 --- /dev/null +++ b/docs/ideas/shufflehorizontal.yaml @@ -0,0 +1,72 @@ +settings: + 1: + ow_mixed: false +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 diff --git a/docs/ideas/shufflelargescreens.yaml b/docs/ideas/shufflelargescreens.yaml new file mode 100644 index 00000000..93f7472d --- /dev/null +++ b/docs/ideas/shufflelargescreens.yaml @@ -0,0 +1,96 @@ +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 WS8 + 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* \ No newline at end of file diff --git a/docs/ideas/shufflelight.yaml b/docs/ideas/shufflelight.yaml new file mode 100644 index 00000000..0a2f9f58 --- /dev/null +++ b/docs/ideas/shufflelight.yaml @@ -0,0 +1,90 @@ +meta: + players: 1 +settings: + 1: + ow_shuffle: full + ow_whirlpool: true + ow_crossed: none + ow_keepsimilar: false + ow_swapped: false + ow_terrain: true + ow_decoupled: none + ow_mixed: false + ow_fluteshuffle: vanilla +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 + one-way: [] +ow-whirlpools: + 1: + two-way: + Qirn Jump Whirlpool: Bomber Corner Whirlpool + one-way: [] diff --git a/docs/ideas/shufflesmallscreens.yaml b/docs/ideas/shufflesmallscreens.yaml new file mode 100644 index 00000000..0dbea02e --- /dev/null +++ b/docs/ideas/shufflesmallscreens.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 diff --git a/docs/ideas/shufflevertical.yaml b/docs/ideas/shufflevertical.yaml new file mode 100644 index 00000000..60c1fe9a --- /dev/null +++ b/docs/ideas/shufflevertical.yaml @@ -0,0 +1,81 @@ +settings: + 1: + ow_mixed: false +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 From 7f0e2d8b65352a6600f062f84e6d9cbe820d3276 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 4 Sep 2023 23:05:22 -0500 Subject: [PATCH 09/30] Removing yamls not meant to be commited --- docs/ideas/shufflehorizontal.yaml | 72 ---------------------- docs/ideas/shufflelargescreens.yaml | 96 ----------------------------- docs/ideas/shufflelight.yaml | 90 --------------------------- docs/ideas/shufflesmallscreens.yaml | 58 ----------------- docs/ideas/shufflevertical.yaml | 81 ------------------------ docs/presets/Swapkeys.yaml | 22 ------- docs/presets/swapkeys.yml | 17 ----- docs/vanilla_multi_lobbies.yaml | 28 --------- 8 files changed, 464 deletions(-) delete mode 100644 docs/ideas/shufflehorizontal.yaml delete mode 100644 docs/ideas/shufflelargescreens.yaml delete mode 100644 docs/ideas/shufflelight.yaml delete mode 100644 docs/ideas/shufflesmallscreens.yaml delete mode 100644 docs/ideas/shufflevertical.yaml delete mode 100644 docs/presets/Swapkeys.yaml delete mode 100644 docs/presets/swapkeys.yml delete mode 100644 docs/vanilla_multi_lobbies.yaml diff --git a/docs/ideas/shufflehorizontal.yaml b/docs/ideas/shufflehorizontal.yaml deleted file mode 100644 index 63246b32..00000000 --- a/docs/ideas/shufflehorizontal.yaml +++ /dev/null @@ -1,72 +0,0 @@ -settings: - 1: - ow_mixed: false -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 diff --git a/docs/ideas/shufflelargescreens.yaml b/docs/ideas/shufflelargescreens.yaml deleted file mode 100644 index 93f7472d..00000000 --- a/docs/ideas/shufflelargescreens.yaml +++ /dev/null @@ -1,96 +0,0 @@ -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 WS8 - 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* \ No newline at end of file diff --git a/docs/ideas/shufflelight.yaml b/docs/ideas/shufflelight.yaml deleted file mode 100644 index 0a2f9f58..00000000 --- a/docs/ideas/shufflelight.yaml +++ /dev/null @@ -1,90 +0,0 @@ -meta: - players: 1 -settings: - 1: - ow_shuffle: full - ow_whirlpool: true - ow_crossed: none - ow_keepsimilar: false - ow_swapped: false - ow_terrain: true - ow_decoupled: none - ow_mixed: false - ow_fluteshuffle: vanilla -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 - one-way: [] -ow-whirlpools: - 1: - two-way: - Qirn Jump Whirlpool: Bomber Corner Whirlpool - one-way: [] diff --git a/docs/ideas/shufflesmallscreens.yaml b/docs/ideas/shufflesmallscreens.yaml deleted file mode 100644 index 0dbea02e..00000000 --- a/docs/ideas/shufflesmallscreens.yaml +++ /dev/null @@ -1,58 +0,0 @@ -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 diff --git a/docs/ideas/shufflevertical.yaml b/docs/ideas/shufflevertical.yaml deleted file mode 100644 index 60c1fe9a..00000000 --- a/docs/ideas/shufflevertical.yaml +++ /dev/null @@ -1,81 +0,0 @@ -settings: - 1: - ow_mixed: false -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 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 From c1f98dfb517c25824d224cd69d11df7012cc8139 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 5 Sep 2023 00:14:05 -0500 Subject: [PATCH 10/30] Customizer: Force Tile Flip for connected whirlpools --- OverworldShuffle.py | 69 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 59a610ee..788c9d2e 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -317,7 +317,7 @@ def link_overworld(world, 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: + 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) @@ -784,13 +784,12 @@ def shuffle_tiles(world, groups, result_list, do_grouped, player): # customizer adjustments undefined_chance = 50 flipped_groups = list() - always_removed = list() + nonflipped_groups = 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: @@ -805,30 +804,72 @@ def shuffle_tiles(world, groups, result_list, do_grouped, player): 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) + nonflipped_groups.extend([g for g in groups if g not in flipped_groups + nonflipped_groups]) + if world.owCrossed[player] != 'none': + # ensure any customized whirlpool connections don't end up crossworld + 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(): + w1_owid = whirlpool_map[whirl1] + w2_owid = whirlpool_map[whirl2] + flip_together = (w1_owid & 0x40) == (w2_owid & 0x40) + w1_nonflipped = any(g for g in nonflipped_groups if w1_owid in g[0]) + w1_flipped = any(g for g in flipped_groups if w1_owid in g[0]) + if w1_nonflipped or w1_flipped: + group = next(g for g in groups if w2_owid in g[0]) + if w1_nonflipped == flip_together: + nonflipped_groups.append(group) + else: + flipped_groups.append(group) + else: + w2_nonflipped = any(g for g in nonflipped_groups if w2_owid in g[0]) + w2_flipped = any(g for g in flipped_groups if w2_owid in g[0]) + if w2_nonflipped or w2_flipped: + group = next(g for g in groups if w1_owid in g[0]) + if w2_nonflipped == flip_together: + nonflipped_groups.append(group) + else: + flipped_groups.append(group) + else: + w1_group = next(g for g in groups if w1_owid in g[0]) + w2_group = next(g for g in groups if w2_owid in g[0]) + if not flip_together: + if random.randint(0, 1) > 0: + nonflipped_groups.append(w1_group) + flipped_groups.append(w2_group) + else: + flipped_groups.append(w1_group) + nonflipped_groups.append(w2_group) + else: + if random.randint(1, 100) > undefined_chance: + nonflipped_groups.append(w1_group) + nonflipped_groups.append(w2_group) + else: + flipped_groups.append(w1_group) + flipped_groups.append(w2_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') 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) From 927588a3d82ef2963a24aec3b1f89e107797b8b3 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 5 Sep 2023 00:30:53 -0500 Subject: [PATCH 11/30] Adding Customizer support for Crossed OWR Also made Layout OWR compatible with Mixed OWR with asterisk notation --- BaseClasses.py | 20 +- OverworldShuffle.py | 328 ++++++++++++++++++++++++------- docs/customizer_example.yaml | 18 ++ source/classes/CustomSettings.py | 5 + 4 files changed, 296 insertions(+), 75 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 3615d0e9..6456c1c5 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) @@ -321,6 +323,16 @@ class World(object): 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: @@ -2248,7 +2260,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 +2301,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 diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 788c9d2e..d18356b5 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -205,20 +205,40 @@ def link_overworld(world, player): # crossed shuffle logging.getLogger('').debug('Crossing overworld edges') - crossed_edges = list() - #TODO: Revisit with changes to Limited/Allowed - if world.owCrossed[player] not in ['none', 'grouped', 'polar', 'chaos']: + # customizer setup + force_crossed = set() + force_noncrossed = set() + count_crossed = 0 + limited_crossed = 9 if world.owCrossed[player] == 'limited' else -1 + 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.check_for_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.check_for_owedge(edgename, player) + force_noncrossed.add(edge.name) + if 'limit_crossed' in custom_crossed: + limited_crossed = custom_crossed['limit_crossed'] + + if limited_crossed > -1: + # connect forced crossed non-parallel edges based on previously determined tile flips for edge in swapped_edges: - crossed_edges.append(edge) - - if world.owCrossed[player] in ['grouped', 'limited'] or (world.owShuffle[player] == 'vanilla' and world.owCrossed[player] == 'chaos'): if edge not in parallel_links_new: + world.owcrossededges[player].append(edge) + count_crossed = count_crossed + 1 + + if world.owCrossed[player] == 'grouped' or (world.owShuffle[player] == 'vanilla' and world.owCrossed[player] == 'chaos') or limited_crossed > -1: 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) + world.owcrossededges[player] = 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])] # update spoiler @@ -244,32 +264,77 @@ def link_overworld(world, player): (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 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) 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: - 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': + 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(0, 1): + 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(0, 1): + 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 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): + 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: - crossed_edges.append(parallel_links_new[edge]) - elif edge in parallel_links_new.inverse: - crossed_edges.append(parallel_links_new.inverse[edge][0]) + 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') @@ -367,53 +432,142 @@ def link_overworld(world, player): # layout shuffle groups = adjust_edge_groups(world, trimmed_groups, edges_to_swap, player) - connect_custom(world, connected_edges, groups, 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 + random.shuffle(groupKeys[2:]) # keep first 2 groups (Standard) first 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(): + s = 0 + while s < len(forward_edge_sets): + forward_set = forward_edge_sets[s] + if forward_set[0] in connected_edges: + 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: + del back_edge_sets[s] + continue + s += 1 + assert len(forward_edge_sets) == len(back_edge_sets) + + 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.check_for_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.check_for_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) @@ -583,8 +737,9 @@ 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, groups, player): - def remove_pair_from_pool(edgename1, edgename2): +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: @@ -593,8 +748,8 @@ def connect_custom(world, connected_edges, groups, player): else: back_set.remove(edgename1) forward_set.remove(edgename2) - unresolved_similars.append(tuple((forward_set, back_set))) - for forward_pool, back_pool in groups: + 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: @@ -635,7 +790,7 @@ def connect_custom(world, connected_edges, groups, player): else: break for pair in unresolved_similars: - forward_set, back_set = pair + forward_set, back_set, _ = pair if edgename1 in forward_set: if edgename2 in back_set: unresolved_similars.remove(pair) @@ -659,24 +814,45 @@ def connect_custom(world, connected_edges, groups, player): 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.check_for_owedge(edgename1, player) edge2 = world.check_for_owedge(edgename2, player) - if edgename1 not in connected_edges and edgename2 not in connected_edges: + 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.check_for_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(edgename1, edgename2) - connect_two_way(world, edgename1, edgename2, player, connected_edges) + remove_pair_from_pool(edge1.name, edge2.name, is_crossed) + connect_two_way(world, edge1.name, edge2.name, player, connected_edges) # resolve parallel - remove_pair_from_pool(parallel_forward_edge, parallel_back_edge) - elif not edge1.dest or not edge2.dest or edge1.dest.name != edgename2 or edge2.dest.name != edgename1: 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 in unresolved_similars: + for forward_pool, back_pool, is_crossed in unresolved_similars: for (forward_edge, back_edge) in zip(forward_pool, back_pool): - connect_two_way(world, forward_edge, back_edge, player, connected_edges) + 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) @@ -1054,12 +1230,16 @@ def reorganize_groups(world, groups, player): def adjust_edge_groups(world, trimmed_groups, edges_to_swap, player): groups = defaultdict(lambda: ([],[])) + limited_crossed = False + 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]) for (key, group) in trimmed_groups.items(): (mode, wrld, dir, terrain, parallel, count) = key if mode == OpenStd.Standard: groups[key] = group else: - if world.owCrossed[player] == 'chaos': + if world.owCrossed[player] == 'chaos' and not limited_crossed: groups[(mode, None, dir, terrain, parallel, count)][0].extend(group[0]) groups[(mode, None, dir, terrain, parallel, count)][1].extend(group[1]) else: @@ -1069,7 +1249,7 @@ def adjust_edge_groups(world, trimmed_groups, edges_to_swap, player): 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()) + 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) diff --git a/docs/customizer_example.yaml b/docs/customizer_example.yaml index ecf209b1..36bfbdde 100644 --- a/docs/customizer_example.yaml +++ b/docs/customizer_example.yaml @@ -69,6 +69,24 @@ 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 +ow-crossed: + 1: + force_crossed: + - Links House ES* + - Kakariko Fortune ES* + force_noncrossed: + - Links House NE + limit_crossed: 9 # emulates Limited Crossed +ow-whirlpools: + 1: + two-way: + River Bend Whirlpool: Lake Hylia Whirlpool ow-tileflips: 1: force_flip: diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 58c9494b..96330516 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -201,6 +201,11 @@ class CustomSettings(object): 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'] From 290fe9f3bd17e5118da0f07dc502ec979ef88ed8 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 5 Sep 2023 00:44:02 -0500 Subject: [PATCH 12/30] Minor logical code restructure Mostly just indentation but GitHub textdiff sucks --- OverworldShuffle.py | 177 ++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index d18356b5..498a28ff 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -233,105 +233,104 @@ def link_overworld(world, player): world.owcrossededges[player].append(edge) count_crossed = count_crossed + 1 - if world.owCrossed[player] == 'grouped' or (world.owShuffle[player] == 'vanilla' and world.owCrossed[player] == 'chaos') or limited_crossed > -1: - 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 = [[],[],[]] - world.owcrossededges[player] = 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 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 = [[],[],[]] + world.owcrossededges[player] = 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])] - # 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: - 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): + # 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] == 'chaos'): + 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 - skip_forward = True + continue 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(0, 1): - 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(0, 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 - assert len(world.owcrossededges[player]) == len(set(world.owcrossededges[player])), "Same edge added to crossed edges" + 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(0, 1): + 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(0, 1): + 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 - random.shuffle(crossed_candidates) - 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" + if limited_crossed > -1: + limit = limited_crossed - count_crossed + random.shuffle(crossed_candidates) + 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]) + 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+world.owcrossededges[player] if (e not in swapped_edges) or (e not in world.owcrossededges[player])] From b0c9f943efd91c95deacf46abe7c1ee10a478e69 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 5 Sep 2023 02:00:19 -0500 Subject: [PATCH 13/30] Adding Customizer documentation for OWR modes --- docs/Customizer.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/Customizer.md b/docs/Customizer.md index 68687c23..0a6c2394 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -87,6 +87,38 @@ 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 one primary subsection: `two-way`. + +#### 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. + +### 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 three primary subsections: `force_crossed`, `force_noncrossed`, and `limit_crossed`. + +#### 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. 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. + +#### 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). + +### 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`. From 508a68e5e5b00c2214967447d24b1d9f53ba294c Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 5 Sep 2023 03:01:49 -0500 Subject: [PATCH 14/30] Merging Limited and Chaos Crossed OWR options into Unrestricted --- BaseClasses.py | 2 +- OverworldShuffle.py | 8 +++---- README.md | 22 ++++++------------- Rom.py | 2 +- TestSuiteStat.py | 2 +- docs/Customizer.md | 2 +- mystery_example.yml | 3 +-- resources/app/cli/args.json | 3 +-- resources/app/cli/lang/en.json | 4 +--- resources/app/gui/lang/en.json | 3 +-- .../app/gui/randomize/overworld/widgets.json | 3 +-- source/classes/CustomSettings.py | 4 ++++ source/tools/MysteryUtils.py | 4 ++-- 13 files changed, 26 insertions(+), 36 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 6456c1c5..5381d677 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3481,7 +3481,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/OverworldShuffle.py b/OverworldShuffle.py index 498a28ff..36dded6b 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -210,7 +210,7 @@ def link_overworld(world, player): force_crossed = set() force_noncrossed = set() count_crossed = 0 - limited_crossed = 9 if world.owCrossed[player] == 'limited' else -1 + limited_crossed = -1 if world.customizer: custom_crossed = world.customizer.get_owcrossed() if custom_crossed and player in custom_crossed: @@ -257,7 +257,7 @@ def link_overworld(world, player): 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] == 'chaos'): + 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 @@ -1084,7 +1084,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: @@ -1238,7 +1238,7 @@ def adjust_edge_groups(world, trimmed_groups, edges_to_swap, player): if mode == OpenStd.Standard: groups[key] = group else: - if world.owCrossed[player] == 'chaos' and not limited_crossed: + if world.owCrossed[player] == 'unrestricted' and not limited_crossed: groups[(mode, None, dir, terrain, parallel, count)][0].extend(group[0]) groups[(mode, None, dir, terrain, parallel, count)][1].extend(group[1]) else: 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 0a6c2394..67aa37e5 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -107,7 +107,7 @@ This must be defined by player. Each player number should be listed with the app #### 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). +`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 if `ow_crossed: unrestricted` is in the `settings` section. ### ow-whirlpools 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/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..ca4543d0 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": [ diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 187f3c53..95336905 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", 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 96330516..c3f20ff9 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]) 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' From bcb224ade8bee3e822751ecbb87687e517ad064a Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 5 Sep 2023 13:38:29 -0500 Subject: [PATCH 15/30] Some code simplification --- BaseClasses.py | 81 +++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 50 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 5381d677..b7e9d812 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -240,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(): @@ -296,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): @@ -319,28 +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: - 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 is_tile_swapped(self, owid, player): return (self.mode[player] == 'inverted') != (owid in self.owswaps[player][0] and self.owMixed[player]) @@ -366,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 From 99753c00390926b5d97e3cb6ded6f6bb1797e3a8 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 6 Sep 2023 12:39:57 -0500 Subject: [PATCH 16/30] Minor fixed to OWR algorithm --- OverworldShuffle.py | 29 +++++++++++++---------------- source/classes/CustomSettings.py | 2 +- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 36dded6b..10853982 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -217,11 +217,11 @@ def link_overworld(world, player): 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.check_for_owedge(edgename, player) + 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.check_for_owedge(edgename, player) + edge = world.get_owedge(edgename, player) force_noncrossed.add(edge.name) if 'limit_crossed' in custom_crossed: limited_crossed = custom_crossed['limit_crossed'] @@ -322,9 +322,10 @@ def link_overworld(world, player): if limited_crossed > -1: limit = limited_crossed - count_crossed - random.shuffle(crossed_candidates) - for edge_set in crossed_candidates[:limit]: - world.owcrossededges[player].extend(edge_set) + if limit > 1: + random.shuffle(crossed_candidates) + 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]): @@ -488,7 +489,7 @@ def link_overworld(world, player): back_parallel_lw_sets, back_parallel_dw_sets = [], [] for edge_set in forward_edge_sets: - if world.check_for_owedge(edge_set[0], player).is_lw(world): + 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]) @@ -497,7 +498,7 @@ def link_overworld(world, player): 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.check_for_owedge(edge_set[0], player).is_lw(world): + 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]) @@ -817,12 +818,12 @@ def connect_custom(world, connected_edges, groups, forced, player): 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.check_for_owedge(edgename1, player) - edge2 = world.check_for_owedge(edgename2, player) + 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.check_for_owedge(edge2.name + '*', player) + edge2 = world.get_owedge(edge2.name + '*', player) is_crossed = not is_crossed else: raise GenerationException('Violation of force crossed rules: \'%s\' <-> \'%s\'', edgename1, edgename2) @@ -856,13 +857,9 @@ def connect_custom(world, connected_edges, groups, forced, player): 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): diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index c3f20ff9..5ec40409 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -388,7 +388,7 @@ class CustomSettings(object): # 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 or f >= 0x80) + 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 From 72e41e20dc4cd6460880620a5c5d532a60caecfc Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 6 Sep 2023 13:58:19 -0500 Subject: [PATCH 17/30] Implemented Customizer OWR Edge Groups --- OWEdges.py | 88 ++++++++++++++++++------------------ OverworldShuffle.py | 54 ++++++++++++++-------- docs/Customizer.md | 15 +++++- docs/customizer_example.yaml | 11 +++++ 4 files changed, 104 insertions(+), 64 deletions(-) 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 10853982..7e3438e7 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -60,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) @@ -75,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: @@ -119,28 +119,28 @@ def link_overworld(world, 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.remove(['Maze Race ES']) - trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][0].append(['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.remove(['Kakariko Suburb WS']) - trimmed_groups[(std, region, axis, terrain, IsParallel.No, 1)][1].append(['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.remove(['Dig Game EC', 'Dig Game ES']) - 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']) + 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.remove(['Frog WC', 'Frog WS']) - 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']) + 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()})} @@ -260,7 +260,7 @@ def link_overworld(world, 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 + (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: @@ -459,7 +459,7 @@ def link_overworld(world, player): random.shuffle(groupKeys) for key in groupKeys: - (mode, wrld, dir, terrain, parallel, count) = key + (mode, wrld, dir, terrain, parallel, count, _) = key (forward_edge_sets, back_edge_sets) = groups[key] def remove_connected(): s = 0 @@ -1227,24 +1227,42 @@ 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] == 'unrestricted' and not limited_crossed: - groups[(mode, None, dir, terrain, parallel, count)][0].extend(group[0]) - groups[(mode, None, dir, terrain, parallel, count)][1].extend(group[1]) + 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) + 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): diff --git a/docs/Customizer.md b/docs/Customizer.md index 67aa37e5..d30a7d30 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -89,7 +89,7 @@ You may define an item and a list of locations that an item should not be placed ### 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 one primary subsection: `two-way`. +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 @@ -97,13 +97,24 @@ This must be defined by player. Each player number should be listed with the app `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 three primary subsections: `force_crossed`, `force_noncrossed`, and `limit_crossed`. #### 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. 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. +`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 diff --git a/docs/customizer_example.yaml b/docs/customizer_example.yaml index 36bfbdde..a9cebd90 100644 --- a/docs/customizer_example.yaml +++ b/docs/customizer_example.yaml @@ -75,6 +75,17 @@ ow-edges: 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: From d709ab7a1965cfd5f1a89d4e32d5299b0351a209 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 6 Sep 2023 17:19:56 -0500 Subject: [PATCH 18/30] Fixed some broken randomization --- OverworldShuffle.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 7e3438e7..ba78893a 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -454,7 +454,9 @@ def link_overworld(world, player): groupKeys = list(groups.keys()) if world.mode[player] == 'standard': - random.shuffle(groupKeys[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(groupKeys) @@ -697,7 +699,9 @@ def link_overworld(world, player): if 0x30 in flute_pool and 0x30 not in forbidden_spots and len(new_spots) < target_spots and ('Desert Teleporter Ledge' in sector[1] or 'Mire Teleporter Ledge' in sector[1]): addSpot(0x30, True, True) # guarantee desert/mire access - random.shuffle(sector[1]) + subset = sector[1] + random.shuffle(subset) + sector[1] = subset f = 0 t = 0 while len(new_spots) < target_spots: From 4cb28a11554b92c60996b8782d9512607dd8e5c4 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 6 Sep 2023 17:36:09 -0500 Subject: [PATCH 19/30] Force tile group merges if Customizer edge connections force it --- OverworldShuffle.py | 181 ++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 81 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index ba78893a..3e737ac5 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -109,7 +109,6 @@ 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() @@ -152,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, player, False) + swapped_edges = shuffle_tiles(world, tile_groups, world.owswaps[player], False, (force_flipped, force_nonflipped, undefined_chance), player) update_world_regions(world, player) @@ -237,7 +237,8 @@ def link_overworld(world, player): # 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 = [[],[],[]] - world.owcrossededges[player] = shuffle_tiles(world, define_tile_groups(world, player, True), ow_crossed_tiles_mask, True, player) + tile_groups, force_flipped, force_nonflipped, undefined_chance = define_tile_groups(world, player, True) + 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 @@ -900,7 +901,96 @@ def connect_two_way(world, edgename1, edgename2, player, connected_edges=None): 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, player): + undefined_chance = 50 + flipped_groups = list() + nonflipped_groups = list() + merged_owids = list() + if world.customizer: + 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'] + + for group in tile_ow_groups: + if any(owid in group[0]+group[1] for owid in forced_nonflips): + nonflipped_groups.append(group) + if any(owid in group[0]+group[1] 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: @@ -957,82 +1047,6 @@ 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() - nonflipped_groups = 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] - 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) - - if undefined_chance == 0: - nonflipped_groups.extend([g for g in groups if g not in flipped_groups + nonflipped_groups]) - if world.owCrossed[player] != 'none': - # ensure any customized whirlpool connections don't end up crossworld - 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(): - w1_owid = whirlpool_map[whirl1] - w2_owid = whirlpool_map[whirl2] - flip_together = (w1_owid & 0x40) == (w2_owid & 0x40) - w1_nonflipped = any(g for g in nonflipped_groups if w1_owid in g[0]) - w1_flipped = any(g for g in flipped_groups if w1_owid in g[0]) - if w1_nonflipped or w1_flipped: - group = next(g for g in groups if w2_owid in g[0]) - if w1_nonflipped == flip_together: - nonflipped_groups.append(group) - else: - flipped_groups.append(group) - else: - w2_nonflipped = any(g for g in nonflipped_groups if w2_owid in g[0]) - w2_flipped = any(g for g in flipped_groups if w2_owid in g[0]) - if w2_nonflipped or w2_flipped: - group = next(g for g in groups if w1_owid in g[0]) - if w2_nonflipped == flip_together: - nonflipped_groups.append(group) - else: - flipped_groups.append(group) - else: - w1_group = next(g for g in groups if w1_owid in g[0]) - w2_group = next(g for g in groups if w2_owid in g[0]) - if not flip_together: - if random.randint(0, 1) > 0: - nonflipped_groups.append(w1_group) - flipped_groups.append(w2_group) - else: - flipped_groups.append(w1_group) - nonflipped_groups.append(w2_group) - else: - if random.randint(1, 100) > undefined_chance: - nonflipped_groups.append(w1_group) - nonflipped_groups.append(w2_group) - else: - flipped_groups.append(w1_group) - flipped_groups.append(w2_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') - attempts = 1 if 0 < undefined_chance < 100: # do roughly 1000 attempts at a full list @@ -1158,6 +1172,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, player) + for owids in merged_owids: + merge_groups([owids]) + tile_groups = [] for group in groups: if can_shuffle_group(group): @@ -1167,7 +1186,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 = {} From 535945477bb0bf4ffb819d167712aa043c0e74e8 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 6 Sep 2023 17:46:29 -0500 Subject: [PATCH 20/30] Fixed some broken randomization --- OverworldShuffle.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 3e737ac5..27abd90a 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -700,9 +700,7 @@ def link_overworld(world, player): if 0x30 in flute_pool and 0x30 not in forbidden_spots and len(new_spots) < target_spots and ('Desert Teleporter Ledge' in sector[1] or 'Mire Teleporter Ledge' in sector[1]): addSpot(0x30, True, True) # guarantee desert/mire access - subset = sector[1] - random.shuffle(subset) - sector[1] = subset + random.shuffle(sector[1]) f = 0 t = 0 while len(new_spots) < target_spots: From c0985dacdc29694657ac1ab31d254b5c116de17e Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 7 Sep 2023 11:30:32 -0500 Subject: [PATCH 21/30] Adding Customizer support for grouping tiles together in Mixed OWR --- OverworldShuffle.py | 2 ++ docs/Customizer.md | 11 +++++++++++ docs/customizer_example.yaml | 4 ++++ 3 files changed, 17 insertions(+) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 27abd90a..d0abce2d 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -916,6 +916,8 @@ def determine_forced_flips(world, tile_ow_groups, player): 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[0]+group[1] for owid in forced_nonflips): diff --git a/docs/Customizer.md b/docs/Customizer.md index d30a7d30..075e8602 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -149,6 +149,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 a9cebd90..8849f2e7 100644 --- a/docs/customizer_example.yaml +++ b/docs/customizer_example.yaml @@ -105,6 +105,10 @@ ow-tileflips: force_no_flip: - 0x2c - 0x18 + force_together: + someDescription: + - 0x16 + - 0x2b undefined_chance: 50 ow-flutespots: 1: From a3d7abf71ac21e25150f15e0407fadba71ef7e24 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 7 Sep 2023 11:31:24 -0500 Subject: [PATCH 22/30] Small bugfix for OWR Customizer stuff --- OverworldShuffle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index d0abce2d..f63fbcea 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -920,9 +920,9 @@ def determine_forced_flips(world, tile_ow_groups, player): merged_owids = list(custom_flips['force_together'].values()) for group in tile_ow_groups: - if any(owid in group[0]+group[1] for owid in forced_nonflips): + if any(owid in group for owid in forced_nonflips): nonflipped_groups.append(group) - if any(owid in group[0]+group[1] for owid in forced_flips): + if any(owid in group for owid in forced_flips): flipped_groups.append(group) if undefined_chance == 0: From e19622b566c78ffb136e8e9706752900308d6b80 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 8 Sep 2023 08:48:15 -0500 Subject: [PATCH 23/30] Fixed and reorganized OWR sections on spoilers --- BaseClasses.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index b7e9d812..08ccdd93 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3188,50 +3188,50 @@ class Spoiler(object): for fairy, bottle in self.bottles.items(): outfile.write(f'{fairy}: {bottle}\n') - if self.overworlds or self.whirlpools 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') - - if self.whirlpools: - # 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()])) + 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') From 78abcb4196e52408cdfa4f8de5b5a6b79a53c56f Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 9 Sep 2023 16:28:09 -0500 Subject: [PATCH 24/30] Implemented remaining Crossed OWR Customizer support --- OverworldShuffle.py | 22 ++++++++++++++-------- docs/Customizer.md | 16 +++++++++++++--- docs/customizer_example.yaml | 1 + 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index f63fbcea..48d714eb 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -151,7 +151,7 @@ def link_overworld(world, player): # tile shuffle logging.getLogger('').debug('Flipping overworld tiles') if world.owMixed[player]: - tile_groups, force_flipped, force_nonflipped, undefined_chance = define_tile_groups(world, player, False) + 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) @@ -211,6 +211,7 @@ def link_overworld(world, player): 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: @@ -225,6 +226,8 @@ def link_overworld(world, 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'] if limited_crossed > -1: # connect forced crossed non-parallel edges based on previously determined tile flips @@ -237,7 +240,7 @@ def link_overworld(world, player): # 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, player, True) + 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])] @@ -310,13 +313,13 @@ def link_overworld(world, player): if not skip_back: if limited_crossed > -1: crossed_candidates.append(back_set) - elif random.randint(0, 1): + 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(0, 1): + 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" @@ -899,13 +902,16 @@ def connect_two_way(world, edgename1, edgename2, player, connected_edges=None): except KeyError: raise KeyError('No parallel edge for edge %s' % edgename2) -def determine_forced_flips(world, tile_ow_groups, 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: - custom_flips = world.customizer.get_owtileflips() + 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() @@ -1113,7 +1119,7 @@ def shuffle_tiles(world, groups, result_list, do_grouped, forced_flips, 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): @@ -1173,7 +1179,7 @@ def define_tile_groups(world, player, 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, player) + flipped_groups, nonflipped_groups, undefined_chance, merged_owids = determine_forced_flips(world, groups, do_grouped, player) for owids in merged_owids: merge_groups([owids]) diff --git a/docs/Customizer.md b/docs/Customizer.md index 075e8602..872003c5 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -110,7 +110,7 @@ someDescription: ### 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 three primary subsections: `force_crossed`, `force_noncrossed`, and `limit_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 @@ -118,7 +118,17 @@ This must be defined by player. Each player number should be listed with the app #### 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 if `ow_crossed: unrestricted` is in the `settings` section. +`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 @@ -132,7 +142,7 @@ This must be defined by player. Each player number should be listed with the app ### 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 diff --git a/docs/customizer_example.yaml b/docs/customizer_example.yaml index 8849f2e7..75c997bc 100644 --- a/docs/customizer_example.yaml +++ b/docs/customizer_example.yaml @@ -94,6 +94,7 @@ ow-crossed: force_noncrossed: - Links House NE limit_crossed: 9 # emulates Limited Crossed + undefined_chance: 25 ow-whirlpools: 1: two-way: From 9adba09c54c28e4129fbea7c9d9758a1934de9d4 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 9 Sep 2023 16:31:27 -0500 Subject: [PATCH 25/30] Adding additional info to error message during OWR Layout placement --- OverworldShuffle.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 48d714eb..43e9e70c 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -468,10 +468,12 @@ def link_overworld(world, player): (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 @@ -479,10 +481,14 @@ def link_overworld(world, player): 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 - assert len(forward_edge_sets) == len(back_edge_sets) + 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) From 268bc1b278ab853ec32f3c03089f2de862e45104 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 10 Sep 2023 14:43:15 -0500 Subject: [PATCH 26/30] Adding many OWR customizer mode yamls --- presets/world/owr_districtshuffle-full.yaml | 286 +++++++++++++++++ presets/world/owr_districtshuffle-pangea.yaml | 151 +++++++++ .../owr_districtshuffle-vanillaborders.yaml | 300 ++++++++++++++++++ presets/world/owr_quadrantshuffle-full.yaml | 298 +++++++++++++++++ .../owr_quadrantshuffle-vanillaborders.yaml | 275 ++++++++++++++++ presets/world/owr_shuffle-dark.yaml | 94 ++++++ presets/world/owr_shuffle-horizontal.yaml | 76 +++++ .../owr_shuffle-horizontalbycolumns.yaml | 233 ++++++++++++++ presets/world/owr_shuffle-largescreens.yaml | 210 ++++++++++++ presets/world/owr_shuffle-light.yaml | 84 +++++ .../world/owr_shuffle-separatemountain.yaml | 16 + presets/world/owr_shuffle-smallscreens.yaml | 58 ++++ presets/world/owr_shuffle-vanillaloop.yaml | 41 +++ presets/world/owr_shuffle-vertical.yaml | 87 +++++ presets/world/owr_shuffle-verticalbyrows.yaml | 227 +++++++++++++ presets/world/owr_vanilla-maxcrossed.yaml | 7 + .../world/owr_vanilla-mirroredsimilar.yaml | 148 +++++++++ presets/world/owr_vanilla.yaml | 190 +++++++++++ 18 files changed, 2781 insertions(+) create mode 100644 presets/world/owr_districtshuffle-full.yaml create mode 100644 presets/world/owr_districtshuffle-pangea.yaml create mode 100644 presets/world/owr_districtshuffle-vanillaborders.yaml create mode 100644 presets/world/owr_quadrantshuffle-full.yaml create mode 100644 presets/world/owr_quadrantshuffle-vanillaborders.yaml create mode 100644 presets/world/owr_shuffle-dark.yaml create mode 100644 presets/world/owr_shuffle-horizontal.yaml create mode 100644 presets/world/owr_shuffle-horizontalbycolumns.yaml create mode 100644 presets/world/owr_shuffle-largescreens.yaml create mode 100644 presets/world/owr_shuffle-light.yaml create mode 100644 presets/world/owr_shuffle-separatemountain.yaml create mode 100644 presets/world/owr_shuffle-smallscreens.yaml create mode 100644 presets/world/owr_shuffle-vanillaloop.yaml create mode 100644 presets/world/owr_shuffle-vertical.yaml create mode 100644 presets/world/owr_shuffle-verticalbyrows.yaml create mode 100644 presets/world/owr_vanilla-maxcrossed.yaml create mode 100644 presets/world/owr_vanilla-mirroredsimilar.yaml create mode 100644 presets/world/owr_vanilla.yaml 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-maxcrossed.yaml b/presets/world/owr_vanilla-maxcrossed.yaml new file mode 100644 index 00000000..d77d78e5 --- /dev/null +++ b/presets/world/owr_vanilla-maxcrossed.yaml @@ -0,0 +1,7 @@ +settings: + 1: + ow_shuffle: vanilla + ow_crossed: unrestricted +ow-crossed: + 1: + undefined_chance: 100 \ 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 From 9bb29d32d85e155ce787cc7adb4f579dfa791c76 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 10 Sep 2023 14:44:46 -0500 Subject: [PATCH 27/30] Changing TakeAny sword to count towards item collection --- ItemList.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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)) From 10241268356e263c458edf9893bd1805ab5fc7f2 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 10 Sep 2023 14:51:43 -0500 Subject: [PATCH 28/30] Moving Display Collection Rate option away from post-gen options --- resources/app/cli/lang/en.json | 2 +- resources/app/gui/lang/en.json | 2 +- resources/app/gui/randomize/gameoptions/widgets.json | 1 - resources/app/gui/randomize/item/widgets.json | 1 + source/classes/constants.py | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index ca4543d0..6d41b23d 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -375,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)" ], @@ -425,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 95336905..66aefd98 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -191,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", @@ -249,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/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", From 3a06049bc4d69090bdba44da5dfad3d42c02c385 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 10 Sep 2023 15:40:40 -0500 Subject: [PATCH 29/30] Adding many OWR customizer mode yamls --- ...wr_vanilla-maxcrossed.yaml => owr_crossed-limited.yaml} | 3 +-- presets/world/owr_crossed-max.yaml | 7 +++++++ 2 files changed, 8 insertions(+), 2 deletions(-) rename presets/world/{owr_vanilla-maxcrossed.yaml => owr_crossed-limited.yaml} (55%) create mode 100644 presets/world/owr_crossed-max.yaml diff --git a/presets/world/owr_vanilla-maxcrossed.yaml b/presets/world/owr_crossed-limited.yaml similarity index 55% rename from presets/world/owr_vanilla-maxcrossed.yaml rename to presets/world/owr_crossed-limited.yaml index d77d78e5..54d07a32 100644 --- a/presets/world/owr_vanilla-maxcrossed.yaml +++ b/presets/world/owr_crossed-limited.yaml @@ -1,7 +1,6 @@ settings: 1: - ow_shuffle: vanilla ow_crossed: unrestricted ow-crossed: 1: - undefined_chance: 100 \ No newline at end of file + 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 From a9b5dffcfa016c1cbcf03b85d111576d33710ec4 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 10 Sep 2023 17:11:26 -0500 Subject: [PATCH 30/30] Version bump 0.3.3.0 --- CHANGELOG.md | 6 ++++++ OverworldShuffle.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) 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/OverworldShuffle.py b/OverworldShuffle.py index 43e9e70c..a4e54cca 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType 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 = '-u'