From a1ca99700adebe3ff001aa8bd993f65566c78c1c Mon Sep 17 00:00:00 2001 From: cassidy Date: Thu, 21 Oct 2021 22:36:50 -0400 Subject: [PATCH 01/40] Fix typo in inverted LW portal removal my bad --- Rom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 5680714e..2ea49059 100644 --- a/Rom.py +++ b/Rom.py @@ -2307,7 +2307,7 @@ def set_inverted_mode(world, player, rom): write_int16(rom, snes_to_pc(0x02E8F7), 0x01F8) rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof rom.write_byte(snes_to_pc(0x1BC428), 0x00) # remove diggable light world portals - rom.write_byte(snes_to_pc(0x1BC42A), 0x00) + rom.write_byte(snes_to_pc(0x1BC43A), 0x00) rom.write_byte(snes_to_pc(0x1BC590), 0x00) rom.write_byte(snes_to_pc(0x1BC5A1), 0x00) rom.write_byte(snes_to_pc(0x1BC5B1), 0x00) From 62c348fe7c1c5c0242b7c4197fd397e0dbae2b14 Mon Sep 17 00:00:00 2001 From: aerinon Date: Mon, 25 Oct 2021 16:31:36 -0600 Subject: [PATCH 02/40] Capacity upgrade fairy now sells nothing useful (nor could downgrade your sword) --- Rom.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Rom.py b/Rom.py index 2ea49059..ccfa4c43 100644 --- a/Rom.py +++ b/Rom.py @@ -1619,13 +1619,16 @@ def write_custom_shops(rom, world, player): loc_item = ItemFactory(item['item'], player) if (not world.shopsanity[player] and shop.region.name == 'Capacity Upgrade' and world.difficulty[player] != 'normal'): - continue # skip cap upgrades except in normal/shopsanity - item_id = loc_item.code - price = int16_as_bytes(item['price']) - replace = ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF - replace_price = int16_as_bytes(item['replacement_price']) + # really should be 5A instead of B0 -- surprise!!! + item_id, price, replace, replace_price, item_max = 0xB0, [0, 0], 0xFF, [0, 0], 1 + else: + item_id = loc_item.code + price = int16_as_bytes(item['price']) + replace = ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF + replace_price = int16_as_bytes(item['replacement_price']) + item_max = item['max'] item_player = 0 if item['player'] == player else item['player'] - item_data = [shop_id, item_id] + price + [item['max'], replace] + replace_price + [item_player] + item_data = [shop_id, item_id] + price + [item_max, replace] + replace_price + [item_player] items_data.extend(item_data) rom.write_bytes(0x184800, shop_data) From 3b3fe7f8ca756b412c47da3fd4be1e91f5c0c2bf Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 27 Oct 2021 13:29:07 -0600 Subject: [PATCH 03/40] Bonk fairy (light) standard er restriction --- EntranceShuffle.py | 40 ++++++++++++++++++++++++++++++++++++++-- RELEASENOTES.md | 3 +++ Rules.py | 2 +- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 7e5dcdd3..390cf83d 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -215,6 +215,13 @@ def link_entrances(world, player): if bomb_shop in dw_entrances: dw_entrances.remove(bomb_shop) + # standard mode cannot have Bonk Fairy Light be a connector in case of starting boots + # or boots are in links house, etc. + removed = False + if world.mode[player] == 'standard' and 'Bonk Fairy (Light)' in lw_entrances: + lw_entrances.remove('Bonk Fairy (Light)') + removed = True + # place the old man cave's entrance somewhere in the light world random.shuffle(lw_entrances) old_man_entrance = lw_entrances.pop() @@ -226,6 +233,8 @@ def link_entrances(world, player): # now scramble the rest connect_caves(world, lw_entrances, dw_entrances, caves, player) + if removed: + lw_entrances.append('Bonk Fairy (Light)') # scramble holes scramble_holes(world, player) @@ -395,14 +404,23 @@ def link_entrances(world, player): if bomb_shop in dw_entrances: dw_entrances.remove(bomb_shop) + # standard mode cannot have Bonk Fairy Light be a connector in case of + # starting boots or boots are in links house, etc. + removed = False + if world.mode[player] == 'standard' and 'Bonk Fairy (Light)' in lw_entrances: + lw_entrances.remove('Bonk Fairy (Light)') + removed = True + # place the old man cave's entrance somewhere in the light world old_man_entrance = lw_entrances.pop() connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player) - # now scramble the rest connect_caves(world, lw_entrances, dw_entrances, caves, player) + if removed: + lw_entrances.append('Bonk Fairy (Light)') + # scramble holes scramble_holes(world, player) @@ -487,16 +505,24 @@ def link_entrances(world, player): connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) entrances.remove(bomb_shop) + # standard mode cannot have Bonk Fairy Light be a connector in case of + # starting boots or boots are in links house, etc. + removed = False + if world.mode[player] == 'standard' and 'Bonk Fairy (Light)' in entrances: + entrances.remove('Bonk Fairy (Light)') + removed = True # place the old man cave's entrance somewhere random.shuffle(entrances) old_man_entrance = entrances.pop() connect_two_way(world, old_man_entrance, 'Old Man Cave Exit (West)', player) - # now scramble the rest connect_caves(world, entrances, [], caves, player) + if removed: + entrances.append('Bonk Fairy (Light)') + # scramble holes scramble_holes(world, player) @@ -971,6 +997,13 @@ def link_entrances(world, player): connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) doors.remove(bomb_shop) + # standard mode cannot have Bonk Fairy Light be a connector in case of + # starting boots or boots are in links house, etc. + removed = False + if world.mode[player] == 'standard' and 'Bonk Fairy (Light)' in doors: + doors.remove('Bonk Fairy (Light)') + removed = True + # handle remaining caves for cave in caves: if isinstance(cave, str): @@ -980,6 +1013,9 @@ def link_entrances(world, player): connect_exit(world, exit, exit_pool.pop(), player) connect_entrance(world, doors.pop(), exit, player) + if removed: + doors.append('Bonk Fairy (Light)') + # place remaining doors connect_doors(world, doors, door_targets, player) elif world.shuffle[player] == 'insanity_legacy': diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7098107e..2574015a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -15,6 +15,9 @@ CLI: ```--bombbag``` # Bug Fixes and Notes. +* 0.5.1.5 + * Fix for hard pool capacity upgrades missing + * Bonk Fairy (Light) is no longer in logic for ER Standard and is forbidden to be a connector, so rain state isn't exitable * 0.5.1.4 * Revert quadrant glitch fix for baserom * Fix for inverted diff --git a/Rules.py b/Rules.py index 0d657844..cf19fbb1 100644 --- a/Rules.py +++ b/Rules.py @@ -1212,7 +1212,7 @@ def standard_rules(world, player): 'North Fairy Cave', 'North Fairy Cave Drop', 'Lost Woods Gamble', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Tavern (Front)', 'Bush Covered House', 'Light World Bomb Hut', 'Kakariko Shop', 'Long Fairy Cave', 'Good Bee Cave', '20 Rupee Cave', 'Cave Shop (Lake Hylia)', - 'Waterfall of Wishing', 'Hyrule Castle Main Gate', '50 Rupee Cave', + 'Waterfall of Wishing', 'Hyrule Castle Main Gate', '50 Rupee Cave', 'Bonk Fairy (Light)', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']: add_rule(world.get_entrance(entrance, player), lambda state: state.has('Zelda Delivered', player)) From 4b0c2afa987e3a40ed0c9d52cf068dcbc70ef3b0 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 27 Oct 2021 14:30:25 -0600 Subject: [PATCH 04/40] Retro + enemizer fix for arrows under pots --- RELEASENOTES.md | 1 + Rom.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2574015a..54da4dfc 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -18,6 +18,7 @@ CLI: ```--bombbag``` * 0.5.1.5 * Fix for hard pool capacity upgrades missing * Bonk Fairy (Light) is no longer in logic for ER Standard and is forbidden to be a connector, so rain state isn't exitable + * Bug fix for retro + enemizer and arrows appearing under pots * 0.5.1.4 * Revert quadrant glitch fix for baserom * Fix for inverted diff --git a/Rom.py b/Rom.py index ccfa4c43..eaa78bfe 100644 --- a/Rom.py +++ b/Rom.py @@ -1454,6 +1454,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(0x180176, 0x0A if world.retro[player] else 0x00) # wood arrow cost rom.write_byte(0x180178, 0x32 if world.retro[player] else 0x00) # silver arrow cost rom.write_byte(0x301FC, 0xDA if world.retro[player] else 0xE1) # rupees replace arrows under pots + if enemized: + rom.write_byte(0x1B152e, 0xDA if world.retro[player] else 0xE1) rom.write_byte(0x30052, 0xDB if world.retro[player] else 0xE2) # replace arrows in fish prize from bottle merchant rom.write_bytes(0xECB4E, [0xA9, 0x00, 0xEA, 0xEA] if world.retro[player] else [0xAF, 0x77, 0xF3, 0x7E]) # Thief steals rupees instead of arrows rom.write_bytes(0xF0D96, [0xA9, 0x00, 0xEA, 0xEA] if world.retro[player] else [0xAF, 0x77, 0xF3, 0x7E]) # Pikit steals rupees instead of arrows From 3a413140036a9a29d7f6c0ae5e85aeb3ad32c2b0 Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 29 Oct 2021 11:50:16 -0600 Subject: [PATCH 05/40] Shufflelinks and bombbag added to settings code --- BaseClasses.py | 9 +++++++-- RELEASENOTES.md | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 58530558..0ca14e0b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2396,6 +2396,7 @@ class Spoiler(object): 'weapons': self.world.swords, 'goal': self.world.goal, 'shuffle': self.world.shuffle, + 'shufflelinks': self.world.shufflelinks, 'door_shuffle': self.world.doorShuffle, 'intensity': self.world.intensity, 'item_pool': self.world.difficulty, @@ -2470,6 +2471,7 @@ class Spoiler(object): outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player]) outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player]) outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player]) + outfile.write(f"Link's House Shuffled: {'Yes' if self.metadata['shufflelinks'][player] else 'No'}\n") outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player]) outfile.write('Intensity: %s\n' % self.metadata['intensity'][player]) addition = ' (Random)' if self.world.crystals_gt_orig[player] == 'random' else '' @@ -2669,7 +2671,7 @@ access_mode = {"items": 0, "locations": 1, "none": 2} boss_mode = {"none": 0, "simple": 1, "full": 2, "random": 3, "chaos": 3} enemy_mode = {"none": 0, "shuffled": 1, "random": 2, "chaos": 2, "legacy": 3} -# byte 7: HHHD DP?? (enemy_health, enemy_dmg, potshuffle, ?) +# byte 7: HHHD DPBS (enemy_health, enemy_dmg, potshuffle, bomb logic, shuffle links) e_health = {"default": 0, "easy": 1, "normal": 2, "hard": 3, "expert": 4} e_dmg = {"default": 0, "shuffled": 1, "random": 2} @@ -2700,7 +2702,8 @@ class Settings(object): | (0x20 if w.mapshuffle[p] else 0) | (0x10 if w.compassshuffle[p] else 0) | (boss_mode[w.boss_shuffle[p]] << 2) | (enemy_mode[w.enemy_shuffle[p]]), - (e_health[w.enemy_health[p]] << 5) | (e_dmg[w.enemy_damage[p]] << 3) | (0x4 if w.potshuffle[p] else 0)]) + (e_health[w.enemy_health[p]] << 5) | (e_dmg[w.enemy_damage[p]] << 3) | (0x4 if w.potshuffle[p] else 0) + | (0x2 if w.bombbag[p] else 0) | (1 if w.shufflelinks[p] else 0)]) return base64.b64encode(code, "+-".encode()).decode() @staticmethod @@ -2744,6 +2747,8 @@ class Settings(object): args.enemy_health[p] = r(e_health)[(settings[7] & 0xE0) >> 5] args.enemy_damage[p] = r(e_dmg)[(settings[7] & 0x18) >> 3] args.shufflepots[p] = True if settings[7] & 0x4 else False + args.bombbag[p] = True if settings[7] & 0x2 else False + args.shufflelinks[p] = True if settings[7] & 0x1 else False class KeyRuleType(FastEnum): diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 54da4dfc..75c18e0d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -19,6 +19,7 @@ CLI: ```--bombbag``` * Fix for hard pool capacity upgrades missing * Bonk Fairy (Light) is no longer in logic for ER Standard and is forbidden to be a connector, so rain state isn't exitable * Bug fix for retro + enemizer and arrows appearing under pots + * Add bombbag and shufflelinks to settings code * 0.5.1.4 * Revert quadrant glitch fix for baserom * Fix for inverted From c9307d364058bd9f40a4c868e912c159b038099c Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 30 Oct 2021 18:47:14 -0500 Subject: [PATCH 06/40] Fix issue with SP not flooding lobby in vanilla DR/ER --- EntranceShuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index e845587f..2750b5e6 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -658,7 +658,7 @@ def link_entrances(world, player): ignore_pool = True # check for swamp palace fix - if not (world.get_entrance('Dam', player).connected_region.name in ['Dam', 'Swamp Portal'] and world.get_entrance('Swamp Palace', player).connected_region.name == ['Dam', 'Swamp Portal']): + if not (world.get_entrance('Dam', player).connected_region.name in ['Dam', 'Swamp Portal'] and world.get_entrance('Swamp Palace', player).connected_region.name in ['Dam', 'Swamp Portal']): world.swamp_patch_required[player] = True # check for potion shop location From 0d6565d6f09628419e7888b050980c58645459fc Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 31 Oct 2021 00:07:23 -0500 Subject: [PATCH 07/40] Fixed issue with whirlpools not changing world in Crossed OW --- asm/owrando.asm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/asm/owrando.asm b/asm/owrando.asm index d4a5ebd1..edb79ea7 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -130,9 +130,11 @@ OWWorldCheck16: OWWhirlpoolUpdate: { jsl $02ea6c ; what we wrote over - lda.l OWFlags : and #$01 : beq + - ldx $8a : jsr OWWorldUpdate - + rtl + lda.l OWFlags : and #$01 : bne + + lda.l OWMode+1 : and #$02 : beq .return + + ldx $8a : jsr OWWorldUpdate + .return + rtl } OWFluteCancel: From 0b5c1e70aee15ed8b9d53c557dc04519809ff4c0 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 31 Oct 2021 00:08:21 -0500 Subject: [PATCH 08/40] Fix issue with SP not flooding lobby in vanilla DR/ER --- Plando.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plando.py b/Plando.py index fa9fa848..77e1d77c 100755 --- a/Plando.py +++ b/Plando.py @@ -58,7 +58,7 @@ def main(args): fill_world(world, args.plando) - if world.get_entrance('Dam', 1).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', 1).connected_region.name != 'Swamp Palace (Entrance)': + if not (world.get_entrance('Dam', 1).connected_region.name in ['Dam', 'Swamp Portal'] and world.get_entrance('Swamp Palace', 1).connected_region.name in ['Swamp Portal', 'Dam']): world.swamp_patch_required[1] = True logger.info('Calculating playthrough.') From e2afe98b7522e7caf8c4d360e9fc2d59815123e9 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 31 Oct 2021 15:57:32 -0500 Subject: [PATCH 09/40] Fixed issue with shuffling Ganon/GT via CLI --- Utils.py | 18 ++++++++++++------ resources/app/cli/args.json | 6 +++--- resources/app/cli/lang/en.json | 6 +++--- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Utils.py b/Utils.py index b35e6f4c..c28aa250 100644 --- a/Utils.py +++ b/Utils.py @@ -318,6 +318,10 @@ def update_deprecated_args(args): if args: argVars = vars(args) truthy = [1, True, "True", "true"] + if "multi" in argVars: + players = int(args.multi) + else: + players = 1 # Hints default to FALSE # Don't do: Yes # Do: No @@ -354,12 +358,14 @@ def update_deprecated_args(args): # Shuffle Ganon defaults to TRUE # Don't do: Yes # Do: No - if "no_shuffleganon" in argVars: - args.shuffleganon = not args.no_shuffleganon in truthy - # Don't do: No - # Do: Yes - if "shuffleganon" in argVars: - args.no_shuffleganon = not args.shuffleganon in truthy + orig_shuffleganon = args.shuffleganon + if isinstance(orig_shuffleganon, bool): + args.shuffleganon = {} + for player in range(1, players + 1): + args.shuffleganon[player] = orig_shuffleganon + for player in range(1, players + 1): + if "no_shuffleganon" in argVars: + args.shuffleganon[player] = not args.no_shuffleganon in truthy # Playthrough defaults to TRUE # Don't do: Yes diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 05bc7dea..464fd83b 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -359,12 +359,12 @@ }, "shuffleganon": { "action": "store_false", - "type": "bool" + "type": "bool", + "help": "suppress" }, "no_shuffleganon": { "action": "store_true", - "dest": "shuffleganon", - "help": "suppress" + "dest": "shuffleganon" }, "shufflelinks": { "action": "store_true", diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index 30e46f20..b38fea4c 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -301,7 +301,7 @@ "Keys are universal, shooting arrows costs rupees,", "and a few other little things make this more like Zelda-1. (default: %(default)s)" ], - "pseudoboots": [ " Players starts with pseudo boots that allow dashing but no item checks (default: %(default)s"], + "pseudoboots": [ " Players starts with pseudo boots that allow dashing but no item checks (default: %(default)s)"], "bombbag": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ], "startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ], "usestartinventory": [ "Toggle usage of Starting Inventory." ], @@ -315,8 +315,8 @@ "None: You will be able to reach enough locations to beat the game." ], "hints": [ "Make telepathic tiles and storytellers give helpful hints. (default: %(default)s)" ], - "shuffleganon": [ - "Include the Ganon's Tower and Pyramid Hole in the", + "no_shuffleganon": [ + "Don't include the Ganon's Tower and Pyramid Hole in the", "entrance shuffle pool. (default: %(default)s)" ], "shufflelinks": [ From 1056a6d3ad9e23920ad385bd094d95aa8fdc51b0 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 31 Oct 2021 18:53:09 -0500 Subject: [PATCH 10/40] Fixed Shuffle Ganon CLI/Gui issue --- Utils.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Utils.py b/Utils.py index c28aa250..bdf71e6b 100644 --- a/Utils.py +++ b/Utils.py @@ -358,15 +358,20 @@ def update_deprecated_args(args): # Shuffle Ganon defaults to TRUE # Don't do: Yes # Do: No - orig_shuffleganon = args.shuffleganon - if isinstance(orig_shuffleganon, bool): - args.shuffleganon = {} - for player in range(1, players + 1): - args.shuffleganon[player] = orig_shuffleganon - for player in range(1, players + 1): + if isinstance(args.shuffleganon, bool): if "no_shuffleganon" in argVars: + args.shuffleganon = not args.no_shuffleganon in truthy + else: + for player in range(1, players + 1): args.shuffleganon[player] = not args.no_shuffleganon in truthy - + + if isinstance(args.no_shuffleganon, bool): + if "shuffleganon" in argVars: + args.no_shuffleganon = not args.shuffleganon in truthy + else: + for player in range(1, players + 1): + args.no_shuffleganon[player] = not args.shuffleganon in truthy + # Playthrough defaults to TRUE # Don't do: Yes # Do: No From fe358e921a058f3a96655ee20126a2559a6bd9d9 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 31 Oct 2021 19:47:57 -0500 Subject: [PATCH 11/40] Added missing Starting Equipment section in spoiler log --- BaseClasses.py | 2 +- Main.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index a2bf19b5..b1dee353 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2810,7 +2810,7 @@ class Spoiler(object): if self.startinventory: outfile.write('Starting Inventory:'.ljust(line_width)) - outfile.write('\n'.ljust(line_width+1).join(self.startinventory)) + outfile.write('\n'.ljust(line_width+1).join(self.startinventory) + '\n') def to_file(self, filename): self.parse_data() diff --git a/Main.py b/Main.py index b5740bf4..e4c14248 100644 --- a/Main.py +++ b/Main.py @@ -136,10 +136,6 @@ def main(args, seed=None, fish=None): else: outfilebase = f'DR_{args.outputname if args.outputname else world.seed}' - if args.create_spoiler and not args.jsonout: - logger.info(world.fish.translate("cli","cli","patching.spoiler")) - world.spoiler.meta_to_file(output_path('%s_Spoiler.txt' % outfilebase)) - for player in range(1, world.players + 1): world.difficulty_requirements[player] = difficulties[world.difficulty[player]] @@ -151,7 +147,12 @@ def main(args, seed=None, fish=None): item = ItemFactory(tok.strip(), player) if item: world.push_precollected(item) + + if args.create_spoiler and not args.jsonout: + logger.info(world.fish.translate("cli","cli","patching.spoiler")) + world.spoiler.meta_to_file(output_path('%s_Spoiler.txt' % outfilebase)) + for player in range(1, world.players + 1): create_regions(world, player) create_dungeon_regions(world, player) create_owedges(world, player) From 057f8cbebaf271f07ffe1e14af45b53aa6216db4 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 31 Oct 2021 19:57:40 -0500 Subject: [PATCH 12/40] Fixed Shuffle Ganon CLI/GUI issue --- Utils.py | 19 ++++++------------- resources/app/cli/args.json | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/Utils.py b/Utils.py index bdf71e6b..deed090d 100644 --- a/Utils.py +++ b/Utils.py @@ -358,20 +358,13 @@ def update_deprecated_args(args): # Shuffle Ganon defaults to TRUE # Don't do: Yes # Do: No - if isinstance(args.shuffleganon, bool): - if "no_shuffleganon" in argVars: + if "no_shuffleganon" in argVars: + if isinstance(args.shuffleganon, dict): + for player in range(1, players + 1): + args.shuffleganon[player] = not args.no_shuffleganon in truthy + else: args.shuffleganon = not args.no_shuffleganon in truthy - else: - for player in range(1, players + 1): - args.shuffleganon[player] = not args.no_shuffleganon in truthy - - if isinstance(args.no_shuffleganon, bool): - if "shuffleganon" in argVars: - args.no_shuffleganon = not args.shuffleganon in truthy - else: - for player in range(1, players + 1): - args.no_shuffleganon[player] = not args.shuffleganon in truthy - + # Playthrough defaults to TRUE # Don't do: Yes # Do: No diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 464fd83b..365e40e6 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -358,7 +358,7 @@ "help": "suppress" }, "shuffleganon": { - "action": "store_false", + "action": "store_true", "type": "bool", "help": "suppress" }, From d7e4ada0e250515d5b38bd86a4f7ae3798205f02 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 31 Oct 2021 21:02:50 -0500 Subject: [PATCH 13/40] Play Sanc music when arriving in Sanc in Standard --- Rom.py | 2 +- data/base2current.bps | Bin 141111 -> 141110 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index bdb02639..502eb4b2 100644 --- a/Rom.py +++ b/Rom.py @@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '77b7b9a93f622b0cd08c49e9ee4eac4a' +RANDOMIZERBASEHASH = '4f22298a5c72fff1b04b5bb3278ce13d' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index a552143f7db2b8a7e3c3c6c125d579da90ad6709..1422496b838cfc81a3c47b8a7c72df8b6cfba202 100644 GIT binary patch delta 5617 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 OMbX6xe?2+m&HW#9`~?62 delta 5593 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

?;g&z|-5;r8=g z9JuwT$nXR2R}dkT*9si&EK(Dzd*wtPD)|<9rN^dnxO$0Jdm#JxeJ<>8*trPa_^Hri z)|}Tw-tIjme%UXA!OHv`&Z{ zCBkd`B90KNtJhj3p?U4{}R#~JBLJqOr=**Sl zMUEY_1HZ!b7F~>TNNOp~(cYq#od3O{QsBf_G2>1KaIoN$G&>)U3Vmav+_wvG(#mxJ zYIP)O+4iahM3nV1{nVOECtcH8EDlZ{AQdR)Pqg zzf(>7$18zzudCm>Z;9Ov2Z_Rl+3kA+xPNj%MteaJH&p<9s56tfdxej8bVLxJyx#VI D26_jp From 6cfcdf039c822c4c8efe197a2dc1869732212393 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 1 Nov 2021 02:09:29 -0500 Subject: [PATCH 14/40] Preserve Sanc music change in Standard --- Rom.py | 42 +++++++++++++++++++++++++++++++++++++++--- data/base2current.bps | Bin 141110 -> 141113 bytes 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Rom.py b/Rom.py index 502eb4b2..181396b9 100644 --- a/Rom.py +++ b/Rom.py @@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '4f22298a5c72fff1b04b5bb3278ce13d' +RANDOMIZERBASEHASH = 'a83652bc433c024cff1e277e1afeb627' class JsonRom(object): @@ -688,8 +688,44 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): 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()) + if edge.name == 'Lost Woods NW': + if edge.dest.name != 'Master Sword Meadow SC': + write_int16(rom, 0x15e53 + 0x96, edge.dest.midpoint) + write_int16(rom, 0x15bdb + 0x96, edge.dest.vramLoc) + rom.write_byte(0x15b8c + 0x4b, edge.dest.owIndex) + if edge.dest.owIndex == 0x81: + write_int16(rom, 0x15c79 + 0x96, 0x320) + write_int16(rom, 0x15d17 + 0x96, 0x21e) + write_int16(rom, 0x15db5 + 0x96, 0x3e8) + write_int16(rom, 0x15ef1 + 0x96, 0x019) + write_int16(rom, 0x15f8f + 0x96, 0x2a1) + rom.write_byte(0x1607c + 0x4b, 0xf2) + else: + o = ((edge.dest.owSlotIndex >> 3 + 1) * 2 - 1) * 0x100 + 0xe8 + write_int16(rom, 0x15db5 + 0x96, o) + elif edge.name == 'Zora Waterfall NE': + if edge.dest.name != 'Zoras Domain SW': + write_int16(rom, 0x15e53 + 0x9a, edge.dest.midpoint) + write_int16(rom, 0x15bdb + 0x9a, edge.dest.vramLoc) + rom.write_byte(0x15b8c + 0x4d, edge.dest.owIndex) + if edge.dest.owIndex == 0x80: + write_int16(rom, 0x15c79 + 0x9a, 0x120) + write_int16(rom, 0x15d17 + 0x9a, 0x0) + write_int16(rom, 0x15db5 + 0x9a, 0x1e8) + write_int16(rom, 0x15ef1 + 0x9a, 0x19d) + write_int16(rom, 0x15f8f + 0x9a, 0x083) + rom.write_byte(0x1607c + 0x4d, 0x0e) + else: + o = ((edge.dest.owSlotIndex >> 3 + 1) * 2 - 1) * 0x100 + 0xe8 + write_int16(rom, 0x15db5 + 0x96, o) + elif edge.name == 'Stone Bridge WC': + if edge.dest.name != 'Hobo EC': + write_int16(rom, 0x15db5 + 0x98, edge.dest.midpoint) + write_int16(rom, 0x15bdb + 0x98, edge.dest.vramLoc) + rom.write_byte(0x15b8c + 0x4c, edge.dest.owIndex) + else: + write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc) + write_int16(rom, edge.getAddress() + 0x0e, edge.getTarget()) write_int16(rom, 0x150002, owMode) write_int16(rom, 0x150004, owFlags) diff --git a/data/base2current.bps b/data/base2current.bps index 1422496b838cfc81a3c47b8a7c72df8b6cfba202..3e30500e3acaafe3ea50406c90b492eafb86239f 100644 GIT binary patch delta 5581 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 Z^HW9q{Cv7)G=G;kIrehUpS}+l{vXZo3Zei2 delta 5597 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 Date: Mon, 1 Nov 2021 11:03:49 -0500 Subject: [PATCH 15/40] Fake flipper kill fix reversal and replacement --- Rom.py | 42 +++--------------------------------------- data/base2current.bps | Bin 141113 -> 141231 bytes 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/Rom.py b/Rom.py index 181396b9..e1f2a276 100644 --- a/Rom.py +++ b/Rom.py @@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'a83652bc433c024cff1e277e1afeb627' +RANDOMIZERBASEHASH = '9b5682d6bbf65457ba03eda9c9a0b5c9' class JsonRom(object): @@ -688,44 +688,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): for edge in world.owedges: if edge.dest is not None and isinstance(edge.dest, OWEdge) and edge.player == player: - if edge.name == 'Lost Woods NW': - if edge.dest.name != 'Master Sword Meadow SC': - write_int16(rom, 0x15e53 + 0x96, edge.dest.midpoint) - write_int16(rom, 0x15bdb + 0x96, edge.dest.vramLoc) - rom.write_byte(0x15b8c + 0x4b, edge.dest.owIndex) - if edge.dest.owIndex == 0x81: - write_int16(rom, 0x15c79 + 0x96, 0x320) - write_int16(rom, 0x15d17 + 0x96, 0x21e) - write_int16(rom, 0x15db5 + 0x96, 0x3e8) - write_int16(rom, 0x15ef1 + 0x96, 0x019) - write_int16(rom, 0x15f8f + 0x96, 0x2a1) - rom.write_byte(0x1607c + 0x4b, 0xf2) - else: - o = ((edge.dest.owSlotIndex >> 3 + 1) * 2 - 1) * 0x100 + 0xe8 - write_int16(rom, 0x15db5 + 0x96, o) - elif edge.name == 'Zora Waterfall NE': - if edge.dest.name != 'Zoras Domain SW': - write_int16(rom, 0x15e53 + 0x9a, edge.dest.midpoint) - write_int16(rom, 0x15bdb + 0x9a, edge.dest.vramLoc) - rom.write_byte(0x15b8c + 0x4d, edge.dest.owIndex) - if edge.dest.owIndex == 0x80: - write_int16(rom, 0x15c79 + 0x9a, 0x120) - write_int16(rom, 0x15d17 + 0x9a, 0x0) - write_int16(rom, 0x15db5 + 0x9a, 0x1e8) - write_int16(rom, 0x15ef1 + 0x9a, 0x19d) - write_int16(rom, 0x15f8f + 0x9a, 0x083) - rom.write_byte(0x1607c + 0x4d, 0x0e) - else: - o = ((edge.dest.owSlotIndex >> 3 + 1) * 2 - 1) * 0x100 + 0xe8 - write_int16(rom, 0x15db5 + 0x96, o) - elif edge.name == 'Stone Bridge WC': - if edge.dest.name != 'Hobo EC': - write_int16(rom, 0x15db5 + 0x98, edge.dest.midpoint) - write_int16(rom, 0x15bdb + 0x98, edge.dest.vramLoc) - rom.write_byte(0x15b8c + 0x4c, edge.dest.owIndex) - else: - write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc) - write_int16(rom, edge.getAddress() + 0x0e, edge.getTarget()) + write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc) + write_int16(rom, edge.getAddress() + 0x0e, edge.getTarget()) write_int16(rom, 0x150002, owMode) write_int16(rom, 0x150004, owFlags) diff --git a/data/base2current.bps b/data/base2current.bps index 3e30500e3acaafe3ea50406c90b492eafb86239f..be13fe553cb3aa8f502484eb38aaa9523627028f 100644 GIT binary patch delta 13080 zcmX9k3tUY3_xIkJsp&nv({sALlZ1#$LWn|nMM4N^Jn~qQG~YW+Of^l@S6ww~Zp~Dt zWJ<^@ldzgBW*3WCtX(#-KeJem*6ROl|1+O^&-uR3{eI8)obx^Bd+rujdz)JtVCU0M z>G~;kG?1pv0kuae)7Ho*&30?Nq~?jl^%vPCQZoM@DwUJ##OW7-7M|aBTWt7p>u3d?Y>+?!m{{ zuYbf0pkJwYVBj!?#p|Txb=Zl!M0?b#2OdbtzK80-LdmHf^`?UovtA|%4S(tZGhhiM ziM>oIoZt`gPDn}m2$OeDLym^(iLbciGiXaVI`00N89?LL|IGX#B{voa_!hR1Jur&! z_wIhhI8@e>t0d~-kq53KB8%0Qh~mb>jPHSRvKNYoNW2wx67IMq>?0P%{`Swy-WWdpZosy6NP{H=_$`e=e#fQo5Czx5lEC4K8RZ!mc{TKcBU*eXF zrDPK9VNdb&?Nc9;jkgEvs!BHdEB5W%x3KX*vbdK~D`H0!L4VH3kndWVr3Dp<3#mX# z5-C?dmXm)JsncC3Df!_z<6BlvHvho@tGL7E~A1B25^+RYN8!KWPY$S>EKRw?=JI_>ze| zSWZ4tF?#+R$zM=r;w9vEGU>xBOa618UMn@o$z}JM^l+s#4G|C~swPD$#z>?OgrJYx z^@s@v;^=GeSsa?Q1=r}U%gQb)!WNc^N#1-Adn#5WalOVQmC}1YoubWe=hRDf-eugY z%gLT$cJrlF$?j5#Wj%KR=R$!l=EZ%nC`69=dbGd8_U*4ylMyUOr+rp*bFe>0CD+_ZMa$_Mn`Mddv(Y9+zB& zMO@D{p%2t)uw>rrdNclqAp@KL=+r=BiNwB#ao?}pzF>d+k!rHM^gkZ9Y>|?khnapk zX$jQ>VTUO%1y+KgK~9ybGY?D2Pv5JLOG#&_KGMPRgWS4W^LGqjlSd)XYy=U04~{hR z_LTI#Z|sI>>poL>F7x*jchdQn32b#uv5G#QTlOn=3UND6*6 z8)ue_zIS*}x5A0$K8~~hVnV2LQuY@EEVQdh$X3b8GMH`77b1Ge`+qW}l}8b>!N>$k zE6K(iOybMqNob=K-Czc=5)Ijda=0D*C7%T$kITt7s2euDJ_5!{#&Umo+PywBI{OOrw&cSY%khHAKdSR2Qqt=L zlZa+`ZqKj;=5iIRAZa#5jclzX|0z|I<9ihO+YT;5G$4_~7D+V(Hei&JBjsvKl=rPu z?NIncxVTUp99@-TQ4_mYB$)%%*+8BqJk&H0d#IYMIl_>u;1kR7Jp0sA*(B9tnMKD= zpx87?4t=dAbD@?=7s<&6xX~)u@gkZ_+U>o{PC9W?Fn36EL%&pz9!cG*t} z!YRq0HN#ByL#g_Wg#1^bvQ3eM1FhA(QU_2?mMQ<^(<5T?96gcKfQ0=6dD=6Sd6r(A zD9;v2k?eN1UV`6*TdYSUZaSpF?24U0O#Yy(=c1{1DN)B#6hIqle=C!IwPTBz4JbC! z6py897ewvPt<2p{^0ymIsYT+Ur~H|}36LU*L)swjCNsPWXIdHBYZG)Sl#;18nVs-6 zZ_KjUZOp*1RR4dl90Bxg>0!lk(y^UM&ndj^TapJPpfVq(sWb;LQgjdTVB*U+X@}(G zW>g!gv1R1}mSQp4Pmei44Os41@j6b)$pI*`4f7R~duX4WlV`=P1*MdC9-{G!oIzXP ztBkolZBxsl0y&utAK3C;p59a^UcbUe6~b?+8N@KR)M~9OZ9g^+-LyuB39|!k?n` zR6f*4x#4Q~B5I6(@gGd0NSZcTqP7%MD`-!bCvl*BV1P`LsD06<$SP6~91^d9(b29x zUhSI)UFdSM3Q4_zxLOI@=tQ zGgwAK!xpcg$80SVAN{>z-1K*IMMobHM;{VLUlFMcMv8ATxr3Pkas$kXEjKB{f)3L^ zLC2{ftf`g-?Qv7{aLbBOma0pEW=C|XiMsY5ra2Pc5A|vdE`3F4Ar)rikS}kj1!~KQ z0=~;((r{fZAjR#(j59bQ{@l!P!hBT^8bQ#PO73j`6rYacO{%4HI95S7)WDp~L~l0P z*uHLl6CNyPv&+1)0mW6MQEeDuLJ(~3zu$(w4*o;)%%ybn+>4j&CO*0nvAPdVN~T%+ zTyDTS$(PtQJNA{s@&)5r>({=3Hy32E)_Ta>!xu{M6_fy4Jd@&r?y#Dveh@l-CzoTM z9Fx}-8FD`m<{32Q>2GSn=%{fNugD0^*q|ZAqmSC*M}H@dezg%iJ%55R{4M|#Mf+^% zQaHul9YbluK-g#pQJ9g9Y{MTGO|w|Gp!D}dyLR}D zV#|JkUsC+0+b(%fwcfmBGtilyVyXx1bZ!U)+v`RnkY%r%jzE*WE@imPUMCnXbI=Kg z%N%rYxXeM<2v;wSASNz_RZF*o&QH`!Mve)Ag!*Li0r8m7_RK)NvX+)tJy+Dw^3fn7 zSg*|r)|dEGqk+#TIAPghBG3*>m$?$FHbTv^2(Pgn`V6d;l_>Afn-4={haMk>^Ur3O z)7B1fXqgNC7P_SRO?z}!A*C>-ND;B`6P%X!N#@rmo%kvPYYu6o*dr;CZ1yq9#8>9p zdB-SXIJsGalDKxehQgewy%gLK427xjzQ|0~CMOB?Lk14%{WnKYhb4S)IQJpo@3cuM z)tAbpH@U#qsVR}kd;d8HnCE=WkPOvN>^=XSUtt?l$Ppd6os}d+BsQJb;rcMt(SInW z54)X|Bs8)TYhd2;X+(?@>{`A|7!i5!i-FM0*88J(mU3N^aPU|+Uxhd6rd?o~`13C0 z4$`(cMg=?UOKqb3Ts?#Ov#Lu7ZTw3gUHV=Fq?k8<;{}Zkg2QA>_(p3D_FAjV2lar^ zV6u%#LhS-*wZGO5V}zkm^-Kt7HAw$|7HeUkeQiT z!A*zqw7-f>1S)|$)TOzaY`h?NzeEb3ruh<47a?aw7+0Klt??-|2QX^I^vTaJ78)%R zKJYtbM=Ik!as(EoL3-)pE&|mOUvIEQ62J+51#yd zcwxoJd1Ei>2{c)|FX>qbnCbLv1D;+%&S@*>87({QF2S{B<2e?`SsOubU!H(Pfz!?fNth-)<0Y!Gub zm&9g(tJzB5Qo14g1Bxgy?KSTbHB&*RcSvW>!3dfw5X)oHz^|GMsV{peQH|RIMp>$| z7E!TU7A4-RYdk;|HCj^(DJzQh*wEYPzM)sereqvSoXV}@r#zEwoL*8pDfqIHl?%q_ zDscZ7*FyNWFY`k$lP~w1l(P75FZ1i^=!q|Wb!h1$3^w&2gMiVjo~O5LW%2*k^`IZU zk%s=O#?F`>TUh;cVUqAUzm?xGBIDO`X(*oPeOa0Bd_XyGl2~z*vaMP$y;?ei>d-58 zyt&+mxS(*(oF?6xB%ur`k-|o7Ijmk4K?GlhKd(yioaAt$B|deSWrA2(r1>#AJG&Q2 zzFF+Aj^Nx57?$$r-JLtwoUY>jPm;L#ih>l&(O}*D>xar!xVibU zHaO|NxTi;veIHI*Jppfr*{j_-$&dBt+M#^4!_4SkWK$kV%r%5e0OT4RSZH8TC;!M* z4bc~`MT9hE^5D=PSU^)w>tDjdDW zKhd<~IbUp&VH&SpUZh-9QcGq(({iJt8khvgv=UGTlc56^<^$=adBB@E}R+*?m@#ECw5u%l~?ff zn%OgJugMNc_=m31X+c1-E(GWUt}(zAWstu%GnoQDDn9~UMuAGbufaW)@r9%IfjWzr zz6#+2bYA21s0FDoHLE>$EslHtbe*}zE@kzDzjb%6GxWl!#~Z0abMq$M-Rq3BKS}p9 zJem=XUxGhoxDwMQ!#^{8($8O$oi17nByTTXldS=r-S zH=4vjo6G>hCJ0W<i%3tcVd4?!r|m;G8vT zZLSUekdM?20ix(dDe!aFIN_^>L>Fc-;~ReB<984tUAVynC5ACVm3M$*sYDXC!9>wP zaa5Nm6P2jewA8%Iy48d~78aH}pq3>+DN5uvDAQR5<<6*e1w1ZyL1|Z%c10Dm$`-MQ zL3y#(4Q29C%NST%%SQ#5?(oAt-jyAryj9v-5*7NQ!amp~_eH%7z%scXg68moY{tQA zL{9)pEr5LjPhl`TFCT|enXs@nqSUG@vek^As@x4~BT*;OttNag7!Igtm6n>Uasjn5 zC^r`6o`i)|yb4mYRgMR!IoiJR1VqHUGXUmQnC zbjH57Io;xSux+~o5iu2B-@b@g69+wZxDWyZjMy>V!t=47U5ZBv_@0lUc*k}kaS8mg z!-%hk13RZVZh6AoWU&m4A`d^3%Cz^UKWuAco8*?K%Aw6dtMAlxX_#v&8e z*RWgDq*xe(1Ibu1;RAvfND#4?!RfoaiR9;S{jLSX?3eKTt{?)ndahmyiMUlEYEO)S#t-&#Yb`Cmo4Pi!an)Fw|xqCc`n7MHCo@v&5CVgs&Z_>qz!VnL1 z!OlHPt#)tMm&>v)=j+yVq>qDS?rLI03>4>%B}iX*F4uz?69*sUrVx>laLnEjCf5g; zwD8w3Y41FI4OH$8C7c()+k4$@V|<6?87!A|M7tBHX41*^@atX=caH0WYe!r*J54+8 zJgpS(dEL!Nr~1@8c1{n(3>=@gLHOsNf_jV}{8pfgy^>Ehec_r(`Eacg`27J^m=sK)wNI9Mv1$_6jK&_6kmF$Xc&GSqb||; zNgr#n#V!5)hj{PPwd0WPH>+8&U4u6BkhGUAXk7RHoI~X8>F@JPt+eQ^U)x%-7PJYp z+urBHZ}}dUt9}mwD*$;KV59^F2-jLF@2j;l6@x{ka&jH45YDm+dR8`Ng-D#nPoO5d zzyaa4n9buU=#fCXO$4E=s+-UG$m*G8J95T@%@t7TPQyAG5{G*}%Sk$IpV zOA_{@1IYV29vz(t{{$&cNk6K|54}v<+6w=9pG@~pBX2a#jeiDHsaWgvD7NF!&DZ9& zTOW|@Za+qOSa{Ys`qfuH!F-In+E44b#!=%WE$07wR3)5yX)coIJY8e`}rGlCf|Vd<==6nzmSi7 zp+`j^Yd&_deOAR&4(SzMaZCV=8s$7|T2mV>@%<>RkXg94f zWjRgWSXdc%s=mi%BUX``RVm?MuW9dD(6^RvvMRo?IcgW2Q|mr;{`$g7%pk_WtncA zpr2tJi$GAZV8&)}5?|$h9wykYg2sUl6kU4k)Q!vFB znl|ntLOr3d(U(~J2G%z&B+TOBVB>5jf4v&1g#cwZA^okedJ7dMP8>{|0hb-iU@Nw6 z1@Q8*DW1tI3#gBEt|5igo4Vj76!pAf^ZaV5u@C&Lh>xp;o|?^`Tdj(#Ok70OMw8Ak zYds-ooHX@dxr;z{?R~z&X)4rcLQD*8jKbLwKGMu4l5(Mc(?%lj2Pkg}BkY~vm8SRO z6C8_SoMSPv<}Z}9Gd1YAPbXv*)$5UWf}_FfFae!Rh~zy*i2) zRqXbs(Bt@cOP}yQsh|%zDkdh}hbxcwnfNXOs&pL2w9KA)`g=9qt}$}8i{IxPh)h9d zO=5%sPS2Gp#_pA#v-~gHByez8vrEtQD2yf@v#d4n5T@e3v)CfwfUDX_GioiU@ zd{YWW4#Jt4u;hfB)0VBEYP)@jc)nAeazk-B zX`~tLLB$9MX{Ve~Kj$IW9NNJ%(a~j1)ue?=%2HwG4Hs&Kc4*HB4hrbW$<;+ee+x)l zuZFL*<8Y+PTgN&g(}1>|MU`unXhwN-XxR)v*29d}F&1l={!+`WAB{YYYa!DbvS8Dw z*NO(%t~d#Gic3W|U_#Ubed2AH*bk8gGnmw|6bOxsq+_BVh;Kt#0cD{SQTFI@Lyr%7 zM#@Cux^c2XIMw9wuLf&=DfDcch)2VewuQndg|>v19TbZhy|l3iK|0Z*Zhs~7n8&{j zL0}zJ-laSm8>zj@Bgp7KT;310#jI@lyM4vy3>J0GmCUpMDvr?>(|LKt5{o*O(g{!= zu!RD$R!V_JN3G8F!@BlL=69ZU8Y`PW;xN=xJXw>psEUC>Cq0A~Rm|_Uv;{>^qZCh( zlkuXQg<^tsbRn%S+6*eMR5EF{+8MBN#}sdJC#g^t#%e&Qu(No$+XqR zBkZ?IW|OUUHo{(`FR<0lLD+jlqOCRoVgFPz{kGba{Wy!28tu|C;@yXwhin*~1G-TD34rFId~|uzq?K^OdJvOtU#6YLU|NfOJO{ zlLyD5W^|f}jw)0j&rw|zs${EOLVF#oOhCnU+7#M`qIN37fP8rs<8DuziKvB&up(Gr zi!5r3y0s{}-dG0JD2+VK7IgyXc8c#LFqbN`%%$>Rdsk@)T?m6_6)SUQ!sJs|iBULo zKK(b5Wdg0wB=e@&h+vG3NW6rn@Ik0K+125NY)r%+!f+2cBao&^t9a`ck7Q3> ztPTU?lo*{LY>__azjUOt9KTf&8w;pg6(Xs%t@aTeI2Hz;iyl>aSWw?%U~AaG9eJ#f zQ3)L2r1nYz9b#*ego^o7W!0FtXSj~j6>BIzx5H&K^SW8kVrRi4G!}ZxQshaM+F1yc z-q8KL7hy6BPCg%Lzr>?t*i7~VCdon+A{MjBe_`SI1=f3VO2iijs)Vq*a1Pl72hIly zSEy){M{~h5Q2L(1>ae~GI!961V2~GPZf>4>?A(evrHelQ+^RaID*~(QluHp(2-Dm(c66W zj^c*#lN;%+li=-(en}H!WbnHX6Lc_i?n`D>Tv>qddXDzsyL^F$j|mzrM3u%_eZ$8u z+9FCOHbl_wDPUuPzEORRZ1vFH7>1>ex|;~{Tdj1rVO-~L&dz)F)utL8m$`)ID?GRL ziVb#(_4&mx=F&Lfr(@0CVHJBP!OMbAn&JOv^u#rN(!?~=6UB{3DJk-49B!6L+MD(5 zwD@d`ww$`#eyhdU@=0^DZTzWEn&?x?zsq+ZB)(1dnR=zDsP8`gN%P&APnv~ibTa^z zhmP{pe$<2V%xTmEJgXZ)DUV3BXFDND*~-tH{iL~iqevclE?vu__vW?Zx>-1}c^sV6 zwFM{J&vl)_9dVxYw8iiTgpm2N1!TU~jgIEDALw4o#s%&D-;ZM<&Eej=gRmG4<-N0s zC2aV(S75ehqEV8rO})cyPr9*&NDcA?ZC=C1FW9l8sBw^{yh?hs`J`63S*g~~xT|%u_now{y z52|mC8-27>ZFDN6EhhhS4rv<$N3$sim}^!A0S+BL&m2(Gx@RDr+)M8p3(8rECD8OX z-?rqU&gPp{(9m1i%7O$4D>hb89_$eqA)tcr35Av*HYe^byAVHMyLpy z49^<;mWD^mDw{Krldn)fk8po-ZlX?|q*HIzsk6J(1zqYh0Y@cBNYFcKP7C<5%Nacx z`e6x!+>+=Fg7LC@d0(2`WSXJN$lH$2M*M^;^qz@rKO(>N_#b^@H+lR~%{JQC>s>aQ zT~Se7S&PDK%j-t&me*wgIr7ca+y=cau}jSxsW%$fFKxjL{a?c#@GBr({|+Gu@W_u5 z?0>tFd+5%OGaY7L?&W=`nYr`)cfgP&?Cs@!Mm0wL^w4BnwCu7b09xJ|;pCir^Yol< zwadl>>91vkEmp6mr7c-7>P|V4?*@Om(mXbY7-tpQ~pD_ z!|1aAQ0rlI`F|*nccC|o0Oy~F(V@wT%K9GHARBRya%KC}yIKOD1poTki9gjIARn8R zc9haGw1gT(Z!j&bpZ+1=V5S}QAwQC~h5`3IhupzI!-e0hfC{8pFzdJr=>1S045a0M*} z0#TUY?)6-N2R8bzE|G~iK!DQ2F>e&8F!*=*8g09nQqQgvt*%FcYz(+-Q`rOC@Kq~H zuC&)9r-n)DvEk+lE?XvNlj!!DQZBX8ZhkM@0;t(Ck#zQl{7l8%DJ68^6gcBSnCphs zB~&CWlB2lz>az;h)g^K-G*p0MT@sW%a2@ZNP;%L>+gsc8A%7zmg%&kKL$W4%`j}E^ z7g5^c(CuB1A>FhU6*vA5CS=LPvMnkT_~b!^YuxpC+Lm8JX9bqfqvyV=w$eroPf-+| z1xG&&UL1Fw-ZrkZVst{w!$efI4{1B?@ceqX$`BYPyg79p&}gI4Y|GF~>qn0Wr!+2G z{g4+g0{L?MmGPGHdjAjkE?ZGD$Oaa`6nNs{Qeyrz$nEpzI^UP%f_3ytIH7M0a=2yo z9Zs^@U<&S~-86ELfYq2*C)w~>H~)*UO~0v(9`~nm>fEQ4k1pG!rfg?saZQFM&cryI{Nwe9Ykak%mQaLg2uVzh#8@-e`4 z;@hSqA$ZUK0*%jRIQs>e0c11ag)(fBu*3qV!`#gP+zb`|2I02%}TCthupk@O2!V`dcVI8fO1?neUR( z`RlV-tkpsz#FR_B^85RNF;IicW}v`K9Q2+BlYhUpXb}l$Rsc|*tVh1VpAb)_bmc3_ zZ?(_du~ti+;ptd~d!DTPE#r=9??AKj<&pX!taS=K#i#FKS2WgYtNZ$NY~O|9?g#t( zdwRgY1)Uw-@nZByo1{`Ike-$T;F5hM)UxX$Dib{$+eKwIn~I?zSuWp~di((a`_MkQ z`C^|R3xo49kt$Y)ETGa{B?}e4N8cJEYhFAN*W!RJn#8p_WywCB?OvAxS%E3^2~21yK3U zi&&WlyWZ^~LS0o+?^(&{h{?YW=@sP~E@l*HeUM6gMt_>0C_x9c$T^Zq3^xR5W8ODM z(@)LTN~AU#j<52tOe<}0GlbGB!2 zC&#&dqh;p^jE7lcE|?wWgqdRwikg}PyonZ$`b2e=Mcz1*l-@T+#Od*gaL1=m53kAhC}ZQwN%zE>3YbULn__57X(}|ffm%;9 zc+ zkbbiL<3As9yDI*)GxB463_D*Xqt4w}i*7l8``6p9Mqb4lb*LI#1sM9BdB0ZF9{vro za0A_gqMRN`NetgSLid>TTH{}OU*n&H%JpO4N-`q_G)bEfc#%mA+en*?plJfnA|kVC z77LFhG8T8tVBw(zvDt_Ij)Qw!1c#N#N(-R!oAY7E)3_N!9g9uydcv_H%v7Q@b+QJP>{w1e_5-_S zvg6Mk)@FFNx%qBCc~oAxDO*0HZT9J;vuZL$t4|EVsSesR!zt}`oR+1j~-fr2ijJD#=c^2?1!-H+s2=q1crv_ zNhx?J%gv;U&Pu_PSoW4}9T!vZHaxhBG!wUBhX_Z4IKGHa{KKrO!hEFSAq-|KYPexl zQUWKijs(*Mpo3n9Z}wtW^n8JVOOdw~f-g*r||EZv2!rY(s0s2(~ z9?O=!<52XdMtm9vh8Ft)dS@dZ%!MJ9)Lw=6dHPr*9>rQQwxZ)@BYu>{uGp8^NFQv* zeObPymGp^b{4_D1qSqbA=Xt@^C+=Y%ynu2&YX}>{{$1RJVITOw3uEYUTo2Ik({cQN zj_eB3qLjYYjgKPo#&-POjfb;XytU^$LcYgCt$7vkD^6B(FfL|~ImIf+R?~vJ_+ge= z${!uXJ*2OKE8MWk)8B@^eQRo3wd!vMGv(-@)mi{kM*vOJ;?LNSZs_geZ%s%Q)1Q99 z_2$ypp~YC)qVK?Iy7viQ$jTs^I#QnEF}N38wsa1Vwr8zD{Ej?NVhTZ|XV9H|;v^Bu>DcB?%;XRz ULi(IPk;8qWn{;|ziel~m0n~XZ{Qv*} delta 12904 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 Date: Mon, 1 Nov 2021 17:58:01 +0100 Subject: [PATCH 16/40] Include bottle refills in spoiler --- BaseClasses.py | 15 +++++++++++++++ ItemList.py | 9 +++++++++ Main.py | 1 + Rom.py | 8 ++------ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 58530558..d7625a33 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -97,6 +97,7 @@ class World(object): set_player_attr('player_names', []) set_player_attr('remote_items', False) set_player_attr('required_medallions', ['Ether', 'Quake']) + set_player_attr('bottle_refills', ['Bottle (Green Potion)', 'Bottle (Green Potion)']) set_player_attr('swamp_patch_required', False) set_player_attr('powder_patch_required', False) set_player_attr('ganon_at_pyramid', True) @@ -2272,6 +2273,7 @@ class Spoiler(object): self.doorTypes = {} self.lobbies = {} self.medallions = {} + self.bottles = {} self.playthrough = {} self.unreachables = [] self.startinventory = [] @@ -2315,6 +2317,15 @@ class Spoiler(object): self.medallions[f'Misery Mire ({self.world.get_player_names(player)})'] = self.world.required_medallions[player][0] self.medallions[f'Turtle Rock ({self.world.get_player_names(player)})'] = self.world.required_medallions[player][1] + self.bottles = OrderedDict() + if self.world.players == 1: + self.bottles['Waterfall Bottle'] = self.world.bottle_refills[1][0] + self.bottles['Pyramid Bottle'] = self.world.bottle_refills[1][1] + else: + for player in range(1, self.world.players + 1): + self.bottles[f'Waterfall Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][0] + self.bottles[f'Pyramid Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][1] + self.startinventory = list(map(str, self.world.precollected_items)) self.locations = OrderedDict() @@ -2434,6 +2445,7 @@ class Spoiler(object): out.update(self.locations) out['Starting Inventory'] = self.startinventory out['Special'] = self.medallions + out['Bottles'] = self.bottles if self.hashes: out['Hashes'] = {f"{self.world.player_names[player][team]} (Team {team+1})": hash for (player, team), hash in self.hashes.items()} if self.shops: @@ -2519,6 +2531,9 @@ class Spoiler(object): outfile.write('\n\nMedallions:\n') for dungeon, medallion in self.medallions.items(): outfile.write(f'\n{dungeon}: {medallion} Medallion') + outfile.write('\n\nBottle Refills:\n') + for fairy, bottle in self.bottles.items(): + outfile.write(f'\n{fairy}: {bottle}') if self.startinventory: outfile.write('\n\nStarting Inventory:\n\n') outfile.write('\n'.join(self.startinventory)) diff --git a/ItemList.py b/ItemList.py index c0f2f86c..9e0b0411 100644 --- a/ItemList.py +++ b/ItemList.py @@ -370,6 +370,15 @@ def generate_itempool(world, player): tr_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)] world.required_medallions[player] = (mm_medallion, tr_medallion) + # shuffle bottle refills + if world.difficulty[player] in ['hard', 'expert']: + waterfall_bottle = hardbottles[random.randint(0, 5)] + pyramid_bottle = hardbottles[random.randint(0, 5)] + else: + waterfall_bottle = normalbottles[random.randint(0, 6)] + pyramid_bottle = normalbottles[random.randint(0, 6)] + world.bottle_refills[player] = (waterfall_bottle, pyramid_bottle) + set_up_shops(world, player) if world.retro[player]: diff --git a/Main.py b/Main.py index 75fe9242..e13eda0d 100644 --- a/Main.py +++ b/Main.py @@ -364,6 +364,7 @@ def copy_world(world): ret.player_names = copy.deepcopy(world.player_names) ret.remote_items = world.remote_items.copy() ret.required_medallions = world.required_medallions.copy() + ret.bottle_refills = world.bottle_refills.copy() ret.swamp_patch_required = world.swamp_patch_required.copy() ret.ganon_at_pyramid = world.ganon_at_pyramid.copy() ret.powder_patch_required = world.powder_patch_required.copy() diff --git a/Rom.py b/Rom.py index 2ea49059..fad83d84 100644 --- a/Rom.py +++ b/Rom.py @@ -1066,12 +1066,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): ]) # set Fountain bottle exchange items - if world.difficulty[player] in ['hard', 'expert']: - rom.write_byte(0x348FF, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)]) - rom.write_byte(0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x48][random.randint(0, 5)]) - else: - rom.write_byte(0x348FF, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x3D, 0x48][random.randint(0, 6)]) - rom.write_byte(0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x3D, 0x48][random.randint(0, 6)]) + rom.write_byte(0x348FF, ItemFactory(world.bottle_refills[player][0], player).code) + rom.write_byte(0x3493B, ItemFactory(world.bottle_refills[player][1], player).code) #enable Fat Fairy Chests rom.write_bytes(0x1FC16, [0xB1, 0xC6, 0xF9, 0xC9, 0xC6, 0xF9]) From 8dab54ba9b3be56dd87bfbd942502cf95f96180e Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 1 Nov 2021 13:29:26 -0500 Subject: [PATCH 17/40] Added new spot type checks for OW exits --- BaseClasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BaseClasses.py b/BaseClasses.py index b1dee353..03e4f410 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -939,7 +939,7 @@ class CollectionState(object): # try to resolve a name if resolution_hint == 'Location': spot = self.world.get_location(spot, player) - elif resolution_hint in ['Entrance', 'OWEdge']: + elif resolution_hint in ['Entrance', 'OWEdge', 'OWTerrain', 'Ledge', 'Portal', 'Whirlpool', 'Mirror', 'Flute']: spot = self.world.get_entrance(spot, player) else: # default to Region From e2c51b5dc41b4d7baf387747bd13cb97b393f3d6 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 1 Nov 2021 13:30:46 -0500 Subject: [PATCH 18/40] Minor stuff missing --- DoorShuffle.py | 3 ++- mystery_example.yml | 1 + resources/app/cli/lang/en.json | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index 0c2a9992..6e80d19d 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -91,8 +91,9 @@ def link_doors_main(world, player): world.get_portal('Desert East', player).destination = True if (world.mode[player] == 'inverted') != (0x30 in world.owswaps[player][0] and world.owMixed[player]): world.get_portal('Desert West', player).destination = True - else: + if (world.mode[player] == 'inverted') == (0x00 in world.owswaps[player][0] and world.owMixed[player]): world.get_portal('Skull 2 West', player).destination = True + if (world.mode[player] == 'inverted') == (0x05 in world.owswaps[player][0] and world.owMixed[player]): world.get_portal('Turtle Rock Lazy Eyes', player).destination = True world.get_portal('Turtle Rock Eye Bridge', player).destination = True else: diff --git a/mystery_example.yml b/mystery_example.yml index 3ac5950b..d6fa1eb5 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -50,6 +50,7 @@ restricted: 2 full: 2 lite: 2 + lean: 2 crossed: 3 insanity: 1 shufflelinks: diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index b38fea4c..59d9a9f3 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -181,10 +181,10 @@ " connect remaining entrances.", "Full: Mix cave and dungeon entrances freely while limiting", " multi-entrance caves to one world.", - "Lite: Entrances are put into separate pools based on their", - " vanilla location. Dungeons, dropdowns, connector caves,", - " and locations that have an item are shuffled from", - " individual pools. Non-item locations remain vanilla.", + "Lite: Beginner-friendly. Dungeons/connectors, dropdowns, and", + " item locations are shuffled in separate pools. Non-item", + " locations remain vanilla. Connectors are same-world.", + "Lean: Same as Lite, except connectors can travel cross worlds.", "Crossed: Mix cave and dungeon entrances freely while allowing", " caves to cross between worlds.", "Insanity: Decouple entrances and exits from each other and", From 5bac1ba5cc10126a496db1a597b6a2e578f4903c Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:04:54 +0100 Subject: [PATCH 19/40] Add support for Subweights --- Mystery.py | 13 +++++++- mystery_example_subweights.yml | 57 ++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 mystery_example_subweights.yml diff --git a/Mystery.py b/Mystery.py index 73644500..d3d05fa0 100644 --- a/Mystery.py +++ b/Mystery.py @@ -99,7 +99,8 @@ def get_weights(path): raise Exception(f'Failed to read weights file: {e}') def roll_settings(weights): - def get_choice(option, root=weights): + def get_choice(option, root=None): + root = weights if root is None else root if option not in root: return None if type(root[option]) is not dict: @@ -114,6 +115,16 @@ def roll_settings(weights): return default return choice + while True: + subweights = weights.get('subweights', {}) + if len(subweights) == 0: + break + chances = ({k: int(v['chance']) for (k, v) in subweights.items()}) + subweight_name = random.choices(list(chances.keys()), weights=list(chances.values()))[0] + subweights = weights.get('subweights', {}).get(subweight_name, {}).get('weights', {}) + subweights['subweights'] = subweights.get('subweights', {}) + weights = {**weights, **subweights} + ret = argparse.Namespace() glitches_required = get_choice('glitches_required') diff --git a/mystery_example_subweights.yml b/mystery_example_subweights.yml new file mode 100644 index 00000000..1ec43cac --- /dev/null +++ b/mystery_example_subweights.yml @@ -0,0 +1,57 @@ + description: Example for subweights + glitches_required: none + world_state: open + goals: ganon + weapons: randomized + entrance_shuffle: none + intensity: 3 + subweights: + vanilla: + chance: 25 + weights: + door_shuffle: vanilla + keydropshuffle: + on: 40 + off: 60 + basic: + chance: 25 + weights: + door_shuffle: basic + keydropshuffle: + on: 70 + off: 30 + crossed: + chance: 25 + weights: + door_shuffle: crossed + keydropshuffle: + on: 90 + off: 10 + chaos: + chance: 25 + weights: + door_shuffle: crossed + entrance_shuffle: + none: 30 + crossed: 70 + keydropshuffle: + on: 90 + off: 10 + shopsanity: + on: 50 + off: 50 + bombbag: + on: 25 + off: 75 + subweights: + normal: + chance: 40 + weights: {} + swordless: + chance: 20 + weights: + weapons: swordless + keysanity: + chance: 40 + weights: + dungeon_items: full From 59dd62e3ce2aae97e8c017991e293fb9e85c1dde Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Mon, 1 Nov 2021 21:24:54 +0100 Subject: [PATCH 20/40] Fix some settings being mandatory in weight files --- Mystery.py | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/Mystery.py b/Mystery.py index d3d05fa0..9cf0e729 100644 --- a/Mystery.py +++ b/Mystery.py @@ -128,10 +128,11 @@ def roll_settings(weights): ret = argparse.Namespace() glitches_required = get_choice('glitches_required') - if glitches_required not in ['none', 'no_logic']: - print("Only NMG and No Logic supported") - glitches_required = 'none' - ret.logic = {'none': 'noglitches', 'no_logic': 'nologic'}[glitches_required] + if glitches_required is not None: + if glitches_required not in ['none', 'no_logic']: + print("Only NMG and No Logic supported") + glitches_required = 'none' + ret.logic = {'none': 'noglitches', 'no_logic': 'nologic'}[glitches_required] item_placement = get_choice('item_placement') # not supported in ER @@ -163,26 +164,27 @@ def roll_settings(weights): ret.standardize_palettes = get_choice('standardize_palettes') if 'standardize_palettes' in weights else 'standardize' goal = get_choice('goals') - ret.goal = {'ganon': 'ganon', - 'fast_ganon': 'crystals', - 'dungeons': 'dungeons', - 'pedestal': 'pedestal', - 'triforce-hunt': 'triforcehunt' - }[goal] + if goal is not None: + ret.goal = {'ganon': 'ganon', + 'fast_ganon': 'crystals', + 'dungeons': 'dungeons', + 'pedestal': 'pedestal', + 'triforce-hunt': 'triforcehunt' + }[goal] ret.openpyramid = goal == 'fast_ganon' if ret.shuffle in ['vanilla', 'dungeonsfull', 'dungeonssimple'] else False ret.crystals_gt = get_choice('tower_open') ret.crystals_ganon = get_choice('ganon_open') - - if ret.goal == 'triforcehunt': - goal_min = get_choice_default('triforce_goal_min', default=20) - goal_max = get_choice_default('triforce_goal_max', default=20) - pool_min = get_choice_default('triforce_pool_min', default=30) - pool_max = get_choice_default('triforce_pool_max', default=30) - ret.triforce_goal = random.randint(int(goal_min), int(goal_max)) - min_diff = get_choice_default('triforce_min_difference', default=10) - ret.triforce_pool = random.randint(max(int(pool_min), ret.triforce_goal + int(min_diff)), int(pool_max)) + + goal_min = get_choice_default('triforce_goal_min', default=20) + goal_max = get_choice_default('triforce_goal_max', default=20) + pool_min = get_choice_default('triforce_pool_min', default=30) + pool_max = get_choice_default('triforce_pool_max', default=30) + ret.triforce_goal = random.randint(int(goal_min), int(goal_max)) + min_diff = get_choice_default('triforce_min_difference', default=10) + ret.triforce_pool = random.randint(max(int(pool_min), ret.triforce_goal + int(min_diff)), int(pool_max)) + ret.mode = get_choice('world_state') if ret.mode == 'retro': ret.mode = 'open' @@ -193,11 +195,13 @@ def roll_settings(weights): ret.hints = get_choice('hints') == 'on' - ret.swords = {'randomized': 'random', - 'assured': 'assured', - 'vanilla': 'vanilla', - 'swordless': 'swordless' - }[get_choice('weapons')] + swords = get_choice('weapons') + if swords is not None: + ret.swords = {'randomized': 'random', + 'assured': 'assured', + 'vanilla': 'vanilla', + 'swordless': 'swordless' + }[swords] ret.difficulty = get_choice('item_pool') From 1b1292f6b8f5c05ce0a3511dbcad42a872adb50d Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Mon, 1 Nov 2021 23:29:06 +0100 Subject: [PATCH 21/40] ROM fixes --- Rom.py | 2 +- asm/doorrando.asm | 1 + asm/doortables.asm | 2 ++ asm/drhooks.asm | 3 +++ asm/gfx.asm | 10 ++++++++++ asm/normal.asm | 15 ++++++++++----- asm/scroll.asm | 6 +++++- data/base2current.bps | Bin 136114 -> 136201 bytes 8 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Rom.py b/Rom.py index fad83d84..1153da24 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '11daec4f3e1afc96cd044585dfba9df8' +RANDOMIZERBASEHASH = 'bcce69ecfff6c169371afc84193c0402' class JsonRom(object): diff --git a/asm/doorrando.asm b/asm/doorrando.asm index 807095c7..8cceeba0 100644 --- a/asm/doorrando.asm +++ b/asm/doorrando.asm @@ -9,6 +9,7 @@ ; Normal doors use $FE to store the trap door indicator ; Normal doors use $045e to store Y coordinate when transitioning to in-room stairs ; Normal doors use $045f to determine the order in which supertile quadrants are drawn +; Straight stairs use $046d to store X coordinate on animation start ; Spiral doors use $045e to store stair type ; Gfx uses $b1 to for sub-sub-sub-module thing diff --git a/asm/doortables.asm b/asm/doortables.asm index eae16430..90678ca3 100644 --- a/asm/doortables.asm +++ b/asm/doortables.asm @@ -681,6 +681,8 @@ db $00,$07,$20,$20,$07,$07,$07,$07,$07,$20,$20,$07,$20,$20,$20,$20 db $07,$07,$02,$02,$02,$02,$07,$07,$07,$20,$20,$07,$20,$20,$20,$07 ;27f300 +DungeonTilesets: +db $04,$04,$05,$12,$04,$08,$07,$0C,$09,$0B,$05,$0A,$0D,$0E,$06,$06 ; ;org $27ff00 diff --git a/asm/drhooks.asm b/asm/drhooks.asm index 1d3b485b..f067dad4 100644 --- a/asm/drhooks.asm +++ b/asm/drhooks.asm @@ -76,6 +76,9 @@ nop : jsl OverridePaletteHeader org $02817e ; Bank02.asm : 414 (LDA $02811E, X) jsl FixAnimatedTiles +org $0aef43 ; UnderworldMap_RecoverGFX +jsl FixCloseDungeonMap + org $028a06 ; Bank02.asm : 1941 Dungeon_ResetTorchBackgroundAndPlayer JSL FixWallmasterLamp diff --git a/asm/gfx.asm b/asm/gfx.asm index b22fba62..94cb8848 100644 --- a/asm/gfx.asm +++ b/asm/gfx.asm @@ -45,6 +45,16 @@ FixAnimatedTiles: + LDA $02802E, X ; what we wrote over RTL +FixCloseDungeonMap: + LDA.l DRMode : CMP #$02 : BNE .vanilla + LDA $040C : BMI .vanilla + LSR : TAX + LDA.l DungeonTilesets,x + RTL + .vanilla + LDA $7EC20E + RTL + FixWallmasterLamp: ORA $0458 STY $1C : STA $1D : RTL ; what we wrote over diff --git a/asm/normal.asm b/asm/normal.asm index 3bdf9622..13323d88 100644 --- a/asm/normal.asm +++ b/asm/normal.asm @@ -150,15 +150,14 @@ LoadRoomVert: .notEdge lda $01 : and #$03 : cmp #$03 : bne .normal jsr ScrollToInroomStairs + stz $046d bra .end .normal ldy #$01 : jsr ShiftVariablesMainDir jsr PrepScrollToNormal .scroll - lda $01 : and #$40 : pha + lda $01 : and #$40 : sta $046d jsr ScrollX - pla : beq .end - ldy #$00 : jsr ApplyScroll .end plb ; restore db register rts @@ -291,6 +290,11 @@ StraightStairsAdj: stx $0464 : sty $012e ; what we wrote over lda.l DRMode : beq + lda $045e : bne .toInroom + lda $046d : beq .noScroll + sta $22 + ldy #$00 : jsr ApplyScroll + stz $046d + .noScroll jsr GetTileAttribute : tax lda $11 : cmp #$12 : beq .goingNorth lda $a2 : cmp #$51 : bne ++ @@ -338,9 +342,10 @@ db $d0, $f6, $10, $1a, $f0, $00 StraightStairsFix: { + pha lda.l DRMode : bne + - !add $20 : sta $20 ;what we wrote over - + rtl + pla : !add $20 : sta $20 : rtl ;what we wrote over + + pla : rtl } StraightStairLayerFix: diff --git a/asm/scroll.asm b/asm/scroll.asm index f66918c8..435b5c98 100644 --- a/asm/scroll.asm +++ b/asm/scroll.asm @@ -168,7 +168,11 @@ ScrollX: ;change the X offset variables pla : sta $00 sep #$30 - lda $04 : sta $22 + lda $04 : ldx $046d : bne .straight + sta $22 : bra + + .straight + sta $046d ; set X position later + + lda $00 : sta $23 : sta $0609 : sta $060d lda $01 : sta $a9 lda $0e : asl : ora $ac : sta $ac diff --git a/data/base2current.bps b/data/base2current.bps index a0d85faa0dc758ea3e0d3f04179760dc1e401269..7d88566a4996c6ae95d21586ca043435130550ef 100644 GIT binary patch delta 2460 zcmW+$dsGuw9-cdyJO~Mdpcr0t7}RNeW~mRXtfkaNMAZ7MMWpE#TiWQctMnnYa3^8F z2q78nh5=GccuX}=1dLm?iv?}Fg`Tp;-PInqwY9QPiLX&X)YIw?{bzoU@80izXYTKQ z#}2FPM^s%IU`bEq3q?i!Zt89|9SWI~p_{6zrXfJhY0pD0L>V0P*7AC4xr6QkX48=U z{8z0cyzhsV5LRYnugLFJum{n8yNmIM`{6^y-tZ7phaheFiuYP!JYpiZ7^ z)xh6jB1Bj@>Tx9-P1C^aSZin7>-(l zG_p+aZ?sWXF=JIVy~58?tz~rR2YX8eZE|x|v{d}cQ46GiNy?r@k7WzMlE8doF8~(; z&GLmf_!@nuya+C#qpG|JT{ZosKs`J8tEk!40YljH0E`53)h_|CD{w4)9thJh4(do1 zjXeom)qEoZFQX1!I%p2u(%pC(Yz%zAbTa^E^oM0Rz#J%9_VHi9jlj%~hf7M&GXgds z3#!R-XJOY$)(2lG6nuy1f4&M8Ebha|-xvWHp*XEo(f34D3V^h7P%eej92sweGIEJc z!qcKmR4-bELO*Ufsx%1?#kd&?zd zJ1YdAF>)X>s4lotaMeGZ{h1vyOI#*C9A%BH#ODLVjbwu~^ux#+b5gDzq8aP-u)DA$ zp9mIo>>@-pOQD73m!vbv%eFQlYCtb02+afQgSxY%-{95Cf7QZCr1!RshOt+$pjz-r zDB)iW!&`6lVIsKJJ8Gk|_^kfz=!0M4OMkJA&4qc1XK*uiKh6-78oaNI6S1sL9MVB$ zA&Q+~Eroo_oL`${!YxZL^#!n?Y=>KnC=6<{Jju{OuxkrzR)#~j<*1}lR@3LVe3DOy zVS|&E^Iz5bpd)AsxM{!WG5Wpy&^WWN;Qr3?(F$&WnPc;@MH~{Lx)RkYFh&lg2~9*knhT z!l8B6qIID+Rcbq*#AWjvj`Vs?$I`9G35;vkNC_YJsh55*g>&W5FbfCIGJsfP#vq32$nhl{2M8y zfLvNh-aSzKs2y40@JIQ?cj8;tBj!fNVl~H7 z{xKLXy`oGh{YR32f+bsW<@F4X_SB%T*Kugi`TIeSE(eE>oP$OMO84@+(Zd@lAOp?4 z83&f3l{b?$dk)kKc?o1ij=ZZ-keV--j)P^^SHu5|g zy-6vwEsV^QhoWw!l*XDL49Z#gsUERSkT)6>adC}timRlV$1@(Veoz~^Z z**wOGFjzCw$618#;QE%#QawDhR$y~~LNhyWZ)$D`=R03c)I(>Jn;fVb>9%-gv~mUA zBV88n+k_tSGF>!eqyBq%Cmsz2qOA~uN4@h+5cj@Y^|Pi!LztA=ZN1n%+R_ECpU9akK@Q6oT+Am`S;ehldbfc-n7KJ z!OJcwkL5_cYZ4Y@tglS*#ne-$2_p=K2?Prye}r0r@a`{nliOU9OL{kT2UeYIoLpd# z79dR%E2_PVe3Tm+Bm*>~(e^DTFTCXvWRm%r$$c(?ByBEZIz|qn>N|-U3rsU5dkA}5Q_^+sgN@1I*pOokyD-DTff8(kFM$f`bBrYBh`1 zWlK`wWpf{fiBCIuCYiT7&LSAgAE^Hh!APEuG0@CFB);V*3WW z=VP?#MSDF4f^_Hdd+jFvr)h7ZHDfTUk#{!pMZ4gc)~`!Wn?$k^{W#`|_Sd5QjG)AV zvK)V{KkDhu^l-$CPbZVyw4wBmZu&^CS)}V%#Ps+3$7e{fMY~vRQjzbYzVVrQMXKmo zW3xy0?yt?-`H4e8cA|;#jObt7o_BN&oJ3i~qYTJs__tBc{keF29V)(`2!>JJ{k5~{ z&%48=VeT3$iStUIN4w!mCc8b?hjkueu*09$7n@n1qnhAT%t$veH{unAhdpbWrVV<3%J;$>hW@}qs#7P{2!--AQ}Jw delta 2460 zcmX9;dsGuw8lRa=9)!dY&=@f4I8eu^RF)P=wXI0CrHGAS0`q{=g7`d0z+gYVRNPFqVxIZNiimoSs==PHUn zC&+4_*<;-R>>rj>xRoVqpbOI#6qivrV9C7CTR!n%z3s9yJHb7q&?&go5=g$E^=6m=UMWRjk?(Ubi*jT zsG?ou3s5b28SR1_B;`rE8frz*MIJ4qM*eHJms2So7by`pzq!cSVn9S<^WlVK5sHTv z;d@cEDby@|7DJE1Z{%O0Ct$lGZ^|{6`h+LtlQ%_`tdM5-qj}o~qAQeNUi#51x8B~vI!12W>Z^0x10 zfyPotVaFCG05&M#n*`eHxGY;!5fomsx@S z|Ddd-j@fy{QAQ&$-pU;)NB~}hZ))vE{9Ms)nq@G30apyaAIMGIVddrku@~0YsBPh} zCZf#0k$*EdoB4scWfqC0a7MU(@D(go3XctDqnYr>!PW0ln_~e?%8dmBZ=BhNM>Y~y zZLPdE94i?3rtrE*%q1eI_vaq|RShPQo?A8w#NR+7NcyKX@Zn@u!23O z_DA2I2EvC?r!*LY0^BtGHex1L9tk5tQdlk+!lnLbVWrWN zR{Eyj+NduVxhyJoYB@LDTYO6bWN^udLAO0w3;dhsYXML42$RT0$yl}HC_FH-Td}`_ zQ?t!`SvWMZPz~)cqX8D^y>?=v0?xVfT&V(`0UiYq;+IOkHJg!%8o{zn12RF)$dvkm zR;D$8I?g**Lx!z%9356awd_NFhm3!oO9fA^ap*@?~~IJnHQAl z3kZe?-q9D33<>mb?-6@!@Cj!+mJFu;Srd;WR_Y7j_jgpf*;V2xf{}}ApIt?KQ&IG! z4eq4fcMYf%&b;fuQg*?!cQY4%?PSQ{D2NuPEzZS||C$pVXNYFA)JtQ~wSj zbCGq;v8A!#_!^$sd>y9wALP61qq+8{X2t?Xqlc)i9z199CAGNn&kc51{LkaDfXmgy z0Y>}nNfQeuly12dD;P#QqdX}f?w!62HYdO4Xi^*(0$OWS zTHrpI47_IJ1Zo;UxR)-}JoA7%{MSEz68el2$SEEn;vs|aa&aSO;@cTD$f+(LuAOMW zh!-G(@G5SlVcd(G1xXM=xy3uu#;!8>%@lJt(#J@Kx)1g-^2rp3MP0PQVLc<|apG&| zP`9^_iH1$A%52p5-kbvqACfZDoaumxgU*M9atmX-|zybpm=$sl#vB2#e9+>0Q>JO@W7a#q#>K|ELCZGk{T6u}vztBfB* zZmTD#Km<#B;%EtRh8sVy&h9$_-_5mq5i~-zzxZ=o3U~c4h0rkyv~O{aCT`z5;NzB0 zOS)48;w?x#a=x~|78cXI9EnJB_SXir^V&Bn>$`$6^H`;hovLGJ>Db#khhGYkrZ-_o z5JB{%_m5KgQl*DF)ngVY?+RUifACR~7@Mgyp;1AsgxJ_qu|&GyTWzyzdWvha-agIB zh+_EMSZ3ULk53a*?-GBuoP(KwR&h#LGqw;L;^4)xndnFG+p#tCKj=Oeo!#2gFnE+dZb2;1LYvT*29FqE&ODPAACG4TOg6W~^@nm^y zHdsn@9=N^bu(wma;!bVehv!4z{_*})b*b%=j^4V9-lYO-c6V-%L*t&7N9A?WD?Tmk lJhU8jPs8H&a_UW}0b9DJbHOI`tBZ;+eo07s)1UnQ{{Ucq8Pxy) From 90f7016f497ca0d74a8937bc201c19d228fb082f Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 2 Nov 2021 15:25:34 -0600 Subject: [PATCH 22/40] Update release notes and version Remove tileset fix (I like the other more visually) --- Main.py | 2 +- RELEASENOTES.md | 8 +++++++- Rom.py | 2 +- asm/drhooks.asm | 3 --- asm/gfx.asm | 10 ---------- data/base2current.bps | Bin 136201 -> 136415 bytes 6 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Main.py b/Main.py index e13eda0d..453e33e8 100644 --- a/Main.py +++ b/Main.py @@ -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 Utils import output_path, parse_player_names -__version__ = '0.5.1.4-u' +__version__ = '0.5.1.5-u' from source.classes.BabelFish import BabelFish diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 75c18e0d..c1a7a62c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -19,7 +19,13 @@ CLI: ```--bombbag``` * Fix for hard pool capacity upgrades missing * Bonk Fairy (Light) is no longer in logic for ER Standard and is forbidden to be a connector, so rain state isn't exitable * Bug fix for retro + enemizer and arrows appearing under pots - * Add bombbag and shufflelinks to settings code + * Added bombbag and shufflelinks to settings code + * Catobat fixes: + * Fairy refills in spoiler + * Subweights support in mystery + * More defaults for mystery weights + * Less camera jank for straight stair transitions + * Bug with Straight stairs with vanilla doors where Link's walking animation stopped early is fixed * 0.5.1.4 * Revert quadrant glitch fix for baserom * Fix for inverted diff --git a/Rom.py b/Rom.py index f0484b02..f3b3cb68 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'bcce69ecfff6c169371afc84193c0402' +RANDOMIZERBASEHASH = '2cfa164d4b66a15406f53ca4750ef59a' class JsonRom(object): diff --git a/asm/drhooks.asm b/asm/drhooks.asm index f067dad4..1d3b485b 100644 --- a/asm/drhooks.asm +++ b/asm/drhooks.asm @@ -76,9 +76,6 @@ nop : jsl OverridePaletteHeader org $02817e ; Bank02.asm : 414 (LDA $02811E, X) jsl FixAnimatedTiles -org $0aef43 ; UnderworldMap_RecoverGFX -jsl FixCloseDungeonMap - org $028a06 ; Bank02.asm : 1941 Dungeon_ResetTorchBackgroundAndPlayer JSL FixWallmasterLamp diff --git a/asm/gfx.asm b/asm/gfx.asm index 94cb8848..b22fba62 100644 --- a/asm/gfx.asm +++ b/asm/gfx.asm @@ -45,16 +45,6 @@ FixAnimatedTiles: + LDA $02802E, X ; what we wrote over RTL -FixCloseDungeonMap: - LDA.l DRMode : CMP #$02 : BNE .vanilla - LDA $040C : BMI .vanilla - LSR : TAX - LDA.l DungeonTilesets,x - RTL - .vanilla - LDA $7EC20E - RTL - FixWallmasterLamp: ORA $0458 STY $1C : STA $1D : RTL ; what we wrote over diff --git a/data/base2current.bps b/data/base2current.bps index 7d88566a4996c6ae95d21586ca043435130550ef..328d0f8196c9f52c4e8bb095e2ff83a9157dc2ea 100644 GIT binary patch delta 9649 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

$LjCK)|i1Hr6i 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 QYsU+Z_FC}AysV!81Gzb&;{X5v delta 9515 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 From a433629d1c8c7bac252bffe210ba448bb6e36c5c Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 2 Nov 2021 17:18:00 -0500 Subject: [PATCH 23/40] Fixed boss music --- Rom.py | 2 +- data/base2current.bps | Bin 141231 -> 141230 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index e1f2a276..929a778f 100644 --- a/Rom.py +++ b/Rom.py @@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '9b5682d6bbf65457ba03eda9c9a0b5c9' +RANDOMIZERBASEHASH = '98dd1d63d05b2a3bf2989782679a6b5e' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index be13fe553cb3aa8f502484eb38aaa9523627028f..7b89d22cedeacd5fe4527ce3f942cebd3f01b742 100644 GIT binary patch delta 5450 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 bH9iUBPZR+@6BEJTEM9c!rf+FWU$6fIYZ=i= delta 5579 zcmW+)30xCL7tiE?a0m&YAcuza00beTRtu=8pcJS@#d@WRMJpOST910dZZKd1n-GSu zh6q{0MhuFJjS8rUf-MHC#MXXQYSnr-_K4LMi>-V^ncvL(c{^`r-h1=jyvd1PA=@h~ z$KowohLb<$8PV~KV3KfBmX6mQGRQvuhH*AU3vnVkr$i?+;dRcu5+x2Yi%40IE;}}) z;Q}L4C@tst8WJn`4l(L53&}WzXNh&Xnq@w92N|bx*$F}-E!NAXKpu$1Qo5NSoW#mX z8HU8>vvgHj%ya2UtCZ^{-~i6t7w3K8`yd)b!`)zRM0YnM#P!&max_ik0$c}#BY=BQ zg-#Y$$2f11Sl?|XQmr}#AA<41ILJ)@S%}?-V(!x5)hfh+{w||6${267U_&K6_JAJi zfeLQIsAdOqS?}vAaJV^B2$i3b*ZS8{X zK&bkP;h;VBz<1r(fuEqseS_%jZ6>8eDej{daS4f5^%w>U*N9`)Od6%fejQS{2pMBP zR0(5*e8|X_LnwaAu$a8 z<}uZ84_YU)NQdR3K8c6Sw;xXRoDVACe$Tvo!%fC{REM3aq@9m+Sequod8lqrH7)xL z?Zqi9CS_fHOiqy=Tm6J~I*%KXk}Xf^P+TYb6*1-@O_W_@uBaSp`quZ^u>^_PuFyF) z6?X3k_4%Gd%Ls#vUpgdZKnaOWgbTe!M!iKRp_$q66W95MYyGKWdbUBhHE zI_v|2c3#oRra|bn5FCJyy<&ntf=lJN(pjF3v~v0x?OmjoebTE}=J+S_&}Kz+AxiCQ@!sd|@JZSr1)DjhOgk-&uq8=c7qYp~iwG`6~%sS2B4 z{e1X`6{^(-8)ZnT0SDlq_o>3@ZYJNSNVR#eF8`oywlBdsMGhHxte%|1;jph&0~O3J zJks^_X-h_J?!p#F%hXchoqy-k_Co*#PK&R7BYGna*g)Fr^4TxH~p z_jI`=s1kG7gsJBMu-h)rtL1^l`rLHEu&ApH?uq50mX9^qwtk>@2b*nfOD}i>f$huO zY~F~nD@@a6es4G~bs3{37oW7dyF##97`HwU)Y|5+AL#|8wl$x9Apizjz^=~#_{dhW zd$=1=!J5KcV6p*xE&x3+mDmBYZ0CrX5_dNf(<#ER3Uh#9w28q=Z6nQQe)ewMkK^E* z18@(E*^VIBERtj0b_Po*0iB{FbjOoo=79)1T*7%r$xKr+Un!X-#mu8(=5aA2XJ_M5 zIM)ZS>6DsfBdrc0wQcf1_W~$xNDC25h4>p0Y6wp+Tw&a<_;!b)%IEVZA^4|odqX@J z4;vbyP6dV)H9RgY#b9t?S*1)4Yg`PY$jXk;$zFvox2K` z+L3}}UDwg3zOv2+TcEJ9$GfG>@`p;|7>3779>Tkg>x6em#`Q9X%7YolR)OKL@z{YN zY1m&dV|W=%8D2)D!E<_ko)yURs0=voxDK11@qI;LE}<&iNf;-`Xy3&L+(l)Y;2F4SCrmpLC0OnK(zFZiJTW?KR~;kUT+3kb3I^+d5!n4U2IJrzSQN=% zB>dvUG!O`#Cq_-4mq)6&E;nlB3@yx=p;ZA_1T`OF&x=Gz!{#k`^=JMX<(4ATI~=mY zJEw9JA&Z2GY{Hz>3dTC9b-gNR@&pb~R(!Dl3F22pWAPM?{aMOT?x9*rHWG(vMTF4w zNhoegSYM{cTolcg7)J(>?K;@PP6tWQ#V#M7yZfmDd(}fn4#=q)3u{UT|CD0@u4E_|vbx5chz5z-52?{5h79!Ck6lXn62x|s6xXe+rbGQH4+XKeiS|%TSkVHm$H1?4ibttFTLygW5r zn5Q=6kR!s$z;J4cmxi#LqR|)slgh(x4Uv$0{$sElt~;NfIh{fGP%^(Ze);3N^L%T9 z4|cpWgq0?0Rpul?mqB+yU@hmHDyeN*b*jvr%vZ(+X;xkRacCjV+a9^&!v$tlpG6J5 zqj4$$hP8)-HE>pYta$oNE!+{~hAZ*FzJG6L|W<)WZIw$2z4|d*6kZ{T z?ziqZ({EjTrXv+6_8C{Bj2$AkgYrpmK)lyw-TMo;k z_S$xLv;u(H;xC;60YF5a_Ob$?jll}Ei?9MVgi5mg)47%pU*{UFX(YK z9T__NYQD$r=`K|cyW(4+&3-kX3&il9>*D|mW!L8l`RCZ6R|OI$Y`DH4VrmLmgGIM9 z4IXnnZr@b zsga>~+opFgSsl!l4rc2`ruZUrCgQLP*wY%m%im%T+ThVuPYAV5Mvu+U8-$ym zS48a6Z6e-3V(-Yj$cUotE(iaK7*Dmoa0n#Jy6`FXKM=@(qHm`0|Lv4~0W-dt7clQq zkLXqHyzOUq;Et@qo*vO_G{W-D?WvQKw3nlI){n>FwYr>6iRB6v zxbWKP^iC#d!-1UVTCSL5u~THzMriw1&n*an={Lv3Wo&yR3*LnrzL$*fj@1wosrByVmbtGA93Je%R|N@_ z4>Wxr#@!zPFMOZqvpKH(%ZyhA!CKT{DbW2^OysyVnx9HIj)2G&^jK`yHJat%kq(~Z zX7?T(L^h0HqtPk^xLk4*uDliNxB4SZm(5}y>u_6fbZCfC2#vQw1@F(&P?7Nbtx1LJ z*Jy|YN}V{2NC!D}?S(P@2bgmGP#ru1y-xzZDt)V>j~3bd#W_V5A4OU1ULiSizq5Z9cmwB`I1Xpr@@kAFd6N4o`t^x`0$&aOr;4Fc&rq}wWQ*@X! zr`lg^s(XDnIlL)3-0`|%MisROI4>nzMCkeQp54clYWHx&JrEhiaUOWXB3vi1Z*>T( zc7lWTA`V`)_^q;2)SU@C?=As67<4ZTB*S;^-2i)_@ct&S5bnIcAH5l0-CqJeh3P+q zA)NP9YT&pi58TSZfm+MSF4TAdN*d~c!%gt=PvIe<+sm8o&AKIZxpklxe`(xYc0(Hj zIBA%w;=%a<|Nk*Aw;oZy8oy%2$?)(_DK#HD9t42V@bQECz+F*axBU70MO6p3_v&14 zcf3XD<&IOUq3PjB6cO7V#)3H8vxhgph|qmn{qJ-rhy50MoYg1T2RY5Ns9CW0aR~ZV z>G|WhXy2@IB9fZ36o((~*AUCQ6+|AY8*GXS-~2KtU#QdVUvc~v7xvY=!PF=FeKThM zL*#wFt2lVY3to&W$#&xj=IOB}{h-Ph^D!>8{o@K8dff&5F-;(l9W-u(S${Nvbolm< zAQZ3zUmoVgpfp|54XKaxRw2hFXUCv;e4pz7AX9}h--L9Pfdd>7?97+PlBjzg@ZMh` z=*|4*FETK48-9uDE@+p!BsG-wNO!@poVSD2IGd@zAH-I6Gkw&`3n#tO8#|hjCzwz( zum#^TL8V$jbJ$vf({RSHCr3$>8a_4FcKPou0{0E0%T~_8_u3K$?Z9*U>^Em5Vtfp~ zq-7WYu>d%zBrX^?($UQfxF%+>(>F(C-J|l@)G0}M(yE(Qo&5Vi*jr5tGxzzt3U|*+NYv+`S+aZ^@qt-Wv{vQ)d=~2=Hmk-Nit7)hlMr55(v7MZ~`P k4_aP~;=bg9*p|oP-1!3FMoo<1?iSwdc=z Date: Tue, 2 Nov 2021 18:14:40 -0500 Subject: [PATCH 24/40] Minor spoiler log changes --- BaseClasses.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 0b01c3ed..34e1f5f2 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2802,12 +2802,14 @@ class Spoiler(object): outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_whirlpool'][player] else 'No')) 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('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shuffleganon'][player] else 'No')) - outfile.write('Shuffle Links:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shufflelinks'][player] else 'No')) + if self.metadata['shuffle'][player] != 'vanilla': + outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shuffleganon'][player] else 'No')) + outfile.write('Shuffle Links:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shufflelinks'][player] else 'No')) outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No')) outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player]) - outfile.write('Intensity:'.ljust(line_width) + '%s\n' % self.metadata['intensity'][player]) - outfile.write('Experimental:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['experimental'][player] else 'No')) + if self.metadata['door_shuffle'][player] != 'vanilla': + outfile.write('Intensity:'.ljust(line_width) + '%s\n' % self.metadata['intensity'][player]) + outfile.write('Experimental:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['experimental'][player] else 'No')) outfile.write('Pot Shuffle:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['potshuffle'][player] else 'No')) outfile.write('Key Drop Shuffle:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['keydropshuffle'][player] else 'No')) outfile.write('Map Shuffle:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No')) From e6805f26c01bea10a02c4b1943bdedea5f218cac Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 2 Nov 2021 18:28:53 -0500 Subject: [PATCH 25/40] Version bump 0.2.1.3 --- CHANGELOG.md | 9 +++++++++ OverworldShuffle.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5d855fc..b71abfd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +### 0.2.1.3 +- New fake flipper handling to allow S+Q rather than insta-kill +- Fixed whirlpools in Crossed OW +- Spoiler fixes, incl. missing Starting Inventory in Spoiler +- Fixed music track change to Sanc music when Standard mode is delivering Zelda +- Fixed SP flooding issue +- Fixed issue with Shuffle Ganon in CLI/GUI +- ~~Merged DR v0.5.1.5 - Mystery subweights~~ + ### 0.2.1.2 - Fixed issue with whirlpools not changing world when in Crossed OW diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 8207d66b..d34be226 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -3,7 +3,7 @@ from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSl from Regions import mark_dark_world_regions, mark_light_world_regions from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel -__version__ = '0.2.1.2-u' +__version__ = '0.2.1.3-u' def link_overworld(world, player): # setup mandatory connections From 34cea05444b78d6955ab30bed17c3a23f8df05ba Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Nov 2021 23:15:05 -0500 Subject: [PATCH 26/40] Fixed bomb rules to require pearl when applicable --- Rules.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Rules.py b/Rules.py index f02796be..695104d1 100644 --- a/Rules.py +++ b/Rules.py @@ -605,9 +605,11 @@ def bomb_rules(world, player): 'Hookshot Cave Back to Middle', 'Hookshot Cave Front to Middle', 'Hookshot Cave Middle to Front','Hookshot Cave Middle to Back', 'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery'] for entrance in bonkable_doors: - add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + add_bunny_rule(world.get_entrance(entrance, player), player) for entrance in bombable_doors: - add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player)) + add_bunny_rule(world.get_entrance(entrance, player), player) bonkable_items = ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right'] bombable_items = ['Blind\'s Hideout - Top', 'Kakariko Well - Top', 'Chicken House', 'Aginah\'s Cave', 'Graveyard Cave', @@ -615,18 +617,23 @@ def bomb_rules(world, player): 'Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom'] for location in bonkable_items: add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player)) + add_bunny_rule(world.get_location(location, player), player) for location in bombable_items: add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player)) + add_bunny_rule(world.get_location(location, player), player) cave_kill_locations = ['Mini Moldorm Cave - Far Left', 'Mini Moldorm Cave - Far Right', 'Mini Moldorm Cave - Left', 'Mini Moldorm Cave - Right', 'Mini Moldorm Cave - Generous Guy', 'Spiral Cave'] for location in cave_kill_locations: add_rule(world.get_location(location, player), lambda state: state.can_kill_most_things(player) or state.can_use_bombs(player)) + add_bunny_rule(world.get_location(location, player), player) add_rule(world.get_entrance('Spiral Cave (top to bottom)', player), lambda state: state.can_kill_most_things(player) or state.can_use_bombs(player)) + add_bunny_rule(world.get_entrance('Spiral Cave (top to bottom)', player), player) paradox_switch_chests = ['Paradox Cave Lower - Far Left', 'Paradox Cave Lower - Left', 'Paradox Cave Lower - Right', 'Paradox Cave Lower - Far Right', 'Paradox Cave Lower - Middle'] for location in paradox_switch_chests: add_rule(world.get_location(location, player), lambda state: state.can_hit_crystal_through_barrier(player)) - + add_bunny_rule(world.get_location(location, player), player) + # Dungeon bomb logic easy_kill_rooms = [ # Door, bool-bombable ('Hyrule Dungeon Armory S', True), # One green guard @@ -683,7 +690,7 @@ def bomb_rules(world, player): if world.doorShuffle[player] == 'vanilla': add_rule(world.get_entrance('TR Lazy Eyes SE', player), lambda state: state.can_use_bombs(player)) # ToDo: Add always true for inverted, cross-entrance, and door-variants and so on. add_rule(world.get_entrance('Turtle Rock Ledge Exit (West)', player), lambda state: state.can_use_bombs(player)) # Is this the same as above? - + dungeon_bonkable = ['Sewers Rat Path WS', 'Sewers Rat Path WN', 'PoD Warp Hint SE', 'PoD Jelly Hall NW', 'PoD Jelly Hall NE', 'PoD Mimics 1 SW', 'Thieves Ambush E', 'Thieves Rail Ledge W', From 891c2d3565079e2b177533e0d2f67e0c4c19d256 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Nov 2021 23:16:35 -0500 Subject: [PATCH 27/40] Fix issue with Crossed ER trying to use a previously consumed entrance --- EntranceShuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EntranceShuffle.py b/EntranceShuffle.py index e70b20b3..65d99e2e 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -557,10 +557,10 @@ def link_entrances(world, player): if world.logic[player] in ['noglitches', 'minorglitches'] or (invFlag != (0x1b in world.owswaps[player][0] and world.owMixed[player])): bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop = random.choice(bomb_shop_doors) - pool.remove(bomb_shop) connect_entrance(world, bomb_shop, 'Big Bomb Shop', player) # shuffle connectors + pool = [e for e in pool if e in entrance_pool] connect_caves(world, pool, [], caves, player) # place remaining doors From b251df440a460a4b6bbfa7cd7d8f82f9c1b5261f Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 4 Nov 2021 21:34:31 -0500 Subject: [PATCH 28/40] Added pseudo items/locations in prep for Big Bomb logic --- ItemList.py | 6 ++++++ Items.py | 2 ++ Regions.py | 6 ++++-- Rules.py | 16 +++++++--------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ItemList.py b/ItemList.py index 817eb72a..b22b5cae 100644 --- a/ItemList.py +++ b/ItemList.py @@ -223,6 +223,12 @@ def generate_itempool(world, player): world.push_item(world.get_location('Floodgate', player), ItemFactory('Open Floodgate', player), False) world.get_location('Floodgate', player).event = True world.get_location('Floodgate', player).locked = True + world.push_item(world.get_location('Big Bomb', player), ItemFactory('Pick Up Big Bomb', player), False) + world.get_location('Big Bomb', player).event = True + world.get_location('Big Bomb', player).locked = True + world.push_item(world.get_location('Pyramid Crack', player), ItemFactory('Detonate Big Bomb', player), False) + world.get_location('Pyramid Crack', player).event = True + world.get_location('Pyramid Crack', player).locked = True world.push_item(world.get_location('Trench 1 Switch', player), ItemFactory('Trench 1 Filled', player), False) world.get_location('Trench 1 Switch', player).event = True world.get_location('Trench 1 Switch', player).locked = True diff --git a/Items.py b/Items.py index 808a0740..d78170e9 100644 --- a/Items.py +++ b/Items.py @@ -177,6 +177,8 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Return Smith': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Pick Up Purple Chest': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Open Floodgate': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Pick Up Big Bomb': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Detonate Big Bomb': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Trench 1 Filled': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Trench 2 Filled': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Drained Swamp': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), diff --git a/Regions.py b/Regions.py index 26b3aeb7..2c3cb99f 100644 --- a/Regions.py +++ b/Regions.py @@ -163,7 +163,7 @@ def create_regions(world, player): create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop', 'Kakariko Grass Mirror Spot']), create_dw_region(player, 'Shield Shop Area', None, ['Shield Shop Fence (Outer) Ledge Drop', 'Forgotton Forest Mirror Spot', 'Shield Shop NW', 'Shield Shop NE']), create_dw_region(player, 'Shield Shop Fence', None, ['Shield Shop Fence (Inner) Ledge Drop', 'Red Shield Shop', 'Forgotton Forest Fence Mirror Spot']), - create_dw_region(player, 'Pyramid Area', ['Pyramid'], ['Pyramid Fairy', 'Pyramid Hole', 'HC Ledge Mirror Spot', 'HC Courtyard Mirror Spot', 'HC Area Mirror Spot', 'HC East Entry Mirror Spot', 'Pyramid ES']), + create_dw_region(player, 'Pyramid Area', ['Pyramid', 'Pyramid Crack'], ['Pyramid Fairy', 'Pyramid Hole', 'HC Ledge Mirror Spot', 'HC Courtyard Mirror Spot', 'HC Area Mirror Spot', 'HC East Entry Mirror Spot', 'Pyramid ES']), create_dw_region(player, 'Pyramid Exit Ledge', None, ['Pyramid Exit Ledge Drop', 'HC Courtyard Left Mirror Spot', 'Pyramid Entrance']), create_dw_region(player, 'Pyramid Pass', None, ['Post Aga Inverted Teleporter', 'HC Area South Mirror Spot', 'Pyramid SW', 'Pyramid SE']), create_dw_region(player, 'Broken Bridge Area', None, ['Broken Bridge Hammer Rock (South)', 'Broken Bridge Water Drop', 'Wooden Bridge Mirror Spot', 'Broken Bridge SW']), @@ -321,7 +321,7 @@ def create_regions(world, player): create_cave_region(player, 'Dark World Hammer Peg Cave', 'a cave with an item', ['Peg Cave']), create_cave_region(player, 'Archery Game', 'a game of skill'), create_cave_region(player, 'Bonk Fairy (Dark)', 'a fairy fountain'), - create_cave_region(player, 'Big Bomb Shop', 'the bomb shop'), + create_cave_region(player, 'Big Bomb Shop', 'the bomb shop', ['Big Bomb']), create_cave_region(player, 'Dark Lake Hylia Healer Fairy', 'a fairy fountain'), create_cave_region(player, 'East Dark World Hint', 'a storyteller'), create_cave_region(player, 'Hype Cave', 'a bounty of five items', ['Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', @@ -1488,6 +1488,8 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Frog': (None, None, False, None), 'Missing Smith': (None, None, False, None), 'Dark Blacksmith Ruins': (None, None, False, None), + 'Big Bomb': (None, None, False, None), + 'Pyramid Crack': (None, None, False, None), 'Trench 1 Switch': (None, None, False, None), 'Trench 2 Switch': (None, None, False, None), 'Swamp Drain': (None, None, False, None), diff --git a/Rules.py b/Rules.py index 695104d1..81359f13 100644 --- a/Rules.py +++ b/Rules.py @@ -58,14 +58,7 @@ def set_rules(world, player): elif world.goal[player] == 'triforcehunt': add_rule(world.get_location('Murahdahla', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) - if world.mode[player] != 'inverted': - set_big_bomb_rules(world, player) - if world.logic[player] == 'owglitches' and world.shuffle[player] not in ('insanity', 'insanity_legacy'): - path_to_hc = mirrorless_path_to_location(world, 'West Death Mountain (Bottom)', 'Hyrule Castle Area', player) - path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.world.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard) and all(rule(state) for rule in path_to_hc), 'or') - else: - set_inverted_big_bomb_rules(world, player) + set_big_bomb_rules(world, player) # if swamp and dam have not been moved we require mirror for swamp palace if not world.swamp_patch_required[player]: @@ -194,6 +187,8 @@ def global_rules(world, player): set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) + set_rule(world.get_location('Big Bomb', player), lambda state: state.has('Crystal 5', player) and state.has('Crystal 6', player)) + set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Detonate Big Bomb', player)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith @@ -1647,6 +1642,8 @@ def find_rules_for_zelda_delivery(world, player): def set_big_bomb_rules(world, player): # this is a mess if len(world.get_region('Big Bomb Shop', player).entrances) > 0: + set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) + bombshop_entrance = world.get_region('Big Bomb Shop', player).entrances[0] Normal_LW_entrances = ['Blinds Hideout', 'Bonk Fairy (Light)', @@ -1877,6 +1874,7 @@ def set_big_bomb_rules(world, player): add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.can_flute(player))) #TODO: Fix red bomb rules, artifically adding a bunch of rules to help reduce unbeatable seeds in OW shuffle + set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: False) #add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('Pyramid Area', 'Region', player)) #add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and state.has('Flippers', player) and state.can_flute(player) and state.has('Hammer', player) and state.has('Hookshot', player) and state.has_Pearl(player) and state.has_Mirror(player))) @@ -2088,7 +2086,7 @@ def set_bunny_rules(world, player, inverted): 'Checkerboard Cave', 'Potion Shop', 'Spectacle Rock Cave', 'Pyramid', 'Hype Cave - Generous Guy', 'Peg Cave', 'Bumper Cave Ledge', 'Dark Blacksmith Ruins', 'Spectacle Rock', 'Bombos Tablet', 'Ether Tablet', 'Purple Chest', 'Blacksmith', - 'Missing Smith', 'Master Sword Pedestal', 'Bottle Merchant', 'Sunken Treasure', 'Desert Ledge', + 'Missing Smith', 'Pyramid Crack', 'Big Bomb', 'Master Sword Pedestal', 'Bottle Merchant', 'Sunken Treasure', 'Desert Ledge', 'Kakariko Shop - Left', 'Kakariko Shop - Middle', 'Kakariko Shop - Right', 'Lake Hylia Shop - Left', 'Lake Hylia Shop - Middle', 'Lake Hylia Shop - Right', 'Potion Shop - Left', 'Potion Shop - Middle', 'Potion Shop - Right', From 9ce4f2abfc329e77de98e2a8ab1eb02d674d7469 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 4 Nov 2021 21:36:56 -0500 Subject: [PATCH 29/40] Minor code move --- Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 81359f13..b2f860b2 100644 --- a/Rules.py +++ b/Rules.py @@ -186,7 +186,6 @@ def global_rules(world, player): set_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest - set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_location('Big Bomb', player), lambda state: state.has('Crystal 5', player) and state.has('Crystal 6', player)) set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Detonate Big Bomb', player)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) @@ -726,6 +725,7 @@ def default_rules(world, player): set_rule(world.get_location('Zora\'s Ledge', player), lambda state: state.has('Flippers', player)) set_rule(world.get_location('Potion Shop', player), lambda state: state.has('Mushroom', player)) set_rule(world.get_location('Flute Spot', player), lambda state: state.has('Shovel', player)) + set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) # Entrance Access From 87f0cdd3fd7b89b8e4fd989c6e7655f921b222e5 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Nov 2021 12:28:16 -0500 Subject: [PATCH 30/40] Initial red bomb pathing --- BaseClasses.py | 48 +++++- Main.py | 2 +- Rules.py | 437 +------------------------------------------------ 3 files changed, 48 insertions(+), 439 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 34e1f5f2..605122c6 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1581,15 +1581,55 @@ class Entrance(object): self.player = player self.door = None self.hide_path = False + self.temp_path = [] def can_reach(self, state): - if self.parent_region.can_reach(state) and self.access_rule(state): - if not self.hide_path and not self in state.path: - state.path[self] = (self.name, state.path.get(self.parent_region, (self.parent_region.name, None))) - return True + if self.name == 'Pyramid Fairy': + world = self.parent_region.world if self.parent_region else None + big_bomb_location = world.get_location('Big Bomb', self.player) + if big_bomb_location.can_reach(state) and self.can_reach_thru(state, big_bomb_location.parent_region, True, True) and self.access_rule(state): + if not self in state.path: + path = state.path.get(big_bomb_location.parent_region, (big_bomb_location.parent_region.name, None)) + path = ('Big Bomb Shop Exit', ('Pick Up Big Bomb', path)) + while len(self.temp_path): + exit = self.temp_path.pop(0) + path = (exit.name, (exit.parent_region.name, path)) + path = ('Detonate Big Bomb', (self.parent_region.name, path)) + state.path[self] = (self.name, path) + return True + else: + if self.parent_region.can_reach(state) and self.access_rule(state): + if not self.hide_path and not self in state.path: + state.path[self] = (self.name, state.path.get(self.parent_region, (self.parent_region.name, None))) + return True return False + def can_reach_thru(self, state, start_region, ignore_underworld=False, ignore_ledges=False): + def explore_region(region, path = []): + nonlocal found + if region not in explored_regions or len(explored_regions[region]) > len(path): + explored_regions[region] = path + for exit in region.exits: + if exit.connected_region and (not ignore_ledges or exit.spot_type != 'Ledge') \ + and (not ignore_underworld or exit.connected_region.type not in [RegionType.Cave, RegionType.Dungeon]) \ + and exit.access_rule(state): + if exit.connected_region == self.parent_region: + found = True + explored_regions[self.parent_region] = path + [exit] + else: + explore_region(exit.connected_region, path + [exit]) + + found = False + explored_regions = {} + explore_region(start_region.entrances[0].parent_region) + if found: + self.temp_path = explored_regions[self.parent_region] + + #TODO: Implement residual mirror portal placing for the previous leg, to be used for the final destination + + return found + def connect(self, region, addresses=None, target=None, vanilla=None): self.connected_region = region self.target = target diff --git a/Main.py b/Main.py index 0b6de69e..0b55a51c 100644 --- a/Main.py +++ b/Main.py @@ -567,7 +567,7 @@ def create_playthrough(world): # get locations containing progress items prog_locations = [location for location in world.get_filled_locations() if location.item.advancement] - optional_locations = ['Trench 1 Switch', 'Trench 2 Switch', 'Ice Block Drop'] + optional_locations = ['Trench 1 Switch', 'Trench 2 Switch', 'Ice Block Drop', 'Big Bomb', 'Pyramid Crack'] state_cache = [None] collection_spheres = [] state = CollectionState(world) diff --git a/Rules.py b/Rules.py index b2f860b2..8fd9f1dc 100644 --- a/Rules.py +++ b/Rules.py @@ -58,7 +58,9 @@ def set_rules(world, player): elif world.goal[player] == 'triforcehunt': add_rule(world.get_location('Murahdahla', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) - set_big_bomb_rules(world, player) + # big bomb rules + if len(world.get_region('Big Bomb Shop', player).entrances) > 0: + set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) # if swamp and dam have not been moved we require mirror for swamp palace if not world.swamp_patch_required[player]: @@ -1639,441 +1641,8 @@ def find_rules_for_zelda_delivery(world, player): raise Exception('No path to Sanctuary found') -def set_big_bomb_rules(world, player): - # this is a mess - if len(world.get_region('Big Bomb Shop', player).entrances) > 0: - set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) - bombshop_entrance = world.get_region('Big Bomb Shop', player).entrances[0] - Normal_LW_entrances = ['Blinds Hideout', - 'Bonk Fairy (Light)', - 'Lake Hylia Fairy', - 'Light Hype Fairy', - 'Desert Fairy', - 'Chicken House', - 'Aginahs Cave', - 'Sahasrahlas Hut', - 'Cave Shop (Lake Hylia)', - 'Blacksmiths Hut', - 'Sick Kids House', - 'Lost Woods Gamble', - 'Fortune Teller (Light)', - 'Snitch Lady (East)', - 'Snitch Lady (West)', - 'Bush Covered House', - 'Tavern (Front)', - 'Light World Bomb Hut', - 'Kakariko Shop', - 'Mini Moldorm Cave', - 'Long Fairy Cave', - 'Good Bee Cave', - '20 Rupee Cave', - '50 Rupee Cave', - 'Ice Rod Cave', - 'Bonk Rock Cave', - 'Library', - 'Potion Shop', - 'Dam', - 'Lumberjack House', - 'Lake Hylia Fortune Teller', - 'Eastern Palace', - 'Kakariko Gamble Game', - 'Kakariko Well Cave', - 'Bat Cave Cave', - 'Elder House (East)', - 'Elder House (West)', - 'North Fairy Cave', - 'Lost Woods Hideout Stump', - 'Lumberjack Tree Cave', - 'Two Brothers House (East)', - 'Sanctuary', - 'Hyrule Castle Entrance (South)', - 'Hyrule Castle Secret Entrance Stairs'] - LW_walkable_entrances = ['Dark Lake Hylia Ledge Fairy', - 'Dark Lake Hylia Ledge Spike Cave', - 'Dark Lake Hylia Ledge Hint', - 'Mire Shed', - 'Dark Desert Hint', - 'Dark Desert Fairy', - 'Misery Mire'] - Northern_DW_entrances = ['Brewery', - 'C-Shaped House', - 'Chest Game', - 'Dark World Hammer Peg Cave', - 'Red Shield Shop', - 'Dark Sanctuary Hint', - 'Fortune Teller (Dark)', - 'Dark World Shop', - 'Dark World Lumberjack Shop', - 'Thieves Town', - 'Skull Woods First Section Door', - 'Skull Woods Second Section Door (East)'] - Southern_DW_entrances = ['Hype Cave', - 'Bonk Fairy (Dark)', - 'Archery Game', - 'Big Bomb Shop', - 'Dark Lake Hylia Shop', - 'Swamp Palace'] - Isolated_DW_entrances = ['Spike Cave', - 'Cave Shop (Dark Death Mountain)', - 'Dark Death Mountain Fairy', - 'Mimic Cave', - 'Skull Woods Second Section Door (West)', - 'Skull Woods Final Section', - 'Ice Palace', - 'Turtle Rock', - 'Dark Death Mountain Ledge (West)', - 'Dark Death Mountain Ledge (East)', - 'Bumper Cave (Top)', - 'Superbunny Cave (Top)', - 'Superbunny Cave (Bottom)', - 'Hookshot Cave', - 'Ganons Tower', - 'Turtle Rock Isolated Ledge Entrance', - 'Hookshot Cave Back Entrance'] - Isolated_LW_entrances = ['Capacity Upgrade', - 'Tower of Hera', - 'Death Mountain Return Cave (West)', - 'Paradox Cave (Top)', - 'Fairy Ascension Cave (Top)', - 'Spiral Cave', - 'Desert Palace Entrance (East)'] - West_LW_DM_entrances = ['Old Man Cave (East)', - 'Old Man House (Bottom)', - 'Old Man House (Top)', - 'Death Mountain Return Cave (East)', - 'Spectacle Rock Cave Peak', - 'Spectacle Rock Cave', - 'Spectacle Rock Cave (Bottom)'] - East_LW_DM_entrances = ['Paradox Cave (Bottom)', - 'Paradox Cave (Middle)', - 'Hookshot Fairy', - 'Spiral Cave (Bottom)'] - Mirror_from_SDW_entrances = ['Two Brothers House (West)', - 'Cave 45'] - Castle_ledge_entrances = ['Hyrule Castle Entrance (West)', - 'Hyrule Castle Entrance (East)', - 'Agahnims Tower'] - Desert_mirrorable_ledge_entrances = ['Desert Palace Entrance (West)', - 'Desert Palace Entrance (North)', - 'Desert Palace Entrance (South)', - 'Checkerboard Cave'] - - set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_reach('Pyramid Area', 'Region', player) or state.can_reach('East Dark World', 'Region', player)) and state.can_reach('Big Bomb Shop', 'Region', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player)) - - #crossing peg bridge starting from the southern dark world - def cross_peg_bridge(state): - return state.has('Hammer', player) and state.has_Pearl(player) - - # returning via the eastern and southern teleporters needs the same items, so we use the southern teleporter for out routing. - # crossing preg bridge already requires hammer so we just add the gloves to the requirement - def southern_teleporter(state): - return state.can_lift_rocks(player) and cross_peg_bridge(state) - - # the basic routes assume you can reach eastern light world with the bomb. - # you can then use the southern teleporter, or (if you have beaten Aga1) the hyrule castle gate warp - def basic_routes(state): - return southern_teleporter(state) or state.has('Beat Agahnim 1', player) - - # Key for below abbreviations: - # P = pearl - # A = Aga1 - # H = hammer - # M = Mirror - # G = Glove - - if bombshop_entrance.name in Normal_LW_entrances: - #1. basic routes - #2. Can reach Eastern dark world some other way, mirror, get bomb, return to mirror spot, walk to pyramid: Needs mirror - # -> M or BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: basic_routes(state) or state.has_Mirror(player)) - elif bombshop_entrance.name in LW_walkable_entrances: - #1. Mirror then basic routes - # -> M and BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and basic_routes(state)) - elif bombshop_entrance.name in Northern_DW_entrances: - #1. Mirror and basic routes - #2. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl - # -> (Mitts and CPB) or (M and BR) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (state.has_Mirror(player) and basic_routes(state))) - elif bombshop_entrance.name == 'Bumper Cave (Bottom)': - #1. Mirror and Lift rock and basic_routes - #2. Mirror and Flute and basic routes (can make difference if accessed via insanity or w/ mirror from connector, and then via hyrule castle gate, because no gloves are needed in that case) - #3. Go to south DW and then cross peg bridge: Need Mitts and hammer and moon pearl - # -> (Mitts and CPB) or (((G or Flute) and M) and BR)) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and cross_peg_bridge(state)) or (((state.can_lift_rocks(player) or state.can_flute(player)) and state.has_Mirror(player)) and basic_routes(state))) - elif bombshop_entrance.name in Southern_DW_entrances: - #1. Mirror and enter via gate: Need mirror and Aga1 - #2. cross peg bridge: Need hammer and moon pearl - # -> CPB or (M and A) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: cross_peg_bridge(state) or (state.has_Mirror(player) and state.has('Beat Agahnim 1', player))) - elif bombshop_entrance.name in Isolated_DW_entrances: - # 1. mirror then flute then basic routes - # -> M and Flute and BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and state.can_flute(player) and basic_routes(state)) - elif bombshop_entrance.name in Isolated_LW_entrances: - # 1. flute then basic routes - # Prexisting mirror spot is not permitted, because mirror might have been needed to reach these isolated locations. - # -> Flute and BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and basic_routes(state)) - elif bombshop_entrance.name in West_LW_DM_entrances: - # 1. flute then basic routes or mirror - # Prexisting mirror spot is permitted, because flute can be used to reach west DM directly. - # -> Flute and (M or BR) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('West Death Mountain (Bottom)', 'Region', player)) - elif bombshop_entrance.name in East_LW_DM_entrances: - # 1. flute then basic routes or mirror and hookshot - # Prexisting mirror spot is permitted, because flute can be used to reach west DM directly and then east DM via Hookshot - # -> Flute and ((M and Hookshot) or BR) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('East Death Mountain (Bottom)', 'Region', player)) - elif bombshop_entrance.name == 'Fairy Ascension Cave (Bottom)': - # Same as East_LW_DM_entrances except navigation without BR requires Mitts - # -> Flute and ((M and Hookshot and Mitts) or BR) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('East Death Mountain (Bottom)', 'Region', player) and state.can_lift_heavy_rocks(player)) - elif bombshop_entrance.name in Castle_ledge_entrances: - # 1. mirror on pyramid to castle ledge, grab bomb, return through mirror spot: Needs mirror - # 2. flute then basic routes - # -> M or (Flute and BR) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('Hyrule Castle Ledge', 'Region', player)) - elif bombshop_entrance.name in Desert_mirrorable_ledge_entrances: - # Cases when you have mire access: Mirror to reach locations, return via mirror spot, move to center of desert, mirror anagin and: - # 1. Have mire access, Mirror to reach locations, return via mirror spot, move to center of desert, mirror again and then basic routes - # 2. flute then basic routes - # -> (Mire access and M) or Flute) and BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('Desert Ledge', 'Region', player)) - elif bombshop_entrance.name == 'Old Man Cave (West)': - # 1. Lift rock then basic_routes - # 2. flute then basic_routes - # -> (Flute or G) and BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('Death Mountain Entrance', 'Region', player)) - elif bombshop_entrance.name == 'Graveyard Cave': - # 1. flute then basic routes - # 2. (has west dark world access) use existing mirror spot (required Pearl), mirror again off ledge - # -> (Flute or (M and P and West Dark World access) and BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or (state.can_reach('Dark Graveyard Area', 'Region', player) and state.has_Pearl(player) and state.has_Mirror(player))) and basic_routes(state)) - elif bombshop_entrance.name in Mirror_from_SDW_entrances: - # 1. flute then basic routes - # 2. (has South dark world access) use existing mirror spot, mirror again off ledge - # -> (Flute or (M and South Dark World access) and BR - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or (state.can_reach('Pyramid Area', 'Region', player) and state.has_Mirror(player))) and basic_routes(state)) - elif bombshop_entrance.name == 'Dark World Potion Shop': - # 1. walk down by lifting rock: needs gloves and pearl` - # 2. walk down by hammering peg: needs hammer and pearl - # 3. mirror and basic routes - # -> (P and (H or Gloves)) or (M and BR) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('Dark Witch Area', 'Region', player)) - elif bombshop_entrance.name == 'Kings Grave': - # same as the Normal_LW_entrances case except that the pre-existing mirror is only possible if you have mitts - # (because otherwise mirror was used to reach the grave, so would cancel a pre-existing mirror spot) - # to account for insanity, must consider a way to escape without a cave for basic_routes - # -> (M and Mitts) or ((Mitts or Flute or (M and P and West Dark World access)) and BR) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) or state.can_flute(player) or (state.can_reach('Dark Graveyard Area', 'Region', player) and state.has_Pearl(player) and state.has_Mirror(player)))) - elif bombshop_entrance.name == 'Waterfall of Wishing': - # same as the Normal_LW_entrances case except in insanity it's possible you could be here without Flippers which - # means you need an escape route of either Flippers or Flute - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.can_flute(player))) - #TODO: Fix red bomb rules, artifically adding a bunch of rules to help reduce unbeatable seeds in OW shuffle - set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) - set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: False) - #add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_reach('Pyramid Area', 'Region', player)) - #add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_lift_heavy_rocks(player) and state.has('Flippers', player) and state.can_flute(player) and state.has('Hammer', player) and state.has('Hookshot', player) and state.has_Pearl(player) and state.has_Mirror(player))) - -def set_inverted_big_bomb_rules(world, player): - if len(world.get_region('Big Bomb Shop', player).entrances) > 0: - bombshop_entrance = world.get_region('Big Bomb Shop', player).entrances[0] - Normal_LW_entrances = ['Blinds Hideout', - 'Bonk Fairy (Light)', - 'Lake Hylia Fairy', - 'Light Hype Fairy', - 'Desert Fairy', - 'Chicken House', - 'Aginahs Cave', - 'Sahasrahlas Hut', - 'Cave Shop (Lake Hylia)', - 'Blacksmiths Hut', - 'Sick Kids House', - 'Lost Woods Gamble', - 'Fortune Teller (Light)', - 'Snitch Lady (East)', - 'Snitch Lady (West)', - 'Tavern (Front)', - 'Kakariko Shop', - 'Mini Moldorm Cave', - 'Long Fairy Cave', - 'Good Bee Cave', - '20 Rupee Cave', - '50 Rupee Cave', - 'Ice Rod Cave', - 'Bonk Rock Cave', - 'Library', - 'Potion Shop', - 'Dam', - 'Lumberjack House', - 'Lake Hylia Fortune Teller', - 'Eastern Palace', - 'Kakariko Gamble Game', - 'Kakariko Well Cave', - 'Bat Cave Cave', - 'Elder House (East)', - 'Elder House (West)', - 'North Fairy Cave', - 'Lost Woods Hideout Stump', - 'Lumberjack Tree Cave', - 'Two Brothers House (East)', - 'Sanctuary', - 'Hyrule Castle Entrance (South)', - 'Hyrule Castle Secret Entrance Stairs', - 'Hyrule Castle Entrance (West)', - 'Hyrule Castle Entrance (East)', - 'Ganons Tower', - 'Cave 45', - 'Checkerboard Cave', - 'Links House'] - Isolated_LW_entrances = ['Old Man Cave (East)', - 'Old Man House (Bottom)', - 'Old Man House (Top)', - 'Death Mountain Return Cave (East)', - 'Spectacle Rock Cave Peak', - 'Tower of Hera', - 'Death Mountain Return Cave (West)', - 'Paradox Cave (Top)', - 'Fairy Ascension Cave (Top)', - 'Spiral Cave', - 'Paradox Cave (Bottom)', - 'Paradox Cave (Middle)', - 'Hookshot Fairy', - 'Spiral Cave (Bottom)', - 'Mimic Cave', - 'Fairy Ascension Cave (Bottom)', - 'Desert Palace Entrance (West)', - 'Desert Palace Entrance (North)', - 'Desert Palace Entrance (South)'] - Eastern_DW_entrances = ['Palace of Darkness', - 'Palace of Darkness Hint', - 'Dark Lake Hylia Fairy', - 'East Dark World Hint'] - Northern_DW_entrances = ['Brewery', - 'C-Shaped House', - 'Chest Game', - 'Dark World Hammer Peg Cave', - 'Dark Sanctuary Hint', - 'Fortune Teller (Dark)', - 'Dark World Lumberjack Shop', - 'Thieves Town', - 'Skull Woods First Section Door', - 'Skull Woods Second Section Door (East)'] - Southern_DW_entrances = ['Hype Cave', - 'Bonk Fairy (Dark)', - 'Archery Game', - 'Big Bomb Shop', - 'Dark Lake Hylia Shop', - 'Swamp Palace'] - Isolated_DW_entrances = ['Spike Cave', - 'Cave Shop (Dark Death Mountain)', - 'Dark Death Mountain Fairy', - 'Skull Woods Second Section Door (West)', - 'Skull Woods Final Section', - 'Turtle Rock', - 'Dark Death Mountain Ledge (West)', - 'Dark Death Mountain Ledge (East)', - 'Bumper Cave (Top)', - 'Superbunny Cave (Top)', - 'Superbunny Cave (Bottom)', - 'Hookshot Cave', - 'Turtle Rock Isolated Ledge Entrance', - 'Hookshot Cave Back Entrance', - 'Agahnims Tower'] - LW_walkable_entrances = ['Dark Lake Hylia Ledge Fairy', - 'Dark Lake Hylia Ledge Spike Cave', - 'Dark Lake Hylia Ledge Hint', - 'Mire Shed', - 'Dark Desert Hint', - 'Dark Desert Fairy', - 'Misery Mire', - 'Red Shield Shop'] - LW_bush_entrances = ['Bush Covered House', - 'Light World Bomb Hut', - 'Graveyard Cave'] - LW_inaccessible_entrances = ['Desert Palace Entrance (East)', - 'Spectacle Rock Cave', - 'Spectacle Rock Cave (Bottom)'] - - set_rule(world.get_entrance('Pyramid Fairy', player), - lambda state: state.can_reach('Pyramid Area', 'Region', player) and state.can_reach('Big Bomb Shop', 'Region', player) and state.has('Crystal 5', player) and state.has('Crystal 6', player)) - - # Key for below abbreviations: - # P = pearl - # A = Aga1 - # H = hammer - # M = Mirror - # G = Glove - if bombshop_entrance.name in Eastern_DW_entrances: - # Just walk to the pyramid - pass - elif bombshop_entrance.name in Normal_LW_entrances: - # Just walk to the castle and mirror. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player)) - elif bombshop_entrance.name in Isolated_LW_entrances: - # For these entrances, you cannot walk to the castle/pyramid and thus must use Mirror and then Flute. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) and state.has_Mirror(player)) - elif bombshop_entrance.name in Northern_DW_entrances: - # You can just fly with the Flute, you can take a long walk with Mitts and Hammer, - # or you can leave a Mirror portal nearby and then walk to the castle to Mirror again. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Hyrule Castle Area', 'Region', player))) - elif bombshop_entrance.name in Southern_DW_entrances: - # This is the same as north DW without the Mitts rock present. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Hammer', player) or state.can_flute(player) or (state.has_Mirror(player) and state.can_reach('Hyrule Castle Area', 'Region', player))) - elif bombshop_entrance.name in Isolated_DW_entrances: - # There's just no way to escape these places with the bomb and no Flute. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player)) - elif bombshop_entrance.name in LW_walkable_entrances: - # You can fly with the flute, or leave a mirror portal and walk through the light world - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) or (state.has_Mirror(player) and state.can_reach('Hyrule Castle Area', 'Region', player))) - elif bombshop_entrance.name in LW_bush_entrances: - # These entrances are behind bushes in LW so you need either Pearl or the tools to solve NDW bomb shop locations. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and (state.can_flute(player) or state.has_Pearl(player) or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)))) - elif bombshop_entrance.name == 'Dark World Shop': - # This is mostly the same as NDW but the Mirror path requires the Pearl, or using the Hammer - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_reach('Hyrule Castle Area', 'Region', player) and (state.has_Pearl(player) or state.has('Hammer', player)))) - elif bombshop_entrance.name == 'Bumper Cave (Bottom)': - # This is mostly the same as NDW but the Mirror path requires being able to lift a rock. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute or (state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.has_Mirror(player) and state.can_lift_rocks(player) and state.can_reach('Hyrule Castle Area', 'Region', player))) - elif bombshop_entrance.name == 'Old Man Cave (West)': - # The three paths back are Mirror and DW walk, Mirror and Flute, or LW walk and then Mirror. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has_Mirror(player) and ((state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) or (state.can_lift_rocks(player) and state.has_Pearl(player)) or state.can_flute(player))) - elif bombshop_entrance.name == 'Dark World Potion Shop': - # You either need to Flute to 5 or cross the rock/hammer choice pass to the south. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.can_flute(player) or state.has('Hammer', player) or state.can_lift_rocks(player)) - elif bombshop_entrance.name == 'Kings Grave': - # Either lift the rock and walk to the castle to Mirror or Mirror immediately and Flute. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or (state.has_Pearl(player) and state.can_lift_heavy_rocks(player))) and state.has_Mirror(player)) - elif bombshop_entrance.name == 'Two Brothers House (West)': - # First you must Mirror. Then you can either Flute, cross the peg bridge, or use the Agah 1 portal to Mirror again. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) and state.has_Mirror(player)) - elif bombshop_entrance.name == 'Waterfall of Wishing': - # You absolutely must be able to swim to return it from here. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) and state.has_Pearl(player) and state.has_Mirror(player)) - elif bombshop_entrance.name == 'Ice Palace': - # You can swim to the dock or use the Flute to get off the island. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Flippers', player) or state.can_flute(player)) - elif bombshop_entrance.name == 'Capacity Upgrade': - # You must Mirror but then can use either Ice Palace return path. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.has('Flippers', player) or state.can_flute(player)) and state.has_Mirror(player)) - elif bombshop_entrance.name == 'Two Brothers House (West)': - # First you must Mirror. Then you can either Flute, cross the peg bridge, or use the Agah 1 portal to Mirror again. - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: (state.can_flute(player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) and state.has_Mirror(player)) - elif bombshop_entrance.name in LW_inaccessible_entrances: - # You can't get to the pyramid from these entrances without bomb duping. - raise Exception('No valid path to open Pyramid Fairy. (Could not route from %s)' % bombshop_entrance.name) - elif bombshop_entrance.name == 'Pyramid Fairy': - # Self locking. The shuffles don't put the bomb shop here, but doesn't lock anything important. - set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: False) - else: - raise Exception('No logic found for routing from %s to the pyramid.' % bombshop_entrance.name) - - if world.owShuffle[player] != 'vanilla' or world.owMixed[player] or world.owCrossed[player] not in ['none', 'polar']: - set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: False) #temp disable progression until routing to Pyramid get be guaranteed def set_bunny_rules(world, player, inverted): From f0d128d9a00e356a85cc89886eefa71ad13e5fec Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Nov 2021 16:27:31 -0500 Subject: [PATCH 31/40] Moved special Big Bomb pathing to Pyramid Crack --- BaseClasses.py | 2 +- Main.py | 2 +- OWEdges.py | 2 ++ OverworldShuffle.py | 1 + Regions.py | 3 ++- 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 605122c6..f296cb8b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1584,7 +1584,7 @@ class Entrance(object): self.temp_path = [] def can_reach(self, state): - if self.name == 'Pyramid Fairy': + if self.name == 'Pyramid Crack': world = self.parent_region.world if self.parent_region else None big_bomb_location = world.get_location('Big Bomb', self.player) if big_bomb_location.can_reach(state) and self.can_reach_thru(state, big_bomb_location.parent_region, True, True) and self.access_rule(state): diff --git a/Main.py b/Main.py index 0b55a51c..0b0443f0 100644 --- a/Main.py +++ b/Main.py @@ -567,7 +567,7 @@ def create_playthrough(world): # get locations containing progress items prog_locations = [location for location in world.get_filled_locations() if location.item.advancement] - optional_locations = ['Trench 1 Switch', 'Trench 2 Switch', 'Ice Block Drop', 'Big Bomb', 'Pyramid Crack'] + optional_locations = ['Trench 1 Switch', 'Trench 2 Switch', 'Ice Block Drop', 'Big Bomb'] state_cache = [None] collection_spheres = [] state = CollectionState(world) diff --git a/OWEdges.py b/OWEdges.py index b9064281..f3c2369d 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -891,6 +891,7 @@ OWTileRegions = bidict({ 'Shield Shop Fence': 0x5a, 'Pyramid Area': 0x5b, + 'Pyramid Crack': 0x5b, 'Pyramid Exit Ledge': 0x5b, 'Pyramid Pass': 0x5b, @@ -1597,6 +1598,7 @@ OWExitTypes = { 'Catfish Approach Rocks (East)', 'Village of Outcasts Pegs', 'Grassy Lawn Pegs', + 'Pyramid Crack', 'Broken Bridge Hammer Rock (South)', 'Broken Bridge Hammer Rock (North)', 'Broken Bridge Hookshot Gap', diff --git a/OverworldShuffle.py b/OverworldShuffle.py index d34be226..6c76d134 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -942,6 +942,7 @@ mandatory_connections = [# Intra-tile OW Connections ('Shield Shop Fence (Outer) Ledge Drop', 'Shield Shop Fence'), ('Shield Shop Fence (Inner) Ledge Drop', 'Shield Shop Area'), ('Pyramid Exit Ledge Drop', 'Pyramid Area'), + ('Pyramid Crack', 'Pyramid Crack'), ('Broken Bridge Hammer Rock (South)', 'Broken Bridge Northeast'), #hammer/glove ('Broken Bridge Hammer Rock (North)', 'Broken Bridge Area'), #hammer/glove ('Broken Bridge Hookshot Gap', 'Broken Bridge West'), #hookshot diff --git a/Regions.py b/Regions.py index 2c3cb99f..ff11366e 100644 --- a/Regions.py +++ b/Regions.py @@ -163,7 +163,8 @@ def create_regions(world, player): create_dw_region(player, 'Dark Grassy Lawn', None, ['Grassy Lawn Pegs', 'Dark World Shop', 'Kakariko Grass Mirror Spot']), create_dw_region(player, 'Shield Shop Area', None, ['Shield Shop Fence (Outer) Ledge Drop', 'Forgotton Forest Mirror Spot', 'Shield Shop NW', 'Shield Shop NE']), create_dw_region(player, 'Shield Shop Fence', None, ['Shield Shop Fence (Inner) Ledge Drop', 'Red Shield Shop', 'Forgotton Forest Fence Mirror Spot']), - create_dw_region(player, 'Pyramid Area', ['Pyramid', 'Pyramid Crack'], ['Pyramid Fairy', 'Pyramid Hole', 'HC Ledge Mirror Spot', 'HC Courtyard Mirror Spot', 'HC Area Mirror Spot', 'HC East Entry Mirror Spot', 'Pyramid ES']), + create_dw_region(player, 'Pyramid Area', ['Pyramid'], ['Pyramid Fairy', 'Pyramid Crack', 'Pyramid Hole', 'HC Ledge Mirror Spot', 'HC Courtyard Mirror Spot', 'HC Area Mirror Spot', 'HC East Entry Mirror Spot', 'Pyramid ES']), + create_dw_region(player, 'Pyramid Crack', ['Pyramid Crack'], None), create_dw_region(player, 'Pyramid Exit Ledge', None, ['Pyramid Exit Ledge Drop', 'HC Courtyard Left Mirror Spot', 'Pyramid Entrance']), create_dw_region(player, 'Pyramid Pass', None, ['Post Aga Inverted Teleporter', 'HC Area South Mirror Spot', 'Pyramid SW', 'Pyramid SE']), create_dw_region(player, 'Broken Bridge Area', None, ['Broken Bridge Hammer Rock (South)', 'Broken Bridge Water Drop', 'Wooden Bridge Mirror Spot', 'Broken Bridge SW']), From 97ce86fd77acdf60a6ac5eac2ef3321ad2eebae9 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Nov 2021 19:45:56 -0500 Subject: [PATCH 32/40] Added Smith/Purple Chest pathing --- BaseClasses.py | 34 ++++++++++++++++++++++------------ EntranceShuffle.py | 1 + ItemList.py | 3 +++ Items.py | 1 + OWEdges.py | 2 ++ OverworldShuffle.py | 1 + Regions.py | 7 +++++-- Rules.py | 7 +++---- 8 files changed, 38 insertions(+), 18 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index f296cb8b..45de668a 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1584,18 +1584,28 @@ class Entrance(object): self.temp_path = [] def can_reach(self, state): - if self.name == 'Pyramid Crack': - world = self.parent_region.world if self.parent_region else None - big_bomb_location = world.get_location('Big Bomb', self.player) - if big_bomb_location.can_reach(state) and self.can_reach_thru(state, big_bomb_location.parent_region, True, True) and self.access_rule(state): - if not self in state.path: - path = state.path.get(big_bomb_location.parent_region, (big_bomb_location.parent_region.name, None)) - path = ('Big Bomb Shop Exit', ('Pick Up Big Bomb', path)) - while len(self.temp_path): - exit = self.temp_path.pop(0) - path = (exit.name, (exit.parent_region.name, path)) - path = ('Detonate Big Bomb', (self.parent_region.name, path)) - state.path[self] = (self.name, path) + # Destination Pickup OW Only No Ledges Can S&Q + multi_step_locations = { 'Pyramid Crack': ('Big Bomb', True, True, False), + 'Missing Smith': ('Frog', True, False, True), + 'Middle Aged Man': ('Dark Blacksmith Ruins', True, False, True) } + + if self.name in multi_step_locations: + if self not in state.path: + world = self.parent_region.world if self.parent_region else None + step_location = world.get_location(multi_step_locations[self.name][0], self.player) + if step_location.can_reach(state) and self.can_reach_thru(state, step_location.parent_region, multi_step_locations[self.name][1], multi_step_locations[self.name][2], multi_step_locations[self.name][3]) and self.access_rule(state): + if not self in state.path: + path = state.path.get(step_location.parent_region, (step_location.parent_region.name, None)) + item_name = step_location.item.name if step_location.item else 'Pick Up Item' + path = (f'{step_location.parent_region.name} Exit', (item_name, path)) + while len(self.temp_path): + exit = self.temp_path.pop(0) + path = (exit.name, (exit.parent_region.name, path)) + item_name = self.connected_region.locations[0].item.name if self.connected_region.locations[0].item else 'Deliver Item' + path = (item_name, (self.parent_region.name, path)) + state.path[self] = (self.name, path) + return True + else: return True else: if self.parent_region.can_reach(state) and self.access_rule(state): diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 65d99e2e..34733fc2 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -2184,6 +2184,7 @@ mandatory_connections = [('Links House S&Q', 'Links House'), ('Fairy Ascension Cave Climb', 'Fairy Ascension Cave (Top)'), ('Fairy Ascension Cave Pots', 'Fairy Ascension Cave (Bottom)'), ('Fairy Ascension Cave Drop', 'Fairy Ascension Cave (Drop)'), + ('Missing Smith', 'Missing Smith'), ('Superbunny Cave Climb', 'Superbunny Cave (Top)'), ('Hookshot Cave Front to Middle', 'Hookshot Cave (Middle)'), ('Hookshot Cave Middle to Front', 'Hookshot Cave (Front)'), diff --git a/ItemList.py b/ItemList.py index b22b5cae..29963caa 100644 --- a/ItemList.py +++ b/ItemList.py @@ -214,6 +214,9 @@ def generate_itempool(world, player): world.push_item(world.get_location('Dark Blacksmith Ruins', player), ItemFactory('Pick Up Purple Chest', player), False) world.get_location('Dark Blacksmith Ruins', player).event = True world.get_location('Dark Blacksmith Ruins', player).locked = True + world.push_item(world.get_location('Middle Aged Man', player), ItemFactory('Deliver Purple Chest', player), False) + world.get_location('Middle Aged Man', player).event = True + world.get_location('Middle Aged Man', player).locked = True world.push_item(world.get_location('Frog', player), ItemFactory('Get Frog', player), False) world.get_location('Frog', player).event = True world.get_location('Frog', player).locked = True diff --git a/Items.py b/Items.py index d78170e9..637d0b30 100644 --- a/Items.py +++ b/Items.py @@ -176,6 +176,7 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Get Frog': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Return Smith': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Pick Up Purple Chest': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Deliver Purple Chest': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Open Floodgate': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Pick Up Big Bomb': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Detonate Big Bomb': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), diff --git a/OWEdges.py b/OWEdges.py index f3c2369d..6a232e24 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -820,6 +820,7 @@ OWTileRegions = bidict({ 'Ice Cave Area': 0x37, 'Desert Pass Area': 0x3a, + 'Middle Aged Man': 0x3a, 'Desert Pass Southeast': 0x3a, 'Desert Pass Ledge': 0x3a, @@ -1575,6 +1576,7 @@ OWExitTypes = { 'Desert Pass Rocks (North)', 'Desert Pass Rocks (South)', 'Desert Pass Ladder (North)', + 'Middle Aged Man', 'Octoballoon Pier', 'Skull Woods Bush Rock (East)', 'Skull Woods Bush Rock (West)', diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 6c76d134..4ec1ff10 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -902,6 +902,7 @@ mandatory_connections = [# Intra-tile OW Connections ('Desert Pass Ledge Drop', 'Desert Pass Area'), ('Desert Pass Rocks (North)', 'Desert Pass Southeast'), #glove ('Desert Pass Rocks (South)', 'Desert Pass Area'), #glove + ('Middle Aged Man', 'Middle Aged Man'), ('Octoballoon Water Drop', 'Octoballoon Water'), #flippers ('Octoballoon Waterfall Water Drop', 'Octoballoon Water'), #flippers ('Octoballoon Pier', 'Octoballoon Area'), diff --git a/Regions.py b/Regions.py index ff11366e..79f6aeb5 100644 --- a/Regions.py +++ b/Regions.py @@ -111,7 +111,8 @@ def create_regions(world, player): create_lw_region(player, 'Lake Hylia Island', ['Lake Hylia Island'], ['Lake Hylia Island Water Drop']), create_lw_region(player, 'Lake Hylia Water', None, ['Lake Hylia Central Island Pier', 'Lake Hylia Island Pier', 'Lake Hylia West Pier', 'Lake Hylia East Pier', 'Lake Hylia NC', 'Lake Hylia EC', 'Lake Hylia Whirlpool'], Terrain.Water), create_lw_region(player, 'Ice Cave Area', None, ['Ice Rod Cave', 'Good Bee Cave', '20 Rupee Cave', 'Shopping Mall Mirror Spot', 'Ice Cave SE', 'Ice Cave SW']), - create_lw_region(player, 'Desert Pass Area', ['Purple Chest'], ['Desert Pass Ladder (South)', 'Desert Fairy', '50 Rupee Cave', 'Swamp Nook Mirror Spot', 'Desert Pass WS', 'Desert Pass EC', 'Desert Pass Rocks (North)']), + create_lw_region(player, 'Desert Pass Area', None, ['Desert Pass Ladder (South)', 'Middle Aged Man', 'Desert Fairy', '50 Rupee Cave', 'Swamp Nook Mirror Spot', 'Desert Pass WS', 'Desert Pass EC', 'Desert Pass Rocks (North)']), + create_lw_region(player, 'Middle Aged Man', ['Purple Chest'], None), create_lw_region(player, 'Desert Pass Southeast', None, ['Desert Pass Rocks (South)', 'Swamp Nook Southeast Mirror Spot', 'Desert Pass ES']), create_lw_region(player, 'Desert Pass Ledge', None, ['Desert Pass Ladder (North)', 'Desert Pass Ledge Drop', 'Swamp Nook Pegs Mirror Spot', 'Desert Pass WC']), create_lw_region(player, 'Dam Area', ['Sunken Treasure'], ['Dam', 'Swamp Mirror Spot', 'Dam WC', 'Dam WS', 'Dam NC', 'Dam EC']), @@ -269,7 +270,8 @@ def create_regions(world, player): create_cave_region(player, 'Tavern (Front)', 'the tavern'), create_cave_region(player, 'Hyrule Castle Secret Entrance', 'a drop\'s exit', ['Link\'s Uncle', 'Secret Passage'], ['Hyrule Castle Secret Entrance Exit']), create_cave_region(player, 'Sahasrahlas Hut', 'Sahasrahla', ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right', 'Sahasrahla']), - create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith', 'Missing Smith']), + create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith'], ['Missing Smith']), + create_cave_region(player, 'Missing Smith', None, ['Missing Smith']), create_cave_region(player, 'Bat Cave (right)', 'a drop\'s exit', ['Magic Bat'], ['Bat Cave Door']), create_cave_region(player, 'Bat Cave (left)', 'a drop\'s exit', None, ['Bat Cave Exit']), create_cave_region(player, 'Two Brothers House', 'a connector', None, ['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']), @@ -1491,6 +1493,7 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Dark Blacksmith Ruins': (None, None, False, None), 'Big Bomb': (None, None, False, None), 'Pyramid Crack': (None, None, False, None), + 'Middle Aged Man': (None, None, False, None), 'Trench 1 Switch': (None, None, False, None), 'Trench 2 Switch': (None, None, False, None), 'Swamp Drain': (None, None, False, None), diff --git a/Rules.py b/Rules.py index 8fd9f1dc..03d77ca7 100644 --- a/Rules.py +++ b/Rules.py @@ -58,9 +58,6 @@ def set_rules(world, player): elif world.goal[player] == 'triforcehunt': add_rule(world.get_location('Murahdahla', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) - # big bomb rules - if len(world.get_region('Big Bomb Shop', player).entrances) > 0: - set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) # if swamp and dam have not been moved we require mirror for swamp palace if not world.swamp_patch_required[player]: @@ -187,8 +184,10 @@ def global_rules(world, player): set_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) - set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest + set_rule(world.get_entrance('Middle Aged Man', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest + set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Deliver Purple Chest', player)) # Can S&Q with chest set_rule(world.get_location('Big Bomb', player), lambda state: state.has('Crystal 5', player) and state.has('Crystal 6', player)) + set_rule(world.get_entrance('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Detonate Big Bomb', player)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) From f15f29b2c45847f5bd0843cec57b9fa968923c33 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Nov 2021 19:53:32 -0500 Subject: [PATCH 33/40] Added Smith/Purple Chest pathing --- BaseClasses.py | 12 +++++++++--- Rules.py | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 45de668a..95f35e80 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1615,19 +1615,19 @@ class Entrance(object): return False - def can_reach_thru(self, state, start_region, ignore_underworld=False, ignore_ledges=False): + def can_reach_thru(self, state, start_region, ignore_underworld=False, ignore_ledges=False, allow_save_quit=False): def explore_region(region, path = []): nonlocal found if region not in explored_regions or len(explored_regions[region]) > len(path): explored_regions[region] = path for exit in region.exits: if exit.connected_region and (not ignore_ledges or exit.spot_type != 'Ledge') \ - and (not ignore_underworld or exit.connected_region.type not in [RegionType.Cave, RegionType.Dungeon]) \ + and exit.connected_region.name not in ['Dig Game Area'] \ and exit.access_rule(state): if exit.connected_region == self.parent_region: found = True explored_regions[self.parent_region] = path + [exit] - else: + elif not ignore_underworld or region.type == exit.connected_region.type or exit.connected_region.type not in [RegionType.Cave, RegionType.Dungeon]: explore_region(exit.connected_region, path + [exit]) found = False @@ -1635,6 +1635,12 @@ class Entrance(object): explore_region(start_region.entrances[0].parent_region) if found: self.temp_path = explored_regions[self.parent_region] + elif allow_save_quit: + world = self.parent_region.world if self.parent_region else None + exit = world.get_entrance('Links House S&Q', self.player) + explore_region(exit.connected_region, [exit]) + if found: + self.temp_path = explored_regions[self.parent_region] #TODO: Implement residual mirror portal placing for the previous leg, to be used for the final destination diff --git a/Rules.py b/Rules.py index 03d77ca7..fd4775db 100644 --- a/Rules.py +++ b/Rules.py @@ -191,7 +191,7 @@ def global_rules(world, player): set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Detonate Big Bomb', player)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) - set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player) and state.can_reach('Blacksmiths Hut', 'Region', player)) # Can't S&Q with smith + set_rule(world.get_location('Missing Smith', player), lambda state: state.has('Get Frog', player)) set_rule(world.get_location('Blacksmith', player), lambda state: state.has('Return Smith', player)) set_rule(world.get_location('Magic Bat', player), lambda state: state.has('Magic Powder', player)) set_rule(world.get_location('Sick Kid', player), lambda state: state.has_bottle(player)) From 4dd8ff4de1dda560799b63003b104a3eb2213b0e Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Nov 2021 20:08:01 -0500 Subject: [PATCH 34/40] Added Smith/Purple Chest pathing --- Regions.py | 2 +- Rules.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Regions.py b/Regions.py index 79f6aeb5..bb332366 100644 --- a/Regions.py +++ b/Regions.py @@ -111,7 +111,7 @@ def create_regions(world, player): create_lw_region(player, 'Lake Hylia Island', ['Lake Hylia Island'], ['Lake Hylia Island Water Drop']), create_lw_region(player, 'Lake Hylia Water', None, ['Lake Hylia Central Island Pier', 'Lake Hylia Island Pier', 'Lake Hylia West Pier', 'Lake Hylia East Pier', 'Lake Hylia NC', 'Lake Hylia EC', 'Lake Hylia Whirlpool'], Terrain.Water), create_lw_region(player, 'Ice Cave Area', None, ['Ice Rod Cave', 'Good Bee Cave', '20 Rupee Cave', 'Shopping Mall Mirror Spot', 'Ice Cave SE', 'Ice Cave SW']), - create_lw_region(player, 'Desert Pass Area', None, ['Desert Pass Ladder (South)', 'Middle Aged Man', 'Desert Fairy', '50 Rupee Cave', 'Swamp Nook Mirror Spot', 'Desert Pass WS', 'Desert Pass EC', 'Desert Pass Rocks (North)']), + create_lw_region(player, 'Desert Pass Area', ['Middle Aged Man'], ['Desert Pass Ladder (South)', 'Middle Aged Man', 'Desert Fairy', '50 Rupee Cave', 'Swamp Nook Mirror Spot', 'Desert Pass WS', 'Desert Pass EC', 'Desert Pass Rocks (North)']), create_lw_region(player, 'Middle Aged Man', ['Purple Chest'], None), create_lw_region(player, 'Desert Pass Southeast', None, ['Desert Pass Rocks (South)', 'Swamp Nook Southeast Mirror Spot', 'Desert Pass ES']), create_lw_region(player, 'Desert Pass Ledge', None, ['Desert Pass Ladder (North)', 'Desert Pass Ledge Drop', 'Swamp Nook Pegs Mirror Spot', 'Desert Pass WC']), diff --git a/Rules.py b/Rules.py index fd4775db..6aeb447d 100644 --- a/Rules.py +++ b/Rules.py @@ -184,10 +184,10 @@ def global_rules(world, player): set_rule(world.get_location('Sunken Treasure', player), lambda state: state.has('Open Floodgate', player)) set_rule(world.get_location('Dark Blacksmith Ruins', player), lambda state: state.has('Return Smith', player)) - set_rule(world.get_entrance('Middle Aged Man', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest + set_rule(world.get_location('Middle Aged Man', player), lambda state: state.has('Pick Up Purple Chest', player)) # Can S&Q with chest set_rule(world.get_location('Purple Chest', player), lambda state: state.has('Deliver Purple Chest', player)) # Can S&Q with chest set_rule(world.get_location('Big Bomb', player), lambda state: state.has('Crystal 5', player) and state.has('Crystal 6', player)) - set_rule(world.get_entrance('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) + set_rule(world.get_location('Pyramid Crack', player), lambda state: state.has('Pick Up Big Bomb', player)) set_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.has('Detonate Big Bomb', player)) set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) From 03a0efe69fdf4a314cbcad570d6e1ce50ae615db Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Nov 2021 20:26:12 -0500 Subject: [PATCH 35/40] Some corrections to Ledges and OWG connections --- OWEdges.py | 20 ++++++++++---------- OverworldShuffle.py | 3 ++- Regions.py | 4 ++-- Rules.py | 5 ----- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/OWEdges.py b/OWEdges.py index 6a232e24..a0ce750b 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -1405,8 +1405,6 @@ OWExitTypes = { 'Zora Waterfall Water Drop', 'Bonk Rock Ledge Drop', 'Graveyard Ledge Drop', - 'River Bend Water Drop', - 'River Bend East Water Drop', 'Potion Shop Water Drop', 'Potion Shop Northeast Water Drop', 'Zora Approach Bottom Ledge Drop', @@ -1446,13 +1444,9 @@ OWExitTypes = { 'Dam Cliff Ledge Drop', 'Bombos Tablet Drop', 'Cave 45 Ledge Drop', - 'Lake Hylia Water Drop', 'Lake Hylia South Water Drop', - 'Lake Hylia Northeast Water Drop', - 'Lake Hylia Central Water Drop', 'Lake Hylia Island Water Drop', 'Desert Pass Ledge Drop', - 'Octoballoon Water Drop', 'Octoballoon Waterfall Water Drop', 'Dark Death Mountain Drop (West)', 'Dark Death Mountain Drop (East)', @@ -1462,7 +1456,6 @@ OWExitTypes = { 'Bumper Cave Ledge Drop', 'Bumper Cave Entrance Drop', 'Qirn Jump Water Drop', - 'Qirn Jump East Water Drop', 'Dark Witch Water Drop', 'Dark Witch Northeast Water Drop', 'Catfish Approach Bottom Ledge Drop', @@ -1485,6 +1478,7 @@ OWExitTypes = { 'Dark Bonk Rocks Cliff Ledge Drop', 'Bomb Shop Cliff Ledge Drop', 'Hammer Bridge South Cliff Ledge Drop', + 'Ice Lake Moat Bomb Jump', 'Ice Lake Area Cliff Ledge Drop', 'Ice Palace Island FAWT Ledge Drop', 'Hammer Bridge EC Cliff Water Drop', @@ -1501,10 +1495,8 @@ OWExitTypes = { 'Swamp Nook Cliff Ledge Drop', 'Swamp Cliff Ledge Drop', 'Ice Lake Water Drop', - 'Ice Lake Northeast Water Drop', 'Ice Lake Southwest Water Drop', 'Ice Lake Southeast Water Drop', - 'Bomber Corner Water Drop', 'Bomber Corner Waterfall Water Drop' ], 'OWTerrain': ['Lost Woods Bush (West)', @@ -1530,7 +1522,9 @@ OWExitTypes = { 'Graveyard Ladder (Bottom)', 'Graveyard Ladder (Top)', 'Kings Grave Inner Rocks', + 'River Bend Water Drop', 'River Bend West Pier', + 'River Bend East Water Drop', 'River Bend East Pier', 'Potion Shop Rock (South)', 'Potion Shop Rock (North)', @@ -1568,15 +1562,19 @@ OWExitTypes = { 'C Whirlpool Rock (Top)', 'Statues Water Entry', 'Statues Landing', + 'Lake Hylia Central Water Drop', 'Lake Hylia Central Island Pier', 'Lake Hylia Island Pier', + 'Lake Hylia Water Drop', 'Lake Hylia West Pier', + 'Lake Hylia Northeast Water Drop', 'Lake Hylia East Pier', 'Desert Pass Ladder (South)', 'Desert Pass Rocks (North)', 'Desert Pass Rocks (South)', 'Desert Pass Ladder (North)', 'Middle Aged Man', + 'Octoballoon Water Drop', 'Octoballoon Pier', 'Skull Woods Bush Rock (East)', 'Skull Woods Bush Rock (West)', @@ -1593,6 +1591,7 @@ OWExitTypes = { 'Skull Woods Pass Rock (Bottom)', 'Dark Graveyard Bush (South)', 'Dark Graveyard Bush (North)', + 'Qirn Jump East Water Drop', 'Qirn Jump Pier', 'Dark Witch Rock (South)', 'Dark Witch Rock (North)', @@ -1621,11 +1620,12 @@ OWExitTypes = { 'Dark C Whirlpool Rock (Top)', 'Hype Cave Water Entry', 'Hype Cave Landing', + 'Ice Lake Northeast Water Drop', 'Ice Lake Northeast Pier', 'Ice Lake Moat Water Entry', - 'Ice Lake Northeast Pier Bomb Jump', 'Ice Palace Approach', 'Ice Palace Leave', + 'Bomber Corner Water Drop', 'Bomber Corner Pier' ], 'Portal': ['West Death Mountain Teleporter', diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 4ec1ff10..be277b1a 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -1025,7 +1025,8 @@ mandatory_connections = [# Intra-tile OW Connections ('Dark Bonk Rocks Cliff Ledge Drop', 'Dark Bonk Rocks Area'), ('Hammer Bridge South Cliff Ledge Drop', 'Hammer Bridge South Area'), ('Ice Lake Area Cliff Ledge Drop', 'Ice Lake Area'), - ('Ice Lake Northeast Pier Bomb Jump', 'Ice Lake Northeast Bank'), + ('Ice Lake Northeast Pier Hop', 'Ice Lake Northeast Bank'), + ('Ice Lake Moat Bomb Jump', 'Ice Lake Moat'), ('Dark C Whirlpool Cliff Ledge Drop', 'Dark C Whirlpool Area'), ('Dark C Whirlpool Outer Cliff Ledge Drop', 'Dark C Whirlpool Outer Area'), ('Hype Cliff Ledge Drop', 'Hype Cave Area'), diff --git a/Regions.py b/Regions.py index bb332366..a5d3309d 100644 --- a/Regions.py +++ b/Regions.py @@ -208,8 +208,8 @@ def create_regions(world, player): create_dw_region(player, 'Ice Lake Northeast Bank', None, ['Ice Lake Northeast Water Drop', 'Lake Hylia Northeast Mirror Spot', 'Ice Lake NE']), create_dw_region(player, 'Ice Lake Ledge (West)', None, ['Ice Lake Southwest Water Drop', 'South Shore Mirror Spot', 'Ice Lake WS']), create_dw_region(player, 'Ice Lake Ledge (East)', None, ['Ice Lake Southeast Water Drop', 'South Shore East Mirror Spot', 'Ice Lake ES']), - create_dw_region(player, 'Ice Lake Water', None, ['Ice Lake Northeast Pier', 'Lake Hylia Island Mirror Spot', 'Ice Lake NC', 'Ice Lake EC'], Terrain.Water), - create_dw_region(player, 'Ice Lake Moat', None, ['Ice Lake Moat Water Entry', 'Ice Lake Northeast Pier Bomb Jump', 'Ice Palace Approach', 'Lake Hylia Water Mirror Spot']), + create_dw_region(player, 'Ice Lake Water', None, ['Ice Lake Northeast Pier', 'Ice Lake Moat Bomb Jump', 'Lake Hylia Island Mirror Spot', 'Ice Lake NC', 'Ice Lake EC'], Terrain.Water), + create_dw_region(player, 'Ice Lake Moat', None, ['Ice Lake Moat Water Entry', 'Ice Lake Northeast Pier Hop', 'Ice Palace Approach', 'Lake Hylia Water Mirror Spot']), create_dw_region(player, 'Ice Palace Area', None, ['Ice Palace Leave', 'Ice Palace', 'Ice Palace Teleporter', 'Lake Hylia Central Island Mirror Spot']), create_dw_region(player, 'Shopping Mall Area', None, ['Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Spike Cave', 'Ice Cave Mirror Spot', 'Shopping Mall SW', 'Shopping Mall SE']), create_dw_region(player, 'Swamp Nook Area', None, ['Desert Pass Ledge Mirror Spot', 'Desert Pass Mirror Spot', 'Swamp Nook EC', 'Swamp Nook ES']), diff --git a/Rules.py b/Rules.py index 6aeb447d..3c07d8ca 100644 --- a/Rules.py +++ b/Rules.py @@ -58,7 +58,6 @@ def set_rules(world, player): elif world.goal[player] == 'triforcehunt': add_rule(world.get_location('Murahdahla', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) - # if swamp and dam have not been moved we require mirror for swamp palace if not world.swamp_patch_required[player]: add_rule(world.get_entrance('Swamp Lobby Moat', player), lambda state: state.has_Mirror(player)) @@ -1640,10 +1639,6 @@ def find_rules_for_zelda_delivery(world, player): raise Exception('No path to Sanctuary found') - - - - def set_bunny_rules(world, player, inverted): # regions for the exits of multi-entrace caves/drops that bunny cannot pass From 5bffd0c7e1339dfd9b11c034b18743b11a3b7f5c Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Nov 2021 20:52:43 -0500 Subject: [PATCH 36/40] Some corrections to Ledges and OWG connections --- OWEdges.py | 1 + 1 file changed, 1 insertion(+) diff --git a/OWEdges.py b/OWEdges.py index a0ce750b..14849137 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -1478,6 +1478,7 @@ OWExitTypes = { 'Dark Bonk Rocks Cliff Ledge Drop', 'Bomb Shop Cliff Ledge Drop', 'Hammer Bridge South Cliff Ledge Drop', + 'Ice Lake Northeast Pier Hop', 'Ice Lake Moat Bomb Jump', 'Ice Lake Area Cliff Ledge Drop', 'Ice Palace Island FAWT Ledge Drop', From a4c1fd5049451115537a55ec248d5be467f7d0d0 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 6 Nov 2021 04:35:14 -0500 Subject: [PATCH 37/40] Minor logic fix to minor glitch rule --- Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 3c07d8ca..688e63da 100644 --- a/Rules.py +++ b/Rules.py @@ -1354,7 +1354,7 @@ def no_glitches_rules(world, player): def fake_flipper_rules(world, player): - set_rule(world.get_entrance('Waterfall of Wishing Cave Entry', player), lambda state: state.has('Flippers', player) or (state.has_Pearl(player) and state.can_reach('Lake Hylia Water', player))) + set_rule(world.get_entrance('Waterfall of Wishing Cave Entry', player), lambda state: True) # warning, assumes FF possible on other end of whirlpool or local ancilla splash delete set_rule(world.get_entrance('River Bend Water Drop', player), lambda state: True) set_rule(world.get_entrance('River Bend East Water Drop', player), lambda state: True) set_rule(world.get_entrance('Potion Shop Water Drop', player), lambda state: True) From 46abc05adab8bbc6424fcccd7f01ae4ab2c5f516 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 6 Nov 2021 04:42:35 -0500 Subject: [PATCH 38/40] Minor spoiler log formatting --- BaseClasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BaseClasses.py b/BaseClasses.py index 95f35e80..9c5f9e9c 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2907,7 +2907,7 @@ class Spoiler(object): outfile.write('\n\nBottle Refills:\n\n') for fairy, bottle in self.bottles.items(): - outfile.write(f'\n{fairy}: {bottle}') + outfile.write(f'{fairy}: {bottle}\n') if self.overworlds: # overworlds: overworld transitions; From 53106c9b1efbcc546aa4142c3aa8598cb32df992 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 6 Nov 2021 04:45:02 -0500 Subject: [PATCH 39/40] Version bump 0.2.2.0 --- CHANGELOG.md | 5 +++++ OverworldShuffle.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b71abfd3..62d13649 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +### 0.2.2.0 +- Delivering Big Red Bomb is now in logic +- Smith/Purple Chest have proper dynamic pathing to fix logical issues +- Fixed issue with bomb walls in OW not requiring moon pearl in DW + ### 0.2.1.3 - New fake flipper handling to allow S+Q rather than insta-kill - Fixed whirlpools in Crossed OW diff --git a/OverworldShuffle.py b/OverworldShuffle.py index be277b1a..cad95825 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -3,7 +3,7 @@ from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSl from Regions import mark_dark_world_regions, mark_light_world_regions from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel -__version__ = '0.2.1.3-u' +__version__ = '0.2.2.0-u' def link_overworld(world, player): # setup mandatory connections From 1bbbd30a7175f735a57a2faae52037e8856161d4 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 6 Nov 2021 04:51:50 -0500 Subject: [PATCH 40/40] Readme update --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index da4f5dad..5eb15aea 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,11 @@ This is a very new mode of LTTPR so the tools and info is very limited. - There is an [OW OWG Reference Sheet](https://zelda.codemann8.com/images/shared/ow-owg-reference-sheet.png) that shows all the in-logic places where boots/mirror clips and fake flippers are expected from the player. # Known Issues -(Updated 2021-08-26) +(Updated 2021-11-06) ### If you want to playtest this, know these things: -- Big Red Bomb may require bomb duping as ledge drops may be in the way of your path to the Pyramid Fairy crack -- If you fake flipper, beware of transitioning south. You could end up at the top of the waterfall in the southeast of either world. If you mistakenly drop down, it is important to NOT make any other movements and S+Q immediately when the game allows you to (might take several seconds, the game has to scroll back to the original point of water entry) or there will be a hardlock. Falling from the waterfall is avoidable but it is super easy to do as it is super close to the transition. -- In Crossed OW, there are some interesting bunny swimming situations that can occur, these are meant to be out-of-logic but beware of logic bugs around this area. But also, hardlocks can occur; if you take damage, be sure to S+Q immediately before moving in any direction, or you may get an infinite screen wrap glitch. +- If you fake flipper, beware of transitioning south. You could end up at the top of the waterfall in the southeast of either world. If you mistakenly drop down, it is important to know that altho the game may appear as frozen for a bit of time, the game is simply scrolling Link back to the original point of water entry. Upon "landing", you'll be able to S+Q properly. Falling from the waterfall is avoidable but it is super easy to do as it is super close to the transition. +- In Crossed OW, there are some interesting bunny swimming situations that can occur, these ARE in logic currently, just be careful and avoid taking a hit from an enemy. ### Known bugs: - Screens that loop on itself and also have free-standing items, the sprites are duplicated and can cause item duplication