Implemented Whirlpool Shuffle

This commit is contained in:
codemann8
2021-10-27 01:19:01 -05:00
parent 32d6a55838
commit 08ab32537b
15 changed files with 225 additions and 86 deletions

View File

@@ -26,6 +26,7 @@ class World(object):
self.owCrossed = owCrossed.copy()
self.owKeepSimilar = {}
self.owMixed = owMixed.copy()
self.owWhirlpoolShuffle = {}
self.owFluteShuffle = {}
self.shuffle = shuffle.copy()
self.doorShuffle = doorShuffle.copy()
@@ -76,6 +77,7 @@ class World(object):
self.spoiler = Spoiler(self)
self.lamps_needed_for_dark_rooms = 1
self.owswaps = {}
self.owwhirlpools = {}
self.owedges = []
self._owedge_cache = {}
self.owflutespots = {}
@@ -105,6 +107,7 @@ class World(object):
set_player_attr('_region_cache', {})
set_player_attr('player_names', [])
set_player_attr('owswaps', [[],[],[]])
set_player_attr('owwhirlpools', [])
set_player_attr('remote_items', False)
set_player_attr('required_medallions', ['Ether', 'Quake'])
set_player_attr('swamp_patch_required', False)
@@ -2693,6 +2696,7 @@ class Spoiler(object):
'ow_crossed': self.world.owCrossed,
'ow_keepsimilar': self.world.owKeepSimilar,
'ow_mixed': self.world.owMixed,
'ow_whirlpool': self.world.owWhirlpoolShuffle,
'ow_fluteshuffle': self.world.owFluteShuffle,
'shuffle': self.world.shuffle,
'shuffleganon': self.world.shuffle_ganon,
@@ -2784,6 +2788,7 @@ class Spoiler(object):
outfile.write('Keep Similar OW Edges Together:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_keepsimilar'][player] else 'No'))
outfile.write('Crossed OW:'.ljust(line_width) + '%s\n' % self.metadata['ow_crossed'][player])
outfile.write('Swapped OW (Mixed):'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_mixed'][player] else 'No'))
outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_whirlpool'][player] else 'No'))
outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player])
outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player])
outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shuffleganon'][player] else 'No'))
@@ -2807,6 +2812,7 @@ class Spoiler(object):
if self.startinventory:
outfile.write('Starting Inventory:'.ljust(line_width))
outfile.write('\n'.ljust(line_width+1).join(self.startinventory))
outfile.write('\n\nRequirements:\n\n')
for dungeon, medallion in self.medallions.items():
outfile.write(f'{dungeon}:'.ljust(line_width) + '%s Medallion\n' % medallion)

3
CLI.py
View File

@@ -94,7 +94,7 @@ def parse_cli(argv, no_defaults=False):
playerargs = parse_cli(shlex.split(getattr(ret, f"p{player}")), True)
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
'ow_shuffle', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_fluteshuffle',
'ow_shuffle', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle',
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid',
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
'bombbag', 'shuffleganon',
@@ -149,6 +149,7 @@ def parse_settings():
"ow_crossed": "none",
"ow_keepsimilar": False,
"ow_mixed": False,
"ow_whirlpool": False,
"ow_fluteshuffle": "vanilla",
"shuffle": "vanilla",
"shufflelinks": False,

View File

@@ -87,6 +87,7 @@ def main(args, seed=None, fish=None):
world.crystals_ganon_orig = args.crystals_ganon.copy()
world.crystals_gt_orig = args.crystals_gt.copy()
world.owKeepSimilar = args.ow_keepsimilar.copy()
world.owWhirlpoolShuffle = args.ow_whirlpool.copy()
world.owFluteShuffle = args.ow_fluteshuffle.copy()
world.open_pyramid = args.openpyramid.copy()
world.boss_shuffle = args.shufflebosses.copy()
@@ -406,6 +407,7 @@ def copy_world(world):
ret.crystals_ganon_orig = world.crystals_ganon_orig.copy()
ret.crystals_gt_orig = world.crystals_gt_orig.copy()
ret.owKeepSimilar = world.owKeepSimilar.copy()
ret.owWhirlpoolShuffle = world.owWhirlpoolShuffle.copy()
ret.owFluteShuffle = world.owFluteShuffle.copy()
ret.open_pyramid = world.open_pyramid.copy()
ret.boss_shuffle = world.boss_shuffle.copy()

View File

@@ -138,6 +138,7 @@ def roll_settings(weights):
ret.ow_crossed = get_choice('overworld_crossed')
ret.ow_keepsimilar = get_choice('overworld_keepsimilar') == 'on'
ret.ow_mixed = get_choice('overworld_swap') == 'on'
ret.ow_whirlpool = get_choice('whirlpool_shuffle') == 'on'
overworld_flute = get_choice('flute_shuffle')
ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla'
entrance_shuffle = get_choice('entrance_shuffle')

View File

@@ -969,7 +969,7 @@ OWTileRegions = bidict({
})
OWTileGroups = {
("Woods", "Regular"): (
("Woods", "Regular", "None"): (
[
0x00, 0x2d, 0x80
],
@@ -977,7 +977,7 @@ OWTileGroups = {
0x40, 0x6d
]
),
("Lumberjack", "Regular"): (
("Lumberjack", "Regular", "None"): (
[
0x02
],
@@ -985,7 +985,7 @@ OWTileGroups = {
0x42
]
),
("West Mountain", "Regular"): (
("West Mountain", "Regular", "None"): (
[
0x03
],
@@ -993,7 +993,7 @@ OWTileGroups = {
0x43
]
),
("East Mountain", "Regular"): (
("East Mountain", "Regular", "None"): (
[
0x05
],
@@ -1001,23 +1001,31 @@ OWTileGroups = {
0x45
]
),
("East Mountain", "Entrance"): (
("East Mountain", "Entrance", "None"): (
[
0x07,
0x07
],
[
0x47
]
),
("Lake", "Regular"): (
("Lake", "Regular", "Zora"): (
[
0x0f, 0x35, 0x81
0x0f, 0x81
],
[
0x4f, 0x75
0x4f
]
),
("Mountain Entry", "Regular"): (
("Lake", "Regular", "Lake"): (
[
0x35
],
[
0x75
]
),
("Mountain Entry", "Regular", "None"): (
[
0x0a
],
@@ -1025,7 +1033,7 @@ OWTileGroups = {
0x4a
]
),
("Woods Pass", "Regular"): (
("Woods Pass", "Regular", "None"): (
[
0x10
],
@@ -1033,7 +1041,7 @@ OWTileGroups = {
0x50
]
),
("Fortune", "Regular"): (
("Fortune", "Regular", "None"): (
[
0x11
],
@@ -1041,15 +1049,39 @@ OWTileGroups = {
0x51
]
),
("Whirlpools", "Regular"): (
("Whirlpools", "Regular", "Pond"): (
[
0x12, 0x15, 0x33, 0x3f
0x12
],
[
0x52, 0x55, 0x73, 0x7f
0x52
]
),
("Castle", "Entrance"): (
("Whirlpools", "Regular", "Witch"): (
[
0x15
],
[
0x55
]
),
("Whirlpools", "Regular", "CWhirlpool"): (
[
0x33
],
[
0x73
]
),
("Whirlpools", "Regular", "Southeast"): (
[
0x3f
],
[
0x7f
]
),
("Castle", "Entrance", "None"): (
[
0x13, 0x14
],
@@ -1057,7 +1089,7 @@ OWTileGroups = {
0x53, 0x54
]
),
("Castle", "Regular"): (
("Castle", "Regular", "None"): (
[
0x1a, 0x1b
],
@@ -1065,7 +1097,7 @@ OWTileGroups = {
0x5a, 0x5b
]
),
("Witch", "Regular"): (
("Witch", "Regular", "None"): (
[
0x16
],
@@ -1073,7 +1105,7 @@ OWTileGroups = {
0x56
]
),
("Water Approach", "Regular"): (
("Water Approach", "Regular", "None"): (
[
0x17
],
@@ -1081,7 +1113,7 @@ OWTileGroups = {
0x57
]
),
("Village", "Regular"): (
("Village", "Regular", "None"): (
[
0x18
],
@@ -1089,7 +1121,7 @@ OWTileGroups = {
0x58
]
),
("Wooden Bridge", "Regular"): (
("Wooden Bridge", "Regular", "None"): (
[
0x1d
],
@@ -1097,7 +1129,7 @@ OWTileGroups = {
0x5d
]
),
("Eastern", "Regular"): (
("Eastern", "Regular", "None"): (
[
0x1e
],
@@ -1105,7 +1137,7 @@ OWTileGroups = {
0x5e
]
),
("Blacksmith", "Regular"): (
("Blacksmith", "Regular", "None"): (
[
0x22
],
@@ -1113,7 +1145,7 @@ OWTileGroups = {
0x62
]
),
("Dunes", "Regular"): (
("Dunes", "Regular", "None"): (
[
0x25
],
@@ -1121,7 +1153,7 @@ OWTileGroups = {
0x65
]
),
("Game", "Regular"): (
("Game", "Regular", "None"): (
[
0x28, 0x29
],
@@ -1129,7 +1161,7 @@ OWTileGroups = {
0x68, 0x69
]
),
("Grove", "Regular"): (
("Grove", "Regular", "None"): (
[
0x2a
],
@@ -1137,7 +1169,7 @@ OWTileGroups = {
0x6a
]
),
("Central Bonk Rocks", "Regular"): (
("Central Bonk Rocks", "Regular", "None"): (
[
0x2b
],
@@ -1145,7 +1177,7 @@ OWTileGroups = {
0x6b
]
),
# ("Links", "Regular"): (
# ("Links", "Regular", "None"): (
# [
# 0x2c
# ],
@@ -1153,7 +1185,7 @@ OWTileGroups = {
# 0x6c
# ]
# ),
("Tree Line", "Regular"): (
("Tree Line", "Regular", "None"): (
[
0x2e
],
@@ -1161,7 +1193,7 @@ OWTileGroups = {
0x6e
]
),
("Nook", "Regular"): (
("Nook", "Regular", "None"): (
[
0x2f
],
@@ -1169,7 +1201,7 @@ OWTileGroups = {
0x6f
]
),
("Desert", "Regular"): (
("Desert", "Regular", "None"): (
[
0x30, 0x3a
],
@@ -1177,7 +1209,7 @@ OWTileGroups = {
0x70, 0x7a
]
),
("Grove Approach", "Regular"): (
("Grove Approach", "Regular", "None"): (
[
0x32
],
@@ -1185,7 +1217,7 @@ OWTileGroups = {
0x72
]
),
("Hype", "Regular"): (
("Hype", "Regular", "None"): (
[
0x34
],
@@ -1193,7 +1225,7 @@ OWTileGroups = {
0x74
]
),
("Shopping Mall", "Regular"): (
("Shopping Mall", "Regular", "None"): (
[
0x37
],
@@ -1201,7 +1233,7 @@ OWTileGroups = {
0x77
]
),
("Swamp", "Regular"): (
("Swamp", "Regular", "None"): (
[
0x3b
],
@@ -1209,7 +1241,7 @@ OWTileGroups = {
0x7b
]
),
("South Pass", "Regular"): (
("South Pass", "Regular", "None"): (
[
0x3c
],

View File

@@ -187,6 +187,44 @@ def link_overworld(world, player):
trimmed_groups = performSwap(trimmed_groups, crossed_edges)
assert len(crossed_edges) == 0, 'Not all edges were crossed successfully: ' + ', '.join(crossed_edges)
# whirlpool shuffle
logging.getLogger('').debug('Shuffling whirlpools')
if not world.owWhirlpoolShuffle[player]:
for (_, from_whirlpool, from_region), (_, to_whirlpool, to_region) in default_whirlpool_connections:
connect_simple(world, from_whirlpool, to_region, player)
connect_simple(world, to_whirlpool, from_region, player)
else:
whirlpool_candidates = [[],[]]
for (from_owid, from_whirlpool, from_region), (to_owid, to_whirlpool, to_region) in default_whirlpool_connections:
if world.owCrossed[player] != 'none':
whirlpool_candidates[0].append(tuple((from_owid, from_whirlpool, from_region)))
whirlpool_candidates[0].append(tuple((to_owid, to_whirlpool, to_region)))
else:
if world.get_region(from_region, player).type == RegionType.LightWorld:
whirlpool_candidates[0].append(tuple((from_owid, from_whirlpool, from_region)))
else:
whirlpool_candidates[1].append(tuple((from_owid, from_whirlpool, from_region)))
if world.get_region(to_region, player).type == RegionType.LightWorld:
whirlpool_candidates[0].append(tuple((to_owid, to_whirlpool, to_region)))
else:
whirlpool_candidates[1].append(tuple((to_owid, to_whirlpool, to_region)))
# shuffle happens here
world.owwhirlpools[player] = [None] * 8
whirlpool_map = [ 0x35, 0x0f, 0x15, 0x33, 0x12, 0x3f, 0x55, 0x7f ]
for whirlpools in whirlpool_candidates:
random.shuffle(whirlpools)
while len(whirlpools):
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)
# layout shuffle
logging.getLogger('').debug('Shuffling overworld layout')
connected_edges = []
@@ -387,22 +425,33 @@ def connect_two_way(world, edgename1, edgename2, player, connected_edges=None):
def shuffle_tiles(world, groups, result_list, player):
swapped_edges = list()
valid_whirlpool_parity = False
# tile shuffle happens here
removed = list()
for group in groups.keys():
if random.randint(0, 1):
removed.append(group)
# save shuffled tiles to list
for group in groups.keys():
if group not in removed:
(owids, lw_regions, dw_regions) = groups[group]
(exist_owids, exist_lw_regions, exist_dw_regions) = result_list
exist_owids.extend(owids)
exist_lw_regions.extend(lw_regions)
exist_dw_regions.extend(dw_regions)
result_list = [exist_owids, exist_lw_regions, exist_dw_regions]
while not valid_whirlpool_parity:
# tile shuffle happens here
removed = list()
for group in groups.keys():
# if group[0] in ['Links', 'Central Bonk Rocks', 'Castle']: # TODO: Standard + Inverted
if random.randint(0, 1):
removed.append(group)
# save shuffled tiles to list
new_results = [[],[],[]]
for group in groups.keys():
if group not in removed:
(owids, lw_regions, dw_regions) = groups[group]
(exist_owids, exist_lw_regions, exist_dw_regions) = new_results
exist_owids.extend(owids)
exist_lw_regions.extend(lw_regions)
exist_dw_regions.extend(dw_regions)
# check whirlpool parity
valid_whirlpool_parity = world.owCrossed[player] != 'none' or len(set(new_results[0]) & set({0x0f, 0x12, 0x15, 0x33, 0x35, 0x3f, 0x55, 0x7f})) % 2 == 0
(exist_owids, exist_lw_regions, exist_dw_regions) = result_list
exist_owids.extend(new_results[0])
exist_lw_regions.extend(new_results[1])
exist_dw_regions.extend(new_results[2])
# replace LW edges with DW
ignore_list = list() #TODO: Remove ignore_list when special OW areas are included in pool
@@ -426,36 +475,62 @@ def shuffle_tiles(world, groups, result_list, player):
def reorganize_tile_groups(world, player):
groups = {}
for (name, groupType) in OWTileGroups.keys():
for (name, groupType, whirlpoolGroup) in OWTileGroups.keys():
if world.mode[player] != 'standard' or name not in ['Castle', 'Links', 'Central Bonk Rocks'] \
or (world.mode[player] == 'standard' and world.shuffle[player] in ['lite', 'lean', 'crossed', 'insanity'] and name == 'Castle' and groupType == 'Entrance'):
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'simple', 'restricted']:
groups[(name,)] = ([], [], [])
if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none':
groups[(name, whirlpoolGroup)] = ([], [], [])
else:
groups[(name,)] = ([], [], [])
else:
groups[(name, groupType)] = ([], [], [])
if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none':
groups[(name, groupType, whirlpoolGroup)] = ([], [], [])
else:
groups[(name, groupType)] = ([], [], [])
for (name, groupType) in OWTileGroups.keys():
for (name, groupType, whirlpoolGroup) in OWTileGroups.keys():
if world.mode[player] != 'standard' or name not in ['Castle', 'Links', 'Central Bonk Rocks'] \
or (world.mode[player] == 'standard' and world.shuffle[player] in ['lite', 'lean', 'crossed', 'insanity'] and name == 'Castle' and groupType == 'Entrance'):
(lw_owids, dw_owids) = OWTileGroups[(name, groupType,)]
(lw_owids, dw_owids) = OWTileGroups[(name, groupType, whirlpoolGroup)]
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'simple', 'restricted']:
(exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name,)]
exist_owids.extend(lw_owids)
exist_owids.extend(dw_owids)
for owid in lw_owids:
exist_lw_regions.extend(OWTileRegions.inverse[owid])
for owid in dw_owids:
exist_dw_regions.extend(OWTileRegions.inverse[owid])
groups[(name,)] = (exist_owids, exist_lw_regions, exist_dw_regions)
if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none':
(exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, whirlpoolGroup)]
exist_owids.extend(lw_owids)
exist_owids.extend(dw_owids)
for owid in lw_owids:
exist_lw_regions.extend(OWTileRegions.inverse[owid])
for owid in dw_owids:
exist_dw_regions.extend(OWTileRegions.inverse[owid])
groups[(name, whirlpoolGroup)] = (exist_owids, exist_lw_regions, exist_dw_regions)
else:
(exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name,)]
exist_owids.extend(lw_owids)
exist_owids.extend(dw_owids)
for owid in lw_owids:
exist_lw_regions.extend(OWTileRegions.inverse[owid])
for owid in dw_owids:
exist_dw_regions.extend(OWTileRegions.inverse[owid])
groups[(name,)] = (exist_owids, exist_lw_regions, exist_dw_regions)
else:
(exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, groupType)]
exist_owids.extend(lw_owids)
exist_owids.extend(dw_owids)
for owid in lw_owids:
exist_lw_regions.extend(OWTileRegions.inverse[owid])
for owid in dw_owids:
exist_dw_regions.extend(OWTileRegions.inverse[owid])
groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions)
if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none':
(exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, groupType, whirlpoolGroup)]
exist_owids.extend(lw_owids)
exist_owids.extend(dw_owids)
for owid in lw_owids:
exist_lw_regions.extend(OWTileRegions.inverse[owid])
for owid in dw_owids:
exist_dw_regions.extend(OWTileRegions.inverse[owid])
groups[(name, groupType, whirlpoolGroup)] = (exist_owids, exist_lw_regions, exist_dw_regions)
else:
(exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, groupType)]
exist_owids.extend(lw_owids)
exist_owids.extend(dw_owids)
for owid in lw_owids:
exist_lw_regions.extend(OWTileRegions.inverse[owid])
for owid in dw_owids:
exist_dw_regions.extend(OWTileRegions.inverse[owid])
groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions)
return groups
def remove_reserved(world, groupedlist, connected_edges, player):
@@ -733,17 +808,7 @@ temporary_mandatory_connections = [
]
# these are connections that cannot be shuffled and always exist. They link together separate parts of the world we need to divide into regions
mandatory_connections = [# Whirlpool Connections
('C Whirlpool', 'River Bend Water'),
('River Bend Whirlpool', 'C Whirlpool Water'),
('Lake Hylia Whirlpool', 'Zora Waterfall Water'),
('Zora Whirlpool', 'Lake Hylia Water'),
('Kakariko Pond Whirlpool', 'Octoballoon Water'),
('Octoballoon Whirlpool', 'Kakariko Pond Area'),
('Qirn Jump Whirlpool', 'Bomber Corner Water'),
('Bomber Corner Whirlpool', 'Qirn Jump Water'),
# Intra-tile OW Connections
mandatory_connections = [# Intra-tile OW Connections
('Lost Woods Bush (West)', 'Lost Woods East Area'), #pearl
('Lost Woods Bush (East)', 'Lost Woods West Area'), #pearl
('West Death Mountain Drop', 'West Death Mountain (Bottom)'),
@@ -967,6 +1032,13 @@ mandatory_connections = [# Whirlpool Connections
('Dark Tree Line WC Cliff Water Drop', 'Dark Tree Line Water') #fake flipper
]
default_whirlpool_connections = [
((0x33, 'C Whirlpool', 'C Whirlpool Water'), (0x15, 'River Bend Whirlpool', 'River Bend Water')),
((0x35, 'Lake Hylia Whirlpool', 'Lake Hylia Water'), (0x0f, 'Zora Whirlpool', 'Zora Waterfall Water')),
((0x12, 'Kakariko Pond Whirlpool', 'Kakariko Pond Area'), (0x3f, 'Octoballoon Whirlpool', 'Octoballoon Water')),
((0x55, 'Qirn Jump Whirlpool', 'Qirn Jump Water'), (0x7f, 'Bomber Corner Whirlpool', 'Bomber Corner Water'))
]
default_flute_connections = [
0x0b, 0x16, 0x18, 0x2c, 0x2f, 0x38, 0x3b, 0x3f
]

7
Rom.py
View File

@@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = 'c6c2a2d5d89a3c84871f58806bbb3acf'
RANDOMIZERBASEHASH = 'e9dea70e0a0b15bfa0ff7ecd63228a0c'
class JsonRom(object):
@@ -644,6 +644,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_byte(snes_to_pc(0x0AB793 + o), data[11] & 0xff) # Y low byte
rom.write_byte(snes_to_pc(0x0AB79B + o), data[11] // 0x100) # Y high byte
# patch whirlpools
if world.owWhirlpoolShuffle[player]:
owFlags |= 0x01
write_int16s(rom, snes_to_pc(0x02EA5C), world.owwhirlpools[player])
# patch overworld edges
inverted_buffer = [0] * 0x82
owMode = 0

Binary file not shown.

View File

@@ -15,6 +15,9 @@
overworld_swap:
on: 1
off: 1
whirlpool_shuffle:
on: 1
off: 1
flute_shuffle:
vanilla: 0
balanced: 1

View File

@@ -133,6 +133,10 @@
"action": "store_true",
"type": "bool"
},
"ow_whirlpool": {
"action": "store_true",
"type": "bool"
},
"ow_fluteshuffle": {
"choices": [
"vanilla",

View File

@@ -221,6 +221,9 @@
"ow_mixed": [
"Overworld tiles are randomly chosen to become part of the opposite world."
],
"ow_whirlpool": [
"Whirlpools will be shuffled and paired together."
],
"ow_fluteshuffle": [
"This randomizes the flute spot destinations.",
"Vanilla: All flute spots remain unchanged.",

View File

@@ -123,13 +123,18 @@
"randomizer.overworld.crossed.grouped": "Grouped",
"randomizer.overworld.crossed.limited": "Limited",
"randomizer.overworld.crossed.chaos": "Chaos",
"randomizer.overworld.keepsimilar": "Keep Similar Edges Together",
"randomizer.overworld.mixed": "Tile Swap (Mixed)",
"randomizer.overworld.whirlpool": "Whirlpool Shuffle",
"randomizer.overworld.overworldflute": "Flute Shuffle",
"randomizer.overworld.overworldflute.vanilla": "Vanilla",
"randomizer.overworld.overworldflute.balanced": "Balanced",
"randomizer.overworld.overworldflute.random": "Random",
"randomizer.entrance.openpyramid": "Pre-open Pyramid Hole",
"randomizer.entrance.shuffleganon": "Include Ganon's Tower and Pyramid Hole in shuffle pool",

View File

@@ -24,6 +24,10 @@
"type": "checkbox",
"default": true
},
"whirlpool": {
"type": "checkbox",
"default": false
},
"overworldflute": {
"type": "selectbox",
"default": "vanilla",

View File

@@ -79,6 +79,7 @@ SETTINGSTOPROCESS = {
"crossed": "ow_crossed",
"keepsimilar": "ow_keepsimilar",
"mixed": "ow_mixed",
"whirlpool": "ow_whirlpool",
"overworldflute": "ow_fluteshuffle"
},
"entrance": {

View File

@@ -33,7 +33,7 @@ def overworld_page(parent):
packAttrs = {"side":LEFT, "pady":(18,0)}
elif key == "overworldflute":
packAttrs["pady"] = (20,0)
elif key == "mixed":
elif key in ["whirlpool", "mixed"]:
packAttrs = {"anchor":W, "padx":(79,0)}
self.widgets[key].pack(packAttrs)