From 79f35582e8a0a6cf8466eebcdf830afa6a50f75e Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 20 Jul 2022 21:57:06 -0500 Subject: [PATCH 01/29] Adding Zelda Delivered rule to Agahnim 1 rules if Standard --- BaseClasses.py | 11 +++++++---- Rules.py | 14 +++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 5073d6cd..2a214716 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1110,7 +1110,7 @@ class CollectionState(object): for region in tree_pulls: if can_reach_non_bunny(region): return True - if not self.has('Beat Agahnim 1', player): + if not self.has_beaten_aga(player): for region in pre_aga_tree_pulls: if can_reach_non_bunny(region): return True @@ -1125,7 +1125,7 @@ class CollectionState(object): for region in bush_crabs: if can_reach_non_bunny(region): return True - if not self.has('Beat Agahnim 1', player): + if not self.has_beaten_aga(player): for region in pre_aga_bush_crabs: if can_reach_non_bunny(region): return True @@ -1202,7 +1202,7 @@ class CollectionState(object): for region in tree_pulls: if can_reach_non_bunny(region): return True - if not self.has('Beat Agahnim 1', player): + if not self.has_beaten_aga(player): for region in pre_aga_tree_pulls: if can_reach_non_bunny(region): return True @@ -1217,7 +1217,7 @@ class CollectionState(object): for region in bush_crabs: if can_reach_non_bunny(region): return True - if not self.has('Beat Agahnim 1', player): + if not self.has_beaten_aga(player): for region in pre_aga_bush_crabs: if can_reach_non_bunny(region): return True @@ -1343,6 +1343,9 @@ class CollectionState(object): self.is_not_bunny(cave, player) ) + def has_beaten_aga(self, player): + return self.has_beaten_aga(player) and (self.world.mode[player] != 'standard' or self.has('Zelda Delivered', player)) + def has_sword(self, player): return self.has('Fighter Sword', player) or self.has('Master Sword', player) or self.has('Tempered Sword', player) or self.has('Golden Sword', player) diff --git a/Rules.py b/Rules.py index 35572ec5..933951f6 100644 --- a/Rules.py +++ b/Rules.py @@ -54,7 +54,7 @@ def set_rules(world, player): if world.goal[player] == 'dungeons': # require all dungeons to beat ganon - add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player) and state.has('Beat Agahnim 1', player) and state.has('Beat Agahnim 2', player) and state.has_crystals(7, player)) + add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player) and state.has_beaten_aga(player) and state.has('Beat Agahnim 2', player) and state.has_crystals(7, player)) elif world.goal[player] == 'ganon': # require aga2 to beat ganon add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player)) @@ -807,7 +807,7 @@ def pot_rules(world, player): def default_rules(world, player): - set_rule(world.get_entrance('Other World S&Q', player), lambda state: state.has_Mirror(player) and state.has('Beat Agahnim 1', player)) + set_rule(world.get_entrance('Other World S&Q', player), lambda state: state.has_Mirror(player) and state.has_beaten_aga(player)) # Underworld Logic set_rule(world.get_entrance('Old Man Cave Exit (West)', player), lambda state: False) # drop cannot be climbed up @@ -950,7 +950,7 @@ def ow_rules(world, player): if world.is_atgt_swapped(player): set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) else: - set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle + set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player) or state.has_beaten_aga(player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle set_rule(world.get_entrance('GT Entry Approach', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) set_rule(world.get_entrance('GT Entry Leave', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player) or state.world.shuffle[player] in ('restricted', 'full', 'lite', 'lean', 'crossed', 'insanity')) @@ -1117,8 +1117,8 @@ def ow_rules(world, player): set_rule(world.get_entrance('HC East Entry Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('HC Courtyard Left Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('HC Area South Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player)) - set_rule(world.get_entrance('Top of Pyramid (Inner)', player), lambda state: state.has('Beat Agahnim 1', player)) + set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has_beaten_aga(player)) + set_rule(world.get_entrance('Top of Pyramid (Inner)', player), lambda state: state.has_beaten_aga(player)) else: set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: world.is_pyramid_open(player) or state.has('Beat Agahnim 2', player)) set_rule(world.get_entrance('Pyramid Hole', player), lambda state: False) @@ -1130,7 +1130,7 @@ def ow_rules(world, player): set_rule(world.get_entrance('Pyramid Uncle Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Pyramid From Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Pyramid Entry Mirror Spot', player), lambda state: state.has_Mirror(player)) - set_rule(world.get_entrance('Post Aga Inverted Teleporter', player), lambda state: state.has('Beat Agahnim 1', player)) + set_rule(world.get_entrance('Post Aga Inverted Teleporter', player), lambda state: state.has_beaten_aga(player)) if not world.is_tile_swapped(0x1d, player): set_rule(world.get_entrance('Wooden Bridge Mirror Spot', player), lambda state: state.has_Mirror(player)) @@ -1620,7 +1620,7 @@ def swordless_rules(world, player): set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has('Hammer', player)) # need to damage ganon to get tiles to drop if not world.is_atgt_swapped(player): - set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has('Hammer', player) or state.has('Beat Agahnim 1', player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle + set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has('Hammer', player) or state.has_beaten_aga(player)) # barrier gets removed after killing agahnim, relevant for entrance shuffle set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has_misery_mire_medallion(player)) # sword not required to use medallion for opening in swordless (!) set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has_turtle_rock_medallion(player) and state.can_reach('Turtle Rock Ledge', 'Region', player)) # sword not required to use medallion for opening in swordless (!) From fb02ae0159cf81f00206a4497ad62aa643bf2c31 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 21 Jul 2022 10:46:56 -0500 Subject: [PATCH 02/29] Adding Zelda Delivered rule to Agahnim 1 rules if Standard --- BaseClasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BaseClasses.py b/BaseClasses.py index 2a214716..5bd55485 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1344,7 +1344,7 @@ class CollectionState(object): ) def has_beaten_aga(self, player): - return self.has_beaten_aga(player) and (self.world.mode[player] != 'standard' or self.has('Zelda Delivered', player)) + return self.has('Beat Agahnim 1', player) and (self.world.mode[player] != 'standard' or self.has('Zelda Delivered', player)) def has_sword(self, player): return self.has('Fighter Sword', player) or self.has('Master Sword', player) or self.has('Tempered Sword', player) or self.has('Golden Sword', player) From ce9cb8de2647ab2a6de66b499f82d0edf9d552de Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 22 Jul 2022 10:55:35 -0500 Subject: [PATCH 03/29] 619 --- Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 933951f6..c83f1733 100644 --- a/Rules.py +++ b/Rules.py @@ -824,7 +824,7 @@ def default_rules(world, 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 - set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has('Beat Agahnim 1', player)) + set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has_beaten_aga(player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Sanctuary Grave', player), lambda state: state.can_lift_rocks(player)) set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player)) From 360a61a65c3e59a4e28e278a10ec43f0a6c1524d Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 22 Jul 2022 10:57:28 -0500 Subject: [PATCH 04/29] Fixed issue with pre-opened pyramid when it shouldn't be --- Rom.py | 2 +- Rules.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index add74a53..b614e730 100644 --- a/Rom.py +++ b/Rom.py @@ -1390,7 +1390,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest - if world.open_pyramid[player]: + if world.is_pyramid_open(player): rom.initial_sram.pre_open_pyramid_hole() if world.crystals_needed_for_gt[player] == 0: rom.initial_sram.pre_open_ganons_tower() diff --git a/Rules.py b/Rules.py index c83f1733..45aa6ba6 100644 --- a/Rules.py +++ b/Rules.py @@ -1109,7 +1109,7 @@ def ow_rules(world, player): if not world.is_tile_swapped(0x1b, player): set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: False) set_rule(world.get_entrance('Inverted Pyramid Entrance', player), lambda state: False) - set_rule(world.get_entrance('Pyramid Hole', player), lambda state: world.open_pyramid[player] or state.has('Beat Agahnim 2', player)) + set_rule(world.get_entrance('Pyramid Hole', player), lambda state: world.is_pyramid_open(player) or state.has('Beat Agahnim 2', player)) set_rule(world.get_entrance('HC Area Mirror Spot', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('HC Ledge Mirror Spot', player), lambda state: state.has_Mirror(player)) From a5729b51a242d829512bb5f15e144adcb39ffa41 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 12:42:08 -0500 Subject: [PATCH 05/29] Adding new option for Bonk Drop Shuffle --- BaseClasses.py | 2 +- CLI.py | 3 ++- Main.py | 2 ++ Mystery.py | 1 + resources/app/cli/args.json | 4 ++++ resources/app/cli/lang/en.json | 3 +++ resources/app/gui/lang/en.json | 2 ++ resources/app/gui/randomize/overworld/widgets.json | 6 ++++++ source/classes/constants.py | 1 + source/gui/randomize/overworld.py | 8 ++++++-- 10 files changed, 28 insertions(+), 4 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 5bd55485..01825043 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -54,7 +54,7 @@ class World(object): self._entrance_cache = {} self._location_cache = {} self.required_locations = [] - self.shuffle_bonk_prizes = False + self.shuffle_bonk_drops = {} self.light_world_light_cone = False self.dark_world_light_cone = False self.clock_mode = 'none' diff --git a/CLI.py b/CLI.py index 8ba224bd..4e7ad021 100644 --- a/CLI.py +++ b/CLI.py @@ -109,7 +109,7 @@ def parse_cli(argv, no_defaults=False): 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle', 'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', - 'msu_resume', 'collection_rate', 'colorizepots']: + 'msu_resume', 'collection_rate', 'colorizepots', 'bonk_drops']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: setattr(ret, name, {1: value}) @@ -159,6 +159,7 @@ def parse_settings(): "ow_mixed": False, "ow_whirlpool": False, "ow_fluteshuffle": "vanilla", + "bonk_drops": False, "shuffle": "vanilla", "shufflelinks": False, "overworld_map": "default", diff --git a/Main.py b/Main.py index ac5843e5..2ac286bf 100644 --- a/Main.py +++ b/Main.py @@ -91,6 +91,7 @@ def main(args, seed=None, fish=None): world.owKeepSimilar = args.ow_keepsimilar.copy() world.owWhirlpoolShuffle = args.ow_whirlpool.copy() world.owFluteShuffle = args.ow_fluteshuffle.copy() + world.shuffle_bonk_drops = args.bonk_drops.copy() world.open_pyramid = args.openpyramid.copy() world.boss_shuffle = args.shufflebosses.copy() world.enemy_shuffle = args.shuffleenemies.copy() @@ -438,6 +439,7 @@ def copy_world(world, partial_copy=False): ret.owKeepSimilar = world.owKeepSimilar.copy() ret.owWhirlpoolShuffle = world.owWhirlpoolShuffle.copy() ret.owFluteShuffle = world.owFluteShuffle.copy() + ret.shuffle_bonk_drops = world.shuffle_bonk_drops.copy() ret.open_pyramid = world.open_pyramid.copy() ret.boss_shuffle = world.boss_shuffle.copy() ret.enemy_shuffle = world.enemy_shuffle.copy() diff --git a/Mystery.py b/Mystery.py index 07955bff..60a3f064 100644 --- a/Mystery.py +++ b/Mystery.py @@ -174,6 +174,7 @@ def roll_settings(weights): ret.ow_whirlpool = get_choice('whirlpool_shuffle') == 'on' overworld_flute = get_choice('flute_shuffle') ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla' + ret.shuffle_bonk_drops = get_choice('bonk_drops') == 'on' entrance_shuffle = get_choice('entrance_shuffle') ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla' overworld_map = get_choice('overworld_map') diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 2c169dcf..ebeedf53 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -167,6 +167,10 @@ "action": "store_true", "type": "bool" }, + "bonk_drops": { + "action": "store_true", + "type": "bool" + }, "ow_fluteshuffle": { "choices": [ "vanilla", diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index 802acf1e..5d753a66 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -234,6 +234,9 @@ "ow_whirlpool": [ "Whirlpools will be shuffled and paired together." ], + "bonk_drops": [ + "Bonk drops from trees, rocks, and statues are shuffled with the item pool." + ], "ow_fluteshuffle": [ "This randomizes the flute spot destinations.", "Vanilla: All flute spots remain unchanged.", diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index b325429c..b25f4233 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -145,6 +145,8 @@ "randomizer.overworld.whirlpool": "Whirlpool Shuffle", + "randomizer.overworld.bonk_drops": "Bonk Drops", + "randomizer.overworld.overworldflute": "Flute Shuffle", "randomizer.overworld.overworldflute.vanilla": "Vanilla", "randomizer.overworld.overworldflute.balanced": "Balanced", diff --git a/resources/app/gui/randomize/overworld/widgets.json b/resources/app/gui/randomize/overworld/widgets.json index 43dc9394..9595ea8e 100644 --- a/resources/app/gui/randomize/overworld/widgets.json +++ b/resources/app/gui/randomize/overworld/widgets.json @@ -1,4 +1,10 @@ { + "topOverworldFrame": { + "bonk_drops": { + "type": "checkbox", + "default": false + } + }, "leftOverworldFrame": { "overworldshuffle": { "type": "selectbox", diff --git a/source/classes/constants.py b/source/classes/constants.py index c120734b..1b6a6aa5 100644 --- a/source/classes/constants.py +++ b/source/classes/constants.py @@ -81,6 +81,7 @@ SETTINGSTOPROCESS = { "keepsimilar": "ow_keepsimilar", "mixed": "ow_mixed", "whirlpool": "ow_whirlpool", + "bonk_drops": "bonk_drops", "overworldflute": "ow_fluteshuffle" }, "entrance": { diff --git a/source/gui/randomize/overworld.py b/source/gui/randomize/overworld.py index 3cc3eb36..d3796af6 100644 --- a/source/gui/randomize/overworld.py +++ b/source/gui/randomize/overworld.py @@ -15,12 +15,16 @@ def overworld_page(parent): # Load Overworld Shuffle option widgets as defined by JSON file # Defns include frame name, widget type, widget options, widget placement attributes - # These get split left & right + self.frames["topOverworldFrame"] = Frame(self) self.frames["leftOverworldFrame"] = Frame(self) self.frames["rightOverworldFrame"] = Frame(self) + self.frames["topOverworldFrame"].pack(side=TOP, anchor=NW) self.frames["leftOverworldFrame"].pack(side=LEFT, anchor=NW, fill=Y) self.frames["rightOverworldFrame"].pack(anchor=NW, fill=Y) + + shuffleLabel = Label(self.frames["topOverworldFrame"], text="Shuffle: ") + shuffleLabel.pack(side=LEFT) with open(os.path.join("resources","app","gui","randomize","overworld","widgets.json")) as overworldWidgets: myDict = json.load(overworldWidgets) @@ -33,7 +37,7 @@ def overworld_page(parent): packAttrs = {"side":LEFT, "pady":(18,0)} elif key == "overworldflute": packAttrs["pady"] = (20,0) - elif key in ["whirlpool", "mixed"]: + elif key in ["mixed", "whirlpool"]: packAttrs = {"anchor":W, "padx":(79,0)} self.widgets[key].pack(packAttrs) From 97455dc1406727c825c6454282a8b6ef2d5ec7de Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 12:50:37 -0500 Subject: [PATCH 06/29] Implemented Bonk Drop Shuffle --- BaseClasses.py | 8 +- Fill.py | 29 +++--- ItemList.py | 33 ++++++- Items.py | 8 +- Regions.py | 49 +++++++++- Rom.py | 65 +++++++++---- Rules.py | 14 +++ Tables.py | 32 ++++--- asm/owrando.asm | 199 +++++++++++++++++++++++++++++++++++++++- data/base2current.bps | Bin 99252 -> 103920 bytes mystery_example.yml | 3 + source/item/FillUtil.py | 4 +- 12 files changed, 389 insertions(+), 55 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 01825043..4a484834 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1080,6 +1080,9 @@ class CollectionState(object): return True return False + def can_collect_bonkdrops(self, player): + return self.has_Boots(player) or (self.has_sword(player) and self.has('Quake', player)) + def can_farm_rupees(self, player): tree_pulls = ['Lost Woods East Area', 'Snitch Lady (East)', @@ -1192,7 +1195,7 @@ class CollectionState(object): if can_reach_non_bunny(region): return True - if self.has_Boots(player): + if not self.world.shuffle_bonk_drops[player] and self.can_collect_bonkdrops(player): for region in bonk_bombs: if can_reach_non_bunny(region): return True @@ -2696,6 +2699,7 @@ class LocationType(FastEnum): Shop = 3 Pot = 4 Drop = 5 + Bonk = 6 class Item(object): @@ -2911,6 +2915,7 @@ class Spoiler(object): 'ow_mixed': self.world.owMixed, 'ow_whirlpool': self.world.owWhirlpoolShuffle, 'ow_fluteshuffle': self.world.owFluteShuffle, + 'bonk_drops': self.world.shuffle_bonk_drops, 'shuffle': self.world.shuffle, 'shuffleganon': self.world.shuffle_ganon, 'shufflelinks': self.world.shufflelinks, @@ -3123,6 +3128,7 @@ class Spoiler(object): outfile.write('Swapped OW (Mixed):'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_mixed'][player])) outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_whirlpool'][player])) outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player]) + outfile.write('Bonk Drops:'.ljust(line_width) + '%s\n' % yn(self.metadata['bonk_drops'][player])) outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player]) if self.metadata['shuffle'][player] != 'vanilla': outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffleganon'][player])) diff --git a/Fill.py b/Fill.py index 9bf7f98f..fe9cbcf9 100644 --- a/Fill.py +++ b/Fill.py @@ -355,18 +355,23 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None # handle pot shuffle pots_used = False pot_item_pool = collections.defaultdict(list) - for item in world.itempool: - if item.name in ['Chicken', 'Big Magic']: # can only fill these in that players world - pot_item_pool[item.player].append(item) - for player, pot_pool in pot_item_pool.items(): - if pot_pool: - for pot_item in pot_pool: - world.itempool.remove(pot_item) - pot_locations = [location for location in fill_locations - if location.type == LocationType.Pot and location.player == player] - pot_locations = filter_pot_locations(pot_locations, world) - fast_fill_helper(world, pot_pool, pot_locations) - pots_used = True + + # guarantee one big magic in a bonk location + for player in range(1, world.players + 1): + if world.shuffle_bonk_drops[player]: + for item in world.itempool: + if item.name in ['Big Magic']: + pot_item_pool[player].append(item) + break + + for player, magic_pool in pot_item_pool.items(): + world.itempool.remove(magic_pool[0]) + pot_locations = [location for location in fill_locations + if location.type == LocationType.Bonk and location.player == player] + pot_locations = filter_pot_locations(pot_locations, world) + fast_fill_helper(world, magic_pool, pot_locations) + pots_used = True + if pots_used: fill_locations = world.get_unfilled_locations() random.shuffle(fill_locations) diff --git a/ItemList.py b/ItemList.py index 18472fb0..7350ff9a 100644 --- a/ItemList.py +++ b/ItemList.py @@ -3,11 +3,12 @@ import logging import math import RaceRandom as random -from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem +from BaseClasses import LocationType, Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem from EntranceShuffle import connect_entrance from Regions import shop_to_location_table, retro_shops, shop_table_by_location, valid_pot_location from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool from PotShuffle import vanilla_pots +from Tables import bonk_prize_lookup from Items import ItemFactory from source.item.FillUtil import trash_items, pot_items @@ -411,6 +412,10 @@ def generate_itempool(world, player): if world.pottery[player] not in ['none', 'keys']: add_pot_contents(world, player) + if world.shuffle_bonk_drops[player]: + create_dynamic_bonkdrop_locations(world, player) + add_bonkdrop_contents(world, player) + take_any_locations = [ 'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut', @@ -500,6 +505,21 @@ def create_dynamic_shop_locations(world, player): loc.locked = True +def create_dynamic_bonkdrop_locations(world, player): + from Regions import bonk_prize_table + for bonk_location, (_, _, _, region_name, hint_text) in bonk_prize_table.items(): + region = world.get_region(region_name, player) + loc = Location(player, bonk_location, 0, region, hint_text) + loc.type = LocationType.Bonk + loc.parent_region = region + loc.address = 0x2abb00 + (bonk_prize_table[loc.name][0] * 6) + 3 + + region.locations.append(loc) + world.dynamic_locations.append(loc) + + world.clear_location_cache() + + def fill_prizes(world, attempts=15): all_state = world.get_all_state(keys=True) for player in range(1, world.players + 1): @@ -779,6 +799,17 @@ def add_pot_contents(world, player): world.itempool.append(ItemFactory(item, player)) +def add_bonkdrop_contents(world, player): + from Items import item_table + for item_name, (_, count, alt_item) in bonk_prize_lookup.items(): + if item_name not in item_table: + item_name = alt_item + while (count > 0): + item = ItemFactory(item_name, player) + world.itempool.append(item) + count -= 1 + + def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic, flute_activated): pool = [] placed_items = {} diff --git a/Items.py b/Items.py index ea81c136..10d93159 100644 --- a/Items.py +++ b/Items.py @@ -81,10 +81,10 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), 'Arrow Upgrade (+5)': (False, False, None, 0x53, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), 'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'), - 'Arrows (5)': (False, False, None, 0x5A, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'), + 'Arrows (5)': (False, False, None, 0xB5, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'), 'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'), - 'Big Magic': (False, False, None, 0x5A, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'), - 'Chicken': (False, False, None, 0x5A, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'), + 'Big Magic': (False, False, None, 0xB4, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'), + 'Chicken': (False, False, None, 0xB3, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'), 'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'), 'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'), 'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'Increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), @@ -177,6 +177,8 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche 'Blue Potion': (False, False, None, 0x30, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'), 'Bee': (False, False, None, 0x0E, 10, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bee'), 'Small Heart': (False, False, None, 0x42, 10, 'Just a little\npiece of love!', 'and the heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart'), + 'Apples': (False, False, None, 0xB1, 30, 'Just a few pieces of fruit!', 'and the juicy fruit', 'the fruity kid', 'the fruit stand', 'expired fruit', 'bottle boy has fruit again', 'an apple hoard'), + 'Fairy': (False, False, None, 0xB2, 50, 'Just a pixie!', 'and the pixie', 'the pixie kid', 'pixie for sale', 'pixie fungus', 'bottle boy has pixie again', 'a pixie'), 'Beat Agahnim 1': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Beat Agahnim 2': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Get Frog': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), diff --git a/Regions.py b/Regions.py index 18c14c9a..af3c13ef 100644 --- a/Regions.py +++ b/Regions.py @@ -1266,7 +1266,54 @@ def pot_address(pot_index, super_tile): return 0x7f6018 + super_tile * 2 + (pot_index << 24) -# (type, room_id, shopkeeper, custom, locked, [items]) +# bonk location: record id, aga required, default item, region, hint text +bonk_prize_table = { + 'Lost Woods Hideout Tree': (0x00, False, '', 'Lost Woods East Area', 'in a tree'), + 'Death Mountain Bonk Rocks': (0x01, False, '', 'East Death Mountain (Top East)', 'encased in stone'), + 'Mountain Entry Pull Tree': (0x02, False, '', 'Mountain Entry Area', 'in a tree'), + 'Mountain Entry Southeast Tree': (0x03, False, '', 'Mountain Entry Area', 'in a tree'), + 'Lost Woods Pass West Tree': (0x04, False, '', 'Lost Woods Pass West Area', 'in a tree'), + 'Kakariko Portal Tree': (0x05, False, '', 'Lost Woods Pass East Top Area', 'in a tree'), + 'Fortune Bonk Rocks': (0x06, False, '', 'Kakariko Fortune Area', 'in a tree'), + 'Kakariko Pond Tree': (0x07, True, '', 'Kakariko Pond Area', 'in a tree'), + 'Bonk Rocks Tree': (0x08, True, '', 'Bonk Rock Ledge', 'in a tree'), + 'Sanctuary Tree': (0x09, False, '', 'Sanctuary Area', 'in a tree'), + 'River Bend West Tree': (0x0a, True, '', 'River Bend Area', 'in a tree'), + 'River Bend East Tree': (0x0b, False, '', 'River Bend East Bank', 'in a tree'), + 'Blinds Hideout Tree': (0x0c, False, '', 'Kakariko Area', 'in a tree'), + 'Kakariko Welcome Tree': (0x0d, False, '', 'Kakariko Area', 'in a tree'), + 'Forgotten Forest Southwest Tree': (0x0e, False, '', 'Forgotten Forest Area', 'in a tree'), + 'Forgotten Forest Central Tree': (0x0f, False, '', 'Forgotten Forest Area', 'in a tree'), + #'Forgotten Forest Southeast Tree': (0x??, False, '', 'Forgotten Forest Area', 'in a tree'), + 'Hyrule Castle Tree': (0x10, False, '', 'Hyrule Castle Courtyard', 'in a tree'), + 'Wooden Bridge Tree': (0x11, False, '', 'Wooden Bridge Area', 'in a tree'), + 'Eastern Palace Tree': (0x12, True, '', 'Eastern Palace Area', 'in a tree'), + 'Flute Boy South Tree': (0x13, True, '', 'Flute Boy Area', 'in a tree'), + 'Flute Boy East Tree': (0x14, True, '', 'Flute Boy Area', 'in a tree'), + 'Central Bonk Rocks Tree': (0x15, False, '', 'Central Bonk Rocks Area', 'in a tree'), + 'Tree Line Tree 2': (0x16, True, '', 'Tree Line Area', 'in a tree'), + 'Tree Line Tree 4': (0x17, True, '', 'Tree Line Area', 'in a tree'), + 'Flute Boy Approach South Tree': (0x18, False, '', 'Flute Boy Approach Area', 'in a tree'), + 'Flute Boy Approach North Tree': (0x19, False, '', 'Flute Boy Approach Area', 'in a tree'), + 'Dark Lumberjack Tree': (0x1a, False, '', 'Dark Lumberjack Area', 'in a tree'), + 'Dark Fortune Bonk Rocks (Drop 1)': (0x1b, False, '', 'Dark Fortune Area', 'encased in stone'), + 'Dark Fortune Bonk Rocks (Drop 2)': (0x1c, False, '', 'Dark Fortune Area', 'encased in stone'), + 'Dark Graveyard West Bonk Rocks': (0x1d, False, '', 'Dark Graveyard Area', 'encased in stone'), + 'Dark Graveyard North Bonk Rocks': (0x1e, False, '', 'Dark Graveyard North', 'encased in stone'), + 'Dark Graveyard Tomb Bonk Rocks': (0x1f, False, '', 'Dark Graveyard North', 'encased in stone'), + 'Qirn Jump West Tree': (0x20, False, '', 'Qirn Jump Area', 'in a tree'), + 'Qirn Jump East Tree': (0x21, False, '', 'Qirn Jump East Bank', 'in a tree'), + 'Dark Witch Tree': (0x22, False, '', 'Dark Witch Area', 'in a tree'), + 'Pyramid Tree': (0x23, False, '', 'Pyramid Area', 'in a tree'), + 'Palace of Darkness Tree': (0x24, False, '', 'Palace of Darkness Area', 'in a tree'), + 'Dark Tree Line Tree 2': (0x25, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Dark Tree Line Tree 3': (0x26, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Dark Tree Line Tree 4': (0x27, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Hype Cave Statue': (0x28, False, '', 'Hype Cave Area', 'encased in stone') +} + + +# (room_id, type, shopkeeper, custom, locked, [items]) # item = (item, price, max=0, replacement=None, replacement_price=0) _basic_shop_defaults = [('Red Potion', 150), ('Small Heart', 10), ('Bombs (10)', 50)] _dark_world_shop_defaults = [('Red Potion', 150), ('Blue Shield', 50), ('Bombs (10)', 50)] diff --git a/Rom.py b/Rom.py index b614e730..7c43ea9f 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '210e4631353e3d094f01bf91562844a5' +RANDOMIZERBASEHASH = 'f76555dcc8cbd0f185fb37eafa3779c3' class JsonRom(object): @@ -630,6 +630,14 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(sprite_pointer+1, 0) rom.write_byte(sprite_pointer+2, code) continue + elif location.type == LocationType.Bonk: + address = snes_to_pc(location.address) + rom.write_byte(address, handle_native_dungeon(location, itemid)) + if location.item.player != player: + rom.write_byte(address+1, location.item.player) + else: + rom.write_byte(address+1, 0) + continue if location.address is None or (type(location.address) is int and location.address >= 0x400000): continue @@ -771,18 +779,42 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # set world flag world_flag = 0x00 if b >= 0x40 and b < 0x80 else 0x40 - rom.write_byte(0x153A00 + b, world_flag) + rom.write_byte(0x1539B0 + b, world_flag) if b & 0xBF in megatiles: - rom.write_byte(0x153A00 + b + 1, world_flag) - rom.write_byte(0x153A00 + b + 8, world_flag) - rom.write_byte(0x153A00 + b + 9, world_flag) + rom.write_byte(0x1539B0 + b + 1, world_flag) + rom.write_byte(0x1539B0 + b + 8, world_flag) + rom.write_byte(0x1539B0 + b + 9, world_flag) 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) if not edge.specialExit: - rom.write_byte(0x1539e0 + (edge.specialID - 0x80) * 2 if edge.specialEntrance else edge.getAddress() + 0x0e, edge.getTarget()) + rom.write_byte(0x1539A0 + (edge.specialID - 0x80) * 2 if edge.specialEntrance else edge.getAddress() + 0x0e, edge.getTarget()) + # patch bonk prizes + if world.shuffle_bonk_drops: + bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, 0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79, 0xE3, 0xE3, + 0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3, 0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD] + bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A, 0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD, + 0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D, 0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51, + 0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387, 0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7, + 0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3, 0x4D504, 0x4D507, 0x4D55E, 0x4D56A] + + # # legacy bonk prize shuffle, shuffles bonk prizes amongst themselves + # random.shuffle(bonk_prizes) + # for prize, address in zip(bonk_prizes, bonk_addresses): + # rom.write_byte(address, prize) + + owFlags |= 0x200 + + # setting spriteID to D8, a placeholder sprite we use to inform ROM to spawn a dynamic item + #for address in bonk_addresses: + for address in [b for b in bonk_addresses if b != 0x4D0AE]: # temp fix for screen 1A murahdahla sprite replacement + rom.write_byte(address, 0xD8) + # temporary fix for screen 1A + rom.write_byte(snes_to_pc(0x09AE32), 0xD8) + rom.write_byte(snes_to_pc(0x09AE35), 0xD8) + write_int16(rom, 0x150002, owMode) write_int16(rom, 0x150004, owFlags) @@ -875,6 +907,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): valid_locations = [l for l in my_locations if ((l.type == LocationType.Pot and not l.forced_item) or (l.type == LocationType.Drop and not l.forced_item) or (l.type == LocationType.Normal and not l.forced_item) + or (l.type == LocationType.Bonk and not l.forced_item) or (l.type == LocationType.Shop and world.shopsanity[player]))] valid_loc_by_dungeon = valid_dungeon_locations(valid_locations) @@ -1251,18 +1284,6 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # fill enemy prize packs rom.write_bytes(0x37A78, pack_prizes) - # set bonk prizes - bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, 0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79, 0xE3, 0xE3, - 0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3, 0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD] - bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A, 0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD, - 0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D, 0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51, - 0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387, 0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7, - 0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3, 0x4D504, 0x4D507, 0x4D55E, 0x4D56A] - if world.shuffle_bonk_prizes: - random.shuffle(bonk_prizes) - for prize, address in zip(bonk_prizes, bonk_addresses): - rom.write_byte(address, prize) - # Fill in item substitutions table rom.write_bytes(0x184000, [ # original_item, limit, replacement_item, filler @@ -1644,6 +1665,12 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # temporarally we are just nopping out this check we will conver this to a rom fix soon. rom.write_bytes(0x02F539, [0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0, 0x4F]) + # sprite patches + rom.write_byte(snes_to_pc(0x0db7d1), 0x03) # patch apple sprites to not permadeatch like enemies + if world.shuffle_bonk_drops[player]: + # warning, this temporary patch might cause fairies to respawn differently?, limiting this to bonk drop mode only + rom.write_byte(snes_to_pc(0x0db808), 0x03) # patch fairies sprites to not permadeatch like enemies + # allow smith into multi-entrance caves in appropriate shuffles if world.shuffle[player] in ['restricted', 'full', 'lite', 'lean', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'): rom.write_byte(0x18004C, 0x01) @@ -2754,7 +2781,7 @@ def set_inverted_mode(world, player, rom, inverted_buffer): # apply inverted map changes for b in range(0x00, len(inverted_buffer)): - rom.write_byte(0x153B00 + b, inverted_buffer[b]) + rom.write_byte(0x153A70 + b, inverted_buffer[b]) def patch_shuffled_dark_sanc(world, rom, player): dark_sanc = world.get_region('Dark Sanctuary Hint', player) diff --git a/Rules.py b/Rules.py index 45aa6ba6..9619c897 100644 --- a/Rules.py +++ b/Rules.py @@ -823,6 +823,15 @@ def default_rules(world, 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)) + # Bonk Item Access + if world.shuffle_bonk_drops[player]: + if world.get_region('Big Bomb Shop', player).entrances: # just some location that is placed late in the ER algorithm, prevent standard rules from applying when trying to search reachability in the overworld + from Regions import bonk_prize_table + for location_name, (_, aga_required, _, _, _) in bonk_prize_table.items(): + loc = world.get_location(location_name, player) + set_rule(loc, lambda state: (state.can_collect_bonkdrops(player)) and (not aga_required or state.has_beaten_aga(player))) + add_bunny_rule(loc, player) + # Entrance Access set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has_beaten_aga(player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) @@ -1731,6 +1740,11 @@ def standard_rules(world, player): add_rule(world.get_entrance('Hyrule Castle Ledge Drop', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has('Zelda Delivered', player)) + if world.shuffle_bonk_drops[player]: + if world.get_region('Big Bomb Shop', player).entrances: # just some location that is placed late in the ER algorithm, prevent standard rules from applying when trying to search reachability in the overworld + add_rule(world.get_location('Hyrule Castle Tree', player), lambda state: state.has('Zelda Delivered', player)) + add_rule(world.get_location('Central Bonk Rocks Tree', player), lambda state: state.has('Zelda Delivered', player)) + # don't allow bombs to get past here before zelda is rescued set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: (state.can_use_bombs(player) and state.has('Zelda Delivered', player)) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) # or state.has('Cane of Somaria', player)) diff --git a/Tables.py b/Tables.py index 64464b9f..a30f24f0 100644 --- a/Tables.py +++ b/Tables.py @@ -125,17 +125,23 @@ divisor_lookup = { # 0xf8: 0xbac, 0xf9: 0xbba, 0xfa: 0xbc1, 0xfb: 0xbcc, 0xfc: 0xbd7, 0xfd: 0xbd7, 0xfe: 0xbba, 0xff: 0xbe3 # } -prize_lookup = { - 0xd8: 'Small Magic Refill', - 0xd9: 'Rupee (1)', - 0xda: 'Rupees (5)', - 0xdb: 'Rupees (20)', - 0xdc: 'Bomb (1)', - 0xdd: 'Bombs (4)', - 0xde: 'Bombs (8)', - 0xdf: 'Heart', - 0xe0: 'Fairy', - 0xe1: 'Arrows (5)', - 0xe2: 'Arrows (10)', - 0xe3: 'Full Magic Refill' +# item name: (spriteID, pool count, replacement item) +bonk_prize_lookup = { + 'Chicken': (0x0b, 0, None), + 'Bee Trap': (0x79, 6, None), + 'Apples': (0xac, 8, None), + 'Small Heart': (0xd8, 2, None), + 'Rupee (1)': (0xd9, 0, None), + 'Rupees (5)': (0xda, 3, None), # TODO: add in murahdahla tree rupee + 'Rupees (20)': (0xdb, 3, None), + 'Single Bomb': (0xdc, 2, None), + 'Bombs (3)': (None, 0, 'Bombs (4)'), + 'Bombs (4)': (0xdd, 0, 'Bombs (3)'), + 'Bombs (8)': (0xde, 1, 'Bombs (10)'), + 'Bombs (10)': (None, 0, 'Bombs (8)'), + 'Small Magic': (0xdf, 0, None), + 'Big Magic': (0xe0, 1, None), + 'Arrows (5)': (0xe1, 0, None), + 'Arrows (10)': (0xe2, 0, None), + 'Fairy': (0xe3, 15, None) } diff --git a/asm/owrando.asm b/asm/owrando.asm index 2d0c1ebd..7793ce2d 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -143,6 +143,9 @@ jsl.l OWWorldCheck16 : nop org $02b16e ; AND #$3F : ORA 7EF3CA and #$7f : eor #$40 : nop #2 +org $06AD4C +jsl.l OWBonkDrops : nop #4 + ;Code org $aa8800 OWTransitionDirection: @@ -368,6 +371,136 @@ LoadMapDarkOrMixed: dw $0400+$0210 ; bottom right } +; Y = sprite slot index of bonk sprite +OWBonkDrops: +{ + CMP.b #$D8 : BEQ + + RTL + + LDA.l OWFlags+1 : AND.b #$02 : BNE + + JSL.l Sprite_TransmuteToBomb : RTL + + + + ; loop thru rando bonk table to find match + PHB : PHK : PLB + LDA.b $8A + LDX.b #(40*6) ; 40 bonk items, 6 bytes each + - CMP.w OWBonkPrizeData,X : BNE + + INX + LDA.w $0D10,Y : LSR A : LSR A : LSR A : LSR A + EOR.w $0D00,Y : CMP.w OWBonkPrizeData,X : BNE ++ ; X = row + 1 + BRA .found_match + ++ DEX : LDA.b $8A + + CPX.b #$00 : BNE + + PLB : RTL + + DEX : DEX : DEX : DEX : DEX : DEX : BRA - + + .found_match + INX : LDA.w OWBonkPrizeData,X : PHX : PHA ; S = FlagBitmask, X (row + 2) + LDX.b $8A : LDA.l OverworldEventDataWRAM,X : AND 1,S : PHA : BNE + ; S = Collected, FlagBitmask, X (row + 2) + LDA.b #$1B : STA $12F ; JSL Sound_SetSfx3PanLong ; seems that when you bonk, there is a pending bonk sfx, so we clear that out and replace with reveal secret sfx + + + LDA 3,S : TAX : INX : LDA.w OWBonkPrizeData,X + PHA : INX : LDA.w OWBonkPrizeData,X : BEQ + + ; multiworld item + DEX : PLA ; X = row + 3 + JMP .spawn_item + + DEX : PLA ; X = row + 3 + + .determine_type ; A = item id ; S = Collected, FlagBitmask, X (row + 2) + CMP.b #$B0 : BNE + + LDA.b #$79 : JMP .sprite_transform ; transform to bees + + CMP.b #$42 : BNE + + JSL.l Sprite_TransmuteToBomb ; transform a heart to bomb, vanilla behavior + JMP .mark_collected + + CMP.b #$34 : BNE + + LDA.b #$D9 : CLC : JMP .sprite_transform ; transform to single rupee + + CMP.b #$35 : BNE + + LDA.b #$DA : CLC : BRA .sprite_transform ; transform to blue rupee + + CMP.b #$36 : BNE + + LDA.b #$DB : CLC : BRA .sprite_transform ; transform to red rupee + + CMP.b #$27 : BNE + + LDA.b #$DC : CLC : BRA .sprite_transform ; transform to 1 bomb + + CMP.b #$28 : BNE + + LDA.b #$DD : CLC : BRA .sprite_transform ; transform to 4 bombs + + CMP.b #$31 : BNE + + LDA.b #$DE : CLC : BRA .sprite_transform ; transform to 8 bombs + + CMP.b #$45 : BNE + + LDA.b #$DF : CLC : BRA .sprite_transform ; transform to small magic + + CMP.b #$B4 : BNE + + LDA.b #$E0 : CLC : BRA .sprite_transform ; transform to big magic + + CMP.b #$B5 : BNE + + LDA.b #$E1 : CLC : BRA .sprite_transform ; transform to 5 arrows + + CMP.b #$44 : BNE + + LDA.b #$E2 : CLC : BRA .sprite_transform ; transform to 10 arrows + + CMP.b #$B1 : BNE + + LDA.b #$AC : BRA .sprite_transform ; transform to apples + + CMP.b #$B2 : BNE + + LDA.b #$E3 : BRA .sprite_transform ; transform to fairy + + CMP.b #$B3 : BNE .spawn_item + INX : INX : LDA.w OWBonkPrizeData,X ; X = row + 5 + CLC : ADC.b #$08 : PHA + LDA.w $0D00,Y : SEC : SBC.b 1,S : STA.w $0D00,Y + LDA.w $0D20,Y : SBC.b #$00 : STA.w $0D20,Y : PLX + LDA.b #$0B : SEC ; BRA .sprite_transform ; transform to chicken + + .sprite_transform + STA.w $0E20,Y + TYX : JSL.l Sprite_LoadProperties + BEQ + + ; these are sprite properties that make it fall out of the tree to the east + LDA #$30 : STA $0F80,Y ; amount of force (related to speed) + LDA #$10 : STA $0D50,Y ; eastward rate of speed + LDA #$FF : STA $0B58,Y ; expiration timer + + + + .mark_collected ; S = Collected, FlagBitmask, X (row + 2) + PLA : BNE + ; S = FlagBitmask, X (row + 2) + LDX.b $8A : LDA.l OverworldEventDataWRAM,X : ORA 1,S : STA.l OverworldEventDataWRAM,X + + REP #$20 + LDA.l TotalItemCounter : INC : STA.l TotalItemCounter + SEP #$20 + + JMP .return + + ; spawn itemget item + .spawn_item ; A = item id ; Y = tree sprite slot ; S = Collected, FlagBitmask, X (row + 2) + PLX : BEQ + : LDA.b #$00 : STA.w $0DD0,Y : JMP .return ; S = FlagBitmask, X (row + 2) + + LDA 2,S : TAX : INX : INX + LDA.w OWBonkPrizeData,X : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID + DEX + + LDA.b #$01 : STA !REDRAW + + LDA.b #$EB + STA.l $7FFE00 + JSL Sprite_SpawnDynamically+15 ; +15 to skip finding a new slot, use existing sprite + + ; affects the rate the item moves in the Y/X direction + LDA.b #$00 : STA.w $0D40,Y + LDA.b #$0A : STA.w $0D50,Y + + LDA.b #$20 : STA.w $0F80,Y ; amount of force (gives height to the arch) + LDA.b #$FF : STA.w $0B58,Y ; stun timer + LDA.b #$30 : STA.w $0F10,Y ; aux delay timer 4 ?? dunno what that means + + LDA.b #$00 : STA.w $0F20,Y ; layer the sprite is on + + ; sets OW event bitmask flag, uses free RAM + PLA : STA.w $0ED0,Y ; S = X (row + 2) + + ; determines the initial spawn point of item + PLX : INX : INX : INX + LDA.w $0D00,Y : SEC : SBC.w OWBonkPrizeData,X : STA.w $0D00,Y + LDA.w $0D20,Y : SBC #$00 : STA.w $0D20,Y + + LDA.b #$01 : STA !REDRAW : STA !FORCE_HEART_SPAWN + + PLB : RTL + + .return + PLA : PLA : PLB : RTL +} + org $aa9000 OWDetectEdgeTransition: { @@ -1130,11 +1263,11 @@ dw $0f20, $0f40, $0020, $0f30, $757e, $0000, $0000, $0049 dw $0f70, $0fb8, $0048, $0f94, $757e, $0000, $0000, $004a dw $0058, $00c0, $0068, $008c, $8080, $0000, $0000, $0017 ;Hobo (unused) -org $aab9e0 ;PC 1539e0 +org $aab9a0 ;PC 1539a0 OWSpecialDestIndex: dw $0080, $0081, $0082 -org $aaba00 ;PC 153a00 +org $aab9b0 ;PC 1539b0 OWTileWorldAssoc: db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0 @@ -1154,7 +1287,7 @@ db $40, $40, $40, $40, $40, $40, $40, $40 db $40, $40, $40, $40, $40, $40, $40, $40 db $00, $00 -org $aabb00 ;PC 153b00 +org $aaba70 ;PC 153a70 OWTileMapAlt: db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0 @@ -1175,3 +1308,63 @@ db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0 + +org $aabb00 ;PC 153b00 +OWBonkPrizeData: +; OWID YX Flag Item MW Offset +db $00, $59, $10, $b0, $00, $20 +db $05, $04, $10, $b2, $00, $00 +db $0a, $4e, $10, $b0, $00, $20 +db $0a, $a9, $08, $b1, $00, $20 +db $10, $c7, $10, $b1, $00, $20 +db $10, $f7, $08, $b4, $00, $20 +db $11, $08, $10, $27, $00, $00 +db $12, $a4, $10, $b2, $00, $20 +db $13, $c7, $10, $31, $00, $20 +db $13, $98, $08, $b1, $00, $20 +db $15, $a4, $10, $b1, $00, $20 +db $15, $fb, $08, $b2, $00, $20 +db $18, $a8, $10, $b2, $00, $20 +db $18, $36, $08, $35, $00, $20 +db $1a, $8a, $10, $42, $00, $20 +db $1a, $1d, $08, $b2, $00, $20 +;db $1a, $77, $04, $35, $00, $20 ; pre aga ONLY ; hijacked murahdahla bonk tree +db $1b, $46, $10, $b1, $00, $10 +db $1d, $6b, $10, $b1, $00, $20 +db $1e, $72, $10, $b2, $00, $20 +db $2a, $8f, $10, $36, $00, $20 +db $2a, $45, $08, $36, $00, $20 +db $2b, $d6, $10, $b2, $00, $20 +db $2e, $9c, $10, $b2, $00, $20 +db $2e, $b4, $08, $b0, $00, $20 +db $32, $29, $10, $42, $00, $20 +db $32, $9a, $08, $b2, $00, $20 +db $42, $66, $10, $b2, $00, $20 +db $51, $08, $10, $b2, $00, $00 +db $51, $09, $08, $b2, $00, $00 +db $54, $b5, $10, $27, $00, $00 +db $54, $ef, $08, $b2, $00, $08 +db $54, $b9, $04, $36, $00, $00 +db $55, $aa, $10, $b0, $00, $20 +db $55, $fb, $08, $35, $00, $20 +db $56, $e4, $10, $b0, $00, $20 +db $5b, $a7, $10, $b2, $00, $20 +db $5e, $00, $10, $b2, $00, $20 +db $6e, $8c, $10, $35, $00, $10 +db $6e, $90, $08, $b0, $00, $10 +db $6e, $a4, $04, $b1, $00, $10 +db $74, $4e, $10, $b1, $00, $1c + +; temporary fix - murahdahla replaces one of the bonk tree prizes +; so we copy the sprite table here and update the pointer +; longterm solution should be to spawn in murahdahla separately +org $09AE2A +Overworld_Sprites_Screen1A_2: +db $08, $0F, $41 ; yx:{ 0x080, 0x0F0 } +db $0E, $0C, $41 ; yx:{ 0x0E0, 0x0C0 } +db $11, $0D, $E3 ; yx:{ 0x110, 0x0D0 } +db $18, $0A, $D8 ; yx:{ 0x180, 0x0A0 } +db $18, $0F, $45 ; yx:{ 0x180, 0x0F0 } +db $FF ; END +org $09CA55 +dw Overworld_Sprites_Screen1A_2&$FFFF \ No newline at end of file diff --git a/data/base2current.bps b/data/base2current.bps index 52e4e07c704403b489d94ed7510bf4ac972dc0f3..9e8c66e6f28d20e47f2a3afbf45daccad2b38606 100644 GIT binary patch delta 21133 zcmZ_030M?I^Ef;^yPR_0D#$u4_aOqxsUo7H5JkKR8a#upcf1dFW?|6UJ-sizDfbspNruOP&se7uLDfn+Ks@GBDa!zTlC{0dl3zdNFB?JH(z5{H4(#FO8U zUbqaGJwh%bAAHnNG*;weH>OMXNiThU~bd3eUJ z=zxh6e(WY{GZ`On?WlHMURlaa%8ycpsC17irlmc$qiAB&5v`=8l(_U#OIj!HEhQ#D zLWF7H7_VP-5g?F~#~_fbJ?IP^G(M65p(0;Conn63sX=46$Z8J@zUDwWokz&uZuar|? zYTc-|sfvqArS7h7`ZzQypoV`+I~Emb$#l_7@o4a+PVE_73Cu zlcKLrM-|MYlgY zt31`Nf}T4)MS&JW1{2S;eet_h#O$XKH^Afos*R*latkfA@NirHQkQ{>roF7S5WgER zio_3(_N5dlzqyW(MOe77OLvGSzAMq~YZH1S^Xda3AGD;1==`9K2cb1pXp4os73ePV zy`zlI(_UBl{(wGOcn?p1qO}8p_D5P$xRfj>e7d#$qP~47aw#dvrHQgu4Z zB()Z!<0}Vk&93T?NfoXd>Z}?onmOOLWR|sQHLj+TOB> zF%)`i8E&~3hQynRt54C8L4?KX_u3$;lxTgACJqXcL0^f#e$y70LwAXScUnKXoG>$L zQ(hcOg*pH7mbMQo;s`&;F>e#k`6vx~R7%+K<71acqIjh$o*9`cd#B3y?q^+Jy^1J= zss5vicva-vx9>oqTASgIbbWp1d345Kzv>>SGM2*RS|=|hw)KIM9a1v{O?14}x|6C5 z?_OPBCfJjUPjy$6#(eFA`?Ese^Elo>4ptI;ZWoHO8ilX@6|J@Mz>gk9MOGt;Gr*JB z{+OLGQlnEC^JkG7n;1|?c!dVh<=EkS$SIAdZo3>Db28cjV!F=5;xYLof(#o zd4V|157)cHTn##0AJnL5|6`+^YF@Wn8F1J;zNKPYq0(WnOH@Uv?Zg2^`9& zye|(Cm4ONq{U6lT=1Q8lKL@p6N0`(tkZg z-Ol4I@_TjWIl%TA@^wj)rN7om3efZ~OQOK<6!d6CP_*c^4uDLe5JkH3aGp@eYZIx>-mMUyA(%$I&3h0b%Xs?hF$R#wIAje215zNbq z*Seh)^3FSf3a+ci>=TnUqpO2*RfM`ni(b2&ohf;(6={^jl2_~y_dF$U{N$>PwXd~( ze$=y!fmhnT{HYB+Vq#tn%#gmNUo4$OfWynIKR_63bW-sXgEanZDY5#Lj^U?xv)&?nlsXQ8Qvo zyJr4MEsEY)pj>uC>o$~Bp1cXm697kfka|=(zsNU>Qe}LEnF($t{E4<%Irxco9em|n zFw7`*!>>DG!dg6m54R4qsrNC8q1KTlYuuFc_A6i9)NUo2t&I78C0LR8I_15aS_~FU zPS3PiC~I7nPufkbgrscu*L>;uMD>zTKhkcjqVBO19Oa3*JaMWksqDFlK8yOppx-Z0-pD1ll1#Kv-?F^a)T(#Fv#etFM6BpAK!1Kr>Ib)DJNv&-)5(T z>h6telMwGdxJzfGu;h2`a2-mnrG z4_eNon9s^)V_-#ASa*rk7=Yw-+ z6>0L(7|HHZGTU&(7@@W?%b_*|k`eAXs!4`cV?c#h;w38P`--w~lj5=@8->cvaMWnd zj+}nkf+Veg!kn9I!fbwYoKB3qpFuJ5vM6_cUGmU@-OltgRSy-^JS|0(Ku>)udUW1kA#IG3unB}*{>z3goT zCsZ4#uUNUFpJ3O{?p1IiH8C62PTUeemy@A%2sJ4vuQA#7;gTFHhleAm9gYv%um#_` zQWjf(J{y|M$jCLpf1_iQ{E|E^_A_4B&xR*gbp&4TSm1rEbTa(K;$fsyVt1=U?C}xQ z7?ZQD@oo>lCTEPidMm2sIFVf9N=?l+luh4oE|3Zz@~|v+nF|t9nPn0htt9;3; z3v=eCRG@^(Ve`JqDO7&*cJs`fNGgOP>99#8X(Jy!jG@R@kHuGakitquC&uDiY8U6N z_GI+IgMefBbVYiu`KX&HG4a_A(|zJ;(f}~AuH<;p7*~{(HsZ*ymbfmt^W{6Z-7gP8cF-dMB zrd(Z*4khh%{`^SC3Fu#NqV%CokEqao6Jk&|nmuKK-)5t(Ke0!guPLDo=FP6xs_FA$ za@d>P@j2(kQt`vRM1Pk~%75doDG%`Glj!Kw5BS|5S`Q_A;7fO^we^HfttA3#wG2!V zP>4<+qca+Hjj}zw^3HEIBu2EV%!tZzGq;q<6;VXTb?x>~(ynv@)|G7BH4n1AT3b&Z zHz%x*Xo~}q()C!Xtlx})wOR^O(N5YBHZ3T4n#a^kwU+!D(&TkC$ne{cPI13WXJo%a zXH>sUXLP?M(XZ1Mi@1;|shbpemQSScC~5mbD_I%g#r!0EYvnl63-8$yfd4CkyQfwt&Rf{z8S8O`X_wj;Pe?KIP$`@-V+o zDf250J#{v#(AMc+4xV4hxnlkUm>>G*alQe=jAnY_>4uaO)#&N;A+i(IYD_`7oSsNh zcHQ!VtK}w`F|plfquw#`iporHak`-{bJ7)R{PX9hzsW5>QEjlqjDz({6_hP2r<~cL z6lHgMBSj5m?MZ4l>qM5?^9+31=28b931$l^$J5_a;p`VA70qH4<$PLBjbo!JY9bp) zQ8G73CbOF;Y6iQNqJ}_fE;~|AEnp+$r9=4^maxr~2P3Ce0KZ`nuZ7sJZlsb*c%Gem zdWVAVQvha6)i2#cZDPNmO3nFNJM_UMHT8LF4rO^kP6aZ}6vc*D2itL zsZdrR+oQzrX3bOuHQ{*>d3sZRjax3|`WyyhcEKu-3OijvAz)YzVN{)zq7r#3`+ORh z#@3nB)Wqitw7;CHg(ezVIXw$A zdh3_Usg}k~c~qN>&CH|Pp=kE$)6@m_9%TT04zrKC#THXvo=%oicl8T$smah{1Xa3_ zAKF89T`rYXH-n;*o+m3P^9zZ4s5PfSpwAlR)X(f$>Q^?Aq&70cNa`&#Le-5YsVUDV zD=CYP)p`06q*80RQWuA))YHQYC|PRv>OA_T&JbP~hNv0OVK60p(yT6^gi3?tgd#qf zUN^OfnhD9sLOy9)H@1+P1xeQeKIvaKtbm&R|0WOd$vKcT$>&R-)LG?Ib0N8FH=iu7 z6YZhqL2?WbgB-#4CH)5WL%5Mk_SNH*s1^k@Q5RO7}%K<$m zG?+0*D&qm=goboRSveliN}<6N&;&qLLW4h`6982R4Tk_t1azCw@C49_fUXuAiUFMj z=pvy(2k2x#XA2F_08M%>3zbh18hQYq0@-7PhCW8gO$BtM&@fbBbWw-zIccU(h71p( zJ_RBdAv2Y%G}C_pxTTPJacr1=8lazX4#VUh@kSex6P<35|BM@in9-Rn`@u{<9m?fV4OENe=?0nnB(6_|k|Q`%Q#V?3(he$D;d&Q{SlnQzuWE4zGzZrc z5beZSdrheyVC!(Uurvgar8rYqx4r6Q1mLN-J_e#GxWQR}^JF}rqj3Esh(d6Ko4)E~ z3ZO%9eHuiLxM2viJx>PsfIzRk|5c zodR}n>B*gd9Tn(jKL>g z$V@1=7Z_rBd=}s)0z-oS_9ZQl{D$dgLrx!Nmim{ohzU&p8ls^XD=jO12be9; z*P6NM=RpM_#$hORPvv&0-X4xC%-IwMInF$s5`BgWRR@4oeJ*dyE>+g+qtx-`N^ptl zF%%^R1M``*PGSWr+Dl*@t)7D@J0Og%JW#Jse;!K48-~@1swn&CBgnSo{m6ROgy6OP zl{R{CMn>~2rpSXziD}Ft?TBelbfhIg0~8V0pXj;@k{cU3WQWkMS;J*9jfTHqZ8;gC zbO%!Tk8ubZO49cFFW<6WHefgzc`Y=;iKK?l#u#;!EvcCTMsN@#S3{A`Jg4uVz7T5`|Xc+bOc z*E5u3%|d%pU8s~bWw8y4?T2e}VG#Z`Qr_w#Q%6!EYeMT_f6D$`FqdR{XQ=3$LLGzwtJG)V)ZWO64YH{6u}qN8kY8p(3LqZcxp3xI>*cAz|jHt zOX^B*Kwo>4$ab!;+o@(Erja%C??Mr251F~Xq%z4oiM7r~)8@L{%9^xHKxZ}+)|s6J zJww~(5<`!*@O^BypFKZL=du4Br z7)s8IHO|w~)_JFJzfcr0Khk{qBTB^Nvh&e5^8-Utw){a!(KDr!eh%^;L6!>`0pGAX zG?YA$RGZK2OO<6wkBl0B3#dl^j;_y-vGYEvHU20iVX@)$b*FmOY~+$Y!DCxANn2*= z3(CC57b&D!C^3#i^W(@0_dQHp9NL`Dcz!jGd`$Quo!=*^ej>^5^~_xqn3UV&tiUu$ z@ksJz2rRHR?>T0InPY=63(O3&!mP2f*hSx>wZreD)nAUrA00!rUwZl_iZ6idWC~cE|gz&j9X}K@1Hz&d%8OsmZ+G zg7fhMf=W|YHfY-?<&P;F(2NWZzWsF>MB=Vx4=R>h7Of^bzCNL?>~rYY0a1Ws2LsVc z$Br6^8XP;?_%g?iYkZkgM>k*Q)bW-tbLucViSA{L#<#9OHVf8-*e*0E14jlSTz6zf zu3}_Jt6z*kbAVM<^r)*?)d+G+tU(_TXDITaMvzO!qJ{;t@hmSSSU3dt+<`n6Mn;#M zHY~-8g(<(ChNUUQsb>rVKGvUEYROLXHdvG9QNQ#GUs#fF6;_=CMoX<}t&Q8Z>9A>E zD6xxeSJM=xk*l}Zd_*{ea|=Up-#GMk;rJld&a=yenoNk{?@grDSn|7# z?eBcwXGBA)E8U#6vs9wYuTtZEcT<)cd+WbXlG+|IH^4xxlz@&Nahd(td=vS;TPss# z&@s!74sdYL+`lMh2)&gG$}3Fyd=~xo)p$JH7e!=lSXtenZ4e*s*#3!~GT~2k;`l!g zr2N)itA%RTHM@NO`OOel{FWnWY`ECa!P!F0_faYCx8bmtdQF!9KeZ$*KbRG%GJP7d z&N*PE2h=wIk`~41QFCCWSfG|u=@1tpyG3Hpz>r^03NS3+Z3Su1&!3*qeHzJ*SHa|Y zyG-DKrZ0+#E19&7ex~l^;%So!`%Nc6>@u87r(K7`mTyo(TfCh5@`Ai%rd!eFT6Flb zo+9td(czjwq%y_(9J;V*;n;+8`TbVO@5pn^zVgHmCQ>kMX!P!OQ*p+(;=e95!p6%u zDEZw1G%b%tA5Ek+O--}U0S)oec6zsVIfBoAxOe>I$j(b#C&Rl&idI zXqr}2Tw^1r;`Ks`dI<7=xr36k3$|XZ%h-CgMno|tlp@`{LOk~=v!dugbpEA&;dXM= zcJ=tkpT?6x;t}79M-*KmUgVe-3&qpF6`OqfFYeUTg&S>aKlqdV7PWQ;t7f5i_Qfmk z$BIXyD@(#Am07#xRCdpV4=ZjK9~_+gxReeNq)?YMvM7bdCRw4rLD^TNO{k;?fQI!j z`Sn~EC{jMZ*dNvflMwzl^ zE`K|dC%?apdY4M@siTq2vK4ND$~h?5S11Q0&SMPq;Rc%Iv=U{PN4oe_a0SvhWIGmOF=I ze%OP769b(P`XSUq;M3+9pT@9nuUz#8m4jJ*Ui>yb{aWQo^%Zn`xsUAY(>-E^=~A;K z{g(xrSw#nURrypSu(V{?4l67f=b&&V{rG_#xKeYa?g}=5k>miDnOR&6-n1({Nnu(m zHY{$otP!vxnSvwD`KmCARpA;L7?o!Oe;&g>4~&g_!73%{VEuia&n9xzdr?56#c1FZBGsMSlVzcAM%u-l*|%^-tV+yaLXeEB}K zFotY0NR003S_vG#jgnW76FpK8j2Y$!9wGT5nP;NQjgd#OA1Sbe13aojV$w8nnh75b~i{n0}u{EPW4nV%5*d* znGwTCcJNlTX{DD(id%Q7-kS_%zELX_{g%}$H{Pb~nLUbrbIsadbZq5xuiBLU8ysFq zS}z?@vXnZPMfbW_HQTstmx9!sjkC?mlC6-R)E!^$j3!AXBMv>(HC+_l8cv4xt5+oE zwHVC$hZ1K&++4Wg3LAGrIY=*McYd8)&Y4LeAC*hRc;qc~TAFA(WiCneqpVpZ$Jr8) zXR}H?w7eR_Itp%SnF>X3?;lm=Pd%~X@BKbq-eg9jsjEhZ1z0}Sm@Mw5q$OYH-AK|C zu<8&IjkmOVuYa*?x6}c4PY#R+_W?x)K^-vz9a$CO8f|v#n=(P%Xp^z?x}h zx6nVUyuEgPXAl@?>5J3{D^t3vv8R^J)@8DxWTo&E`Bg9Z<`bHmfhMl@#^W>4s?~EX zWZ!|}xv?Y1qU)=N;A2x!@9H4Wd$*Ii%>O+Y7RrCZI<1V>Ofbn=kW3*Qec!u{!q>zm zveIl4%rA00S9lB0E`05U7SraL{_I+opk+C65Jl0e^yY~IRr_=pAVCFX!i3|>4qf*X&Z?ILL zqU^v|x~nymg}UT`r@&}g%NYbX%0uLoxMtlnd;`{76eb zB%si_rn#NjAQ@qb{hivOXtDge9&r;K#^We!t*!fkpTNX+zRMn>0r1q?I7q)7mS`fd zkINpQy=xN&*W#U^gw+CZ>3uPGABNEhhuGD)xD>rv>nl58R&3d6(`+j4L`9`eMho%G z`|2Ww3hW+;?SEkE zso^#HV}#KJI1YKx=>-VR+$ohnOCugI>I2?JOTu}tRve8EGc)&CR6>7zp=>RxTIVU7 zk4~w=A*De1wUNcvoiWW8;@zn5!@>0V zCS1UJ^seWrSAuBY;gI-0qM!k0snzF<(&g3 z&!Y%5c;hsgZ!PsVYn4~FaeMELX%@qrQDkY*1{abes$XjfyM0>mtLsv8pG;DTY@&=r;R$42Ks@P54joU{Z8@#6maB3e zf;CV-EZq)HOKV+|bk>s`GM-e_C!sgY$mUW3GaYtYYN1~rmBc0r`bx71E%-GQAimSm z%^L@QyM8kcXA;>j%_utYZML+^d}1BQzu)Ed9!jd&XiK3}n>2D#NwI~1Mk@D5!rZ0u?ECkHM<8*Ua1oVW$IlM3><1w=~E&So^cbW+g3K z{8;Nn=FyFQ+oeTsetP%yCAb1GOoct0V}=>532ifMNOMSAs;4C1R)z?q)f3Xtip`T` zR*{c>y70^+1LW6UYz+%}QO2}x4+EBw*6pERq~3K2){yJID+M=18LikYIZS$v0#;0? zXb@r&%2U}8H#jZ&^#H8JNGl?+L5ogkhEF3Ib7ztZ=od(#vjVApOlwr5C%J1CiN=PJ z-_A~?lpU7cZ-$*yL|b*+lDSo}(cR2+xQWg`ZH?wp$YaK@2P{BoAKPXu(3j!MAJZ8N z^`;v0NqZ5#>Mj*kw#?-r`g%)1yvyvL&^TZ6oWZ=`yyNe01sNW-CQ_o7)2hFGOgY2C zBb}`@4D>tHC+Qc~xs|tMz-5g7_FpCpT+~U`7SBOZPYt4CL5x%!^%Q;DBDLGR z;V0PUvT>tK%2IX5~QNWtx;n=;BAp8qw=V!-k*0!8LFeE2l0p!mAKjQyj|;x zSEW66WPpA-yYiq)A3%oIS7Y#fp_qV2Iw%nh-!=v(dr;=K$Rx)rl!S>RYa2TD^k{Fu ze2r5JLO-e^IP;`NHa_HIWpgO$W0-6tn9*d7-(||FVvb!NoKKXXuddL|=G#A^i8ka& zQi`5z3l@gXCz18`srZsUG=Fi*#2I3X|t$vU$F@{FhB~+)~weex1q>sr|+PO74e6a@S;i`^*frpbI$O=UsLV< zA_LxRk;PeQ1sQ{TOtKsFn)dmf@`~WTiHf z$nQt%Nq78<0K|~ars+Np6c>L(4P>(Hi{CxSFuDTHO*SYhV4JR&QK9F>M$==M*#38E zEhe7!R@xDNA)9FYjB6%DzejP&AJh|*KcGa2zkoOe;@J?-f_MSM84xdncqzoIAzlUX zCWtpeybI!;5SyfYK%$fn?E3B2U6poVF6@8T_p{ks5k-~b)7~O?d63Phda%F7^ zMry34qdD^QL0>QLp)(GBGE*lkN2len_^w&#qkP!%;tvf~`u)gh(T8fCUa;tcqWD8a zm7+(ic3b#C;c%=Zr_pr>Rhn6g)nOg2)3PbW`B1glk`IcW59)(FsHb|^NsB&Ity47h z_U^HJo2d_n^`u2r+6E5H-T-}7B(0nL4#{%D?E^P_o_=B2H=h@f#4)%(J@*V<$XSfv z??b-1A+Cb=Clga;F-bjQX{{q1E@X(4DSP1`XmxIwB=(|<|MM?D+MU1A!>^eqgFV>$ zk8Q?=Jy=J(PRCSueO`aI^8%GYVgc}PDweNaLZX-Xv~bycdFzgX{bu%C z=H%AGMQktZ*WXs#u{-A=KQzozxvuvqI}5+;PoWuT?2tV_>WEplw1n2E%UDvjVSH(< z+}ty#;ftiFh(qzVB)qG1Ixp7mY_-W%s$RB!L^lKuC25OaAF#(9Fh|S@bFSH%OriUw ze!^Xo`daZa*TJ@R(lsC0m9Bp%6R7hQwu)9iy+UAKwsOO%YiVPzp<~TkOz6kNLkSwu z;wPMrooSulQYEtXA)~)Ic06i&8;aSHk3`3BdQBrojlA3R2j=!Oo5^O@&uvR$7k^n$ zx!f&X!v8Bvusnv|AD5a=bv&&}Sk}6{ElEH$qzKMvmZyEs*yUat7|6~}$X=c;iIc=F z2P`|g%0qU#_0|asp^M4<{PI0VYp=Miz{;XRJf@QS8MZj{KUQ(a>=3>6G+j7KJ@b3I(*FtwBWpC@K>K0 zb6PJNQ&f^MPk{nw(bQGOnq(KwLKWxZ@UKUs2j`~*PkN*Shv%ztSYP-&zj6%~sz~{i zu?+2_BroM93#}eh(mRAw{dCx%_4<=&`h`Fty8SDXU2qqvr3vLob77n?dQ~@icEL@! zJh2@8ePQ*mMY{?rOx@&_{if}qHU?Z;w|d6zQa34c>20=p>I}5|VvwoNajiPp8=btk z0pDY64Zh?j7`0khh?WZrVKaKVRFuUDq*?6zc?GowIMXxX1l8c)Tpi_2S5jpliB0g1 z$B{&F`%%HS!J>-z4c+L>x1+4QBD!d4*LiV`&D8s?|9l%Ka6k8hj&0@o&Gob2W*hM= zX;xKIq#CWxqSYBI(CjN>OOu4cq9J2QjaveeUCFSixUM5GvV*u&s3VR%M!#GcMR&=kW^zaRlsvB9xOu{KAOvbqrYjxZxB z)3R;Du*NP3704a4wkDLP~rCR${AD;V80OdbPgobW1yOUXQ>{z#V*nWH1VZPgODT9NXq#I_Moc+n26uo+39$EUCQI}Dyt zSgO~6nC)1fl8Gcd=0qQ^hT6NXcznRTc0|93$a$zM8@j5nHS$`lz-8B}!jrI#T3oJu zYA4P^_;Qly@1brqTZ;AxR2xJIo|k6u%VLVlPn8(yO5 zcdE8$S_~xCY+~8)_Z+VAd}!H@Xmn0Gr-A=B7s4S3l0$6v-n#t?mnN2`Jk)tirE+4^ zmyKlw-%)yf9u?nuvnfMAry-!V?bw`#v&S@rrJn)mJi=%dyNI={}h0#jbO#FQqxjxQD>c`97xd@E*3#EfXxltG$5K4!Ia$Oi563X>p zG!j2aL@S=8;aMzdf8sN=gpE@e9JrG>9Vg~2g!EW3XCtJ~iqThj=<^ddv&OIXj3-YX zLGIn50yp$U_c+@Z3&<`%I>Vp)9;15*4pnsrnKL=4gw-%D=uWq-o)TP&b6C7h{%UM!)XO6Ux4?k2{ZUqPaMPh(9O zoSZ?T`%g!SnBvv>$obh$fj45G?Lcll3OpefX?l{~YhEb&1xRzu#+NSgrHg%O8$a64 zuWW}%**Y1SK2LN_N$B5{YZ^eC2hf%Qv{e9Y7eG4%&}ixN?da#{!RFjD0d0!rl_2*Y z#ZIGg_IPvdIBn@e=ljr>zI47Xhi3k`%`}M1K*0#z`*9>bQI0Hr8jn(c3Ue-@LK(TD zIgrU!9N|G|5R?B5RsJ-@VsegR&WM_*T4&Vx)8t4X%JpY*EA#xhd?CFDP&mjRu^TP` zA2Eq}lqnjuyWmVyUSOtP4~twOX28)ml!*exznF>2UxZt8^UY`?klr7}ZG$tlA6|sG zx3V&O`hY3tfYVO{^{o%X))tm>(KtPIOid>8|Ji@g)$eap*EDkL+~p@x#?PzJ&7ViR zSFP}-7UjUnqmZw6HkSJxqff+g<^nn@4h8h42Xh~A`brE}CZw;%aN$BaK9)|15gnG$p(x*W_JmZY*I7JMtP!uH`A-o5H)s%bQ8n2UA)c#4I8U^7JWW<@r$k zmQxKz$8YD&zSS<}as}05OJb*CD357bQ6Ze8R1-COsA^OvJ0R@|)titF{`j@XiucmZ9tZ5A)nL0Efvznk=!yNeS0LgTu9#;$$c%P?~UZLgmh{cw?as#g>fr|^sF#W zDx~Lxach7+j9UxzVca^P598JYeHgb1=)<|qKp)O+0s3%mE6|5$GVpsBx8a~*LwMlM zgJC?_C*xrS5BBq*iU)24fFV3^=fN-@?BhWN5BBq*ieSc&ytd{l!gvtDgV90EBvR4L zqepmfln2Lym~lWE3}_e+B6u)57$}+fCn%wek@For8q9a}crXfTQ&@Qeg$)nvc;LW; zLLLoF$xm=ee(oI8+9 zI1dc?Z{~A<17dG(8W4MP(;=7s0c<*Jq>dt?oH`B{fhUkmPMrcI0>WqrQ4nGv9EI>7 zg8yH6d5j+~Q!qI>@JK{XSwesZ5>y_9JrMFC6hbhC@P8?{kQWALaxlbUelmWHVn2S2 zgdaafi61}4DnEXVT0a;gUG2x!!@&GF800X2evo2+7$i;jbDM$QpMzmm`SZin`ol2k zYJU#Ksq;ru^Qa&+A*Uro!hiTs3IE~4P(^``hL3(2RhBnPI2nBNBd7@S;Dd*tN-7k( z9R}eLgu@V;k=#Un#G4;-UlgxKucG+YUPtk*^+)k)v@)8Xp{t^KEm{-JYtg!BUW@vo zc`bSs&1=!?XnuzFNAojuWeh(G_U9Qi`}6Gw1n}(#1@P^M1n}*L2Jr1S$O3og`vfIyx>P$17BB#>ti8i-~p6%M@hapHjsfPymx?TQjUwU-BF|0m1Ai>Km&3lH3Q zP{M<~JSgMAJ}+cd@Xrg`XnJ8JuYC8x84f{sZiz9hWd^MV08p+hFmPgW0BAHxO zRwVtDk5@+0JrEBkS4Gl4M)F$uB9dMh#VclSB%K+>>t zB#Lh&ihjz+E2HQhh=B)2VT=sHW4R>3Pv~ zS{!GJ(bHl%GboMaEPy_iv&85-(cB=6Hb&F;qB$#!z8%e3WAuY)&K@$O=zCGLF_v?H z{3!ZC6n#6EbA&2UbXOF8CzhXLvS~5&tQdZprN+>6VmKGz7sC(bW(<8Nh98PChQ1fW z4TC0PIB$S)oDa}M(et9{v{-H=M$d`m2l@c?82S`Nr$=$yFghcO+kw%KqPU%a!(ie# zIYxIy(|6*y9B4C+7u)q1ZZF9BUMxSq=f&^_;d(UxEpA5hHXtR2I|d_;;*LY-qUbqM z+({^k;?6>5G(9bjpXKvnxhIer%iDmISd>foAyWkv0P{8oLI{%6_5R!nbc|XFNhu^j z=lsycf_7>hWUNPWSve?MeE_!^6;WFtYb(&eL~%#sC~6p_#SjPx`yo_8&_bw&;11#c zTCSF(S4{|*18kp0)l@Fc!Gi7$}+CqUMJH5Jsgg4fyo04Nt^ zQ9!u?)evO4hwsO;G6_G2_DT3TR3YK#(0&O&hg{Iy-T$TJI}FqZ(KwQ-hq?_&UQh^E zC`)9!sTGj^k9d~vrq-Y(yQ#I1^B?&v-%Ue9KFGEJBrE3ys|fNz<_hWvire?UyhIq< zwg10v1Q_r@<=0jmnU$`roGc<{_YI%>S&X2=zzF4CN1n{|*0( zfSr)@%rbyCIaUF@$*~FGO^#gvZ*ua{XvM#ds0b<-BYC@JATK7XKweBXf!uoJOVOKT zJmECz{}3vQ1JNYXgCrz0cnwfRiG+6?U>1BNbQrh`aG(-8Lc;53wFI2V0vcQ{4NihS zC;>+T`X-@a%qqg04gq(rl6cdhyj%D2MoyK?*ZVm-!kbstYHz4qN9$zX|EcW#pUU3! zQCGQ~azO9|-U<5c0)hY5B@p&PD1)#Mf&+yAOZoeK;9KKOX^{^%-jp`=;Sx+~b02Pk zDeOtOL{sL~PZLe)TpwQ%srqXmTpl_2rVGt}mAYb$z)n zpsp`B&6KwCuWOz=Hg!hghuMi3EAVFTC65dCGyuu{Bn*@0s zlJK4qY|dc`?<~ROG)ut$Mf0=&h=livz<1I=b1W+XP7pM=XQM*&+6tVo{w=9&*b)~%q4QkZbeoko5Q%) zvza;+AXmcXrjAtf@_F0p*mNCofV^*G|03ZhB8tQ~b*^GkocfaLK@4nx{z{Xx<8l?> z#;9eviYqbKhUHd*54j#gpO3A}rNOVvLo*xL0G;Z3G<`lsovXSTO<#;r*Q-)uU_WI> zZpf_!w=pl4PKv9`tpwka0{g5uM|n~X7^N{)V6|Wl@@7kd%=Y{by9K#AKIi|lTwm}s z|J$_b%;YdNdqPokCfVYtpYS$YtiE+#e9$z%V%g|pii2io*beeQ#^r3%=De62i4@cj zrmzHlD4cl}-`sD2-6^>ZSv*?Q6eLIjvCr-=-u9B zi!*QOm%$!5peBV-Q91If{idKzePhEmWfm)3^4U!hf8O>96*iPu+YI9^_k^p|`JMmX1y)k;#SvYLF{wx}l)FF$*5T zxF|SH|x2k57UmP@a%==zv7ij1=ieA{06Aix^O`tLvVfY=8x%be!Uq_o*+!LR@ zi$=UobWXc-)$U!@q>ZOGk;YWn)vI6Q&e z!vTMQ+QgkH-HjQC)z-7K1{M8abn@e0r2(BjwV@uK$-L{@P73_$d~8Xk%!HIe8clx} z9I@7gxzJh*kJwDp>v zL&v)_R17OuWl4!eC)68%_$<`F*T=YF84wZBY@sd1(>5c5q*% zwLX@YNGyvx_Mz(ce%`5F?6MujWh0WCen+>$#ZEYkxz_dkq$m1L2^&!#CZ8g;t^(Fy+pgA^G=JzS9%5<0r+qvJc*FU;V7y zPA+3ZtX0%PWU`GEkXAEg@Sp>o`QUEmuni9OPQWkPKcIy9;pXJsj2rzX@C<@8t4y^O z`#mN2XSi8UHF4p;YQ}%jO(k8JTt{Qr9|Kj3ziBLU%A-Ekq;C5}Uya9b^~81P*dJr@ zA+6~BAM@P8p4I1uiX{L?O1t2Ru^4O6Vq*ATHI{vh7$kY-wya0dBNc}|L%NTXaX72{ z^OEM z3m-HV`TgaNCyhmu{xaf6o*}otrMU71QvAIWANdm!{xb{ben#{EapzN8{z;tWyxD?; zpC1VF8ElrUXpn#vuYfDJFUP2U6Lk#S4`sMiS;x2sp$2=n1#^L0Ft1`S!-!_j0n72K zrfw+cH|2}Tx9T;8-!VY~EQ!B*wf%f1Ao&+vzv)%GKk~^d@UVOM@bjUp*>-dC&jw3N zxCEpfCZub{SdX}4?l0*5=W4gC&DY!Bzv)zV5Ie4g&o?96w$3#p+36WbKj4N(Y(j>C zVB9kkeH=K8`%Wx9A#lgXOfS7BxEZ@{1j$Z`AT>v7;eGgRP!xEcrpX#a9(d}GHCuHU zyTjBek;SENwCu-5eNng@xX`dCxIY1IM!4}`LSVe9PALo zQ1dU#sVoR9TID6Ss|r!%&=S?I^g|DD)K!z_S^{^vf*r!xLI1F~aY1nC(KkAHIAHYn z^dxN4@%I_$KiG5}f1~>Z_nrF{7(hW17mg|LEQOE@SEt+m!;TONB>40<>};W6w{U{B z8QU!s15sv&=*gXJZy1Z(J8BH&ag8Jz_4?Hq}J%hY*iX zV<%V$YH|PH*ggwEI6m2e^|Tbw_%}i9VM~EOo*mfsgQXx|U>Rvrt`rYevXR@{ysQMJ z0(_y2J!LIO7H(a?ug%;>P$00h&)%)HB|OyQGutX{1(^b~Sld17FCA5^$X?Kh$E33@ z_5xS@%T4T6d%-X>pIrwiZ{*$f#$G@Q@rvv0dS}7dk+V1NDGj=uon^3OO4+^Y9r^s4 zS`AYiQ?_6Nr{8Ce+AXC3uoow+#iNgpL8WPTix(J+v(*-0u$wjbgX~tOUobGaV zduYG7d>?c0a&}|p=K(f&1#=R|>@XY54KC1KFiXq{Rh5~3UCIvIP+Vm>hoU-9&32&5 zR!B~$ocPj;Rk7vAhGE3rV_N>VEB*sUfqKod-EaZG`p2>^u7Z$ZUroD9_19S@-&M?D zk)6EO3=X?fX0V*SpFU)JIlI_Zu-bad_HtFfskm`pqm8VbedH<_@32Kyt^z{$eJFvX ztk?}$1smcfScNAfv-{lyOJdwCDwHmMnT$b2XuEV>tmpZb|EGg%4{GX4kQ6RYum-zb!W@W?oPA2?bM0gvgdmL_|5Nr-*+A}_s%`%&iQ_yKiNb~^2wA0 zye%lV{(L7X9dM(a1*4~JC+a%}j2{Z{5h>0JgXzNfQ!I{)<=zW}MwnsEX`E&$d)3-$ z7PwklZtf-LZ`W7~`(-}s_3;Hnc4K`v&p9Fq3<5w3LPBK@RmK?3h=B2QWcm`WkARIz z8kL;9Zr@eh(^EZf^sxb8&2GHa3qXJ*5I7E~&*6VWKm{#b_aDxG9h`(oJJUN^TL@CA zf9V9^YESY{>>!P*_X`pGr#_{2#yqA3;7*^3oqf2GQb$a&=&-d;a&kL`kZR2^fE?Yk^aN}T0w>?pblVf1E(E3K+ z*D4k_$H2{N_{_pheDz%2Au+acVkhTEvE^>|SY4H1t;FX1ZVp?;+(03soP zVo_s!qkcSb{VRMp7QRLO;Ya*wER<0nl;AI8Azx_#PsPD^4E-KIM(BP@UfQBk0eVak ztxxrYkXNXTTp08$gSjQy%B=NxQuo6eAmMK*BwZZ2@Ej~r^xn$KtGuZY@z#RvRXS#d|Kg(@7TL zS90E(LEK-<(Fu1ZA>YVRt2>U6zsQl!9Z$%z9M!o~2ze$)RqpMCd@DyKr0|B1^SK=5 zyKfWnogDqfolnSLz2Z>wrK&&8_c(A8<4qp`J&f@Bf^&N5;jD+UiZb9 zG+4xMW-r@w&azGRI)&Bf6x(*&v(g?79oe~ZsjT4Htj@L+=v`S^nFW$9{{wU5+EX;b zl9DZ!em;+XT(8qz6aV(=UWcTi^U>vBgf}SU3ZjwABU1jWd%`Q+|fwVY}DwP@v!ZdOH6?UFDAi*w5-U2QFm$aX%%) zcCmq7Yd==-D2|P)?RlbD_c#uT4|nB}1m5-?XKR>Ap!5+iHvtfr@?7i`O#vmd!0`C9 zXqsfOiI_M5f`>_rGGu{CA@~s=BOB&pWUoZTE+6B)@=Q?%P=;S%v;-BrJ)(fb7#M|~ z4~;y^2W>DhnFP0s2qrw?Ey|A&%C<2SXaoIac!Ebca-GZAl#A zPL{ws((rU`e+Lysp_anCwiKyU3Zv5o!)13JQBB;gI+y_?qTB92Bn}{@)1rY?%0S4F z1w#rPwG`*5C%Z7FC*X)>rmfLpI^4m&T8R0X`}2Odmi7yZxo>T`a!Gy=|MMWc9%)r( z_L}xv@y2te$}{XeyQ0hVfyMak%hm7u@=`juPY%J)rIPARJ;s;7bfk{eRGGPR??bD= z?_T>=j|I+{e|4Tl*GxOftx9^;pH#0lXEI7VbQ10(Q zyrwR^rnIqu&YT8n_E%-D{ZSc{=v&ySwUf!~&$^V-!uQ^Ez18z$36L;>sDl);7Sz;+i$|YD25xfF6c3~M60FAOM0#{Ipl40t0HsH zvC4Gvn(;~mVQGfp*q3zPQMepWB18t*f=9UA>gD>;ue_$eKTB`>A-}&rxq~K88{nU~ zU)IZq+JIt3LyvaNUd3etmxkK&=_jt=3MkBbxN0~Rw7Lg(623(2#WCoW!v zUBp=LGq<&!O43fQ?N6l?!{pk{)vEq}a!Z+i&K{a{z5~5^GbTRj*8T_`x)o3KTqaAC zwyj)_T+yo3`k)u}skr_$h9>74wWd-0`!1KbmnQG*^%pZVAW%nXGW<8F=Pf5@UWHD4 zKcZX@C-D93>@%*S>VO&VJ`p9&S}^a}^96Zfge{Xaoc5Ip|lL+vOu zATREt0m&_b-};yM$W`Q@CUO^OPH-&|0u_1FG+YNFcLMt6J+9xV@c)TBt0a%s!(xFa zo&p;Mk;DZpd@S&mO6s|2s}Bn6<9F%FbFhtV(RH8&WwWSeA-fcj+vbWtv?w?k9E` zZB&xg_qeQ48afm8CPG$CO10bok<}j}pF@++d%00S{?}#rED;Tu^%Zvgf{L^1h*=eK z^6Cr_e>`5MxO`}?(2$$UzYR?qQe^1#0~ z?5iTP6;1v9t*Ltynes;vHwtBn_gZdqy<&7dm!?)&Jkloar99MW1SMt^k8f!AE519) zbt*j7oLGYf+rZ^kDt_+fHp?oOI8>xk6nrj>O|AQpOS49MrQv8}f5=r->>;-XwR`zP z(>#qY)+Vzm@=KAnzu&HmCQFO8AC%;`kGTH$y-M;h8j$!VCAk_sx)~^>J#dwUr_0!0 zZ6++6{*WUc{rh254)7_U z$zLA9siKtGl{-ZT(yA!CcvMB#Lp0?Lb1flFK2d0sW$nhCGNzh#*ZA;L<;^MCCMCX>_179+_AIM1e9Tz~OnYzlQzB-bIxI@xat{*GYk$X^zuw6X& zlO*Jkid<^yHoGDU#w(QZ%!oAU2W6)Ap0>YHNtPm}@UxQqwamYNf6X>Eml+7r=nD(! z%o~ri_m!F7qiwiBrXqV@qUCr*&5$&SI^qG8nV(PvS%~wnH?`dgV=;ICr`cg>D%W*G z4=W#{@h(iT8cifTf;+4{3ENh<-)e+8gB~HT-iJmjSEBeHd~4-xA%4wS?NMbudjuV< zW2MpGps^GlZS+8UH{@tzNVELhUz=rA>-N2rZ`v`H?WDmWu1?VhRJM~%$o5UBbn+c- zW(iHk_h^xr5DL}2Kzaj31-Dj_@5;4gK#w|qvRPe`NNNB z##3MYnpvbIy-;Z+o$yM3E4iGkVn-aM`mOfV*|i^6l41AYO2-lSpRmeNOdS6So^kYc z?Z2r_?YbmJO^q{ZIhq_})MldbzHt-2cZ{=G^pjSIc0jTbj&n+uhCbH%l)xDaE25EX zdi0nxZH`fowWvS;k!fg-QR=g{)Nd>9)8zZd+Shun`^^9Dzk8fnKxbAz)^3++F014= znZ8f70VQ;1I;yXf!DT))oFu~llZd!c>|^aN3i=kFgeBM1aMZ%t}Aw~Ud4ldPx!@XZ|SuVwjH9g$Wy$W+glqhn0 zxU?s9CI;F)1VAyl2i}?BFFo8{7ryP>p{P+0q4$*iiq3A%#T_Vy_HYNtg)$R7QE0lS z9ak(U^UtM}nNuJ9r)(5F;93={A8;GcR6j+$9Ijh%e;3-W87RAd16omI*=TA5s7ToO zeEvbj#2#)tV74>Dg9^k#;u{nrdN>T}Rm<^5a9iAJzZL`M11Q^rbql?pDBqI5{={uQ zM2%o4Imi+VOl8xYfnt0QG>;DraX~Z0ucAi7S+`>i)L7Qlc!Y`B0&*yLC{YeeVxQBQ zW3PK!sf46T&j%DOjT&DL~}%e zf!b?wav!`E?>fY~p2H5S$gd{ZJHJ>-3J=3C@%6;l$FOeVRO?YsxMcnQ&iny>u8a@= zp6E`jl|!e5)g~ZIcxtg$Zpbk5QW3R!lH5UjL(4o;t}~jGOW0!NdIS$aBJoh>T6wYP zx)tAeSTu`bzA9Rc9tUzqKBb1{x$-njHx)}OC0p{z*F=0TNZdh&{0z>7L2##QoT$Wh_ zaKeynbRbJAI8^Sf*a_+enesF#@G&ei+LBYCDOv4ON!uG*jnG+sZoph;W2zDRoLiET z`Lq0Xo~KL#B$GabQ6W+Ln~Aaem$~h+8uBol+UfAH9b5E+Gi9;;m-7)Rj1=Gib|eMF zrujT&hF?1$nR2Kj_*%yz-|yL&)DtT~Ja#agvUGje7Vq+KB}gC9b2IvwIko(|hcnWv z!zprAX=OxIH4LBPX;r)30=QEHi}y&=%i+Q)Ba`EbO2a5Xk4yp}c+W!KRcEkrue=ju zy`=Tog%$cx%M;;Lj?Y0|o!Bk)%8KF3>EwK|-BLy);WT0Nv92F%DO*J0k&Ma0w&_+YBH`6Yu^ zVpAzi8F8c9aYk%n51K?@nJn@&HYBaFL2*&bc}A zBioebWObFfOX`#Z(WF~9m-kuHn?WKSkxjbc2{JjZ5u6Z`xh-6IP;!PIOOp5XwTu*yDQXVA)V0!Hl1S!L?lzomGgCB(GnL4bgbM6pk}%Y!PLT2(}%;~r~Aa48eY|zPokbw zqu1SO=5i&;XNbvf<(XVV!MS>O)S4rxHCxr>)M`!w7rxRN&2!25EfxUJO=bx=XT~^u zI8@GXvcv;ErzTb#`WkX1@VglcrHR!#XDo0K3xNN&6dQP$QBqGDvdzmiJ_Yi4s@-&Z z=v*M5$EkA*D5o=_fUo5&y&Iqijv z5?zu}5$rgb0wY>Aqh!=1RK&BeZk>#BM!8b+OGsxO-S8Wgh|# zaY94R9xCaDtSg10rp*IFIkm9CxqzC2QnCP*+wcuVC8L^zmrxGX@U5JhiYSYYP?;XF zQO?lakRYSd&YNV7ySREZUS4R zmOX;W1G6invW)#&E5V{*TL?Sc}p&N07IYQ$Rx*RuTAao)^7vKf~LK6`B z4Q>cT=p=+r#0^IfnuyTRxZw#xCnGcvHsZB0?%N!wr21 zpNf+I#ti+8LN^VezhMS<+~}m9C_81YPeBO}FnuZlw=rfKs5aMsgYX|P=GCzf{d9z$ z#&j4aI}SZ6p}mT7WMvo3^)pcVK}e&bf)!LP0%)n2>t~{r#h5-8fq9r=w5iZ6gr{JJaVC5=!s9SQf(f64@JP%sO*0#K z0)Nb~(3ChACAwpVToXPI;kKB8GU4+P&O>d53+2^$621KgL4Kf+O)P}u+@q=H%~XUM zqbY|MviAH^MWa4i9bK+K978>xqQtC>{tB#<*&Tc7;ka>(dU`QshYF6^SJSA^co6~O z4PFhq_EGjP!a@5a2tDRa3XSTow$Y=#YZT@(Wu8>3>ToWwBZpnr0uh;o?tD^nUE7P! zD@`4}4X||HFsbUW;U6S6r$Fe&1B!o*ZqOaj_WFhI*=1iTb4FH=>d^5ehOfpL_4YxH z1rJb`j7))2)uk$)Zj!`+v9UaG9XIlHi4p^Wz+{OoNn#i@hNyW!V~_v$0F#O%{rE#Z z+((77vKp~O7bY=$G6ur1`2tVrSIU}^G0}sX$iWt#E>NNil1K!Jlam~%F$y?uzE1=d zvJ=S8$9o@rzq5jJsPiI#x>V8In9DZF@9OFbP`d-`f(byG!z3P%_cp?#^POhKp;w#3 zX#{8=DQC+RgGTqdB|^Z8F;JJdx1@+Rd@)+VNkX8>F$aoIM$hIrbJGKEI8aY7poB00 zXv`I;vbqAgw^4$zGZsLn1?f^j`q_>s&!UT?q=o;8y^46?!Z^^WOg4?`d!7TJoHa6o zrJe;5N816Khq55*2sM|HsoiMWkY#kN^Rz>{ zm|oQoV+W{g^={@0dUlzSZ<6SSoB=*k1e{_2f+0k6GyJ+>xD`axK_~ZSG{L|M7@pzp z;&_Bq9cFj?_QKV14;g0{phy-bv%H;fU51BkZzIP9b>=f8JM(i<+hA1&>2B9zYGtdf z4wtLb(==5&A{kigh(q7*R>6B2qorOeUs6_31}6)CRRWQYkgMG!vKR4gujTr0;gVo* zb#5?_OOm0b2areR!Xy`9@YetIA%DP1fB!?iNp|QkV6B%?Sq+79odjC-&n7BC1z0zfQ@%Lt!5VOQA zFmucbv&JfyOt}pM16{_~`5c=mIAW!(7g% zAM4olJ|9WS^Qf@Zl40hOV*}P_5k6`O=`KIUny>uaA{?;L`30Z?)dFWWd&OtP&#Bkp z#wDJn`pcJ)iIKDJA6OwOTMIfawsF<{Lptsu5aiI&kHBh&j;{zbIdlv;j`AEj{16Bl z+7W}m>Y*Le5oj9Pk$oI~Tr!3Tn+LereR$-%c2EuyS5%YP&&Xg3av) z+yq4@b3`oP!C(!9(QjV!UWveaxmD+&QN#)AZCrLVorEn*ee5bvs%Z+-$kd^`{({jv z|ANn#Mi7evp+ok>kjhb39cI8}MAN6INfGZcBZvKICaJ|zKHNO{!T-<9v54x;5VG0M zKSPk6HgV<94oak%lK0Ok!1ald_KY4&m7netSK3b~Hk0kYxjIdXTDJUj2X2T!_5Ft; zfpIeptzKU0g457$*+gQLBb>Et)9Qaub4_B4GkKp`X~f^^ys*D(Qd3XWbLcVax=6== ze>cRIzt;g88z%NSqq9ZO)JTPRz($9?)oZ+*|E&jv4r5lON%b?K^`06lJwk0?c5*Pj zkeb^pqh6_HR0e{-!0;Tg_fq%YPT?3J8i#C}ai?ysTXqFokx16-FA69ebO z|9<`B8C^VWHtC>X5`s>{bQ!esu!@kvc2VN*)WS=$im~-w_3&tyo&rC~;L$ouphyL0 z;m4h}>WG1O= zX=y!+%82K#u!XS0zd8DiIQZJu3@Qrv@B{}Vw%5K2w-1T#CS%vDE zUHOM|j~k}#qdqh5SYPsbwXK;UpFvl%%kb;f)(A&eiF)k?1vqW3-Z|&B&LFqYOr2^>xbrz|2Y2^dKt3 z&f4_rg@=zA{88Mnbpgy=8AZJ8gsPQk-r){cThO5bt-wGY79(n8SFG=$ z1nhX;7e{a^>=NYX`Vg2849Z>QyfpenwVBxABH$YcO?K)F6%z7@gw45r)(#i*J~wC8 z@!u#?11`ZQx#`5ZOK`+0ZxfigDo{G>vX1CY)=Sc)O}S#xW$1KjG6)1l^Ji8AJn^PW z-LKIvE9TOKOG%ezUYdJp@g*S^fDH@=U}6OCBWR+d;RNpclY^auCkF@6)rc-;pInGB z1u6{tp}WTyrpOh-i{kfYvg%VGFUg6#jQucek3EpXudCdp7fQ%-4i==6Cp;Xd$M7M^}4DcU@tktJy6FsUb+En^U1qQ6Vv^ULvc{m7GO~E?Cb= z*znvpFhTN0Ay9ai!(gG?aV}OOJjjtj5ymXKCk%^p~P)HaZrzt{LvM zPlLvWSDd17|ukZ)j29n zN}lQB4iDiyrE{x*&7GBtUR9WFHXf5!ZLpOj3(3T8uH5_ZxLGo2<^0MJff+@JR}=DZ zU93E*PaKdd(Zp&fYq)U#u~vR`s-zp(nF?9L=~YxY^s)ntznLRo=dFYL*A6EL0X(iQY_3OW)pHw~b#>(#meC`U~QVJ#O z$BfL{_Ea-&##2gCv9j=bvYte$2A>pM<@Ce^}E?Q&dAsR zxN`Wb=YBW;GsO+;M0>cUjBgl%7)+|iO@po4$>$Yihoqi|T0>c=D{8!Pqo`hIzzJ9Y zC;2?3jpp?_O{Nbr>9I8wRwttz)wd`obYcnsq5z0f@IuYJ&U}NZzBOzDc(CSXpST4X z1VafoH^bn7|INX75k~XQkuV>;M7*-|L%y2^-JV$+E%hsq;>Aat?!+BEor%kIsY=4I-R}D2Rbnv z&PIXw8+b(Nf@n8HyP*PCG%a#ZqvmXlJ4zIzM?GPAjTmJty(7;4k!hrc)#<+{jb`YT zk~^Kl5kfFODt%B*09M!d8bzezK2BT=k2150EUHm^{83gXJpZk?v$S-@6N)AX-Y zDX2YrZmW@(HWgu$?x@#+nr~3?G*o;Nbfc)W=ACjX9kOhWoSNBuLYa;-;iApH0h5*k z+O0_}fnjTae5p}0xj>nN@>bNPQK}6H0j-*wDo}0%k8hq}zGOrTl?hkCzc)t^*|%Zv zmOKL7fel;I?dCl zR$U&Hoa!759DG;RIe6+K6vM=A)1?me)ECyOuyXSv1?&1zj!WS9r^h7qe58;Y$}x1t zl^&Ywv#+*FzM@MVu@z8eQ0fSnv_f_8UWFi+Vb02PHE^*L(2?)oaHQRSPJC0<9OVou zW+gXJxp0#+IF>`?@GeG3$VDGL^^4j@U!jJ+uyqIRYv`IPPGoI5IWddj%+JtcyPtHu zqv=@bv<^_`*k`OQ8dqSep8fCl=I1zTlQ~eL!>T*2)sw!!DS%33?bZV5od6n~;(<3X zp9mV}=`_nI<&XE!R#!h%)6NgHLuO=xNo03#22AcQa7Z}00gd#4)9oTkqB#uTZucJTo!4I_ zLAK^_T*BII?cWGmzVMK_Fy&v*)Ykhg3wg*v%|lp*5NV5j5y+ItOKrIi<92w*9=p%I zDx{@t_c;<2nt|qkJjs9^=I~+Vm2-=&4Aam-%OTSoDR8!#Hb97Ik$Pv?V?`J)sU0^P z9@vp24fA>Q^3rq9Of+)m%B_*|&Ci_v)YE`v&V1^rU#ebp1u1-)w^a4T2Fhr~Zrj6T z?2!XLJWZnkOooL@8#17tgTK`voe5Zxg$O^Xv7QbXp(D@*4d4>gSX`nX-{ynHZP*e3 zxB7q|<|I;zj)lGNL>J`5qF%T(&%q~d!f!PeXgNN%&0M5shf1H(nTz!TjcfE(NUXU_ zMOOw*r{Mm)pjFWcFJZ7hIA;(J2s^&~fMlZiJ zl^@GQ24ns0f6N%GjqOlf(r?;SN5=9Qc2smrkc;eP$Sg|W=inNRJ zVPZjjQ^$kH+;y}?W7ScfpOm9?!sKRltNW+w)(GHdm|`TEF`#Z}7d7<2T)RSKU#Ng7 z-O5%WQpRBFrBDFvcZU*IayW7KG~)P6Nbep?XkWta-Lb^k=TMM8)0CKzA81OH=X1j4 zzss8g;JmdkRO(91w}i=3e=D_Q_$LL5;!tDGf5SZK++maFQRk2Wg=n?N)md?PrfZ*B zZWKtCQk1nuR+&EH5d2*lPnb=BkzgdT`4_knBzk9~fFu*+usbv}^o=7Ru-0kf(XWw_ z3o}kc2hh`b~_QZ*>YTrDj@h+hkBN zt1sktWVgqTfSuGzVv8pXl#L{;NVrJm>F1uX?{4O~lkRe?zPPCaJJS@1ECOEoMHr?I z9`XIZL;g!W4LMn=M{GZrsq5!-HVhts>G=QMtxb1z$apB+GoJYAEu69^bQPX9cr00j ze$g-RJ$P;o&L*sd6p!_v2&rUs06D14;khg)+MGZ&mqk8&%M}pJ(eJTx;uR6_Iaksr zE+rBU+b;i3e#BY5-ueEO{Vr>r5{@`0l;hoRFN%@>EaT2Dhx>BJ-{9jtDblfjc!H7i z0b~lV$J^~9r2g)$>y(wW{2OOaB=iU^~&gva0PyT^RTWyD!N%n90 z0am;M9xtdOH2;G$X?*|@*&?>>}ejGOR2Kzu?DQ8ZG(i8 zUyM-4A-mTfYHi6Vz&e=F11Zz@vQi1v^7?g=-TN$kBvKeH4%tlo4za~Sx`!`mh}jCD zzA)1Mnnzv%JzOAwBpn1&1RR#6Pzw{cN#NXH2u}P~69uJoPRf~0C z;tfwb2ayH)^)tuv-$D4r2zI^C)o-W`ub*M!@{fHHaChYdw}p4Kq`rqEzwOXwE@NkJ zKQm4y3@mG!Vb%lhR>s@jdc}dE7sdKrZ8impzE^EN>~(wyoWASV8hdOA=70^w9P5^b z_d{M)058jJPg_`(v#af4=ef1)&_+c9b@9OF8MSS*zmwxaHYu;|DmJMSK5yH`D_eOC zE;=4S?0nExbo>zC+8@l6)SQ@&w7#|LRWS0@jo~u@5%)vOUzp1;Y!;i8pW0rzHXmKclhQ-ljU8j1OxLlAh7{&8%eX3a$(e=I1BmugLd_^@&}9 zu>AZ(NmSe584I4%3`ucS(ee6jmsMD0H1aN(VQ*RIBqYJI zT@_akD#=ABhD+F+$lo3|(E`AwxiGt9JdxtiR@0G*6OK#aV5e9hF$WOo@4gpyT6hXe zsRE5ySPFF)JS`$EN~t2v7>m-jn->ysBIho2yc9-Y>2UHTMx@zlQ$f|%iNpSYPcON~ zPIWE4<)Fg>AL;4X^%3|0j}FBTh9WsU$M)45qTXF%K(-A-!hq0_h8SVGQK-**pKp*3 zR4%K6qc4vlI<7*=<$CKs%!K!1fa?Ng65vtL>&gbg2kEC*d|Vx0GeTO=A756HIbRO9 zte~kL#u~5zE8+DkvBZd}(DH|=VXjxTNKX1|GI{ii;_7u&ggo_gW;EPS`Mj0EacS%# zir&eS=x2Zk6NJ=7zjy&ZQNd!i-fuIK3~0N0&MRJ5m3iC_1YouP1h#k#nrY&-2wQR6sJ;{ z=v0bMoM%-0TpcdSWuqh|^#)|YGt=RlR~dTS!kV?y;|1%eLtTg!(z}^NmEVB==Bqlp03uq}6`AV8K2)|yNB4zVJud&-b07O1ep=PTy(73HGRgus4bNan%OGo-{ z0jKS=lk^Jv#0M|)4(9O>3M~&>SXK%*{&4GHm+irB+k*z%gFUtfui75GW_$3uEsHOD zP-WWd$nedMPp>W+{8K`H=+S0I?a`9M^c)$a=W6*95|R4(d*Bb(U2Oy?6-DWySFr0m z|APO!9ynxsBBj!6&;;1Aeif4eiaLXVHzMrE&V5`XtPdaHlXH8tmEntjY+HR}9PYGG zT6zkdyt1pfXLjO32uA2j+3ftbGdF8-;!O)&a;w@Y-HO(vS<%WM2RAx|Ert`5OEq@M zaLDb;JYT#FKDhmXmn|r3Gu~N`6WcDfO}rb4^OlOr;I@0DZ^}vxsLUqm>}UbYZ=iD# zmwm@iM8QQ{AwfEeU4E#DrK~dz5XG)I->3Od#O0#83*I; z#|%yKDx>&nnJ*BeOHnYIoKK$o0n+!=iM8LtXZNEB;vRH;5H;S_r=q_5nQOTLc{Hxp zu(K!E{IjtLnp>8^`KycJvem^^S;$O_jI?ZsWf^7A47V&pb|=? z*G`>jLLm!CjSkjcjHr$0A4=SEs^%m9jqOX=a!;~UtNNJ_~dsTA~i`_8*?r~gNov4@h>t~9&K#?Jdx!$TVd36)8bhJ+39 zOK%KcI1{XbF%SPXZxQj;)_Ddv;gPq+=5;;PDzz0(!xfL_NL?%B14C==nPUckwVH{V zzRc7$UyP{SITl`!%xp6KXQ8VRU4BQ{t@|1d%3WGmn(|f`GS!MHEsL5f>6uLv^m+r8 z(RRCKtA1wFwze@RW;TsKp($1EMu>GA!%<(NlQ%qGD}lyI_RGN7U_Ee1+dY23*< zZFTav(_N+PXrNeldKH`ol-Z|eHf^|CqTF^mOV4Acpe?lcag-MiX;$dWVyhcw+i}iH_lcm-hU@+&==0%OdUw_g?2zTdv}gGO z4Zp-ywgTRGw!&MJ4`8rN84y8-L?8#ZE+~Q?8KLXN=&%UpzBL8Yo+p}VVyUWhxbOK) zVz&&we(uL3*)`C<&q-{%_dyX!3y0H1!)c)pUF1U-`{>4Cbm8ziNzr(a50m>Ma3{E< zFK);uU2g!L8K}F1(S2k?AT<`iuD%cvy@F(eC|1KO#d<-_O~^FruXB>Rn$)s&0|x9HU2x@?@z^3e%!I@^bS=0j)tHf-OwR(1oU zvxn30`xoQ*bnb8+{PV?V3wll6#C=<2`8pW(^DaT1U!`e~n}0@wY_-RJ&ob!uQcipe zVav-DkA_!nv{MQo&npuUDK@gn$dZfEMH6BEmroA=T zH0|F7o2ES?1Wh^(OJBQLWERNhhS%*V*a-Enr;IffEC@6eEDY2Y^XQ^LQ*k~_(;|1} zBWB26Q>%(f&ejwLXX)e6V&uVLPtvK`IvDz9mY~_{%{O2T1aBg(nTbG22Ga*am>M)^ zoo~X(N$iM`G-a#tv7)Om-4KF)77R0WH?5DWbYls6+W5LPP}CnN%D8izTFA;q$kxCK z{c8l8tR@R80XFrI@zec*(I?00gg6}?t5H^MGL826afepNM zXut?$$Gr8E-sg+goxdnPEGRy(e9ZUq!{#t?45-QM$_F+V#kvttPPs9q6~h4?dHygT z))ya;A2x#}#T9A>U4_cIUHN@txOOz4A|Xq8mv!qCMuXzh>Ov~JK~@q3Oi#0pOUk3J zAl6%aR`2p5UmST}znqF-g6cLcDyKq_6*8<&rikduXE0C^YT3g4T=Gz`& zpXc$$%`Jjs{uw*LYkpCkEEM$F9ds4biw11YXy*8pdjix?qy@G7<3lWVhj;#ov|-k7K)M<{NlD&GHuXcNF9(HK&J7A< zXS>4FUt)4H1&F7GmQa??ASAS;syVk7c_}58BW|2>zMu`ipq+j}JL95u`9*De`m`sC zbBDC-cKP=b@w!Vn-8lww+eIxh-LIuoSj2`NyT6;T8r_pi$TfzJb>g5a?2hPTx5QCb z;QW8di9x=J2WdEH2eiLZ(GMWy{-!q%ChN{I@ITfNu^PI)X21?Sc&hM*b^% zFxl|C(F{EdMj8GGN0ZvOedg;NxCkYH%X_Z`IB_n$jhq3Z9%It3&k&V zvldQIz7M>tby-!A^_C&*v3dhbw@keZR}AhWVu!;ogTr|iJAYS^c(S8M#9b-|%IcTa zVUf6q5Mcz26RD*5EFx8;`VkK%c3QOKI39o#8?4!20)J0z6SHC-?ieR=1jxK>tq;{~ zjw(Y@HNlqU^^-p28!hyqAM#_^nU>|xJG?L9Up8w zLFz55%2azXqgQ>S+CyA+cW3}|Jei8=)0!HQ^}NfF2k?M~)NZEI3`h`Z3b;kKHKSjr z&wza=SMJq$w3Q9z_2X)g#}PAfwUroI1^lQSwndB)f!{mpznG{&aA7;TF0=CX81Ud;f7>(cX%0_ zH?oX%ob#sIT0hP-Jmc7a>2KIIW_W<_a05F!s=P8hrR6~?Dvh-02)$|O-Q5@jOo5z` z$YM{K;lmtuWtG+YeaLrNAB7yQwy+RR3S)mW!xLR51W+x}?-Ed3C!|S{z2%U=O9scT zX4t6$+;^PgT}2*P&dyFQrxwHDQ78!4YL?Vw6b5MqGozPYI7`~3x0of>gyH#!HHr`k zqep>sP;!$+f*DSdt}_RBGp`SrAw#RqygJQR{LhX5-1FmZ9!mB6O=GpZlycX**&jMY zTFanl$=Sp95tpb>byjZGbWc1+s3pN{zBxXD*m9ITZ;sD*F*7z6M2P>o*;p__(u-mb z#8?xDiOr2{m=GUj`PWUC<$dx#iP+4@t`*`_h($*Bgb>g7`{9nZB?Lz{PJ6wZECL-m zn^AnmSHxPL-a1N%pUny#;H8G%W-~1CMMT;N_LK$AM4h~)`{$zFK`cRSJKP?8|LI`- zu$K5?#!otm#uC^hZ+mbd9(l{n2c{Zq1|}OUjNyHDYX2x!D#G1}?2)WmgwG~+TC%^3 za1SEdinX=GjfC9DKDWdrMCM&~x)r{Q;Qz>8v%+VKcisCn5+8VP3dKN88?c7%$`Qak z`dt$WAbKxGrQ)seMAva6EC7mR!iyPfwzSL=XOn!;aUS1M&Q@FF-n@uiwF814yT6J-H;ViiHVm0hLPrb1-%TPBvK!DtCS`D9tWVq#be}zMgV&C< z8F{V!&v%`Q4sz$!1w+k2yO)DGV7EBewVSy%UeM*}wi|cX4~>(?W~|G;y7lwhj0m>E z77ryRyR#Q;@$R7XK)jQ4u)8B#fepSU72C>#S)_li<2c5B4t9{3prz3mMXy$k3e}4VCyBqYM z=?GZS%U-s}LqmgSms0_(S2}=BLWWw{4VY{Xju3Vs0?#?)JpMbq}#9Sro zH3Z+uTblHRJvampb=>5$i2P_ad?@PdEKhdvP<$27W5ac}XDA+P6S|ygc3Mf9E2i#UmQ~(9 z)Di!SM{JE_tzGeYV%Tf;xGNq>m|^T2SDYr&6M)h8S;- z&vF!j15RQ4sU?-mNO=uroU8vl;6ISY;v*=^U9)fB`SFh!_>SPrb7kIk9DG4%$st9K&$qLj44! zH@xPRhc&NYsZp#XOF@;hD=2oCf{Lz_)x;o8CyI0}s#SZ;R;ZUPQK+XcVXyh(uED>X?Ghp!n)6ZHWVJJ6s%OSHu0?95BGG8IL4WR;sOVa zxH>tgNIrnG-+seB_rt@y9AocN0}b)fcjf6Uw3F4FBQIKNI;*n}&~LXoz=rzcYpo|* zA5abm#LfGg=i47(8~pK!_G5t#mGjvDU$s^&wuk-fkFO!NN3*#B__CO6_X7&2fGoy< zz9=+kds**`$1IU5(`s_(qTA>7z};7&K;LcX3n;8XR+X0}=jbv%J8dp&7Ko1$Op{RT zREPGsK%B-$v-4v*DMD>amQYyJ{2gE+2(da$5p4Lz$0{>(6p&)cjti}-x3;mxFni2l zsH5gvK^cn&;{m*c_4RB>Fur;s0eB;u)eDk4D_k}<(`Ho|#(D&OK+!5z);5@CGVj-8 zm@~E?b8*EmH_RPt2w3o<2J`dBDg)TSpvshpbM5zn@m4(4cZY(iasX4Z{!w69O-0zB zR4ot8&qjxuAJn_YYL$&*3_Go6s8d(BxVEuvq4+RIjbyy`K*-RRYH%4~=y&4%_OaUb zSE0BYPV5R{iE!MPm>kv~7>>K(f}mAY!&riy5`nikc`n_LEZKEFpeFBgZoTls^H&n} zB)4|a2s{wyjg2j1$Be`Sc?ni!Z1zaJh3IW$?IZC8gfM_z6N&o{Mc+c?N(!)!Ec1L* zypeGdyLdWVABl(hAZ36=xyYAb&=34#@ELgVSu<~Qkuo<%!g2aJ_4OMaGofSK@1i5 z5SpS_hqkR9#iozO;|R3cDn{c{uUo=T_@LbY@s%Jj%nQeGk#KduYSxE8zzW=o*^n{# zJlBvu1JZ|)9I-{(N@r1SZf@pNy_q^Gi#<37H+|N@ZjHj1CMX6h>}IuuZ2jlf!7l=2 zHE6Qsfu;eW__y+w&w>c^${mTC>ynERD442I)TEPQ^k;$CZeO%S9ldbxFlu0X$FugD zvG@ss@C{%W#NxxOa$?Gq$-pzvmL0X0EsVwYm|kT$9^Yr4zmd{pB_C)%JRTp9k8-j9 zs`A4yT#O&uIPq|UiuDYvt@B=~V{<%S(0CvUo*embrzfMP}Wyva(nyA z(D?rL(@XHv_HL`gtK|eqfb~<(RgJK>x5tM^*19>K)2zvFFWZQZ#@!d>U%rkqFneC) zaLnG`4#(}#rnSd3cKr4yn~}_n&cKnE#<*m4`_&PYKj@WXYnX`xLPy)X!FwcOT~C4Uvxe=seLENT_FH$HiIiIXlc-#po*j_n*Eo-7w{&m{=R)dInI~~ OYk%|+{O{Nri~k270uTrQ diff --git a/mystery_example.yml b/mystery_example.yml index 41a46ca6..ab7ffe63 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -22,6 +22,9 @@ vanilla: 0 balanced: 1 random: 1 + bonk_drops: + on: 1 + off: 1 door_shuffle: vanilla: 0 basic: 2 diff --git a/source/item/FillUtil.py b/source/item/FillUtil.py index 9acdb45b..bf48c755 100644 --- a/source/item/FillUtil.py +++ b/source/item/FillUtil.py @@ -792,8 +792,8 @@ trash_items = { 'Bee Trap': 0, 'Rupee (1)': 1, 'Rupees (5)': 1, 'Small Heart': 1, 'Bee': 1, 'Arrows (5)': 1, 'Chicken': 1, 'Single Bomb': 1, 'Rupees (20)': 2, 'Small Magic': 2, - 'Bombs (3)': 3, 'Arrows (10)': 3, 'Bombs (10)': 3, - 'Big Magic': 4, 'Red Potion': 4, 'Blue Shield': 4, 'Rupees (50)': 4, 'Rupees (100)': 4, + 'Bombs (3)': 3, 'Arrows (10)': 3, 'Bombs (10)': 3, 'Apples': 3, + 'Fairy': 4, 'Big Magic': 4, 'Red Potion': 4, 'Blue Shield': 4, 'Rupees (50)': 4, 'Rupees (100)': 4, 'Rupees (300)': 5, 'Piece of Heart': 17 } From db15fdfbdc81dfcb887987bf5b4592f4f55af184 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 13:49:28 -0500 Subject: [PATCH 07/29] Shifted AddReceivedItemExpanded data table down, will affect people patching itemgfx --- Rom.py | 2 +- data/base2current.bps | Bin 103920 -> 104024 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 7c43ea9f..7be52c23 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'f76555dcc8cbd0f185fb37eafa3779c3' +RANDOMIZERBASEHASH = '3c8a6a640f2e0e004c8a9e0e72310622' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 9e8c66e6f28d20e47f2a3afbf45daccad2b38606..2ec7b58c91d9d6abce9da52887ff53ffa9c11fc6 100644 GIT binary patch delta 9522 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 delta 9459 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 Date: Sun, 24 Jul 2022 13:56:36 -0500 Subject: [PATCH 08/29] Fixed wrong loot ID for 5 arrows items --- Rom.py | 2 +- data/base2current.bps | Bin 104024 -> 104024 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 7be52c23..2a68ea42 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '3c8a6a640f2e0e004c8a9e0e72310622' +RANDOMIZERBASEHASH = '603d2b84ca1c96fd47f5bba83a0c688c' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2ec7b58c91d9d6abce9da52887ff53ffa9c11fc6..cc8b89d84f68d6a875e5e04cc5e93c123dae31fc 100644 GIT binary patch delta 38 ucmcbyhV8~0whf7l%)y`5Y))a^>CCvbS0NMZ8tOnSu2C!iP16A^>vt$9eLjkjc9!0kvMFBEV2>jz2xgL7t20kATq5uE@ From 58afaa52e8a1cfc6773b41efcfd7abc35b5fdbe7 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 14:56:25 -0500 Subject: [PATCH 09/29] Fixed issue with bonk prize on screen 2B --- Rom.py | 2 +- data/base2current.bps | Bin 104024 -> 104010 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 2a68ea42..0acf2ad8 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '603d2b84ca1c96fd47f5bba83a0c688c' +RANDOMIZERBASEHASH = '528840ac74c94330e8bb70ce6d96161e' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index cc8b89d84f68d6a875e5e04cc5e93c123dae31fc..795be7ea926e1e80dc6fbde6d2e386a51d5c9775 100644 GIT binary patch delta 8612 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 delta 8572 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 QXMp(WL0d*YKYh*r0Z82coB#j- From a97ee6c57a776a6fbc4b233ab8234f6d20d7dd4d Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 16:19:26 -0500 Subject: [PATCH 10/29] Implemented Bonk Drop Shuffle --- Fill.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Fill.py b/Fill.py index fe9cbcf9..80da0109 100644 --- a/Fill.py +++ b/Fill.py @@ -471,7 +471,7 @@ def calc_trash_locations(world, player): total_count, gt_count = 0, 0 for loc in world.get_locations(): if (loc.player == player and loc.item is None - and (loc.type not in {LocationType.Pot, LocationType.Drop, LocationType.Normal} or not loc.forced_item) + and (loc.type not in {LocationType.Bonk, LocationType.Pot, LocationType.Drop, LocationType.Normal} or not loc.forced_item) and (loc.type != LocationType.Shop or world.shopsanity[player]) and loc.parent_region.dungeon): total_count += 1 @@ -482,18 +482,22 @@ def calc_trash_locations(world, player): def ensure_good_pots(world, write_skips=False): for loc in world.get_locations(): - # convert Arrows 5 and Nothing when necessary - if (loc.item.name in {'Arrows (5)', 'Nothing'} + # # convert Arrows 5 when necessary + # if (loc.item.name in {'Arrows (5)'} + # and loc.type not in [LocationType.Pot, LocationType.Bonk]): + # loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.item.player) + # convert Nothing when necessary + if (loc.item.name in {'Nothing'} and (loc.type != LocationType.Pot or loc.item.player != loc.player)): loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.item.player) - # can be placed here by multiworld balancing or shop balancing - # change it to something normal for the player it got swapped to - elif (loc.item.name in {'Chicken', 'Big Magic'} - and (loc.type != LocationType.Pot or loc.item.player != loc.player)): - if loc.type == LocationType.Pot: - loc.item.player = loc.player - else: - loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.player) + # # can be placed here by multiworld balancing or shop balancing + # # change it to something normal for the player it got swapped to + # elif (loc.item.name in {'Chicken', 'Big Magic'} + # and (loc.type != LocationType.Pot or loc.item.player != loc.player)): + # if loc.type == LocationType.Pot: + # loc.item.player = loc.player + # else: + # loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.player) # do the arrow retro check if world.retro[loc.item.player] and loc.item.name in {'Arrows (5)', 'Arrows (10)'}: loc.item = ItemFactory('Rupees (5)', loc.item.player) From 9ef8f54e5bed89713e625cd1de330d1457c0c1c3 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 16:21:21 -0500 Subject: [PATCH 11/29] Added Multiworld Support for Bonk Drops --- ItemList.py | 2 +- MultiClient.py | 14 ++++++-- Regions.py | 91 ++++++++++++++++++++++++++------------------------ Rules.py | 2 +- 4 files changed, 61 insertions(+), 48 deletions(-) diff --git a/ItemList.py b/ItemList.py index 7350ff9a..fdcf5412 100644 --- a/ItemList.py +++ b/ItemList.py @@ -507,7 +507,7 @@ def create_dynamic_shop_locations(world, player): def create_dynamic_bonkdrop_locations(world, player): from Regions import bonk_prize_table - for bonk_location, (_, _, _, region_name, hint_text) in bonk_prize_table.items(): + for bonk_location, (_, _, _, _, region_name, hint_text) in bonk_prize_table.items(): region = world.get_region(region_name, player) loc = Location(player, bonk_location, 0, region, hint_text) loc.type = LocationType.Bonk diff --git a/MultiClient.py b/MultiClient.py index fbde673d..fd0e8b4f 100644 --- a/MultiClient.py +++ b/MultiClient.py @@ -929,14 +929,22 @@ async def track_locations(ctx : Context, roomid, roomdata): ow_unchecked = {} for location, screenid in location_table_ow.items(): if location not in ctx.locations_checked: - ow_unchecked[location] = screenid + ow_unchecked[location] = (screenid, 0x40) + ow_begin = min(ow_begin, screenid) + ow_end = max(ow_end, screenid + 1) + from Regions import bonk_prize_table + from OWEdges import OWTileRegions + for location, (_, flag, _, _, region_name, _) in bonk_prize_table.items(): + if location not in ctx.locations_checked: + screenid = OWTileRegions[region_name] + ow_unchecked[location] = (screenid, flag) ow_begin = min(ow_begin, screenid) ow_end = max(ow_end, screenid + 1) if ow_begin < ow_end: ow_data = await snes_read(ctx, SAVEDATA_START + 0x280 + ow_begin, ow_end - ow_begin) if ow_data is not None: - for location, screenid in ow_unchecked.items(): - if ow_data[screenid - ow_begin] & 0x40 != 0: + for location, (screenid, flag) in ow_unchecked.items(): + if ow_data[screenid - ow_begin] & flag != 0: new_check(location) if not all([location in ctx.locations_checked for location in location_table_npc.keys()]): diff --git a/Regions.py b/Regions.py index af3c13ef..9e6f18ac 100644 --- a/Regions.py +++ b/Regions.py @@ -1266,52 +1266,55 @@ def pot_address(pot_index, super_tile): return 0x7f6018 + super_tile * 2 + (pot_index << 24) -# bonk location: record id, aga required, default item, region, hint text +# bonk location: record id, OW flag bitmask, aga required, default item, region, hint text bonk_prize_table = { - 'Lost Woods Hideout Tree': (0x00, False, '', 'Lost Woods East Area', 'in a tree'), - 'Death Mountain Bonk Rocks': (0x01, False, '', 'East Death Mountain (Top East)', 'encased in stone'), - 'Mountain Entry Pull Tree': (0x02, False, '', 'Mountain Entry Area', 'in a tree'), - 'Mountain Entry Southeast Tree': (0x03, False, '', 'Mountain Entry Area', 'in a tree'), - 'Lost Woods Pass West Tree': (0x04, False, '', 'Lost Woods Pass West Area', 'in a tree'), - 'Kakariko Portal Tree': (0x05, False, '', 'Lost Woods Pass East Top Area', 'in a tree'), - 'Fortune Bonk Rocks': (0x06, False, '', 'Kakariko Fortune Area', 'in a tree'), - 'Kakariko Pond Tree': (0x07, True, '', 'Kakariko Pond Area', 'in a tree'), - 'Bonk Rocks Tree': (0x08, True, '', 'Bonk Rock Ledge', 'in a tree'), - 'Sanctuary Tree': (0x09, False, '', 'Sanctuary Area', 'in a tree'), - 'River Bend West Tree': (0x0a, True, '', 'River Bend Area', 'in a tree'), - 'River Bend East Tree': (0x0b, False, '', 'River Bend East Bank', 'in a tree'), - 'Blinds Hideout Tree': (0x0c, False, '', 'Kakariko Area', 'in a tree'), - 'Kakariko Welcome Tree': (0x0d, False, '', 'Kakariko Area', 'in a tree'), - 'Forgotten Forest Southwest Tree': (0x0e, False, '', 'Forgotten Forest Area', 'in a tree'), - 'Forgotten Forest Central Tree': (0x0f, False, '', 'Forgotten Forest Area', 'in a tree'), - #'Forgotten Forest Southeast Tree': (0x??, False, '', 'Forgotten Forest Area', 'in a tree'), - 'Hyrule Castle Tree': (0x10, False, '', 'Hyrule Castle Courtyard', 'in a tree'), - 'Wooden Bridge Tree': (0x11, False, '', 'Wooden Bridge Area', 'in a tree'), - 'Eastern Palace Tree': (0x12, True, '', 'Eastern Palace Area', 'in a tree'), - 'Flute Boy South Tree': (0x13, True, '', 'Flute Boy Area', 'in a tree'), - 'Flute Boy East Tree': (0x14, True, '', 'Flute Boy Area', 'in a tree'), - 'Central Bonk Rocks Tree': (0x15, False, '', 'Central Bonk Rocks Area', 'in a tree'), - 'Tree Line Tree 2': (0x16, True, '', 'Tree Line Area', 'in a tree'), - 'Tree Line Tree 4': (0x17, True, '', 'Tree Line Area', 'in a tree'), - 'Flute Boy Approach South Tree': (0x18, False, '', 'Flute Boy Approach Area', 'in a tree'), - 'Flute Boy Approach North Tree': (0x19, False, '', 'Flute Boy Approach Area', 'in a tree'), - 'Dark Lumberjack Tree': (0x1a, False, '', 'Dark Lumberjack Area', 'in a tree'), - 'Dark Fortune Bonk Rocks (Drop 1)': (0x1b, False, '', 'Dark Fortune Area', 'encased in stone'), - 'Dark Fortune Bonk Rocks (Drop 2)': (0x1c, False, '', 'Dark Fortune Area', 'encased in stone'), - 'Dark Graveyard West Bonk Rocks': (0x1d, False, '', 'Dark Graveyard Area', 'encased in stone'), - 'Dark Graveyard North Bonk Rocks': (0x1e, False, '', 'Dark Graveyard North', 'encased in stone'), - 'Dark Graveyard Tomb Bonk Rocks': (0x1f, False, '', 'Dark Graveyard North', 'encased in stone'), - 'Qirn Jump West Tree': (0x20, False, '', 'Qirn Jump Area', 'in a tree'), - 'Qirn Jump East Tree': (0x21, False, '', 'Qirn Jump East Bank', 'in a tree'), - 'Dark Witch Tree': (0x22, False, '', 'Dark Witch Area', 'in a tree'), - 'Pyramid Tree': (0x23, False, '', 'Pyramid Area', 'in a tree'), - 'Palace of Darkness Tree': (0x24, False, '', 'Palace of Darkness Area', 'in a tree'), - 'Dark Tree Line Tree 2': (0x25, False, '', 'Dark Tree Line Area', 'in a tree'), - 'Dark Tree Line Tree 3': (0x26, False, '', 'Dark Tree Line Area', 'in a tree'), - 'Dark Tree Line Tree 4': (0x27, False, '', 'Dark Tree Line Area', 'in a tree'), - 'Hype Cave Statue': (0x28, False, '', 'Hype Cave Area', 'encased in stone') + 'Lost Woods Hideout Tree': (0x00, 0x10, False, '', 'Lost Woods East Area', 'in a tree'), + 'Death Mountain Bonk Rocks': (0x01, 0x10, False, '', 'East Death Mountain (Top East)', 'encased in stone'), + 'Mountain Entry Pull Tree': (0x02, 0x10, False, '', 'Mountain Entry Area', 'in a tree'), + 'Mountain Entry Southeast Tree': (0x03, 0x08, False, '', 'Mountain Entry Area', 'in a tree'), + 'Lost Woods Pass West Tree': (0x04, 0x10, False, '', 'Lost Woods Pass West Area', 'in a tree'), + 'Kakariko Portal Tree': (0x05, 0x08, False, '', 'Lost Woods Pass East Top Area', 'in a tree'), + 'Fortune Bonk Rocks': (0x06, 0x10, False, '', 'Kakariko Fortune Area', 'in a tree'), + 'Kakariko Pond Tree': (0x07, 0x10, True, '', 'Kakariko Pond Area', 'in a tree'), + 'Bonk Rocks Tree': (0x08, 0x10, True, '', 'Bonk Rock Ledge', 'in a tree'), + 'Sanctuary Tree': (0x09, 0x08, False, '', 'Sanctuary Area', 'in a tree'), + 'River Bend West Tree': (0x0a, 0x10, True, '', 'River Bend Area', 'in a tree'), + 'River Bend East Tree': (0x0b, 0x08, False, '', 'River Bend East Bank', 'in a tree'), + 'Blinds Hideout Tree': (0x0c, 0x10, False, '', 'Kakariko Area', 'in a tree'), + 'Kakariko Welcome Tree': (0x0d, 0x08, False, '', 'Kakariko Area', 'in a tree'), + 'Forgotten Forest Southwest Tree': (0x0e, 0x10, False, '', 'Forgotten Forest Area', 'in a tree'), + 'Forgotten Forest Central Tree': (0x0f, 0x08, False, '', 'Forgotten Forest Area', 'in a tree'), + #'Forgotten Forest Southeast Tree': (0x??, 0x04, False, '', 'Forgotten Forest Area', 'in a tree'), + 'Hyrule Castle Tree': (0x10, 0x10, False, '', 'Hyrule Castle Courtyard', 'in a tree'), + 'Wooden Bridge Tree': (0x11, 0x10, False, '', 'Wooden Bridge Area', 'in a tree'), + 'Eastern Palace Tree': (0x12, 0x10, True, '', 'Eastern Palace Area', 'in a tree'), + 'Flute Boy South Tree': (0x13, 0x10, True, '', 'Flute Boy Area', 'in a tree'), + 'Flute Boy East Tree': (0x14, 0x08, True, '', 'Flute Boy Area', 'in a tree'), + 'Central Bonk Rocks Tree': (0x15, 0x10, False, '', 'Central Bonk Rocks Area', 'in a tree'), + 'Tree Line Tree 2': (0x16, 0x10, True, '', 'Tree Line Area', 'in a tree'), + 'Tree Line Tree 4': (0x17, 0x08, True, '', 'Tree Line Area', 'in a tree'), + 'Flute Boy Approach South Tree': (0x18, 0x10, False, '', 'Flute Boy Approach Area', 'in a tree'), + 'Flute Boy Approach North Tree': (0x19, 0x08, False, '', 'Flute Boy Approach Area', 'in a tree'), + 'Dark Lumberjack Tree': (0x1a, 0x10, False, '', 'Dark Lumberjack Area', 'in a tree'), + 'Dark Fortune Bonk Rocks (Drop 1)': (0x1b, 0x10, False, '', 'Dark Fortune Area', 'encased in stone'), + 'Dark Fortune Bonk Rocks (Drop 2)': (0x1c, 0x08, False, '', 'Dark Fortune Area', 'encased in stone'), + 'Dark Graveyard West Bonk Rocks': (0x1d, 0x10, False, '', 'Dark Graveyard Area', 'encased in stone'), + 'Dark Graveyard North Bonk Rocks': (0x1e, 0x08, False, '', 'Dark Graveyard North', 'encased in stone'), + 'Dark Graveyard Tomb Bonk Rocks': (0x1f, 0x04, False, '', 'Dark Graveyard North', 'encased in stone'), + 'Qirn Jump West Tree': (0x20, 0x10, False, '', 'Qirn Jump Area', 'in a tree'), + 'Qirn Jump East Tree': (0x21, 0x08, False, '', 'Qirn Jump East Bank', 'in a tree'), + 'Dark Witch Tree': (0x22, 0x10, False, '', 'Dark Witch Area', 'in a tree'), + 'Pyramid Tree': (0x23, 0x10, False, '', 'Pyramid Area', 'in a tree'), + 'Palace of Darkness Tree': (0x24, 0x10, False, '', 'Palace of Darkness Area', 'in a tree'), + 'Dark Tree Line Tree 2': (0x25, 0x10, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Dark Tree Line Tree 3': (0x26, 0x08, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Dark Tree Line Tree 4': (0x27, 0x04, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Hype Cave Statue': (0x28, 0x10, False, '', 'Hype Cave Area', 'encased in stone') } +bonk_table_by_location_id = {0x153B00+(data[0]*6)+3: name for name, data in bonk_prize_table.items()} +bonk_table_by_location = {y: x for x, y in bonk_table_by_location_id.items()} + # (room_id, type, shopkeeper, custom, locked, [items]) # item = (item, price, max=0, replacement=None, replacement_price=0) @@ -1662,5 +1665,7 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int} lookup_id_to_name.update(shop_table_by_location_id) +lookup_id_to_name.update(bonk_table_by_location_id) lookup_name_to_id = {name: data[0] for name, data in location_table.items() if type(data[0]) == int} lookup_name_to_id.update(shop_table_by_location) +lookup_name_to_id.update(bonk_table_by_location) diff --git a/Rules.py b/Rules.py index 9619c897..ffa8374f 100644 --- a/Rules.py +++ b/Rules.py @@ -827,7 +827,7 @@ def default_rules(world, player): if world.shuffle_bonk_drops[player]: if world.get_region('Big Bomb Shop', player).entrances: # just some location that is placed late in the ER algorithm, prevent standard rules from applying when trying to search reachability in the overworld from Regions import bonk_prize_table - for location_name, (_, aga_required, _, _, _) in bonk_prize_table.items(): + for location_name, (_, _, aga_required, _, _, _) in bonk_prize_table.items(): loc = world.get_location(location_name, player) set_rule(loc, lambda state: (state.can_collect_bonkdrops(player)) and (not aga_required or state.has_beaten_aga(player))) add_bunny_rule(loc, player) From 3983bf347fbf16af032331d7fc4291f291d601b4 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 20:57:58 -0500 Subject: [PATCH 12/29] Fixed Namespace error in Mystery with Bonk Drop option --- Mystery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mystery.py b/Mystery.py index 60a3f064..1a02d10d 100644 --- a/Mystery.py +++ b/Mystery.py @@ -174,7 +174,7 @@ def roll_settings(weights): ret.ow_whirlpool = get_choice('whirlpool_shuffle') == 'on' overworld_flute = get_choice('flute_shuffle') ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla' - ret.shuffle_bonk_drops = get_choice('bonk_drops') == 'on' + ret.bonk_drops = get_choice('bonk_drops') == 'on' entrance_shuffle = get_choice('entrance_shuffle') ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla' overworld_map = get_choice('overworld_map') From e1cc74c05c9a53dac751ee1a67043c3658b7e0e2 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 21:27:40 -0500 Subject: [PATCH 13/29] Suppressing meta output if outputting spoiler --- Main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Main.py b/Main.py index 2ac286bf..d3d0b3d3 100644 --- a/Main.py +++ b/Main.py @@ -160,7 +160,7 @@ def main(args, seed=None, fish=None): if args.create_spoiler and not args.jsonout: logger.info(world.fish.translate("cli", "cli", "create.meta")) world.spoiler.meta_to_file(output_path(f'{outfilebase}_Spoiler.txt')) - if args.mystery and not args.suppress_meta: + if args.mystery and not (args.suppress_meta or args.create_spoiler): world.spoiler.mystery_meta_to_file(output_path(f'{outfilebase}_meta.txt')) for player in range(1, world.players + 1): @@ -359,7 +359,7 @@ def main(args, seed=None, fish=None): with open(output_path('%s_multidata' % outfilebase), 'wb') as f: f.write(multidata) - if args.mystery and not args.suppress_meta: + if args.mystery and not (args.suppress_meta or args.create_spoiler): world.spoiler.hashes_to_file(output_path(f'{outfilebase}_meta.txt')) elif args.create_spoiler and not args.jsonout: world.spoiler.hashes_to_file(output_path(f'{outfilebase}_Spoiler.txt')) From 79448be9d4c7c756af60c67c101188c8322a8632 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 21:35:47 -0500 Subject: [PATCH 14/29] Fixed error with pot rule in OWR accessibility check --- Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index ffa8374f..36bbfafe 100644 --- a/Rules.py +++ b/Rules.py @@ -356,7 +356,7 @@ def global_rules(world, player): # byrna could work with sufficient magic set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) loc = world.get_location('Misery Mire - Spikes Pot Key', player) - if loc.pot.x == 48 and loc.pot.y == 28: # pot shuffled to spike area + if loc.pot is not None and loc.pot.x == 48 and loc.pot.y == 28: # pot shuffled to spike area set_rule(loc, lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) set_rule(world.get_entrance('Mire Left Bridge Hook Path', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('Mire Tile Room NW', player), lambda state: state.has_fire_source(player)) From b877ddb4d74a6e535d14c4d3702cd4c241a573c9 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 21:49:28 -0500 Subject: [PATCH 15/29] Making file output prefix always OR --- Main.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Main.py b/Main.py index d3d0b3d3..6241a830 100644 --- a/Main.py +++ b/Main.py @@ -139,10 +139,7 @@ def main(args, seed=None, fish=None): world.player_names[player].append(name) logger.info('') - if world.owShuffle[1] != 'vanilla' or world.owCrossed[1] not in ['none', 'polar'] or world.owMixed[1] or world.owWhirlpoolShuffle[1] or world.owFluteShuffle[1] != 'vanilla' or str(args.outputname).startswith('M'): - outfilebase = f'OR_{args.outputname if args.outputname else world.seed}' - else: - outfilebase = f'DR_{args.outputname if args.outputname else world.seed}' + outfilebase = f'OR_{args.outputname if args.outputname else world.seed}' for player in range(1, world.players + 1): world.difficulty_requirements[player] = difficulties[world.difficulty[player]] From ce269daa88f8bce50b56b2ff78711e8901ff7279 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 26 Jul 2022 21:06:09 -0500 Subject: [PATCH 16/29] Improvements to Bonk Drop Shuffle - Trees revert color when collected - Fixed issue with sprites getting stuck in rocks --- Rom.py | 2 +- asm/owrando.asm | 6 +++--- data/base2current.bps | Bin 104010 -> 104312 bytes 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rom.py b/Rom.py index 0acf2ad8..cfdfdb02 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '528840ac74c94330e8bb70ce6d96161e' +RANDOMIZERBASEHASH = 'ae56110fe1228423c9d6a6cee361f7ac' class JsonRom(object): diff --git a/asm/owrando.asm b/asm/owrando.asm index 7793ce2d..b5dc88f1 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -1340,9 +1340,9 @@ db $2e, $b4, $08, $b0, $00, $20 db $32, $29, $10, $42, $00, $20 db $32, $9a, $08, $b2, $00, $20 db $42, $66, $10, $b2, $00, $20 -db $51, $08, $10, $b2, $00, $00 -db $51, $09, $08, $b2, $00, $00 -db $54, $b5, $10, $27, $00, $00 +db $51, $08, $10, $b2, $00, $04 +db $51, $09, $08, $b2, $00, $04 +db $54, $b5, $10, $27, $00, $14 db $54, $ef, $08, $b2, $00, $08 db $54, $b9, $04, $36, $00, $00 db $55, $aa, $10, $b0, $00, $20 diff --git a/data/base2current.bps b/data/base2current.bps index 795be7ea926e1e80dc6fbde6d2e386a51d5c9775..3bfea7f1aee535c575f86e68eed66a3a9828780c 100644 GIT binary patch delta 6638 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 MzPVLV@~-*60Ce?vyZ`_I delta 6421 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 z Date: Tue, 26 Jul 2022 22:57:42 -0500 Subject: [PATCH 17/29] Fixed Aga rules on Bonk Locations? --- Rules.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Rules.py b/Rules.py index 36bbfafe..7e020507 100644 --- a/Rules.py +++ b/Rules.py @@ -829,7 +829,10 @@ def default_rules(world, player): from Regions import bonk_prize_table for location_name, (_, _, aga_required, _, _, _) in bonk_prize_table.items(): loc = world.get_location(location_name, player) - set_rule(loc, lambda state: (state.can_collect_bonkdrops(player)) and (not aga_required or state.has_beaten_aga(player))) + if not aga_required: + set_rule(loc, lambda state: state.can_collect_bonkdrops(player)) + else: + set_rule(loc, lambda state: state.can_collect_bonkdrops(player) and state.has_beaten_aga(player)) add_bunny_rule(loc, player) # Entrance Access From fb064b595033b99a9fe53d30827ee96e81ea1438 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 27 Jul 2022 08:24:34 -0500 Subject: [PATCH 18/29] Guarantee Big Magic on non-Aga Bonk Location --- Fill.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Fill.py b/Fill.py index 80da0109..9633da49 100644 --- a/Fill.py +++ b/Fill.py @@ -364,10 +364,11 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None pot_item_pool[player].append(item) break + from Regions import bonk_prize_table for player, magic_pool in pot_item_pool.items(): world.itempool.remove(magic_pool[0]) - pot_locations = [location for location in fill_locations - if location.type == LocationType.Bonk and location.player == player] + pot_locations = [location for location in fill_locations if location.player == player + and location.name in [n for n, (_, _, aga, _, _, _) in bonk_prize_table.items() if not aga]] pot_locations = filter_pot_locations(pot_locations, world) fast_fill_helper(world, magic_pool, pot_locations) pots_used = True From 5ded3be2764bbe5cdb68deeeba6735654d96c9d7 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 27 Jul 2022 18:01:56 -0500 Subject: [PATCH 19/29] Rename Drop Shuffle to Enemy Drop Shuffle in spoiler --- BaseClasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BaseClasses.py b/BaseClasses.py index 4a484834..ab4d536e 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3141,7 +3141,7 @@ class Spoiler(object): outfile.write('Intensity:'.ljust(line_width) + '%s\n' % self.metadata['intensity'][player]) outfile.write('Experimental:'.ljust(line_width) + '%s\n' % yn(self.metadata['experimental'][player])) outfile.write('Dungeon Counters:'.ljust(line_width) + '%s\n' % self.metadata['dungeon_counters'][player]) - outfile.write('Drop Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['dropshuffle'][player])) + outfile.write('Enemy Drop Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['dropshuffle'][player])) outfile.write('Pottery Mode:'.ljust(line_width) + '%s\n' % self.metadata['pottery'][player]) outfile.write('Pot Shuffle (Legacy):'.ljust(line_width) + '%s\n' % yn(self.metadata['potshuffle'][player])) outfile.write('Map Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['mapshuffle'][player])) From ceff7688c4ee7fa739a86cf1b0988064d4771bdf Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 27 Jul 2022 18:02:42 -0500 Subject: [PATCH 20/29] Fixed issue with bonk drops getting enabled in non-bonk drop --- Rom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index cfdfdb02..9ad28cab 100644 --- a/Rom.py +++ b/Rom.py @@ -792,7 +792,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(0x1539A0 + (edge.specialID - 0x80) * 2 if edge.specialEntrance else edge.getAddress() + 0x0e, edge.getTarget()) # patch bonk prizes - if world.shuffle_bonk_drops: + if world.shuffle_bonk_drops[player]: bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, 0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79, 0xE3, 0xE3, 0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3, 0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD] bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A, 0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD, From abdf4cd2588906353118de59119117959d1ffab8 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 28 Jul 2022 16:05:00 -0500 Subject: [PATCH 21/29] ROM Fixes - Fixed Aga2 check on Ganon vulnerability - Fixed disappearing mirror portals in Inverted+CrossedOWR --- Rom.py | 2 +- asm/owrando.asm | 4 +++- data/base2current.bps | Bin 104312 -> 104324 bytes 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index 9ad28cab..37962bc7 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'ae56110fe1228423c9d6a6cee361f7ac' +RANDOMIZERBASEHASH = 'c80605a079983f1a9dac37273e2b377a' class JsonRom(object): diff --git a/asm/owrando.asm b/asm/owrando.asm index b5dc88f1..b1c1ebdf 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -271,7 +271,9 @@ OWMirrorSpriteRestore: OWLightWorldOrCrossed: { lda.l OWMode+1 : and.b #!FLAG_OW_CROSSED : beq + - lda #$00 : rtl + lda.l InvertedMode : beq + + lda #$40 : rtl + + lda #$00 : rtl + jsl OWWorldCheck : rtl } diff --git a/data/base2current.bps b/data/base2current.bps index 3bfea7f1aee535c575f86e68eed66a3a9828780c..d51dc56eb7dc07a6d5483caeaf7dc404c89f27ce 100644 GIT binary patch delta 313 zcmV-90mlCLt_Fm!2C!iP1P0~#8na~q^#%bolUoQj0c*382#Ev%dy^au#TiG5s_H<9 zog$B$pdtd@q?R2=n(Gx-l8Gmi`VB4toU^T9V3+9XZ@RtE0-Mviamzg>NJs4De1Av!tEtH*)Gf;o4YiMYu z3O=DXpDCB_Isv{0p8=f}fCHDYI{_vF8v(c3I{~Kx1)ns54S<)1J^>{Gt+%W`0mN7c LV#=p3rzIpNYR-K$ delta 301 zcmV+|0n+}2uLk(82C!iP1ij}%7_(&o^#%bflUoQj0b;X~2#Ev%a+4el#Th<{s_H<9 zog$B$pdtd@q?R2=n(Gx-l8GLZ`VB4tld~xfR=Ew9ZBLzz@Y;aZn`T6rlZ?l40|pp^ zvdC(152*vG0Ba&Vh^lL^1(V<5mxMS0ClP3YrSJ@;^2tEZ2B`s)s;?E7y*L430T`Db zIRRDyNSAgw0YCu>m$x|qAR%#!%4o^3&;_Y^OgW3mLeK{ySgi(3Qj5tn&<3g57)&{r z_&EWh3*C$Q@RtE0-MviRm!&!ZJs3iM1Av!bEtH*)Gf;o4YiMYu3O=D*pF5ZOIsv`~ zqkozafS0~I0VV<;1GnZo0jB~6n_z$ufC-n9J^>{Gs<*g40mN7cU4gdVpqBo^rz3mE From e218b8dc97de3153e91407d3fb85fd91742788dd Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 28 Jul 2022 19:52:32 -0500 Subject: [PATCH 22/29] Reserving bonk drop slot for Murahdahla tree --- Regions.py | 52 +++++++++++++++++++++--------------------- Rom.py | 2 +- asm/owrando.asm | 45 ++++++++++++++++++++++++++++++++++-- data/base2current.bps | Bin 104324 -> 104324 bytes 4 files changed, 70 insertions(+), 29 deletions(-) diff --git a/Regions.py b/Regions.py index 9e6f18ac..435f7622 100644 --- a/Regions.py +++ b/Regions.py @@ -1284,32 +1284,32 @@ bonk_prize_table = { 'Kakariko Welcome Tree': (0x0d, 0x08, False, '', 'Kakariko Area', 'in a tree'), 'Forgotten Forest Southwest Tree': (0x0e, 0x10, False, '', 'Forgotten Forest Area', 'in a tree'), 'Forgotten Forest Central Tree': (0x0f, 0x08, False, '', 'Forgotten Forest Area', 'in a tree'), - #'Forgotten Forest Southeast Tree': (0x??, 0x04, False, '', 'Forgotten Forest Area', 'in a tree'), - 'Hyrule Castle Tree': (0x10, 0x10, False, '', 'Hyrule Castle Courtyard', 'in a tree'), - 'Wooden Bridge Tree': (0x11, 0x10, False, '', 'Wooden Bridge Area', 'in a tree'), - 'Eastern Palace Tree': (0x12, 0x10, True, '', 'Eastern Palace Area', 'in a tree'), - 'Flute Boy South Tree': (0x13, 0x10, True, '', 'Flute Boy Area', 'in a tree'), - 'Flute Boy East Tree': (0x14, 0x08, True, '', 'Flute Boy Area', 'in a tree'), - 'Central Bonk Rocks Tree': (0x15, 0x10, False, '', 'Central Bonk Rocks Area', 'in a tree'), - 'Tree Line Tree 2': (0x16, 0x10, True, '', 'Tree Line Area', 'in a tree'), - 'Tree Line Tree 4': (0x17, 0x08, True, '', 'Tree Line Area', 'in a tree'), - 'Flute Boy Approach South Tree': (0x18, 0x10, False, '', 'Flute Boy Approach Area', 'in a tree'), - 'Flute Boy Approach North Tree': (0x19, 0x08, False, '', 'Flute Boy Approach Area', 'in a tree'), - 'Dark Lumberjack Tree': (0x1a, 0x10, False, '', 'Dark Lumberjack Area', 'in a tree'), - 'Dark Fortune Bonk Rocks (Drop 1)': (0x1b, 0x10, False, '', 'Dark Fortune Area', 'encased in stone'), - 'Dark Fortune Bonk Rocks (Drop 2)': (0x1c, 0x08, False, '', 'Dark Fortune Area', 'encased in stone'), - 'Dark Graveyard West Bonk Rocks': (0x1d, 0x10, False, '', 'Dark Graveyard Area', 'encased in stone'), - 'Dark Graveyard North Bonk Rocks': (0x1e, 0x08, False, '', 'Dark Graveyard North', 'encased in stone'), - 'Dark Graveyard Tomb Bonk Rocks': (0x1f, 0x04, False, '', 'Dark Graveyard North', 'encased in stone'), - 'Qirn Jump West Tree': (0x20, 0x10, False, '', 'Qirn Jump Area', 'in a tree'), - 'Qirn Jump East Tree': (0x21, 0x08, False, '', 'Qirn Jump East Bank', 'in a tree'), - 'Dark Witch Tree': (0x22, 0x10, False, '', 'Dark Witch Area', 'in a tree'), - 'Pyramid Tree': (0x23, 0x10, False, '', 'Pyramid Area', 'in a tree'), - 'Palace of Darkness Tree': (0x24, 0x10, False, '', 'Palace of Darkness Area', 'in a tree'), - 'Dark Tree Line Tree 2': (0x25, 0x10, False, '', 'Dark Tree Line Area', 'in a tree'), - 'Dark Tree Line Tree 3': (0x26, 0x08, False, '', 'Dark Tree Line Area', 'in a tree'), - 'Dark Tree Line Tree 4': (0x27, 0x04, False, '', 'Dark Tree Line Area', 'in a tree'), - 'Hype Cave Statue': (0x28, 0x10, False, '', 'Hype Cave Area', 'encased in stone') + #'Forgotten Forest Southeast Tree': (0x10, 0x04, False, '', 'Forgotten Forest Area', 'in a tree'), + 'Hyrule Castle Tree': (0x11, 0x10, False, '', 'Hyrule Castle Courtyard', 'in a tree'), + 'Wooden Bridge Tree': (0x12, 0x10, False, '', 'Wooden Bridge Area', 'in a tree'), + 'Eastern Palace Tree': (0x13, 0x10, True, '', 'Eastern Palace Area', 'in a tree'), + 'Flute Boy South Tree': (0x14, 0x10, True, '', 'Flute Boy Area', 'in a tree'), + 'Flute Boy East Tree': (0x15, 0x08, True, '', 'Flute Boy Area', 'in a tree'), + 'Central Bonk Rocks Tree': (0x16, 0x10, False, '', 'Central Bonk Rocks Area', 'in a tree'), + 'Tree Line Tree 2': (0x17, 0x10, True, '', 'Tree Line Area', 'in a tree'), + 'Tree Line Tree 4': (0x18, 0x08, True, '', 'Tree Line Area', 'in a tree'), + 'Flute Boy Approach South Tree': (0x19, 0x10, False, '', 'Flute Boy Approach Area', 'in a tree'), + 'Flute Boy Approach North Tree': (0x1a, 0x08, False, '', 'Flute Boy Approach Area', 'in a tree'), + 'Dark Lumberjack Tree': (0x1b, 0x10, False, '', 'Dark Lumberjack Area', 'in a tree'), + 'Dark Fortune Bonk Rocks (Drop 1)': (0x1c, 0x10, False, '', 'Dark Fortune Area', 'encased in stone'), + 'Dark Fortune Bonk Rocks (Drop 2)': (0x1d, 0x08, False, '', 'Dark Fortune Area', 'encased in stone'), + 'Dark Graveyard West Bonk Rocks': (0x1e, 0x10, False, '', 'Dark Graveyard Area', 'encased in stone'), + 'Dark Graveyard North Bonk Rocks': (0x1f, 0x08, False, '', 'Dark Graveyard North', 'encased in stone'), + 'Dark Graveyard Tomb Bonk Rocks': (0x20, 0x04, False, '', 'Dark Graveyard North', 'encased in stone'), + 'Qirn Jump West Tree': (0x21, 0x10, False, '', 'Qirn Jump Area', 'in a tree'), + 'Qirn Jump East Tree': (0x22, 0x08, False, '', 'Qirn Jump East Bank', 'in a tree'), + 'Dark Witch Tree': (0x23, 0x10, False, '', 'Dark Witch Area', 'in a tree'), + 'Pyramid Tree': (0x24, 0x10, False, '', 'Pyramid Area', 'in a tree'), + 'Palace of Darkness Tree': (0x25, 0x10, False, '', 'Palace of Darkness Area', 'in a tree'), + 'Dark Tree Line Tree 2': (0x26, 0x10, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Dark Tree Line Tree 3': (0x27, 0x08, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Dark Tree Line Tree 4': (0x28, 0x04, False, '', 'Dark Tree Line Area', 'in a tree'), + 'Hype Cave Statue': (0x29, 0x10, False, '', 'Hype Cave Area', 'encased in stone') } bonk_table_by_location_id = {0x153B00+(data[0]*6)+3: name for name, data in bonk_prize_table.items()} diff --git a/Rom.py b/Rom.py index 37962bc7..68768420 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'c80605a079983f1a9dac37273e2b377a' +RANDOMIZERBASEHASH = '61e3137ae471ed8772deb7f84cc85fb9' class JsonRom(object): diff --git a/asm/owrando.asm b/asm/owrando.asm index b1c1ebdf..07ab9f55 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -385,7 +385,7 @@ OWBonkDrops: ; loop thru rando bonk table to find match PHB : PHK : PLB LDA.b $8A - LDX.b #(40*6) ; 40 bonk items, 6 bytes each + LDX.b #(41*6) ; 41 bonk items, 6 bytes each - CMP.w OWBonkPrizeData,X : BNE + INX LDA.w $0D10,Y : LSR A : LSR A : LSR A : LSR A @@ -1311,6 +1311,47 @@ db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0 +;================================================================================ +; Bonk Prize Data ($AABB00 - $AABBFB) +;-------------------------------------------------------------------------------- +; This table stores data relating to bonk locations for Bonk Drop Shuffle +; +; Example: We can use OWBonkPrizeTable[$09].loot to read what item is in the +; east tree on the Sanctuary screen +;-------------------------------------------------------------------------------- +; Search Criteria - The following two fields are used as a unique index +; .owid = OW screen ID +; .yx = Y & X coordinate data *see below* +; +; .flag = OW event flag bitmask +; .loot = Loot ID +; .mw_player = Multiworld player ID +; .vert_offset = Vertical offset, # of pixels the sprite moves up when activated +; +; .yx field is a combination of both the least significant digits of the Y and X +; coordinates of the static location of the sprite located in a bonk location. +; All sprites, when initialized, are aligned by a 16 pixel increment. +; The coordinate system in LTTP is handled by two bytes: +; (high) (low) +; - - - w w w w s s s s s s s s s +; w = world absolute coords, every screen is $200 pixels in each dimension +; s = local screen coords, coords relative to the bounds of the current screen +; Because of the 16 pixel alignment of sprites, the last four bits of the coords +; are unset. This leaves 5 bits remaining, we simply disregard the highest bit +; and then combine the Y and X coords together to be used as search criteria. +; This does open the possibility of a false positive match from 3 other coords +; on the same screen (15 on megatile screens) but there are no bonk sprites that +; have collision in this regard. +;-------------------------------------------------------------------------------- +struct OWBonkPrizeTable $AABB00 + .owid: skip 1 + .yx: skip 1 + .flag: skip 1 + .loot: skip 1 + .mw_player: skip 1 + .vert_offset: skip 1 +endstruct align 6 + org $aabb00 ;PC 153b00 OWBonkPrizeData: ; OWID YX Flag Item MW Offset @@ -1330,7 +1371,7 @@ db $18, $a8, $10, $b2, $00, $20 db $18, $36, $08, $35, $00, $20 db $1a, $8a, $10, $42, $00, $20 db $1a, $1d, $08, $b2, $00, $20 -;db $1a, $77, $04, $35, $00, $20 ; pre aga ONLY ; hijacked murahdahla bonk tree +db $ff, $77, $04, $35, $00, $20 ; pre aga ONLY ; hijacked murahdahla bonk tree db $1b, $46, $10, $b1, $00, $10 db $1d, $6b, $10, $b1, $00, $20 db $1e, $72, $10, $b2, $00, $20 diff --git a/data/base2current.bps b/data/base2current.bps index d51dc56eb7dc07a6d5483caeaf7dc404c89f27ce..c56129a9f3e943873ee428c38f821efcc1c2366b 100644 GIT binary patch delta 9079 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 Date: Fri, 29 Jul 2022 12:39:00 -0500 Subject: [PATCH 23/29] Fixed Multiworld support for Bonk Drop shuffle --- Fill.py | 16 ++++++++-------- Regions.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Fill.py b/Fill.py index 9633da49..75637093 100644 --- a/Fill.py +++ b/Fill.py @@ -360,18 +360,18 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None for player in range(1, world.players + 1): if world.shuffle_bonk_drops[player]: for item in world.itempool: - if item.name in ['Big Magic']: + if item.name in ['Big Magic'] and item.player == player: pot_item_pool[player].append(item) break - from Regions import bonk_prize_table for player, magic_pool in pot_item_pool.items(): - world.itempool.remove(magic_pool[0]) - pot_locations = [location for location in fill_locations if location.player == player - and location.name in [n for n, (_, _, aga, _, _, _) in bonk_prize_table.items() if not aga]] - pot_locations = filter_pot_locations(pot_locations, world) - fast_fill_helper(world, magic_pool, pot_locations) - pots_used = True + if len(magic_pool) > 0: + world.itempool.remove(magic_pool[0]) + pot_locations = [location for location in fill_locations if location.player == player + and location.name in [n for n, (_, _, aga, _, _, _) in bonk_prize_table.items() if not aga]] + pot_locations = filter_pot_locations(pot_locations, world) + fast_fill_helper(world, magic_pool, pot_locations) + pots_used = True if pots_used: fill_locations = world.get_unfilled_locations() diff --git a/Regions.py b/Regions.py index 435f7622..a37b7da5 100644 --- a/Regions.py +++ b/Regions.py @@ -1312,7 +1312,7 @@ bonk_prize_table = { 'Hype Cave Statue': (0x29, 0x10, False, '', 'Hype Cave Area', 'encased in stone') } -bonk_table_by_location_id = {0x153B00+(data[0]*6)+3: name for name, data in bonk_prize_table.items()} +bonk_table_by_location_id = {0x2ABB00+(data[0]*6)+3: name for name, data in bonk_prize_table.items()} bonk_table_by_location = {y: x for x, y in bonk_table_by_location_id.items()} From 1e0a0461519e3b1368d34f4e667f6617986d180b Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 29 Jul 2022 16:41:29 -0500 Subject: [PATCH 24/29] Fixed 4 digits collection rate in credits issue --- Rom.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 68768420..ae8e8bfa 100644 --- a/Rom.py +++ b/Rom.py @@ -1072,7 +1072,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(cr_pc+0x1f, thousands_bot) # modify stat config stat_address = 0x23B969 - stat_pc = snes_to_pc(stat_address) + owr_difference = 0x26 # can't remember why there is a difference between DR fork + stat_pc = snes_to_pc(stat_address - owr_difference) rom.write_byte(stat_pc, 0xa9) # change to pos 21 (from b1) rom.write_byte(stat_pc+2, 0xc0) # change to 12 bits (from a0) rom.write_byte(stat_pc+3, 0x80) # change to four digits (from 60) From eca58ebccaec2502ab6a22a645bef96022477730 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 29 Jul 2022 16:45:21 -0500 Subject: [PATCH 25/29] Adjusted sprite alignment when coming from a chest --- Rom.py | 2 +- data/base2current.bps | Bin 104324 -> 104326 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index ae8e8bfa..1f10b8e3 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '61e3137ae471ed8772deb7f84cc85fb9' +RANDOMIZERBASEHASH = '0574a782e225a87b90637db0847c5ae0' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index c56129a9f3e943873ee428c38f821efcc1c2366b..b48472f343c2e495ca98cb4f09ae31edac2e3b87 100644 GIT binary patch delta 43 zcmV+`0M!44uLg#%2C!iP0~*ccvt$8TLk5WhDfq8dgTX|%!9)SOQV8^|<-`qez2b)m B6M+B# delta 41 xcmZo$&(^Y@Z9^g>v)0+Gn^PDgomm>$w?{S~cG-T|g>iQf$47>=`}^uzY5`k`5qAIp From a36d65ef8115cccea5a536922b9e04afc4225242 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 29 Jul 2022 21:29:32 -0500 Subject: [PATCH 26/29] Adding sprite patch for Apples so they don't prevent kill rooms from opening --- Rom.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index 1f10b8e3..688c0274 100644 --- a/Rom.py +++ b/Rom.py @@ -1667,10 +1667,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_bytes(0x02F539, [0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0, 0x4F]) # sprite patches - rom.write_byte(snes_to_pc(0x0db7d1), 0x03) # patch apple sprites to not permadeatch like enemies + rom.write_byte(snes_to_pc(0x0DB7D1), 0x03) # patch apple sprites to not permadeatch like enemies + rom.write_byte(snes_to_pc(0x0DB4F8), 0x40) # patch apples to not prevent kill rooms from opening if world.shuffle_bonk_drops[player]: # warning, this temporary patch might cause fairies to respawn differently?, limiting this to bonk drop mode only - rom.write_byte(snes_to_pc(0x0db808), 0x03) # patch fairies sprites to not permadeatch like enemies + rom.write_byte(snes_to_pc(0x0DB808), 0x03) # patch fairies sprites to not permadeath like enemies # allow smith into multi-entrance caves in appropriate shuffles if world.shuffle[player] in ['restricted', 'full', 'lite', 'lean', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'): From 383a2a274de253f4936e919bd3da076875a94168 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 29 Jul 2022 21:33:10 -0500 Subject: [PATCH 27/29] Catching infinite loop at balance_money_progression --- Fill.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Fill.py b/Fill.py index 75637093..daa6f6bd 100644 --- a/Fill.py +++ b/Fill.py @@ -830,7 +830,12 @@ def balance_money_progression(world): return False done = False + attempts = world.players * 20 + 20 while not done: + attempts -= 1 + if attempts < 0: + from DungeonGenerator import GenerationException + raise GenerationException(f'Infinite loop detected at "balance_money_progression"') sphere_costs = {player: 0 for player in range(1, world.players+1)} locked_by_money = {player: set() for player in range(1, world.players+1)} sphere_locations = get_sphere_locations(state, unchecked_locations) From a9fa2a326f8e1c8aa21b0106ae99ebf3837f04e3 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 29 Jul 2022 21:35:27 -0500 Subject: [PATCH 28/29] Scaling infinite loop check to number of players --- BaseClasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BaseClasses.py b/BaseClasses.py index ab4d536e..551d4957 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1606,7 +1606,7 @@ class Region(object): def can_reach(self, state): from Utils import stack_size3a from DungeonGenerator import GenerationException - if stack_size3a() > 500: + if stack_size3a() > self.world.players * 500: raise GenerationException(f'Infinite loop detected for "{self.name}" located at \'Region.can_reach\'') if state.stale[self.player]: From 8721858e2c790def7757dd2ea0b112e503a79953 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 29 Jul 2022 22:37:38 -0500 Subject: [PATCH 29/29] Version bump 0.2.9.0 --- CHANGELOG.md | 7 +++++++ OverworldShuffle.py | 2 +- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aef17765..fe3f74df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### 0.2.9.0 +- Added Bonk Drop Shuffle +- Fixed disappearing mirror portal issue in Inverted+Crossed OWR +- Fixed 4-digit collection rate in credits +- Fixed Ganon vulnerability to reference Aga2 boss flag rather than pyramid hole +- Fixed issue with pre-opened pyramid when not expected + ### 0.2.8.0 - ~Merged DR v1.0.1.0 - Pottery options, BPS support, MSU Resume, Collection Rate Counter~ - Various improvements to increase generation success rate and reduce generation time diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 5a940200..f5812ffc 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -6,7 +6,7 @@ from Regions import mark_dark_world_regions, mark_light_world_regions from OWEdges import OWTileRegions, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel from Utils import bidict -version_number = '0.2.8.0' +version_number = '0.2.9.0' version_branch = '-u' __version__ = '%s%s' % (version_number, version_branch) diff --git a/README.md b/README.md index 9dbb35fe..c6e5187c 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Alternatively, run ```Gui.py``` for a simple graphical user interface. # Settings -Only extra settings are found here. All door and entrance randomizer settings are supported. See their [readme](https://github.com/Aerinon/ALttPDoorRandomizer/blob/master/README.md) +Only extra settings added by this Overworld Shuffle fork are found here. All door and entrance randomizer settings are supported. See their [readme](https://github.com/Aerinon/ALttPDoorRandomizer/blob/master/README.md) ## Overworld Layout Shuffle (--ow_shuffle) @@ -136,6 +136,37 @@ New flute spots are chosen at random, with restrictions that limit the promixity New flute spots are chosen at random with minimum bias. +## Bonk Drop Shuffle (--bonk_drops) + +This adds 41 new item locations to the game. These bonk locations are limited to the ones that drop a static item in the vanilla game. + +- Bonk Locations consist of some trees, rocks, and statues + - 33 Trees + - 8 of the tree locations require Agahnim to be defeated to access the item + - 6 Rocks + - 1 of the rocks drops 2 items + - 1 Statue +- Bonk locations can be collected by bonking into them with the Pegasus Boots or using the Quake Medallion +- One of the bonk locations are guaranteed to have a full magic decanter +- Some of the drops can be farmed repeatedly, but only increments the collection rate once +- All of the bonk trees have been given an alternate color (and all non-bonk trees are reverted to normal tree color) + - Some screens are coded to change the "alternate tree color", some of them are strange (just how the vanilla game does it) + - Rocks and statues are unable to be made to have a different color +- Since Fairies and Apples are new items that can appear in plain sight, they don't have a proper graphic for them yet. For now, they show up as Power Stars + +Future Note: This does NOT include the Good Bee (Cold Bee) Cave Statue...yet. In the future, this could be an additional item location. + +#### Items Added To Pool: +- 15 Fairies +- 8 Apples +- 6 Bee Traps +- 3 Red Rupees +- 3 Blue Rupees +- 2 Single Bomb +- 2 Small Hearts +- 1 Large Magic Decanter +- 1 8x Bomb Pack + ## New Goal Options (--goal) ### Trinity @@ -216,3 +247,9 @@ This gives each OW tile a random chance to be swapped to the opposite world ``` For randomizing the flute spots around the overworld + +``` +--bonk_drops +``` + +This extends the item pool to bonk locations and makes them additional item locations