Merge branch 'OverworldShuffleDev' into OverworldShuffle
This commit is contained in:
+11
-9
@@ -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])
|
||||||
@@ -2553,11 +2556,10 @@ class Pot(object):
|
|||||||
self.flags = flags
|
self.flags = flags
|
||||||
|
|
||||||
|
|
||||||
# byte 0: DDOO EEEE (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 = {"parallel": 1, "full": 2, "vanilla": 0}
|
or_mode = {"vanilla": 0, "parallel": 1, "full": 1}
|
||||||
er_mode = {"vanilla": 0, "simple": 1, "restricted": 2, "full": 3, "crossed": 4, "insanity": 5, "restricted_legacy": 8,
|
er_mode = {"vanilla": 0, "simple": 1, "restricted": 3, "full": 3, "crossed": 4, "insanity": 5, "dungeonsfull": 7, "dungeonssimple": 7}
|
||||||
"full_legacy": 9, "madness_legacy": 10, "insanity_legacy": 11, "dungeonsfull": 7, "dungeonssimple": 6}
|
|
||||||
|
|
||||||
# byte 1: LLLW WSSR (logic, mode, sword, retro)
|
# byte 1: LLLW WSSR (logic, mode, sword, retro)
|
||||||
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
|
logic_mode = {"noglitches": 0, "minorglitches": 1, "nologic": 2, "owglitches": 3, "majorglitches": 4}
|
||||||
@@ -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) | 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),
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### 0.1.8.0
|
||||||
|
- Moved Crossed to its own checkbox option
|
||||||
|
- Removed Legacy ER shuffles
|
||||||
|
- Added OW Shuffle support for Plando module (needs user testing)
|
||||||
|
- Fixed issue with Sanc start at TR as bunny when it is LW
|
||||||
|
- Fixed issue with Pyramid Hole not getting shuffled
|
||||||
|
- ~~Merged DR v0.5.0.3 - Minor DR fixes~~
|
||||||
|
|
||||||
### 0.1.7.4
|
### 0.1.7.4
|
||||||
- Fixed issue with Mixed OW failing to generate when HC/Pyramid is swapped
|
- Fixed issue with Mixed OW failing to generate when HC/Pyramid is swapped
|
||||||
- Various fixes to improve generation rates for Mixed OW Shuffle
|
- Various fixes to improve generation rates for Mixed OW Shuffle
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
+4
-2
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
@@ -1071,6 +1071,7 @@ def assign_cross_keys(dungeon_builders, world, player):
|
|||||||
# Step 3: Initial valid combination find - reduce flex if needed
|
# Step 3: Initial valid combination find - reduce flex if needed
|
||||||
for name, builder in dungeon_builders.items():
|
for name, builder in dungeon_builders.items():
|
||||||
suggested = builder.key_doors_num - builder.key_drop_cnt
|
suggested = builder.key_doors_num - builder.key_drop_cnt
|
||||||
|
builder.total_keys = builder.key_doors_num
|
||||||
find_valid_combination(builder, start_regions_map[name], world, player)
|
find_valid_combination(builder, start_regions_map[name], world, player)
|
||||||
actual_chest_keys = builder.key_doors_num - builder.key_drop_cnt
|
actual_chest_keys = builder.key_doors_num - builder.key_drop_cnt
|
||||||
if actual_chest_keys < suggested:
|
if actual_chest_keys < suggested:
|
||||||
@@ -1087,6 +1088,7 @@ def assign_cross_keys(dungeon_builders, world, player):
|
|||||||
name = builder.name
|
name = builder.name
|
||||||
logger.debug('Cross Dungeon: Increasing key count by 1 for %s', name)
|
logger.debug('Cross Dungeon: Increasing key count by 1 for %s', name)
|
||||||
builder.key_doors_num += 1
|
builder.key_doors_num += 1
|
||||||
|
builder.total_keys = builder.key_doors_num
|
||||||
result = find_valid_combination(builder, start_regions_map[name], world, player, drop_keys=False)
|
result = find_valid_combination(builder, start_regions_map[name], world, player, drop_keys=False)
|
||||||
if result:
|
if result:
|
||||||
remaining -= 1
|
remaining -= 1
|
||||||
@@ -1380,7 +1382,7 @@ def shuffle_key_doors(builder, world, player):
|
|||||||
skips.append(world.get_door(dp.door_a, player))
|
skips.append(world.get_door(dp.door_a, player))
|
||||||
break
|
break
|
||||||
num_key_doors += 1
|
num_key_doors += 1
|
||||||
builder.key_doors_num = num_key_doors
|
builder.key_doors_num = builder.total_keys = num_key_doors
|
||||||
find_small_key_door_candidates(builder, start_regions, world, player)
|
find_small_key_door_candidates(builder, start_regions, world, player)
|
||||||
find_valid_combination(builder, start_regions, world, player)
|
find_valid_combination(builder, start_regions, world, player)
|
||||||
reassign_key_doors(builder, world, player)
|
reassign_key_doors(builder, world, player)
|
||||||
|
|||||||
@@ -1175,6 +1175,7 @@ class DungeonBuilder(object):
|
|||||||
self.pre_open_stonewalls = set() # used by stonewall system
|
self.pre_open_stonewalls = set() # used by stonewall system
|
||||||
|
|
||||||
self.candidates = None
|
self.candidates = None
|
||||||
|
self.total_keys = None
|
||||||
self.key_doors_num = None
|
self.key_doors_num = None
|
||||||
self.combo_size = None
|
self.combo_size = None
|
||||||
self.flex = 0
|
self.flex = 0
|
||||||
|
|||||||
@@ -375,6 +375,13 @@ flexible_starts = {
|
|||||||
'Skull Woods': ['Skull Left Drop', 'Skull Pinball']
|
'Skull Woods': ['Skull Left Drop', 'Skull Pinball']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default_key_counts = {
|
||||||
|
'Hyrule Castle': 1, 'Eastern Palace': 0, 'Desert Palace': 1,
|
||||||
|
'Tower of Hera': 1, 'Agahnims Tower': 2, 'Palace of Darkness': 6,
|
||||||
|
'Swamp Palace': 1, 'Skull Woods': 3, 'Thieves Town': 1,
|
||||||
|
'Ice Palace': 2, 'Misery Mire': 3, 'Turtle Rock': 4, 'Ganons Tower': 4
|
||||||
|
}
|
||||||
|
|
||||||
dungeon_keys = {
|
dungeon_keys = {
|
||||||
'Hyrule Castle': 'Small Key (Escape)',
|
'Hyrule Castle': 'Small Key (Escape)',
|
||||||
'Eastern Palace': 'Small Key (Eastern Palace)',
|
'Eastern Palace': 'Small Key (Eastern Palace)',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ In the vanilla, dungeonssimple, and dungeonsfull shuffles, the following ratios
|
|||||||
8 hints for valuable items.
|
8 hints for valuable items.
|
||||||
7 junk hints.
|
7 junk hints.
|
||||||
|
|
||||||
In the simple, restricted, and restricted legacy shuffles, these are the ratios:
|
In the simple, restricted shuffles, these are the ratios:
|
||||||
|
|
||||||
2 hints for inconvenient entrances.
|
2 hints for inconvenient entrances.
|
||||||
1 hint for an inconvenient dungeon entrance.
|
1 hint for an inconvenient dungeon entrance.
|
||||||
|
|||||||
+27
-596
@@ -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')
|
||||||
@@ -374,61 +374,6 @@ def link_entrances(world, player):
|
|||||||
|
|
||||||
# place remaining doors
|
# place remaining doors
|
||||||
connect_doors(world, doors, door_targets, player)
|
connect_doors(world, doors, door_targets, player)
|
||||||
elif not invFlag and world.shuffle[player] == 'restricted_legacy':
|
|
||||||
simple_shuffle_dungeons(world, player)
|
|
||||||
|
|
||||||
lw_entrances = list(LW_Entrances)
|
|
||||||
dw_entrances = list(DW_Entrances)
|
|
||||||
dw_must_exits = list(DW_Entrances_Must_Exit)
|
|
||||||
old_man_entrances = list(Old_Man_Entrances)
|
|
||||||
caves = list(Cave_Exits)
|
|
||||||
three_exit_caves = list(Cave_Three_Exits)
|
|
||||||
single_doors = list(Single_Cave_Doors)
|
|
||||||
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
|
|
||||||
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
|
|
||||||
door_targets = list(Single_Cave_Targets)
|
|
||||||
|
|
||||||
# only use two exit caves to do mandatory dw connections
|
|
||||||
connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player)
|
|
||||||
# add three exit doors to pool for remainder
|
|
||||||
caves.extend(three_exit_caves)
|
|
||||||
|
|
||||||
# place old man, has limited options
|
|
||||||
# exit has to come from specific set of doors, the entrance is free to move about
|
|
||||||
random.shuffle(old_man_entrances)
|
|
||||||
old_man_exit = old_man_entrances.pop()
|
|
||||||
lw_entrances.extend(old_man_entrances)
|
|
||||||
random.shuffle(lw_entrances)
|
|
||||||
old_man_entrance = lw_entrances.pop()
|
|
||||||
connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player)
|
|
||||||
connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player)
|
|
||||||
|
|
||||||
# place Old Man House in Light World
|
|
||||||
connect_caves(world, lw_entrances, [], Old_Man_House, player)
|
|
||||||
|
|
||||||
# connect rest. There's 2 dw entrances remaining, so we will not run into parity issue placing caves
|
|
||||||
connect_caves(world, lw_entrances, dw_entrances, caves, player)
|
|
||||||
|
|
||||||
# scramble holes
|
|
||||||
scramble_holes(world, player)
|
|
||||||
|
|
||||||
# place blacksmith, has limited options
|
|
||||||
random.shuffle(blacksmith_doors)
|
|
||||||
blacksmith_hut = blacksmith_doors.pop()
|
|
||||||
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
|
|
||||||
bomb_shop_doors.extend(blacksmith_doors)
|
|
||||||
|
|
||||||
# place dam and pyramid fairy, have limited options
|
|
||||||
random.shuffle(bomb_shop_doors)
|
|
||||||
bomb_shop = bomb_shop_doors.pop()
|
|
||||||
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
|
|
||||||
single_doors.extend(bomb_shop_doors)
|
|
||||||
|
|
||||||
# tavern back door cannot be shuffled yet
|
|
||||||
connect_doors(world, ['Tavern North'], ['Tavern'], player)
|
|
||||||
|
|
||||||
# place remaining doors
|
|
||||||
connect_doors(world, single_doors, door_targets, player)
|
|
||||||
elif world.shuffle[player] == 'full':
|
elif world.shuffle[player] == 'full':
|
||||||
skull_woods_shuffle(world, player)
|
skull_woods_shuffle(world, player)
|
||||||
|
|
||||||
@@ -769,324 +714,6 @@ def link_entrances(world, player):
|
|||||||
|
|
||||||
# place remaining doors
|
# place remaining doors
|
||||||
connect_doors(world, entrances, door_targets, player)
|
connect_doors(world, entrances, door_targets, player)
|
||||||
elif not invFlag and world.shuffle[player] == 'full_legacy':
|
|
||||||
skull_woods_shuffle(world, player)
|
|
||||||
|
|
||||||
lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + Old_Man_Entrances)
|
|
||||||
dw_entrances = list(DW_Entrances + DW_Dungeon_Entrances)
|
|
||||||
dw_must_exits = list(DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit)
|
|
||||||
lw_must_exits = list(LW_Dungeon_Entrances_Must_Exit)
|
|
||||||
old_man_entrances = list(Old_Man_Entrances + ['Tower of Hera'])
|
|
||||||
caves = list(Cave_Exits + Dungeon_Exits + Cave_Three_Exits) # don't need to consider three exit caves, have one exit caves to avoid parity issues
|
|
||||||
single_doors = list(Single_Cave_Doors)
|
|
||||||
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
|
|
||||||
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
|
|
||||||
door_targets = list(Single_Cave_Targets)
|
|
||||||
|
|
||||||
if world.mode[player] == 'standard':
|
|
||||||
# must connect front of hyrule castle to do escape
|
|
||||||
connect_two_way(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
|
|
||||||
else:
|
|
||||||
caves.append(tuple(random.sample(['Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'],3)))
|
|
||||||
lw_entrances.append('Hyrule Castle Entrance (South)')
|
|
||||||
|
|
||||||
if not world.shuffle_ganon:
|
|
||||||
connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player)
|
|
||||||
else:
|
|
||||||
dw_entrances.append('Ganons Tower')
|
|
||||||
caves.append('Ganons Tower Exit')
|
|
||||||
|
|
||||||
# we randomize which world requirements we fulfill first so we get better dungeon distribution
|
|
||||||
if random.randint(0, 1) == 0:
|
|
||||||
connect_mandatory_exits(world, lw_entrances, caves, lw_must_exits, player)
|
|
||||||
connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player)
|
|
||||||
else:
|
|
||||||
connect_mandatory_exits(world, dw_entrances, caves, dw_must_exits, player)
|
|
||||||
connect_mandatory_exits(world, lw_entrances, caves, lw_must_exits, player)
|
|
||||||
if world.mode[player] == 'standard':
|
|
||||||
# rest of hyrule castle must be in light world
|
|
||||||
connect_caves(world, lw_entrances, [], [('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)')], player)
|
|
||||||
|
|
||||||
# place old man, has limited options
|
|
||||||
# exit has to come from specific set of doors, the entrance is free to move about
|
|
||||||
old_man_entrances = [door for door in old_man_entrances if door in lw_entrances]
|
|
||||||
random.shuffle(old_man_entrances)
|
|
||||||
old_man_exit = old_man_entrances.pop()
|
|
||||||
lw_entrances.remove(old_man_exit)
|
|
||||||
|
|
||||||
random.shuffle(lw_entrances)
|
|
||||||
old_man_entrance = lw_entrances.pop()
|
|
||||||
connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player)
|
|
||||||
connect_two_way(world, old_man_exit, 'Old Man Cave Exit (East)', player)
|
|
||||||
|
|
||||||
# place Old Man House in Light World
|
|
||||||
connect_caves(world, lw_entrances, [], list(Old_Man_House), player) #need this to avoid badness with multiple seeds
|
|
||||||
|
|
||||||
# now scramble the rest
|
|
||||||
connect_caves(world, lw_entrances, dw_entrances, caves, player)
|
|
||||||
|
|
||||||
# scramble holes
|
|
||||||
scramble_holes(world, player)
|
|
||||||
|
|
||||||
# place blacksmith, has limited options
|
|
||||||
random.shuffle(blacksmith_doors)
|
|
||||||
blacksmith_hut = blacksmith_doors.pop()
|
|
||||||
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
|
|
||||||
bomb_shop_doors.extend(blacksmith_doors)
|
|
||||||
|
|
||||||
# place bomb shop, has limited options
|
|
||||||
random.shuffle(bomb_shop_doors)
|
|
||||||
bomb_shop = bomb_shop_doors.pop()
|
|
||||||
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
|
|
||||||
single_doors.extend(bomb_shop_doors)
|
|
||||||
|
|
||||||
# tavern back door cannot be shuffled yet
|
|
||||||
connect_doors(world, ['Tavern North'], ['Tavern'], player)
|
|
||||||
|
|
||||||
# place remaining doors
|
|
||||||
connect_doors(world, single_doors, door_targets, player)
|
|
||||||
elif not invFlag and world.shuffle[player] == 'madness_legacy':
|
|
||||||
# here lie dragons, connections are no longer two way
|
|
||||||
lw_entrances = list(LW_Entrances + LW_Dungeon_Entrances + Old_Man_Entrances)
|
|
||||||
dw_entrances = list(DW_Entrances + DW_Dungeon_Entrances)
|
|
||||||
dw_entrances_must_exits = list(DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit)
|
|
||||||
|
|
||||||
lw_doors = list(LW_Entrances + LW_Dungeon_Entrances + LW_Dungeon_Entrances_Must_Exit) + ['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump',
|
|
||||||
'Lumberjack Tree Cave'] + list(Old_Man_Entrances)
|
|
||||||
dw_doors = list(DW_Entrances + DW_Dungeon_Entrances + DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit) + ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)']
|
|
||||||
|
|
||||||
random.shuffle(lw_doors)
|
|
||||||
random.shuffle(dw_doors)
|
|
||||||
|
|
||||||
dw_entrances_must_exits.append('Skull Woods Second Section Door (West)')
|
|
||||||
dw_entrances.append('Skull Woods Second Section Door (East)')
|
|
||||||
dw_entrances.append('Skull Woods First Section Door')
|
|
||||||
|
|
||||||
lw_entrances.extend(['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave'])
|
|
||||||
|
|
||||||
lw_entrances_must_exits = list(LW_Dungeon_Entrances_Must_Exit)
|
|
||||||
|
|
||||||
old_man_entrances = list(Old_Man_Entrances) + ['Tower of Hera']
|
|
||||||
|
|
||||||
mandatory_light_world = ['Old Man House Exit (Bottom)', 'Old Man House Exit (Top)']
|
|
||||||
mandatory_dark_world = []
|
|
||||||
caves = list(Cave_Exits + Dungeon_Exits + Cave_Three_Exits)
|
|
||||||
|
|
||||||
# shuffle up holes
|
|
||||||
|
|
||||||
lw_hole_entrances = ['Kakariko Well Drop', 'Bat Cave Drop', 'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree', 'Sanctuary Grave']
|
|
||||||
dw_hole_entrances = ['Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole']
|
|
||||||
|
|
||||||
hole_targets = [('Kakariko Well Exit', 'Kakariko Well (top)'),
|
|
||||||
('Bat Cave Exit', 'Bat Cave (right)'),
|
|
||||||
('North Fairy Cave Exit', 'North Fairy Cave'),
|
|
||||||
('Lost Woods Hideout Exit', 'Lost Woods Hideout (top)'),
|
|
||||||
('Lumberjack Tree Exit', 'Lumberjack Tree (top)'),
|
|
||||||
(('Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)'), 'Skull Back Drop')]
|
|
||||||
|
|
||||||
if world.mode[player] == 'standard':
|
|
||||||
# cannot move uncle cave
|
|
||||||
connect_entrance(world, 'Hyrule Castle Secret Entrance Drop', 'Hyrule Castle Secret Entrance', player)
|
|
||||||
connect_exit(world, 'Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance Stairs', player)
|
|
||||||
connect_entrance(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player)
|
|
||||||
else:
|
|
||||||
lw_hole_entrances.append('Hyrule Castle Secret Entrance Drop')
|
|
||||||
hole_targets.append(('Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance'))
|
|
||||||
lw_doors.append('Hyrule Castle Secret Entrance Stairs')
|
|
||||||
lw_entrances.append('Hyrule Castle Secret Entrance Stairs')
|
|
||||||
|
|
||||||
if not world.shuffle_ganon:
|
|
||||||
connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player)
|
|
||||||
connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
|
|
||||||
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
|
|
||||||
else:
|
|
||||||
dw_entrances.append('Ganons Tower')
|
|
||||||
caves.append('Ganons Tower Exit')
|
|
||||||
dw_hole_entrances.append('Pyramid Hole')
|
|
||||||
hole_targets.append(('Pyramid Exit', 'Pyramid'))
|
|
||||||
dw_entrances_must_exits.append('Pyramid Entrance')
|
|
||||||
dw_doors.extend(['Ganons Tower', 'Pyramid Entrance'])
|
|
||||||
|
|
||||||
random.shuffle(lw_hole_entrances)
|
|
||||||
random.shuffle(dw_hole_entrances)
|
|
||||||
random.shuffle(hole_targets)
|
|
||||||
|
|
||||||
# decide if skull woods first section should be in light or dark world
|
|
||||||
sw_light = random.randint(0, 1) == 0
|
|
||||||
if sw_light:
|
|
||||||
sw_hole_pool = lw_hole_entrances
|
|
||||||
mandatory_light_world.append('Skull Woods First Section Exit')
|
|
||||||
else:
|
|
||||||
sw_hole_pool = dw_hole_entrances
|
|
||||||
mandatory_dark_world.append('Skull Woods First Section Exit')
|
|
||||||
for target in ['Skull Left Drop', 'Skull Pinball', 'Skull Pot Circle']:
|
|
||||||
connect_entrance(world, sw_hole_pool.pop(), target, player)
|
|
||||||
|
|
||||||
# sanctuary has to be in light world
|
|
||||||
connect_entrance(world, lw_hole_entrances.pop(), 'Sewer Drop', player)
|
|
||||||
mandatory_light_world.append('Sanctuary Exit')
|
|
||||||
|
|
||||||
# fill up remaining holes
|
|
||||||
for hole in dw_hole_entrances:
|
|
||||||
exits, target = hole_targets.pop()
|
|
||||||
mandatory_dark_world.append(exits)
|
|
||||||
connect_entrance(world, hole, target, player)
|
|
||||||
|
|
||||||
for hole in lw_hole_entrances:
|
|
||||||
exits, target = hole_targets.pop()
|
|
||||||
mandatory_light_world.append(exits)
|
|
||||||
connect_entrance(world, hole, target, player)
|
|
||||||
|
|
||||||
# hyrule castle handling
|
|
||||||
if world.mode[player] == 'standard':
|
|
||||||
# must connect front of hyrule castle to do escape
|
|
||||||
connect_entrance(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
|
|
||||||
connect_exit(world, 'Hyrule Castle Exit (South)', 'Hyrule Castle Entrance (South)', player)
|
|
||||||
mandatory_light_world.append(('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
|
||||||
else:
|
|
||||||
lw_doors.append('Hyrule Castle Entrance (South)')
|
|
||||||
lw_entrances.append('Hyrule Castle Entrance (South)')
|
|
||||||
caves.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
|
||||||
|
|
||||||
# now let's deal with mandatory reachable stuff
|
|
||||||
def extract_reachable_exit(cavelist):
|
|
||||||
random.shuffle(cavelist)
|
|
||||||
candidate = None
|
|
||||||
for cave in cavelist:
|
|
||||||
if isinstance(cave, tuple) and len(cave) > 1:
|
|
||||||
# special handling: TRock and Spectracle Rock cave have two entries that we should consider entrance only
|
|
||||||
# ToDo this should be handled in a more sensible manner
|
|
||||||
if cave[0] in ['Turtle Rock Exit (Front)', 'Spectacle Rock Cave Exit (Peak)'] and len(cave) == 2:
|
|
||||||
continue
|
|
||||||
candidate = cave
|
|
||||||
break
|
|
||||||
if candidate is None:
|
|
||||||
raise RuntimeError('No suitable cave.')
|
|
||||||
cavelist.remove(candidate)
|
|
||||||
return candidate
|
|
||||||
|
|
||||||
def connect_reachable_exit(entrance, general, worldspecific, worldoors):
|
|
||||||
# select which one is the primary option
|
|
||||||
if random.randint(0, 1) == 0:
|
|
||||||
primary = general
|
|
||||||
secondary = worldspecific
|
|
||||||
else:
|
|
||||||
primary = worldspecific
|
|
||||||
secondary = general
|
|
||||||
|
|
||||||
try:
|
|
||||||
cave = extract_reachable_exit(primary)
|
|
||||||
except RuntimeError:
|
|
||||||
cave = extract_reachable_exit(secondary)
|
|
||||||
|
|
||||||
exit = cave[-1]
|
|
||||||
cave = cave[:-1]
|
|
||||||
connect_exit(world, exit, entrance, player)
|
|
||||||
connect_entrance(world, worldoors.pop(), exit, player)
|
|
||||||
# rest of cave now is forced to be in this world
|
|
||||||
worldspecific.append(cave)
|
|
||||||
|
|
||||||
# we randomize which world requirements we fulfill first so we get better dungeon distribution
|
|
||||||
if random.randint(0, 1) == 0:
|
|
||||||
for entrance in lw_entrances_must_exits:
|
|
||||||
connect_reachable_exit(entrance, caves, mandatory_light_world, lw_doors)
|
|
||||||
for entrance in dw_entrances_must_exits:
|
|
||||||
connect_reachable_exit(entrance, caves, mandatory_dark_world, dw_doors)
|
|
||||||
else:
|
|
||||||
for entrance in dw_entrances_must_exits:
|
|
||||||
connect_reachable_exit(entrance, caves, mandatory_dark_world, dw_doors)
|
|
||||||
for entrance in lw_entrances_must_exits:
|
|
||||||
connect_reachable_exit(entrance, caves, mandatory_light_world, lw_doors)
|
|
||||||
|
|
||||||
# place old man, has limited options
|
|
||||||
# exit has to come from specific set of doors, the entrance is free to move about
|
|
||||||
old_man_entrances = [entrance for entrance in old_man_entrances if entrance in lw_entrances]
|
|
||||||
random.shuffle(old_man_entrances)
|
|
||||||
old_man_exit = old_man_entrances.pop()
|
|
||||||
lw_entrances.remove(old_man_exit)
|
|
||||||
|
|
||||||
connect_exit(world, 'Old Man Cave Exit (East)', old_man_exit, player)
|
|
||||||
connect_entrance(world, lw_doors.pop(), 'Old Man Cave Exit (East)', player)
|
|
||||||
mandatory_light_world.append('Old Man Cave Exit (West)')
|
|
||||||
|
|
||||||
# we connect up the mandatory associations we have found
|
|
||||||
for mandatory in mandatory_light_world:
|
|
||||||
if not isinstance(mandatory, tuple):
|
|
||||||
mandatory = (mandatory,)
|
|
||||||
for exit in mandatory:
|
|
||||||
# point out somewhere
|
|
||||||
connect_exit(world, exit, lw_entrances.pop(), player)
|
|
||||||
# point in from somewhere
|
|
||||||
connect_entrance(world, lw_doors.pop(), exit, player)
|
|
||||||
|
|
||||||
for mandatory in mandatory_dark_world:
|
|
||||||
if not isinstance(mandatory, tuple):
|
|
||||||
mandatory = (mandatory,)
|
|
||||||
for exit in mandatory:
|
|
||||||
# point out somewhere
|
|
||||||
connect_exit(world, exit, dw_entrances.pop(), player)
|
|
||||||
# point in from somewhere
|
|
||||||
connect_entrance(world, dw_doors.pop(), exit, player)
|
|
||||||
|
|
||||||
# handle remaining caves
|
|
||||||
while caves:
|
|
||||||
# connect highest exit count caves first, prevent issue where we have 2 or 3 exits across worlds left to fill
|
|
||||||
cave_candidate = (None, 0)
|
|
||||||
for i, cave in enumerate(caves):
|
|
||||||
if isinstance(cave, str):
|
|
||||||
cave = (cave,)
|
|
||||||
if len(cave) > cave_candidate[1]:
|
|
||||||
cave_candidate = (i, len(cave))
|
|
||||||
cave = caves.pop(cave_candidate[0])
|
|
||||||
|
|
||||||
place_lightworld = random.randint(0, 1) == 0
|
|
||||||
if place_lightworld:
|
|
||||||
target_doors = lw_doors
|
|
||||||
target_entrances = lw_entrances
|
|
||||||
else:
|
|
||||||
target_doors = dw_doors
|
|
||||||
target_entrances = dw_entrances
|
|
||||||
|
|
||||||
if isinstance(cave, str):
|
|
||||||
cave = (cave,)
|
|
||||||
|
|
||||||
# check if we can still fit the cave into our target group
|
|
||||||
if len(target_doors) < len(cave):
|
|
||||||
if not place_lightworld:
|
|
||||||
target_doors = lw_doors
|
|
||||||
target_entrances = lw_entrances
|
|
||||||
else:
|
|
||||||
target_doors = dw_doors
|
|
||||||
target_entrances = dw_entrances
|
|
||||||
|
|
||||||
for exit in cave:
|
|
||||||
connect_exit(world, exit, target_entrances.pop(), player)
|
|
||||||
connect_entrance(world, target_doors.pop(), exit, player)
|
|
||||||
|
|
||||||
# handle simple doors
|
|
||||||
|
|
||||||
single_doors = list(Single_Cave_Doors)
|
|
||||||
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
|
|
||||||
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
|
|
||||||
door_targets = list(Single_Cave_Targets)
|
|
||||||
|
|
||||||
# place blacksmith, has limited options
|
|
||||||
random.shuffle(blacksmith_doors)
|
|
||||||
blacksmith_hut = blacksmith_doors.pop()
|
|
||||||
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
|
|
||||||
bomb_shop_doors.extend(blacksmith_doors)
|
|
||||||
|
|
||||||
# place dam and pyramid fairy, have limited options
|
|
||||||
random.shuffle(bomb_shop_doors)
|
|
||||||
bomb_shop = bomb_shop_doors.pop()
|
|
||||||
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
|
|
||||||
single_doors.extend(bomb_shop_doors)
|
|
||||||
|
|
||||||
# tavern back door cannot be shuffled yet
|
|
||||||
connect_doors(world, ['Tavern North'], ['Tavern'], player)
|
|
||||||
|
|
||||||
# place remaining doors
|
|
||||||
connect_doors(world, single_doors, door_targets, player)
|
|
||||||
elif world.shuffle[player] == 'insanity':
|
elif world.shuffle[player] == 'insanity':
|
||||||
# beware ye who enter here
|
# beware ye who enter here
|
||||||
|
|
||||||
@@ -1164,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')
|
||||||
@@ -1177,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')
|
||||||
@@ -1304,205 +931,6 @@ def link_entrances(world, player):
|
|||||||
|
|
||||||
# place remaining doors
|
# place remaining doors
|
||||||
connect_doors(world, doors, door_targets, player)
|
connect_doors(world, doors, door_targets, player)
|
||||||
elif world.shuffle[player] == 'insanity_legacy':
|
|
||||||
world.fix_fake_world[player] = False
|
|
||||||
# beware ye who enter here
|
|
||||||
|
|
||||||
if not invFlag:
|
|
||||||
entrances_must_exits = DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit + LW_Dungeon_Entrances_Must_Exit + ['Skull Woods Second Section Door (West)']
|
|
||||||
|
|
||||||
doors = LW_Entrances + LW_Dungeon_Entrances + DW_Entrances + DW_Dungeon_Entrances + Old_Man_Entrances + ['Skull Woods Second Section Door (East)', 'Skull Woods First Section Door', 'Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave']
|
|
||||||
else:
|
|
||||||
entrances_must_exits = Inverted_LW_Entrances_Must_Exit + Inverted_LW_Dungeon_Entrances_Must_Exit
|
|
||||||
|
|
||||||
doors = Inverted_LW_Entrances + Inverted_LW_Dungeon_Entrances + Inverted_LW_Entrances_Must_Exit + Inverted_LW_Dungeon_Entrances_Must_Exit + ['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave', 'Hyrule Castle Secret Entrance Stairs'] + Inverted_Old_Man_Entrances +\
|
|
||||||
Inverted_DW_Entrances + Inverted_DW_Dungeon_Entrances + ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)'] +\
|
|
||||||
Inverted_LW_Single_Cave_Doors + Inverted_DW_Single_Cave_Doors + ['Desert Palace Entrance (West)', 'Desert Palace Entrance (North)']
|
|
||||||
|
|
||||||
exit_pool = list(doors)
|
|
||||||
|
|
||||||
# randomize which desert ledge door is a must-exit
|
|
||||||
if random.randint(0, 1) == 0:
|
|
||||||
entrances_must_exits.append('Desert Palace Entrance (North)')
|
|
||||||
else:
|
|
||||||
entrances_must_exits.append('Desert Palace Entrance (West)')
|
|
||||||
|
|
||||||
doors = LW_Entrances + LW_Dungeon_Entrances + LW_Dungeon_Entrances_Must_Exit + ['Kakariko Well Cave', 'Bat Cave Cave', 'North Fairy Cave', 'Sanctuary', 'Lost Woods Hideout Stump', 'Lumberjack Tree Cave'] + Old_Man_Entrances +\
|
|
||||||
DW_Entrances + DW_Dungeon_Entrances + DW_Entrances_Must_Exit + DW_Dungeon_Entrances_Must_Exit + ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)']
|
|
||||||
|
|
||||||
random.shuffle(doors)
|
|
||||||
|
|
||||||
old_man_entrances = list(Old_Man_Entrances) + ['Tower of Hera']
|
|
||||||
|
|
||||||
caves = Cave_Exits + Dungeon_Exits + Cave_Three_Exits + ['Old Man House Exit (Bottom)', 'Old Man House Exit (Top)', 'Skull Woods First Section Exit', 'Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)',
|
|
||||||
'Kakariko Well Exit', 'Bat Cave Exit', 'North Fairy Cave Exit', 'Lost Woods Hideout Exit', 'Lumberjack Tree Exit', 'Sanctuary Exit']
|
|
||||||
|
|
||||||
# shuffle up holes
|
|
||||||
|
|
||||||
hole_entrances = ['Kakariko Well Drop', 'Bat Cave Drop', 'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree', 'Sanctuary Grave',
|
|
||||||
'Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole']
|
|
||||||
|
|
||||||
hole_targets = ['Kakariko Well (top)', 'Bat Cave (right)', 'North Fairy Cave', 'Lost Woods Hideout (top)', 'Lumberjack Tree (top)', 'Sewer Drop', 'Skull Back Drop',
|
|
||||||
'Skull Left Drop', 'Skull Pinball', 'Skull Pot Circle']
|
|
||||||
|
|
||||||
# tavern back door cannot be shuffled yet
|
|
||||||
connect_doors(world, ['Tavern North'], ['Tavern'], player)
|
|
||||||
|
|
||||||
if world.mode[player] == 'standard':
|
|
||||||
# cannot move uncle cave
|
|
||||||
connect_entrance(world, 'Hyrule Castle Secret Entrance Drop', 'Hyrule Castle Secret Entrance', player)
|
|
||||||
connect_exit(world, 'Hyrule Castle Secret Entrance Exit', 'Hyrule Castle Secret Entrance Stairs', player)
|
|
||||||
connect_entrance(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player)
|
|
||||||
else:
|
|
||||||
hole_entrances.append('Hyrule Castle Secret Entrance Drop')
|
|
||||||
hole_targets.append('Hyrule Castle Secret Entrance')
|
|
||||||
doors.append('Hyrule Castle Secret Entrance Stairs')
|
|
||||||
caves.append('Hyrule Castle Secret Entrance Exit')
|
|
||||||
|
|
||||||
if not world.shuffle_ganon:
|
|
||||||
connect_two_way(world, 'Ganons Tower', 'Ganons Tower Exit', player)
|
|
||||||
if invFlag == (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
|
||||||
connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
|
|
||||||
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
|
|
||||||
else:
|
|
||||||
connect_two_way(world, 'Inverted Pyramid Entrance', 'Pyramid Exit', player)
|
|
||||||
connect_entrance(world, 'Inverted Pyramid Hole', 'Pyramid', player)
|
|
||||||
else:
|
|
||||||
caves.extend(['Ganons Tower Exit', 'Pyramid Exit'])
|
|
||||||
hole_targets.append('Pyramid')
|
|
||||||
|
|
||||||
if not invFlag:
|
|
||||||
doors.extend(['Ganons Tower'])
|
|
||||||
exit_pool.extend(['Ganons Tower'])
|
|
||||||
else:
|
|
||||||
doors.extend(['Agahnims Tower'])
|
|
||||||
exit_pool.extend(['Agahnims Tower'])
|
|
||||||
|
|
||||||
if invFlag == (0x1b in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
|
||||||
hole_entrances.append('Pyramid Hole')
|
|
||||||
doors.extend(['Pyramid Entrance'])
|
|
||||||
exit_pool.extend(['Pyramid Entrance'])
|
|
||||||
else:
|
|
||||||
hole_entrances.append('Inverted Pyramid Hole')
|
|
||||||
doors.extend(['Inverted Pyramid Entrance'])
|
|
||||||
exit_pool.extend(['Inverted Pyramid Entrance'])
|
|
||||||
|
|
||||||
random.shuffle(hole_entrances)
|
|
||||||
random.shuffle(hole_targets)
|
|
||||||
random.shuffle(exit_pool)
|
|
||||||
|
|
||||||
# fill up holes
|
|
||||||
for hole in hole_entrances:
|
|
||||||
connect_entrance(world, hole, hole_targets.pop(), player)
|
|
||||||
|
|
||||||
# hyrule castle handling
|
|
||||||
if world.mode[player] == 'standard':
|
|
||||||
# must connect front of hyrule castle to do escape
|
|
||||||
connect_entrance(world, 'Hyrule Castle Entrance (South)', 'Hyrule Castle Exit (South)', player)
|
|
||||||
connect_exit(world, 'Hyrule Castle Exit (South)', 'Hyrule Castle Entrance (South)', player)
|
|
||||||
caves.append(('Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
|
||||||
else:
|
|
||||||
doors.append('Hyrule Castle Entrance (South)')
|
|
||||||
caves.append(('Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)'))
|
|
||||||
|
|
||||||
if not world.shufflelinks[player]:
|
|
||||||
if not invFlag:
|
|
||||||
links_house = 'Links House'
|
|
||||||
else:
|
|
||||||
links_house = 'Big Shop Shop'
|
|
||||||
else:
|
|
||||||
if not invFlag:
|
|
||||||
links_house_doors = [i for i in doors if i not in Sanctuary_Doors + Isolated_LH_Doors]
|
|
||||||
else:
|
|
||||||
links_house_doors = [i for i in doors if i not in Inverted_Dark_Sanctuary_Doors + Isolated_LH_Doors]
|
|
||||||
links_house = random.choice(links_house_doors)
|
|
||||||
connect_two_way(world, links_house, 'Links House Exit', player)
|
|
||||||
connect_exit(world, 'Chris Houlihan Room Exit', links_house, player) # should always match link's house, except for plandos
|
|
||||||
doors.remove(links_house)
|
|
||||||
exit_pool.remove(links_house)
|
|
||||||
|
|
||||||
if not invFlag:
|
|
||||||
sanc_doors = [door for door in exit_pool] #[door for door in Sanctuary_Doors if door in exit_pool]
|
|
||||||
else:
|
|
||||||
sanc_doors = [door for door in Inverted_Dark_Sanctuary_Doors if door in exit_pool]
|
|
||||||
sanc_door = random.choice(sanc_doors)
|
|
||||||
exit_pool.remove(sanc_door)
|
|
||||||
doors.remove(sanc_door)
|
|
||||||
connect_entrance(world, sanc_door, 'Dark Sanctuary Hint', player)
|
|
||||||
world.get_entrance('Dark Sanctuary Hint Exit', player).connect(world.get_entrance(sanc_door, player).parent_region)
|
|
||||||
|
|
||||||
# now let's deal with mandatory reachable stuff
|
|
||||||
def extract_reachable_exit(cavelist):
|
|
||||||
random.shuffle(cavelist)
|
|
||||||
candidate = None
|
|
||||||
for cave in cavelist:
|
|
||||||
if isinstance(cave, tuple) and len(cave) > 1:
|
|
||||||
# special handling: TRock has two entries that we should consider entrance only
|
|
||||||
# ToDo this should be handled in a more sensible manner
|
|
||||||
if cave[0] in ['Turtle Rock Exit (Front)', 'Spectacle Rock Cave Exit (Peak)'] and len(cave) == 2:
|
|
||||||
continue
|
|
||||||
candidate = cave
|
|
||||||
break
|
|
||||||
if candidate is None:
|
|
||||||
raise RuntimeError('No suitable cave.')
|
|
||||||
cavelist.remove(candidate)
|
|
||||||
return candidate
|
|
||||||
|
|
||||||
def connect_reachable_exit(entrance, caves, doors, exit_pool):
|
|
||||||
cave = extract_reachable_exit(caves)
|
|
||||||
|
|
||||||
exit = cave[-1]
|
|
||||||
cave = cave[:-1]
|
|
||||||
connect_exit(world, exit, entrance, player)
|
|
||||||
connect_entrance(world, doors.pop(), exit, player)
|
|
||||||
# rest of cave now is forced to be in this world
|
|
||||||
exit_pool.remove(entrance)
|
|
||||||
caves.append(cave)
|
|
||||||
|
|
||||||
# connect mandatory exits
|
|
||||||
for entrance in entrances_must_exits:
|
|
||||||
connect_reachable_exit(entrance, caves, doors, exit_pool)
|
|
||||||
|
|
||||||
# place old man, has limited options
|
|
||||||
# exit has to come from specific set of doors, the entrance is free to move about
|
|
||||||
old_man_entrances = [entrance for entrance in old_man_entrances if entrance in exit_pool]
|
|
||||||
random.shuffle(old_man_entrances)
|
|
||||||
old_man_exit = old_man_entrances.pop()
|
|
||||||
exit_pool.remove(old_man_exit)
|
|
||||||
|
|
||||||
connect_exit(world, 'Old Man Cave Exit (East)', old_man_exit, player)
|
|
||||||
connect_entrance(world, doors.pop(), 'Old Man Cave Exit (East)', player)
|
|
||||||
caves.append('Old Man Cave Exit (West)')
|
|
||||||
|
|
||||||
# handle simple doors
|
|
||||||
single_doors = list(Single_Cave_Doors)
|
|
||||||
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors)
|
|
||||||
blacksmith_doors = list(Blacksmith_Single_Cave_Doors)
|
|
||||||
door_targets = list(Single_Cave_Targets)
|
|
||||||
|
|
||||||
# place blacksmith, has limited options
|
|
||||||
random.shuffle(blacksmith_doors)
|
|
||||||
blacksmith_hut = blacksmith_doors.pop()
|
|
||||||
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
|
|
||||||
doors.remove(blacksmith_hut)
|
|
||||||
|
|
||||||
# place dam and pyramid fairy, have limited options
|
|
||||||
random.shuffle(bomb_shop_doors)
|
|
||||||
bomb_shop = bomb_shop_doors.pop()
|
|
||||||
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
|
|
||||||
doors.remove(bomb_shop)
|
|
||||||
|
|
||||||
# handle remaining caves
|
|
||||||
for cave in caves:
|
|
||||||
if isinstance(cave, str):
|
|
||||||
cave = (cave,)
|
|
||||||
|
|
||||||
for exit in cave:
|
|
||||||
connect_exit(world, exit, exit_pool.pop(), player)
|
|
||||||
connect_entrance(world, doors.pop(), exit, player)
|
|
||||||
|
|
||||||
# place remaining doors
|
|
||||||
connect_doors(world, single_doors, door_targets, player)
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError('Shuffling not supported yet')
|
raise NotImplementedError('Shuffling not supported yet')
|
||||||
|
|
||||||
@@ -1515,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
|
||||||
@@ -1601,16 +1029,6 @@ def scramble_holes(world, player):
|
|||||||
('Lost Woods Hideout Exit', 'Lost Woods Hideout (top)'),
|
('Lost Woods Hideout Exit', 'Lost Woods Hideout (top)'),
|
||||||
('Lumberjack Tree Exit', 'Lumberjack Tree (top)')]
|
('Lumberjack Tree Exit', 'Lumberjack Tree (top)')]
|
||||||
|
|
||||||
if not world.shuffle_ganon:
|
|
||||||
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owSwap[player] == 'mixed'):
|
|
||||||
connect_two_way(world, 'Pyramid Entrance', 'Pyramid Exit', player)
|
|
||||||
connect_entrance(world, 'Pyramid Hole', 'Pyramid', player)
|
|
||||||
else:
|
|
||||||
connect_two_way(world, 'Inverted Pyramid Entrance', 'Pyramid Exit', player)
|
|
||||||
connect_entrance(world, 'Inverted Pyramid Hole', 'Pyramid', player)
|
|
||||||
else:
|
|
||||||
hole_targets.append(('Pyramid Exit', 'Pyramid'))
|
|
||||||
|
|
||||||
if world.mode[player] == 'standard':
|
if world.mode[player] == 'standard':
|
||||||
# cannot move uncle cave
|
# cannot move uncle cave
|
||||||
connect_two_way(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player)
|
connect_two_way(world, 'Hyrule Castle Secret Entrance Stairs', 'Hyrule Castle Secret Entrance Exit', player)
|
||||||
@@ -1622,18 +1040,31 @@ def scramble_holes(world, player):
|
|||||||
# do not shuffle sanctuary into pyramid hole unless shuffle is crossed
|
# do not shuffle sanctuary into pyramid hole unless shuffle is crossed
|
||||||
if world.shuffle[player] == 'crossed':
|
if world.shuffle[player] == 'crossed':
|
||||||
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
|
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
|
||||||
if world.shuffle_ganon:
|
|
||||||
random.shuffle(hole_targets)
|
# determine pyramid hole
|
||||||
exit, target = hole_targets.pop()
|
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:
|
||||||
connect_two_way(world, 'Inverted Pyramid Entrance', 'Pyramid Exit', player)
|
connect_two_way(world, 'Inverted Pyramid Entrance', 'Pyramid Exit', player)
|
||||||
connect_entrance(world, 'Inverted Pyramid Hole', 'Pyramid', player)
|
connect_entrance(world, 'Inverted Pyramid Hole', 'Pyramid', player)
|
||||||
|
else:
|
||||||
|
hole_targets.append(('Pyramid Exit', 'Pyramid'))
|
||||||
|
|
||||||
|
random.shuffle(hole_targets)
|
||||||
|
exit, target = hole_targets.pop()
|
||||||
|
if (world.mode[player] == 'inverted') == (0x03 in world.owswaps[player][0] and world.owMixed[player]):
|
||||||
|
connect_two_way(world, 'Pyramid Entrance', exit, player)
|
||||||
|
connect_entrance(world, 'Pyramid Hole', target, player)
|
||||||
|
else:
|
||||||
|
connect_two_way(world, 'Inverted Pyramid Entrance', exit, player)
|
||||||
|
connect_entrance(world, 'Inverted Pyramid Hole', target, player)
|
||||||
|
|
||||||
if world.shuffle[player] != 'crossed':
|
if world.shuffle[player] != 'crossed':
|
||||||
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
|
hole_targets.append(('Sanctuary Exit', 'Sewer Drop'))
|
||||||
|
|
||||||
|
# shuffle the rest
|
||||||
random.shuffle(hole_targets)
|
random.shuffle(hole_targets)
|
||||||
for entrance, drop in hole_entrances:
|
for entrance, drop in hole_entrances:
|
||||||
exit, target = hole_targets.pop()
|
exit, target = hole_targets.pop()
|
||||||
|
|||||||
+5
-6
@@ -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 = []
|
||||||
@@ -986,13 +986,12 @@ def test():
|
|||||||
for mode in ['open', 'standard', 'inverted', 'retro']:
|
for mode in ['open', 'standard', 'inverted', 'retro']:
|
||||||
for swords in ['random', 'assured', 'swordless', 'vanilla']:
|
for swords in ['random', 'assured', 'swordless', 'vanilla']:
|
||||||
for progressive in ['on', 'off']:
|
for progressive in ['on', 'off']:
|
||||||
for shuffle in ['full', 'insanity_legacy']:
|
for shuffle in ['vanilla', 'full', 'crossed', 'insanity']:
|
||||||
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', 'vanilla']:
|
for bombbag in [True, False]:
|
||||||
for owSwap in ['mixed', 'vanilla']:
|
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
|
||||||
|
|||||||
+4
-3
@@ -4,7 +4,7 @@ from collections import defaultdict, deque
|
|||||||
|
|
||||||
from BaseClasses import DoorType
|
from BaseClasses import DoorType
|
||||||
from Regions import dungeon_events
|
from Regions import dungeon_events
|
||||||
from Dungeons import dungeon_keys, dungeon_bigs
|
from Dungeons import dungeon_keys, dungeon_bigs, default_key_counts
|
||||||
from DungeonGenerator import ExplorationState, special_big_key_doors
|
from DungeonGenerator import ExplorationState, special_big_key_doors
|
||||||
|
|
||||||
|
|
||||||
@@ -1384,9 +1384,10 @@ def create_key_counters(key_layout, world, player):
|
|||||||
flat_proposal = key_layout.flat_prop
|
flat_proposal = key_layout.flat_prop
|
||||||
state = ExplorationState(dungeon=key_layout.sector.name)
|
state = ExplorationState(dungeon=key_layout.sector.name)
|
||||||
if world.doorShuffle[player] == 'vanilla':
|
if world.doorShuffle[player] == 'vanilla':
|
||||||
state.key_locations = len(world.get_dungeon(key_layout.sector.name, player).small_keys)
|
state.key_locations = default_key_counts[key_layout.sector.name]
|
||||||
else:
|
else:
|
||||||
state.key_locations = world.dungeon_layouts[player][key_layout.sector.name].key_doors_num
|
builder = world.dungeon_layouts[player][key_layout.sector.name]
|
||||||
|
state.key_locations = builder.total_keys - builder.key_drop_cnt
|
||||||
state.big_key_special, special_region = False, None
|
state.big_key_special, special_region = False, None
|
||||||
for region in key_layout.sector.regions:
|
for region in key_layout.sector.regions:
|
||||||
for location in region.locations:
|
for location in region.locations:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc
|
|||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
__version__ = '0.5.0.2-u'
|
__version__ = '0.5.0.3-u'
|
||||||
|
|
||||||
from source.classes.BabelFish import BabelFish
|
from source.classes.BabelFish import BabelFish
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
+1
-1
@@ -846,7 +846,7 @@ async def track_locations(ctx : Context, roomid, roomdata):
|
|||||||
new_locations.append(Regions.lookup_name_to_id[location])
|
new_locations.append(Regions.lookup_name_to_id[location])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if roomid in location_shop_ids:
|
if ctx.shop_mode or ctx.retro_mode:
|
||||||
misc_data = await snes_read(ctx, SHOP_ADDR, SHOP_SRAM_LEN)
|
misc_data = await snes_read(ctx, SHOP_ADDR, SHOP_SRAM_LEN)
|
||||||
for cnt, b in enumerate(misc_data):
|
for cnt, b in enumerate(misc_data):
|
||||||
my_check = Regions.shop_table_by_location_id[0x400000 + cnt]
|
my_check = Regions.shop_table_by_location_id[0x400000 + cnt]
|
||||||
|
|||||||
+2
-2
@@ -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')
|
||||||
|
|||||||
+4
-1
@@ -697,7 +697,6 @@ OWTileRegions = bidict({
|
|||||||
'Spectacle Rock Ledge': 0x03,
|
'Spectacle Rock Ledge': 0x03,
|
||||||
'West Death Mountain (Bottom)': 0x03,
|
'West Death Mountain (Bottom)': 0x03,
|
||||||
|
|
||||||
'Death Mountain Floating Island': 0x05,
|
|
||||||
'East Death Mountain (Top West)': 0x05,
|
'East Death Mountain (Top West)': 0x05,
|
||||||
'East Death Mountain (Top East)': 0x05,
|
'East Death Mountain (Top East)': 0x05,
|
||||||
'Spiral Cave Ledge': 0x05,
|
'Spiral Cave Ledge': 0x05,
|
||||||
@@ -706,6 +705,7 @@ OWTileRegions = bidict({
|
|||||||
'Fairy Ascension Plateau': 0x05,
|
'Fairy Ascension Plateau': 0x05,
|
||||||
'East Death Mountain (Bottom Left)': 0x05,
|
'East Death Mountain (Bottom Left)': 0x05,
|
||||||
'East Death Mountain (Bottom)': 0x05,
|
'East Death Mountain (Bottom)': 0x05,
|
||||||
|
'Death Mountain Floating Island': 0x05,
|
||||||
|
|
||||||
'Death Mountain TR Pegs': 0x07,
|
'Death Mountain TR Pegs': 0x07,
|
||||||
'Death Mountain TR Pegs Ledge': 0x07,
|
'Death Mountain TR Pegs Ledge': 0x07,
|
||||||
@@ -846,6 +846,9 @@ OWTileRegions = bidict({
|
|||||||
'East Dark Death Mountain (Top)': 0x45,
|
'East Dark Death Mountain (Top)': 0x45,
|
||||||
'East Dark Death Mountain (Bottom Left)': 0x45,
|
'East Dark Death Mountain (Bottom Left)': 0x45,
|
||||||
'East Dark Death Mountain (Bottom)': 0x45,
|
'East Dark Death Mountain (Bottom)': 0x45,
|
||||||
|
'Dark Death Mountain Ledge': 0x45,
|
||||||
|
'Dark Death Mountain Isolated Ledge': 0x45,
|
||||||
|
'Dark Death Mountain Floating Island': 0x45,
|
||||||
|
|
||||||
'Turtle Rock Area': 0x47,
|
'Turtle Rock Area': 0x47,
|
||||||
'Turtle Rock Ledge': 0x47,
|
'Turtle Rock Ledge': 0x47,
|
||||||
|
|||||||
+377
-64
@@ -2,7 +2,7 @@ import RaceRandom as random, logging, copy
|
|||||||
from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance
|
from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance
|
||||||
from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OpenStd, parallel_links, IsParallel
|
from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OpenStd, parallel_links, IsParallel
|
||||||
|
|
||||||
__version__ = '0.1.7.4-u'
|
__version__ = '0.1.8.0-u'
|
||||||
|
|
||||||
def link_overworld(world, player):
|
def link_overworld(world, player):
|
||||||
# setup mandatory connections
|
# setup mandatory connections
|
||||||
@@ -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:
|
||||||
@@ -148,61 +164,93 @@ def link_overworld(world, player):
|
|||||||
|
|
||||||
connected_edges = []
|
connected_edges = []
|
||||||
|
|
||||||
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]:
|
||||||
for grouping in (trimmed_groups,):
|
# 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)
|
connect_custom(world, connected_edges, player)
|
||||||
|
|
||||||
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
|
||||||
|
if world.owShuffle[player] != 'vanilla':
|
||||||
|
# layout shuffle
|
||||||
random.shuffle(groups)
|
random.shuffle(groups)
|
||||||
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)
|
||||||
|
random.shuffle(forward_edge_sets)
|
||||||
random.shuffle(back_edge_sets)
|
random.shuffle(back_edge_sets)
|
||||||
for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets):
|
if len(forward_edge_sets) > 0:
|
||||||
|
f = 0
|
||||||
|
b = 0
|
||||||
|
while f < len(forward_edge_sets) and b < len(back_edge_sets):
|
||||||
|
forward_set = forward_edge_sets[f]
|
||||||
|
back_set = back_edge_sets[b]
|
||||||
|
while forward_set[0] in connected_edges:
|
||||||
|
f += 1
|
||||||
|
if f < len(forward_edge_sets):
|
||||||
|
forward_set = forward_edge_sets[f]
|
||||||
|
f += 1
|
||||||
|
while back_set[0] in connected_edges:
|
||||||
|
b += 1
|
||||||
|
if b < len(back_edge_sets):
|
||||||
|
back_set = back_edge_sets[b]
|
||||||
|
b += 1
|
||||||
assert len(forward_set) == len(back_set)
|
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)
|
else:
|
||||||
connected_edges.append(back_edge)
|
# vanilla/crossed shuffle
|
||||||
if world.owShuffle[player] == 'parallel':
|
for (forward_edge_sets, back_edge_sets) in groups:
|
||||||
if forward_edge in parallel_links.keys() or forward_edge in parallel_links.inverse.keys():
|
assert len(forward_edge_sets) == len(back_edge_sets)
|
||||||
try:
|
for (forward_set, back_set) in zip(forward_edge_sets, back_edge_sets):
|
||||||
parallel_forward_edge = parallel_links[forward_edge] if forward_edge in parallel_links.keys() else parallel_links.inverse[forward_edge][0]
|
assert len(forward_set) == len(back_set)
|
||||||
parallel_back_edge = parallel_links[back_edge] if back_edge in parallel_links.keys() else parallel_links.inverse[back_edge][0]
|
swapped = random.randint(0, 1)
|
||||||
connect_two_way(world, parallel_forward_edge, parallel_back_edge, player)
|
for (forward_edge, back_edge) in zip(forward_set, back_set):
|
||||||
connected_edges.append(parallel_forward_edge)
|
if forward_edge not in connected_edges and back_edge not in connected_edges:
|
||||||
connected_edges.append(parallel_back_edge)
|
if swapped:
|
||||||
except KeyError:
|
forward_edge = parallel_links[forward_edge] if forward_edge in parallel_links else parallel_links.inverse[forward_edge][0]
|
||||||
# TODO: Figure out why non-parallel edges are getting into parallel groups
|
connect_two_way(world, forward_edge, back_edge, player, connected_edges)
|
||||||
raise KeyError('No parallel edge for edge %d' % back_edge)
|
|
||||||
|
|
||||||
assert len(connected_edges) == len(default_connections) * 2, connected_edges
|
assert len(connected_edges) == len(default_connections) * 2, connected_edges
|
||||||
|
|
||||||
@@ -211,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)
|
||||||
@@ -233,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]
|
||||||
@@ -270,18 +318,23 @@ 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)
|
if edgename1 in connected_edges or edgename2 in connected_edges:
|
||||||
connected_edges.append(edgename1)
|
owedge1 = world.check_for_owedge(edgename1, player)
|
||||||
connected_edges.append(edgename2)
|
owedge2 = world.check_for_owedge(edgename2, player)
|
||||||
|
if owedge1.dest is not None and owedge1.dest.name == owedge2.name:
|
||||||
|
continue # if attempting to connect a pair that was already connected earlier, allow it to continue
|
||||||
|
raise RuntimeError('Invalid plando connection: rule violation based on current settings')
|
||||||
|
connect_two_way(world, edgename1, edgename2, player, connected_edges)
|
||||||
|
if world.owKeepSimilar[player]: #TODO: If connecting an edge that belongs to a similar pair, the remaining edges need to get connected automatically
|
||||||
|
continue
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
@@ -303,23 +356,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)
|
||||||
@@ -330,8 +401,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)
|
||||||
@@ -341,11 +410,94 @@ 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.owKeepSimilar[player]:
|
||||||
if world.mode[player] == 'standard':
|
if world.mode[player] == 'standard':
|
||||||
#tuple stays (A,B,C,D,_,F)
|
# tuple goes to (A,_,C,D,_,F)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, _, count) = group
|
||||||
|
new_grouping[(std, axis, terrain, count)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, _, count) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain, count)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(std, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
# tuple goes to (_,_,C,D,_,F)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, _, count) = group
|
||||||
|
new_grouping[(axis, terrain, count)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, _, count) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain, count)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
if world.mode[player] == 'standard':
|
||||||
|
# tuple goes to (A,_,C,D,_,_)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, _, _) = group
|
||||||
|
new_grouping[(std, axis, terrain)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, _, _) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
forward_edges = [[i] for l in forward_edges for i in l]
|
||||||
|
back_edges = [[i] for l in back_edges for i in l]
|
||||||
|
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(std, axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
# tuple goes to (_,_,C,D,_,_)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, _, _) = group
|
||||||
|
new_grouping[(axis, terrain)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, _, _) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
forward_edges = [[i] for l in forward_edges for i in l]
|
||||||
|
back_edges = [[i] for l in back_edges for i in l]
|
||||||
|
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
if world.owKeepSimilar[player]:
|
||||||
|
if world.mode[player] == 'standard':
|
||||||
|
# tuple goes to (A,B,C,D,_,F)
|
||||||
for grouping in (groups,):
|
for grouping in (groups,):
|
||||||
new_grouping = {}
|
new_grouping = {}
|
||||||
|
|
||||||
@@ -363,7 +515,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 = {}
|
||||||
|
|
||||||
@@ -382,7 +534,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 = {}
|
||||||
|
|
||||||
@@ -403,7 +555,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 = {}
|
||||||
|
|
||||||
@@ -424,14 +576,95 @@ def reorganize_groups(world, groups, player):
|
|||||||
|
|
||||||
return list(new_grouping.values())
|
return list(new_grouping.values())
|
||||||
elif world.owShuffle[player] == 'parallel':
|
elif world.owShuffle[player] == 'parallel':
|
||||||
#predefined shuffle groups get reorganized here
|
if 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,E,F)
|
# tuple goes to (A,_,C,D,E,F)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, parallel, count) = group
|
||||||
|
new_grouping[(std, axis, terrain, parallel, count)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, parallel, count) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain, parallel, count)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(std, axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
# tuple goes to (_,_,C,D,E,F)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, parallel, count) = group
|
||||||
|
new_grouping[(axis, terrain, parallel, count)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, parallel, count) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain, parallel, count)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(axis, terrain, parallel, count)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
if world.mode[player] == 'standard':
|
||||||
|
# tuple goes to (A,_,C,D,E,_)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, parallel, _) = group
|
||||||
|
new_grouping[(std, axis, terrain, parallel)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, _, axis, terrain, parallel, _) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
forward_edges = [[i] for l in forward_edges for i in l]
|
||||||
|
back_edges = [[i] for l in back_edges for i in l]
|
||||||
|
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(std, axis, terrain, parallel)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(std, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
# tuple goes to (_,_,C,D,E,_)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, parallel, _) = group
|
||||||
|
new_grouping[(axis, terrain, parallel)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, _, axis, terrain, parallel, _) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
forward_edges = [[i] for l in forward_edges for i in l]
|
||||||
|
back_edges = [[i] for l in back_edges for i in l]
|
||||||
|
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(axis, terrain, parallel)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
if world.owKeepSimilar[player]:
|
||||||
|
if world.mode[player] == 'standard':
|
||||||
|
# tuple stays (A,B,C,D,E,F)
|
||||||
for grouping in (groups,):
|
for grouping in (groups,):
|
||||||
return list(grouping.values())
|
return list(grouping.values())
|
||||||
else:
|
else:
|
||||||
#tuple goes to (_,B,C,D,E,F)
|
# tuple goes to (_,B,C,D,E,F)
|
||||||
for grouping in (groups,):
|
for grouping in (groups,):
|
||||||
new_grouping = {}
|
new_grouping = {}
|
||||||
|
|
||||||
@@ -450,7 +683,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,E,_)
|
# tuple goes to (A,B,C,D,E,_)
|
||||||
for grouping in (groups,):
|
for grouping in (groups,):
|
||||||
new_grouping = {}
|
new_grouping = {}
|
||||||
|
|
||||||
@@ -471,7 +704,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,E,_)
|
# tuple goes to (_,B,C,D,E,_)
|
||||||
for grouping in (groups,):
|
for grouping in (groups,):
|
||||||
new_grouping = {}
|
new_grouping = {}
|
||||||
|
|
||||||
@@ -490,14 +723,95 @@ def reorganize_groups(world, groups, player):
|
|||||||
exist_back_edges.extend(back_edges)
|
exist_back_edges.extend(back_edges)
|
||||||
new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
|
new_grouping[(region, axis, terrain, parallel)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
elif world.owShuffle[player] == 'vanilla' and world.owCrossed[player]:
|
||||||
|
if world.owKeepSimilar[player]:
|
||||||
|
if world.mode[player] == 'standard':
|
||||||
|
# tuple goes to (A,B,C,D,_,F)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, region, axis, terrain, _, count) = group
|
||||||
|
new_grouping[(std, region, axis, terrain, count)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, region, axis, terrain, _, count) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain, count)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(std, region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
# tuple goes to (_,B,C,D,_,F)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, region, axis, terrain, _, count) = group
|
||||||
|
new_grouping[(region, axis, terrain, count)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, region, axis, terrain, _, count) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain, count)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(region, axis, terrain, count)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
if world.mode[player] == 'standard':
|
||||||
|
# tuple goes to (A,B,C,D,_,_)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, region, axis, terrain, _, _) = group
|
||||||
|
new_grouping[(std, region, axis, terrain)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(std, region, axis, terrain, _, _) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
forward_edges = [[i] for l in forward_edges for i in l]
|
||||||
|
back_edges = [[i] for l in back_edges for i in l]
|
||||||
|
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(std, region, axis, terrain)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(std, region, axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
|
return list(new_grouping.values())
|
||||||
|
else:
|
||||||
|
# tuple goes to (_,B,C,D,_,_)
|
||||||
|
for grouping in (groups,):
|
||||||
|
new_grouping = {}
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, region, axis, terrain, _, _) = group
|
||||||
|
new_grouping[(region, axis, terrain)] = ([], [])
|
||||||
|
|
||||||
|
for group in grouping.keys():
|
||||||
|
(_, region, axis, terrain, _, _) = group
|
||||||
|
(forward_edges, back_edges) = grouping[group]
|
||||||
|
forward_edges = [[i] for l in forward_edges for i in l]
|
||||||
|
back_edges = [[i] for l in back_edges for i in l]
|
||||||
|
|
||||||
|
(exist_forward_edges, exist_back_edges) = new_grouping[(region, axis, terrain)]
|
||||||
|
exist_forward_edges.extend(forward_edges)
|
||||||
|
exist_back_edges.extend(back_edges)
|
||||||
|
new_grouping[(region, axis, terrain)] = (exist_forward_edges, exist_back_edges)
|
||||||
|
|
||||||
return list(new_grouping.values())
|
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)
|
||||||
@@ -507,7 +821,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]:
|
||||||
@@ -1111,8 +1425,7 @@ 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
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import sys
|
|||||||
|
|
||||||
from BaseClasses import World
|
from BaseClasses import World
|
||||||
from Regions import create_regions
|
from Regions import create_regions
|
||||||
|
from OverworldShuffle import link_overworld
|
||||||
from EntranceShuffle import link_entrances, connect_entrance, connect_two_way, connect_exit
|
from EntranceShuffle import link_entrances, connect_entrance, connect_two_way, connect_exit
|
||||||
from Rom import patch_rom, LocalRom, write_string_to_rom, apply_rom_settings, get_sprite_from_name
|
from Rom import patch_rom, LocalRom, write_string_to_rom, apply_rom_settings, get_sprite_from_name
|
||||||
from Rules import set_rules
|
from Rules import set_rules
|
||||||
@@ -42,6 +43,11 @@ def main(args):
|
|||||||
create_regions(world, 1)
|
create_regions(world, 1)
|
||||||
create_dungeons(world, 1)
|
create_dungeons(world, 1)
|
||||||
|
|
||||||
|
text_patches = []
|
||||||
|
prefill_world(world, args.plando, text_patches)
|
||||||
|
|
||||||
|
link_overworld(world, 1)
|
||||||
|
|
||||||
link_entrances(world, 1)
|
link_entrances(world, 1)
|
||||||
|
|
||||||
logger.info('Calculating Access Rules.')
|
logger.info('Calculating Access Rules.')
|
||||||
@@ -50,9 +56,7 @@ def main(args):
|
|||||||
|
|
||||||
logger.info('Fill the world.')
|
logger.info('Fill the world.')
|
||||||
|
|
||||||
text_patches = []
|
fill_world(world, args.plando)
|
||||||
|
|
||||||
fill_world(world, args.plando, text_patches)
|
|
||||||
|
|
||||||
if world.get_entrance('Dam', 1).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', 1).connected_region.name != 'Swamp Palace (Entrance)':
|
if world.get_entrance('Dam', 1).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', 1).connected_region.name != 'Swamp Palace (Entrance)':
|
||||||
world.swamp_patch_required[1] = True
|
world.swamp_patch_required[1] = True
|
||||||
@@ -92,18 +96,52 @@ def main(args):
|
|||||||
return world
|
return world
|
||||||
|
|
||||||
|
|
||||||
def fill_world(world, plando, text_patches):
|
def fill_world(world, plando):
|
||||||
|
logger = logging.getLogger('')
|
||||||
|
with open(plando, 'r') as plandofile:
|
||||||
|
for line in plandofile.readlines():
|
||||||
|
line = line.lstrip()
|
||||||
|
if line.startswith('#'):
|
||||||
|
continue
|
||||||
|
elif ':' in line:
|
||||||
|
locationstr, itemstr = line.split(':', 1)
|
||||||
|
location = world.get_location(locationstr.strip(), 1)
|
||||||
|
if location is None:
|
||||||
|
logger.warning('Unknown location: %s', locationstr)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
item = ItemFactory(itemstr.strip(), 1)
|
||||||
|
if item is not None:
|
||||||
|
world.push_item(location, item)
|
||||||
|
if item.smallkey or item.bigkey:
|
||||||
|
location.event = True
|
||||||
|
#TODO: move entrance stuff to prefill_world to work like OW stuff
|
||||||
|
elif '<=>' in line:
|
||||||
|
entrance, exit = line.split('<=>', 1)
|
||||||
|
connect_two_way(world, entrance.strip(), exit.strip(), 1)
|
||||||
|
elif '=>' in line:
|
||||||
|
entrance, exit = line.split('=>', 1)
|
||||||
|
connect_entrance(world, entrance.strip(), exit.strip(), 1)
|
||||||
|
elif '<=' in line:
|
||||||
|
entrance, exit = line.split('<=', 1)
|
||||||
|
connect_exit(world, exit.strip(), entrance.strip(), 1)
|
||||||
|
|
||||||
|
# set up Agahnim Events
|
||||||
|
world.get_location('Agahnim 1', 1).event = True
|
||||||
|
world.get_location('Agahnim 1', 1).item = ItemFactory('Beat Agahnim 1', 1)
|
||||||
|
world.get_location('Agahnim 2', 1).event = True
|
||||||
|
world.get_location('Agahnim 2', 1).item = ItemFactory('Beat Agahnim 2', 1)
|
||||||
|
|
||||||
|
def prefill_world(world, plando, text_patches):
|
||||||
mm_medallion = 'Ether'
|
mm_medallion = 'Ether'
|
||||||
tr_medallion = 'Quake'
|
tr_medallion = 'Quake'
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
with open(plando, 'r') as plandofile:
|
with open(plando, 'r') as plandofile:
|
||||||
for line in plandofile.readlines():
|
for line in plandofile.readlines():
|
||||||
|
line = line.lstrip()
|
||||||
if line.startswith('#'):
|
if line.startswith('#'):
|
||||||
continue
|
continue
|
||||||
if ':' in line:
|
elif line.startswith('!'):
|
||||||
line = line.lstrip()
|
|
||||||
|
|
||||||
if line.startswith('!'):
|
|
||||||
if line.startswith('!mm_medallion'):
|
if line.startswith('!mm_medallion'):
|
||||||
_, medallionstr = line.split(':', 1)
|
_, medallionstr = line.split(':', 1)
|
||||||
mm_medallion = medallionstr.strip()
|
mm_medallion = medallionstr.strip()
|
||||||
@@ -119,6 +157,17 @@ def fill_world(world, plando, text_patches):
|
|||||||
elif line.startswith('!goal'):
|
elif line.startswith('!goal'):
|
||||||
_, goalstr = line.split(':', 1)
|
_, goalstr = line.split(':', 1)
|
||||||
world.goal = {1: goalstr.strip()}
|
world.goal = {1: goalstr.strip()}
|
||||||
|
elif line.startswith('!owShuffle'):
|
||||||
|
_, modestr = line.split(':', 1)
|
||||||
|
world.owShuffle = {1: modestr.strip()}
|
||||||
|
elif line.startswith('!owCrossed'):
|
||||||
|
_, modestr = line.split(':', 1)
|
||||||
|
modestr = modestr.strip().lower()
|
||||||
|
world.owCrossed = {1: True if modestr in ('true', 'yes', 'on', 'enabled') else False}
|
||||||
|
elif line.startswith('!owKeepSimilar'):
|
||||||
|
_, modestr = line.split(':', 1)
|
||||||
|
modestr = modestr.strip().lower()
|
||||||
|
world.owKeepSimilar = {1: True if modestr in ('true', 'yes', 'on', 'enabled') else False}
|
||||||
elif line.startswith('!light_cone_sewers'):
|
elif line.startswith('!light_cone_sewers'):
|
||||||
_, sewerstr = line.split(':', 1)
|
_, sewerstr = line.split(':', 1)
|
||||||
world.sewer_light_cone = {1: sewerstr.strip().lower() == 'true'}
|
world.sewer_light_cone = {1: sewerstr.strip().lower() == 'true'}
|
||||||
@@ -160,36 +209,24 @@ def fill_world(world, plando, text_patches):
|
|||||||
# textname, text = line.split(':', 1)
|
# textname, text = line.split(':', 1)
|
||||||
# text_patches.append([textname.lstrip('!credits_').strip(), 'credits', text.strip()])
|
# text_patches.append([textname.lstrip('!credits_').strip(), 'credits', text.strip()])
|
||||||
continue
|
continue
|
||||||
|
elif line.startswith('$'):
|
||||||
locationstr, itemstr = line.split(':', 1)
|
edge1, edge2 = line.split('=', 1)
|
||||||
location = world.get_location(locationstr.strip(), 1)
|
if world.custom_overworld is None:
|
||||||
if location is None:
|
world.custom_overworld = {1: []}
|
||||||
logger.warning('Unknown location: %s', locationstr)
|
world.custom_overworld[1].append(edge1.strip(), edge2.strip())
|
||||||
continue
|
#TODO: Do entrances similar to OW
|
||||||
else:
|
|
||||||
item = ItemFactory(itemstr.strip(), 1)
|
|
||||||
if item is not None:
|
|
||||||
world.push_item(location, item)
|
|
||||||
if item.smallkey or item.bigkey:
|
|
||||||
location.event = True
|
|
||||||
elif '<=>' in line:
|
elif '<=>' in line:
|
||||||
entrance, exit = line.split('<=>', 1)
|
entrance, exit = line.split('<=>', 1)
|
||||||
connect_two_way(world, entrance.strip(), exit.strip(), 1)
|
#connect_two_way(world, entrance.strip(), exit.strip(), 1)
|
||||||
elif '=>' in line:
|
elif '=>' in line:
|
||||||
entrance, exit = line.split('=>', 1)
|
entrance, exit = line.split('=>', 1)
|
||||||
connect_entrance(world, entrance.strip(), exit.strip(), 1)
|
#connect_entrance(world, entrance.strip(), exit.strip(), 1)
|
||||||
elif '<=' in line:
|
elif '<=' in line:
|
||||||
entrance, exit = line.split('<=', 1)
|
entrance, exit = line.split('<=', 1)
|
||||||
connect_exit(world, exit.strip(), entrance.strip(), 1)
|
#connect_exit(world, exit.strip(), entrance.strip(), 1)
|
||||||
|
|
||||||
world.required_medallions[1] = (mm_medallion, tr_medallion)
|
world.required_medallions[1] = (mm_medallion, tr_medallion)
|
||||||
|
|
||||||
# set up Agahnim Events
|
|
||||||
world.get_location('Agahnim 1', 1).event = True
|
|
||||||
world.get_location('Agahnim 1', 1).item = ItemFactory('Beat Agahnim 1', 1)
|
|
||||||
world.get_location('Agahnim 2', 1).event = True
|
|
||||||
world.get_location('Agahnim 2', 1).item = ItemFactory('Beat Agahnim 2', 1)
|
|
||||||
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
|
|||||||
@@ -242,3 +242,10 @@ Ganons Tower - Mini Helmasaur Room - Right: Nothing
|
|||||||
Ganons Tower - Pre-Moldorm Chest: Small Key (Ganons Tower)
|
Ganons Tower - Pre-Moldorm Chest: Small Key (Ganons Tower)
|
||||||
Ganons Tower - Validation Chest: Nothing
|
Ganons Tower - Validation Chest: Nothing
|
||||||
Ganon: Triforce
|
Ganon: Triforce
|
||||||
|
|
||||||
|
# set Overworld connections (lines starting with $, separate edges with =)
|
||||||
|
!owShuffle: parallel
|
||||||
|
#!owMixed: true # Mixed OW not supported yet
|
||||||
|
!owCrossed: true
|
||||||
|
!owKeepSimilar: true
|
||||||
|
$Links House NE = Kakariko Village SE
|
||||||
|
|||||||
@@ -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>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ CLI: ```--bombbag```
|
|||||||
|
|
||||||
# Bug Fixes and Notes.
|
# Bug Fixes and Notes.
|
||||||
|
|
||||||
|
* 0.5.0.3
|
||||||
|
* Fixed a bug in retro+vanilla and big key placement
|
||||||
|
* Fixed a problem with shops not registering in the Multiclient until you visit one
|
||||||
|
* Fixed a bug in the Mystery code with sfx
|
||||||
* 0.5.0.2
|
* 0.5.0.2
|
||||||
* --shuffle_sfx option added
|
* --shuffle_sfx option added
|
||||||
* 0.5.0.1
|
* 0.5.0.1
|
||||||
|
|||||||
@@ -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,10 +2174,10 @@ 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':
|
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 Ledge': 'The pyramid ledge'})
|
entrances_to_hint.update({'Pyramid Entrance': 'The pyramid ledge'})
|
||||||
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 0
|
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 0
|
||||||
for entrance in all_entrances:
|
for entrance in all_entrances:
|
||||||
if entrance.name in entrances_to_hint:
|
if entrance.name in entrances_to_hint:
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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.
+6
-4
@@ -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",
|
||||||
@@ -142,10 +143,6 @@
|
|||||||
"full",
|
"full",
|
||||||
"crossed",
|
"crossed",
|
||||||
"insanity",
|
"insanity",
|
||||||
"restricted_legacy",
|
|
||||||
"full_legacy",
|
|
||||||
"madness_legacy",
|
|
||||||
"insanity_legacy",
|
|
||||||
"dungeonsfull",
|
"dungeonsfull",
|
||||||
"dungeonssimple"
|
"dungeonssimple"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -189,10 +189,8 @@
|
|||||||
" which they are entered.",
|
" which they are entered.",
|
||||||
"Vanilla: All entrances are in the same locations they were",
|
"Vanilla: All entrances are in the same locations they were",
|
||||||
" in the base game.",
|
" in the base game.",
|
||||||
"Legacy shuffles preserve behavior from older versions of the",
|
|
||||||
"entrance randomizer including significant technical limitations.",
|
|
||||||
"The dungeon variants only mix up dungeons and keep the rest of",
|
"The dungeon variants only mix up dungeons and keep the rest of",
|
||||||
"the overworld vanilla."
|
"the entrances vanilla."
|
||||||
],
|
],
|
||||||
"ow_shuffle": [
|
"ow_shuffle": [
|
||||||
"This shuffles the layout of the overworld.",
|
"This shuffles the layout of the overworld.",
|
||||||
@@ -203,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",
|
||||||
|
|||||||
@@ -12,10 +12,6 @@
|
|||||||
"full",
|
"full",
|
||||||
"crossed",
|
"crossed",
|
||||||
"insanity",
|
"insanity",
|
||||||
"restricted_legacy",
|
|
||||||
"full_legacy",
|
|
||||||
"madness_legacy",
|
|
||||||
"insanity_legacy",
|
|
||||||
"dungeonsfull",
|
"dungeonsfull",
|
||||||
"dungeonssimple"
|
"dungeonssimple"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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