Merge branch 'OverworldShuffleDev' into OverworldShuffle

This commit is contained in:
codemann8
2022-01-03 18:10:42 -06:00
16 changed files with 188 additions and 154 deletions

View File

@@ -299,6 +299,9 @@ class World(object):
return edge return edge
return None return None
def is_tile_swapped(self, owid, player):
return (self.mode[player] == 'inverted') != (owid in self.owswaps[player][0] and self.owMixed[player])
def check_for_door(self, doorname, player): def check_for_door(self, doorname, player):
if isinstance(doorname, Door): if isinstance(doorname, Door):
return doorname return doorname
@@ -2831,6 +2834,12 @@ class Spoiler(object):
'triforcepool': self.world.treasure_hunt_total, 'triforcepool': self.world.treasure_hunt_total,
'code': {p: Settings.make_code(self.world, p) for p in range(1, self.world.players + 1)} 'code': {p: Settings.make_code(self.world, p) for p in range(1, self.world.players + 1)}
} }
for p in range(1, self.world.players + 1):
from ItemList import set_default_triforce
if self.world.custom and p in self.world.customitemarray:
self.metadata['triforcegoal'][p], self.metadata['triforcepool'][p] = set_default_triforce(self.metadata['goal'][p], self.world.customitemarray[p]["triforcepiecesgoal"], self.world.customitemarray[p]["triforcepieces"])
else:
self.metadata['triforcegoal'][p], self.metadata['triforcepool'][p] = set_default_triforce(self.metadata['goal'][p], 0, 0)
def parse_data(self): def parse_data(self):
self.medallions = OrderedDict() self.medallions = OrderedDict()
@@ -2965,7 +2974,7 @@ class Spoiler(object):
outfile.write('Retro:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['retro'][player] else 'No')) outfile.write('Retro:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['retro'][player] else 'No'))
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player]) outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
outfile.write('Goal:'.ljust(line_width) + '%s\n' % self.metadata['goal'][player]) outfile.write('Goal:'.ljust(line_width) + '%s\n' % self.metadata['goal'][player])
if self.metadata['goal'][player] == 'triforcehunt': if self.metadata['goal'][player] in ['triforcehunt', 'trinity']:
outfile.write('Triforce Pieces Required:'.ljust(line_width) + '%s\n' % self.metadata['triforcegoal'][player]) outfile.write('Triforce Pieces Required:'.ljust(line_width) + '%s\n' % self.metadata['triforcegoal'][player])
outfile.write('Triforce Pieces Total:'.ljust(line_width) + '%s\n' % self.metadata['triforcepool'][player]) outfile.write('Triforce Pieces Total:'.ljust(line_width) + '%s\n' % self.metadata['triforcepool'][player])
outfile.write('Crystals Required for GT:'.ljust(line_width) + '%s\n' % str(self.world.crystals_gt_orig[player])) outfile.write('Crystals Required for GT:'.ljust(line_width) + '%s\n' % str(self.world.crystals_gt_orig[player]))
@@ -2986,6 +2995,7 @@ class Spoiler(object):
if self.metadata['shuffle'][player] != 'vanilla': if self.metadata['shuffle'][player] != 'vanilla':
outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shuffleganon'][player] else 'No')) outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shuffleganon'][player] else 'No'))
outfile.write('Shuffle Links:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shufflelinks'][player] else 'No')) outfile.write('Shuffle Links:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shufflelinks'][player] else 'No'))
if self.metadata['goal'][player] != 'trinity':
outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No')) outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No'))
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])
if self.metadata['door_shuffle'][player] != 'vanilla': if self.metadata['door_shuffle'][player] != 'vanilla':
@@ -3212,7 +3222,7 @@ world_mode = {"open": 0, "standard": 1, "inverted": 2}
sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3} sword_mode = {"random": 0, "assured": 1, "swordless": 2, "vanilla": 3}
# byte 2: GGGD DFFH (goal, diff, item_func, hints) # byte 2: GGGD DFFH (goal, diff, item_func, hints)
goal_mode = {"ganon": 0, "pedestal": 1, "dungeons": 2, "triforcehunt": 3, "crystals": 4} goal_mode = {"ganon": 0, "pedestal": 1, "dungeons": 2, "triforcehunt": 3, "crystals": 4, "trinity": 5}
diff_mode = {"normal": 0, "hard": 1, "expert": 2} diff_mode = {"normal": 0, "hard": 1, "expert": 2}
func_mode = {"normal": 0, "hard": 1, "expert": 2} func_mode = {"normal": 0, "hard": 1, "expert": 2}

View File

@@ -1,5 +1,10 @@
# Changelog # Changelog
### 0.2.3.6
- Added Trinity goal (8/10 default TF pieces)
- Many improvements to TFH pool allocation
- Fixed some issues with Multiworld generation with Custom Item Pools
### 0.2.3.5 ### 0.2.3.5
- Fixed issue with multiworld generation - Fixed issue with multiworld generation
- Added infinite loop detection - Added infinite loop detection

View File

@@ -89,11 +89,11 @@ def link_doors_main(world, player):
if world.mode[player] == 'standard': if world.mode[player] == 'standard':
world.get_portal('Sanctuary', player).destination = True world.get_portal('Sanctuary', player).destination = True
world.get_portal('Desert East', player).destination = True world.get_portal('Desert East', player).destination = True
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x30, player):
world.get_portal('Desert West', player).destination = True world.get_portal('Desert West', player).destination = True
if (world.mode[player] == 'inverted') == (0x00 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x00, player):
world.get_portal('Skull 2 West', player).destination = True world.get_portal('Skull 2 West', player).destination = True
if (world.mode[player] == 'inverted') == (0x05 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x05, player):
world.get_portal('Turtle Rock Lazy Eyes', player).destination = True world.get_portal('Turtle Rock Lazy Eyes', player).destination = True
world.get_portal('Turtle Rock Eye Bridge', player).destination = True world.get_portal('Turtle Rock Eye Bridge', player).destination = True
else: else:
@@ -1837,7 +1837,7 @@ def find_inaccessible_regions(world, player):
if connect.type is not RegionType.Dungeon or connect.name.endswith(' Portal'): if connect.type is not RegionType.Dungeon or connect.name.endswith(' Portal'):
queue.append(connect) queue.append(connect)
world.inaccessible_regions[player].extend([r.name for r in all_regions if r not in visited_regions and valid_inaccessible_region(r)]) world.inaccessible_regions[player].extend([r.name for r in all_regions if r not in visited_regions and valid_inaccessible_region(r)])
if (world.mode[player] == 'inverted') != (0x1b in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x1b, player):
ledge = world.get_region('Hyrule Castle Ledge', player) ledge = world.get_region('Hyrule Castle Ledge', player)
if any(x for x in ledge.exits if x.connected_region and x.connected_region.name == 'Agahnims Tower Portal'): if any(x for x in ledge.exits if x.connected_region and x.connected_region.name == 'Agahnims Tower Portal'):
world.inaccessible_regions[player].append('Hyrule Castle Ledge') world.inaccessible_regions[player].append('Hyrule Castle Ledge')
@@ -1857,7 +1857,7 @@ def find_accessible_entrances(world, player, builder):
start_regions = ['Links House', 'Sanctuary'] start_regions = ['Links House', 'Sanctuary']
else: else:
start_regions = ['Links House', 'Dark Sanctuary Hint'] start_regions = ['Links House', 'Dark Sanctuary Hint']
if (world.mode[player] == 'inverted') != (0x1b in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x1b, player):
start_regions.append('Hyrule Castle Ledge') start_regions.append('Hyrule Castle Ledge')
regs = convert_regions(start_regions, world, player) regs = convert_regions(start_regions, world, player)
visited_regions = set() visited_regions = set()
@@ -1873,7 +1873,7 @@ def find_accessible_entrances(world, player, builder):
while len(queue) > 0: while len(queue) > 0:
next_region = queue.popleft() next_region = queue.popleft()
visited_regions.add(next_region) visited_regions.add(next_region)
if (world.mode[player] == 'inverted') != (0x1b in world.owswaps[player][0] and world.owMixed[player]) and next_region.name == 'Tower Agahnim 1': if world.is_tile_swapped(0x1b, player) and next_region.name == 'Tower Agahnim 1':
connect = world.get_region('Hyrule Castle Ledge', player) connect = world.get_region('Hyrule Castle Ledge', player)
if connect not in queue and connect not in visited_regions: if connect not in queue and connect not in visited_regions:
queue.append(connect) queue.append(connect)

View File

@@ -34,7 +34,7 @@ def link_entrances(world, player):
world.owsectors[player] = build_sectors(world, player) world.owsectors[player] = build_sectors(world, player)
# modifications to lists # modifications to lists
if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x1b, player):
drop_connections.append(tuple(('Pyramid Hole', 'Pyramid'))) drop_connections.append(tuple(('Pyramid Hole', 'Pyramid')))
dropexit_connections.append(tuple(('Pyramid Entrance', 'Pyramid Exit'))) dropexit_connections.append(tuple(('Pyramid Entrance', 'Pyramid Exit')))
connect_simple(world, 'Other World S&Q', 'Pyramid Area', player) connect_simple(world, 'Other World S&Q', 'Pyramid Area', player)
@@ -47,7 +47,7 @@ def link_entrances(world, player):
dropexit_connections.append(tuple(('Inverted Pyramid Entrance', 'Pyramid Exit'))) dropexit_connections.append(tuple(('Inverted Pyramid Entrance', 'Pyramid Exit')))
connect_simple(world, 'Other World S&Q', 'Hyrule Castle Ledge', player) connect_simple(world, 'Other World S&Q', 'Hyrule Castle Ledge', player)
if invFlag == (0x03 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x03, player):
connect_simple(world, 'Old Man S&Q', 'Old Man House', player) connect_simple(world, 'Old Man S&Q', 'Old Man House', player)
else: else:
connect_simple(world, 'Old Man S&Q', 'West Dark Death Mountain (Bottom)', player) connect_simple(world, 'Old Man S&Q', 'West Dark Death Mountain (Bottom)', player)
@@ -89,18 +89,16 @@ def link_entrances(world, player):
# inverted entrance mods # inverted entrance mods
ignore_pool = True ignore_pool = True
for owid in swapped_connections.keys(): for owid in swapped_connections.keys():
if invFlag != (owid in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(owid, 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.owMixed[player]) and \ if world.is_tile_swapped(0x03, player) and not world.is_tile_swapped(0x0a, player):
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.owMixed[player]) and \ elif world.is_tile_swapped(0x0a, player) and not world.is_tile_swapped(0x03, player):
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)
ignore_pool = False ignore_pool = False
@@ -144,15 +142,15 @@ def link_entrances(world, player):
Two_Door_Caves_Directional = list() Two_Door_Caves_Directional = list()
Two_Door_Caves = [('Elder House (East)', 'Elder House (West)'), Two_Door_Caves = [('Elder House (East)', 'Elder House (West)'),
('Superbunny Cave (Bottom)', 'Superbunny Cave (Top)')] ('Superbunny Cave (Bottom)', 'Superbunny Cave (Top)')]
if invFlag == (0x0a in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x0a, player):
Two_Door_Caves_Directional.append(tuple({'Bumper Cave (Bottom)', 'Bumper Cave (Top)'})) Two_Door_Caves_Directional.append(tuple({'Bumper Cave (Bottom)', 'Bumper Cave (Top)'}))
else: else:
Two_Door_Caves_Directional.append(tuple({'Old Man Cave (West)', 'Death Mountain Return Cave (West)'})) Two_Door_Caves_Directional.append(tuple({'Old Man Cave (West)', 'Death Mountain Return Cave (West)'}))
if invFlag == (0x05 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x05, player):
Two_Door_Caves_Directional.append(tuple({'Hookshot Cave', 'Hookshot Cave Back Entrance'})) Two_Door_Caves_Directional.append(tuple({'Hookshot Cave', 'Hookshot Cave Back Entrance'}))
else: else:
Two_Door_Caves.append(tuple({'Hookshot Cave', 'Hookshot Cave Back Entrance'})) Two_Door_Caves.append(tuple({'Hookshot Cave', 'Hookshot Cave Back Entrance'}))
if invFlag == (0x28 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x28, player):
Two_Door_Caves.append(tuple({'Two Brothers House (East)', 'Two Brothers House (West)'})) Two_Door_Caves.append(tuple({'Two Brothers House (East)', 'Two Brothers House (West)'}))
else: else:
Two_Door_Caves_Directional.append(tuple({'Two Brothers House (East)', 'Two Brothers House (West)'})) Two_Door_Caves_Directional.append(tuple({'Two Brothers House (East)', 'Two Brothers House (West)'}))
@@ -181,14 +179,14 @@ def link_entrances(world, player):
caves.extend(list(Old_Man_House)) caves.extend(list(Old_Man_House))
caves.extend(list(three_exit_caves)) caves.extend(list(three_exit_caves))
if invFlag == (0x18 in world.owswaps[player][0] and world.owMixed[player]) or invFlag == (0x03 in world.owswaps[player][0] and world.owMixed[player]): # ability to activate flute in LW if (not world.is_tile_swapped(0x18, player)) or (not world.is_tile_swapped(0x03, player)): # ability to activate flute in LW
candidates = [e for e in lw_wdm_entrances if e != 'Old Man House (Bottom)'] candidates = [e for e in lw_wdm_entrances if e != 'Old Man House (Bottom)']
random.shuffle(candidates) random.shuffle(candidates)
old_man_exit = candidates.pop() old_man_exit = candidates.pop()
lw_wdm_entrances.remove(old_man_exit) lw_wdm_entrances.remove(old_man_exit)
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 == (0x0a in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x0a, player):
lw_wdm_entrances.extend(['Old Man Cave (West)', 'Death Mountain Return Cave (West)']) lw_wdm_entrances.extend(['Old Man Cave (West)', 'Death Mountain Return Cave (West)'])
else: else:
lw_wdm_entrances.extend(['Bumper Cave (Bottom)', 'Bumper Cave (Top)']) lw_wdm_entrances.extend(['Bumper Cave (Bottom)', 'Bumper Cave (Top)'])
@@ -213,7 +211,7 @@ def link_entrances(world, 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)
# place old man, bumper cave bottom to DDM entrances not in east bottom # place old man, bumper cave bottom to DDM entrances not in east bottom
if invFlag == (0x0a in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x0a, player):
connect_two_way(world, 'Old Man Cave (West)', 'Old Man Cave Exit (West)', player) connect_two_way(world, 'Old Man Cave (West)', 'Old Man Cave Exit (West)', player)
else: else:
connect_two_way(world, 'Bumper Cave (Bottom)', 'Old Man Cave Exit (West)', player) connect_two_way(world, 'Bumper Cave (Bottom)', 'Old Man Cave Exit (West)', player)
@@ -223,7 +221,7 @@ def link_entrances(world, player):
connect_caves(world, lw_wdm_entrances + lw_edm_entrances, [], caves, player) connect_caves(world, lw_wdm_entrances + lw_edm_entrances, [], caves, player)
else: else:
# place Old Man House in WDM if not swapped # place Old Man House in WDM if not swapped
if invFlag == (0x03 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x03, player):
connect_caves(world, lw_wdm_entrances, [], list(Old_Man_House), player) connect_caves(world, lw_wdm_entrances, [], list(Old_Man_House), player)
else: else:
connect_caves(world, lw_edm_entrances, [], list(Old_Man_House), player) connect_caves(world, lw_edm_entrances, [], list(Old_Man_House), player)
@@ -258,7 +256,7 @@ def link_entrances(world, player):
# place bomb shop, has limited options # place bomb shop, has limited options
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
bomb_shop = random.choice(bomb_shop_doors) bomb_shop = random.choice(bomb_shop_doors)
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
@@ -303,7 +301,7 @@ def link_entrances(world, player):
# place bomb shop, has limited options # place bomb shop, has limited options
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
bomb_shop = random.choice(bomb_shop_doors) bomb_shop = random.choice(bomb_shop_doors)
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
@@ -360,7 +358,7 @@ def link_entrances(world, player):
# place bomb shop, has limited options # place bomb shop, has limited options
bomb_shop_doors = [e for e in entrance_pool if e not in list(zip(*drop_connections + dropexit_connections))[0]] bomb_shop_doors = [e for e in entrance_pool if e not in list(zip(*drop_connections + dropexit_connections))[0]]
if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in bomb_shop_doors if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in bomb_shop_doors if e not in ['Pyramid Fairy']]
bomb_shop = random.choice(bomb_shop_doors) bomb_shop = random.choice(bomb_shop_doors)
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
@@ -462,7 +460,7 @@ def link_entrances(world, player):
# place bomb shop, has limited options # place bomb shop, has limited options
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
bomb_shop = random.choice(bomb_shop_doors) bomb_shop = random.choice(bomb_shop_doors)
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
@@ -516,7 +514,7 @@ def link_entrances(world, player):
# place bomb shop, has limited options # place bomb shop, has limited options
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
bomb_shop = random.choice(bomb_shop_doors) bomb_shop = random.choice(bomb_shop_doors)
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
@@ -565,7 +563,7 @@ def link_entrances(world, player):
# place bomb shop, has limited options # place bomb shop, has limited options
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
bomb_shop = random.choice(bomb_shop_doors) bomb_shop = random.choice(bomb_shop_doors)
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
@@ -604,11 +602,11 @@ 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.owMixed[player]) else 'Inverted Pyramid Entrance', 'Pyramid Exit', player) connect_two_way(world, 'Pyramid Entrance' if not world.is_tile_swapped(0x1b, player) else 'Inverted Pyramid Entrance', 'Pyramid Exit', player)
connect_entrance(world, 'Pyramid Hole' if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]) else 'Inverted Pyramid Hole', 'Pyramid', player) connect_entrance(world, 'Pyramid Hole' if not world.is_tile_swapped(0x1b, player) else 'Inverted Pyramid Hole', 'Pyramid', player)
else: else:
caves.extend(['Ganons Tower Exit', 'Pyramid Exit']) caves.extend(['Ganons Tower Exit', 'Pyramid Exit'])
hole_entrances.append('Pyramid Hole' if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]) else 'Inverted Pyramid Hole') hole_entrances.append('Pyramid Hole' if not world.is_tile_swapped(0x1b, player) else 'Inverted Pyramid Hole')
hole_targets.append('Pyramid') hole_targets.append('Pyramid')
# shuffle holes # shuffle holes
@@ -648,7 +646,7 @@ def link_entrances(world, player):
# place bomb shop, has limited options # place bomb shop, has limited options
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
random.shuffle(bomb_shop_doors) random.shuffle(bomb_shop_doors)
bomb_shop = bomb_shop_doors.pop() bomb_shop = bomb_shop_doors.pop()
@@ -693,7 +691,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 == (0x1b in world.owswaps[player][0] and world.owMixed[player]) else 'Inverted Pyramid Hole', player).connected_region.name != 'Pyramid': if world.get_entrance('Pyramid Hole' if not world.is_tile_swapped(0x1b, 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
@@ -1074,7 +1072,7 @@ def scramble_holes(world, player):
hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance')) hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance'))
if world.shuffle_ganon: if world.shuffle_ganon:
hole_entrances.append(('Pyramid Entrance', 'Pyramid Hole') if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]) else ('Inverted Pyramid Entrance', 'Inverted Pyramid Hole')) hole_entrances.append(('Pyramid Entrance', 'Pyramid Hole') if not world.is_tile_swapped(0x1b, player) else ('Inverted Pyramid Entrance', 'Inverted Pyramid Hole'))
hole_targets.append(('Pyramid Exit', 'Pyramid')) hole_targets.append(('Pyramid Exit', 'Pyramid'))
# shuffle sanctuary hole in same world as other HC entrances # shuffle sanctuary hole in same world as other HC entrances
@@ -1099,11 +1097,11 @@ def scramble_holes(world, player):
else: else:
# checks if drop candidates exist in LW # checks if drop candidates exist in LW
drop_owids = [ 0x00, 0x02, 0x13, 0x15, 0x18, 0x1b, 0x22 ] drop_owids = [ 0x00, 0x02, 0x13, 0x15, 0x18, 0x1b, 0x22 ]
hc_in_lw = any([invFlag == (owid in world.owswaps[player][0] and world.owMixed[player]) for owid in drop_owids]) hc_in_lw = any([not world.is_tile_swapped(owid, player) for owid in drop_owids])
candidate_drops = list() candidate_drops = list()
for door, drop in hole_entrances: for door, drop in hole_entrances:
if hc_in_lw == (drop_owid_map[door][1] == (invFlag == (drop_owid_map[door][0] in world.owswaps[player][0] and world.owMixed[player]))): if hc_in_lw == (drop_owid_map[door][1] == (not world.is_tile_swapped(drop_owid_map[door][0], player))):
candidate_drops.append(tuple((door, drop))) candidate_drops.append(tuple((door, drop)))
random.shuffle(candidate_drops) random.shuffle(candidate_drops)
@@ -1117,7 +1115,7 @@ def scramble_holes(world, player):
# place pyramid hole # place pyramid hole
if not world.shuffle_ganon: if not world.shuffle_ganon:
exit, target = ('Pyramid Exit', 'Pyramid') exit, target = ('Pyramid Exit', 'Pyramid')
if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x1b, player):
connect_two_way(world, 'Pyramid Entrance', exit, player) connect_two_way(world, 'Pyramid Entrance', exit, player)
connect_entrance(world, 'Pyramid Hole', target, player) connect_entrance(world, 'Pyramid Hole', target, player)
else: else:
@@ -1183,16 +1181,16 @@ def simple_shuffle_dungeons(world, player):
# checks if drop candidates exist in LW # checks if drop candidates exist in LW
drop_owids = [ 0x00, 0x02, 0x13, 0x15, 0x18, 0x1b, 0x22 ] drop_owids = [ 0x00, 0x02, 0x13, 0x15, 0x18, 0x1b, 0x22 ]
drops_in_light_world = any([invFlag == (owid in world.owswaps[player][0] and world.owMixed[player]) for owid in drop_owids]) drops_in_light_world = any([not world.is_tile_swapped(owid, player) for owid in drop_owids])
# placing HC in guaranteed same-world as available dropdowns # placing HC in guaranteed same-world as available dropdowns
if not drops_in_light_world or not invFlag: if not drops_in_light_world or not invFlag:
candidate_dungeons = list() candidate_dungeons = list()
for d in multi_dungeons: for d in multi_dungeons:
if not drops_in_light_world and dungeon_owid_map[d][1] == (invFlag != (dungeon_owid_map[d][0] in world.owswaps[player][0] and world.owMixed[player])): if not drops_in_light_world and dungeon_owid_map[d][1] == world.is_tile_swapped(dungeon_owid_map[d][0], player):
# only adding DW candidates # only adding DW candidates
candidate_dungeons.append(d) candidate_dungeons.append(d)
elif not invFlag and dungeon_owid_map[d][1] == (invFlag == (dungeon_owid_map[d][0] in world.owswaps[player][0] and world.owMixed[player])): elif not invFlag and dungeon_owid_map[d][1] == (not world.is_tile_swapped(dungeon_owid_map[d][0], player)):
# only adding LW candidates # only adding LW candidates
candidate_dungeons.append(d) candidate_dungeons.append(d)
random.shuffle(candidate_dungeons) random.shuffle(candidate_dungeons)
@@ -1218,7 +1216,7 @@ def simple_shuffle_dungeons(world, player):
elif hc_target == 'Turtle Rock': elif hc_target == 'Turtle Rock':
connect_two_way(world, 'Turtle Rock', 'Hyrule Castle Exit (South)', player) connect_two_way(world, 'Turtle Rock', 'Hyrule Castle Exit (South)', player)
connect_two_way(world, 'Dark Death Mountain Ledge (West)', 'Hyrule Castle Exit (West)', player) connect_two_way(world, 'Dark Death Mountain Ledge (West)', 'Hyrule Castle Exit (West)', player)
if invFlag == (0x45 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x45, player):
connect_two_way(world, 'Turtle Rock Isolated Ledge Entrance', 'Hyrule Castle Exit (East)', player) connect_two_way(world, 'Turtle Rock Isolated Ledge Entrance', 'Hyrule Castle Exit (East)', player)
connect_two_way(world, 'Dark Death Mountain Ledge (East)', at_door, player) connect_two_way(world, 'Dark Death Mountain Ledge (East)', at_door, player)
else: else:
@@ -1302,7 +1300,7 @@ def full_shuffle_dungeons(world, Dungeon_Exits, player):
lw_entrances = list() lw_entrances = list()
dw_entrances = list() dw_entrances = list()
for owid in dungeon_owid_map.keys(): for owid in dungeon_owid_map.keys():
if dungeon_owid_map[owid][1] == (invFlag == (owid in world.owswaps[player][0] and world.owMixed[player])): if dungeon_owid_map[owid][1] == (not world.is_tile_swapped(owid, player)):
lw_entrances.extend([e for e in dungeon_owid_map[owid][0] if e in entrance_pool]) lw_entrances.extend([e for e in dungeon_owid_map[owid][0] if e in entrance_pool])
else: else:
dw_entrances.extend([e for e in dungeon_owid_map[owid][0] if e in entrance_pool]) dw_entrances.extend([e for e in dungeon_owid_map[owid][0] if e in entrance_pool])
@@ -1315,7 +1313,7 @@ def full_shuffle_dungeons(world, Dungeon_Exits, player):
dw_must_exit = list() dw_must_exit = list()
lw_related = list() lw_related = list()
dw_related = list() dw_related = list()
if invFlag == (0x45 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x45, player):
dw_entrances.remove('Turtle Rock Isolated Ledge Entrance') dw_entrances.remove('Turtle Rock Isolated Ledge Entrance')
dw_must_exit.append('Turtle Rock Isolated Ledge Entrance') dw_must_exit.append('Turtle Rock Isolated Ledge Entrance')
if 'Dark Death Mountain Ledge' in world.inaccessible_regions[player]: if 'Dark Death Mountain Ledge' in world.inaccessible_regions[player]:
@@ -1324,7 +1322,7 @@ def full_shuffle_dungeons(world, Dungeon_Exits, player):
random.shuffle(ledge) random.shuffle(ledge)
dw_must_exit.append(ledge.pop()) dw_must_exit.append(ledge.pop())
dw_related.extend(ledge) dw_related.extend(ledge)
if invFlag == (0x30 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x30, player):
if 'Desert Palace Mouth' in world.inaccessible_regions[player]: if 'Desert Palace Mouth' in world.inaccessible_regions[player]:
lw_entrances.remove('Desert Palace Entrance (East)') lw_entrances.remove('Desert Palace Entrance (East)')
lw_must_exit.append('Desert Palace Entrance (East)') lw_must_exit.append('Desert Palace Entrance (East)')
@@ -1337,7 +1335,7 @@ def full_shuffle_dungeons(world, Dungeon_Exits, player):
random.shuffle(ledge) random.shuffle(ledge)
dw_must_exit.append(ledge.pop()) dw_must_exit.append(ledge.pop())
dw_related.extend(ledge) dw_related.extend(ledge)
if invFlag == (0x1b in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x1b, player):
if 'Hyrule Castle Ledge' in world.inaccessible_regions[player]: if 'Hyrule Castle Ledge' in world.inaccessible_regions[player]:
ledge = ['Hyrule Castle Entrance (West)', 'Hyrule Castle Entrance (East)', 'Agahnims Tower'] ledge = ['Hyrule Castle Entrance (West)', 'Hyrule Castle Entrance (East)', 'Agahnims Tower']
lw_entrances = [e for e in lw_entrances if e not in ledge] lw_entrances = [e for e in lw_entrances if e not in ledge]
@@ -1352,7 +1350,7 @@ def full_shuffle_dungeons(world, Dungeon_Exits, player):
hyrule_castle_exits = list([tuple(e for e in hyrule_castle_exits if e in exit_pool)]) hyrule_castle_exits = list([tuple(e for e in hyrule_castle_exits if e in exit_pool)])
hyrule_castle_exits.extend([e for e in dungeon_exits if isinstance(e, str)]) hyrule_castle_exits.extend([e for e in dungeon_exits if isinstance(e, str)])
dungeon_exits = [e for e in dungeon_exits if not isinstance(e, str)] dungeon_exits = [e for e in dungeon_exits if not isinstance(e, str)]
if invFlag == (0x13 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x13, player):
connect_mandatory_exits(world, lw_entrances, hyrule_castle_exits, lw_must_exit, player, False) connect_mandatory_exits(world, lw_entrances, hyrule_castle_exits, lw_must_exit, player, False)
dungeon_exits.extend([e for e in hyrule_castle_exits if isinstance(e, str)]) dungeon_exits.extend([e for e in hyrule_castle_exits if isinstance(e, str)])
hyrule_castle_exits = [e for e in hyrule_castle_exits if not isinstance(e, str)] hyrule_castle_exits = [e for e in hyrule_castle_exits if not isinstance(e, str)]
@@ -1444,7 +1442,7 @@ def place_blacksmith(world, links_house, player):
def place_old_man(world, pool, player, ignore_list=[]): def place_old_man(world, pool, player, ignore_list=[]):
# exit has to come from specific set of doors, the entrance is free to move about # exit has to come from specific set of doors, the entrance is free to move about
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x03, player):
region_name = 'West Death Mountain (Top)' region_name = 'West Death Mountain (Top)'
else: else:
region_name = 'West Dark Death Mountain (Top)' region_name = 'West Dark Death Mountain (Top)'
@@ -1537,7 +1535,7 @@ def connect_inaccessible_regions(world, lw_entrances, dw_entrances, caves, playe
for region_name in inaccessible_regions.copy(): for region_name in inaccessible_regions.copy():
region = world.get_region(region_name, player) region = world.get_region(region_name, player)
if region.type not in [RegionType.LightWorld, RegionType.DarkWorld] or not any((not exit.connected_region and exit.spot_type == 'Entrance') for exit in region.exits) \ if region.type not in [RegionType.LightWorld, RegionType.DarkWorld] or not any((not exit.connected_region and exit.spot_type == 'Entrance') for exit in region.exits) \
or (region_name == 'Pyramid Exit Ledge' and world.shuffle[player] != 'insanity' or invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): or (region_name == 'Pyramid Exit Ledge' and world.shuffle[player] != 'insanity' or world.is_tile_swapped(0x1b, player)):
inaccessible_regions.remove(region_name) inaccessible_regions.remove(region_name)
elif region.type == (RegionType.LightWorld if not invFlag else RegionType.DarkWorld): elif region.type == (RegionType.LightWorld if not invFlag else RegionType.DarkWorld):
must_exit_regions.append(region_name) must_exit_regions.append(region_name)

View File

@@ -358,7 +358,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
if not gftower_trash or not world.ganonstower_vanilla[player] or world.doorShuffle[player] == 'crossed' or world.logic[player] in ['owglitches', 'nologic']: if not gftower_trash or not world.ganonstower_vanilla[player] or world.doorShuffle[player] == 'crossed' or world.logic[player] in ['owglitches', 'nologic']:
continue continue
gftower_trash_count = (random.randint(15, 50) if world.goal[player] == 'triforcehunt' else random.randint(0, 15)) gftower_trash_count = (random.randint(15, 50) if world.goal[player] in ['triforcehunt', 'trinity'] else random.randint(0, 15))
gtower_locations = [location for location in fill_locations if 'Ganons Tower' in location.name and location.player == player] gtower_locations = [location for location in fill_locations if 'Ganons Tower' in location.name and location.player == player]
random.shuffle(gtower_locations) random.shuffle(gtower_locations)
@@ -701,7 +701,7 @@ def balance_money_progression(world):
sphere_locations = get_sphere_locations(state, unchecked_locations) sphere_locations = get_sphere_locations(state, unchecked_locations)
checked_locations = [] checked_locations = []
for player in range(1, world.players+1): for player in range(1, world.players+1):
kiki_payable = state.prog_items[('Moon Pearl', player)] > 0 or (world.mode[player] == 'inverted') != (0x1e in world.owswaps[player][0] and world.owMixed[player]) kiki_payable = state.prog_items[('Moon Pearl', player)] > 0 or world.is_tile_swapped(0x1e, player)
if kiki_payable and world.get_region('Palace of Darkness Area', player) in state.reachable_regions[player]: if kiki_payable and world.get_region('Palace of Darkness Area', player) in state.reachable_regions[player]:
if not kiki_paid[player]: if not kiki_paid[player]:
kiki_check[player] = True kiki_check[player] = True

View File

@@ -178,7 +178,7 @@ def get_custom_array_key(item):
def generate_itempool(world, player): def generate_itempool(world, player):
if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'] if (world.difficulty[player] not in ['normal', 'hard', 'expert'] or world.goal[player] not in ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'trinity', 'crystals']
or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']): or world.mode[player] not in ['open', 'standard', 'inverted'] or world.timer not in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'] or world.progressive not in ['on', 'off', 'random']):
raise NotImplementedError('Not supported yet') raise NotImplementedError('Not supported yet')
@@ -190,7 +190,7 @@ def generate_itempool(world, player):
else: else:
world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False) world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False)
if world.goal[player] in ['triforcehunt']: if world.goal[player] in ['triforcehunt', 'trinity']:
region = world.get_region('Hyrule Castle Courtyard',player) region = world.get_region('Hyrule Castle Courtyard',player)
loc = Location(player, "Murahdahla", parent=region) loc = Location(player, "Murahdahla", parent=region)
@@ -262,8 +262,8 @@ def generate_itempool(world, player):
world.get_location('Zelda Drop Off', player).locked = True world.get_location('Zelda Drop Off', player).locked = True
# set up item pool # set up item pool
if world.custom: if world.custom and player in 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) (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_total, 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[player])
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.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])
@@ -337,14 +337,9 @@ def generate_itempool(world, player):
if clock_mode is not None: if clock_mode is not None:
world.clock_mode = clock_mode world.clock_mode = clock_mode
if world.goal[player] == 'triforcehunt': if world.goal[player] in ['triforcehunt', 'trinity']:
if world.treasure_hunt_count[player] == 0: world.treasure_hunt_count[player], world.treasure_hunt_total[player] = set_default_triforce(world.goal[player], world.treasure_hunt_count[player], world.treasure_hunt_total[player])
world.treasure_hunt_count[player] = 20
if world.treasure_hunt_total[player] == 0:
world.treasure_hunt_total[player] = 30
world.treasure_hunt_icon[player] = 'Triforce Piece' world.treasure_hunt_icon[player] = 'Triforce Piece'
if world.custom:
world.treasure_hunt_count[player] = treasure_hunt_count
world.itempool.extend([item for item in get_dungeon_item_pool(world) if item.player == player world.itempool.extend([item for item in get_dungeon_item_pool(world) if item.player == player
and ((item.smallkey and world.keyshuffle[player]) and ((item.smallkey and world.keyshuffle[player])
@@ -355,9 +350,9 @@ def generate_itempool(world, player):
# logic has some branches where having 4 hearts is one possible requirement (of several alternatives) # logic has some branches where having 4 hearts is one possible requirement (of several alternatives)
# rather than making all hearts/heart pieces progression items (which slows down generation considerably) # rather than making all hearts/heart pieces progression items (which slows down generation considerably)
# We mark one random heart container as an advancement item (or 4 heart pieces in expert mode) # We mark one random heart container as an advancement item (or 4 heart pieces in expert mode)
if world.difficulty[player] in ['normal', 'hard'] and not (world.custom and world.customitemarray[player]["heartcontainer"] == 0): if world.difficulty[player] in ['normal', 'hard'] and not (world.custom and player in world.customitemarray and world.customitemarray[player]["heartcontainer"] == 0):
next(item for item in items if item.name == 'Boss Heart Container').advancement = True next(item for item in items if item.name == 'Boss Heart Container').advancement = True
elif world.difficulty[player] in ['expert'] and not (world.custom and world.customitemarray[player]["heartpiece"] < 4): elif world.difficulty[player] in ['expert'] and not (world.custom and player in world.customitemarray and world.customitemarray[player]["heartpiece"] < 4):
adv_heart_pieces = (item for item in items if item.name == 'Piece of Heart') adv_heart_pieces = (item for item in items if item.name == 'Piece of Heart')
for i in range(4): for i in range(4):
next(adv_heart_pieces).advancement = True next(adv_heart_pieces).advancement = True
@@ -414,7 +409,7 @@ def set_up_take_anys(world, player):
if world.mode[player] == 'inverted': if world.mode[player] == 'inverted':
if 'Dark Sanctuary Hint' in take_any_locations: if 'Dark Sanctuary Hint' in take_any_locations:
take_any_locations.remove('Dark Sanctuary Hint') take_any_locations.remove('Dark Sanctuary Hint')
if (world.mode[player] == 'inverted') != (0x29 in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x29, player):
if 'Archery Game' in take_any_locations: if 'Archery Game' in take_any_locations:
take_any_locations.remove('Archery Game') take_any_locations.remove('Archery Game')
@@ -759,7 +754,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
placed_items = {} placed_items = {}
precollected_items = [] precollected_items = []
clock_mode = None clock_mode = None
if goal == 'triforcehunt': if goal in ['triforcehunt', 'trinity']:
if treasure_hunt_total == 0: if treasure_hunt_total == 0:
treasure_hunt_total = 30 treasure_hunt_total = 30
triforcepool = ['Triforce Piece'] * int(treasure_hunt_total) triforcepool = ['Triforce Piece'] * int(treasure_hunt_total)
@@ -841,7 +836,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
place_item('Link\'s Uncle', swords_to_use.pop()) place_item('Link\'s Uncle', swords_to_use.pop())
place_item('Blacksmith', swords_to_use.pop()) place_item('Blacksmith', swords_to_use.pop())
place_item('Pyramid Fairy - Left', swords_to_use.pop()) place_item('Pyramid Fairy - Left', swords_to_use.pop())
if goal != 'pedestal': if goal not in ['pedestal', 'trinity']:
place_item('Master Sword Pedestal', swords_to_use.pop()) place_item('Master Sword Pedestal', swords_to_use.pop())
else: else:
place_item('Master Sword Pedestal', 'Triforce') place_item('Master Sword Pedestal', 'Triforce')
@@ -866,7 +861,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
pool.extend(diff.timedohko) pool.extend(diff.timedohko)
extraitems -= len(diff.timedohko) extraitems -= len(diff.timedohko)
clock_mode = 'countdown-ohko' clock_mode = 'countdown-ohko'
if goal == 'triforcehunt': if goal in ['triforcehunt', 'trinity']:
pool.extend(triforcepool) pool.extend(triforcepool)
extraitems -= len(triforcepool) extraitems -= len(triforcepool)
@@ -877,7 +872,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
pool.extend(extra) pool.extend(extra)
extraitems -= len(extra) extraitems -= len(extra)
if goal == 'pedestal' and swords != 'vanilla': if goal in ['pedestal', 'trinity'] and swords != 'vanilla':
place_item('Master Sword Pedestal', 'Triforce') place_item('Master Sword Pedestal', 'Triforce')
if retro: if retro:
pool = [item.replace('Single Arrow','Rupees (5)') for item in pool] pool = [item.replace('Single Arrow','Rupees (5)') for item in pool]
@@ -901,13 +896,12 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms)
def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bombbag, customitemarray): def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bombbag, customitemarray):
if isinstance(customitemarray,dict) and 1 in customitemarray:
customitemarray = customitemarray[1]
pool = [] pool = []
placed_items = {} placed_items = {}
precollected_items = [] precollected_items = []
clock_mode = None clock_mode = None
treasure_hunt_count = None treasure_hunt_count = None
treasure_hunt_total = None
treasure_hunt_icon = None treasure_hunt_icon = None
def place_item(loc, item): def place_item(loc, item):
@@ -916,7 +910,7 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
# Correct for insanely oversized item counts and take initial steps to handle undersized pools. # Correct for insanely oversized item counts and take initial steps to handle undersized pools.
# Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors # Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors
for x in [*range(0, 66 + 1), 68, 69]: for x in [*range(0, 69)]:
key = CONST.CUSTOMITEMS[x] key = CONST.CUSTOMITEMS[x]
if customitemarray[key] > total_items_to_place: if customitemarray[key] > total_items_to_place:
customitemarray[key] = total_items_to_place customitemarray[key] = total_items_to_place
@@ -925,6 +919,10 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
if customitemarray["triforce"] > total_items_to_place: if customitemarray["triforce"] > total_items_to_place:
customitemarray["triforce"] = total_items_to_place customitemarray["triforce"] = total_items_to_place
# Triforce Pieces
if goal in ['triforcehunt', 'trinity']:
customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"] = set_default_triforce(goal, customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"])
itemtotal = 0 itemtotal = 0
# Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors # Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors
for x in [*range(0, 66 + 1), 68, 69]: for x in [*range(0, 66 + 1), 68, 69]:
@@ -955,13 +953,7 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
pool.append(thisbottle) pool.append(thisbottle)
if customitemarray["triforcepieces"] > 0 or customitemarray["triforcepiecesgoal"] > 0: if customitemarray["triforcepieces"] > 0 or customitemarray["triforcepiecesgoal"] > 0:
treasure_hunt_count = max(min(customitemarray["triforcepiecesgoal"], 99), 1) #To display, count must be between 1 and 99.
treasure_hunt_icon = 'Triforce Piece' treasure_hunt_icon = 'Triforce Piece'
# Ensure game is always possible to complete here, force sufficient pieces if the player is unwilling.
if (customitemarray["triforcepieces"] < treasure_hunt_count) and (goal == 'triforcehunt') and (customitemarray["triforce"] == 0):
extrapieces = treasure_hunt_count - customitemarray["triforcepieces"]
pool.extend(['Triforce Piece'] * extrapieces)
itemtotal = itemtotal + extrapieces
if timer in ['display', 'timed', 'timed-countdown']: if timer in ['display', 'timed', 'timed-countdown']:
clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch' clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch'
@@ -970,7 +962,7 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
elif timer == 'ohko': elif timer == 'ohko':
clock_mode = 'ohko' clock_mode = 'ohko'
if goal == 'pedestal': if goal in ['pedestal', 'trinity']:
place_item('Master Sword Pedestal', 'Triforce') place_item('Master Sword Pedestal', 'Triforce')
itemtotal = itemtotal + 1 itemtotal = itemtotal + 1
@@ -1003,12 +995,24 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
# print("Placing " + str(nothings) + " Nothings") # print("Placing " + str(nothings) + " Nothings")
pool.extend(['Nothing'] * nothings) pool.extend(['Nothing'] * nothings)
return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_total, treasure_hunt_icon, lamps_needed_for_dark_rooms)
def set_default_triforce(goal, custom_goal, custom_total):
triforce_goal, triforce_total = 0, 0
if goal == 'triforcehunt':
triforce_goal, triforce_total = 20, 30
elif goal == 'trinity':
triforce_goal, triforce_total = 8, 10
if custom_goal > 0:
triforce_goal = max(min(custom_goal, 128), 1)
if custom_total > 0 or custom_goal > 0:
triforce_total = max(min(custom_total, 128), triforce_goal) #128 max to ensure other progression can fit.
return (triforce_goal, triforce_total)
# A quick test to ensure all combinations generate the correct amount of items. # A quick test to ensure all combinations generate the correct amount of items.
def test(): def test():
for difficulty in ['normal', 'hard', 'expert']: for difficulty in ['normal', 'hard', 'expert']:
for goal in ['ganon', 'triforcehunt', 'pedestal']: for goal in ['ganon', 'triforcehunt', 'pedestal', 'trinity']:
for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']: for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']:
for mode in ['open', 'standard', 'inverted', 'retro']: for mode in ['open', 'standard', 'inverted', 'retro']:
for swords in ['random', 'assured', 'swordless', 'vanilla']: for swords in ['random', 'assured', 'swordless', 'vanilla']:
@@ -1022,7 +1026,7 @@ def test():
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 in ['pedestal', 'trinity'] 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:

View File

@@ -1970,7 +1970,7 @@ def val_mire(key_logic, world, player):
def val_turtle(key_logic, world, player): def val_turtle(key_logic, world, player):
# todo: check vanilla key logic when TR back doors are accessible # todo: check vanilla key logic when TR back doors are accessible
if world.shuffle[player] == 'vanilla' and (world.mode[player] == 'inverted') == (0x05 in world.owswaps[player][0] and world.owMixed[player]) and world.logic[player] in ('noglitches', 'minorglitches'): if world.shuffle[player] == 'vanilla' and (not world.is_tile_swapped(0x05, player)) and world.logic[player] in ('noglitches', 'minorglitches'):
val_rule(key_logic.door_rules['TR Hub NW'], 1) val_rule(key_logic.door_rules['TR Hub NW'], 1)
val_rule(key_logic.door_rules['TR Pokey 1 NW'], 2) val_rule(key_logic.door_rules['TR Pokey 1 NW'], 2)
val_rule(key_logic.door_rules['TR Chain Chomps Down Stairs'], 3) val_rule(key_logic.door_rules['TR Chain Chomps Down Stairs'], 3)

View File

@@ -179,9 +179,10 @@ def roll_settings(weights):
'fast_ganon': 'crystals', 'fast_ganon': 'crystals',
'dungeons': 'dungeons', 'dungeons': 'dungeons',
'pedestal': 'pedestal', 'pedestal': 'pedestal',
'triforce-hunt': 'triforcehunt' 'triforce-hunt': 'triforcehunt',
'trinity': 'trinity'
}[goal] }[goal]
ret.openpyramid = goal == 'fast_ganon' if ret.shuffle in ['vanilla', 'dungeonsfull', 'dungeonssimple'] else False ret.openpyramid = goal in ['fast_ganon', 'trinity'] if ret.shuffle in ['vanilla', 'dungeonsfull', 'dungeonssimple'] else False
ret.shuffleganon = get_choice('shuffleganon') == 'on' ret.shuffleganon = get_choice('shuffleganon') == 'on'

View File

@@ -1,10 +1,11 @@
import RaceRandom as random, logging, copy import RaceRandom as random, logging, copy
from collections import OrderedDict from collections import OrderedDict
from DungeonGenerator import GenerationException
from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance
from Regions import mark_dark_world_regions, mark_light_world_regions from Regions import mark_dark_world_regions, mark_light_world_regions
from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel
__version__ = '0.2.3.5-u' __version__ = '0.2.3.6-u'
def link_overworld(world, player): def link_overworld(world, player):
# setup mandatory connections # setup mandatory connections
@@ -159,7 +160,7 @@ def link_overworld(world, player):
# apply tile logical connections # apply tile logical 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.owMixed[player]): if not world.is_tile_swapped(owid, 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:
@@ -342,7 +343,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.owMixed[player]): if not world.is_tile_swapped(flute_data[owslot][1], 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)
@@ -364,7 +365,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.owMixed[player]): if not world.is_tile_swapped(flute_data[owid][1], 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]

View File

@@ -136,6 +136,12 @@ New flute spots are chosen at random, with restrictions that limit the promixity
New flute spots are chosen at random with minimum bias. New flute spots are chosen at random with minimum bias.
## New Goal Options (--goal)
### Trinity
This goal gives you the choice between 3 goals, only one of which the player needs to complete: Defeat Ganon (no Aga2), Pulling Pedestal, or turn in TF pieces to Murahdulah. By default, you need to find 8 of 10 total TF pieces but this can be changed with a Custom Item Pool. It is recommended to set GT Entry to 7 crystals and Ganon to 5 crystals or Random crystals, although the player can flexibly change these settings as they seem fit.
## New Entrance Shuffle Options (--shuffle) ## New Entrance Shuffle Options (--shuffle)
### Lite ### Lite

42
Rom.py
View File

@@ -624,7 +624,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
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.owMixed[player]): if world.is_tile_swapped(data[1], 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
@@ -755,7 +755,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
dr_flags = DROptions.Eternal_Mini_Bosses if world.doorShuffle[player] == 'vanilla' else DROptions.Town_Portal dr_flags = DROptions.Eternal_Mini_Bosses if world.doorShuffle[player] == 'vanilla' else DROptions.Town_Portal
if world.doorShuffle[player] == 'crossed': if world.doorShuffle[player] == 'crossed':
dr_flags |= DROptions.Map_Info dr_flags |= DROptions.Map_Info
if world.experimental[player] and world.goal[player] != 'triforcehunt': if world.experimental[player] and world.goal[player] not in ['triforcehunt', 'trinity']:
dr_flags |= DROptions.Debug dr_flags |= DROptions.Debug
if world.doorShuffle[player] == 'crossed' and world.logic[player] != 'nologic'\ if world.doorShuffle[player] == 'crossed' and world.logic[player] != 'nologic'\
and world.mixed_travel[player] == 'prevent': and world.mixed_travel[player] == 'prevent':
@@ -1235,7 +1235,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
# set up goals for treasure hunt # set up goals for treasure hunt
rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28]) rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon[player] == 'Triforce Piece' else [0x0D, 0x28])
if world.goal[player] == 'triforcehunt': if world.goal[player] in ['triforcehunt', 'trinity']:
rom.write_byte(0x180167, int(world.treasure_hunt_count[player]) % 256) rom.write_byte(0x180167, int(world.treasure_hunt_count[player]) % 256)
rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled) rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled)
@@ -1261,7 +1261,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest
rom.write_byte(0x50599, 0x00) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest
rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest
rom.write_byte(0x18008B, 0x01 if world.open_pyramid[player] else 0x00) # pre-open Pyramid Hole rom.write_byte(0x18008B, 0x01 if world.open_pyramid[player] or world.goal[player] == 'trinity' else 0x00) # pre-open Pyramid Hole
rom.write_byte(0x18008C, 0x01 if world.crystals_needed_for_gt[player] == 0 else 0x00) # GT pre-opened if crystal requirement is 0 rom.write_byte(0x18008C, 0x01 if world.crystals_needed_for_gt[player] == 0 else 0x00) # GT pre-opened if crystal requirement is 0
rom.write_byte(0xF5D73, 0xF0) # bees are catchable rom.write_byte(0xF5D73, 0xF0) # bees are catchable
rom.write_byte(0xF5F10, 0xF0) # bees are catchable rom.write_byte(0xF5F10, 0xF0) # bees are catchable
@@ -1446,7 +1446,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_byte(0x18003E, 0x01) # make ganon invincible rom.write_byte(0x18003E, 0x01) # make ganon invincible
elif world.goal[player] in ['dungeons']: elif world.goal[player] in ['dungeons']:
rom.write_byte(0x18003E, 0x02) # make ganon invincible until all dungeons are beat rom.write_byte(0x18003E, 0x02) # make ganon invincible until all dungeons are beat
elif world.goal[player] in ['crystals']: elif world.goal[player] in ['crystals', 'trinity']:
rom.write_byte(0x18003E, 0x04) # make ganon invincible until all crystals rom.write_byte(0x18003E, 0x04) # make ganon invincible until all crystals
else: else:
rom.write_byte(0x18003E, 0x03) # make ganon invincible until all crystals and aga 2 are collected rom.write_byte(0x18003E, 0x03) # make ganon invincible until all crystals and aga 2 are collected
@@ -2186,7 +2186,7 @@ def write_strings(rom, world, player, team):
elif world.shopsanity[player]: elif world.shopsanity[player]:
entrances_to_hint.update(ShopEntrances) entrances_to_hint.update(ShopEntrances)
if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull']: if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
if world.mode[player] == 'inverted' != (0x2c in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x2c, player):
entrances_to_hint.update({'Links House': 'The hero\'s old residence'}) entrances_to_hint.update({'Links House': 'The hero\'s old residence'})
if world.shufflelinks[player]: if world.shufflelinks[player]:
entrances_to_hint.update({'Big Bomb Shop': 'The old bomb shop'}) entrances_to_hint.update({'Big Bomb Shop': 'The old bomb shop'})
@@ -2198,7 +2198,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.owMixed[player]): if world.is_tile_swapped(0x1b, 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'})
@@ -2374,6 +2374,10 @@ def write_strings(rom, world, player, team):
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.' tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
tt['sign_ganon'] = 'You need to get to the pedestal... Ganon is invincible!' tt['sign_ganon'] = 'You need to get to the pedestal... Ganon is invincible!'
else: else:
if world.goal[player] in ['trinity']:
trinity_crystal_text = ('%d crystal to beat Ganon.' if world.crystals_needed_for_ganon[player] == 1 else '%d crystals to beat Ganon.') % world.crystals_needed_for_ganon[player]
tt['sign_ganon'] = 'Three ways to victory! %s Get to it!' % trinity_crystal_text
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % int(world.treasure_hunt_count[player])
tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)] tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)]
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!' tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!' tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
@@ -2495,9 +2499,9 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
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.owMixed[player]): if world.is_tile_swapped(0x03, player):
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull'] \ if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull'] \
or (world.shuffle[player] == 'simple' and (world.mode[player] == 'inverted' != (0x05 in world.owswaps[player][0] and world.owMixed[player]))): or (world.shuffle[player] == 'simple' and world.is_tile_swapped(0x05, player)):
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
write_int16(rom, snes_to_pc(0x02D8DE), 0x00F1) # change mountain cave spawn point to just outside old man cave write_int16(rom, snes_to_pc(0x02D8DE), 0x00F1) # change mountain cave spawn point to just outside old man cave
@@ -2519,20 +2523,20 @@ 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.owMixed[player]): if world.is_tile_swapped(0x05, 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
rom.write_byte(snes_to_pc(0x1BC428), 0x00) # remove secret portal rom.write_byte(snes_to_pc(0x1BC428), 0x00) # remove secret portal
if (world.mode[player] == 'inverted') != (0x07 in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x07, 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.owMixed[player]): if world.is_tile_swapped(0x10, 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
rom.write_byte(snes_to_pc(0x1BC43A), 0x00) # remove secret portal rom.write_byte(snes_to_pc(0x1BC43A), 0x00) # remove secret portal
if (world.mode[player] == 'inverted') != (0x1B in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x1b, 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)
@@ -2637,24 +2641,24 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
rom.write_byte(0x1607C + 0x37, 0x0A) rom.write_byte(0x1607C + 0x37, 0x0A)
write_int16(rom, 0x160CB + 2 * 0x37, 0x0000) write_int16(rom, 0x160CB + 2 * 0x37, 0x0000)
write_int16(rom, 0x16169 + 2 * 0x37, 0x811C) write_int16(rom, 0x16169 + 2 * 0x37, 0x811C)
if (world.mode[player] == 'inverted') != (0x29 in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x29, 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.owMixed[player]): if world.is_tile_swapped(0x2c, 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.owMixed[player]): if world.is_tile_swapped(0x2f, 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
rom.write_byte(snes_to_pc(0x1BC590), 0x00) # remove secret portal rom.write_byte(snes_to_pc(0x1BC590), 0x00) # remove secret portal
if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x30, 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
rom.write_byte(snes_to_pc(0x1BC5A1), 0x00) # remove secret portal rom.write_byte(snes_to_pc(0x1BC5A1), 0x00) # remove secret portal
if (world.mode[player] == 'inverted') != (0x33 in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x33, 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
rom.write_byte(snes_to_pc(0x1BC5B1), 0x00) # remove secret portal rom.write_byte(snes_to_pc(0x1BC5B1), 0x00) # remove secret portal
if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owMixed[player]): if world.is_tile_swapped(0x35, 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
rom.write_byte(snes_to_pc(0x1BC5C7), 0x00) # remove secret portal rom.write_byte(snes_to_pc(0x1BC5C7), 0x00) # remove secret portal

View File

@@ -55,7 +55,7 @@ def set_rules(world, player):
elif world.goal[player] == 'ganon': elif world.goal[player] == 'ganon':
# require aga2 to beat ganon # require aga2 to beat ganon
add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player)) add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player))
elif world.goal[player] == 'triforcehunt': if world.goal[player] in ['triforcehunt', 'trinity']:
if ('Murahdahla', player) in world._location_cache: if ('Murahdahla', player) in world._location_cache:
add_rule(world.get_location('Murahdahla', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) add_rule(world.get_location('Murahdahla', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player]))
@@ -860,7 +860,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.owMixed[player]): if not world.is_tile_swapped(0x00, 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))
@@ -875,12 +875,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.owMixed[player]): if not world.is_tile_swapped(0x02, 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.owMixed[player]): if not world.is_tile_swapped(0x03, 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:
@@ -888,7 +888,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.owMixed[player]): if not world.is_tile_swapped(0x05, 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))
@@ -910,7 +910,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.owMixed[player]): if not world.is_tile_swapped(0x07, 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:
@@ -918,7 +918,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.owMixed[player]): if not world.is_tile_swapped(0x0a, 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))
@@ -927,12 +927,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.owMixed[player]): if not world.is_tile_swapped(0x0f, 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.owMixed[player]): if not world.is_tile_swapped(0x10, 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 Portal Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Lost Woods Pass Portal Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -944,24 +944,24 @@ def ow_rules(world, player):
set_rule(world.get_entrance('Skull Woods Pass Portal Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Skull Woods Pass Portal Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('Skull Woods Pass East Bottom Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Skull Woods Pass East Bottom Mirror Spot', player), lambda state: state.has_Mirror(player))
if (world.mode[player] == 'inverted') == (0x11 in world.owswaps[player][0] and world.owMixed[player]): if not world.is_tile_swapped(0x11, 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.owMixed[player]): if not world.is_tile_swapped(0x12, 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.owMixed[player]): if not world.is_tile_swapped(0x13, 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.owMixed[player]): if not world.is_tile_swapped(0x14, 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:
@@ -971,28 +971,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.owMixed[player]): if not world.is_tile_swapped(0x15, 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.owMixed[player]): if not world.is_tile_swapped(0x16, 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.owMixed[player]): if not world.is_tile_swapped(0x17, 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.owMixed[player]): if not world.is_tile_swapped(0x18, 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:
@@ -1000,16 +1000,16 @@ 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.owMixed[player]): if not world.is_tile_swapped(0x1a, 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.owMixed[player]): if not world.is_tile_swapped(0x1b, 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: world.open_pyramid[player] or world.goal[player] == 'trinity' or state.has('Beat Agahnim 2', player))
set_rule(world.get_entrance('HC Area Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('HC Area Mirror Spot', player), lambda state: state.has_Mirror(player))
set_rule(world.get_entrance('HC Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('HC Ledge Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -1020,8 +1020,8 @@ def ow_rules(world, player):
set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player))
set_rule(world.get_entrance('Top of Pyramid (Inner)', player), lambda state: state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Top of Pyramid (Inner)', player), lambda state: state.has('Beat Agahnim 1', player))
else: else:
set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid[player]) set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: world.open_pyramid[player] or world.goal[player] == 'trinity' or state.has('Beat Agahnim 2', player))
add_rule(world.get_entrance('Pyramid Hole', player), lambda state: False) set_rule(world.get_entrance('Pyramid Hole', player), lambda state: False)
set_rule(world.get_entrance('Pyramid Entrance', player), lambda state: False) set_rule(world.get_entrance('Pyramid Entrance', player), lambda state: False)
set_rule(world.get_entrance('Pyramid Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Pyramid Mirror Spot', player), lambda state: state.has_Mirror(player))
@@ -1032,7 +1032,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.owMixed[player]): if not world.is_tile_swapped(0x1d, 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))
@@ -1041,12 +1041,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.owMixed[player]): if not world.is_tile_swapped(0x1e, 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.owMixed[player]): if not world.is_tile_swapped(0x22, 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))
@@ -1054,19 +1054,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.owMixed[player]): if not world.is_tile_swapped(0x25, 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.owMixed[player]): if not world.is_tile_swapped(0x28, 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.owMixed[player]): if not world.is_tile_swapped(0x29, 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:
@@ -1074,24 +1074,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.owMixed[player]): if not world.is_tile_swapped(0x2a, 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.owMixed[player]): if not world.is_tile_swapped(0x2b, 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.owMixed[player]): if not world.is_tile_swapped(0x2c, 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.owMixed[player]): if not world.is_tile_swapped(0x2d, 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))
@@ -1100,19 +1100,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.owMixed[player]): if not world.is_tile_swapped(0x2e, 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.owMixed[player]): if not world.is_tile_swapped(0x2f, 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.owMixed[player]): if not world.is_tile_swapped(0x30, 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))
@@ -1127,14 +1127,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.owMixed[player]): if not world.is_tile_swapped(0x32, 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.owMixed[player]): if not world.is_tile_swapped(0x33, 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
@@ -1145,12 +1145,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.owMixed[player]): if not world.is_tile_swapped(0x34, 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.owMixed[player]): if not world.is_tile_swapped(0x35, 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))
@@ -1167,12 +1167,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.owMixed[player]): if not world.is_tile_swapped(0x37, 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.owMixed[player]): if not world.is_tile_swapped(0x3a, 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:
@@ -1180,17 +1180,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.owMixed[player]): if not world.is_tile_swapped(0x3b, 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.owMixed[player]): if not world.is_tile_swapped(0x3c, 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.owMixed[player]): if not world.is_tile_swapped(0x3f, 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))

View File

@@ -73,6 +73,7 @@
dungeons: 1 dungeons: 1
pedestal: 2 pedestal: 2
triforce-hunt: 2 triforce-hunt: 2
trinity: 1
triforce_goal_min: 10 triforce_goal_min: 10
triforce_goal_max: 30 triforce_goal_max: 30
triforce_pool_min: 20 triforce_pool_min: 20

View File

@@ -103,7 +103,9 @@
"All Dungeons: Collect all crystals, pendants, beat both", "All Dungeons: Collect all crystals, pendants, beat both",
" Agahnim fights and then defeat Ganon.", " Agahnim fights and then defeat Ganon.",
"Triforce Hunt: Places 30 Triforce Pieces in the world, collect", "Triforce Hunt: Places 30 Triforce Pieces in the world, collect",
" 20 of them to beat the game." " 20 of them to beat the game.",
"Trinity: Can beat the game by defeating Ganon, pulling",
" Pedestal, or delivering Triforce Pieces."
], ],
"difficulty": [ "difficulty": [
"Select game difficulty. Affects available itempool. (default: %(default)s)", "Select game difficulty. Affects available itempool. (default: %(default)s)",

View File

@@ -238,6 +238,7 @@
"randomizer.item.goal.pedestal": "Master Sword Pedestal", "randomizer.item.goal.pedestal": "Master Sword Pedestal",
"randomizer.item.goal.dungeons": "All Dungeons", "randomizer.item.goal.dungeons": "All Dungeons",
"randomizer.item.goal.triforcehunt": "Triforce Hunt", "randomizer.item.goal.triforcehunt": "Triforce Hunt",
"randomizer.item.goal.trinity": "Trinity",
"randomizer.item.goal.crystals": "Crystals", "randomizer.item.goal.crystals": "Crystals",
"randomizer.item.crystals_gt": "Crystals to open GT", "randomizer.item.crystals_gt": "Crystals to open GT",

View File

@@ -35,6 +35,7 @@
"pedestal", "pedestal",
"dungeons", "dungeons",
"triforcehunt", "triforcehunt",
"trinity",
"crystals" "crystals"
] ]
}, },