Moved Crossed OW Shuffle to its own setting, Renamed Tile Swap to Mixed

This commit is contained in:
codemann8
2021-08-16 22:46:26 -05:00
parent 7b81c5d9da
commit be6203e3f0
20 changed files with 645 additions and 345 deletions

View File

@@ -19,13 +19,14 @@ from RoomData import Room
class World(object): 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): timer, progressive, goal, algorithm, accessibility, shuffle_ganon, retro, custom, customitemarray, hints):
self.players = players self.players = players
self.teams = 1 self.teams = 1
self.owShuffle = owShuffle.copy() self.owShuffle = owShuffle.copy()
self.owSwap = owSwap.copy() self.owCrossed = owCrossed.copy()
self.owKeepSimilar = {} self.owKeepSimilar = {}
self.owMixed = owMixed.copy()
self.owFluteShuffle = {} self.owFluteShuffle = {}
self.shuffle = shuffle.copy() self.shuffle = shuffle.copy()
self.doorShuffle = doorShuffle.copy() self.doorShuffle = doorShuffle.copy()
@@ -2308,8 +2309,9 @@ class Spoiler(object):
'weapons': self.world.swords, 'weapons': self.world.swords,
'goal': self.world.goal, 'goal': self.world.goal,
'ow_shuffle': self.world.owShuffle, 'ow_shuffle': self.world.owShuffle,
'ow_swap': self.world.owSwap, 'ow_crossed': self.world.owCrossed,
'ow_keepsimilar': self.world.owKeepSimilar, 'ow_keepsimilar': self.world.owKeepSimilar,
'ow_mixed': self.world.owMixed,
'ow_fluteshuffle': self.world.owFluteShuffle, 'ow_fluteshuffle': self.world.owFluteShuffle,
'shuffle': self.world.shuffle, 'shuffle': self.world.shuffle,
'door_shuffle': self.world.doorShuffle, '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('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('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 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': 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('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('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('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]) 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) # byte 0: DDOO OEEE (DR, OR, ER)
dr_mode = {"basic": 1, "crossed": 2, "vanilla": 0} dr_mode = {"basic": 1, "crossed": 2, "vanilla": 0}
or_mode = {"vanilla": 0, "parallel": 1, "full": 2} or_mode = {"vanilla": 0, "parallel": 1, "full": 1}
orswap_mode = {"vanilla": 0, "mixed": 1, "crossed": 1}
er_mode = {"vanilla": 0, "simple": 1, "restricted": 3, "full": 3, "crossed": 4, "insanity": 5, "dungeonsfull": 7, "dungeonssimple": 7} 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) # byte 1: LLLW WSSR (logic, mode, sword, retro)
@@ -2592,7 +2594,7 @@ class Settings(object):
@staticmethod @staticmethod
def make_code(w, p): def make_code(w, p):
code = bytes([ 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) (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), | (sword_mode[w.swords[p]] << 1) | (1 if w.retro[p] else 0),

5
CLI.py
View File

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

View File

@@ -214,7 +214,7 @@ def vanilla_key_logic(world, player):
analyze_dungeon(key_layout, world, player) analyze_dungeon(key_layout, world, player)
world.key_logic[player][builder.name] = key_layout.key_logic world.key_logic[player][builder.name] = key_layout.key_logic
log_key_logic(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) validate_vanilla_key_logic(world, player)

View File

@@ -50,18 +50,18 @@ def link_entrances(world, player):
# inverted entrance mods # inverted entrance mods
for owid in swapped_connections.keys(): 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]: for (entrancename, exitname) in swapped_connections[owid]:
try: try:
connect_two_way(world, entrancename, exitname, player) connect_two_way(world, entrancename, exitname, player)
except RuntimeError: except RuntimeError:
connect_entrance(world, entrancename, exitname, player) connect_entrance(world, entrancename, exitname, player)
if invFlag != (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed') and \ if invFlag != (0x03 in world.owswaps[player][0] and world.owMixed[player]) and \
invFlag == (0x0a in world.owswaps[player][0] and world.owSwap[player] == 'mixed'): 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) 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 \ elif invFlag != (0x0a in world.owswaps[player][0] and world.owMixed[player]) and \
invFlag == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'): 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) connect_two_way(world, 'Bumper Cave (Top)', 'Death Mountain Return Cave Exit (West)', player)
# dungeon entrance shuffle # dungeon entrance shuffle
@@ -225,7 +225,7 @@ def link_entrances(world, player):
random.shuffle(remaining_entrances) random.shuffle(remaining_entrances)
old_man_entrance = remaining_entrances.pop() 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) connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player)
if invFlag and old_man_exit == 'Spike Cave': if invFlag and old_man_exit == 'Spike Cave':
bomb_shop_doors.remove('Spike Cave') bomb_shop_doors.remove('Spike Cave')
@@ -791,8 +791,8 @@ def link_entrances(world, player):
if not world.shuffle_ganon: 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, '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_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.owSwap[player] == 'mixed') else 'Inverted Pyramid Hole', 'Pyramid', 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: else:
caves.extend(['Ganons Tower Exit', 'Pyramid Exit']) caves.extend(['Ganons Tower Exit', 'Pyramid Exit'])
hole_targets.append('Pyramid') hole_targets.append('Pyramid')
@@ -804,7 +804,7 @@ def link_entrances(world, player):
exit_pool.extend(['Agahnims Tower']) exit_pool.extend(['Agahnims Tower'])
doors.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']) exit_pool.extend(['Pyramid Entrance'])
hole_entrances.append('Pyramid Hole') hole_entrances.append('Pyramid Hole')
entrances_must_exits.append('Pyramid Entrance') entrances_must_exits.append('Pyramid Entrance')
@@ -943,7 +943,7 @@ def link_entrances(world, player):
world.powder_patch_required[player] = True world.powder_patch_required[player] = True
# check for ganon location # 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 world.ganon_at_pyramid[player] = False
# check for Ganon's Tower location # check for Ganon's Tower location
@@ -1030,7 +1030,7 @@ def scramble_holes(world, player):
('Lumberjack Tree Exit', 'Lumberjack Tree (top)')] ('Lumberjack Tree Exit', 'Lumberjack Tree (top)')]
if not world.shuffle_ganon: 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_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player) connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
else: else:
@@ -1053,7 +1053,7 @@ def scramble_holes(world, player):
if world.shuffle_ganon: if world.shuffle_ganon:
random.shuffle(hole_targets) random.shuffle(hole_targets)
exit, target = hole_targets.pop() 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_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player) connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
else: else:

View File

@@ -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) (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) world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999)
else: 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(): if player in world.pool_adjustment.keys():
amt = world.pool_adjustment[player] 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} '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 = [] pool = []
placed_items = {} placed_items = {}
precollected_items = [] precollected_items = []
@@ -990,21 +990,20 @@ def test():
for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']: for logic in ['noglitches', 'minorglitches', 'owglitches', 'nologic']:
for retro in [True, False]: for retro in [True, False]:
for door_shuffle in ['basic', 'crossed', 'vanilla']: for door_shuffle in ['basic', 'crossed', 'vanilla']:
for owShuffle in ['full', 'parallel', 'vanilla']: for bombbag in [True, False]:
for owSwap in ['vanilla', 'mixed', 'crossed']: out = get_pool_core(progressive, shuffle, difficulty, 30, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic)
out = get_pool_core(progressive, owShuffle, owSwap, shuffle, difficulty, 30, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic) count = len(out[0]) + len(out[1])
count = len(out[0]) + len(out[1])
correct_count = total_items_to_place correct_count = total_items_to_place
if goal == 'pedestal' and swords != 'vanilla': if goal == 'pedestal' and swords != 'vanilla':
# pedestal goals generate one extra item # pedestal goals generate one extra item
correct_count += 1 correct_count += 1
if retro: if retro:
correct_count += 28 correct_count += 28
try: try:
assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bombbag)) assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bombbag))
except AssertionError as e: except AssertionError as e:
print(e) print(e)
if __name__ == '__main__': if __name__ == '__main__':
test() test()

View File

@@ -61,7 +61,7 @@ def main(args, seed=None, fish=None):
for player, code in args.code.items(): for player, code in args.code.items():
if code: if code:
Settings.adjust_args_from_code(code, player, args) 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.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm,
args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints) args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints)
logger = logging.getLogger('') logger = logging.getLogger('')
@@ -263,7 +263,7 @@ def main(args, seed=None, fish=None):
customize_shops(world, player) customize_shops(world, player)
balance_money_progression(world) 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}' outfilebase = f'OR_{args.outputname if args.outputname else world.seed}'
else: else:
outfilebase = f'DR_{args.outputname if args.outputname else world.seed}' 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): def copy_world(world):
# ToDo: Not good yet # 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.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) world.accessibility, world.shuffle_ganon, world.retro, world.custom, world.customitemarray, world.hints)
ret.teams = world.teams ret.teams = world.teams

View File

@@ -133,9 +133,9 @@ def roll_settings(weights):
overworld_shuffle = get_choice('overworld_shuffle') overworld_shuffle = get_choice('overworld_shuffle')
ret.ow_shuffle = overworld_shuffle if overworld_shuffle != 'none' else 'vanilla' ret.ow_shuffle = overworld_shuffle if overworld_shuffle != 'none' else 'vanilla'
overworld_swap = get_choice('overworld_swap') ret.ow_crossed = get_choice('overworld_crossed')
ret.ow_swap = overworld_swap if overworld_swap != 'none' else 'vanilla'
ret.ow_keepsimilar = get_choice('overworld_keepsimilar') ret.ow_keepsimilar = get_choice('overworld_keepsimilar')
ret.ow_mixed = get_choice('overworld_mixed')
overworld_flute = get_choice('flute_shuffle') overworld_flute = get_choice('flute_shuffle')
ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla' ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla'
entrance_shuffle = get_choice('entrance_shuffle') entrance_shuffle = get_choice('entrance_shuffle')

View File

@@ -11,9 +11,25 @@ def link_overworld(world, player):
for exitname, destname in temporary_mandatory_connections: for exitname, destname in temporary_mandatory_connections:
connect_two_way(world, exitname, destname, player) connect_two_way(world, exitname, destname, player)
# tile shuffle
trimmed_groups = copy.deepcopy(OWEdgeGroups) 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 = {} tile_groups = {}
for (name, groupType) in OWTileGroups.keys(): for (name, groupType) in OWTileGroups.keys():
if world.mode[player] != 'standard' or name not in ['Castle', 'Links', 'Central Bonk Rocks']: 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]) exist_dw_regions.extend(OWTileRegions.inverse[owid])
tile_groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions) tile_groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions)
#tile shuffle happens here, the groups that remain in the list are the tiles that get swapped # tile shuffle happens here, the groups that remain in the list are the tiles that get swapped
removed = list() removed = list()
for group in tile_groups.keys(): for group in tile_groups.keys():
if random.randint(0, 1): if random.randint(0, 1):
@@ -52,7 +68,7 @@ def link_overworld(world, player):
for group in removed: for group in removed:
tile_groups.pop(group, None) tile_groups.pop(group, None)
#save shuffled tiles to world object # save shuffled tiles to world object
for group in tile_groups.keys(): for group in tile_groups.keys():
(owids, lw_regions, dw_regions) = tile_groups[group] (owids, lw_regions, dw_regions) = tile_groups[group]
(exist_owids, exist_lw_regions, exist_dw_regions) = world.owswaps[player] (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) exist_dw_regions.extend(dw_regions)
world.owswaps[player] = [exist_owids, exist_lw_regions, exist_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 ignore_list = list() #TODO: Remove ignore_list when special OW areas are included in pool
for edgeset in temporary_mandatory_connections: for edgeset in temporary_mandatory_connections:
for edge in edgeset: 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 #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') 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)][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.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']) 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 # make new connections
for owid in ow_connections.keys(): 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]: for (exitname, regionname) in ow_connections[owid][0]:
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
else: else:
@@ -151,57 +167,90 @@ def link_overworld(world, player):
connect_custom(world, connected_edges, player) connect_custom(world, connected_edges, player)
# layout shuffle # layout shuffle
if world.owShuffle[player] == 'vanilla': if world.owShuffle[player] == 'vanilla' and not world.owCrossed[player]:
# vanilla transitions
groups = list(trimmed_groups.values()) groups = list(trimmed_groups.values())
for (forward_edge_sets, back_edge_sets) in groups: for (forward_edge_sets, back_edge_sets) in groups:
assert len(forward_edge_sets) == len(back_edge_sets) assert len(forward_edge_sets) == len(back_edge_sets)
for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets): for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets):
assert len(forward_set) == len(back_set) assert len(forward_set) == len(back_set)
for (forward_edge, back_edge) in zip(forward_set, back_set): for (forward_edge, back_edge) in zip(forward_set, back_set):
connect_two_way(world, forward_edge, back_edge, player) connect_two_way(world, forward_edge, back_edge, player, connected_edges)
connected_edges.append(forward_edge)
connected_edges.append(back_edge)
assert len(connected_edges) == len(default_connections) * 2, connected_edges assert len(connected_edges) == len(default_connections) * 2, connected_edges
else: else:
if world.owKeepSimilar[player] and world.owShuffle[player] == 'parallel': if world.owKeepSimilar[player] and world.owShuffle[player] == 'parallel':
for exitname, destname in parallelsimilar_connections: for exitname, destname in parallelsimilar_connections:
connect_two_way(world, exitname, destname, player) connect_two_way(world, exitname, destname, player, connected_edges)
connected_edges.append(exitname)
connected_edges.append(destname) 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 #TODO: Remove, just for testing
for exitname, destname in test_connections: for exitname, destname in test_connections:
connect_two_way(world, exitname, destname, player) connect_two_way(world, exitname, destname, player, connected_edges)
connected_edges.append(exitname)
connected_edges.append(destname)
trimmed_groups = remove_reserved(world, trimmed_groups, connected_edges, player) trimmed_groups = remove_reserved(world, trimmed_groups, connected_edges, player)
groups = reorganize_groups(world, trimmed_groups, player) groups = reorganize_groups(world, trimmed_groups, player)
#all shuffling occurs here # all layout shuffling occurs here
random.shuffle(groups) if world.owShuffle[player] != 'vanilla':
for (forward_edge_sets, back_edge_sets) in groups: # layout shuffle
assert len(forward_edge_sets) == len(back_edge_sets) random.shuffle(groups)
random.shuffle(back_edge_sets) for (forward_edge_sets, back_edge_sets) in groups:
for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets): assert len(forward_edge_sets) == len(back_edge_sets)
assert len(forward_set) == len(back_set) random.shuffle(forward_edge_sets)
for (forward_edge, back_edge) in zip(forward_set, back_set): random.shuffle(back_edge_sets)
connect_two_way(world, forward_edge, back_edge, player) if len(forward_edge_sets) > 0:
connected_edges.append(forward_edge) f = 0
connected_edges.append(back_edge) b = 0
if world.owShuffle[player] == 'parallel': while f < len(forward_edge_sets) and b < len(back_edge_sets):
if forward_edge in parallel_links.keys() or forward_edge in parallel_links.inverse.keys(): forward_set = forward_edge_sets[f]
try: back_set = back_edge_sets[b]
parallel_forward_edge = parallel_links[forward_edge] if forward_edge in parallel_links.keys() else parallel_links.inverse[forward_edge][0] while forward_set[0] in connected_edges:
parallel_back_edge = parallel_links[back_edge] if back_edge in parallel_links.keys() else parallel_links.inverse[back_edge][0] f += 1
connect_two_way(world, parallel_forward_edge, parallel_back_edge, player) if f < len(forward_edge_sets):
connected_edges.append(parallel_forward_edge) forward_set = forward_edge_sets[f]
connected_edges.append(parallel_back_edge) f += 1
except KeyError: while back_set[0] in connected_edges:
# TODO: Figure out why non-parallel edges are getting into parallel groups b += 1
raise KeyError('No parallel edge for edge %d' % back_edge) 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)
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 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)): for o in range(0, len(flute_destinations)):
owslot = flute_destinations[o] owslot = flute_destinations[o]
regions = flute_data[owslot][0] 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) connect_simple(world, 'Flute Spot ' + str(o + 1), regions[0], player)
else: else:
connect_simple(world, 'Flute Spot ' + str(o + 1), regions[1], player) 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) new_ignored.add(exit.connected_region.name)
getIgnored(exit.connected_region.name, base_owid, OWTileRegions[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] new_region = flute_data[owid][0][0]
else: else:
new_region = flute_data[owid][0][1] new_region = flute_data[owid][0][1]
@@ -269,18 +318,15 @@ def link_overworld(world, player):
world.owflutespots[player] = new_spots world.owflutespots[player] = new_spots
connect_flutes(new_spots) connect_flutes(new_spots)
def connect_custom(world, connected_edges, player): def connect_custom(world, connected_edges, player):
if hasattr(world, 'custom_overworld') and world.custom_overworld[player]: if hasattr(world, 'custom_overworld') and world.custom_overworld[player]:
for edgename1, edgename2 in world.custom_overworld[player]: for edgename1, edgename2 in world.custom_overworld[player]:
connect_two_way(world, edgename1, edgename2, player) connect_two_way(world, edgename1, edgename2, player, connected_edges)
connected_edges.append(edgename1)
connected_edges.append(edgename2)
def connect_simple(world, exitname, regionname, player): def connect_simple(world, exitname, regionname, player):
world.get_entrance(exitname, player).connect(world.get_region(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) edge1 = world.get_entrance(edgename1, player)
edge2 = world.get_entrance(edgename2, player) edge2 = world.get_entrance(edgename2, player)
@@ -302,23 +348,41 @@ def connect_two_way(world, edgename1, edgename2, player):
x.dest = y x.dest = y
y.dest = x 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) 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): def remove_reserved(world, groupedlist, connected_edges, player):
new_grouping = {} new_grouping = {}
for group in groupedlist.keys(): for group in groupedlist.keys():
new_grouping[group] = ([], []) new_grouping[group] = ([], [])
for group in groupedlist.keys(): for group in groupedlist.keys():
(std, region, axis, terrain, parallel, count) = group (_, region, _, _, _, _) = group
(forward_edges, back_edges) = groupedlist[group] (forward_edges, back_edges) = groupedlist[group]
# remove edges already connected (thru plando and other forced connections)
for edge in connected_edges: for edge in connected_edges:
forward_edges = list(list(filter((edge).__ne__, i)) for i in forward_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) 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: for edge in parallel_links:
forward_edges = list(list(filter((parallel_links[edge]).__ne__, i)) for i in forward_edges) 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) 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)) forward_edges = list(filter(([]).__ne__, forward_edges))
back_edges = list(filter(([]).__ne__, back_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, exist_back_edges) = new_grouping[group]
exist_forward_edges.extend(forward_edges) exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges) exist_back_edges.extend(back_edges)
@@ -340,11 +402,324 @@ def remove_reserved(world, groupedlist, connected_edges, player):
return new_grouping return new_grouping
def reorganize_groups(world, groups, player): 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': 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 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 = {}
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())
elif world.owShuffle[player] == 'parallel':
if world.owCrossed[player]:
if world.owKeepSimilar[player]:
if world.mode[player] == 'standard':
# 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)
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, parallel, count) = group
new_grouping[(region, axis, terrain, parallel, count)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, parallel, count) = group
(forward_edges, back_edges) = grouping[group]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel, count)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges)
return list(new_grouping.values())
else:
if world.mode[player] == 'standard':
# tuple goes to (A,B,C,D,E,_)
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
(std, region, axis, terrain, parallel, _) = group
new_grouping[(std, region, axis, terrain, parallel)] = ([], [])
for group in grouping.keys():
(std, region, axis, terrain, parallel, _) = group
(forward_edges, back_edges) = grouping[group]
forward_edges = [[i] for l in forward_edges for i in l]
back_edges = [[i] for l in back_edges for i in l]
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, parallel)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(std, region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
return list(new_grouping.values())
else:
# tuple goes to (_,B,C,D,E,_)
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, parallel, _) = group
new_grouping[(region, axis, terrain, parallel)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, parallel, _) = group
(forward_edges, back_edges) = grouping[group]
forward_edges = [[i] for l in forward_edges for i in l]
back_edges = [[i] for l in back_edges for i in l]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
return list(new_grouping.values())
elif world.owShuffle[player] == 'vanilla' and world.owCrossed[player]:
if world.owKeepSimilar[player]: if world.owKeepSimilar[player]:
if world.mode[player] == 'standard': if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,_,F) # tuple goes to (A,B,C,D,_,F)
for grouping in (groups,): for grouping in (groups,):
new_grouping = {} new_grouping = {}
@@ -362,7 +737,7 @@ def reorganize_groups(world, groups, player):
return list(new_grouping.values()) return list(new_grouping.values())
else: else:
#tuple goes to (_,B,C,D,_,F) # tuple goes to (_,B,C,D,_,F)
for grouping in (groups,): for grouping in (groups,):
new_grouping = {} new_grouping = {}
@@ -381,7 +756,7 @@ def reorganize_groups(world, groups, player):
return list(new_grouping.values()) return list(new_grouping.values())
else: else:
if world.mode[player] == 'standard': if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,_,_) # tuple goes to (A,B,C,D,_,_)
for grouping in (groups,): for grouping in (groups,):
new_grouping = {} new_grouping = {}
@@ -402,7 +777,7 @@ def reorganize_groups(world, groups, player):
return list(new_grouping.values()) return list(new_grouping.values())
else: else:
#tuple goes to (_,B,C,D,_,_) # tuple goes to (_,B,C,D,_,_)
for grouping in (groups,): for grouping in (groups,):
new_grouping = {} new_grouping = {}
@@ -421,82 +796,14 @@ def reorganize_groups(world, groups, player):
exist_back_edges.extend(back_edges) exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain)] = (exist_forward_edges, exist_back_edges) new_grouping[(region, axis, terrain)] = (exist_forward_edges, exist_back_edges)
return list(new_grouping.values())
elif world.owShuffle[player] == 'parallel':
#predefined shuffle groups get reorganized here
if world.owKeepSimilar[player]:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,E,F)
for grouping in (groups,):
return list(grouping.values())
else:
#tuple goes to (_,B,C,D,E,F)
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, parallel, count) = group
new_grouping[(region, axis, terrain, parallel, count)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, parallel, count) = group
(forward_edges, back_edges) = grouping[group]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel, count)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges)
return list(new_grouping.values())
else:
if world.mode[player] == 'standard':
#tuple stays (A,B,C,D,E,_)
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
(std, region, axis, terrain, parallel, _) = group
new_grouping[(std, region, axis, terrain, parallel)] = ([], [])
for group in grouping.keys():
(std, region, axis, terrain, parallel, _) = group
(forward_edges, back_edges) = grouping[group]
forward_edges = [[i] for l in forward_edges for i in l]
back_edges = [[i] for l in back_edges for i in l]
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, parallel)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(std, region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
return list(new_grouping.values())
else:
#tuple goes to (_,B,C,D,E,_)
for grouping in (groups,):
new_grouping = {}
for group in grouping.keys():
(_, region, axis, terrain, parallel, _) = group
new_grouping[(region, axis, terrain, parallel)] = ([], [])
for group in grouping.keys():
(_, region, axis, terrain, parallel, _) = group
(forward_edges, back_edges) = grouping[group]
forward_edges = [[i] for l in forward_edges for i in l]
back_edges = [[i] for l in back_edges for i in l]
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, parallel)]
exist_forward_edges.extend(forward_edges)
exist_back_edges.extend(back_edges)
new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
return list(new_grouping.values()) return list(new_grouping.values())
else: else:
raise NotImplementedError('Shuffling not supported yet') raise NotImplementedError('Shuffling not supported yet')
def create_flute_exits(world, player): 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']): 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) \ if (not world.owMixed[player] and region.type == RegionType.LightWorld) \
or (world.owSwap[player] == 'mixed' and region.type in [RegionType.LightWorld, RegionType.DarkWorld] \ 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])): and (region.name not in world.owswaps[player][1] or region.name in world.owswaps[player][2])):
exitname = 'Flute From ' + region.name exitname = 'Flute From ' + region.name
exit = Entrance(region.player, exitname, region) exit = Entrance(region.player, exitname, region)
@@ -506,7 +813,7 @@ def create_flute_exits(world, player):
world.initialize_regions() world.initialize_regions()
def update_world_regions(world, player): def update_world_regions(world, player):
if world.owSwap[player] == 'mixed': if world.owMixed[player]:
for name in world.owswaps[player][1]: for name in world.owswaps[player][1]:
world.get_region(name, player).type = RegionType.DarkWorld world.get_region(name, player).type = RegionType.DarkWorld
for name in world.owswaps[player][2]: for name in world.owswaps[player][2]:
@@ -1110,9 +1417,8 @@ ow_connections = {
} }
parallelsimilar_connections = [('Maze Race ES', 'Kakariko Suburb WS'), parallelsimilar_connections = [('Maze Race ES', 'Kakariko Suburb WS'),
('Dig Game EC', 'Frog WC'), ('Dig Game EC', 'Frog WC')
('Dig Game ES', 'Frog WS') ]
]
# non shuffled overworld # non shuffled overworld
default_connections = [#('Lost Woods NW', 'Master Sword Meadow SC'), default_connections = [#('Lost Woods NW', 'Master Sword Meadow SC'),

View File

@@ -66,19 +66,9 @@ OW Transitions are shuffled, but both worlds will have a matching layout.
OW Transitions are shuffled within each world separately. OW Transitions are shuffled within each world separately.
## Overworld Tile Swap (--ow_swap) ## Crossed (--ow_crossed)
### Vanilla This allows OW connections to be shuffled cross-world.
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.
## Visual Representation of Main OW Shuffle Settings ## 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 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) ## 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. 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) 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 --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 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> --ow_fluteshuffle <mode>
``` ```

137
Rom.py
View File

@@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = 'cc8fc59caa0bbe6d26ac64b9d2893709' RANDOMIZERBASEHASH = '99f3f57ab2c9449172cade4927a462d6'
class JsonRom(object): class JsonRom(object):
@@ -612,71 +612,20 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
if world.pot_contents[player]: if world.pot_contents[player]:
write_pots_to_rom(rom, 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 # patch flute spots
owFlags = 0
if world.owFluteShuffle[player] == 'vanilla': if world.owFluteShuffle[player] == 'vanilla':
flute_spots = default_flute_connections flute_spots = default_flute_connections
else: else:
flute_spots = world.owflutespots[player] flute_spots = world.owflutespots[player]
owFlags |= 0x100
for o in range(0, len(flute_spots)): for o in range(0, len(flute_spots)):
owslot = flute_spots[o] owslot = flute_spots[o]
offset = 0 offset = 0
data = flute_data[owslot] 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 offset = 0x40
write_int16(rom, snes_to_pc(0x02E849 + (o * 2)), data[1] + offset) # owid 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(0x0AB793 + o), data[11] & 0xff) # Y low byte
rom.write_byte(snes_to_pc(0x0AB79B + o), data[11] // 0x100) # Y high 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 # patch entrance/exits/holes
for region in world.regions: 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']: if world.shuffle[player] in ['insanity', 'madness_legacy', 'insanity_legacy']:
entrances_to_hint.update(InsanityEntrances) entrances_to_hint.update(InsanityEntrances)
if world.shuffle_ganon: 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'}) entrances_to_hint.update({'Inverted Pyramid Entrance': 'The extra castle passage'})
else: else:
entrances_to_hint.update({'Pyramid Entrance': 'The pyramid ledge'}) 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 tt[hint_locations.pop(0)] = this_hint
# Adding a guaranteed hint for the Flute in overworld shuffle. # 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) this_location = world.find_items_not_key_only('Ocarina', player)
if this_location: if this_location:
this_hint = this_location[0].item.hint_text + ' can be found ' + hint_text(this_location[0]) + '.' 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. # 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() 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') items_to_hint.remove('Ocarina')
if world.keyshuffle[player]: if world.keyshuffle[player]:
items_to_hint.extend(SmallKeys) items_to_hint.extend(SmallKeys)
@@ -2264,7 +2261,7 @@ def write_strings(rom, world, player, team):
random.shuffle(items_to_hint) random.shuffle(items_to_hint)
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 8 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 += 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: while hint_count > 0:
this_item = items_to_hint.pop(0) this_item = items_to_hint.pop(0)
this_location = world.find_items_not_key_only(this_item, player) 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: if world.doorShuffle[player] == 'vanilla' or world.intensity[player] < 3:
write_int16(rom, 0x15AEE + 2*0x38, 0x00E0) write_int16(rom, 0x15AEE + 2*0x38, 0x00E0)
write_int16(rom, 0x15AEE + 2*0x25, 0x000C) 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']: if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple']:
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01]) # mountain cave starts on OW 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_byte(snes_to_pc(0x02D9B8), 0x12)
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00]) #indicates the overworld door being used for the single entrance spawn point rom.write_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 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(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_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_byte(0x180089, 0x01) # open TR after exit
rom.write_bytes(0x0086E, [0x5C, 0x00, 0xA0, 0xA1]) # TR tail rom.write_bytes(0x0086E, [0x5C, 0x00, 0xA0, 0xA1]) # TR tail
if world.shuffle[player] in ['vanilla']: if world.shuffle[player] in ['vanilla']:
world.fix_trock_doors[player] = True 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 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 write_int16(rom, 0x15AEE + 2 * 0x06, 0x0020) # post aga hyrule castle spawn
rom.write_byte(0x15B8C + 0x06, 0x1B) rom.write_byte(0x15B8C + 0x06, 0x1B)
write_int16(rom, 0x15BDB + 2 * 0x06, 0x00AE) 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, 0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door
write_int16(rom, 0xDBA71 + 2 * 0x35, 0x011C) 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 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']: if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
rom.write_byte(0x15B8C, 0x6C) # exit links at bomb shop area 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 + 0x00, 0x53) # switch bomb shop and links house
rom.write_byte(0xDBB73 + 0x52, 0x01) 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 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 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(0x1BC3DF), [0xD8, 0xD1]) # add warp under rock
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF]) # 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 rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82]) # add warp under rock
# apply inverted map changes # apply inverted map changes

View File

@@ -844,7 +844,7 @@ def ow_rules(world, player):
else: else:
set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) set_rule(world.get_entrance('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 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 Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pedestal Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Lost Woods 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 Forgotten (Middle) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Front Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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)) set_rule(world.get_entrance('Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dark Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark Lumberjack Mirror Spot', player), lambda state: state.has_Mirror(player))
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('West Death Mountain (Top) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Spectacle Rock Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Spectacle Rock Mirror Spot', player), lambda state: state.has_Mirror(player))
else: 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('Bubble Boy Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('West Dark Death Mountain (Bottom) Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 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('East Death Mountain (Top East) Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mimic Cave Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 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)) 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 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)) set_rule(world.get_entrance('TR Pegs Teleporter', player), lambda state: state.has('Hammer', player))
else: 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 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)) 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 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 Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Mountain Entry Entrance Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bumper Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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)) set_rule(world.get_entrance('Zora Waterfall Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Catfish Mirror Spot', player), lambda state: state.has_Mirror(player)) 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 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 Top Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lost Woods Pass East Bottom Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 (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 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)) set_rule(world.get_entrance('Kakariko Fortune Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Outcast Fortune Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Outcast Fortune Mirror Spot', player), lambda state: state.has_Mirror(player))
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)) set_rule(world.get_entrance('Kakariko Pond Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Outcast Pond Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Outcast Pond Mirror Spot', player), lambda state: state.has_Mirror(player))
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('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)) set_rule(world.get_entrance('Bonk Rock Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dark Chapel Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark Chapel Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Chapel Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark 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('Graveyard Ledge Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player)) set_rule(world.get_entrance('Kings Grave Mirror Spot', player), lambda state: state.has_Pearl(player) and state.has_Mirror(player))
else: 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 Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Graveyard Grave Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('River Bend East Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('River Bend East Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Qirn Jump Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Qirn Jump Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Qirn Jump East Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Potion Shop Northeast Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Potion Shop Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dark Witch Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark Witch Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Witch Northeast Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Zora Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Zora Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Catfish Approach Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Catfish Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Catfish Approach Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Grass Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Kakariko Grass Mirror Spot', player), lambda state: state.has_Mirror(player))
else: 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('Village of Outcasts Southwest Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hammer House Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Forgotton Forest Fence Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Forgotton Forest Fence Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Shield Shop Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Shield Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
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 Hole', player), lambda state: False)
set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False) set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False)
set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player]) set_rule(world.get_entrance('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('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)) 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 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 Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Wooden Bridge West Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 East Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Broken Bridge Northeast Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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)) set_rule(world.get_entrance('Eastern Palace Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Palace of Darkness Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Palace of Darkness Mirror Spot', player), lambda state: state.has_Mirror(player))
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 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('Blacksmith Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Bat Cave Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hammer Pegs Entry Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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)) set_rule(world.get_entrance('Sand Dunes Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dark Dunes Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark Dunes Mirror Spot', player), lambda state: state.has_Mirror(player))
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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Maze Race Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Maze Race Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dig Game Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dig Game Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dig Game Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Kakariko Suburb South Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Kakariko Suburb South Mirror Spot', player), lambda state: state.has_Mirror(player))
else: 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('Frog Prison Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Archery Game Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Flute Boy Pass Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Flute Boy Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Stumpy Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Stumpy Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Stumpy Pass Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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)) set_rule(world.get_entrance('Central Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dark Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark Bonk Rocks Mirror Spot', player), lambda state: state.has_Mirror(player))
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)) set_rule(world.get_entrance('Links House Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Big Bomb Shop Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Big Bomb Shop Mirror Spot', player), lambda state: state.has_Mirror(player))
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 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('Stone Bridge South Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Hobo Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player)) set_rule(world.get_entrance('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('Hammer Bridge South Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Dark Hobo Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Dark 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)) set_rule(world.get_entrance('Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dark Tree Line Mirror Spot', player), lambda state: state.has_Mirror(player)) 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('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 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: else:
set_rule(world.get_entrance('Darkness Nook Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Darkness Nook Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('East Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) set_rule(world.get_entrance('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('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 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 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)) 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('Cave 45 Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Flute Boy Entry Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Flute Boy Entry Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Stumpy Approach Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Stumpy Approach Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Stumpy Bush Entry Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('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 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('C Whirlpool Outer Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('South Hyrule Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player)) # bunny cannot use hammer set_rule(world.get_entrance('South 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 Dark World Teleporter', player), lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and state.has_Pearl(player))
set_rule(world.get_entrance('South Teleporter Cliff Ledge Drop', player), lambda state: state.can_lift_rocks(player) and state.has_Pearl(player)) set_rule(world.get_entrance('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)) set_rule(world.get_entrance('Statues Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Hype Cave Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Hype Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
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 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 Northeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Lake Hylia Island Mirror Spot', player), lambda state: state.has_Mirror(player) and state.has_Pearl(player) and state.has('Flippers', player)) set_rule(world.get_entrance('Lake Hylia 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 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)) 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)) set_rule(world.get_entrance('Ice Cave Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Shopping Mall Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Shopping Mall Mirror Spot', player), lambda state: state.has_Mirror(player))
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 Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Desert Pass Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Desert Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
else: 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 Southeast Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Swamp Nook Pegs Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Swamp 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)) set_rule(world.get_entrance('Dam Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Swamp Mirror Spot', player), lambda state: state.has_Mirror(player)) 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)) set_rule(world.get_entrance('South Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Dark South Pass Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Dark South Pass Mirror Spot', player), lambda state: state.has_Mirror(player))
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)) set_rule(world.get_entrance('Octoballoon Mirror Spot', player), lambda state: state.has_Mirror(player))
else: else:
set_rule(world.get_entrance('Bomber Corner Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Bomber Corner Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -2050,7 +2050,7 @@ def set_inverted_big_bomb_rules(world, player):
else: else:
raise Exception('No logic found for routing from %s to the pyramid.' % bombshop_entrance.name) 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 add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: False) #temp disable progression until routing to Pyramid get be guaranteed

View File

@@ -341,7 +341,7 @@ OWNewDestination:
sep #$30 : lda OWOppSlotOffset,y : !add $04 : asl : and #$7f : sta $700 sep #$30 : lda OWOppSlotOffset,y : !add $04 : asl : and #$7f : sta $700
; crossed OW shuffle ; 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 ldx $05 : lda.l OWTileWorldAssoc,x : sta.l $7ef3ca ; change world
; toggle bunny mode ; toggle bunny mode

Binary file not shown.

View File

@@ -3,13 +3,15 @@
vanilla: 0 vanilla: 0
parallel: 2 parallel: 2
full: 2 full: 2
overworld_crossed:
on: 1
off: 1
overworld_keepsimilar: overworld_keepsimilar:
on: 1 on: 1
off: 1 off: 1
overworld_swap: overworld_mixed:
vanilla: 0 on: 1
mixed: 2 off: 1
crossed: 2
flute_shuffle: flute_shuffle:
vanilla: 0 vanilla: 0
balanced: 1 balanced: 1

View File

@@ -116,17 +116,18 @@
"full" "full"
] ]
}, },
"ow_swap": { "ow_crossed": {
"choices": [ "action": "store_true",
"vanilla", "type": "bool"
"mixed",
"crossed"
]
}, },
"ow_keepsimilar": { "ow_keepsimilar": {
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"
}, },
"ow_mixed": {
"action": "store_true",
"type": "bool"
},
"ow_fluteshuffle": { "ow_fluteshuffle": {
"choices": [ "choices": [
"vanilla", "vanilla",

View File

@@ -201,22 +201,19 @@
"Full: Overworld transitions are shuffled, but both worlds", "Full: Overworld transitions are shuffled, but both worlds",
" will have an independent map shape." " will have an independent map shape."
], ],
"ow_swap": [ "ow_crossed": [
"This swaps the tiles of the overworld from one world to the other.", "This allows cross-world connections to occur on the overworld." ],
"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_keepsimilar": [ "ow_keepsimilar": [
"This keeps similar edge transitions together. ie. the two west edges on", "This keeps similar edge transitions together. ie. the two west edges on",
"Potion Shop will be paired with another similar pair." ], "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": [ "ow_fluteshuffle": [
"This randomizes the flute spot destinations.", "This randomizes the flute spot destinations.",
"Vanilla: All flute spots remain unchanged.", "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." "Random: New flute spots will be generated with minimal bias."
], ],
"door_shuffle": [ "door_shuffle": [

View File

@@ -117,12 +117,9 @@
"randomizer.overworld.overworldshuffle.parallel": "Parallel", "randomizer.overworld.overworldshuffle.parallel": "Parallel",
"randomizer.overworld.overworldshuffle.full": "Full", "randomizer.overworld.overworldshuffle.full": "Full",
"randomizer.overworld.overworldswap": "Tile Swap", "randomizer.overworld.crossed": "Crossed",
"randomizer.overworld.overworldswap.vanilla": "Vanilla",
"randomizer.overworld.overworldswap.mixed": "Mixed",
"randomizer.overworld.overworldswap.crossed": "Crossed",
"randomizer.overworld.keepsimilar": "Keep Similar Edges Together", "randomizer.overworld.keepsimilar": "Keep Similar Edges Together",
"randomizer.overworld.mixed": "Mixed",
"randomizer.overworld.overworldflute": "Flute Shuffle", "randomizer.overworld.overworldflute": "Flute Shuffle",
"randomizer.overworld.overworldflute.vanilla": "Vanilla", "randomizer.overworld.overworldflute.vanilla": "Vanilla",

View File

@@ -9,15 +9,6 @@
"full" "full"
] ]
}, },
"overworldswap": {
"type": "selectbox",
"default": "mixed",
"options": [
"vanilla",
"mixed",
"crossed"
]
},
"overworldflute": { "overworldflute": {
"type": "selectbox", "type": "selectbox",
"default": "vanilla", "default": "vanilla",
@@ -29,6 +20,14 @@
} }
}, },
"rightOverworldFrame": { "rightOverworldFrame": {
"crossed": {
"type": "checkbox",
"default": false
},
"mixed": {
"type": "checkbox",
"default": true
},
"keepsimilar": { "keepsimilar": {
"type": "checkbox", "type": "checkbox",
"default": true "default": true

View File

@@ -76,8 +76,9 @@ SETTINGSTOPROCESS = {
}, },
"overworld": { "overworld": {
"overworldshuffle": "ow_shuffle", "overworldshuffle": "ow_shuffle",
"overworldswap": "ow_swap", "crossed": "ow_crossed",
"keepsimilar": "ow_keepsimilar", "keepsimilar": "ow_keepsimilar",
"mixed": "ow_mixed",
"overworldflute": "ow_fluteshuffle" "overworldflute": "ow_fluteshuffle"
}, },
"entrance": { "entrance": {

View File

@@ -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 source.gui.widgets as widgets
import json import json
import os import os
@@ -16,12 +16,10 @@ def overworld_page(parent):
# Load Overworld Shuffle option widgets as defined by JSON file # Load Overworld Shuffle option widgets as defined by JSON file
# Defns include frame name, widget type, widget options, widget placement attributes # Defns include frame name, widget type, widget options, widget placement attributes
# These get split left & right # These get split left & right
self.frames["widgets"] = Frame(self) self.frames["leftOverworldFrame"] = Frame(self)
self.frames["leftOverworldFrame"] = Frame(self.frames["widgets"]) self.frames["rightOverworldFrame"] = Frame(self)
self.frames["rightOverworldFrame"] = Frame(self.frames["widgets"]) self.frames["leftOverworldFrame"].pack(side=LEFT, anchor=NW)
self.frames["widgets"].pack(fill=X) self.frames["rightOverworldFrame"].pack(anchor=NW)
self.frames["leftOverworldFrame"].pack(side=LEFT)
self.frames["rightOverworldFrame"].pack(side=LEFT, anchor=NW)
with open(os.path.join("resources","app","gui","randomize","overworld","widgets.json")) as overworldWidgets: with open(os.path.join("resources","app","gui","randomize","overworld","widgets.json")) as overworldWidgets:
myDict = json.load(overworldWidgets) myDict = json.load(overworldWidgets)
@@ -29,8 +27,8 @@ def overworld_page(parent):
dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename]) dictWidgets = widgets.make_widgets_from_dict(self, theseWidgets, self.frames[framename])
for key in dictWidgets: for key in dictWidgets:
self.widgets[key] = dictWidgets[key] self.widgets[key] = dictWidgets[key]
if key == "rightOverworldFrame": if framename == "rightOverworldFrame":
self.widgets[key].pack(anchor=E) self.widgets[key].pack(side=LEFT)
else: else:
self.widgets[key].pack(anchor=E) self.widgets[key].pack(anchor=E)