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)