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