From e834fd85a1132b6db62471399c3ebf67beaefabf Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 3 Dec 2020 16:25:51 -0700 Subject: [PATCH] Initial Shopsanity Retro work --- BaseClasses.py | 39 ++- CLI.py | 3 +- Fill.py | 17 + InvertedRegions.py | 2 +- ItemList.py | 180 ++++++++-- Items.py | 330 +++++++++--------- Main.py | 27 +- RELEASENOTES.md | 8 +- Regions.py | 86 ++++- Rom.py | 4 +- data/base2current.bps | Bin 131148 -> 131157 bytes resources/app/cli/args.json | 4 + resources/app/cli/lang/en.json | 1 + resources/app/gui/lang/en.json | 2 + resources/app/gui/randomize/item/widgets.json | 3 +- source/classes/constants.py | 1 + 16 files changed, 471 insertions(+), 236 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index c0248d11..cda3ff61 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -36,7 +36,7 @@ class World(object): self.algorithm = algorithm self.dungeons = [] self.regions = [] - self.shops = [] + self.shops = {} self.itempool = [] self.seed = None self.precollected_items = [] @@ -130,6 +130,7 @@ class World(object): set_player_attr('potshuffle', False) set_player_attr('pot_contents', None) + set_player_attr('shopsanity', False) set_player_attr('keydropshuffle', False) set_player_attr('mixed_travel', 'prevent') set_player_attr('standardize_palettes', 'standardize') @@ -610,7 +611,7 @@ class CollectionState(object): return self.prog_items[item, player] >= count def can_buy_unlimited(self, item, player): - for shop in self.world.shops: + for shop in self.world.shops[player]: if shop.region.player == player and shop.has_unlimited(item) and shop.region.can_reach(self): return True return False @@ -674,7 +675,7 @@ class CollectionState(object): def can_shoot_arrows(self, player): if self.world.retro[player]: #todo: Non-progressive silvers grant wooden arrows, but progressive bows do not. Always require shop arrows to be safe - return self.has('Bow', player) and self.can_buy_unlimited('Single Arrow', player) + return self.has('Bow', player) and (self.can_buy_unlimited('Single Arrow', player) or self.has('Single Arrow', player)) return self.has('Bow', player) def can_get_good_bee(self, player): @@ -1640,6 +1641,7 @@ class Location(object): self.access_rule = lambda state: True self.item_rule = lambda item: True self.player = player + self.skip = False def can_fill(self, state, item, check_access=True): return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) @@ -1677,7 +1679,9 @@ class Location(object): class Item(object): - def __init__(self, name='', advancement=False, priority=False, type=None, code=None, pedestal_hint=None, pedestal_credit=None, sickkid_credit=None, zora_credit=None, witch_credit=None, fluteboy_credit=None, hint_text=None, player=None): + def __init__(self, name='', advancement=False, priority=False, type=None, code=None, price=999, pedestal_hint=None, + pedestal_credit=None, sickkid_credit=None, zora_credit=None, witch_credit=None, fluteboy_credit=None, + hint_text=None, player=None): self.name = name self.advancement = advancement self.priority = priority @@ -1690,6 +1694,7 @@ class Item(object): self.fluteboy_credit_text = fluteboy_credit self.hint_text = hint_text self.code = code + self.price = price self.location = None self.world = None self.player = player @@ -1853,12 +1858,12 @@ class Spoiler(object): self.locations['Dark World'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dw_locations]) listed_locations.update(dw_locations) - cave_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.Cave] + cave_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.Cave and not loc.skip] self.locations['Caves'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in cave_locations]) listed_locations.update(cave_locations) for dungeon in self.world.dungeons: - dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon] + dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and not loc.forced_item] self.locations[str(dungeon)] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations]) listed_locations.update(dungeon_locations) @@ -1868,17 +1873,19 @@ class Spoiler(object): listed_locations.update(other_locations) self.shops = [] - for shop in self.world.shops: - if not shop.custom: - continue - shopdata = {'location': str(shop.region), - 'type': 'Take Any' if shop.type == ShopType.TakeAny else 'Shop' - } - for index, item in enumerate(shop.inventory): - if item is None: + for player in range(1, self.world.players + 1): + for shop in self.world.shops[player]: + if not shop.custom: continue - shopdata['item_{}'.format(index)] = "{} - {}".format(item['item'], item['price']) if item['price'] else item['item'] - self.shops.append(shopdata) + shopdata = {'location': str(shop.region), + 'type': 'Take Any' if shop.type == ShopType.TakeAny else 'Shop' + } + for index, item in enumerate(shop.inventory): + if item is None: + continue + # todo: indicate player? might be fine + shopdata[f'item_{index}'] = f"{item['item']} — {item['price']}" if item['price'] else item['item'] + self.shops.append(shopdata) for player in range(1, self.world.players + 1): self.bosses[str(player)] = OrderedDict() diff --git a/CLI.py b/CLI.py index 35204b65..bcfc2181 100644 --- a/CLI.py +++ b/CLI.py @@ -93,7 +93,7 @@ def parse_cli(argv, no_defaults=False): 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', - 'remote_items', 'keydropshuffle', 'mixed_travel', 'standardize_palettes']: + 'remote_items', 'shopsanity', 'keydropshuffle', 'mixed_travel', 'standardize_palettes']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: setattr(ret, name, {1: value}) @@ -133,6 +133,7 @@ def parse_settings(): "enemy_health": "default", "enemizercli": os.path.join(".", "EnemizerCLI", "EnemizerCLI.Core"), + "shopsanity": False, "keydropshuffle": False, "mapshuffle": False, "compassshuffle": False, diff --git a/Fill.py b/Fill.py index bc841a5b..a4fe672f 100644 --- a/Fill.py +++ b/Fill.py @@ -2,6 +2,7 @@ import random import logging from BaseClasses import CollectionState +from Regions import shop_to_location_table class FillError(RuntimeError): @@ -374,6 +375,22 @@ def flood_items(world): itempool.remove(item_to_place) break + +def sell_keys(world, player): + choices = [] + shop_map = {} + for shop in world.shops[player]: + if shop.region.name in shop_to_location_table: + choices.append(shop.region.name) + shop_map[shop.region.name] = shop + key_seller = random.choice(choices) + location = random.choice(shop_to_location_table[key_seller]) + universal_key = next(item for item in world.itempool if item.name == 'Small Key (Universal)' and item.player == player) + world.push_item(world.get_location(location, player), universal_key, collect=False) + shop_map[key_seller].add_inventory(0, 'Small Key (Universal)', 100) # will be fixed later in customize shops + world.itempool.remove(universal_key) + + def balance_multiworld_progression(world): state = CollectionState(world) checked_locations = [] diff --git a/InvertedRegions.py b/InvertedRegions.py index 71c26fc9..9e439093 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -2,7 +2,7 @@ import collections from BaseClasses import RegionType from Regions import create_lw_region, create_dw_region, create_cave_region, create_dungeon_region, create_menu_region - +# todo: shopsanity locations def create_inverted_regions(world, player): world.regions += [ diff --git a/ItemList.py b/ItemList.py index ae05e9ee..aa93602b 100644 --- a/ItemList.py +++ b/ItemList.py @@ -6,7 +6,8 @@ from BaseClasses import Region, RegionType, Shop, ShopType, Location from Bosses import place_bosses from Dungeons import get_dungeon_item_pool from EntranceShuffle import connect_entrance -from Fill import FillError, fill_restrictive, fast_fill +from Regions import shop_to_location_table, retro_shops +from Fill import FillError, fill_restrictive from Items import ItemFactory import source.classes.constants as CONST @@ -304,6 +305,13 @@ def generate_itempool(world, player): world.get_location(location, player).event = True world.get_location(location, player).locked = True + if world.shopsanity[player]: + for shop in world.shops[player]: + if shop.region.name in shop_to_location_table: + for index, slot in enumerate(shop.inventory): + if slot: + pool.append(slot['item']) + items = ItemFactory(pool, player) world.lamps_needed_for_dark_rooms = lamps_needed_for_dark_rooms @@ -371,6 +379,7 @@ take_any_locations = [ 'Palace of Darkness Hint', 'East Dark World Hint', 'Archery Game', 'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Spike Cave', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint', 'Dark Desert Hint'] + def set_up_take_anys(world, player): if world.mode[player] == 'inverted' and 'Dark Sanctuary Hint' in take_any_locations: take_any_locations.remove('Dark Sanctuary Hint') @@ -385,38 +394,43 @@ def set_up_take_anys(world, player): entrance = world.get_region(reg, player).entrances[0] connect_entrance(world, entrance, old_man_take_any, player) entrance.target = 0x58 - old_man_take_any.shop = Shop(old_man_take_any, 0x0112, ShopType.TakeAny, 0xE2, True, True) - world.shops.append(old_man_take_any.shop) + old_man_take_any.shop = Shop(old_man_take_any, 0x0112, ShopType.TakeAny, 0xE2, True, not world.shopsanity[player]) + world.shops[player].append(old_man_take_any.shop) - swords = [item for item in world.itempool if item.type == 'Sword' and item.player == player] - if swords: - sword = random.choice(swords) - world.itempool.remove(sword) + sword = next((item for item in world.itempool if item.type == 'Sword' and item.player == player), None) + if sword: world.itempool.append(ItemFactory('Rupees (20)', player)) + if not world.shopsanity[player]: + world.itempool.remove(sword) old_man_take_any.shop.add_inventory(0, sword.name, 0, 0, create_location=True) else: - old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0) + if world.shopsanity[player]: + world.itempool.append(ItemFactory('Rupees (300)', player)) + old_man_take_any.shop.add_inventory(0, 'Rupees (300)', 0, 0, create_location=world.shopsanity[player]) + take_any_type = ShopType.Shop if world.shopsanity[player] else ShopType.TakeAny for num in range(4): take_any = Region("Take-Any #{}".format(num+1), RegionType.Cave, 'a cave of choice', player) world.regions.append(take_any) world.dynamic_regions.append(take_any) - target, room_id = random.choice([(0x58, 0x0112), (0x60, 0x010F), (0x46, 0x011F)]) reg = regions.pop() entrance = world.get_region(reg, player).entrances[0] connect_entrance(world, entrance, take_any, player) entrance.target = target - take_any.shop = Shop(take_any, room_id, ShopType.TakeAny, 0xE3, True, True) - world.shops.append(take_any.shop) - take_any.shop.add_inventory(0, 'Blue Potion', 0, 0) - take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0) + take_any.shop = Shop(take_any, room_id, take_any_type, 0xE3, True, not world.shopsanity[player]) + world.shops[player].append(take_any.shop) + take_any.shop.add_inventory(0, 'Blue Potion', 0, 0, create_location=world.shopsanity[player]) + take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0, create_location=world.shopsanity[player]) + if world.shopsanity[player]: + world.itempool.append(ItemFactory('Blue Potion', player)) + world.itempool.append(ItemFactory('Boss Heart Container', player)) world.initialize_regions() def create_dynamic_shop_locations(world, player): - for shop in world.shops: + for shop in world.shops[player]: if shop.region.player == player: for i, item in enumerate(shop.inventory): if item is None: @@ -428,9 +442,10 @@ def create_dynamic_shop_locations(world, player): world.clear_location_cache() - world.push_item(loc, ItemFactory(item['item'], player), False) - loc.event = True - loc.locked = True + if not world.shopsanity[player]: + world.push_item(loc, ItemFactory(item['item'], player), False) + loc.event = True + loc.locked = True def fill_prizes(world, attempts=15): @@ -462,20 +477,125 @@ def fill_prizes(world, attempts=15): def set_up_shops(world, player): - # TODO: move hard+ mode changes for sheilds here, utilizing the new shops - if world.retro[player]: - rss = world.get_region('Red Shield Shop', player).shop - if not rss.locked: - rss.custom = True - rss.add_inventory(2, 'Single Arrow', 80) - for shop in random.sample([s for s in world.shops if not s.locked and s.region.player == player], 5): - shop.custom = True - shop.locked = True - shop.add_inventory(0, 'Single Arrow', 80) - shop.add_inventory(1, 'Small Key (Universal)', 100) - shop.add_inventory(2, 'Bombs (10)', 50) - rss.locked = True + if world.shopsanity[player]: + removals = [next(item for item in world.itempool if item.name == 'Arrows (10)' and item.player == player)] + red_pots = [item for item in world.itempool if item.name == 'Red Potion' and item.player == player][:5] + shields_n_hearts = [item for item in world.itempool if item.name in ['Blue Shield', 'Small Heart'] and item.player == player] + removals.extend(red_pots) + removals.extend(random.sample(shields_n_hearts, 5)) + for remove in removals: + world.itempool.remove(remove) + for i in range(6): + arrow_item = ItemFactory('Single Arrow', player) + arrow_item.advancement = True + world.itempool.append(arrow_item) + for i in range(5): + world.itempool.append(ItemFactory('Small Key (Universal)', player)) + # TODO: move hard+ mode changes for shields here, utilizing the new shops + else: + rss = world.get_region('Red Shield Shop', player).shop + if not rss.locked: + rss.custom = True + rss.add_inventory(2, 'Single Arrow', 80) + for shop in random.sample([s for s in world.shops if not s.locked and s.region.player == player], 5): + shop.custom = True + shop.locked = True + shop.add_inventory(0, 'Single Arrow', 80) + shop.add_inventory(1, 'Small Key (Universal)', 100) + shop.add_inventory(2, 'Bombs (10)', 50) + rss.locked = True + + +def customize_shops(world, player): + found_bomb_upgrade, found_arrow_upgrade = False, False + possible_replacements = [] + shops_to_customize = shop_to_location_table.copy() + if world.retro[player]: + shops_to_customize.update(retro_shops) + for shop_name, loc_list in shops_to_customize.items(): + shop = world.get_region(shop_name, player).shop + shop.custom = True + shop.clear_inventory() + for idx, loc in enumerate(loc_list): + location = world.get_location(loc, player) + item = location.item + max_repeat = 1 + if shop_name not in retro_shops: + if item.name in repeatable_shop_items: + max_repeat = 0 + if item.name in ['Bomb Upgrade (+5)', 'Arrow Upgrade (+5)']: + if item.name == 'Bomb Upgrade (+5)': + found_bomb_upgrade = True + if item.name == 'Arrow Upgrade (+5)': + found_arrow_upgrade = True + max_repeat = 7 + if shop_name in retro_shops: + price = 0 + else: + price = 120 if shop_name == 'Potion Shop' and item.name == 'Red Potion' else item.price + if world.retro[player] and item.name == 'Single Arrow': + price = 80 + # randomize price + shop.add_inventory(idx, item.name, randomize_price(price), max_repeat) + if item.name in cap_replacements and shop_name not in retro_shops: + possible_replacements.append((shop, idx, location, item)) + # todo: randomize shopkeeper + # handle capacity upgrades - randomly choose a bomb bunch or arrow bunch to become capacity upgrades + if not found_bomb_upgrade and len(possible_replacements) > 0: + choices = [] + for shop, idx, loc, item in possible_replacements: + if item.name in ['Bombs (3)', 'Bombs (10)']: + choices.append((shop, idx, loc, item)) + if len(choices) > 0: + shop, idx, loc, item = random.choice(choices) + upgrade = ItemFactory('Bomb Upgrade (+5)', player) + shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6, + item.name, randomize_price(item.price)) + loc.item = upgrade + upgrade.location = loc + if not found_arrow_upgrade and len(possible_replacements) > 0: + choices = [] + for shop, idx, loc, item in possible_replacements: + if item.name == 'Arrows (10)' or (item.name == 'Single Arrow' and not world.retro[player]): + choices.append((shop, idx, loc, item)) + if len(choices) > 0: + shop, idx, loc, item = random.choice(choices) + upgrade = ItemFactory('Arrow Upgrade (+5)', player) + shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6, + item.name, randomize_price(item.price)) + loc.item = upgrade + upgrade.location = loc + change_shop_items_to_rupees(world, player, shops_to_customize) + + +def randomize_price(price): + half_price = price // 2 + max_price = price - half_price + if max_price % 5 == 0: + max_price //= 5 + return random.randint(0, max_price) * 5 + half_price + else: + return price + + +def change_shop_items_to_rupees(world, player, shops): + locations = world.get_filled_locations(player) + for location in locations: + if location.item.name in shop_transfer.keys() and location.parent_region not in shops: + new_item = ItemFactory(shop_transfer[location.item.name], location.item.player) + location.item = new_item + + +repeatable_shop_items = ['Single Arrow', 'Arrows (10)', 'Bombs (3)', 'Bombs (10)', 'Red Potion', 'Small Heart', + 'Blue Shield', 'Red Shield', 'Bee', 'Small Key (Universal)'] + + +cap_replacements = ['Single Arrow', 'Arrows (10)', 'Bombs (3)', 'Bombs (10)'] + + +shop_transfer = {'Red Potion': 'Rupees (100)', 'Bee': 'Rupees (5)', 'Blue Potion': 'Rupees (100)', + 'Blue Shield': 'Rupees (50)', 'Red Shield': 'Rupees (300)'} def get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, door_shuffle): diff --git a/Items.py b/Items.py index b20ebe35..e5d91d4a 100644 --- a/Items.py +++ b/Items.py @@ -11,8 +11,8 @@ def ItemFactory(items, player): singleton = True for item in items: if item in item_table: - advancement, priority, type, code, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit, hint_text = item_table[item] - ret.append(Item(item, advancement, priority, type, code, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit, hint_text, player)) + advancement, priority, type, code, price, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit, hint_text = item_table[item] + ret.append(Item(item, advancement, priority, type, code, price, pedestal_hint, pedestal_credit, sickkid_credit, zora_credit, witch_credit, fluteboy_credit, hint_text, player)) else: logging.getLogger('').warning('Unknown Item: %s', item) return None @@ -23,167 +23,167 @@ def ItemFactory(items, player): # Format: Name: (Advancement, Priority, Type, ItemCode, Pedestal Hint Text, Pedestal Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text, Hint Text) -item_table = {'Bow': (True, False, None, 0x0B, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'), - 'Progressive Bow': (True, False, None, 0x64, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), - 'Progressive Bow (Alt)': (True, False, None, 0x65, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), - 'Book of Mudora': (True, False, None, 0x1D, 'This is a\nparadox?!', 'and the story book', 'the scholarly kid', 'moon runes for sale', 'drugs for literacy', 'book-worm boy can read again', 'the Book'), - 'Hammer': (True, False, None, 0x09, 'stop\nhammer time!', 'and m c hammer', 'hammer-smashing kid', 'm c hammer for sale', 'stop... hammer time', 'stop, hammer time', 'the hammer'), - 'Hookshot': (True, False, None, 0x0A, 'BOING!!!\nBOING!!!\nBOING!!!', 'and the tickle beam', 'tickle-monster kid', 'tickle beam for sale', 'witch and tickle boy', 'beam boy tickles again', 'the Hookshot'), - 'Magic Mirror': (True, False, None, 0x1A, 'Isn\'t your\nreflection so\npretty?', 'the face reflector', 'the narcissistic kid', 'your face for sale', 'trades looking-glass', 'narcissistic boy is happy again', 'the Mirror'), - 'Ocarina': (True, False, None, 0x14, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'ocarina boy plays again', 'the Flute'), - 'Pegasus Boots': (True, False, None, 0x4B, 'Gotta go fast!', 'and the sprint shoes', 'the running-man kid', 'sprint shoe for sale', 'shrooms for speed', 'gotta-go-fast boy runs again', 'the Boots'), - 'Power Glove': (True, False, None, 0x1B, 'Now you can\nlift weak\nstuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the glove'), - 'Cape': (True, False, None, 0x19, 'Wear this to\nbecome\ninvisible!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the cape'), - 'Mushroom': (True, False, None, 0x29, 'I\'m a fun guy!\n\nI\'m a funghi!', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the mushroom'), - 'Shovel': (True, False, None, 0x13, 'Can\n You\n Dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the shovel'), - 'Lamp': (True, False, None, 0x12, 'Baby, baby,\nbaby.\nLight my way!', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the lamp'), - 'Magic Powder': (True, False, None, 0x0D, 'you can turn\nanti-faeries\ninto faeries', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the powder'), - 'Moon Pearl': (True, False, None, 0x1F, ' Bunny Link\n be\n gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the moon pearl'), - 'Cane of Somaria': (True, False, None, 0x15, 'I make blocks\nto hold down\nswitches!', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the red cane'), - 'Fire Rod': (True, False, None, 0x07, 'I\'m the hot\nrod. I make\nthings burn!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the fire rod'), - 'Flippers': (True, False, None, 0x1E, 'fancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the flippers'), - 'Ice Rod': (True, False, None, 0x08, 'I\'m the cold\nrod. I make\nthings freeze!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the ice rod'), - 'Titans Mitts': (True, False, None, 0x1C, 'Now you can\nlift heavy\nstuff!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the mitts'), - 'Bombos': (True, False, None, 0x0F, 'Burn, baby,\nburn! Fear my\nring of fire!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'medallion boy melts room again', 'Bombos'), - 'Ether': (True, False, None, 0x10, 'This magic\ncoin freezes\neverything!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'medallion boy sees floor again', 'Ether'), - 'Quake': (True, False, None, 0x11, 'Maxing out the\nRichter scale\nis what I do!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'medallion boy shakes dirt again', 'Quake'), - 'Bottle': (True, False, None, 0x16, 'Now you can\nstore potions\nand stuff!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'bottle boy has terrarium again', 'a Bottle'), - 'Bottle (Red Potion)': (True, False, None, 0x2B, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a Bottle'), - 'Bottle (Green Potion)': (True, False, None, 0x2C, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a Bottle'), - 'Bottle (Blue Potion)': (True, False, None, 0x2D, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a Bottle'), - 'Bottle (Fairy)': (True, False, None, 0x3D, 'Save me and I will revive you', 'and the captive', 'the tingle kid', 'hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a Bottle'), - 'Bottle (Bee)': (True, False, None, 0x3C, '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 Bottle'), - 'Bottle (Good Bee)': (True, False, None, 0x48, 'I will sting your foes a whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has beetor again', 'a Bottle'), - 'Master Sword': (True, False, 'Sword', 0x50, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again', 'the Master Sword'), - 'Tempered Sword': (True, False, 'Sword', 0x02, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'), - 'Fighter Sword': (True, False, 'Sword', 0x49, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the small sword'), - 'Golden Sword': (True, False, 'Sword', 0x03, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'), - 'Progressive Sword': (True, False, 'Sword', 0x5E, 'a better copy\nof your sword\nfor your time', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again', 'a sword'), - 'Progressive Glove': (True, False, None, 0x61, 'a way to lift\nheavier things', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a glove'), - 'Silver Arrows': (True, False, None, 0x58, 'Do you fancy\nsilver tipped\narrows?', 'and the ganonsbane', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again', 'the silver arrows'), - 'Green Pendant': (True, False, 'Crystal', [0x04, 0x38, 0x62, 0x00, 0x69, 0x01], None, None, None, None, None, None, None), - 'Blue Pendant': (True, False, 'Crystal', [0x02, 0x34, 0x60, 0x00, 0x69, 0x02], None, None, None, None, None, None, None), - 'Red Pendant': (True, False, 'Crystal', [0x01, 0x32, 0x60, 0x00, 0x69, 0x03], None, None, None, None, None, None, None), - 'Triforce': (True, False, None, 0x6A, '\n YOU WIN!', 'and the triforce', 'victorious kid', 'victory for sale', 'fungus for the win', 'greedy boy wins game again', 'the Triforce'), - 'Power Star': (True, False, None, 0x6B, 'a small victory', 'and the power star', 'star-struck kid', 'star for sale', 'see stars with shroom', 'mario powers up again', 'a Power Star'), - 'Triforce Piece': (True, False, None, 0x6C, 'a small victory', 'and the thirdforce', 'triangular kid', 'triangle for sale', 'fungus for triangle', 'wise boy has triangle again', 'a Triforce Piece'), - 'Crystal 1': (True, False, 'Crystal', [0x02, 0x34, 0x64, 0x40, 0x7F, 0x06], None, None, None, None, None, None, None), - 'Crystal 2': (True, False, 'Crystal', [0x10, 0x34, 0x64, 0x40, 0x79, 0x06], None, None, None, None, None, None, None), - 'Crystal 3': (True, False, 'Crystal', [0x40, 0x34, 0x64, 0x40, 0x6C, 0x06], None, None, None, None, None, None, None), - 'Crystal 4': (True, False, 'Crystal', [0x20, 0x34, 0x64, 0x40, 0x6D, 0x06], None, None, None, None, None, None, None), - 'Crystal 5': (True, False, 'Crystal', [0x04, 0x32, 0x64, 0x40, 0x6E, 0x06], None, None, None, None, None, None, None), - 'Crystal 6': (True, False, 'Crystal', [0x01, 0x32, 0x64, 0x40, 0x6F, 0x06], None, None, None, None, None, None, None), - 'Crystal 7': (True, False, 'Crystal', [0x08, 0x34, 0x64, 0x40, 0x7C, 0x06], None, None, None, None, None, None, None), - 'Single Arrow': (False, False, None, 0x43, 'a lonely arrow\nsits here.', 'and the arrow', 'stick-collecting kid', 'sewing needle for sale', 'fungus for arrow', 'archer boy sews again', 'an arrow'), - 'Arrows (10)': (False, False, None, 0x44, 'This will give\nyou ten shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'ten arrows'), - 'Arrow Upgrade (+10)': (False, False, None, 0x54, '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, '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, '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'), - 'Bombs (3)': (False, False, None, 0x28, '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, '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, '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'), - 'Bomb Upgrade (+5)': (False, False, None, 0x51, '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'), - 'Blue Mail': (False, True, None, 0x22, 'Now you\'re a\nblue elf!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the blue mail'), - 'Red Mail': (False, True, None, 0x23, 'Now you\'re a\nred elf!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the red mail'), - 'Progressive Armor': (False, True, None, 0x60, 'time for a\nchange of\nclothes?', 'and the unknown hat', 'the protected kid', 'new hat for sale', 'the clothing store', 'tailor boy has threads again', 'some armor'), - 'Blue Boomerang': (True, False, None, 0x0C, 'No matter what\nyou do, blue\nreturns to you', 'and the bluemarang', 'the bat-throwing kid', 'bent stick for sale', 'fungus for puma-stick', 'throwing boy plays fetch again', 'the blue boomerang'), - 'Red Boomerang': (True, False, None, 0x2A, 'No matter what\nyou do, red\nreturns to you', 'and the badmarang', 'the bat-throwing kid', 'air foil for sale', 'fungus for return-stick', 'magical boy plays fetch again', 'the red boomerang'), - 'Blue Shield': (False, True, None, 0x04, 'Now you can\ndefend against\npebbles!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'the blue shield'), - 'Red Shield': (False, True, None, 0x05, 'Now you can\ndefend against\nfireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'the red shield'), - 'Mirror Shield': (True, False, None, 0x06, 'Now you can\ndefend against\nlasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the mirror shield'), - 'Progressive Shield': (True, False, None, 0x5F, 'have a better\nblocker in\nfront of you', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'), - 'Bug Catching Net': (True, False, None, 0x21, 'Let\'s catch\nsome bees and\nfaeries!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the bug net'), - 'Cane of Byrna': (True, False, None, 0x18, 'Use this to\nbecome\ninvincible!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the blue cane'), - 'Boss Heart Container': (False, False, None, 0x3E, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'), - 'Sanctuary Heart Container': (False, False, None, 0x3F, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'), - 'Piece of Heart': (False, False, None, 0x17, 'Just a little\npiece of love!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'), - 'Rupee (1)': (False, False, None, 0x34, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'), - 'Rupees (5)': (False, False, None, 0x35, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'), - 'Rupees (20)': (False, False, None, 0x36, 'Just couch\ncash. Move\nright along.', 'and the couch cash', 'the piggy-bank kid', 'life lesson for sale', 'the witch buying drugs', 'destitute boy has lunch again', 'a red rupee'), - 'Rupees (50)': (False, False, None, 0x41, 'A rupee pile!\nOkay?', 'and the rupee pile', 'the well-off kid', 'life lesson for sale', 'buying okay drugs', 'destitute boy has dinner again', 'fifty rupees'), - 'Rupees (100)': (False, False, None, 0x40, 'A rupee stash!\nHell yeah!', 'and the rupee stash', 'the kind-of-rich kid', 'life lesson for sale', 'buying good drugs', 'affluent boy goes drinking again', 'one hundred rupees'), - 'Rupees (300)': (False, False, None, 0x46, 'A rupee hoard!\nHell yeah!', 'and the rupee hoard', 'the really-rich kid', 'life lesson for sale', 'buying the best drugs', 'fat-cat boy is rich again', 'three hundred rupees'), - 'Rupoor': (False, False, None, 0x59, 'a debt collector', 'and the toll-booth', 'the toll-booth kid', 'double loss for sale', 'witch stole your rupees', 'affluent boy steals rupees', 'a rupoor'), - 'Red Clock': (False, True, None, 0x5B, 'a waste of time', 'the ruby clock', 'the ruby-time kid', 'red time for sale', 'for ruby time', 'moment boy travels time again', 'a red clock'), - 'Blue Clock': (False, True, None, 0x5C, 'a bit of time', 'the sapphire clock', 'sapphire-time kid', 'blue time for sale', 'for sapphire time', 'moment boy time travels again', 'a blue clock'), - 'Green Clock': (False, True, None, 0x5D, 'a lot of time', 'the emerald clock', 'the emerald-time kid', 'green time for sale', 'for emerald time', 'moment boy adjusts time again', 'a red clock'), - 'Single RNG': (False, True, None, 0x62, 'something you don\'t yet have', None, None, None, None, 'unknown boy somethings again', 'a new mystery'), - 'Multi RNG': (False, True, None, 0x63, 'something you may already have', None, None, None, None, 'unknown boy somethings again', 'a total mystery'), - 'Magic Upgrade (1/2)': (True, False, None, 0x4E, 'Your magic\npower has been\ndoubled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'half magic'), # can be required to beat mothula in an open seed in very very rare circumstance - 'Magic Upgrade (1/4)': (True, False, None, 0x4F, 'Your magic\npower has been\nquadrupled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'quarter magic'), # can be required to beat mothula in an open seed in very very rare circumstance - 'Small Key (Eastern Palace)': (False, False, 'SmallKey', 0xA2, 'A small key to Armos Knights', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Eastern Palace'), - 'Big Key (Eastern Palace)': (False, False, 'BigKey', 0x9D, 'A big key to Armos Knights', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Eastern Palace'), - 'Compass (Eastern Palace)': (False, True, 'Compass', 0x8D, 'Now you can find the Armos Knights!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Eastern Palace'), - 'Map (Eastern Palace)': (False, True, 'Map', 0x7D, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Eastern Palace'), - 'Small Key (Desert Palace)': (False, False, 'SmallKey', 0xA3, 'A small key to the desert', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Desert Palace'), - 'Big Key (Desert Palace)': (False, False, 'BigKey', 0x9C, 'A big key to the desert', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Desert Palace'), - 'Compass (Desert Palace)': (False, True, 'Compass', 0x8C, 'Now you can find Lanmolas!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Desert Palace'), - 'Map (Desert Palace)': (False, True, 'Map', 0x7C, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Desert Palace'), - 'Small Key (Tower of Hera)': (False, False, 'SmallKey', 0xAA, 'A small key to Hera', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Tower of Hera'), - 'Big Key (Tower of Hera)': (False, False, 'BigKey', 0x95, 'A big key to Hera', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Tower of Hera'), - 'Compass (Tower of Hera)': (False, True, 'Compass', 0x85, 'Now you can find Moldorm!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Tower of Hera'), - 'Map (Tower of Hera)': (False, True, 'Map', 0x75, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Tower of Hera'), - 'Small Key (Escape)': (False, False, 'SmallKey', 0xA0, 'A small key to the castle', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Hyrule Castle'), - 'Big Key (Escape)': (False, False, 'BigKey', 0x9F, 'A big key to the castle', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Hyrule Castle'), - 'Compass (Escape)': (False, True, 'Compass', 0x8F, 'Now you can find no boss!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Hyrule Castle'), - 'Map (Escape)': (False, True, 'Map', 0x7F, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Hyrule Castle'), - 'Small Key (Agahnims Tower)': (False, False, 'SmallKey', 0xA4, 'A small key to Agahnim', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Castle Tower'), - 'Big Key (Agahnims Tower)': (False, False, 'BigKey', 0x9B, 'A big key to Agahnim', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Castle Tower'), - 'Compass (Agahnims Tower)': (False, True, 'Compass', 0x8B, 'Now you can find Aga1!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Castle Tower'), - 'Map (Agahnims Tower)': (False, True, 'Map', 0x7B, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Castle Tower'), - 'Small Key (Palace of Darkness)': (False, False, 'SmallKey', 0xA6, 'A small key to darkness', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Palace of Darkness'), - 'Big Key (Palace of Darkness)': (False, False, 'BigKey', 0x99, 'A big key to darkness', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Palace of Darkness'), - 'Compass (Palace of Darkness)': (False, True, 'Compass', 0x89, 'Now you can find Helmasaur King!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Palace of Darkness'), - 'Map (Palace of Darkness)': (False, True, 'Map', 0x79, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Palace of Darkness'), - 'Small Key (Thieves Town)': (False, False, 'SmallKey', 0xAB, 'A small key to thievery', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Thieves\' Town'), - 'Big Key (Thieves Town)': (False, False, 'BigKey', 0x94, 'A big key to thievery', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Thieves\' Town'), - 'Compass (Thieves Town)': (False, True, 'Compass', 0x84, 'Now you can find Blind!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Thieves\' Town'), - 'Map (Thieves Town)': (False, True, 'Map', 0x74, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Thieves\' Town'), - 'Small Key (Skull Woods)': (False, False, 'SmallKey', 0xA8, 'A small key to the woods', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Skull Woods'), - 'Big Key (Skull Woods)': (False, False, 'BigKey', 0x97, 'A big key to the woods', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Skull Woods'), - 'Compass (Skull Woods)': (False, True, 'Compass', 0x87, 'Now you can find Mothula!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Skull Woods'), - 'Map (Skull Woods)': (False, True, 'Map', 0x77, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Skull Woods'), - 'Small Key (Swamp Palace)': (False, False, 'SmallKey', 0xA5, 'A small key to the swamp', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Swamp Palace'), - 'Big Key (Swamp Palace)': (False, False, 'BigKey', 0x9A, 'A big key to the swamp', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Swamp Palace'), - 'Compass (Swamp Palace)': (False, True, 'Compass', 0x8A, 'Now you can find Arrghus!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Swamp Palace'), - 'Map (Swamp Palace)': (False, True, 'Map', 0x7A, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Swamp Palace'), - 'Small Key (Ice Palace)': (False, False, 'SmallKey', 0xA9, 'A small key to the iceberg', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ice Palace'), - 'Big Key (Ice Palace)': (False, False, 'BigKey', 0x96, 'A big key to the iceberg', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ice Palace'), - 'Compass (Ice Palace)': (False, True, 'Compass', 0x86, 'Now you can find Kholdstare!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ice Palace'), - 'Map (Ice Palace)': (False, True, 'Map', 0x76, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ice Palace'), - 'Small Key (Misery Mire)': (False, False, 'SmallKey', 0xA7, 'A small key to the mire', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Misery Mire'), - 'Big Key (Misery Mire)': (False, False, 'BigKey', 0x98, 'A big key to the mire', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Misery Mire'), - 'Compass (Misery Mire)': (False, True, 'Compass', 0x88, 'Now you can find Vitreous!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Misery Mire'), - 'Map (Misery Mire)': (False, True, 'Map', 0x78, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Misery Mire'), - 'Small Key (Turtle Rock)': (False, False, 'SmallKey', 0xAC, 'A small key to the pipe maze', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Turtle Rock'), - 'Big Key (Turtle Rock)': (False, False, 'BigKey', 0x93, 'A big key to the pipe maze', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Turtle Rock'), - 'Compass (Turtle Rock)': (False, True, 'Compass', 0x83, 'Now you can find Trinexx!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Turtle Rock'), - 'Map (Turtle Rock)': (False, True, 'Map', 0x73, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Turtle Rock'), - 'Small Key (Ganons Tower)': (False, False, 'SmallKey', 0xAD, 'A small key to the evil tower', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ganon\'s Tower'), - 'Big Key (Ganons Tower)': (False, False, 'BigKey', 0x92, 'A big key to the evil tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ganon\'s Tower'), - 'Compass (Ganons Tower)': (False, True, 'Compass', 0x82, 'Now you can find Agahnim!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a comapss to Ganon\'s Tower'), - 'Map (Ganons Tower)': (False, True, 'Map', 0x72, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ganon\'s Tower'), - 'Small Key (Universal)': (False, True, None, 0xAF, 'A small key for any door', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key'), - 'Nothing': (False, False, None, 0x5A, 'Some Hot Air', 'and the Nothing', 'the zen kid', 'outright theft', 'shroom theft', 'empty boy is bored again', 'nothing'), - 'Bee Trap': (False, False, None, 0xB0, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'friendship'), - 'Red Potion': (False, False, None, 0x2E, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'), - 'Green Potion': (False, False, None, 0x2F, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'), - 'Blue Potion': (False, False, None, 0x30, '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, '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, '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'), - 'Beat Agahnim 1': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Beat Agahnim 2': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Get Frog': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Return Smith': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Pick Up Purple Chest': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Open Floodgate': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Trench 1 Filled': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Trench 2 Filled': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Drained Swamp': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Shining Light': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Maiden Rescued': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Maiden Unmasked': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Convenient Block': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Zelda Herself': (True, False, 'Event', None, None, None, None, None, None, None, None), - 'Zelda Delivered': (True, False, 'Event', None, None, None, None, None, None, None, None), +item_table = {'Bow': (True, False, None, 0x0B, 300, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'), + 'Progressive Bow': (True, False, None, 0x64, 200, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), + 'Progressive Bow (Alt)': (True, False, None, 0x65, 200, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), + 'Book of Mudora': (True, False, None, 0x1D, 200, 'This is a\nparadox?!', 'and the story book', 'the scholarly kid', 'moon runes for sale', 'drugs for literacy', 'book-worm boy can read again', 'the Book'), + 'Hammer': (True, False, None, 0x09, 300, 'stop\nhammer time!', 'and m c hammer', 'hammer-smashing kid', 'm c hammer for sale', 'stop... hammer time', 'stop, hammer time', 'the hammer'), + 'Hookshot': (True, False, None, 0x0A, 300, 'BOING!!!\nBOING!!!\nBOING!!!', 'and the tickle beam', 'tickle-monster kid', 'tickle beam for sale', 'witch and tickle boy', 'beam boy tickles again', 'the Hookshot'), + 'Magic Mirror': (True, False, None, 0x1A, 300, 'Isn\'t your\nreflection so\npretty?', 'the face reflector', 'the narcissistic kid', 'your face for sale', 'trades looking-glass', 'narcissistic boy is happy again', 'the Mirror'), + 'Ocarina': (True, False, None, 0x14, 300, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'ocarina boy plays again', 'the Flute'), + 'Pegasus Boots': (True, False, None, 0x4B, 300, 'Gotta go fast!', 'and the sprint shoes', 'the running-man kid', 'sprint shoe for sale', 'shrooms for speed', 'gotta-go-fast boy runs again', 'the Boots'), + 'Power Glove': (True, False, None, 0x1B, 150, 'Now you can\nlift weak\nstuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the glove'), + 'Cape': (True, False, None, 0x19, 100, 'Wear this to\nbecome\ninvisible!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the cape'), + 'Mushroom': (True, False, None, 0x29, 100, 'I\'m a fun guy!\n\nI\'m a funghi!', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the mushroom'), + 'Shovel': (True, False, None, 0x13, 100, 'Can\n You\n Dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the shovel'), + 'Lamp': (True, False, None, 0x12, 200, 'Baby, baby,\nbaby.\nLight my way!', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the lamp'), + 'Magic Powder': (True, False, None, 0x0D, 100, 'you can turn\nanti-faeries\ninto faeries', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the powder'), + 'Moon Pearl': (True, False, None, 0x1F, 300, ' Bunny Link\n be\n gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the moon pearl'), + 'Cane of Somaria': (True, False, None, 0x15, 300, 'I make blocks\nto hold down\nswitches!', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the red cane'), + 'Fire Rod': (True, False, None, 0x07, 300, 'I\'m the hot\nrod. I make\nthings burn!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the fire rod'), + 'Flippers': (True, False, None, 0x1E, 300, 'fancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the flippers'), + 'Ice Rod': (True, False, None, 0x08, 300, 'I\'m the cold\nrod. I make\nthings freeze!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the ice rod'), + 'Titans Mitts': (True, False, None, 0x1C, 300, 'Now you can\nlift heavy\nstuff!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the mitts'), + 'Bombos': (True, False, None, 0x0F, 200, 'Burn, baby,\nburn! Fear my\nring of fire!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'medallion boy melts room again', 'Bombos'), + 'Ether': (True, False, None, 0x10, 200, 'This magic\ncoin freezes\neverything!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'medallion boy sees floor again', 'Ether'), + 'Quake': (True, False, None, 0x11, 200, 'Maxing out the\nRichter scale\nis what I do!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'medallion boy shakes dirt again', 'Quake'), + 'Bottle': (True, False, None, 0x16, 100, 'Now you can\nstore potions\nand stuff!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'bottle boy has terrarium again', 'a Bottle'), + 'Bottle (Red Potion)': (True, False, None, 0x2B, 130, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a Bottle'), + 'Bottle (Green Potion)': (True, False, None, 0x2C, 110, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a Bottle'), + 'Bottle (Blue Potion)': (True, False, None, 0x2D, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a Bottle'), + 'Bottle (Fairy)': (True, False, None, 0x3D, 150, 'Save me and I will revive you', 'and the captive', 'the tingle kid', 'hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a Bottle'), + 'Bottle (Bee)': (True, False, None, 0x3C, 100, '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 Bottle'), + 'Bottle (Good Bee)': (True, False, None, 0x48, 110, 'I will sting your foes a whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has beetor again', 'a Bottle'), + 'Master Sword': (True, False, 'Sword', 0x50, 150, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again', 'the Master Sword'), + 'Tempered Sword': (True, False, 'Sword', 0x02, 250, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'), + 'Fighter Sword': (True, False, 'Sword', 0x49, 50, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the small sword'), + 'Golden Sword': (True, False, 'Sword', 0x03, 300, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'), + 'Progressive Sword': (True, False, 'Sword', 0x5E, 200, 'a better copy\nof your sword\nfor your time', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again', 'a sword'), + 'Progressive Glove': (True, False, None, 0x61, 200, 'a way to lift\nheavier things', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a glove'), + 'Silver Arrows': (True, False, None, 0x58, 100, 'Do you fancy\nsilver tipped\narrows?', 'and the ganonsbane', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again', 'the silver arrows'), + 'Green Pendant': (True, False, 'Crystal', [0x04, 0x38, 0x62, 0x00, 0x69, 0x01], 999, None, None, None, None, None, None, None), + 'Blue Pendant': (True, False, 'Crystal', [0x02, 0x34, 0x60, 0x00, 0x69, 0x02], 999, None, None, None, None, None, None, None), + 'Red Pendant': (True, False, 'Crystal', [0x01, 0x32, 0x60, 0x00, 0x69, 0x03], 999, None, None, None, None, None, None, None), + 'Triforce': (True, False, None, 0x6A, 777, '\n YOU WIN!', 'and the triforce', 'victorious kid', 'victory for sale', 'fungus for the win', 'greedy boy wins game again', 'the Triforce'), + 'Power Star': (True, False, None, 0x6B, 50, 'a small victory', 'and the power star', 'star-struck kid', 'star for sale', 'see stars with shroom', 'mario powers up again', 'a Power Star'), + 'Triforce Piece': (True, False, None, 0x6C, 50, 'a small victory', 'and the thirdforce', 'triangular kid', 'triangle for sale', 'fungus for triangle', 'wise boy has triangle again', 'a Triforce Piece'), + 'Crystal 1': (True, False, 'Crystal', [0x02, 0x34, 0x64, 0x40, 0x7F, 0x06], 999, None, None, None, None, None, None, None), + 'Crystal 2': (True, False, 'Crystal', [0x10, 0x34, 0x64, 0x40, 0x79, 0x06], 999, None, None, None, None, None, None, None), + 'Crystal 3': (True, False, 'Crystal', [0x40, 0x34, 0x64, 0x40, 0x6C, 0x06], 999, None, None, None, None, None, None, None), + 'Crystal 4': (True, False, 'Crystal', [0x20, 0x34, 0x64, 0x40, 0x6D, 0x06], 999, None, None, None, None, None, None, None), + 'Crystal 5': (True, False, 'Crystal', [0x04, 0x32, 0x64, 0x40, 0x6E, 0x06], 999, None, None, None, None, None, None, None), + 'Crystal 6': (True, False, 'Crystal', [0x01, 0x32, 0x64, 0x40, 0x6F, 0x06], 999, None, None, None, None, None, None, None), + 'Crystal 7': (True, False, 'Crystal', [0x08, 0x34, 0x64, 0x40, 0x7C, 0x06], 999, None, None, None, None, None, None, None), + 'Single Arrow': (False, False, None, 0x43, 3, 'a lonely arrow\nsits here.', 'and the arrow', 'stick-collecting kid', 'sewing needle for sale', 'fungus for arrow', 'archer boy sews again', 'an arrow'), + 'Arrows (10)': (False, False, None, 0x44, 30, 'This will give\nyou ten shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'ten arrows'), + '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'), + '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'), + 'Bomb Upgrade (+5)': (False, False, None, 0x51, 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'), + 'Blue Mail': (False, True, None, 0x22, 100, 'Now you\'re a\nblue elf!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the blue mail'), + 'Red Mail': (False, True, None, 0x23, 200, 'Now you\'re a\nred elf!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the red mail'), + 'Progressive Armor': (False, True, None, 0x60, 100, 'time for a\nchange of\nclothes?', 'and the unknown hat', 'the protected kid', 'new hat for sale', 'the clothing store', 'tailor boy has threads again', 'some armor'), + 'Blue Boomerang': (True, False, None, 0x0C, 100, 'No matter what\nyou do, blue\nreturns to you', 'and the bluemarang', 'the bat-throwing kid', 'bent stick for sale', 'fungus for puma-stick', 'throwing boy plays fetch again', 'the blue boomerang'), + 'Red Boomerang': (True, False, None, 0x2A, 100, 'No matter what\nyou do, red\nreturns to you', 'and the badmarang', 'the bat-throwing kid', 'air foil for sale', 'fungus for return-stick', 'magical boy plays fetch again', 'the red boomerang'), + 'Blue Shield': (False, True, None, 0x04, 50, 'Now you can\ndefend against\npebbles!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'the blue shield'), + 'Red Shield': (False, True, None, 0x05, 500, 'Now you can\ndefend against\nfireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'the red shield'), + 'Mirror Shield': (True, False, None, 0x06, 300, 'Now you can\ndefend against\nlasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the mirror shield'), + 'Progressive Shield': (True, False, None, 0x5F, 100, 'have a better\nblocker in\nfront of you', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'), + 'Bug Catching Net': (True, False, None, 0x21, 100, 'Let\'s catch\nsome bees and\nfaeries!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the bug net'), + 'Cane of Byrna': (True, False, None, 0x18, 100, 'Use this to\nbecome\ninvincible!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the blue cane'), + 'Boss Heart Container': (False, False, None, 0x3E, 80, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'), + 'Sanctuary Heart Container': (False, False, None, 0x3F, 100, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'), + 'Piece of Heart': (False, False, None, 0x17, 20, 'Just a little\npiece of love!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'), + 'Rupee (1)': (False, False, None, 0x34, 0, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'), + 'Rupees (5)': (False, False, None, 0x35, 2, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'), + 'Rupees (20)': (False, False, None, 0x36, 10, 'Just couch\ncash. Move\nright along.', 'and the couch cash', 'the piggy-bank kid', 'life lesson for sale', 'the witch buying drugs', 'destitute boy has lunch again', 'a red rupee'), + 'Rupees (50)': (False, False, None, 0x41, 25, 'A rupee pile!\nOkay?', 'and the rupee pile', 'the well-off kid', 'life lesson for sale', 'buying okay drugs', 'destitute boy has dinner again', 'fifty rupees'), + 'Rupees (100)': (False, False, None, 0x40, 50, 'A rupee stash!\nHell yeah!', 'and the rupee stash', 'the kind-of-rich kid', 'life lesson for sale', 'buying good drugs', 'affluent boy goes drinking again', 'one hundred rupees'), + 'Rupees (300)': (False, False, None, 0x46, 150, 'A rupee hoard!\nHell yeah!', 'and the rupee hoard', 'the really-rich kid', 'life lesson for sale', 'buying the best drugs', 'fat-cat boy is rich again', 'three hundred rupees'), + 'Rupoor': (False, False, None, 0x59, 0, 'a debt collector', 'and the toll-booth', 'the toll-booth kid', 'double loss for sale', 'witch stole your rupees', 'affluent boy steals rupees', 'a rupoor'), + 'Red Clock': (False, True, None, 0x5B, 0, 'a waste of time', 'the ruby clock', 'the ruby-time kid', 'red time for sale', 'for ruby time', 'moment boy travels time again', 'a red clock'), + 'Blue Clock': (False, True, None, 0x5C, 50, 'a bit of time', 'the sapphire clock', 'sapphire-time kid', 'blue time for sale', 'for sapphire time', 'moment boy time travels again', 'a blue clock'), + 'Green Clock': (False, True, None, 0x5D, 200, 'a lot of time', 'the emerald clock', 'the emerald-time kid', 'green time for sale', 'for emerald time', 'moment boy adjusts time again', 'a red clock'), + 'Single RNG': (False, True, None, 0x62, 300, 'something you don\'t yet have', None, None, None, None, 'unknown boy somethings again', 'a new mystery'), + 'Multi RNG': (False, True, None, 0x63, 100, 'something you may already have', None, None, None, None, 'unknown boy somethings again', 'a total mystery'), + 'Magic Upgrade (1/2)': (True, False, None, 0x4E, 100, 'Your magic\npower has been\ndoubled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'half magic'), # can be required to beat mothula in an open seed in very very rare circumstance + 'Magic Upgrade (1/4)': (True, False, None, 0x4F, 200, 'Your magic\npower has been\nquadrupled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'quarter magic'), # can be required to beat mothula in an open seed in very very rare circumstance + 'Small Key (Eastern Palace)': (False, False, 'SmallKey', 0xA2, 50, 'A small key to Armos Knights', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Eastern Palace'), + 'Big Key (Eastern Palace)': (False, False, 'BigKey', 0x9D, 100, 'A big key to Armos Knights', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Eastern Palace'), + 'Compass (Eastern Palace)': (False, True, 'Compass', 0x8D, 10, 'Now you can find the Armos Knights!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Eastern Palace'), + 'Map (Eastern Palace)': (False, True, 'Map', 0x7D, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Eastern Palace'), + 'Small Key (Desert Palace)': (False, False, 'SmallKey', 0xA3, 50, 'A small key to the desert', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Desert Palace'), + 'Big Key (Desert Palace)': (False, False, 'BigKey', 0x9C, 100, 'A big key to the desert', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Desert Palace'), + 'Compass (Desert Palace)': (False, True, 'Compass', 0x8C, 10, 'Now you can find Lanmolas!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Desert Palace'), + 'Map (Desert Palace)': (False, True, 'Map', 0x7C, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Desert Palace'), + 'Small Key (Tower of Hera)': (False, False, 'SmallKey', 0xAA, 50, 'A small key to Hera', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Tower of Hera'), + 'Big Key (Tower of Hera)': (False, False, 'BigKey', 0x95, 100, 'A big key to Hera', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Tower of Hera'), + 'Compass (Tower of Hera)': (False, True, 'Compass', 0x85, 10, 'Now you can find Moldorm!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Tower of Hera'), + 'Map (Tower of Hera)': (False, True, 'Map', 0x75, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Tower of Hera'), + 'Small Key (Escape)': (False, False, 'SmallKey', 0xA0, 50, 'A small key to the castle', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Hyrule Castle'), + 'Big Key (Escape)': (False, False, 'BigKey', 0x9F, 100, 'A big key to the castle', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Hyrule Castle'), + 'Compass (Escape)': (False, True, 'Compass', 0x8F, 10, 'Now you can find no boss!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Hyrule Castle'), + 'Map (Escape)': (False, True, 'Map', 0x7F, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Hyrule Castle'), + 'Small Key (Agahnims Tower)': (False, False, 'SmallKey', 0xA4, 50, 'A small key to Agahnim', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Castle Tower'), + 'Big Key (Agahnims Tower)': (False, False, 'BigKey', 0x9B, 100, 'A big key to Agahnim', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Castle Tower'), + 'Compass (Agahnims Tower)': (False, True, 'Compass', 0x8B, 10, 'Now you can find Aga1!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Castle Tower'), + 'Map (Agahnims Tower)': (False, True, 'Map', 0x7B, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Castle Tower'), + 'Small Key (Palace of Darkness)': (False, False, 'SmallKey', 0xA6, 50, 'A small key to darkness', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Palace of Darkness'), + 'Big Key (Palace of Darkness)': (False, False, 'BigKey', 0x99, 100, 'A big key to darkness', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Palace of Darkness'), + 'Compass (Palace of Darkness)': (False, True, 'Compass', 0x89, 10, 'Now you can find Helmasaur King!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Palace of Darkness'), + 'Map (Palace of Darkness)': (False, True, 'Map', 0x79, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Palace of Darkness'), + 'Small Key (Thieves Town)': (False, False, 'SmallKey', 0xAB, 50, 'A small key to thievery', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Thieves\' Town'), + 'Big Key (Thieves Town)': (False, False, 'BigKey', 0x94, 100, 'A big key to thievery', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Thieves\' Town'), + 'Compass (Thieves Town)': (False, True, 'Compass', 0x84, 10, 'Now you can find Blind!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Thieves\' Town'), + 'Map (Thieves Town)': (False, True, 'Map', 0x74, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Thieves\' Town'), + 'Small Key (Skull Woods)': (False, False, 'SmallKey', 0xA8, 50, 'A small key to the woods', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Skull Woods'), + 'Big Key (Skull Woods)': (False, False, 'BigKey', 0x97, 100, 'A big key to the woods', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Skull Woods'), + 'Compass (Skull Woods)': (False, True, 'Compass', 0x87, 10, 'Now you can find Mothula!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Skull Woods'), + 'Map (Skull Woods)': (False, True, 'Map', 0x77, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Skull Woods'), + 'Small Key (Swamp Palace)': (False, False, 'SmallKey', 0xA5, 50, 'A small key to the swamp', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Swamp Palace'), + 'Big Key (Swamp Palace)': (False, False, 'BigKey', 0x9A, 100, 'A big key to the swamp', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Swamp Palace'), + 'Compass (Swamp Palace)': (False, True, 'Compass', 0x8A, 10, 'Now you can find Arrghus!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Swamp Palace'), + 'Map (Swamp Palace)': (False, True, 'Map', 0x7A, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Swamp Palace'), + 'Small Key (Ice Palace)': (False, False, 'SmallKey', 0xA9, 50, 'A small key to the iceberg', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ice Palace'), + 'Big Key (Ice Palace)': (False, False, 'BigKey', 0x96, 100, 'A big key to the iceberg', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ice Palace'), + 'Compass (Ice Palace)': (False, True, 'Compass', 0x86, 10, 'Now you can find Kholdstare!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ice Palace'), + 'Map (Ice Palace)': (False, True, 'Map', 0x76, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ice Palace'), + 'Small Key (Misery Mire)': (False, False, 'SmallKey', 0xA7, 50, 'A small key to the mire', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Misery Mire'), + 'Big Key (Misery Mire)': (False, False, 'BigKey', 0x98, 100, 'A big key to the mire', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Misery Mire'), + 'Compass (Misery Mire)': (False, True, 'Compass', 0x88, 10, 'Now you can find Vitreous!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Misery Mire'), + 'Map (Misery Mire)': (False, True, 'Map', 0x78, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Misery Mire'), + 'Small Key (Turtle Rock)': (False, False, 'SmallKey', 0xAC, 50, 'A small key to the pipe maze', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Turtle Rock'), + 'Big Key (Turtle Rock)': (False, False, 'BigKey', 0x93, 100, 'A big key to the pipe maze', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Turtle Rock'), + 'Compass (Turtle Rock)': (False, True, 'Compass', 0x83, 10, 'Now you can find Trinexx!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Turtle Rock'), + 'Map (Turtle Rock)': (False, True, 'Map', 0x73, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Turtle Rock'), + 'Small Key (Ganons Tower)': (False, False, 'SmallKey', 0xAD, 50, 'A small key to the evil tower', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ganon\'s Tower'), + 'Big Key (Ganons Tower)': (False, False, 'BigKey', 0x92, 100, 'A big key to the evil tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ganon\'s Tower'), + 'Compass (Ganons Tower)': (False, True, 'Compass', 0x82, 10, 'Now you can find Agahnim!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a comapss to Ganon\'s Tower'), + 'Map (Ganons Tower)': (False, True, 'Map', 0x72, 50, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ganon\'s Tower'), + 'Small Key (Universal)': (False, True, None, 0xAF, 100, 'A small key for any door', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key'), + 'Nothing': (False, False, None, 0x5A, 1, 'Some Hot Air', 'and the Nothing', 'the zen kid', 'outright theft', 'shroom theft', 'empty boy is bored again', 'nothing'), + 'Bee Trap': (False, False, None, 0xB0, 0, 'We will sting your face a whole lot!', 'and the sting buddies', 'the beekeeper kid', 'insects for sale', 'shroom pollenation', 'bottle boy has mad bees again', 'friendship'), + 'Red Potion': (False, False, None, 0x2E, 150, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a red potion'), + 'Green Potion': (False, False, None, 0x2F, 60, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a green potion'), + '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'), + '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), + 'Return Smith': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Pick Up Purple Chest': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Open Floodgate': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Trench 1 Filled': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Trench 2 Filled': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Drained Swamp': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Shining Light': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Maiden Rescued': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Maiden Unmasked': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Convenient Block': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Zelda Herself': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), + 'Zelda Delivered': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), } diff --git a/Main.py b/Main.py index aaed4a61..721541bc 100644 --- a/Main.py +++ b/Main.py @@ -21,11 +21,12 @@ from DoorShuffle import link_doors, connect_portal_copy from RoomData import create_rooms from Rules import set_rules from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive -from Fill import distribute_items_cutoff, distribute_items_staleness, distribute_items_restrictive, flood_items, balance_multiworld_progression -from ItemList import generate_itempool, difficulties, fill_prizes, fill_specific_items +from Fill import distribute_items_cutoff, distribute_items_staleness, distribute_items_restrictive, flood_items, sell_keys, balance_multiworld_progression +from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops from Utils import output_path, parse_player_names -__version__ = '0.2.0.18u' +__version__ = '0.2.1.0-u' + class EnemizerError(RuntimeError): pass @@ -70,6 +71,7 @@ def main(args, seed=None, fish=None): world.dungeon_counters = args.dungeon_counters.copy() world.potshuffle = args.shufflepots.copy() world.fish = fish + world.shopsanity = args.shopsanity.copy() world.keydropshuffle = args.keydropshuffle.copy() world.mixed_travel = args.mixed_travel.copy() world.standardize_palettes = args.standardize_palettes.copy() @@ -147,6 +149,10 @@ def main(args, seed=None, fish=None): for player in range(1, world.players + 1): set_rules(world, player) + for player in range(1, world.players + 1): + if world.retro[player] and world.shopsanity[player]: + sell_keys(world, player) + logger.info(world.fish.translate("cli","cli","placing.dungeon.prizes")) fill_prizes(world) @@ -205,6 +211,10 @@ def main(args, seed=None, fish=None): if not world.can_beat_game(): raise RuntimeError(world.fish.translate("cli","cli","cannot.beat.game")) + for player in range(1, world.players+1): + if world.shopsanity[player]: + customize_shops(world, player) + outfilebase = 'DR_%s' % (args.outputname if args.outputname else world.seed) rom_names = [] @@ -398,6 +408,7 @@ def copy_world(world): ret.beemizer = world.beemizer.copy() ret.intensity = world.intensity.copy() ret.experimental = world.experimental.copy() + ret.shopsanity = world.shopsanity.copy() ret.keydropshuffle = world.keydropshuffle.copy() ret.mixed_travel = world.mixed_travel.copy() ret.standardize_palettes = world.standardize_palettes.copy() @@ -426,9 +437,10 @@ def copy_world(world): for level, boss in dungeon.bosses.items(): ret.get_dungeon(dungeon.name, dungeon.player).bosses[level] = boss - for shop in world.shops: - copied_shop = ret.get_region(shop.region.name, shop.region.player).shop - copied_shop.inventory = copy.copy(shop.inventory) + for player in range(1, world.players + 1): + for shop in world.shops[player]: + copied_shop = ret.get_region(shop.region.name, shop.region.player).shop + copied_shop.inventory = copy.copy(shop.inventory) # connect copied world for region in world.regions: @@ -490,6 +502,7 @@ def copy_world(world): return ret + def copy_dynamic_regions_and_locations(world, ret): for region in world.dynamic_regions: new_reg = Region(region.name, region.type, region.hint_text, region.player) @@ -501,7 +514,7 @@ def copy_dynamic_regions_and_locations(world, ret): if region.shop: new_reg.shop = Shop(new_reg, region.shop.room_id, region.shop.type, region.shop.shopkeeper_config, region.shop.custom, region.shop.locked) - ret.shops.append(new_reg.shop) + ret.shops[region.player].append(new_reg.shop) for location in world.dynamic_locations: new_reg = ret.get_region(location.parent_region.name, location.parent_region.player) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 46f32ff9..b48a6dc5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -28,7 +28,13 @@ * Known issues: * Palettes aren't perfect * Some ugly colors - * Invisible floors can be see in many palettes + * Invisible floors can be see in many palettes + +## Shopsanity + +--shopsanity added. This adds 29 shop locations (9 more in retro) to the general and location pool. + +** **Todo** **: add more info here. ## Key Drop Shuffle diff --git a/Regions.py b/Regions.py index fb991200..ee251a18 100644 --- a/Regions.py +++ b/Regions.py @@ -1,4 +1,5 @@ import collections +from Items import ItemFactory from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType @@ -38,7 +39,7 @@ def create_regions(world, player): create_cave_region(player, 'Bush Covered House', 'the grass man'), create_cave_region(player, 'Tavern (Front)', 'the tavern'), create_cave_region(player, 'Light World Bomb Hut', 'a restock room'), - create_cave_region(player, 'Kakariko Shop', 'a common shop'), + create_cave_region(player, 'Kakariko Shop', 'a common shop', ['Kakariko Shop - Left', 'Kakariko Shop - Middle', 'Kakariko Shop - Right']), create_cave_region(player, 'Fortune Teller (Light)', 'a fortune teller'), create_cave_region(player, 'Lake Hylia Fortune Teller', 'a fortune teller'), create_cave_region(player, 'Lumberjack House', 'a boring house'), @@ -78,14 +79,14 @@ def create_regions(world, player): create_cave_region(player, 'Ice Rod Cave', 'a cave with a chest', ['Ice Rod Cave']), create_cave_region(player, 'Good Bee Cave', 'a cold bee'), create_cave_region(player, '20 Rupee Cave', 'a cave with some cash'), - create_cave_region(player, 'Cave Shop (Lake Hylia)', 'a common shop'), - create_cave_region(player, 'Cave Shop (Dark Death Mountain)', 'a common shop'), + create_cave_region(player, 'Cave Shop (Lake Hylia)', 'a common shop', ['Lake Hylia Shop - Left', 'Lake Hylia Shop - Middle', 'Lake Hylia Shop - Right']), + create_cave_region(player, 'Cave Shop (Dark Death Mountain)', 'a common shop', ['Dark Death Mountain Shop - Left', 'Dark Death Mountain Shop - Middle', 'Dark Death Mountain Shop - Right']), create_cave_region(player, 'Bonk Rock Cave', 'a cave with a chest', ['Bonk Rock Cave']), create_cave_region(player, 'Library', 'the library', ['Library']), create_cave_region(player, 'Kakariko Gamble Game', 'a game of chance'), create_cave_region(player, 'Potion Shop', 'the potion shop', ['Potion Shop']), create_lw_region(player, 'Lake Hylia Island', ['Lake Hylia Island']), - create_cave_region(player, 'Capacity Upgrade', 'the queen of fairies'), + create_cave_region(player, 'Capacity Upgrade', 'the queen of fairies', ['Capacity Upgrade - Left', 'Capacity Upgrade - Right']), create_cave_region(player, 'Two Brothers House', 'a connector', None, ['Two Brothers House Exit (East)', 'Two Brothers House Exit (West)']), create_lw_region(player, 'Maze Race Ledge', ['Maze Race'], ['Two Brothers House (West)']), create_cave_region(player, '50 Rupee Cave', 'a cave with some cash'), @@ -122,7 +123,7 @@ def create_regions(world, player): 'Paradox Cave Upper - Right'], ['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']), create_cave_region(player, 'Paradox Cave', 'a connector', None, ['Paradox Cave Exit (Middle)', 'Paradox Cave Exit (Top)', 'Paradox Cave Drop']), - create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop'), + create_cave_region(player, 'Light World Death Mountain Shop', 'a common shop', ['Paradox Shop - Left', 'Paradox Shop - Middle', 'Paradox Shop - Right']), create_lw_region(player, 'East Death Mountain (Top)', None, ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'Turtle Rock Teleporter', 'Fairy Ascension Ledge']), create_lw_region(player, 'Spiral Cave Ledge', None, ['Spiral Cave', 'Spiral Cave Ledge Drop']), create_cave_region(player, 'Spiral Cave (Top)', 'a connector', ['Spiral Cave'], ['Spiral Cave (top to bottom)', 'Spiral Cave Exit (Top)']), @@ -157,16 +158,16 @@ def create_regions(world, player): create_dw_region(player, 'Hammer Peg Area', ['Dark Blacksmith Ruins'], ['Bat Cave Drop Ledge Mirror Spot', 'Dark World Hammer Peg Cave', 'Peg Area Rocks']), create_dw_region(player, 'Bumper Cave Entrance', None, ['Bumper Cave (Bottom)', 'Bumper Cave Entrance Mirror Spot', 'Bumper Cave Entrance Drop']), create_cave_region(player, 'Fortune Teller (Dark)', 'a fortune teller'), - create_cave_region(player, 'Village of Outcasts Shop', 'a common shop'), - create_cave_region(player, 'Dark Lake Hylia Shop', 'a common shop'), - create_cave_region(player, 'Dark World Lumberjack Shop', 'a common shop'), - create_cave_region(player, 'Dark World Potion Shop', 'a common shop'), + create_cave_region(player, 'Village of Outcasts Shop', 'a common shop', ['Village of Outcasts Shop - Left', 'Village of Outcasts Shop - Middle', 'Village of Outcasts Shop - Right']), + create_cave_region(player, 'Dark Lake Hylia Shop', 'a common shop', ['Dark Lake Hylia Shop - Left', 'Dark Lake Hylia Shop - Middle', 'Dark Lake Hylia Shop - Right']), + create_cave_region(player, 'Dark World Lumberjack Shop', 'a common shop', ['Dark Lumberjack Shop - Left', 'Dark Lumberjack Shop - Middle', 'Dark Lumberjack Shop - Right']), + create_cave_region(player, 'Dark World Potion Shop', 'a common shop', ['Dark Potion Shop - Left', 'Dark Potion Shop - Middle', 'Dark Potion Shop - Right']), create_cave_region(player, 'Dark World Hammer Peg Cave', 'a cave with an item', ['Peg Cave']), create_cave_region(player, 'Pyramid Fairy', 'a cave with two chests', ['Pyramid Fairy - Left', 'Pyramid Fairy - Right']), create_cave_region(player, 'Brewery', 'a house with a chest', ['Brewery']), create_cave_region(player, 'C-Shaped House', 'a house with a chest', ['C-Shaped House']), create_cave_region(player, 'Chest Game', 'a game of 16 chests', ['Chest Game']), - create_cave_region(player, 'Red Shield Shop', 'the rare shop'), + create_cave_region(player, 'Red Shield Shop', 'the rare shop', ['Red Shield Shop - Left', 'Red Shield Shop - Middle', 'Red Shield Shop - Right']), create_cave_region(player, 'Dark Sanctuary Hint', 'a storyteller'), create_cave_region(player, 'Bumper Cave', 'a connector', None, ['Bumper Cave Exit (Bottom)', 'Bumper Cave Exit (Top)']), create_dw_region(player, 'Bumper Cave Ledge', ['Bumper Cave Ledge'], ['Bumper Cave Ledge Drop', 'Bumper Cave (Top)', 'Bumper Cave Ledge Mirror Spot']), @@ -857,6 +858,7 @@ def mark_light_world_regions(world, player): def create_shops(world, player): + world.shops[player] = [] for region_name, (room_id, type, shopkeeper, custom, locked, inventory) in shop_table.items(): if world.mode[player] == 'inverted' and region_name == 'Dark Lake Hylia Shop': locked = True @@ -864,9 +866,16 @@ def create_shops(world, player): region = world.get_region(region_name, player) shop = Shop(region, room_id, type, shopkeeper, custom, locked) region.shop = shop - world.shops.append(shop) + world.shops[player].append(shop) for index, item in enumerate(inventory): shop.add_inventory(index, *item) + if not world.shopsanity[player]: + if region_name in shop_to_location_table.keys(): + for index, location in enumerate(shop_to_location_table[region_name]): + loc = world.get_location(location, player) + loc.skip = True + loc.forced_item = loc.item = ItemFactory(shop.inventory[index]['item'], player) + loc.item.location = loc def adjust_locations(world, player): @@ -909,6 +918,29 @@ shop_table = { 'Capacity Upgrade': (0x0115, ShopType.UpgradeShop, 0x04, True, True, [('Bomb Upgrade (+5)', 100, 7), ('Arrow Upgrade (+5)', 100, 7)]) } + +shop_to_location_table = { + 'Cave Shop (Dark Death Mountain)': ['Dark Death Mountain Shop - Left', 'Dark Death Mountain Shop - Middle', 'Dark Death Mountain Shop - Right'], + 'Red Shield Shop': ['Red Shield Shop - Left', 'Red Shield Shop - Middle', 'Red Shield Shop - Right'], + 'Dark Lake Hylia Shop': ['Dark Lake Hylia Shop - Left', 'Dark Lake Hylia Shop - Middle', 'Dark Lake Hylia Shop - Right'], + 'Dark World Lumberjack Shop': ['Dark Lumberjack Shop - Left', 'Dark Lumberjack Shop - Middle', 'Dark Lumberjack Shop - Right'], + 'Village of Outcasts Shop': ['Village of Outcasts Shop - Left', 'Village of Outcasts Shop - Middle', 'Village of Outcasts Shop - Right'], + 'Dark World Potion Shop': ['Dark Potion Shop - Left', 'Dark Potion Shop - Middle', 'Dark Potion Shop - Right'], + 'Light World Death Mountain Shop': ['Paradox Shop - Left', 'Paradox Shop - Middle', 'Paradox Shop - Right'], + 'Kakariko Shop': ['Kakariko Shop - Left', 'Kakariko Shop - Middle', 'Kakariko Shop - Right'], + 'Cave Shop (Lake Hylia)': ['Lake Hylia Shop - Left', 'Lake Hylia Shop - Middle', 'Lake Hylia Shop - Right'], + 'Capacity Upgrade': ['Capacity Upgrade - Left', 'Capacity Upgrade - Right'], +} + +retro_shops = { + 'Old Man Sword Cave': ['Old Man Sword Cave Item 1'], + 'Take-Any #1': ['Take-Any #1 Item 1', 'Take-Any #1 Item 2'], + 'Take-Any #2': ['Take-Any #2 Item 1', 'Take-Any #2 Item 2'], + 'Take-Any #3': ['Take-Any #3 Item 1', 'Take-Any #3 Item 2'], + 'Take-Any #4': ['Take-Any #4 Item 1', 'Take-Any #4 Item 2'], +} + + key_drop_data = { 'Hyrule Castle - Map Guard Key Drop': [0x140036, 0x140037, 'in Hyrule Castle', 'Small Key (Escape)'], 'Hyrule Castle - Boomerang Guard Key Drop': [0x140033, 0x140034, 'in Hyrule Castle', 'Small Key (Escape)'], @@ -1202,7 +1234,37 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Skull Woods - Prize': ([0x120A3, 0x53F12, 0x53F13, 0x180058, 0x18007B, 0xC704], None, True, 'Skull Woods'), 'Ice Palace - Prize': ([0x120A4, 0x53F5A, 0x53F5B, 0x180059, 0x180073, 0xC705], None, True, 'Ice Palace'), 'Misery Mire - Prize': ([0x120A2, 0x53F48, 0x53F49, 0x180057, 0x180075, 0xC703], None, True, 'Misery Mire'), - 'Turtle Rock - Prize': ([0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], None, True, 'Turtle Rock')} + 'Turtle Rock - Prize': ([0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], None, True, 'Turtle Rock'), + 'Kakariko Shop - Left': (None, None, False, 'for sale in Kakariko'), + 'Kakariko Shop - Middle': (None, None, False, 'for sale in Kakariko'), + 'Kakariko Shop - Right': (None, None, False, 'for sale in Kakariko'), + 'Lake Hylia Shop - Left': (None, None, False, 'for sale near the lake'), + 'Lake Hylia Shop - Middle': (None, None, False, 'for sale near the lake'), + 'Lake Hylia Shop - Right': (None, None, False, 'for sale near the lake'), + 'Paradox Shop - Left': (None, None, False, 'for sale near seven chests'), + 'Paradox Shop - Middle': (None, None, False, 'for sale near seven chests'), + 'Paradox Shop - Right': (None, None, False, 'for sale near seven chests'), + 'Capacity Upgrade - Left': (None, None, False, 'for sale near the queen'), + 'Capacity Upgrade - Right': (None, None, False, 'for sale near the queen'), + 'Village of Outcasts Shop - Left': (None, None, False, 'for sale near outcasts'), + 'Village of Outcasts Shop - Middle': (None, None, False, 'for sale near outcasts'), + 'Village of Outcasts Shop - Right': (None, None, False, 'for sale near outcasts'), + 'Dark Lumberjack Shop - Left': (None, None, False, 'for sale in the far north'), + 'Dark Lumberjack Shop - Middle': (None, None, False, 'for sale in the far north'), + 'Dark Lumberjack Shop - Right': (None, None, False, 'for sale in the far north'), + 'Dark Lake Hylia Shop - Left': (None, None, False, 'for sale near the dark lake'), + 'Dark Lake Hylia Shop - Middle': (None, None, False, 'for sale near the dark lake'), + 'Dark Lake Hylia Shop - Right': (None, None, False, 'for sale near the dark lake'), + 'Dark Potion Shop - Left': (None, None, False, 'for sale near a catfish'), + 'Dark Potion Shop - Middle': (None, None, False, 'for sale near a catfish'), + 'Dark Potion Shop - Right': (None, None, False, 'for sale near a catfish'), + 'Dark Death Mountain Shop - Left': (None, None, False, 'for sale on the dark mountain'), + 'Dark Death Mountain Shop - Middle': (None, None, False, 'for sale on the dark mountain'), + 'Dark Death Mountain Shop - Right': (None, None, False, 'for sale on the dark mountain'), + 'Red Shield Shop - Left': (None, None, False, 'for sale as a curiosity'), + 'Red Shield Shop - Middle': (None, None, False, 'for sale as a curiosity'), + 'Red Shield Shop - Right': (None, None, False, 'for sale as a curiosity') + } lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int} lookup_id_to_name = {**lookup_id_to_name, **{data[1]: name for name, data in key_drop_data.items()}} diff --git a/Rom.py b/Rom.py index 620470e9..4d24a0c7 100644 --- a/Rom.py +++ b/Rom.py @@ -27,7 +27,7 @@ from EntranceShuffle import door_addresses, exit_ids JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '185a0f74ab0e2ce8899c8d7d309ca68c' +RANDOMIZERBASEHASH = '7264ffb7c430dde5d6bfe6030b79a575' class JsonRom(object): @@ -1493,7 +1493,7 @@ def patch_race_rom(rom): RaceRom.encrypt(rom) def write_custom_shops(rom, world, player): - shops = [shop for shop in world.shops if shop.custom and shop.region.player == player] + shops = [shop for shop in world.shops[player] if shop.custom and shop.region.player == player] shop_data = bytearray() items_data = bytearray() diff --git a/data/base2current.bps b/data/base2current.bps index 61323175649e7f91ca4f97404fb5a9657034ca8d..c0d427e88d6a9a8fd8616fdbae990a34d1d21e78 100644 GIT binary patch delta 11079 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 YmJN|Jm$@~7@8H>AYO(A*^5N_M1K}I4x&QzG delta 11088 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