Moved Crossed OW Shuffle to its own setting, Renamed Tile Swap to Mixed
This commit is contained in:
@@ -19,13 +19,14 @@ from RoomData import Room
|
||||
|
||||
class World(object):
|
||||
|
||||
def __init__(self, players, owShuffle, owSwap, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments,
|
||||
def __init__(self, players, owShuffle, owCrossed, owMixed, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments,
|
||||
timer, progressive, goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints):
|
||||
self.players = players
|
||||
self.teams = 1
|
||||
self.owShuffle = owShuffle.copy()
|
||||
self.owSwap = owSwap.copy()
|
||||
self.owCrossed = owCrossed.copy()
|
||||
self.owKeepSimilar = {}
|
||||
self.owMixed = owMixed.copy()
|
||||
self.owFluteShuffle = {}
|
||||
self.shuffle = shuffle.copy()
|
||||
self.doorShuffle = doorShuffle.copy()
|
||||
@@ -2308,8 +2309,9 @@ class Spoiler(object):
|
||||
'weapons': self.world.swords,
|
||||
'goal': self.world.goal,
|
||||
'ow_shuffle': self.world.owShuffle,
|
||||
'ow_swap': self.world.owSwap,
|
||||
'ow_crossed': self.world.owCrossed,
|
||||
'ow_keepsimilar': self.world.owKeepSimilar,
|
||||
'ow_mixed': self.world.owMixed,
|
||||
'ow_fluteshuffle': self.world.owFluteShuffle,
|
||||
'shuffle': self.world.shuffle,
|
||||
'door_shuffle': self.world.doorShuffle,
|
||||
@@ -2390,9 +2392,10 @@ class Spoiler(object):
|
||||
outfile.write('Difficulty:'.ljust(line_width) + '%s\n' % self.metadata['item_pool'][player])
|
||||
outfile.write('Item Functionality:'.ljust(line_width) + '%s\n' % self.metadata['item_functionality'][player])
|
||||
outfile.write('Overworld Layout Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_shuffle'][player])
|
||||
outfile.write('Overworld Tile Swap:'.ljust(line_width) + '%s\n' % self.metadata['ow_swap'][player])
|
||||
if self.metadata['ow_shuffle'][player] != 'vanilla':
|
||||
outfile.write('Crossed OW:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_crossed'][player] else 'No'))
|
||||
outfile.write('Keep Similar OW Edges Together:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_keepsimilar'][player] else 'No'))
|
||||
outfile.write('Mixed OW:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_mixed'][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('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player])
|
||||
@@ -2555,8 +2558,7 @@ class Pot(object):
|
||||
|
||||
# byte 0: DDOO OEEE (DR, OR, ER)
|
||||
dr_mode = {"basic": 1, "crossed": 2, "vanilla": 0}
|
||||
or_mode = {"vanilla": 0, "parallel": 1, "full": 2}
|
||||
orswap_mode = {"vanilla": 0, "mixed": 1, "crossed": 1}
|
||||
or_mode = {"vanilla": 0, "parallel": 1, "full": 1}
|
||||
er_mode = {"vanilla": 0, "simple": 1, "restricted": 3, "full": 3, "crossed": 4, "insanity": 5, "dungeonsfull": 7, "dungeonssimple": 7}
|
||||
|
||||
# byte 1: LLLW WSSR (logic, mode, sword, retro)
|
||||
@@ -2592,7 +2594,7 @@ class Settings(object):
|
||||
@staticmethod
|
||||
def make_code(w, p):
|
||||
code = bytes([
|
||||
(dr_mode[w.doorShuffle[p]] << 6) | (or_mode[w.owShuffle[p]] << 4) | (orswap_mode[w.owSwap[p]] << 3) | er_mode[w.shuffle[p]],
|
||||
(dr_mode[w.doorShuffle[p]] << 6) | (or_mode[w.owShuffle[p]] << 5) | (0x10 if w.owCrossed[p] else 0) | (0x08 if w.owMixed[p] else 0) | er_mode[w.shuffle[p]],
|
||||
|
||||
(logic_mode[w.logic[p]] << 5) | (world_mode[w.mode[p]] << 3)
|
||||
| (sword_mode[w.swords[p]] << 1) | (1 if w.retro[p] else 0),
|
||||
|
||||
5
CLI.py
5
CLI.py
@@ -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_swap', 'ow_keepsimilar', 'ow_fluteshuffle',
|
||||
'ow_shuffle', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_fluteshuffle',
|
||||
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid',
|
||||
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
|
||||
'bombbag',
|
||||
@@ -146,8 +146,9 @@ def parse_settings():
|
||||
"openpyramid": False,
|
||||
"shuffleganon": True,
|
||||
"ow_shuffle": "vanilla",
|
||||
"ow_swap": "vanilla",
|
||||
"ow_crossed": False,
|
||||
"ow_keepsimilar": False,
|
||||
"ow_mixed": False,
|
||||
"ow_fluteshuffle": "vanilla",
|
||||
"shuffle": "vanilla",
|
||||
"shufflelinks": False,
|
||||
|
||||
@@ -214,7 +214,7 @@ def vanilla_key_logic(world, player):
|
||||
analyze_dungeon(key_layout, world, player)
|
||||
world.key_logic[player][builder.name] = key_layout.key_logic
|
||||
log_key_logic(builder.name, key_layout.key_logic)
|
||||
if world.shuffle[player] == 'vanilla' and world.owShuffle[player] == 'vanilla' and world.owSwap[player] == 'vanilla' and world.accessibility[player] == 'items' and not world.retro[player] and not world.keydropshuffle[player]:
|
||||
if world.shuffle[player] == 'vanilla' and world.owShuffle[player] == 'vanilla' and not world.owCrossed[player] and world.owMixed[player] == 'vanilla' and world.accessibility[player] == 'items' and not world.retro[player] and not world.keydropshuffle[player]:
|
||||
validate_vanilla_key_logic(world, player)
|
||||
|
||||
|
||||
|
||||
@@ -50,18 +50,18 @@ def link_entrances(world, player):
|
||||
|
||||
# inverted entrance mods
|
||||
for owid in swapped_connections.keys():
|
||||
if invFlag != (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if invFlag != (owid in world.owswaps[player][0] and world.owMixed[player]):
|
||||
for (entrancename, exitname) in swapped_connections[owid]:
|
||||
try:
|
||||
connect_two_way(world, entrancename, exitname, player)
|
||||
except RuntimeError:
|
||||
connect_entrance(world, entrancename, exitname, player)
|
||||
|
||||
if invFlag != (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed') and \
|
||||
invFlag == (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if invFlag != (0x03 in world.owswaps[player][0] and world.owMixed[player]) and \
|
||||
invFlag == (0x0a in world.owswaps[player][0] and world.owMixed[player]):
|
||||
connect_entrance(world, 'Death Mountain Return Cave (West)', 'Dark Death Mountain Healer Fairy', player)
|
||||
elif invFlag != (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed') and \
|
||||
invFlag == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
elif invFlag != (0x0a in world.owswaps[player][0] and world.owMixed[player]) and \
|
||||
invFlag == (0x03 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
connect_two_way(world, 'Bumper Cave (Top)', 'Death Mountain Return Cave Exit (West)', player)
|
||||
|
||||
# dungeon entrance shuffle
|
||||
@@ -225,7 +225,7 @@ def link_entrances(world, player):
|
||||
random.shuffle(remaining_entrances)
|
||||
old_man_entrance = remaining_entrances.pop()
|
||||
|
||||
connect_two_way(world, old_man_entrance if invFlag == (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed') else 'Bumper Cave (Bottom)', 'Old Man Cave Exit (West)', player)
|
||||
connect_two_way(world, old_man_entrance if invFlag == (0x0a in world.owswaps[player][0] and world.owMixed[player]) else 'Bumper Cave (Bottom)', 'Old Man Cave Exit (West)', player)
|
||||
connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player)
|
||||
if invFlag and old_man_exit == 'Spike Cave':
|
||||
bomb_shop_doors.remove('Spike Cave')
|
||||
@@ -791,8 +791,8 @@ def link_entrances(world, player):
|
||||
|
||||
if not world.shuffle_ganon:
|
||||
connect_two_way(world, 'Ganons Tower' if not invFlag else 'Agahnims Tower', 'Ganons Tower Exit', player)
|
||||
connect_two_way(world, 'Pyramid Entrance' if invFlag == (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed') else 'Inverted Pyramid Entrance', 'Pyramid Exit', player)
|
||||
connect_entrance(world, 'Pyramid Hole' if invFlag == (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed') else 'Inverted Pyramid Hole', 'Pyramid', player)
|
||||
connect_two_way(world, 'Pyramid Entrance' if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]) else 'Inverted Pyramid Entrance', 'Pyramid Exit', player)
|
||||
connect_entrance(world, 'Pyramid Hole' if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]) else 'Inverted Pyramid Hole', 'Pyramid', player)
|
||||
else:
|
||||
caves.extend(['Ganons Tower Exit', 'Pyramid Exit'])
|
||||
hole_targets.append('Pyramid')
|
||||
@@ -804,7 +804,7 @@ def link_entrances(world, player):
|
||||
exit_pool.extend(['Agahnims Tower'])
|
||||
doors.extend(['Agahnims Tower'])
|
||||
|
||||
if invFlag == (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]):
|
||||
exit_pool.extend(['Pyramid Entrance'])
|
||||
hole_entrances.append('Pyramid Hole')
|
||||
entrances_must_exits.append('Pyramid Entrance')
|
||||
@@ -943,7 +943,7 @@ def link_entrances(world, player):
|
||||
world.powder_patch_required[player] = True
|
||||
|
||||
# check for ganon location
|
||||
if world.get_entrance('Pyramid Hole' if invFlag == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed') else 'Inverted Pyramid Hole', player).connected_region.name != 'Pyramid':
|
||||
if world.get_entrance('Pyramid Hole' if invFlag == (0x03 in world.owswaps[player][0] and world.owMixed[player]) else 'Inverted Pyramid Hole', player).connected_region.name != 'Pyramid':
|
||||
world.ganon_at_pyramid[player] = False
|
||||
|
||||
# check for Ganon's Tower location
|
||||
@@ -1030,7 +1030,7 @@ def scramble_holes(world, player):
|
||||
('Lumberjack Tree Exit', 'Lumberjack Tree (top)')]
|
||||
|
||||
if not world.shuffle_ganon:
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
|
||||
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
|
||||
else:
|
||||
@@ -1053,7 +1053,7 @@ def scramble_holes(world, player):
|
||||
if world.shuffle_ganon:
|
||||
random.shuffle(hole_targets)
|
||||
exit, target = hole_targets.pop()
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
|
||||
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
|
||||
else:
|
||||
|
||||
@@ -258,7 +258,7 @@ def generate_itempool(world, player):
|
||||
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.bombbag[player], world.customitemarray)
|
||||
world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999)
|
||||
else:
|
||||
(pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.owShuffle[player], world.owSwap[player], world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.bombbag[player], world.doorShuffle[player], world.logic[player])
|
||||
(pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.retro[player], world.bombbag[player], world.doorShuffle[player], world.logic[player])
|
||||
|
||||
if player in world.pool_adjustment.keys():
|
||||
amt = world.pool_adjustment[player]
|
||||
@@ -727,7 +727,7 @@ rupee_chart = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)'
|
||||
'Rupees (100)': 100, 'Rupees (300)': 300}
|
||||
|
||||
|
||||
def get_pool_core(progressive, owShuffle, owSwap, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic):
|
||||
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic):
|
||||
pool = []
|
||||
placed_items = {}
|
||||
precollected_items = []
|
||||
@@ -990,9 +990,8 @@ def test():
|
||||
for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']:
|
||||
for retro in [True, False]:
|
||||
for door_shuffle in ['basic', 'crossed', 'vanilla']:
|
||||
for owShuffle in ['full', 'parallel', 'vanilla']:
|
||||
for owSwap in ['vanilla', 'mixed', 'crossed']:
|
||||
out = get_pool_core(progressive, owShuffle, owSwap, shuffle, difficulty, 30, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic)
|
||||
for bombbag in [True, False]:
|
||||
out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic)
|
||||
count = len(out[0]) + len(out[1])
|
||||
|
||||
correct_count = total_items_to_place
|
||||
|
||||
6
Main.py
6
Main.py
@@ -61,7 +61,7 @@ def main(args, seed=None, fish=None):
|
||||
for player, code in args.code.items():
|
||||
if code:
|
||||
Settings.adjust_args_from_code(code, player, args)
|
||||
world = World(args.multi, args.ow_shuffle, args.ow_swap, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords,
|
||||
world = World(args.multi, args.ow_shuffle, args.ow_crossed, args.ow_mixed, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords,
|
||||
args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm,
|
||||
args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints)
|
||||
logger = logging.getLogger('')
|
||||
@@ -263,7 +263,7 @@ def main(args, seed=None, fish=None):
|
||||
customize_shops(world, player)
|
||||
balance_money_progression(world)
|
||||
|
||||
if world.owShuffle[1] != 'vanilla' or world.owSwap[1] != 'vanilla' or str(world.seed).startswith('M'):
|
||||
if world.owShuffle[1] != 'vanilla' or world.owCrossed[1] or world.owMixed[1] or str(world.seed).startswith('M'):
|
||||
outfilebase = f'OR_{args.outputname if args.outputname else world.seed}'
|
||||
else:
|
||||
outfilebase = f'DR_{args.outputname if args.outputname else world.seed}'
|
||||
@@ -369,7 +369,7 @@ def main(args, seed=None, fish=None):
|
||||
|
||||
def copy_world(world):
|
||||
# ToDo: Not good yet
|
||||
ret = World(world.players, world.owShuffle, world.owSwap, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords,
|
||||
ret = World(world.players, world.owShuffle, world.owCrossed, world.owMixed, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords,
|
||||
world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm,
|
||||
world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints)
|
||||
ret.teams = world.teams
|
||||
|
||||
@@ -133,9 +133,9 @@ def roll_settings(weights):
|
||||
|
||||
overworld_shuffle = get_choice('overworld_shuffle')
|
||||
ret.ow_shuffle = overworld_shuffle if overworld_shuffle != 'none' else 'vanilla'
|
||||
overworld_swap = get_choice('overworld_swap')
|
||||
ret.ow_swap = overworld_swap if overworld_swap != 'none' else 'vanilla'
|
||||
ret.ow_crossed = get_choice('overworld_crossed')
|
||||
ret.ow_keepsimilar = get_choice('overworld_keepsimilar')
|
||||
ret.ow_mixed = get_choice('overworld_mixed')
|
||||
overworld_flute = get_choice('flute_shuffle')
|
||||
ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla'
|
||||
entrance_shuffle = get_choice('entrance_shuffle')
|
||||
|
||||
@@ -11,9 +11,25 @@ def link_overworld(world, player):
|
||||
for exitname, destname in temporary_mandatory_connections:
|
||||
connect_two_way(world, exitname, destname, player)
|
||||
|
||||
# tile shuffle
|
||||
trimmed_groups = copy.deepcopy(OWEdgeGroups)
|
||||
if world.owSwap[player] != 'vanilla':
|
||||
|
||||
# adjust Frog/Dig Game swap manually due to NP/P relationship with LW
|
||||
if world.owShuffle[player] == 'parallel' and not world.owKeepSimilar[player]:
|
||||
for group in trimmed_groups.keys():
|
||||
(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))
|
||||
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))
|
||||
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)
|
||||
|
||||
# tile shuffle
|
||||
if world.owMixed[player]:
|
||||
tile_groups = {}
|
||||
for (name, groupType) in OWTileGroups.keys():
|
||||
if world.mode[player] != 'standard' or name not in ['Castle', 'Links', 'Central Bonk Rocks']:
|
||||
@@ -44,7 +60,7 @@ def link_overworld(world, player):
|
||||
exist_dw_regions.extend(OWTileRegions.inverse[owid])
|
||||
tile_groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions)
|
||||
|
||||
#tile shuffle happens here, the groups that remain in the list are the tiles that get swapped
|
||||
# tile shuffle happens here, the groups that remain in the list are the tiles that get swapped
|
||||
removed = list()
|
||||
for group in tile_groups.keys():
|
||||
if random.randint(0, 1):
|
||||
@@ -52,7 +68,7 @@ def link_overworld(world, player):
|
||||
for group in removed:
|
||||
tile_groups.pop(group, None)
|
||||
|
||||
#save shuffled tiles to world object
|
||||
# save shuffled tiles to world object
|
||||
for group in tile_groups.keys():
|
||||
(owids, lw_regions, dw_regions) = tile_groups[group]
|
||||
(exist_owids, exist_lw_regions, exist_dw_regions) = world.owswaps[player]
|
||||
@@ -61,7 +77,7 @@ def link_overworld(world, player):
|
||||
exist_dw_regions.extend(dw_regions)
|
||||
world.owswaps[player] = [exist_owids, exist_lw_regions, exist_dw_regions]
|
||||
|
||||
#replace LW edges with DW
|
||||
# replace LW edges with DW
|
||||
ignore_list = list() #TODO: Remove ignore_list when special OW areas are included in pool
|
||||
for edgeset in temporary_mandatory_connections:
|
||||
for edge in edgeset:
|
||||
@@ -108,7 +124,7 @@ def link_overworld(world, player):
|
||||
#TODO: Figure out a way to handle index changes on the fly when removing items
|
||||
logging.getLogger('').warning('OW Tile Swap encountered minor IndexError... retrying')
|
||||
|
||||
if 0x28 in world.owswaps[player][0]: #handle Frog/Dig Game swap manually due to NP/P relationship with LW
|
||||
if world.owShuffle[player] != 'parallel' and 0x28 in world.owswaps[player][0]: # handle Frog/Dig Game swap manually due to NP/P relationship with LW
|
||||
trimmed_groups[(OpenStd.Open, WorldType.Dark, PolSlot.EastWest, Terrain.Land, IsParallel.Yes, 1)][0].append(['Maze Race ES'])
|
||||
trimmed_groups[(OpenStd.Open, WorldType.Dark, PolSlot.EastWest, Terrain.Land, IsParallel.Yes, 1)][1].append(['Kakariko Suburb WS'])
|
||||
trimmed_groups[(OpenStd.Open, WorldType.Light, PolSlot.EastWest, Terrain.Land, IsParallel.Yes, 1)][0].remove(['Maze Race ES'])
|
||||
@@ -139,7 +155,7 @@ def link_overworld(world, player):
|
||||
|
||||
# make new connections
|
||||
for owid in ow_connections.keys():
|
||||
if (world.mode[player] == 'inverted') == (owid in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (owid in world.owswaps[player][0] and world.owMixed[player]):
|
||||
for (exitname, regionname) in ow_connections[owid][0]:
|
||||
connect_simple(world, exitname, regionname, player)
|
||||
else:
|
||||
@@ -151,57 +167,90 @@ def link_overworld(world, player):
|
||||
connect_custom(world, connected_edges, player)
|
||||
|
||||
# layout shuffle
|
||||
if world.owShuffle[player] == 'vanilla':
|
||||
if world.owShuffle[player] == 'vanilla' and not world.owCrossed[player]:
|
||||
# vanilla transitions
|
||||
groups = list(trimmed_groups.values())
|
||||
for (forward_edge_sets, back_edge_sets) in groups:
|
||||
assert len(forward_edge_sets) == len(back_edge_sets)
|
||||
for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets):
|
||||
assert len(forward_set) == len(back_set)
|
||||
for (forward_edge, back_edge) in zip(forward_set, back_set):
|
||||
connect_two_way(world, forward_edge, back_edge, player)
|
||||
connected_edges.append(forward_edge)
|
||||
connected_edges.append(back_edge)
|
||||
connect_two_way(world, forward_edge, back_edge, player, connected_edges)
|
||||
|
||||
assert len(connected_edges) == len(default_connections) * 2, connected_edges
|
||||
else:
|
||||
if world.owKeepSimilar[player] and world.owShuffle[player] == 'parallel':
|
||||
for exitname, destname in parallelsimilar_connections:
|
||||
connect_two_way(world, exitname, destname, player)
|
||||
connected_edges.append(exitname)
|
||||
connected_edges.append(destname)
|
||||
connect_two_way(world, exitname, destname, player, connected_edges)
|
||||
|
||||
if world.owShuffle[player] == 'vanilla' and world.owCrossed[player]:
|
||||
if world.mode[player] == 'standard':
|
||||
# connect vanilla std
|
||||
for group in trimmed_groups.keys():
|
||||
(std, _, _, _, _, _) = group
|
||||
if std == OpenStd.Standard:
|
||||
(forward_set, back_set) = trimmed_groups[group]
|
||||
for (forward_edges, back_edges) in zip(forward_set, back_set):
|
||||
for (forward_edge, back_edge) in zip(forward_edges, back_edges):
|
||||
connect_two_way(world, forward_edge, back_edge, player, connected_edges)
|
||||
|
||||
# connect non-parallel edges
|
||||
for group in trimmed_groups.keys():
|
||||
(_, _, _, _, parallel, _) = group
|
||||
if parallel == IsParallel.No:
|
||||
(forward_set, back_set) = trimmed_groups[group]
|
||||
for (forward_edges, back_edges) in zip(forward_set, back_set):
|
||||
for (forward_edge, back_edge) in zip(forward_edges, back_edges):
|
||||
if forward_edge not in connected_edges and back_edge not in connected_edges:
|
||||
connect_two_way(world, forward_edge, back_edge, player, connected_edges)
|
||||
|
||||
#TODO: Remove, just for testing
|
||||
for exitname, destname in test_connections:
|
||||
connect_two_way(world, exitname, destname, player)
|
||||
connected_edges.append(exitname)
|
||||
connected_edges.append(destname)
|
||||
connect_two_way(world, exitname, destname, player, connected_edges)
|
||||
|
||||
trimmed_groups = remove_reserved(world, trimmed_groups, connected_edges, player)
|
||||
|
||||
groups = reorganize_groups(world, trimmed_groups, player)
|
||||
|
||||
#all shuffling occurs here
|
||||
# all layout shuffling occurs here
|
||||
if world.owShuffle[player] != 'vanilla':
|
||||
# layout shuffle
|
||||
random.shuffle(groups)
|
||||
for (forward_edge_sets, back_edge_sets) in groups:
|
||||
assert len(forward_edge_sets) == len(back_edge_sets)
|
||||
random.shuffle(forward_edge_sets)
|
||||
random.shuffle(back_edge_sets)
|
||||
for (forward_set, back_set) in zip(forward_edge_sets, 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]
|
||||
f += 1
|
||||
while back_set[0] in connected_edges:
|
||||
b += 1
|
||||
if b < len(back_edge_sets):
|
||||
back_set = back_edge_sets[b]
|
||||
b += 1
|
||||
assert len(forward_set) == len(back_set)
|
||||
for (forward_edge, back_edge) in zip(forward_set, back_set):
|
||||
connect_two_way(world, forward_edge, back_edge, player)
|
||||
connected_edges.append(forward_edge)
|
||||
connected_edges.append(back_edge)
|
||||
if world.owShuffle[player] == 'parallel':
|
||||
if forward_edge in parallel_links.keys() or forward_edge in parallel_links.inverse.keys():
|
||||
try:
|
||||
parallel_forward_edge = parallel_links[forward_edge] if forward_edge in parallel_links.keys() else parallel_links.inverse[forward_edge][0]
|
||||
parallel_back_edge = parallel_links[back_edge] if back_edge in parallel_links.keys() else parallel_links.inverse[back_edge][0]
|
||||
connect_two_way(world, parallel_forward_edge, parallel_back_edge, player)
|
||||
connected_edges.append(parallel_forward_edge)
|
||||
connected_edges.append(parallel_back_edge)
|
||||
except KeyError:
|
||||
# TODO: Figure out why non-parallel edges are getting into parallel groups
|
||||
raise KeyError('No parallel edge for edge %d' % back_edge)
|
||||
connect_two_way(world, forward_edge, back_edge, player, connected_edges)
|
||||
else:
|
||||
# vanilla/crossed shuffle
|
||||
for (forward_edge_sets, back_edge_sets) in groups:
|
||||
assert len(forward_edge_sets) == len(back_edge_sets)
|
||||
for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets):
|
||||
assert len(forward_set) == len(back_set)
|
||||
swapped = random.randint(0, 1)
|
||||
for (forward_edge, back_edge) in zip(forward_set, back_set):
|
||||
if forward_edge not in connected_edges and back_edge not in connected_edges:
|
||||
if swapped:
|
||||
forward_edge = parallel_links[forward_edge] if forward_edge in parallel_links else parallel_links.inverse[forward_edge][0]
|
||||
connect_two_way(world, forward_edge, back_edge, player, connected_edges)
|
||||
|
||||
assert len(connected_edges) == len(default_connections) * 2, connected_edges
|
||||
|
||||
@@ -210,7 +259,7 @@ def link_overworld(world, player):
|
||||
for o in range(0, len(flute_destinations)):
|
||||
owslot = flute_destinations[o]
|
||||
regions = flute_data[owslot][0]
|
||||
if (world.mode[player] == 'inverted') == (flute_data[owslot][1] in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (flute_data[owslot][1] in world.owswaps[player][0] and world.owMixed[player]):
|
||||
connect_simple(world, 'Flute Spot ' + str(o + 1), regions[0], player)
|
||||
else:
|
||||
connect_simple(world, 'Flute Spot ' + str(o + 1), regions[1], player)
|
||||
@@ -232,7 +281,7 @@ def link_overworld(world, player):
|
||||
new_ignored.add(exit.connected_region.name)
|
||||
getIgnored(exit.connected_region.name, base_owid, OWTileRegions[exit.connected_region.name])
|
||||
|
||||
if (world.mode[player] == 'inverted') == (flute_data[owid][1] in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (flute_data[owid][1] in world.owswaps[player][0] and world.owMixed[player]):
|
||||
new_region = flute_data[owid][0][0]
|
||||
else:
|
||||
new_region = flute_data[owid][0][1]
|
||||
@@ -269,18 +318,15 @@ def link_overworld(world, player):
|
||||
world.owflutespots[player] = new_spots
|
||||
connect_flutes(new_spots)
|
||||
|
||||
|
||||
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]:
|
||||
connect_two_way(world, edgename1, edgename2, player)
|
||||
connected_edges.append(edgename1)
|
||||
connected_edges.append(edgename2)
|
||||
connect_two_way(world, edgename1, edgename2, player, connected_edges)
|
||||
|
||||
def connect_simple(world, exitname, regionname, player):
|
||||
world.get_entrance(exitname, player).connect(world.get_region(regionname, player))
|
||||
|
||||
def connect_two_way(world, edgename1, edgename2, player):
|
||||
def connect_two_way(world, edgename1, edgename2, player, connected_edges=None):
|
||||
edge1 = world.get_entrance(edgename1, player)
|
||||
edge2 = world.get_entrance(edgename2, player)
|
||||
|
||||
@@ -302,23 +348,41 @@ def connect_two_way(world, edgename1, edgename2, player):
|
||||
x.dest = y
|
||||
y.dest = x
|
||||
|
||||
if world.owShuffle[player] != 'vanilla' or world.owSwap[player] != 'vanilla':
|
||||
if world.owShuffle[player] != 'vanilla' or world.owMixed[player] or world.owCrossed[player]:
|
||||
world.spoiler.set_overworld(edgename2, edgename1, 'both', player)
|
||||
|
||||
if connected_edges is not None:
|
||||
connected_edges.append(edgename1)
|
||||
connected_edges.append(edgename2)
|
||||
|
||||
# connecting parallel connections
|
||||
if world.owShuffle[player] == 'parallel' or (world.owShuffle[player] == 'vanilla' and world.owCrossed[player]):
|
||||
if (edgename1 in parallel_links.keys() or edgename1 in parallel_links.inverse.keys()):
|
||||
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]
|
||||
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:
|
||||
# TODO: Figure out why non-parallel edges are getting into parallel groups
|
||||
raise KeyError('No parallel edge for edge %s' % edgename2)
|
||||
|
||||
def remove_reserved(world, groupedlist, connected_edges, player):
|
||||
new_grouping = {}
|
||||
for group in groupedlist.keys():
|
||||
new_grouping[group] = ([], [])
|
||||
|
||||
for group in groupedlist.keys():
|
||||
(std, region, axis, terrain, parallel, count) = group
|
||||
(_, region, _, _, _, _) = group
|
||||
(forward_edges, back_edges) = groupedlist[group]
|
||||
|
||||
# remove edges already connected (thru plando and other forced connections)
|
||||
for edge in connected_edges:
|
||||
forward_edges = list(list(filter((edge).__ne__, i)) for i in forward_edges)
|
||||
back_edges = list(list(filter((edge).__ne__, i)) for i in back_edges)
|
||||
|
||||
if world.owShuffle[player] == 'parallel' and region == WorldType.Dark:
|
||||
# remove parallel edges from pool, since they get added during shuffle
|
||||
if (not world.owCrossed[player] and world.owShuffle[player] == 'parallel') and region == WorldType.Dark:
|
||||
for edge in parallel_links:
|
||||
forward_edges = list(list(filter((parallel_links[edge]).__ne__, i)) for i in forward_edges)
|
||||
back_edges = list(list(filter((parallel_links[edge]).__ne__, i)) for i in back_edges)
|
||||
@@ -329,8 +393,6 @@ def remove_reserved(world, groupedlist, connected_edges, player):
|
||||
forward_edges = list(filter(([]).__ne__, forward_edges))
|
||||
back_edges = list(filter(([]).__ne__, back_edges))
|
||||
|
||||
#TODO: Remove edges set in connect_custom. The lists above can be left with invalid counts if connect_custom removes entries, they need to get put into their appropriate group
|
||||
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[group]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
@@ -340,11 +402,94 @@ def remove_reserved(world, groupedlist, connected_edges, player):
|
||||
return new_grouping
|
||||
|
||||
def reorganize_groups(world, groups, player):
|
||||
# predefined shuffle groups get reorganized here
|
||||
# this restructures the candidate pool based on the chosen settings
|
||||
if world.owShuffle[player] == 'full':
|
||||
#predefined shuffle groups get reorganized here
|
||||
if world.owCrossed[player]:
|
||||
if world.owKeepSimilar[player]:
|
||||
if world.mode[player] == 'standard':
|
||||
#tuple stays (A,B,C,D,_,F)
|
||||
# tuple goes to (A,_,C,D,_,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, _, count) = group
|
||||
new_grouping[(std, axis, terrain, count)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, _, count) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain, count)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(std, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
# tuple goes to (_,_,C,D,_,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, _, count) = group
|
||||
new_grouping[(axis, terrain, count)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, _, count) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain, count)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
if world.mode[player] == 'standard':
|
||||
# tuple goes to (A,_,C,D,_,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, _, _) = group
|
||||
new_grouping[(std, axis, terrain)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, _, _) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
forward_edges = [[i] for l in forward_edges for i in l]
|
||||
back_edges = [[i] for l in back_edges for i in l]
|
||||
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(std, axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
# tuple goes to (_,_,C,D,_,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, _, _) = group
|
||||
new_grouping[(axis, terrain)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, _, _) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
forward_edges = [[i] for l in forward_edges for i in l]
|
||||
back_edges = [[i] for l in back_edges for i in l]
|
||||
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
if world.owKeepSimilar[player]:
|
||||
if world.mode[player] == 'standard':
|
||||
# tuple goes to (A,B,C,D,_,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
@@ -362,7 +507,7 @@ def reorganize_groups(world, groups, player):
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
#tuple goes to (_,B,C,D,_,F)
|
||||
# tuple goes to (_,B,C,D,_,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
@@ -381,7 +526,7 @@ def reorganize_groups(world, groups, player):
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
if world.mode[player] == 'standard':
|
||||
#tuple stays (A,B,C,D,_,_)
|
||||
# tuple goes to (A,B,C,D,_,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
@@ -402,7 +547,7 @@ def reorganize_groups(world, groups, player):
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
#tuple goes to (_,B,C,D,_,_)
|
||||
# tuple goes to (_,B,C,D,_,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
@@ -423,14 +568,95 @@ def reorganize_groups(world, groups, player):
|
||||
|
||||
return list(new_grouping.values())
|
||||
elif world.owShuffle[player] == 'parallel':
|
||||
#predefined shuffle groups get reorganized here
|
||||
if world.owCrossed[player]:
|
||||
if world.owKeepSimilar[player]:
|
||||
if world.mode[player] == 'standard':
|
||||
#tuple stays (A,B,C,D,E,F)
|
||||
# tuple goes to (A,_,C,D,E,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, parallel, count) = group
|
||||
new_grouping[(std, axis, terrain, parallel, count)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, parallel, count) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain, parallel, count)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(std, axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
# tuple goes to (_,_,C,D,E,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, parallel, count) = group
|
||||
new_grouping[(axis, terrain, parallel, count)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, parallel, count) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain, parallel, count)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
if world.mode[player] == 'standard':
|
||||
# tuple goes to (A,_,C,D,E,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, parallel, _) = group
|
||||
new_grouping[(std, axis, terrain, parallel)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, _, axis, terrain, parallel, _) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
forward_edges = [[i] for l in forward_edges for i in l]
|
||||
back_edges = [[i] for l in back_edges for i in l]
|
||||
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain, parallel)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(std, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
# tuple goes to (_,_,C,D,E,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, parallel, _) = group
|
||||
new_grouping[(axis, terrain, parallel)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, _, axis, terrain, parallel, _) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
forward_edges = [[i] for l in forward_edges for i in l]
|
||||
back_edges = [[i] for l in back_edges for i in l]
|
||||
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain, parallel)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
if world.owKeepSimilar[player]:
|
||||
if world.mode[player] == 'standard':
|
||||
# tuple stays (A,B,C,D,E,F)
|
||||
for grouping in (groups,):
|
||||
return list(grouping.values())
|
||||
else:
|
||||
#tuple goes to (_,B,C,D,E,F)
|
||||
# tuple goes to (_,B,C,D,E,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
@@ -449,7 +675,7 @@ def reorganize_groups(world, groups, player):
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
if world.mode[player] == 'standard':
|
||||
#tuple stays (A,B,C,D,E,_)
|
||||
# tuple goes to (A,B,C,D,E,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
@@ -470,7 +696,7 @@ def reorganize_groups(world, groups, player):
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
#tuple goes to (_,B,C,D,E,_)
|
||||
# tuple goes to (_,B,C,D,E,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
@@ -489,14 +715,95 @@ def reorganize_groups(world, groups, player):
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
elif world.owShuffle[player] == 'vanilla' and world.owCrossed[player]:
|
||||
if world.owKeepSimilar[player]:
|
||||
if world.mode[player] == 'standard':
|
||||
# tuple goes to (A,B,C,D,_,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, region, axis, terrain, _, count) = group
|
||||
new_grouping[(std, region, axis, terrain, count)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, region, axis, terrain, _, count) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, count)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(std, region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
# tuple goes to (_,B,C,D,_,F)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, region, axis, terrain, _, count) = group
|
||||
new_grouping[(region, axis, terrain, count)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, region, axis, terrain, _, count) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, count)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
if world.mode[player] == 'standard':
|
||||
# tuple goes to (A,B,C,D,_,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, region, axis, terrain, _, _) = group
|
||||
new_grouping[(std, region, axis, terrain)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(std, region, axis, terrain, _, _) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
forward_edges = [[i] for l in forward_edges for i in l]
|
||||
back_edges = [[i] for l in back_edges for i in l]
|
||||
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(std, region, axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
# tuple goes to (_,B,C,D,_,_)
|
||||
for grouping in (groups,):
|
||||
new_grouping = {}
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, region, axis, terrain, _, _) = group
|
||||
new_grouping[(region, axis, terrain)] = ([], [])
|
||||
|
||||
for group in grouping.keys():
|
||||
(_, region, axis, terrain, _, _) = group
|
||||
(forward_edges, back_edges) = grouping[group]
|
||||
forward_edges = [[i] for l in forward_edges for i in l]
|
||||
back_edges = [[i] for l in back_edges for i in l]
|
||||
|
||||
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain)]
|
||||
exist_forward_edges.extend(forward_edges)
|
||||
exist_back_edges.extend(back_edges)
|
||||
new_grouping[(region, axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||
|
||||
return list(new_grouping.values())
|
||||
else:
|
||||
raise NotImplementedError('Shuffling not supported yet')
|
||||
|
||||
def create_flute_exits(world, player):
|
||||
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 (world.owSwap[player] != 'mixed' and region.type == RegionType.LightWorld) \
|
||||
or (world.owSwap[player] == 'mixed' and region.type in [RegionType.LightWorld, RegionType.DarkWorld] \
|
||||
if (not world.owMixed[player] and region.type == RegionType.LightWorld) \
|
||||
or (world.owMixed[player] and region.type in [RegionType.LightWorld, RegionType.DarkWorld] \
|
||||
and (region.name not in world.owswaps[player][1] or region.name in world.owswaps[player][2])):
|
||||
exitname = 'Flute From ' + region.name
|
||||
exit = Entrance(region.player, exitname, region)
|
||||
@@ -506,7 +813,7 @@ def create_flute_exits(world, player):
|
||||
world.initialize_regions()
|
||||
|
||||
def update_world_regions(world, player):
|
||||
if world.owSwap[player] == 'mixed':
|
||||
if world.owMixed[player]:
|
||||
for name in world.owswaps[player][1]:
|
||||
world.get_region(name, player).type = RegionType.DarkWorld
|
||||
for name in world.owswaps[player][2]:
|
||||
@@ -1110,8 +1417,7 @@ ow_connections = {
|
||||
}
|
||||
|
||||
parallelsimilar_connections = [('Maze Race ES', 'Kakariko Suburb WS'),
|
||||
('Dig Game EC', 'Frog WC'),
|
||||
('Dig Game ES', 'Frog WS')
|
||||
('Dig Game EC', 'Frog WC')
|
||||
]
|
||||
|
||||
# non shuffled overworld
|
||||
|
||||
28
README.md
28
README.md
@@ -66,19 +66,9 @@ OW Transitions are shuffled, but both worlds will have a matching layout.
|
||||
|
||||
OW Transitions are shuffled within each world separately.
|
||||
|
||||
## Overworld Tile Swap (--ow_swap)
|
||||
## Crossed (--ow_crossed)
|
||||
|
||||
### Vanilla
|
||||
|
||||
OW tiles remain in their original worlds.
|
||||
|
||||
### Mixed
|
||||
|
||||
OW tiles are randomly chosen to become a part of the opposite world
|
||||
|
||||
### Crossed
|
||||
|
||||
OW tiles remain in their original world, but transitions can now be travel cross-world.
|
||||
This allows OW connections to be shuffled cross-world.
|
||||
|
||||
## Visual Representation of Main OW Shuffle Settings
|
||||
|
||||
@@ -88,6 +78,10 @@ OW tiles remain in their original world, but transitions can now be travel cross
|
||||
|
||||
This keeps similar edge transitions together. ie. The 2 west edges of Potion Shop will be paired to another set of two similar edges
|
||||
|
||||
## Mixed Overworld (--ow_mixed)
|
||||
|
||||
OW tiles are randomly chosen to become a part of the opposite world
|
||||
|
||||
## Flute Shuffle (--ow_fluteshuffle)
|
||||
|
||||
When enabled, new flute spots are generated and gives the player the option to cancel out of the flute menu by pressing X.
|
||||
@@ -120,10 +114,10 @@ Show the help message and exit.
|
||||
For specifying the overworld layout shuffle you want as above. (default: vanilla)
|
||||
|
||||
```
|
||||
--ow_swap <mode>
|
||||
--ow_crossed
|
||||
```
|
||||
|
||||
For specifying the overworld tile swap you want as above. (default: vanilla)
|
||||
This allows cross-world connections on the overworld
|
||||
|
||||
```
|
||||
--ow_keepsimilar
|
||||
@@ -131,6 +125,12 @@ For specifying the overworld tile swap you want as above. (default: vanilla)
|
||||
|
||||
This keeps similar edge transitions paired together with other pairs of transitions
|
||||
|
||||
```
|
||||
--ow_mixed
|
||||
```
|
||||
|
||||
This gives each OW tile a random chance to be swapped to the opposite world
|
||||
|
||||
```
|
||||
--ow_fluteshuffle <mode>
|
||||
```
|
||||
|
||||
137
Rom.py
137
Rom.py
@@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = 'cc8fc59caa0bbe6d26ac64b9d2893709'
|
||||
RANDOMIZERBASEHASH = '99f3f57ab2c9449172cade4927a462d6'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
@@ -612,71 +612,20 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
||||
if world.pot_contents[player]:
|
||||
write_pots_to_rom(rom, world.pot_contents[player])
|
||||
|
||||
# patch overworld edges
|
||||
inverted_buffer = [0] * 0x82
|
||||
if world.owShuffle[player] != 'vanilla' or world.owSwap[player] != 'vanilla':
|
||||
owMode = 0
|
||||
if world.owShuffle[player] == 'parallel':
|
||||
owMode = 1
|
||||
elif world.owShuffle[player] == 'full':
|
||||
owMode = 2
|
||||
|
||||
if world.owSwap[player] == 'mixed':
|
||||
owMode |= 0x100
|
||||
world.fix_fake_world[player] = True
|
||||
elif world.owSwap[player] == 'crossed':
|
||||
owMode |= 0x200
|
||||
world.fix_fake_world[player] = True
|
||||
|
||||
write_int16(rom, 0x150002, owMode)
|
||||
|
||||
owFlags = 0
|
||||
if world.owKeepSimilar[player]:
|
||||
owFlags |= 0x1
|
||||
if world.owFluteShuffle[player] != 'vanilla':
|
||||
owFlags |= 0x100
|
||||
|
||||
write_int16(rom, 0x150004, owFlags)
|
||||
|
||||
rom.write_byte(0x18004C, 0x01) # patch for allowing Frogsmith to enter multi-entrance caves
|
||||
|
||||
# patches map data specific for OW Shuffle
|
||||
#inverted_buffer[0x03] = inverted_buffer[0x03] | 0x2 # convenient portal on WDM
|
||||
inverted_buffer[0x1A] = inverted_buffer[0x1A] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x1B] = inverted_buffer[0x1B] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x22] = inverted_buffer[0x22] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x3F] = inverted_buffer[0x3F] | 0x2 # added C to terrain
|
||||
#inverted_buffer[0x43] = inverted_buffer[0x43] | 0x2 # convenient portal on WDDM
|
||||
inverted_buffer[0x5A] = inverted_buffer[0x5A] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x5B] = inverted_buffer[0x5B] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x62] = inverted_buffer[0x62] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x7F] = inverted_buffer[0x7F] | 0x2 # added C to terrain
|
||||
|
||||
if world.owSwap[player] == 'mixed':
|
||||
for b in world.owswaps[player][0]:
|
||||
# load inverted maps
|
||||
inverted_buffer[b] = (inverted_buffer[b] & 0xFE) | ((inverted_buffer[b] + 1) % 2)
|
||||
|
||||
# set world flag
|
||||
rom.write_byte(0x153A00 + b, 0x00 if b >= 0x40 else 0x40)
|
||||
|
||||
for edge in world.owedges:
|
||||
if edge.dest is not None and isinstance(edge.dest, OWEdge) and edge.player == player:
|
||||
write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc)
|
||||
write_int16(rom, edge.getAddress() + 0x0e, edge.getTarget())
|
||||
|
||||
# patch flute spots
|
||||
owFlags = 0
|
||||
if world.owFluteShuffle[player] == 'vanilla':
|
||||
flute_spots = default_flute_connections
|
||||
else:
|
||||
flute_spots = world.owflutespots[player]
|
||||
owFlags |= 0x100
|
||||
|
||||
for o in range(0, len(flute_spots)):
|
||||
owslot = flute_spots[o]
|
||||
offset = 0
|
||||
data = flute_data[owslot]
|
||||
|
||||
if (world.mode[player] == 'inverted') != (data[1] in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (data[1] in world.owswaps[player][0] and world.owMixed[player]):
|
||||
offset = 0x40
|
||||
|
||||
write_int16(rom, snes_to_pc(0x02E849 + (o * 2)), data[1] + offset) # owid
|
||||
@@ -696,6 +645,54 @@ 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 overworld edges
|
||||
inverted_buffer = [0] * 0x82
|
||||
if world.owShuffle[player] != 'vanilla' or world.owCrossed[player] or world.owMixed[player]:
|
||||
owMode = 0
|
||||
if world.owShuffle[player] == 'parallel':
|
||||
owMode = 1
|
||||
elif world.owShuffle[player] == 'full':
|
||||
owMode = 2
|
||||
|
||||
if world.owKeepSimilar[player] and (world.owShuffle[player] != 'vanilla' or world.owCrossed[player]):
|
||||
owMode |= 0x100
|
||||
if world.owCrossed[player]:
|
||||
owMode |= 0x200
|
||||
world.fix_fake_world[player] = True
|
||||
if world.owMixed[player]:
|
||||
owMode |= 0x400
|
||||
|
||||
write_int16(rom, 0x150002, owMode)
|
||||
|
||||
write_int16(rom, 0x150004, owFlags)
|
||||
|
||||
rom.write_byte(0x18004C, 0x01) # patch for allowing Frogsmith to enter multi-entrance caves
|
||||
|
||||
# patches map data specific for OW Shuffle
|
||||
#inverted_buffer[0x03] = inverted_buffer[0x03] | 0x2 # convenient portal on WDM
|
||||
inverted_buffer[0x1A] = inverted_buffer[0x1A] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x1B] = inverted_buffer[0x1B] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x22] = inverted_buffer[0x22] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x3F] = inverted_buffer[0x3F] | 0x2 # added C to terrain
|
||||
#inverted_buffer[0x43] = inverted_buffer[0x43] | 0x2 # convenient portal on WDDM
|
||||
inverted_buffer[0x5A] = inverted_buffer[0x5A] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x5B] = inverted_buffer[0x5B] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x62] = inverted_buffer[0x62] | 0x2 # rocks added to prevent OWG hardlock
|
||||
inverted_buffer[0x7F] = inverted_buffer[0x7F] | 0x2 # added C to terrain
|
||||
|
||||
if world.owMixed[player]:
|
||||
for b in world.owswaps[player][0]:
|
||||
# load inverted maps
|
||||
inverted_buffer[b] = (inverted_buffer[b] & 0xFE) | ((inverted_buffer[b] + 1) % 2)
|
||||
|
||||
# set world flag
|
||||
rom.write_byte(0x153A00 + b, 0x00 if b >= 0x40 else 0x40)
|
||||
|
||||
for edge in world.owedges:
|
||||
if edge.dest is not None and isinstance(edge.dest, OWEdge) and edge.player == player:
|
||||
write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc)
|
||||
write_int16(rom, edge.getAddress() + 0x0e, edge.getTarget())
|
||||
|
||||
|
||||
# patch entrance/exits/holes
|
||||
for region in world.regions:
|
||||
@@ -2177,7 +2174,7 @@ def write_strings(rom, world, player, team):
|
||||
if world.shuffle[player] in ['insanity', 'madness_legacy', 'insanity_legacy']:
|
||||
entrances_to_hint.update(InsanityEntrances)
|
||||
if world.shuffle_ganon:
|
||||
if world.mode[player] == 'inverted' != (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if world.mode[player] == 'inverted' != (0x1b in world.owswaps[player][0] and world.owMixed[player]):
|
||||
entrances_to_hint.update({'Inverted Pyramid Entrance': 'The extra castle passage'})
|
||||
else:
|
||||
entrances_to_hint.update({'Pyramid Entrance': 'The pyramid ledge'})
|
||||
@@ -2247,7 +2244,7 @@ def write_strings(rom, world, player, team):
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
|
||||
# Adding a guaranteed hint for the Flute in overworld shuffle.
|
||||
if world.owShuffle[player] in ['parallel','full']:
|
||||
if world.owShuffle[player] != 'vanilla' or world.owMixed[player]:
|
||||
this_location = world.find_items_not_key_only('Ocarina', player)
|
||||
if this_location:
|
||||
this_hint = this_location[0].item.hint_text + ' can be found ' + hint_text(this_location[0]) + '.'
|
||||
@@ -2255,7 +2252,7 @@ def write_strings(rom, world, player, team):
|
||||
|
||||
# Lastly we write hints to show where certain interesting items are. It is done the way it is to re-use the silver code and also to give one hint per each type of item regardless of how many exist. This supports many settings well.
|
||||
items_to_hint = RelevantItems.copy()
|
||||
if world.owShuffle[player] in ['parallel','full']:
|
||||
if world.owShuffle[player] != 'vanilla' or world.owMixed[player]:
|
||||
items_to_hint.remove('Ocarina')
|
||||
if world.keyshuffle[player]:
|
||||
items_to_hint.extend(SmallKeys)
|
||||
@@ -2264,7 +2261,7 @@ def write_strings(rom, world, player, team):
|
||||
random.shuffle(items_to_hint)
|
||||
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 8
|
||||
hint_count += 2 if world.doorShuffle[player] == 'crossed' else 0
|
||||
hint_count += 1 if world.owShuffle[player] in ['parallel', 'full'] else 0
|
||||
hint_count += 1 if world.owShuffle[player] != 'vanilla' or world.owMixed[player] else 0
|
||||
while hint_count > 0:
|
||||
this_item = items_to_hint.pop(0)
|
||||
this_location = world.find_items_not_key_only(this_item, player)
|
||||
@@ -2475,7 +2472,7 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
if world.doorShuffle[player] == 'vanilla' or world.intensity[player] < 3:
|
||||
write_int16(rom, 0x15AEE + 2*0x38, 0x00E0)
|
||||
write_int16(rom, 0x15AEE + 2*0x25, 0x000C)
|
||||
if (world.mode[player] == 'inverted') != (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x03 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple']:
|
||||
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01]) # mountain cave starts on OW
|
||||
|
||||
@@ -2498,18 +2495,18 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
rom.write_byte(snes_to_pc(0x02D9B8), 0x12)
|
||||
|
||||
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00]) #indicates the overworld door being used for the single entrance spawn point
|
||||
if (world.mode[player] == 'inverted') != (0x05 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x05 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x1BC655), [0x4A, 0x1D, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x07 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x07 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x1BC387), [0xDD, 0xD1]) # add warps under rocks
|
||||
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF]) # add warps under rocks
|
||||
rom.write_byte(0x180089, 0x01) # open TR after exit
|
||||
rom.write_bytes(0x0086E, [0x5C, 0x00, 0xA0, 0xA1]) # TR tail
|
||||
if world.shuffle[player] in ['vanilla']:
|
||||
world.fix_trock_doors[player] = True
|
||||
if (world.mode[player] == 'inverted') != (0x10 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x10 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x1BC67A), [0x2E, 0x0B, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x1B in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x1B in world.owswaps[player][0] and world.owMixed[player]):
|
||||
write_int16(rom, 0x15AEE + 2 * 0x06, 0x0020) # post aga hyrule castle spawn
|
||||
rom.write_byte(0x15B8C + 0x06, 0x1B)
|
||||
write_int16(rom, 0x15BDB + 2 * 0x06, 0x00AE)
|
||||
@@ -2597,21 +2594,21 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
|
||||
|
||||
write_int16(rom, 0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door
|
||||
write_int16(rom, 0xDBA71 + 2 * 0x35, 0x011C)
|
||||
if (world.mode[player] == 'inverted') != (0x29 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x29 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05]) # frog pickup on contact
|
||||
if (world.mode[player] == 'inverted') != (0x2C in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x2C in world.owswaps[player][0] and world.owMixed[player]):
|
||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||
rom.write_byte(0x15B8C, 0x6C) # exit links at bomb shop area
|
||||
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house
|
||||
rom.write_byte(0xDBB73 + 0x52, 0x01)
|
||||
if (world.mode[player] == 'inverted') != (0x2F in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x2F in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x1BC81E), [0x94, 0x1D, 0x82]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x33 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x33 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x1BC3DF), [0xD8, 0xD1]) # add warp under rock
|
||||
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF]) # add warp under rock
|
||||
if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82]) # add warp under rock
|
||||
|
||||
# apply inverted map changes
|
||||
|
||||
82
Rules.py
82
Rules.py
@@ -844,7 +844,7 @@ def ow_rules(world, player):
|
||||
else:
|
||||
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x00 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x00 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Lost Woods East Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lost Woods Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lost Woods Pedestal Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -859,12 +859,12 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Skull Woods Forgotten (Middle) Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Skull Woods Front Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x02 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x02 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dark Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('West Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Spectacle Rock Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
@@ -872,7 +872,7 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Bubble Boy Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('West Dark Death Mountain (Bottom) Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x05 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x05 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('East Death Mountain (Top West) Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('East Death Mountain (Top East) Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Mimic Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -894,7 +894,7 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Dark Floating Island Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Dark Death Mountain Teleporter (East)', player), lambda state: state.can_lift_heavy_rocks(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x07 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x07 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('TR Pegs Area Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('TR Pegs Teleporter', player), lambda state: state.has('Hammer', player))
|
||||
else:
|
||||
@@ -902,7 +902,7 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Turtle Rock Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_heavy_rocks(player) and state.has_Pearl(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x0a in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Mountain Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Mountain Entry Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Mountain Entry Entrance Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -911,12 +911,12 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Bumper Cave Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x0f in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x0f in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Zora Waterfall Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Catfish Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x10 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x10 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Lost Woods Pass West Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lost Woods Pass East Top Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lost Woods Pass East Bottom Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -929,24 +929,24 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('West Dark World Teleporter (Hammer)', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player))
|
||||
set_rule(world.get_entrance('West Dark World Teleporter (Rock)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) # bunny cannot lift bushes
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x11 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x11 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Kakariko Fortune Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Outcast Fortune Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x12 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x12 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Kakariko Pond Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Outcast Pond Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x13 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x13 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Sanctuary Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Bonk Rock Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dark Chapel Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Dark Chapel Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x14 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x14 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Graveyard Ledge Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
|
||||
else:
|
||||
@@ -956,28 +956,28 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Dark Graveyard Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Dark Graveyard Grave Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x15 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x15 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('River Bend Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('River Bend East Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Qirn Jump Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Qirn Jump East Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x16 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x16 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Potion Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Potion Shop Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dark Witch Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Dark Witch Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x17 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x17 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Zora Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Zora Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Catfish Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Catfish Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x18 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x18 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Kakariko Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Kakariko Grass Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
@@ -985,13 +985,13 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Village of Outcasts Southwest Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Hammer House Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x1a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x1a in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Forgotton Forest Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Forgotton Forest Fence Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Shield Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x1b in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: False)
|
||||
set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False)
|
||||
set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player])
|
||||
@@ -1017,7 +1017,7 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Pyramid Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Post Aga Inverted Teleporter', player), lambda state: state.has('Beat Agahnim 1', player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x1d in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x1d in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Wooden Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Wooden Bridge Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Wooden Bridge West Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -1026,12 +1026,12 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Broken Bridge East Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Broken Bridge Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x1e in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x1e in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Eastern Palace Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Palace of Darkness Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x22 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x22 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Blacksmith Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Blacksmith Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Bat Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -1039,19 +1039,19 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Hammer Pegs Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Hammer Pegs Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x25 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x25 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Sand Dunes Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dark Dunes Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x28 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x28 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Maze Race Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Maze Race Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dig Game Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Dig Game Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x29 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x29 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Kakariko Suburb Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Kakariko Suburb South Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
@@ -1059,24 +1059,24 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Frog Prison Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Archery Game Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x2a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x2a in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Flute Boy Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Flute Boy Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Stumpy Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Stumpy Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x2b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x2b in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Central Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dark Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x2c in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x2c in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Links House Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Big Bomb Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x2d in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x2d in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Stone Bridge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Stone Bridge South Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Hobo Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
|
||||
@@ -1085,19 +1085,19 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Hammer Bridge South Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Dark Hobo Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x2e in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x2e in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dark Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x2f in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x2f in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Eastern Nook Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('East Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer
|
||||
else:
|
||||
set_rule(world.get_entrance('Darkness Nook Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('East Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x30 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x30 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Checkerboard Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Desert Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Desert Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -1112,14 +1112,14 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Misery Mire Main Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Misery Mire Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x32 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x32 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Cave 45 Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Flute Boy Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Stumpy Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Stumpy Bush Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x33 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x33 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('C Whirlpool Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('C Whirlpool Outer Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer
|
||||
@@ -1130,12 +1130,12 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('South Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player))
|
||||
set_rule(world.get_entrance('South Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x34 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x34 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Statues Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Hype Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x35 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x35 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Lake Hylia Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lake Hylia Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player))
|
||||
@@ -1152,12 +1152,12 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Ice Palace Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Ice Palace Teleporter', player), lambda state: state.can_lift_heavy_rocks(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x37 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x37 in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Ice Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Shopping Mall Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x3a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x3a in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Desert Pass Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Desert Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
@@ -1165,17 +1165,17 @@ def ow_rules(world, player):
|
||||
set_rule(world.get_entrance('Swamp Nook Southeast Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
set_rule(world.get_entrance('Swamp Nook Pegs Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x3b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x3b in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Dam Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Swamp Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x3c in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x3c in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('South Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Dark South Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
|
||||
if (world.mode[player] == 'inverted') == (0x3f in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
||||
if (world.mode[player] == 'inverted') == (0x3f in world.owswaps[player][0] and world.owMixed[player]):
|
||||
set_rule(world.get_entrance('Octoballoon Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
else:
|
||||
set_rule(world.get_entrance('Bomber Corner Mirror Spot', player), lambda state: state.has_Mirror(player))
|
||||
@@ -2050,7 +2050,7 @@ def set_inverted_big_bomb_rules(world, player):
|
||||
else:
|
||||
raise Exception('No logic found for routing from %s to the pyramid.' % bombshop_entrance.name)
|
||||
|
||||
if world.owShuffle[player] != 'vanilla' or world.owSwap[player] != 'vanilla':
|
||||
if world.owShuffle[player] != 'vanilla' or world.owMixed[player] or world.owCrossed[player]:
|
||||
add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: False) #temp disable progression until routing to Pyramid get be guaranteed
|
||||
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ OWNewDestination:
|
||||
sep #$30 : lda OWOppSlotOffset,y : !add $04 : asl : and #$7f : sta $700
|
||||
|
||||
; crossed OW shuffle
|
||||
lda.l OWMode+1 : and #$ff : cmp #$02 : bne .return
|
||||
lda.l OWMode+1 : and.b #$02 : beq .return
|
||||
ldx $05 : lda.l OWTileWorldAssoc,x : sta.l $7ef3ca ; change world
|
||||
|
||||
; toggle bunny mode
|
||||
|
||||
Binary file not shown.
@@ -3,13 +3,15 @@
|
||||
vanilla: 0
|
||||
parallel: 2
|
||||
full: 2
|
||||
overworld_crossed:
|
||||
on: 1
|
||||
off: 1
|
||||
overworld_keepsimilar:
|
||||
on: 1
|
||||
off: 1
|
||||
overworld_swap:
|
||||
vanilla: 0
|
||||
mixed: 2
|
||||
crossed: 2
|
||||
overworld_mixed:
|
||||
on: 1
|
||||
off: 1
|
||||
flute_shuffle:
|
||||
vanilla: 0
|
||||
balanced: 1
|
||||
|
||||
@@ -116,17 +116,18 @@
|
||||
"full"
|
||||
]
|
||||
},
|
||||
"ow_swap": {
|
||||
"choices": [
|
||||
"vanilla",
|
||||
"mixed",
|
||||
"crossed"
|
||||
]
|
||||
"ow_crossed": {
|
||||
"action": "store_true",
|
||||
"type": "bool"
|
||||
},
|
||||
"ow_keepsimilar": {
|
||||
"action": "store_true",
|
||||
"type": "bool"
|
||||
},
|
||||
"ow_mixed": {
|
||||
"action": "store_true",
|
||||
"type": "bool"
|
||||
},
|
||||
"ow_fluteshuffle": {
|
||||
"choices": [
|
||||
"vanilla",
|
||||
|
||||
@@ -201,22 +201,19 @@
|
||||
"Full: Overworld transitions are shuffled, but both worlds",
|
||||
" will have an independent map shape."
|
||||
],
|
||||
"ow_swap": [
|
||||
"This swaps the tiles of the overworld from one world to the other.",
|
||||
"Vanilla: All overworld tiles remain in their original world as",
|
||||
" they were in the base game.",
|
||||
"Mixed: Overworld tiles are randomly chosen to become part of",
|
||||
" the opposite world.",
|
||||
"Crossed: Overworld tiles remain in their original world, but",
|
||||
" the transitions are shuffled cross world."
|
||||
],
|
||||
"ow_crossed": [
|
||||
"This allows cross-world connections to occur on the overworld." ],
|
||||
"ow_keepsimilar": [
|
||||
"This keeps similar edge transitions together. ie. the two west edges on",
|
||||
"Potion Shop will be paired with another similar pair." ],
|
||||
"ow_mixed": [
|
||||
"Overworld tiles are randomly chosen to become part of the opposite world."
|
||||
],
|
||||
"ow_fluteshuffle": [
|
||||
"This randomizes the flute spot destinations.",
|
||||
"Vanilla: All flute spots remain unchanged.",
|
||||
"Balanced: New flute spots will be generated but prevents flute spots from being on any adjacent screen.",
|
||||
"Balanced: New flute spots will be generated but prevents flute",
|
||||
" spots from being on any adjacent screen.",
|
||||
"Random: New flute spots will be generated with minimal bias."
|
||||
],
|
||||
"door_shuffle": [
|
||||
|
||||
@@ -117,12 +117,9 @@
|
||||
"randomizer.overworld.overworldshuffle.parallel": "Parallel",
|
||||
"randomizer.overworld.overworldshuffle.full": "Full",
|
||||
|
||||
"randomizer.overworld.overworldswap": "Tile Swap",
|
||||
"randomizer.overworld.overworldswap.vanilla": "Vanilla",
|
||||
"randomizer.overworld.overworldswap.mixed": "Mixed",
|
||||
"randomizer.overworld.overworldswap.crossed": "Crossed",
|
||||
|
||||
"randomizer.overworld.crossed": "Crossed",
|
||||
"randomizer.overworld.keepsimilar": "Keep Similar Edges Together",
|
||||
"randomizer.overworld.mixed": "Mixed",
|
||||
|
||||
"randomizer.overworld.overworldflute": "Flute Shuffle",
|
||||
"randomizer.overworld.overworldflute.vanilla": "Vanilla",
|
||||
|
||||
@@ -9,15 +9,6 @@
|
||||
"full"
|
||||
]
|
||||
},
|
||||
"overworldswap": {
|
||||
"type": "selectbox",
|
||||
"default": "mixed",
|
||||
"options": [
|
||||
"vanilla",
|
||||
"mixed",
|
||||
"crossed"
|
||||
]
|
||||
},
|
||||
"overworldflute": {
|
||||
"type": "selectbox",
|
||||
"default": "vanilla",
|
||||
@@ -29,6 +20,14 @@
|
||||
}
|
||||
},
|
||||
"rightOverworldFrame": {
|
||||
"crossed": {
|
||||
"type": "checkbox",
|
||||
"default": false
|
||||
},
|
||||
"mixed": {
|
||||
"type": "checkbox",
|
||||
"default": true
|
||||
},
|
||||
"keepsimilar": {
|
||||
"type": "checkbox",
|
||||
"default": true
|
||||
|
||||
@@ -76,8 +76,9 @@ SETTINGSTOPROCESS = {
|
||||
},
|
||||
"overworld": {
|
||||
"overworldshuffle": "ow_shuffle",
|
||||
"overworldswap": "ow_swap",
|
||||
"crossed": "ow_crossed",
|
||||
"keepsimilar": "ow_keepsimilar",
|
||||
"mixed": "ow_mixed",
|
||||
"overworldflute": "ow_fluteshuffle"
|
||||
},
|
||||
"entrance": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, Frame, Label, W, E, NW, LEFT, RIGHT, X, TOP
|
||||
from tkinter import ttk, Frame, Label, W, E, NW, LEFT, RIGHT, X, Y, TOP
|
||||
import source.gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -16,12 +16,10 @@ def overworld_page(parent):
|
||||
# Load Overworld Shuffle option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
# These get split left & right
|
||||
self.frames["widgets"] = Frame(self)
|
||||
self.frames["leftOverworldFrame"] = Frame(self.frames["widgets"])
|
||||
self.frames["rightOverworldFrame"] = Frame(self.frames["widgets"])
|
||||
self.frames["widgets"].pack(fill=X)
|
||||
self.frames["leftOverworldFrame"].pack(side=LEFT)
|
||||
self.frames["rightOverworldFrame"].pack(side=LEFT, anchor=NW)
|
||||
self.frames["leftOverworldFrame"] = Frame(self)
|
||||
self.frames["rightOverworldFrame"] = Frame(self)
|
||||
self.frames["leftOverworldFrame"].pack(side=LEFT, anchor=NW)
|
||||
self.frames["rightOverworldFrame"].pack(anchor=NW)
|
||||
|
||||
with open(os.path.join("resources","app","gui","randomize","overworld","widgets.json")) as overworldWidgets:
|
||||
myDict = json.load(overworldWidgets)
|
||||
@@ -29,8 +27,8 @@ def overworld_page(parent):
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
|
||||
for key in dictWidgets:
|
||||
self.widgets[key] = dictWidgets[key]
|
||||
if key == "rightOverworldFrame":
|
||||
self.widgets[key].pack(anchor=E)
|
||||
if framename == "rightOverworldFrame":
|
||||
self.widgets[key].pack(side=LEFT)
|
||||
else:
|
||||
self.widgets[key].pack(anchor=E)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user