Merge branch 'OverworldShuffleDev' into OverworldShuffle

This commit is contained in:
codemann8
2024-01-26 23:34:56 -06:00
22 changed files with 948 additions and 679 deletions

View File

@@ -36,8 +36,9 @@ def main():
parser.add_argument('--ow_palettes', default='default', choices=['default', 'random', 'blackout']) parser.add_argument('--ow_palettes', default='default', choices=['default', 'random', 'blackout'])
parser.add_argument('--uw_palettes', default='default', choices=['default', 'random', 'blackout']) parser.add_argument('--uw_palettes', default='default', choices=['default', 'random', 'blackout'])
parser.add_argument('--reduce_flashing', help='Reduce some in-game flashing.', action='store_true') parser.add_argument('--reduce_flashing', help='Reduce some in-game flashing.', action='store_true')
parser.add_argument('--shuffle_sfx', help='Shuffles sfx instruments', action='store_true') parser.add_argument('--shuffle_sfx', help='Shuffles sound sfx', action='store_true')
parser.add_argument('--shuffle_songinstruments', help='Shuffles sound sfx', action='store_true') parser.add_argument('--shuffle_sfxinstruments', help='Shuffles sound instruments', action='store_true')
parser.add_argument('--shuffle_songinstruments', help='Shuffles song instruments', action='store_true')
parser.add_argument('--msu_resume', help='Enable MSU resume', action='store_true') parser.add_argument('--msu_resume', help='Enable MSU resume', action='store_true')
parser.add_argument('--sprite', help='''\ parser.add_argument('--sprite', help='''\
Path to a sprite sheet to use for Link. Needs to be in Path to a sprite sheet to use for Link. Needs to be in

View File

@@ -33,7 +33,7 @@ def adjust(args):
apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic,
args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx,
args.shuffle_songinstruments, args.msu_resume) args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume)
output_path.cached_path = args.outputpath output_path.cached_path = args.outputpath
rom.write_to_file(output_path('%s.sfc' % outfilebase)) rom.write_to_file(output_path('%s.sfc' % outfilebase))
@@ -68,7 +68,7 @@ def patch(args):
apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic,
args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx,
args.shuffle_songinstruments, args.msu_resume) args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume)
output_path.cached_path = args.outputpath output_path.cached_path = args.outputpath
rom.write_to_file(output_path('%s.sfc' % outfile_base)) rom.write_to_file(output_path('%s.sfc' % outfile_base))

View File

@@ -1,5 +1,11 @@
# Changelog # Changelog
## 0.3.4.2
- Added Shuffle SFX Instruments as post-gen option
- Fixed some issues with Swapped ER failing to place Old Man Cave
- Changed Inverted 2.0 spawn prompt to display Bomb Shop
- Fixed some minor issues with ER and Vanilla GT
## 0.3.4.1 ## 0.3.4.1
- Implemented new District ER mode option - Implemented new District ER mode option
- Added alternate boss logic when in GT Ice Basement - Added alternate boss logic when in GT Ice Basement

5
CLI.py
View File

@@ -143,8 +143,8 @@ def parse_cli(argv, no_defaults=False):
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle', 'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle',
'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_songinstruments', 'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_sfxinstruments',
'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode', 'shuffle_songinstruments', 'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode',
'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'door_self_loops', 'aga_randomness']: 'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'door_self_loops', 'aga_randomness']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1: if player == 1:
@@ -262,6 +262,7 @@ def parse_settings():
"uw_palettes": "default", "uw_palettes": "default",
"reduce_flashing": False, "reduce_flashing": False,
"shuffle_sfx": False, "shuffle_sfx": False,
"shuffle_sfxinstruments": False,
"shuffle_songinstruments": False, "shuffle_songinstruments": False,
"msu_resume": False, "msu_resume": False,
"collection_rate": False, "collection_rate": False,

View File

@@ -338,7 +338,8 @@ def main(args, seed=None, fish=None):
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player], apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
args.fastmenu[player], args.disablemusic[player], args.sprite[player], args.fastmenu[player], args.disablemusic[player], args.sprite[player],
args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player], args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player],
args.shuffle_sfx[player], args.shuffle_songinstruments[player], args.msu_resume[player]) args.shuffle_sfx[player], args.shuffle_sfxinstruments[player], args.shuffle_songinstruments[player],
args.msu_resume[player])
if args.jsonout: if args.jsonout:
jsonout[f'patch_t{team}_p{player}'] = rom.patches jsonout[f'patch_t{team}_p{player}'] = rom.patches

View File

@@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType
from OverworldGlitchRules import create_owg_connections from OverworldGlitchRules import create_owg_connections
from Utils import bidict from Utils import bidict
version_number = '0.3.4.1' version_number = '0.3.4.2'
# branch indicator is intentionally different across branches # branch indicator is intentionally different across branches
version_branch = '' version_branch = ''

23
Rom.py
View File

@@ -32,7 +32,7 @@ from EntranceShuffle import door_addresses, exit_ids, ow_prize_table
from OverworldShuffle import default_flute_connections, flute_data from OverworldShuffle import default_flute_connections, flute_data
from InitialSram import InitialSram from InitialSram import InitialSram
from source.classes.SFX import randomize_sfx, randomize_songinstruments from source.classes.SFX import randomize_sfx, randomize_sfxinstruments, randomize_songinstruments
from source.item.FillUtil import valid_pot_items from source.item.FillUtil import valid_pot_items
from source.dungeon.RoomList import Room0127 from source.dungeon.RoomList import Room0127
@@ -1830,7 +1830,8 @@ def hud_format_text(text):
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite,
ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx, shuffle_songinstruments, msu_resume): ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx,
shuffle_sfxinstruments, shuffle_songinstruments, msu_resume):
if not os.path.exists("data/sprites/official/001.link.1.zspr") and rom.orig_buffer: if not os.path.exists("data/sprites/official/001.link.1.zspr") and rom.orig_buffer:
dump_zspr(rom.orig_buffer[0x80000:0x87000], rom.orig_buffer[0xdd308:0xdd380], dump_zspr(rom.orig_buffer[0x80000:0x87000], rom.orig_buffer[0xdd308:0xdd380],
@@ -1936,6 +1937,8 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
if shuffle_sfx: if shuffle_sfx:
randomize_sfx(rom) randomize_sfx(rom)
if shuffle_sfxinstruments:
randomize_sfxinstruments(rom)
if shuffle_songinstruments: if shuffle_songinstruments:
randomize_songinstruments(rom) randomize_songinstruments(rom)
@@ -2193,9 +2196,9 @@ def write_strings(rom, world, player, team):
# Now we write inconvenient locations for most shuffles and finish taking care of the less chaotic ones. # Now we write inconvenient locations for most shuffles and finish taking care of the less chaotic ones.
if world.shuffle[player] not in ['lite', 'lean']: if world.shuffle[player] not in ['lite', 'lean']:
entrances_to_hint.update(InconvenientOtherEntrances) entrances_to_hint.update(InconvenientOtherEntrances)
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'lite', 'lean', 'district']: if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district', 'swapped']:
hint_count = 0 hint_count = 0
elif world.shuffle[player] in ['simple', 'restricted']: elif world.shuffle[player] in ['simple', 'restricted', 'lite', 'lean']:
hint_count = 2 hint_count = 2
else: else:
hint_count = 4 hint_count = 4
@@ -2247,8 +2250,8 @@ def write_strings(rom, world, player, team):
hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district', 'swapped'] else 0 hint_count = 4 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'district', 'swapped'] else 0
hint_count -= 2 if world.shuffle[player] not in ['simple', 'restricted'] else 0 hint_count -= 2 if world.shuffle[player] not in ['simple', 'restricted'] else 0
for entrance in all_entrances: for entrance in all_entrances:
if entrance.name in entrances_to_hint:
if hint_count > 0: if hint_count > 0:
if entrance.name in entrances_to_hint:
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(entrance.connected_region) + '.' this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(entrance.connected_region) + '.'
tt[hint_locations.pop(0)] = this_hint tt[hint_locations.pop(0)] = this_hint
entrances_to_hint.pop(entrance.name) entrances_to_hint.pop(entrance.name)
@@ -2542,9 +2545,15 @@ def write_strings(rom, world, player, team):
rom.write_byte(0x04a52e, 0x06) # follower set to blind maiden rom.write_byte(0x04a52e, 0x06) # follower set to blind maiden
# inverted spawn menu changes # inverted spawn menu changes
lh_text = "House"
if world.is_tile_swapped(0x2c, player):
lh_text = "Bomb Shop"
sanc_text = "Sanctuary"
if world.mode[player] == 'inverted':
sanc_text = "Dark Chapel"
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n{CHOICE3}"
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s " + lh_text + "\n " + sanc_text + "\n Mountain Cave\n{CHOICE2}"
if world.mode[player] == 'inverted': if world.mode[player] == 'inverted':
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s House\n Dark Chapel\n{CHOICE3}"
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s House\n Dark Chapel\n Mountain Cave\n{CHOICE2}"
tt['intro_main'] = CompressedTextMapper.convert( tt['intro_main'] = CompressedTextMapper.convert(
"{INTRO}\n Episode III\n{PAUSE3}\n A Link to\n the Past\n" "{INTRO}\n Episode III\n{PAUSE3}\n A Link to\n the Past\n"
+ "{PAUSE3}\nInverted\n Randomizer\n{PAUSE3}\nAfter mostly disregarding what happened in the first two games.\n" + "{PAUSE3}\nInverted\n Randomizer\n{PAUSE3}\nAfter mostly disregarding what happened in the first two games.\n"

View File

@@ -269,6 +269,9 @@
shuffle_sfx: shuffle_sfx:
on: 1 on: 1
off: 1 off: 1
shuffle_sfxinstruments:
on: 1
off: 1
shuffle_songinstruments: shuffle_songinstruments:
on: 1 on: 1
off: 1 off: 1

View File

@@ -199,6 +199,9 @@ rom:
shuffle_sfx: shuffle_sfx:
on: 1 on: 1
off: 1 off: 1
shuffle_sfxinstruments:
on: 1
off: 1
shuffle_songinstruments: shuffle_songinstruments:
on: 1 on: 1
off: 1 off: 1

View File

@@ -349,6 +349,10 @@
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"
}, },
"shuffle_sfxinstruments": {
"action": "store_true",
"type": "bool"
},
"shuffle_songinstruments": { "shuffle_songinstruments": {
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"

View File

@@ -429,6 +429,7 @@
], ],
"reduce_flashing": [ "Reduce some in-game flashing (default: %(default)s)" ], "reduce_flashing": [ "Reduce some in-game flashing (default: %(default)s)" ],
"shuffle_sfx": [ "Shuffle sounds effects (default: %(default)s)" ], "shuffle_sfx": [ "Shuffle sounds effects (default: %(default)s)" ],
"shuffle_sfxinstruments": [ "Shuffle sound instruments (default: %(default)s)" ],
"shuffle_songinstruments": [ "Shuffle song instruments (default: %(default)s)" ], "shuffle_songinstruments": [ "Shuffle song instruments (default: %(default)s)" ],
"msu_resume": [ "Enable MSU Resume (default: %(default)s)" ], "msu_resume": [ "Enable MSU Resume (default: %(default)s)" ],
"create_rom": [ "Create an output rom file. (default: %(default)s)" ], "create_rom": [ "Create an output rom file. (default: %(default)s)" ],

View File

@@ -5,6 +5,7 @@
"quickswap": { "type": "checkbox" }, "quickswap": { "type": "checkbox" },
"reduce_flashing": {"type": "checkbox" }, "reduce_flashing": {"type": "checkbox" },
"shuffle_sfx": {"type": "checkbox" }, "shuffle_sfx": {"type": "checkbox" },
"shuffle_sfxinstruments": {"type": "checkbox" },
"shuffle_songinstruments": {"type": "checkbox" } "shuffle_songinstruments": {"type": "checkbox" }
}, },
"leftAdjustFrame": { "leftAdjustFrame": {

View File

@@ -4,6 +4,7 @@
"adjust.quickswap": "L/R Quickswapping", "adjust.quickswap": "L/R Quickswapping",
"adjust.reduce_flashing": "Reduce Flashing", "adjust.reduce_flashing": "Reduce Flashing",
"adjust.shuffle_sfx": "Shuffle Sound Effects", "adjust.shuffle_sfx": "Shuffle Sound Effects",
"adjust.shuffle_sfxinstruments": "Shuffle Sound Instruments",
"adjust.shuffle_songinstruments": "Shuffle Song Instruments", "adjust.shuffle_songinstruments": "Shuffle Song Instruments",
"adjust.msu_resume": "MSU Resume", "adjust.msu_resume": "MSU Resume",
@@ -192,6 +193,7 @@
"randomizer.gameoptions.quickswap": "L/R Quickswapping", "randomizer.gameoptions.quickswap": "L/R Quickswapping",
"randomizer.gameoptions.reduce_flashing": "Reduce Flashing", "randomizer.gameoptions.reduce_flashing": "Reduce Flashing",
"randomizer.gameoptions.shuffle_sfx": "Shuffle Sound Effects", "randomizer.gameoptions.shuffle_sfx": "Shuffle Sound Effects",
"randomizer.gameoptions.shuffle_sfxinstruments": "Shuffle Sound Instruments",
"randomizer.gameoptions.shuffle_songinstruments": "Shuffle Song Instruments", "randomizer.gameoptions.shuffle_songinstruments": "Shuffle Song Instruments",
"randomizer.gameoptions.msu_resume": "MSU Resume", "randomizer.gameoptions.msu_resume": "MSU Resume",

View File

@@ -5,6 +5,7 @@
"quickswap": { "type": "checkbox" }, "quickswap": { "type": "checkbox" },
"reduce_flashing": { "type": "checkbox" }, "reduce_flashing": { "type": "checkbox" },
"shuffle_sfx": { "type": "checkbox" }, "shuffle_sfx": { "type": "checkbox" },
"shuffle_sfxinstruments": { "type": "checkbox" },
"shuffle_songinstruments": { "type": "checkbox" } "shuffle_songinstruments": { "type": "checkbox" }
}, },
"leftRomOptionsFrame": { "leftRomOptionsFrame": {

View File

@@ -186,6 +186,7 @@ class CustomSettings(object):
args.ow_palettes[p] = get_setting(settings['ow_palettes'], args.ow_palettes[p]) args.ow_palettes[p] = get_setting(settings['ow_palettes'], args.ow_palettes[p])
args.uw_palettes[p] = get_setting(settings['uw_palettes'], args.uw_palettes[p]) args.uw_palettes[p] = get_setting(settings['uw_palettes'], args.uw_palettes[p])
args.shuffle_sfx[p] = get_setting(settings['shuffle_sfx'], args.shuffle_sfx[p]) args.shuffle_sfx[p] = get_setting(settings['shuffle_sfx'], args.shuffle_sfx[p])
args.shuffle_sfxinstruments[p] = get_setting(settings['shuffle_sfxinstruments'], args.shuffle_sfxinstruments[p])
args.shuffle_songinstruments[p] = get_setting(settings['shuffle_songinstruments'], args.shuffle_songinstruments[p]) args.shuffle_songinstruments[p] = get_setting(settings['shuffle_songinstruments'], args.shuffle_songinstruments[p])
args.msu_resume[p] = get_setting(settings['msu_resume'], args.msu_resume[p]) args.msu_resume[p] = get_setting(settings['msu_resume'], args.msu_resume[p])

File diff suppressed because it is too large Load Diff

View File

@@ -139,6 +139,7 @@ SETTINGSTOPROCESS = {
"uwpalettes": "uw_palettes", "uwpalettes": "uw_palettes",
"reduce_flashing": "reduce_flashing", "reduce_flashing": "reduce_flashing",
"shuffle_sfx": "shuffle_sfx", "shuffle_sfx": "shuffle_sfx",
"shuffle_sfxinstruments": "shuffle_sfxinstruments",
"shuffle_songinstruments": "shuffle_songinstruments", "shuffle_songinstruments": "shuffle_songinstruments",
'msu_resume': 'msu_resume', 'msu_resume': 'msu_resume',
}, },

View File

@@ -107,6 +107,7 @@ def adjust_page(top, parent, settings):
"reduce_flashing": "reduce_flashing", "reduce_flashing": "reduce_flashing",
'msu_resume': 'msu_resume', 'msu_resume': 'msu_resume',
"shuffle_sfx": "shuffle_sfx", "shuffle_sfx": "shuffle_sfx",
"shuffle_sfxinstruments": "shuffle_sfxinstruments",
"shuffle_songinstruments": "shuffle_songinstruments", "shuffle_songinstruments": "shuffle_songinstruments",
} }
guiargs = Namespace() guiargs = Namespace()
@@ -159,6 +160,7 @@ def adjust_page(top, parent, settings):
"nobgm": "disablemusic", "nobgm": "disablemusic",
"reduce_flashing": "reduce_flashing", "reduce_flashing": "reduce_flashing",
"shuffle_sfx": "shuffle_sfx", "shuffle_sfx": "shuffle_sfx",
"shuffle_sfxinstruments": "shuffle_sfxinstruments",
"shuffle_songinstruments": "shuffle_songinstruments", "shuffle_songinstruments": "shuffle_songinstruments",
"msu_resume": "msu_resume" "msu_resume": "msu_resume"
} }

View File

@@ -202,7 +202,7 @@ def bottom_frame(self, parent, args=None):
def select_output(): def select_output():
from tkinter import filedialog from tkinter import filedialog
folder_selected = filedialog.askdirectory() folder_selected = filedialog.askdirectory()
if folder_selected is not None: if folder_selected is not None and folder_selected != '':
args.outputpath = parent.settings["outputpath"] = folder_selected args.outputpath = parent.settings["outputpath"] = folder_selected
## Output Button ## Output Button
@@ -311,6 +311,7 @@ def create_guiargs(parent):
"uwpalettes": "uw_palettes", "uwpalettes": "uw_palettes",
"reduce_flashing": "reduce_flashing", "reduce_flashing": "reduce_flashing",
"shuffle_sfx": "shuffle_sfx", "shuffle_sfx": "shuffle_sfx",
"shuffle_sfxinstruments": "shuffle_sfxinstruments",
"shuffle_songinstruments": "shuffle_songinstruments" "shuffle_songinstruments": "shuffle_songinstruments"
} }
for adjustarg in adjustargs: for adjustarg in adjustargs:

View File

@@ -225,6 +225,7 @@ def loadadjustargs(gui, settings):
"uwpalettes": "adjust.uwpalettes", "uwpalettes": "adjust.uwpalettes",
"reduce_flashing": "adjust.reduce_flashing", "reduce_flashing": "adjust.reduce_flashing",
"shuffle_sfx": "adjust.shuffle_sfx", "shuffle_sfx": "adjust.shuffle_sfx",
"shuffle_sfxinstruments": "adjust.shuffle_sfxinstruments",
"shuffle_songinstruments": "adjust.shuffle_songinstruments" "shuffle_songinstruments": "adjust.shuffle_songinstruments"
} }
} }

View File

@@ -17,6 +17,7 @@ class EntrancePool(object):
self.keep_drops_together = True self.keep_drops_together = True
self.default_map = {} self.default_map = {}
self.one_way_map = {} self.one_way_map = {}
self.combine_map = {}
self.skull_handled = False self.skull_handled = False
self.links_on_mountain = False self.links_on_mountain = False
self.decoupled_entrances = [] self.decoupled_entrances = []
@@ -71,6 +72,7 @@ def link_entrances_new(world, player):
default_map['Agahnims Tower'] = 'Ganons Tower Exit' default_map['Agahnims Tower'] = 'Ganons Tower Exit'
avail_pool.default_map = default_map avail_pool.default_map = default_map
avail_pool.one_way_map = one_way_map avail_pool.one_way_map = one_way_map
avail_pool.combine_map = {**default_map, **one_way_map}
global LW_Entrances, DW_Entrances global LW_Entrances, DW_Entrances
LW_Entrances = [] LW_Entrances = []
@@ -221,10 +223,6 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
if not avail.coupled: if not avail.coupled:
avail.decoupled_entrances.remove('Agahnims Tower') avail.decoupled_entrances.remove('Agahnims Tower')
avail.decoupled_exits.remove('Ganons Tower Exit') avail.decoupled_exits.remove('Ganons Tower Exit')
if avail.swapped:
connect_swap('Agahnims Tower', 'Ganons Tower Exit', avail)
entrances.remove('Ganons Tower')
exits.remove('Agahnims Tower Exit')
elif 'Ganons Tower' in entrances: elif 'Ganons Tower' in entrances:
connect_two_way('Ganons Tower', 'Ganons Tower Exit', avail) connect_two_way('Ganons Tower', 'Ganons Tower Exit', avail)
entrances.remove('Ganons Tower') entrances.remove('Ganons Tower')
@@ -1129,7 +1127,7 @@ def do_cross_world_connectors(entrances, caves, avail):
avail.decoupled_entrances.remove(choice) avail.decoupled_entrances.remove(choice)
else: else:
if avail.swapped and len(entrances) > 1: if avail.swapped and len(entrances) > 1:
chosen_entrance = next(e for e in entrances if combine_map[e] != ext) chosen_entrance = next(e for e in entrances if avail.combine_map[e] != ext)
entrances.remove(chosen_entrance) entrances.remove(chosen_entrance)
else: else:
chosen_entrance = entrances.pop() chosen_entrance = entrances.pop()
@@ -1178,7 +1176,7 @@ def do_fixed_shuffle(avail, entrance_list):
choice = choices[i] choice = choices[i]
elif rules.must_exit_to_lw: elif rules.must_exit_to_lw:
lw_exits = set() lw_exits = set()
for e, x in combine_map.items(): for e, x in avail.combine_map.items():
if x in avail.exits: if x in avail.exits:
region = avail.world.get_entrance(e, avail.player).parent_region region = avail.world.get_entrance(e, avail.player).parent_region
if region.type == RegionType.LightWorld: if region.type == RegionType.LightWorld:
@@ -1314,6 +1312,22 @@ def do_limited_shuffle_exclude_drops(pool_def, avail, lw=True):
must_exit = set(must_exit_lw if lw else must_exit_dw) must_exit = set(must_exit_lw if lw else must_exit_dw)
base_set = LW_Entrances if lw else DW_Entrances base_set = LW_Entrances if lw else DW_Entrances
entrance_pool = [x for x in base_set if x in avail.entrances and x not in reserved_drops] entrance_pool = [x for x in base_set if x in avail.entrances and x not in reserved_drops]
if not avail.world.shuffle_ganon[avail.player]:
if avail.world.is_atgt_swapped(avail.player):
if 'Agahnims Tower' in entrance_pool:
connect_two_way('Agahnims Tower', 'Ganons Tower Exit', avail)
entrance_pool.remove('Agahnims Tower')
exits.remove('Ganons Tower Exit')
if not avail.coupled:
avail.decoupled_entrances.remove('Agahnims Tower')
avail.decoupled_exits.remove('Ganons Tower Exit')
elif 'Ganons Tower' in entrance_pool:
connect_two_way('Ganons Tower', 'Ganons Tower Exit', avail)
entrance_pool.remove('Ganons Tower')
exits.remove('Ganons Tower Exit')
if not avail.coupled:
avail.decoupled_entrances.remove('Ganons Tower')
avail.decoupled_exits.remove('Ganons Tower Exit')
random.shuffle(entrance_pool) random.shuffle(entrance_pool)
for next_exit in exits: for next_exit in exits:
if next_exit not in Connector_Exit_Set: if next_exit not in Connector_Exit_Set:
@@ -1369,7 +1383,7 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
if entrance not in entrances: if entrance not in entrances:
entrances.append(entrance) entrances.append(entrance)
if avail.swapped: if avail.swapped:
swap_forbidden = [e for e in entrances if combine_map[e] in must_exit] swap_forbidden = [e for e in entrances if avail.combine_map[e] in must_exit]
for e in swap_forbidden: for e in swap_forbidden:
entrances.remove(e) entrances.remove(e)
entrances.sort() # sort these for consistency entrances.sort() # sort these for consistency
@@ -1407,9 +1421,18 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
allow_single = avail.assumed_loose_caves or len(candidate) > 1 allow_single = avail.assumed_loose_caves or len(candidate) > 1
if not isinstance(candidate, str) and allow_single and (candidate in used_caves if not isinstance(candidate, str) and allow_single and (candidate in used_caves
or len(candidate) < len(entrances) - required_entrances): or len(candidate) < len(entrances) - required_entrances):
if not avail.swapped or (combine_map[exit] not in candidate and not any(e for e in must_exit if combine_map[e] in candidate)): #maybe someday allow these, but we need to disallow mutual locks in Swapped if not avail.swapped or (avail.combine_map[exit] not in candidate and not any(e for e in must_exit if avail.combine_map[e] in candidate)): #maybe someday allow these, but we need to disallow mutual locks in Swapped
candidates.append(candidate) candidates.append(candidate)
cave = random.choice(candidates) cave = random.choice(candidates)
if avail.swapped and len(candidates) > 1 and not avail.world.is_tile_swapped(0x03, avail.player):
DM_Connector_Prefixes = ['Spectacle Rock Cave', 'Old Man House', 'Death Mountain Return']
if any(p for p in DM_Connector_Prefixes if p in cave[0]): # if chosen cave is a DM connector
remain = [p for p in DM_Connector_Prefixes if len([e for e in entrances if p in e]) > 0] # gets remaining DM caves left in pool
if len(remain) == 1: # guarantee that old man rescue cave can still be placed
candidates.remove(cave)
cave = random.choice(candidates)
if cave is None: if cave is None:
raise RuntimeError('No more caves left. Should not happen!') raise RuntimeError('No more caves left. Should not happen!')
@@ -1427,10 +1450,10 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
if len(cave) == 2: if len(cave) == 2:
entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit] entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit]
and e not in invalid_cave_connections[tuple(cave)] and e not in must_exit and e not in invalid_cave_connections[tuple(cave)] and e not in must_exit
and (not avail.swapped or rnd_cave[0] != combine_map[e])) and (not avail.swapped or rnd_cave[0] != avail.combine_map[e]))
entrances.remove(entrance) entrances.remove(entrance)
connect_two_way(entrance, rnd_cave[0], avail) connect_two_way(entrance, rnd_cave[0], avail)
if avail.swapped and combine_map[entrance] != rnd_cave[0]: if avail.swapped and avail.combine_map[entrance] != rnd_cave[0]:
swap_ent, _ = connect_cave_swap(entrance, rnd_cave[0], cave) swap_ent, _ = connect_cave_swap(entrance, rnd_cave[0], cave)
entrances.remove(swap_ent) entrances.remove(swap_ent)
if cave in used_caves: if cave in used_caves:
@@ -1451,11 +1474,11 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
cave_entrances.append(entrance) cave_entrances.append(entrance)
else: else:
entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit] and e not in must_exit entrance = next(e for e in entrances[::-1] if e not in invalid_connections[exit] and e not in must_exit
and (not avail.swapped or cave_exit != combine_map[e])) and (not avail.swapped or cave_exit != avail.combine_map[e]))
cave_entrances.append(entrance) cave_entrances.append(entrance)
entrances.remove(entrance) entrances.remove(entrance)
connect_two_way(entrance, cave_exit, avail) connect_two_way(entrance, cave_exit, avail)
if avail.swapped and combine_map[entrance] != cave_exit: if avail.swapped and avail.combine_map[entrance] != cave_exit:
swap_ent, _ = connect_cave_swap(entrance, cave_exit, cave) swap_ent, _ = connect_cave_swap(entrance, cave_exit, cave)
entrances.remove(swap_ent) entrances.remove(swap_ent)
if entrance not in invalid_connections: if entrance not in invalid_connections:
@@ -1482,11 +1505,11 @@ def do_mandatory_connections(avail, entrances, cave_options, must_exit):
continue continue
else: else:
entrance = next(e for e in entrances[::-1] if e not in invalid_cave_connections[tuple(cave)] entrance = next(e for e in entrances[::-1] if e not in invalid_cave_connections[tuple(cave)]
and (not avail.swapped or cave_exit != combine_map[e])) and (not avail.swapped or cave_exit != avail.combine_map[e]))
invalid_cave_connections[tuple(cave)] = set() invalid_cave_connections[tuple(cave)] = set()
entrances.remove(entrance) entrances.remove(entrance)
connect_two_way(entrance, cave_exit, avail) connect_two_way(entrance, cave_exit, avail)
if avail.swapped and combine_map[entrance] != cave_exit: if avail.swapped and avail.combine_map[entrance] != cave_exit:
swap_ent, _ = connect_cave_swap(entrance, cave_exit, cave) swap_ent, _ = connect_cave_swap(entrance, cave_exit, cave)
entrances.remove(swap_ent) entrances.remove(swap_ent)
cave_options.remove(cave) cave_options.remove(cave)
@@ -1604,11 +1627,11 @@ def connect_swapped(entrancelist, targetlist, avail, two_way=False):
random.shuffle(entrancelist) random.shuffle(entrancelist)
sorted_targets = list() sorted_targets = list()
for ent in entrancelist: for ent in entrancelist:
if ent in combine_map: if ent in avail.combine_map:
if combine_map[ent] not in targetlist: if avail.combine_map[ent] not in targetlist:
logging.getLogger('').error(f'{combine_map[ent]} not in target list, cannot swap entrance') logging.getLogger('').error(f'{avail.combine_map[ent]} not in target list, cannot swap entrance')
raise Exception(f'{combine_map[ent]} not in target list, cannot swap entrance') raise Exception(f'{avail.combine_map[ent]} not in target list, cannot swap entrance')
sorted_targets.append(combine_map[ent]) sorted_targets.append(avail.combine_map[ent])
if len(sorted_targets): if len(sorted_targets):
targetlist = list(sorted_targets) targetlist = list(sorted_targets)
else: else:
@@ -1629,9 +1652,9 @@ def connect_swapped(entrancelist, targetlist, avail, two_way=False):
def connect_swap(entrance, exit, avail): def connect_swap(entrance, exit, avail):
swap_exit = combine_map[entrance] swap_exit = avail.combine_map[entrance]
if swap_exit != exit: if swap_exit != exit:
swap_entrance = next(e for e, x in combine_map.items() if x == exit) swap_entrance = next(e for e, x in avail.combine_map.items() if x == exit)
if swap_entrance in ['Pyramid Entrance', 'Pyramid Hole'] and avail.world.is_tile_swapped(0x1b, avail.player): if swap_entrance in ['Pyramid Entrance', 'Pyramid Hole'] and avail.world.is_tile_swapped(0x1b, avail.player):
swap_entrance = 'Inverted ' + swap_entrance swap_entrance = 'Inverted ' + swap_entrance
if entrance in entrance_map: if entrance in entrance_map:
@@ -2447,7 +2470,6 @@ single_entrance_map = {
'Blinds Hideout': 'Blinds Hideout', 'Waterfall of Wishing': 'Waterfall of Wishing' 'Blinds Hideout': 'Blinds Hideout', 'Waterfall of Wishing': 'Waterfall of Wishing'
} }
combine_map = {**entrance_map, **single_entrance_map, **drop_map}
combine_linked_drop_map = {**linked_drop_map, **sw_linked_drop_map} combine_linked_drop_map = {**linked_drop_map, **sw_linked_drop_map}
LW_Entrances = [] LW_Entrances = []

View File

@@ -221,6 +221,7 @@ def roll_settings(weights):
ret.ow_palettes = get_choice('ow_palettes', romweights) ret.ow_palettes = get_choice('ow_palettes', romweights)
ret.uw_palettes = get_choice('uw_palettes', romweights) ret.uw_palettes = get_choice('uw_palettes', romweights)
ret.shuffle_sfx = get_choice('shuffle_sfx', romweights) == 'on' ret.shuffle_sfx = get_choice('shuffle_sfx', romweights) == 'on'
ret.shuffle_sfxinstruments = get_choice('shuffle_sfxinstruments', romweights) == 'on'
ret.shuffle_songinstruments = get_choice('shuffle_songinstruments', romweights) == 'on' ret.shuffle_songinstruments = get_choice('shuffle_songinstruments', romweights) == 'on'
ret.msu_resume = get_choice('msu_resume', romweights) == 'on' ret.msu_resume = get_choice('msu_resume', romweights) == 'on'