Standing Items initial commit

This commit is contained in:
aerinon
2021-12-16 16:02:11 -07:00
parent c651d1d584
commit b2f2565271
26 changed files with 618 additions and 469 deletions

View File

@@ -139,7 +139,7 @@ class World(object):
set_player_attr('pseudoboots', False)
set_player_attr('shopsanity', False)
set_player_attr('keydropshuffle', False)
set_player_attr('keydropshuffle', 'none')
set_player_attr('mixed_travel', 'prevent')
set_player_attr('standardize_palettes', 'standardize')
set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False})
@@ -2119,6 +2119,7 @@ class Location(object):
self.item_rule = lambda item: True
self.player = player
self.skip = False
self.type = LocationType.Normal if not crystal else LocationType.Prize
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)))
@@ -2158,6 +2159,15 @@ class Location(object):
return hash((self.name, self.player))
class LocationType(FastEnum):
Normal = 0
Prize = 1
Logical = 2
Shop = 3
Pot = 4
Drop = 5
class Item(object):
def __init__(self, name='', advancement=False, priority=False, type=None, code=None, price=999, pedestal_hint=None,
@@ -2519,6 +2529,7 @@ class Spoiler(object):
outfile.write(f"Link's House Shuffled: {yn(self.metadata['shufflelinks'])}\n")
outfile.write('Door Shuffle: %s\n' % self.metadata['door_shuffle'][player])
outfile.write('Intensity: %s\n' % self.metadata['intensity'][player])
outfile.write(f"Drop Shuffle Mode: {self.metadata['keydropshuffle'][player]}\n")
addition = ' (Random)' if self.world.crystals_gt_orig[player] == 'random' else ''
outfile.write('Crystals required for GT: %s\n' % (str(self.metadata['gt_crystals'][player]) + addition))
addition = ' (Random)' if self.world.crystals_ganon_orig[player] == 'random' else ''
@@ -2537,7 +2548,6 @@ class Spoiler(object):
outfile.write(f"Pot shuffle: {yn(self.metadata['potshuffle'][player])}\n")
outfile.write(f"Hints: {yn(self.metadata['hints'][player])}\n")
outfile.write(f"Experimental: {yn(self.metadata['experimental'][player])}\n")
outfile.write(f"Key Drops shuffled: {yn(self.metadata['keydropshuffle'][player])}\n")
outfile.write(f"Shopsanity: {yn(self.metadata['shopsanity'][player])}\n")
outfile.write(f"Bombbag: {yn(self.metadata['bombbag'][player])}\n")
outfile.write(f"Pseudoboots: {yn(self.metadata['pseudoboots'][player])}\n")
@@ -2681,6 +2691,8 @@ class PotFlags(FastEnum):
Normal = 0x0
NoSwitch = 0x1 # A switch should never go here
SwitchLogicChange = 0x2 # A switch can go here, but requires a logic change
Block = 0x4 # This is actually a block
LowerRegion = 0x8 # This is a pot in the lower region
class Pot(object):
@@ -2690,6 +2702,23 @@ class Pot(object):
self.item = item
self.room = room
self.flags = flags
self.indicator = None # 0x80 for standing item, 0xC0 multiworld item
self.standing_item_code = None # standing item code if nay
def copy(self):
return Pot(self.x, self.y, self.item, self.room, self.flags)
def empty(self):
return self.item == PotItem.Nothing and self.indicator is None
def pot_data(self):
high_byte = self.y
if self.flags & PotFlags.LowerRegion:
high_byte |= 0x20
if self.indicator:
high_byte |= self.indicator
item = self.item if not self.indicator else self.standing_item_code
return [self.x, high_byte, item]
# byte 0: DDDE EEEE (DR, ER)
@@ -2708,6 +2737,7 @@ diff_mode = {"normal": 0, "hard": 1, "expert": 2}
func_mode = {"normal": 0, "hard": 1, "expert": 2}
# byte 3: SKMM PIII (shop, keydrop, mixed, palettes, intensity)
# todo keydrop is not longer a switch
mixed_travel_mode = {"prevent": 0, "allow": 1, "force": 2}
# intensity is 3 bits (reserves 4-7 levels)

2
CLI.py
View File

@@ -158,7 +158,7 @@ def parse_settings():
"enemizercli": os.path.join(".", "EnemizerCLI", "EnemizerCLI.Core"),
"shopsanity": False,
"keydropshuffle": False,
"keydropshuffle": 'none',
"mapshuffle": False,
"compassshuffle": False,
"keyshuffle": False,

View File

@@ -378,7 +378,7 @@ def choose_portals(world, player):
if world.doorShuffle[player] in ['basic', 'crossed']:
cross_flag = world.doorShuffle[player] == 'crossed'
# key drops allow the big key in the right place in Desert Tiles 2
bk_shuffle = world.bigkeyshuffle[player] or world.keydropshuffle[player]
bk_shuffle = world.bigkeyshuffle[player] or world.keydropshuffle[player] != 'none'
std_flag = world.mode[player] == 'standard'
# roast incognito doors
world.get_room(0x60, player).delete(5)
@@ -994,7 +994,7 @@ def cross_dungeon(world, player):
assign_cross_keys(dungeon_builders, world, player)
all_dungeon_items_cnt = len(list(y for x in world.dungeons if x.player == player for y in x.all_items))
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
target_items = 35 if world.retro[player] else 96
else:
target_items = 34 if world.retro[player] else 63
@@ -1055,7 +1055,7 @@ def assign_cross_keys(dungeon_builders, world, player):
logging.getLogger('').info(world.fish.translate("cli", "cli", "shuffling.keydoors"))
start = time.process_time()
if world.retro[player]:
remaining = 61 if world.keydropshuffle[player] else 29
remaining = 61 if world.keydropshuffle[player] != 'none' else 29
else:
remaining = len(list(x for dgn in world.dungeons if dgn.player == player for x in dgn.small_keys))
total_keys = remaining

View File

@@ -3060,12 +3060,14 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Kings Grave Inner Rocks', 'Light World'),
('Kings Grave Mirror Spot', 'Kings Grave Area'),
('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'),
('Kakariko Well (top to back)', 'Kakariko Well (back)'),
('Master Sword Meadow', 'Master Sword Meadow'),
('Hobo Bridge', 'Hobo Bridge'),
('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'),
('Bat Cave Door', 'Bat Cave (left)'),
('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'),
('Lumberjack Tree (top to bottom)', 'Lumberjack Tree (bottom)'),
('Blinds Hideout N', 'Blinds Hideout (Top)'),
('Desert Palace Stairs', 'Desert Palace Stairs'),
('Desert Palace Stairs Drop', 'Light World'),
('Desert Palace Entrance (North) Rocks', 'Desert Palace Entrance (North) Spot'),
@@ -3078,6 +3080,8 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Death Mountain Entrance Drop', 'Light World'),
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'),
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave (Bottom)'),
('Death Mountain Return Cave E', 'Death Mountain Return Cave (right)'),
('Death Mountain Return Cave W', 'Death Mountain Return Cave (left)'),
('Death Mountain Return Ledge Drop', 'Light World'),
('Old Man Cave Dropdown', 'Old Man Cave'),
('Old Man House Front to Back', 'Old Man House Back'),
@@ -3136,6 +3140,7 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Death Mountain Teleporter', 'Dark Death Mountain (West Bottom)'),
('Paradox Cave Push Block Reverse', 'Paradox Cave Chest Area'),
('Paradox Cave Push Block', 'Paradox Cave Front'),
('Paradox Cave Chest Area NE', 'Paradox Cave Bomb Area'),
('Paradox Cave Bomb Jump', 'Paradox Cave'),
('Paradox Cave Drop', 'Paradox Cave Chest Area'),
('Light World Death Mountain Shop', 'Light World Death Mountain Shop'),
@@ -3185,12 +3190,14 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
('Kings Grave Outer Rocks', 'Kings Grave Area'),
('Kings Grave Inner Rocks', 'Light World'),
('Kakariko Well (top to bottom)', 'Kakariko Well (bottom)'),
('Kakariko Well (top to back)', 'Kakariko Well (back)'),
('Master Sword Meadow', 'Master Sword Meadow'),
('Hobo Bridge', 'Hobo Bridge'),
('Bat Cave Drop Ledge', 'Bat Cave Drop Ledge'),
('Bat Cave Door', 'Bat Cave (left)'),
('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'),
('Lumberjack Tree (top to bottom)', 'Lumberjack Tree (bottom)'),
('Blinds Hideout N', 'Blinds Hideout (Top)'),
('Desert Palace Stairs', 'Desert Palace Stairs'),
('Desert Palace Stairs Drop', 'Light World'),
('Desert Palace Entrance (North) Rocks', 'Desert Palace Entrance (North) Spot'),
@@ -3198,6 +3205,8 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
('Sewer Drop', 'Sewers Rat Path'),
('Death Mountain Entrance Rock', 'Death Mountain Entrance'),
('Death Mountain Entrance Drop', 'Light World'),
('Death Mountain Return Cave E', 'Death Mountain Return Cave (right)'),
('Death Mountain Return Cave W', 'Death Mountain Return Cave (left)'),
('Spectacle Rock Cave Drop', 'Spectacle Rock Cave (Bottom)'),
('Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave (Bottom)'),
('Death Mountain Return Ledge Drop', 'Light World'),
@@ -3241,6 +3250,7 @@ inverted_mandatory_connections = [('Links House S&Q', 'Inverted Links House'),
('Skull Woods Forest', 'Skull Woods Forest'),
('Paradox Cave Push Block Reverse', 'Paradox Cave Chest Area'),
('Paradox Cave Push Block', 'Paradox Cave Front'),
('Paradox Cave Chest Area NE', 'Paradox Cave Bomb Area'),
('Paradox Cave Bomb Jump', 'Paradox Cave'),
('Paradox Cave Drop', 'Paradox Cave Chest Area'),
('Light World Death Mountain Shop', 'Light World Death Mountain Shop'),
@@ -3417,8 +3427,8 @@ default_connections = [('Links House', 'Links House'),
('Old Man House Exit (Bottom)', 'Death Mountain'),
('Old Man House (Top)', 'Old Man House Back'),
('Old Man House Exit (Top)', 'Death Mountain'),
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
('Death Mountain Return Cave (West)', 'Death Mountain Return Cave'),
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave (right)'),
('Death Mountain Return Cave (West)', 'Death Mountain Return Cave (left)'),
('Death Mountain Return Cave Exit (West)', 'Death Mountain Return Ledge'),
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
('Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Peak)'),
@@ -3622,7 +3632,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Inverted Dark Sanctuary', 'Inverted Dark Sanctuary'),
('Inverted Dark Sanctuary Exit', 'West Dark World'),
('Old Man Cave (West)', 'Bumper Cave'),
('Old Man Cave (East)', 'Death Mountain Return Cave'),
('Old Man Cave (East)', 'Death Mountain Return Cave (left)'),
('Old Man Cave Exit (West)', 'West Dark World'),
('Old Man Cave Exit (East)', 'Dark Death Mountain'),
('Dark Death Mountain Fairy', 'Old Man Cave'),
@@ -3631,7 +3641,7 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Bumper Cave Exit (Top)', 'Death Mountain Return Ledge'),
('Bumper Cave Exit (Bottom)', 'Light World'),
('Death Mountain Return Cave (West)', 'Bumper Cave'),
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
('Death Mountain Return Cave (East)', 'Death Mountain Return Cave (right)'),
('Death Mountain Return Cave Exit (West)', 'Death Mountain'),
('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
('Hookshot Cave Front Exit', 'Dark Death Mountain'),

37
Fill.py
View File

@@ -3,7 +3,7 @@ import collections
import itertools
import logging
from BaseClasses import CollectionState, FillError
from BaseClasses import CollectionState, FillError, LocationType
from Items import ItemFactory
from Regions import shop_to_location_table, retro_shops
from source.item.FillUtil import filter_locations, classify_major_items, replace_trash_item, vanilla_fallback
@@ -350,6 +350,24 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
# get items to distribute
classify_major_items(world)
# handle pot shuffle
pots_used = False
pot_item_pool = collections.defaultdict(list)
for item in world.itempool:
if item.name in ['Chicken', 'Big Magic']: # can only fill these in that players world
pot_item_pool[item.player].append(item)
for player, pot_pool in pot_item_pool.items():
if pot_pool:
for pot_item in pot_pool:
world.itempool.remove(pot_item)
pot_locations = [location for location in fill_locations
if location.type == LocationType.Pot and location.player == player]
fast_fill_helper(world, pot_pool, pot_locations)
pots_used = True
if pots_used:
fill_locations = world.get_unfilled_locations()
random.shuffle(fill_locations)
random.shuffle(world.itempool)
progitempool = [item for item in world.itempool if item.advancement]
prioitempool = [item for item in world.itempool if not item.advancement and item.priority]
@@ -425,6 +443,23 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
if unplaced or unfilled:
logging.warning('Unplaced items: %s - Unfilled Locations: %s', unplaced, unfilled)
# convert Arrows 5 and Nothing when necessary
invalid_locations = [loc for loc in world.get_locations() if loc.item.name in {'Arrows (5)', 'Nothing'} and
(loc.type != LocationType.Pot or loc.item.player != loc.player)]
for i_loc in invalid_locations:
i_loc.item = ItemFactory(invalid_location_replacement[i_loc.item.name], i_loc.item.player)
invalid_location_replacement = {'Arrows (5)': 'Arrows (10)', 'Nothing': 'Rupees (5)'}
def fast_fill_helper(world, item_pool, fill_locations):
if world.algorithm == 'vanilla_fill':
fast_vanilla_fill(world, item_pool, fill_locations)
else:
fast_fill(world, item_pool, fill_locations)
# todo: other fast fill methods?
def fast_fill(world, item_pool, fill_locations):
while item_pool and fill_locations:

View File

@@ -25,11 +25,10 @@ def create_inverted_regions(world, player):
create_lw_region(player, 'Hyrule Castle Secret Entrance Area', None, ['Hyrule Castle Secret Entrance Stairs', 'Secret Passage Inner Bushes']),
create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop', 'Bumper Cave Entrance Mirror Spot']),
create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Mirror Spot']),
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top",
"Blind\'s Hideout - Left",
"Blind\'s Hideout - Right",
"Blind\'s Hideout - Far Left",
"Blind\'s Hideout - Far Right"]),
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items',
["Blind's Hideout - Left", "Blind's Hideout - Right", "Blind's Hideout - Far Left",
"Blind's Hideout - Far Right"], ['Blinds Hideout N']),
create_cave_region(player, 'Blinds Hideout (Top)', 'a bounty of five items', ["Blind's Hideout - Top"]),
create_lw_region(player, 'Northeast Light World', None, ['Zoras River', 'Waterfall of Wishing Cave', 'Potion Shop Outer Rock', 'Catfish Mirror Spot', 'Northeast Light World Warp']),
create_lw_region(player, 'Waterfall of Wishing Cave', None, ['Waterfall of Wishing', 'Northeast Light World Return']),
create_lw_region(player, 'Potion Shop Area', None, ['Potion Shop', 'Potion Shop Inner Bushes', 'Potion Shop Inner Rock', 'Potion Shop Mirror Spot', 'Potion Shop River Drop']),
@@ -68,8 +67,11 @@ def create_inverted_regions(world, player):
create_cave_region(player, 'Chicken House', 'a house with a chest', ['Chicken House']),
create_cave_region(player, 'Aginahs Cave', 'a cave with a chest', ['Aginah\'s Cave']),
create_cave_region(player, 'Sahasrahlas Hut', 'Sahasrahla', ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right', 'Sahasrahla']),
create_cave_region(player, 'Kakariko Well (top)', 'a drop\'s exit', ['Kakariko Well - Top', 'Kakariko Well - Left', 'Kakariko Well - Middle',
'Kakariko Well - Right', 'Kakariko Well - Bottom'], ['Kakariko Well (top to bottom)']),
create_cave_region(player, 'Kakariko Well (top)', 'a drop\'s exit',
['Kakariko Well - Left', 'Kakariko Well - Middle', 'Kakariko Well - Right',
'Kakariko Well - Bottom'],
['Kakariko Well (top to bottom)', 'Kakariko Well (top to back)']),
create_cave_region(player, 'Kakariko Well (back)', 'a drop\'s exit', ['Kakariko Well - Top']),
create_cave_region(player, 'Kakariko Well (bottom)', 'a drop\'s exit', None, ['Kakariko Well Exit']),
create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith', 'Missing Smith']),
create_lw_region(player, 'Bat Cave Drop Ledge', None, ['Bat Cave Drop']),
@@ -114,8 +116,8 @@ def create_inverted_regions(world, player):
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave',
'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot']),
create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']),
create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot']),
create_cave_region(player, 'Death Mountain Return Cave (left)', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave E']),
create_cave_region(player, 'Death Mountain Return Cave (right)', 'a connector', None, ['Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave W']),
create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']),
create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']),
create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']),
@@ -127,10 +129,10 @@ def create_inverted_regions(world, player):
'Paradox Cave Lower - Left',
'Paradox Cave Lower - Right',
'Paradox Cave Lower - Far Right',
'Paradox Cave Lower - Middle',
'Paradox Cave Upper - Left',
'Paradox Cave Upper - Right'],
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']),
'Paradox Cave Lower - Middle'],
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump', 'Paradox Cave Chest Area NE']),
create_cave_region(player, 'Paradox Cave Bomb Area', 'a connector', ['Paradox Cave Upper - Left',
'Paradox Cave Upper - Right']),
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', ['Paradox Shop - Left', 'Paradox Shop - Middle', 'Paradox Shop - Right']),
create_lw_region(player, 'East Death Mountain (Top)', ['Floating Island'], ['Paradox Cave (Top)', 'Death Mountain (Top)', 'Spiral Cave Ledge Access', 'East Death Mountain Drop', 'East Death Mountain Mirror Spot (Top)', 'Fairy Ascension Ledge Access', 'Mimic Cave Ledge Access',

View File

@@ -3,10 +3,11 @@ import logging
import math
import RaceRandom as random
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem
from EntranceShuffle import connect_entrance
from Regions import shop_to_location_table, retro_shops, shop_table_by_location
from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool
from PotShuffle import vanilla_pots
from Items import ItemFactory
from source.item.FillUtil import trash_items
@@ -388,11 +389,14 @@ def generate_itempool(world, player):
if world.retro[player]:
set_up_take_anys(world, player)
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
world.itempool += [ItemFactory('Small Key (Universal)', player)] * 32
create_dynamic_shop_locations(world, player)
if world.keydropshuffle[player] == 'potsanity':
add_pot_contents(world, player)
take_any_locations = [
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
@@ -748,6 +752,28 @@ rupee_chart = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)'
'Rupees (100)': 100, 'Rupees (300)': 300}
pot_items = {
PotItem.Nothing: 'Nothing',
PotItem.Bomb: 'Single Bomb',
PotItem.FiveArrows: 'Arrows (5)', # convert to 10
PotItem.OneRupee: 'Rupee (1)',
PotItem.FiveRupees: 'Rupees (5)',
PotItem.Heart: 'Small Heart',
PotItem.BigMagic: 'Big Magic', # fast fill
PotItem.SmallMagic: 'Small Magic',
PotItem.Chicken: 'Chicken' # fast fill
}
valid_pot_items = {y: x for x, y in pot_items.items()}
def add_pot_contents(world, player):
for super_tile, pot_list in vanilla_pots.items():
for pot in pot_list:
if pot.item not in [PotItem.Hole, PotItem.Key, PotItem.Switch]:
world.itempool.append(ItemFactory(pot_items[pot.item], player))
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic):
pool = []
placed_items = {}
@@ -894,6 +920,7 @@ def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer,
pool.extend(['Small Key (Universal)'])
return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms)
def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, bombbag, customitemarray):
if isinstance(customitemarray,dict) and 1 in customitemarray:
customitemarray = customitemarray[1]

View File

@@ -79,6 +79,10 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Arrow Upgrade (+5)': (False, False, None, 0x53, 100, 'increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'),
'Arrows (5)': (False, False, None, 0x5A, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'),
'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'),
'Big Magic': (False, False, None, 0x5A, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'),
'Chicken': (False, False, None, 0x5A, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'),
'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'),

View File

@@ -157,7 +157,7 @@ def main(args, seed=None, fish=None):
if any(world.potshuffle.values()):
logger.info(world.fish.translate("cli", "cli", "shuffling.pots"))
for player in range(1, world.players + 1):
if world.potshuffle[player]:
if world.potshuffle[player] and world.keydropshuffle[player] != 'potsanity':
shuffle_pots(world, player)
logger.info(world.fish.translate("cli","cli","shuffling.world"))

View File

@@ -173,7 +173,7 @@ def roll_settings(weights):
ret.shufflelinks = get_choice('shufflelinks') == 'on'
ret.pseudoboots = get_choice('pseudoboots') == 'on'
ret.shopsanity = get_choice('shopsanity') == 'on'
ret.keydropshuffle = get_choice('keydropshuffle') == 'on'
ret.keydropshuffle = get_choice('keydropshuffle')
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
ret.standardize_palettes = get_choice('standardize_palettes') if 'standardize_palettes' in weights else 'standardize'

View File

@@ -1,7 +1,7 @@
from collections import defaultdict
from BaseClasses import PotItem, Pot, PotFlags, CrystalBarrier
from Regions import key_drop_data
from Utils import int16_as_bytes, pc_to_snes
movable_switch_rooms = defaultdict(lambda: [],
{'PoD Stalfos Basement': ['PoD Basement Ledge'],
@@ -18,18 +18,24 @@ invalid_key_rooms = {
}
vanilla_pots = {
2: [Pot(80, 6, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(80, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 8, PotItem.Nothing, 'Sewers Yet More Rats'), Pot(44, 10, PotItem.Nothing, 'Sewers Yet More Rats')],
2: [Pot(80, 6, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion),
Pot(80, 8, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion),
Pot(44, 8, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion),
Pot(44, 10, PotItem.Nothing, 'Sewers Yet More Rats', PotFlags.LowerRegion)],
4: [Pot(162, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 25, PotItem.Nothing, 'TR Dash Room'), Pot(152, 22, PotItem.Nothing, 'TR Dash Room'), Pot(162, 22, PotItem.Nothing, 'TR Dash Room'), Pot(204, 19, PotItem.Bomb, 'TR Tongue Pull'),
Pot(240, 19, PotItem.Bomb, 'TR Tongue Pull')],
9: [Pot(12, 4, PotItem.OneRupee, 'PoD Shooter Room'), Pot(48, 4, PotItem.Heart, 'PoD Shooter Room'), Pot(12, 12, PotItem.Switch, 'PoD Shooter Room')],
10: [Pot(96, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(104, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(204, 11, PotItem.Switch, 'PoD Stalfos Basement'), Pot(100, 9, PotItem.Nothing, 'PoD Stalfos Basement'),
Pot(156, 17, PotItem.Bomb, 'PoD Basement Ledge', PotFlags.SwitchLogicChange), Pot(160, 17, PotItem.FiveArrows, 'PoD Basement Ledge', PotFlags.SwitchLogicChange)],
11: [Pot(202, 3, PotItem.Bomb, 'PoD Dark Pegs Left'), Pot(202, 12, PotItem.Bomb, 'PoD Dark Pegs Left')],
17: [Pot(152, 19, PotItem.Nothing, 'Sewers Secret Room'), Pot(152, 15, PotItem.Nothing, 'Sewers Secret Room'), Pot(144, 15, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 15, PotItem.Heart, 'Sewers Secret Room'),
0xa: [Pot(96, 8, PotItem.Heart, 'PoD Stalfos Basement'), Pot(104, 8, PotItem.Heart, 'PoD Stalfos Basement'),
Pot(204, 11, PotItem.Switch, 'PoD Stalfos Basement'), Pot(100, 9, PotItem.Nothing, 'PoD Stalfos Basement'),
Pot(100, 7, PotItem.Nothing, 'PoD Stalfos Basement'),
Pot(156, 17, PotItem.Bomb, 'PoD Basement Ledge', PotFlags.SwitchLogicChange),
Pot(160, 17, PotItem.FiveArrows, 'PoD Basement Ledge', PotFlags.SwitchLogicChange)],
0xb: [Pot(202, 3, PotItem.Bomb, 'PoD Dark Pegs Left'), Pot(202, 12, PotItem.Bomb, 'PoD Dark Pegs Left')],
0x11: [Pot(152, 19, PotItem.Nothing, 'Sewers Secret Room'), Pot(152, 15, PotItem.Nothing, 'Sewers Secret Room'), Pot(144, 15, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 15, PotItem.Heart, 'Sewers Secret Room'),
Pot(144, 19, PotItem.Heart, 'Sewers Secret Room'), Pot(160, 19, PotItem.Heart, 'Sewers Secret Room')],
21: [Pot(96, 4, PotItem.Bomb, 'TR Pipe Pit'), Pot(100, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(104, 4, PotItem.Heart, 'TR Pipe Pit'), Pot(108, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(112, 4, PotItem.FiveArrows, 'TR Pipe Pit'),
0x15: [Pot(96, 4, PotItem.Bomb, 'TR Pipe Pit'), Pot(100, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(104, 4, PotItem.Heart, 'TR Pipe Pit'), Pot(108, 4, PotItem.SmallMagic, 'TR Pipe Pit'), Pot(112, 4, PotItem.FiveArrows, 'TR Pipe Pit'),
Pot(12, 6, PotItem.OneRupee, 'TR Pipe Pit'), Pot(16, 6, PotItem.FiveArrows, 'TR Pipe Pit'), Pot(20, 6, PotItem.FiveRupees, 'TR Pipe Pit'), Pot(70, 11, PotItem.BigMagic, 'TR Pipe Ledge')],
22: [Pot(188, 3, PotItem.Heart, 'Swamp I'), Pot(192, 3, PotItem.Heart, 'Swamp I'), Pot(188, 4, PotItem.SmallMagic, 'Swamp I'), Pot(192, 4, PotItem.SmallMagic, 'Swamp I'), Pot(188, 5, PotItem.FiveArrows, 'Swamp I'),
0x16: [Pot(188, 3, PotItem.Heart, 'Swamp I'), Pot(192, 3, PotItem.Heart, 'Swamp I'), Pot(188, 4, PotItem.SmallMagic, 'Swamp I'), Pot(192, 4, PotItem.SmallMagic, 'Swamp I'), Pot(188, 5, PotItem.FiveArrows, 'Swamp I'),
Pot(192, 5, PotItem.FiveArrows, 'Swamp I'), Pot(188, 6, PotItem.Bomb, 'Swamp I'), Pot(192, 6, PotItem.Bomb, 'Swamp I'), Pot(240, 19, PotItem.Key, 'Swamp Waterway')],
23: [Pot(100, 13, PotItem.Heart, 'Hera 5F'), Pot(100, 14, PotItem.Heart, 'Hera 5F'), Pot(100, 15, PotItem.Heart, 'Hera 5F'), Pot(100, 16, PotItem.Heart, 'Hera 5F'), Pot(100, 17, PotItem.Heart, 'Hera 5F'), Pot(100, 18, PotItem.Heart, 'Hera 5F'),
Pot(104, 13, PotItem.Heart, 'Hera 5F'), Pot(104, 14, PotItem.Heart, 'Hera 5F'), Pot(104, 15, PotItem.Heart, 'Hera 5F'), Pot(104, 16, PotItem.Heart, 'Hera 5F'), Pot(104, 17, PotItem.Heart, 'Hera 5F'), Pot(104, 18, PotItem.Heart, 'Hera 5F')],
@@ -52,32 +58,39 @@ vanilla_pots = {
Pot(44, 7, PotItem.Bomb, 'PoD Sexy Statue'), Pot(146, 21, PotItem.Bomb, 'PoD Map Balcony'), Pot(170, 21, PotItem.FiveArrows, 'PoD Map Balcony'), Pot(146, 22, PotItem.Bomb, 'PoD Map Balcony'),
Pot(170, 22, PotItem.FiveArrows, 'PoD Map Balcony')],
44: [Pot(108, 24, PotItem.Heart, 'Hookshot Cave (Middle)'), Pot(112, 24, PotItem.Heart, 'Hookshot Cave (Middle)')],
47: [Pot(28, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(32, 7, PotItem.Heart, 'Kakariko Well (top)'), Pot(28, 9, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(32, 9, PotItem.FiveRupees, 'Kakariko Well (top)'),
Pot(172, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(180, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(104, 27, PotItem.Heart, 'Kakariko Well (bottom)'), Pot(104, 28, PotItem.Heart, 'Kakariko Well (bottom)')],
0x2F: [Pot(28, 7, PotItem.Heart, 'Kakariko Well (back)'), Pot(32, 7, PotItem.Heart, 'Kakariko Well (back)'),
Pot(28, 9, PotItem.FiveRupees, 'Kakariko Well (back)'), Pot(32, 9, PotItem.FiveRupees, 'Kakariko Well (back)'),
Pot(172, 19, PotItem.FiveRupees, 'Kakariko Well (top)'), Pot(180, 19, PotItem.FiveRupees, 'Kakariko Well (top)'),
Pot(104, 27, PotItem.Heart, 'Kakariko Well (bottom)'), Pot(104, 28, PotItem.Heart, 'Kakariko Well (bottom)')],
49: [Pot(92, 28, PotItem.Bomb, 'Hera Beetles'), Pot(96, 28, PotItem.Nothing, 'Hera Beetles')],
50: [Pot(28, 13, PotItem.SmallMagic, 'Sewers Dark Cross')],
52: [Pot(78, 8, PotItem.FiveRupees, 'Swamp Barrier Ledge'), Pot(92, 8, PotItem.FiveRupees, 'Swamp Barrier Ledge')],
53: [Pot(60, 6, PotItem.Key, 'Swamp Trench 2 Alcove'), Pot(20, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(24, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(28, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'),
Pot(32, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(36, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(48, 20, PotItem.Heart, 'Swamp Trench 2 Departure'), Pot(76, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'),
Pot(88, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(100, 27, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(242, 28, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(240, 22, PotItem.Heart, 'Swamp Trench 2 Pots'),
Pot(76, 28, PotItem.Heart, 'Swamp Trench 2 Pots')],
54: [Pot(108, 4, PotItem.Bomb, 'Swamp Hub Dead Ledge'), Pot(112, 4, PotItem.FiveRupees, 'Swamp Hub Dead Ledge'), Pot(10, 16, PotItem.Heart, 'Swamp Hub'), Pot(154, 15, PotItem.Nothing, 'Swamp Hub'), Pot(114, 16, PotItem.Key, 'Swamp Hub'),
Pot(222, 15, PotItem.Nothing, 'Swamp Hub'), Pot(188, 5, PotItem.Nothing, 'Swamp Hub North Ledge'), Pot(192, 5, PotItem.Nothing, 'Swamp Hub North Ledge')],
55: [Pot(60, 6, PotItem.Key, 'Swamp Trench 1 Alcove'), Pot(48, 20, PotItem.Nothing, 'Swamp Trench 1 Key Ledge')],
56: [Pot(164, 12, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 13, PotItem.FiveRupees, 'Swamp Pot Row'), Pot(164, 18, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 19, PotItem.Key, 'Swamp Pot Row')],
0x35: [Pot(60, 6, PotItem.Key, 'Swamp Trench 2 Alcove'), Pot(20, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(24, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(28, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'),
Pot(32, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(36, 8, PotItem.FiveRupees, 'Swamp Big Key Ledge'), Pot(48, 20, PotItem.Heart, 'Swamp Trench 2 Departure'), Pot(76, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'),
Pot(88, 23, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(100, 27, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(242, 28, PotItem.Nothing, 'Swamp Trench 2 Pots'), Pot(240, 22, PotItem.Heart, 'Swamp Trench 2 Pots'),
Pot(76, 28, PotItem.Heart, 'Swamp Trench 2 Pots')],
0x36: [Pot(108, 4, PotItem.Bomb, 'Swamp Hub Dead Ledge'), Pot(112, 4, PotItem.FiveRupees, 'Swamp Hub Dead Ledge'), Pot(10, 16, PotItem.Heart, 'Swamp Hub'), Pot(154, 15, PotItem.Nothing, 'Swamp Hub'), Pot(114, 16, PotItem.Key, 'Swamp Hub'),
Pot(222, 15, PotItem.Nothing, 'Swamp Hub'), Pot(188, 5, PotItem.Nothing, 'Swamp Hub North Ledge'), Pot(192, 5, PotItem.Nothing, 'Swamp Hub North Ledge')],
0x37: [Pot(60, 6, PotItem.Key, 'Swamp Trench 1 Alcove'), Pot(48, 20, PotItem.Nothing, 'Swamp Trench 1 Key Ledge')],
0x38: [Pot(164, 12, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 13, PotItem.FiveRupees, 'Swamp Pot Row'), Pot(164, 18, PotItem.Bomb, 'Swamp Pot Row'), Pot(164, 19, PotItem.Key, 'Swamp Pot Row')],
57: [Pot(12, 20, PotItem.Heart, 'Skull Spike Corner'), Pot(48, 28, PotItem.FiveArrows, 'Skull Spike Corner'), Pot(100, 22, PotItem.SmallMagic, 'Skull Final Drop'), Pot(100, 26, PotItem.FiveArrows, 'Skull Final Drop')],
60: [Pot(24, 8, PotItem.SmallMagic, 'Hookshot Cave (Front)'), Pot(64, 12, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(20, 14, PotItem.OneRupee, 'Hookshot Cave (Front)'), Pot(20, 19, PotItem.Nothing, 'Hookshot Cave (Front)'),
Pot(68, 18, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(96, 19, PotItem.Heart, 'Hookshot Cave (Front)'), Pot(64, 20, PotItem.FiveRupees, 'Hookshot Cave (Front)'), Pot(64, 26, PotItem.FiveRupees, 'Hookshot Cave (Front)')],
61: [Pot(76, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(112, 12, PotItem.Bomb, 'GT Mini Helmasaur Room'), Pot(24, 22, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(40, 22, PotItem.FiveArrows, 'GT Crystal Inner Circle'),
Pot(32, 24, PotItem.Heart, 'GT Crystal Inner Circle'), Pot(20, 26, PotItem.FiveRupees, 'GT Crystal Inner Circle'), Pot(36, 26, PotItem.BigMagic, 'GT Crystal Inner Circle')],
62: [Pot(96, 6, PotItem.Bomb, 'Ice Stalfos Hint'), Pot(100, 6, PotItem.SmallMagic, 'Ice Stalfos Hint'), Pot(88, 10, PotItem.Heart, 'Ice Stalfos Hint'), Pot(92, 10, PotItem.SmallMagic, 'Ice Stalfos Hint')],
63: [Pot(12, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(20, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(12, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(20, 26, PotItem.Bomb, 'Ice Hammer Block'),
Pot(12, 27, PotItem.Switch, 'Ice Hammer Block'), Pot(20, 27, PotItem.Heart, 'Ice Hammer Block'), Pot(28, 23, PotItem.Key, 'Ice Hammer Block')],
65: [Pot(100, 10, PotItem.Heart, 'Sewers Behind Tapestry'), Pot(52, 15, PotItem.OneRupee, 'Sewers Behind Tapestry'), Pot(52, 16, PotItem.SmallMagic, 'Sewers Behind Tapestry'), Pot(148, 22, PotItem.SmallMagic, 'Sewers Behind Tapestry')],
67: [Pot(66, 4, PotItem.FiveArrows, 'Desert Wall Slide'), Pot(78, 4, PotItem.SmallMagic, 'Desert Wall Slide'), Pot(66, 9, PotItem.Heart, 'Desert Wall Slide'), Pot(78, 9, PotItem.Heart, 'Desert Wall Slide'),
Pot(112, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 20, PotItem.Nothing, 'Desert Tiles 2'), Pot(112, 20, PotItem.Key, 'Desert Tiles 2')],
69: [Pot(12, 4, PotItem.FiveArrows, 'Thieves Basement Block'), Pot(48, 12, PotItem.FiveArrows, 'Thieves Basement Block'), Pot(92, 11, PotItem.Nothing, "Thieves Blind's Cell"), Pot(108, 11, PotItem.Heart, "Thieves Blind's Cell"),
Pot(220, 16, PotItem.SmallMagic, "Thieves Blind's Cell"), Pot(236, 16, PotItem.Heart, "Thieves Blind's Cell")],
0x3F: [Pot(12, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(20, 25, PotItem.OneRupee, 'Ice Hammer Block'), Pot(12, 26, PotItem.Bomb, 'Ice Hammer Block'), Pot(20, 26, PotItem.Bomb, 'Ice Hammer Block'),
Pot(12, 27, PotItem.Switch, 'Ice Hammer Block'), Pot(20, 27, PotItem.Heart, 'Ice Hammer Block'), Pot(28, 23, PotItem.Key, 'Ice Hammer Block')],
0x41: [Pot(100, 10, PotItem.Heart, 'Sewers Behind Tapestry'), Pot(52, 15, PotItem.OneRupee, 'Sewers Behind Tapestry'), Pot(52, 16, PotItem.SmallMagic, 'Sewers Behind Tapestry'), Pot(148, 22, PotItem.SmallMagic, 'Sewers Behind Tapestry')],
0x43: [Pot(66, 4, PotItem.FiveArrows, 'Desert Wall Slide'), Pot(78, 4, PotItem.SmallMagic, 'Desert Wall Slide'), Pot(66, 9, PotItem.Heart, 'Desert Wall Slide'), Pot(78, 9, PotItem.Heart, 'Desert Wall Slide'),
Pot(112, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 28, PotItem.Nothing, 'Desert Tiles 2'), Pot(76, 20, PotItem.Nothing, 'Desert Tiles 2'), Pot(112, 20, PotItem.Key, 'Desert Tiles 2')],
0x44: [Pot(204, 7, PotItem.Nothing, 'Thieves Conveyor Bridge', PotFlags.Block)],
0x45: [Pot(12, 4, PotItem.FiveArrows, 'Thieves Basement Block'),
Pot(48, 12, PotItem.FiveArrows, 'Thieves Basement Block'),
Pot(92, 11, PotItem.Nothing, "Thieves Blind's Cell"), Pot(108, 11, PotItem.Heart, "Thieves Blind's Cell"),
Pot(220, 16, PotItem.SmallMagic, "Thieves Blind's Cell"),
Pot(236, 16, PotItem.Heart, "Thieves Blind's Cell"),
Pot(0x9C, 7, PotItem.Nothing, 'Thieves Basement Block', PotFlags.Block)],
70: [Pot(96, 5, PotItem.Heart, 'Swamp Donut Top'), Pot(28, 27, PotItem.Heart, 'Swamp Donut Bottom')],
73: [Pot(104, 15, PotItem.SmallMagic, 'Skull Torch Room'), Pot(104, 16, PotItem.SmallMagic, 'Skull Torch Room'), Pot(156, 27, PotItem.Nothing, 'Skull Star Pits'), Pot(172, 24, PotItem.Nothing, 'Skull Star Pits'),
Pot(172, 23, PotItem.Nothing, 'Skull Star Pits'), Pot(144, 20, PotItem.Nothing, 'Skull Star Pits'), Pot(144, 19, PotItem.SmallMagic, 'Skull Star Pits'), Pot(172, 20, PotItem.Heart, 'Skull Star Pits'),
@@ -87,15 +100,16 @@ vanilla_pots = {
75: [Pot(20, 6, PotItem.FiveArrows, 'PoD Mimics 1'), Pot(40, 6, PotItem.Heart, 'PoD Mimics 1')],
78: [Pot(140, 7, PotItem.Nothing, 'Ice Bomb Jump Catwalk'), Pot(48, 10, PotItem.Nothing, 'Ice Bomb Jump Catwalk'), Pot(140, 11, PotItem.Switch, 'Ice Bomb Jump Catwalk'), Pot(28, 12, PotItem.Heart, 'Ice Bomb Jump Catwalk'),
Pot(112, 12, PotItem.SmallMagic, 'Ice Narrow Corridor')],
80: [Pot(96, 38, PotItem.Heart, 'Hyrule Castle West Hall'), Pot(100, 38, PotItem.Heart, 'Hyrule Castle West Hall')],
0x50: [Pot(96, 0x6, PotItem.Heart, 'Hyrule Castle West Hall', PotFlags.LowerRegion),
Pot(100, 0x6, PotItem.Heart, 'Hyrule Castle West Hall', PotFlags.LowerRegion)],
82: [Pot(138, 3, PotItem.Heart, 'Hyrule Castle East Hall'), Pot(194, 26, PotItem.Heart, 'Hyrule Castle East Hall')],
83: [Pot(92, 11, PotItem.Heart, 'Desert Beamos Hall'), Pot(96, 11, PotItem.SmallMagic, 'Desert Beamos Hall'), Pot(100, 11, PotItem.Key, 'Desert Beamos Hall'), Pot(104, 11, PotItem.Heart, 'Desert Beamos Hall')],
0x53: [Pot(92, 11, PotItem.Heart, 'Desert Beamos Hall'), Pot(96, 11, PotItem.SmallMagic, 'Desert Beamos Hall'), Pot(100, 11, PotItem.Key, 'Desert Beamos Hall'), Pot(104, 11, PotItem.Heart, 'Desert Beamos Hall')],
84: [Pot(186, 25, PotItem.FiveRupees, 'Swamp Attic'), Pot(186, 26, PotItem.Heart, 'Swamp Attic'), Pot(186, 27, PotItem.Heart, 'Swamp Attic'), Pot(186, 28, PotItem.Heart, 'Swamp Attic')],
85: [Pot(230, 24, PotItem.SmallMagic, 'Secret Passage'), Pot(230, 25, PotItem.SmallMagic, 'Secret Passage')],
86: [Pot(100, 6, PotItem.Nothing, 'Skull Back Drop'), Pot(96, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(92, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(20, 6, PotItem.SmallMagic, 'Skull X Room'),
Pot(40, 6, PotItem.SmallMagic, 'Skull X Room'), Pot(24, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(12, 8, PotItem.Heart, 'Skull X Room'), Pot(48, 8, PotItem.Heart, 'Skull X Room'),
Pot(24, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(20, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(40, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(12, 20, PotItem.Key, 'Skull 2 West Lobby'),
Pot(48, 20, PotItem.Nothing, 'Skull 2 West Lobby')],
85: [Pot(230, 24, PotItem.SmallMagic, 'Hyrule Castle Secret Entrance'), Pot(230, 25, PotItem.SmallMagic, 'Hyrule Castle Secret Entrance')],
0x56: [Pot(100, 6, PotItem.Nothing, 'Skull Back Drop'), Pot(96, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(92, 10, PotItem.Nothing, 'Skull Back Drop'), Pot(20, 6, PotItem.SmallMagic, 'Skull X Room'),
Pot(40, 6, PotItem.SmallMagic, 'Skull X Room'), Pot(24, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 7, PotItem.SmallMagic, 'Skull X Room'), Pot(12, 8, PotItem.Heart, 'Skull X Room'), Pot(48, 8, PotItem.Heart, 'Skull X Room'),
Pot(24, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(36, 9, PotItem.SmallMagic, 'Skull X Room'), Pot(20, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(40, 10, PotItem.FiveRupees, 'Skull X Room'), Pot(12, 20, PotItem.Key, 'Skull 2 West Lobby'),
Pot(48, 20, PotItem.Nothing, 'Skull 2 West Lobby')],
87: [Pot(92, 7, PotItem.BigMagic, 'Skull Lone Pot'), Pot(32, 4, PotItem.Nothing, 'Skull Big Key'), Pot(92, 23, PotItem.Bomb, 'Skull Pot Prison'), Pot(100, 23, PotItem.SmallMagic, 'Skull Pot Prison'),
Pot(84, 25, PotItem.FiveRupees, 'Skull Pot Prison'), Pot(76, 27, PotItem.Heart, 'Skull Pot Prison'), Pot(12, 20, PotItem.SmallMagic, 'Skull 2 East Lobby'), Pot(48, 20, PotItem.SmallMagic, 'Skull 2 East Lobby'),
Pot(30, 22, PotItem.Switch, 'Skull 2 East Lobby')],
@@ -103,8 +117,13 @@ vanilla_pots = {
Pot(96, 9, PotItem.Nothing, 'Skull Pot Circle'), Pot(92, 8, PotItem.Nothing, 'Skull Pot Circle'), Pot(108, 8, PotItem.Nothing, 'Skull Pot Circle'), Pot(108, 6, PotItem.Nothing, 'Skull Pot Circle'),
Pot(104, 5, PotItem.Nothing, 'Skull Pot Circle'), Pot(92, 6, PotItem.Nothing, 'Skull Pot Circle'), Pot(96, 5, PotItem.Bomb, 'Skull Pot Circle'), Pot(100, 5, PotItem.SmallMagic, 'Skull Pot Circle'),
Pot(92, 7, PotItem.Heart, 'Skull Pot Circle'), Pot(108, 7, PotItem.Heart, 'Skull Pot Circle'), Pot(100, 9, PotItem.SmallMagic, 'Skull Pot Circle'), Pot(104, 9, PotItem.Bomb, 'Skull Pot Circle')],
89: [Pot(26, 43, PotItem.Heart, 'Skull 3 Lobby'), Pot(32, 40, PotItem.Nothing, 'Skull 3 Lobby'), Pot(76, 28, PotItem.Nothing, 'Skull East Bridge'), Pot(112, 28, PotItem.Nothing, 'Skull East Bridge')],
91: [Pot(218, 37, PotItem.Nothing, 'GT Hidden Spikes'), Pot(222, 37, PotItem.Switch, 'GT Hidden Spikes'), Pot(226, 37, PotItem.Nothing, 'GT Hidden Spikes')],
0x59: [Pot(26, 0xb, PotItem.Heart, 'Skull 3 Lobby', PotFlags.LowerRegion),
Pot(32, 8, PotItem.Nothing, 'Skull 3 Lobby', PotFlags.LowerRegion),
Pot(76, 28, PotItem.Nothing, 'Skull East Bridge'),
Pot(112, 28, PotItem.Nothing, 'Skull East Bridge')],
0x5B: [Pot(218, 0x5, PotItem.Nothing, 'GT Hidden Spikes', PotFlags.LowerRegion),
Pot(222, 0x5, PotItem.Switch, 'GT Hidden Spikes', PotFlags.LowerRegion),
Pot(226, 0x5, PotItem.Nothing, 'GT Hidden Spikes', PotFlags.LowerRegion)],
92: [Pot(228, 25, PotItem.Nothing, 'GT Refill'), Pot(104, 24, PotItem.Nothing, 'GT Refill'), Pot(228, 22, PotItem.Nothing, 'GT Refill'), Pot(216, 25, PotItem.Nothing, 'GT Refill'), Pot(84, 24, PotItem.Nothing, 'GT Refill'),
Pot(216, 22, PotItem.Nothing, 'GT Refill'), Pot(94, 22, PotItem.Bomb, 'GT Refill'), Pot(94, 26, PotItem.BigMagic, 'GT Refill')],
93: [Pot(16, 5, PotItem.Bomb, 'GT Gauntlet 2'), Pot(44, 5, PotItem.FiveRupees, 'GT Gauntlet 2'), Pot(16, 11, PotItem.OneRupee, 'GT Gauntlet 2'), Pot(44, 11, PotItem.FiveArrows, 'GT Gauntlet 2'), Pot(12, 20, PotItem.FiveArrows, 'GT Gauntlet 3'),
@@ -113,15 +132,22 @@ vanilla_pots = {
95: [Pot(44, 27, PotItem.Switch, 'Ice Spike Room')],
96: [Pot(76, 4, PotItem.Heart, 'Hyrule Castle West Lobby'), Pot(112, 4, PotItem.Heart, 'Hyrule Castle West Lobby')],
98: [Pot(208, 21, PotItem.Heart, 'Hyrule Castle East Lobby')],
99: [Pot(48, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 8, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 12, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 8, PotItem.Heart, 'Desert Tiles 1'),
0x63: [Pot(48, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 4, PotItem.Nothing, 'Desert Tiles 1'), Pot(12, 8, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 12, PotItem.Nothing, 'Desert Tiles 1'), Pot(48, 8, PotItem.Heart, 'Desert Tiles 1'),
Pot(12, 12, PotItem.Key, 'Desert Tiles 1')],
100: [Pot(12, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange), Pot(16, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange), Pot(20, 22, PotItem.Bomb, 'Thieves Attic Hint', PotFlags.SwitchLogicChange),
Pot(36, 28, PotItem.Bomb, 'Thieves Attic'), Pot(40, 28, PotItem.SmallMagic, 'Thieves Attic'),
Pot(44, 28, PotItem.SmallMagic, 'Thieves Attic'), Pot(48, 28, PotItem.Switch, 'Thieves Attic')],
101: [Pot(100, 28, PotItem.Bomb, 'Thieves Attic Window'), Pot(104, 28, PotItem.Bomb, 'Thieves Attic Window')],
102: [Pot(48, 37, PotItem.FiveArrows, 'Swamp Refill'), Pot(52, 37, PotItem.Bomb, 'Swamp Refill'), Pot(56, 37, PotItem.FiveRupees, 'Swamp Refill'), Pot(48, 38, PotItem.FiveArrows, 'Swamp Refill'), Pot(52, 38, PotItem.Bomb, 'Swamp Refill'),
Pot(56, 38, PotItem.FiveRupees, 'Swamp Refill'), Pot(84, 5, PotItem.Heart, 'Swamp Behind Waterfall'), Pot(104, 5, PotItem.FiveArrows, 'Swamp Behind Waterfall'), Pot(84, 6, PotItem.Heart, 'Swamp Behind Waterfall'),
Pot(104, 6, PotItem.Bomb, 'Swamp Behind Waterfall')],
0x66: [Pot(48, 0x5, PotItem.FiveArrows, 'Swamp Refill', PotFlags.LowerRegion),
Pot(52, 0x5, PotItem.Bomb, 'Swamp Refill', PotFlags.LowerRegion),
Pot(56, 0x5, PotItem.FiveRupees, 'Swamp Refill', PotFlags.LowerRegion),
Pot(48, 0x6, PotItem.FiveArrows, 'Swamp Refill', PotFlags.LowerRegion),
Pot(52, 0x6, PotItem.Bomb, 'Swamp Refill', PotFlags.LowerRegion),
Pot(56, 0x6, PotItem.FiveRupees, 'Swamp Refill', PotFlags.LowerRegion),
Pot(84, 5, PotItem.Heart, 'Swamp Behind Waterfall'),
Pot(104, 5, PotItem.FiveArrows, 'Swamp Behind Waterfall'),
Pot(84, 6, PotItem.Heart, 'Swamp Behind Waterfall'),
Pot(104, 6, PotItem.Bomb, 'Swamp Behind Waterfall')],
103: [Pot(22, 26, PotItem.Nothing, 'Skull Left Drop'), Pot(18, 22, PotItem.Nothing, 'Skull Left Drop'), Pot(12, 7, PotItem.FiveArrows, 'Skull Left Drop'), Pot(48, 7, PotItem.SmallMagic, 'Skull Left Drop'),
Pot(18, 23, PotItem.SmallMagic, 'Skull Left Drop'), Pot(18, 26, PotItem.Heart, 'Skull Left Drop'), Pot(96, 19, PotItem.Heart, 'Skull Compass Room'), Pot(74, 20, PotItem.SmallMagic, 'Skull Compass Room'),
Pot(92, 9, PotItem.Nothing, 'Skull Compass Room'), Pot(84, 28, PotItem.Nothing, 'Skull Compass Room'), Pot(104, 28, PotItem.Heart, 'Skull Compass Room')],
@@ -139,22 +165,24 @@ vanilla_pots = {
Pot(46, 11, PotItem.FiveArrows, 'Desert Map Room'), Pot(78, 11, PotItem.FiveArrows, 'Desert Map Room'), Pot(110, 11, PotItem.Heart, 'Desert Map Room')],
117: [Pot(148, 22, PotItem.SmallMagic, 'Desert Arrow Pot Corner'), Pot(160, 22, PotItem.FiveArrows, 'Desert Arrow Pot Corner'), Pot(172, 22, PotItem.Heart, 'Desert Arrow Pot Corner')],
118: [Pot(112, 12, PotItem.Heart, 'Swamp Drain Right'), Pot(84, 23, PotItem.Heart, 'Swamp Flooded Spot'), Pot(96, 23, PotItem.Heart, 'Swamp Flooded Spot')],
123: [Pot(48, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(88, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(76, 7, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(60, 4, PotItem.Heart, 'GT Conveyor Star Pits'),
0x7B: [Pot(48, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(88, 10, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(76, 7, PotItem.Nothing, 'GT Conveyor Star Pits'), Pot(60, 4, PotItem.Heart, 'GT Conveyor Star Pits'),
Pot(64, 4, PotItem.Key, 'GT Conveyor Star Pits')],
124: [Pot(36, 21, PotItem.Nothing, 'GT Falling Bridge'), Pot(24, 11, PotItem.Nothing, 'GT Falling Bridge'), Pot(28, 4, PotItem.Heart, 'GT Falling Bridge'), Pot(32, 4, PotItem.Heart, 'GT Falling Bridge')],
125: [Pot(44, 12, PotItem.Nothing, 'GT Firesnake Room'), Pot(44, 6, PotItem.Nothing, 'GT Firesnake Room'), Pot(112, 6, PotItem.Heart, 'GT Firesnake Room'), Pot(108, 20, PotItem.FiveArrows, 'GT Warp Maze - Pot Rail'),
Pot(114, 20, PotItem.Bomb, 'GT Petting Zoo'), Pot(76, 28, PotItem.Bomb, 'GT Petting Zoo')],
126: [Pot(86, 15, PotItem.Heart, 'Ice Tall Hint'), Pot(82, 26, PotItem.SmallMagic, 'Ice Tall Hint'), Pot(100, 26, PotItem.Switch, 'Ice Tall Hint'), Pot(104, 26, PotItem.Nothing, 'Ice Tall Hint')],
128: [Pot(48, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock'), Pot(52, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock'), Pot(56, 4, PotItem.Heart, 'Hyrule Dungeon Cellblock')],
130: [Pot(50, 5, PotItem.Nothing, 'Hyrule Dungeon South Abyss'), Pot(50, 10, PotItem.Nothing, 'Hyrule Dungeon South Abyss'), Pot(76, 50, PotItem.Heart, 'Hyrule Dungeon South Abyss')],
0x82: [Pot(50, 0x5, PotItem.Nothing, 'Hyrule Dungeon South Abyss', PotFlags.LowerRegion),
Pot(50, 0xA, PotItem.Nothing, 'Hyrule Dungeon South Abyss', PotFlags.LowerRegion),
Pot(76, 0x12, PotItem.Heart, 'Hyrule Dungeon South Abyss', PotFlags.LowerRegion)],
131: [Pot(76, 4, PotItem.FiveArrows, 'Desert West Wing'), Pot(80, 4, PotItem.OneRupee, 'Desert West Wing'), Pot(76, 28, PotItem.FiveRupees, 'Desert West Wing'), Pot(80, 28, PotItem.FiveArrows, 'Desert West Wing')],
132: [Pot(64, 17, PotItem.Nothing, 'Desert Main Lobby'), Pot(60, 17, PotItem.Nothing, 'Desert Main Lobby'), Pot(80, 14, PotItem.Nothing, 'Desert Main Lobby'), Pot(44, 14, PotItem.Nothing, 'Desert Main Lobby'),
Pot(100, 6, PotItem.Nothing, 'Desert Main Lobby'), Pot(24, 6, PotItem.Nothing, 'Desert Main Lobby'), Pot(24, 7, PotItem.FiveArrows, 'Desert Main Lobby'), Pot(100, 7, PotItem.FiveArrows, 'Desert Main Lobby')],
133: [Pot(44, 28, PotItem.Heart, 'Desert East Wing'), Pot(48, 28, PotItem.FiveArrows, 'Desert East Wing')],
135: [Pot(12, 11, PotItem.Nothing, 'Hera Tile Room'), Pot(16, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(40, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(32, 12, PotItem.Nothing, 'Hera Tile Room'), Pot(24, 12, PotItem.Nothing, 'Hera Tile Room'),
Pot(16, 11, PotItem.Nothing, 'Hera Tile Room'), Pot(76, 20, PotItem.SmallMagic, 'Hera Torches'), Pot(112, 20, PotItem.BigMagic, 'Hera Torches')],
139: [Pot(76, 12, PotItem.Nothing, 'GT Conveyor Cross'), Pot(112, 12, PotItem.Key, 'GT Conveyor Cross'), Pot(32, 23, PotItem.Nothing, 'GT Hookshot South Platform'), Pot(28, 23, PotItem.Nothing, 'GT Hookshot South Platform'),
Pot(32, 9, PotItem.SmallMagic, 'GT Hookshot East Platform'), Pot(76, 20, PotItem.Nothing, 'GT Map Room'), Pot(76, 28, PotItem.Heart, 'GT Map Room')],
0x8B: [Pot(76, 12, PotItem.Nothing, 'GT Conveyor Cross'), Pot(112, 12, PotItem.Key, 'GT Conveyor Cross'), Pot(32, 23, PotItem.Nothing, 'GT Hookshot South Platform'), Pot(28, 23, PotItem.Nothing, 'GT Hookshot South Platform'),
Pot(32, 9, PotItem.SmallMagic, 'GT Hookshot East Platform'), Pot(76, 20, PotItem.Nothing, 'GT Map Room'), Pot(76, 28, PotItem.Heart, 'GT Map Room')],
140: [Pot(76, 12, PotItem.Switch, 'GT Hope Room'), Pot(112, 12, PotItem.SmallMagic, 'GT Hope Room'), Pot(76, 20, PotItem.Bomb, "GT Bob's Room"), Pot(92, 20, PotItem.Bomb, "GT Bob's Room"), Pot(100, 21, PotItem.FiveArrows, "GT Bob's Room"),
Pot(104, 26, PotItem.Bomb, "GT Bob's Room"), Pot(88, 27, PotItem.Bomb, "GT Bob's Room")],
141: [Pot(204, 11, PotItem.Nothing, 'GT Speed Torch Upper'), Pot(204, 14, PotItem.BigMagic, 'GT Speed Torch Upper'), Pot(28, 23, PotItem.Heart, 'GT Pots n Blocks'), Pot(36, 23, PotItem.Heart, 'GT Pots n Blocks'),
@@ -162,37 +190,59 @@ vanilla_pots = {
142: [Pot(80, 5, PotItem.FiveArrows, 'Ice Lonely Freezor'), Pot(80, 6, PotItem.Nothing, 'Ice Lonely Freezor')],
145: [Pot(84, 4, PotItem.Heart, 'Mire Falling Foes'), Pot(104, 4, PotItem.SmallMagic, 'Mire Falling Foes')],
146: [Pot(86, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(92, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(98, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy'), Pot(104, 23, PotItem.Nothing, 'Mire Tall Dark and Roomy')],
147: [Pot(28, 7, PotItem.Switch, 'Mire Dark Shooters'), Pot(96, 7, PotItem.Heart, 'Mire Dark Shooters', PotFlags.NoSwitch)],
150: [Pot(14, 18, PotItem.Nothing, 'GT Torch Cross'), Pot(32, 5, PotItem.Nothing, 'GT Torch Cross'), Pot(32, 17, PotItem.SmallMagic, 'GT Torch Cross'), Pot(32, 24, PotItem.SmallMagic, 'GT Torch Cross'),
Pot(14, 24, PotItem.Nothing, 'GT Torch Cross'), Pot(76, 21, PotItem.Heart, 'GT Staredown'), Pot(112, 21, PotItem.BigMagic, 'GT Staredown')],
0x93: [Pot(28, 7, PotItem.Switch, 'Mire Dark Shooters'),
Pot(0x9C, 0x17, PotItem.Switch, 'Mire Block X', PotFlags.Block),
Pot(96, 7, PotItem.Heart, 'Mire Dark Shooters', PotFlags.NoSwitch)],
0x96: [Pot(14, 18, PotItem.Nothing, 'GT Torch Cross'),
Pot(32, 5, PotItem.Nothing, 'GT Torch Cross'),
Pot(0x2e, 0xb, PotItem.Nothing, 'GT Torch Cross'),
Pot(32, 17, PotItem.SmallMagic, 'GT Torch Cross'),
Pot(32, 24, PotItem.SmallMagic, 'GT Torch Cross'),
Pot(14, 24, PotItem.Nothing, 'GT Torch Cross'),
Pot(76, 21, PotItem.Heart, 'GT Staredown'),
Pot(112, 21, PotItem.BigMagic, 'GT Staredown')],
153: [Pot(40, 20, PotItem.SmallMagic, 'Eastern Darkness'), Pot(84, 20, PotItem.Heart, 'Eastern Darkness')],
155: [Pot(48, 4, PotItem.SmallMagic, 'GT Double Switch Pot Corners'), Pot(48, 12, PotItem.Key, 'GT Double Switch Pot Corners'), Pot(28, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section'), Pot(32, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section')],
0x9B: [Pot(48, 4, PotItem.SmallMagic, 'GT Double Switch Pot Corners'), Pot(48, 12, PotItem.Key, 'GT Double Switch Pot Corners'), Pot(28, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section'), Pot(32, 24, PotItem.Nothing, 'GT Warp Maze - Mid Section')],
156: [Pot(56, 8, PotItem.SmallMagic, 'GT Invisible Catwalk'), Pot(56, 9, PotItem.FiveArrows, 'GT Invisible Catwalk')],
157: [Pot(76, 4, PotItem.Bomb, 'GT Crystal Conveyor Left'), Pot(84, 4, PotItem.SmallMagic, 'GT Crystal Conveyor Left'), Pot(32, 7, PotItem.Nothing, 'GT Compass Room'), Pot(40, 9, PotItem.Nothing, 'GT Compass Room')],
159: [Pot(138, 20, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 19, PotItem.Heart, 'Ice Many Pots'), Pot(178, 19, PotItem.Heart, 'Ice Many Pots'), Pot(40, 21, PotItem.Switch, 'Ice Many Pots'), Pot(138, 21, PotItem.Key, 'Ice Many Pots'),
Pot(20, 27, PotItem.Heart, 'Ice Many Pots'), Pot(138, 27, PotItem.Heart, 'Ice Many Pots'), Pot(178, 28, PotItem.Heart, 'Ice Many Pots'), Pot(178, 21, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 20, PotItem.Nothing, 'Ice Many Pots'),
Pot(40, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 26, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 28, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 26, PotItem.Nothing, 'Ice Many Pots'),
Pot(20, 21, PotItem.Nothing, 'Ice Many Pots')],
161: [Pot(150, 6, PotItem.Key, 'Mire Fishbone'), Pot(100, 11, PotItem.SmallMagic, 'Mire Fishbone'), Pot(104, 12, PotItem.Heart, 'Mire Fishbone'), Pot(108, 13, PotItem.SmallMagic, 'Mire Fishbone'), Pot(112, 14, PotItem.Heart, 'Mire Fishbone'),
Pot(96, 27, PotItem.Nothing, 'Mire South Fish'), Pot(92, 21, PotItem.Nothing, 'Mire South Fish'), Pot(96, 23, PotItem.Heart, 'Mire South Fish'), Pot(92, 25, PotItem.Nothing, 'Mire South Fish'),
Pot(76, 28, PotItem.Nothing, 'Mire South Fish'), Pot(112, 28, PotItem.Nothing, 'Mire South Fish')],
162: [Pot(12, 28, PotItem.BigMagic, 'Mire Left Bridge')],
0x9F: [Pot(138, 20, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 19, PotItem.Heart, 'Ice Many Pots'), Pot(178, 19, PotItem.Heart, 'Ice Many Pots'), Pot(40, 21, PotItem.Switch, 'Ice Many Pots'), Pot(138, 21, PotItem.Key, 'Ice Many Pots'),
Pot(20, 27, PotItem.Heart, 'Ice Many Pots'), Pot(138, 27, PotItem.Heart, 'Ice Many Pots'), Pot(178, 28, PotItem.Heart, 'Ice Many Pots'), Pot(178, 21, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 20, PotItem.Nothing, 'Ice Many Pots'),
Pot(40, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 27, PotItem.Nothing, 'Ice Many Pots'), Pot(178, 26, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 28, PotItem.Nothing, 'Ice Many Pots'), Pot(138, 26, PotItem.Nothing, 'Ice Many Pots'),
Pot(20, 21, PotItem.Nothing, 'Ice Many Pots')],
0xA1: [Pot(150, 6, PotItem.Key, 'Mire Fishbone'), Pot(100, 11, PotItem.SmallMagic, 'Mire Fishbone'), Pot(104, 12, PotItem.Heart, 'Mire Fishbone'), Pot(108, 13, PotItem.SmallMagic, 'Mire Fishbone'), Pot(112, 14, PotItem.Heart, 'Mire Fishbone'),
Pot(96, 27, PotItem.Nothing, 'Mire South Fish'), Pot(92, 21, PotItem.Nothing, 'Mire South Fish'), Pot(96, 23, PotItem.Heart, 'Mire South Fish'), Pot(92, 25, PotItem.Nothing, 'Mire South Fish'),
Pot(76, 28, PotItem.Nothing, 'Mire South Fish'), Pot(112, 28, PotItem.Nothing, 'Mire South Fish')],
0xA2: [Pot(12, 28, PotItem.BigMagic, 'Mire Left Bridge')],
168: [Pot(138, 28, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(178, 28, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(178, 19, PotItem.Nothing, 'Eastern Stalfos Spawn'), Pot(138, 19, PotItem.Heart, 'Eastern Stalfos Spawn'),
Pot(30, 24, PotItem.OneRupee, 'Eastern Stalfos Spawn')],
169: [Pot(144, 43, PotItem.FiveArrows, 'Eastern Courtyard'), Pot(236, 43, PotItem.FiveArrows, 'Eastern Courtyard'), Pot(144, 44, PotItem.FiveArrows, 'Eastern Courtyard'), Pot(236, 44, PotItem.Heart, 'Eastern Courtyard'),
Pot(12, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'), Pot(112, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'), Pot(16, 20, PotItem.Heart, 'Eastern Courtyard Ledge'), Pot(108, 20, PotItem.Heart, 'Eastern Courtyard Ledge')],
170: [Pot(212, 10, PotItem.Nothing, 'Eastern Pot Switch'), Pot(232, 10, PotItem.Nothing, 'Eastern Pot Switch'), Pot(232, 5, PotItem.Nothing, 'Eastern Pot Switch'), Pot(212, 5, PotItem.Heart, 'Eastern Pot Switch'),
Pot(94, 8, PotItem.Switch, 'Eastern Pot Switch'), Pot(108, 55, PotItem.Heart, 'Eastern Map Balcony'), Pot(108, 56, PotItem.Heart, 'Eastern Map Balcony'), Pot(108, 57, PotItem.Heart, 'Eastern Map Balcony')],
171: [Pot(20, 24, PotItem.Key, 'Thieves Spike Switch')],
0xA9: [Pot(144, 0xB, PotItem.FiveArrows, 'Eastern Courtyard', PotFlags.LowerRegion),
Pot(236, 0xB, PotItem.FiveArrows, 'Eastern Courtyard', PotFlags.LowerRegion),
Pot(144, 0xC, PotItem.FiveArrows, 'Eastern Courtyard', PotFlags.LowerRegion),
Pot(236, 0xC, PotItem.Heart, 'Eastern Courtyard', PotFlags.LowerRegion),
Pot(12, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'),
Pot(112, 19, PotItem.Nothing, 'Eastern Courtyard Ledge'),
Pot(16, 20, PotItem.Heart, 'Eastern Courtyard Ledge'),
Pot(108, 20, PotItem.Heart, 'Eastern Courtyard Ledge')],
0xAA: [Pot(212, 10, PotItem.Nothing, 'Eastern Pot Switch'), Pot(232, 10, PotItem.Nothing, 'Eastern Pot Switch'),
Pot(232, 5, PotItem.Nothing, 'Eastern Pot Switch'), Pot(212, 5, PotItem.Heart, 'Eastern Pot Switch'),
Pot(94, 8, PotItem.Switch, 'Eastern Pot Switch'),
Pot(108, 0x17, PotItem.Heart, 'Eastern Map Balcony', PotFlags.LowerRegion),
Pot(108, 0x18, PotItem.Heart, 'Eastern Map Balcony', PotFlags.LowerRegion),
Pot(108, 0x19, PotItem.Heart, 'Eastern Map Balcony', PotFlags.LowerRegion)],
0xAB: [Pot(20, 24, PotItem.Key, 'Thieves Spike Switch')],
174: [Pot(76, 12, PotItem.Switch, 'Iced T')],
176: [Pot(20, 27, PotItem.Nothing, 'Tower Circle of Pots'), Pot(24, 24, PotItem.Nothing, 'Tower Circle of Pots'), Pot(44, 25, PotItem.Nothing, 'Tower Circle of Pots'), Pot(20, 21, PotItem.Bomb, 'Tower Circle of Pots'),
Pot(28, 21, PotItem.OneRupee, 'Tower Circle of Pots'), Pot(32, 21, PotItem.FiveRupees, 'Tower Circle of Pots'), Pot(40, 21, PotItem.FiveArrows, 'Tower Circle of Pots'), Pot(16, 23, PotItem.FiveRupees, 'Tower Circle of Pots'),
Pot(44, 23, PotItem.OneRupee, 'Tower Circle of Pots'), Pot(36, 24, PotItem.Heart, 'Tower Circle of Pots'), Pot(16, 25, PotItem.Heart, 'Tower Circle of Pots'), Pot(28, 27, PotItem.FiveArrows, 'Tower Circle of Pots'),
Pot(40, 27, PotItem.Bomb, 'Tower Circle of Pots'), Pot(32, 27, PotItem.Nothing, 'Tower Circle of Pots')],
177: [Pot(76, 4, PotItem.Heart, 'Mire Spike Barrier'), Pot(112, 4, PotItem.OneRupee, 'Mire Spike Barrier')],
178: [Pot(48, 40, PotItem.OneRupee, 'Mire BK Door Room'), Pot(76, 40, PotItem.OneRupee, 'Mire BK Door Room'), Pot(48, 41, PotItem.Nothing, 'Mire BK Door Room'), Pot(76, 41, PotItem.Heart, 'Mire BK Door Room'),
Pot(48, 42, PotItem.Nothing, 'Mire BK Door Room'), Pot(76, 40, PotItem.Nothing, 'Mire BK Door Room')],
179: [Pot(12, 20, PotItem.Key, 'Mire Spikes'), Pot(48, 20, PotItem.SmallMagic, 'Mire Spikes'), Pot(48, 28, PotItem.Switch, 'Mire Spikes')],
0xB2: [Pot(48, 0x8, PotItem.OneRupee, 'Mire BK Door Room', PotFlags.LowerRegion),
Pot(76, 0x8, PotItem.OneRupee, 'Mire BK Door Room', PotFlags.LowerRegion),
Pot(48, 0x9, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion),
Pot(76, 0x9, PotItem.Heart, 'Mire BK Door Room', PotFlags.LowerRegion),
Pot(48, 0xA, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion),
Pot(76, 0xA, PotItem.Nothing, 'Mire BK Door Room', PotFlags.LowerRegion)],
0xB3: [Pot(12, 20, PotItem.Key, 'Mire Spikes'), Pot(48, 20, PotItem.SmallMagic, 'Mire Spikes'), Pot(48, 28, PotItem.Switch, 'Mire Spikes')],
180: [Pot(44, 28, PotItem.BigMagic, 'TR Final Abyss'), Pot(48, 28, PotItem.Heart, 'TR Final Abyss')],
181: [Pot(112, 4, PotItem.FiveRupees, 'TR Dark Ride'), Pot(112, 15, PotItem.Heart, 'TR Dark Ride'), Pot(76, 16, PotItem.Switch, 'TR Dark Ride'), Pot(112, 16, PotItem.BigMagic, 'TR Dark Ride'), Pot(112, 17, PotItem.Heart, 'TR Dark Ride'),
Pot(112, 28, PotItem.Bomb, 'TR Dark Ride')],
@@ -200,9 +250,9 @@ vanilla_pots = {
183: [Pot(30, 5, PotItem.SmallMagic, 'TR Roller Room')],
184: [Pot(96, 13, PotItem.Switch, 'Eastern Big Key'), Pot(88, 16, PotItem.Heart, 'Eastern Big Key'), Pot(104, 16, PotItem.Heart, 'Eastern Big Key')],
185: [Pot(92, 18, PotItem.OneRupee, 'Eastern Cannonball'), Pot(96, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(104, 18, PotItem.FiveRupees, 'Eastern Cannonball'), Pot(108, 18, PotItem.OneRupee, 'Eastern Cannonball')],
186: [Pot(100, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(88, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(94, 4, PotItem.OneRupee, 'Eastern Dark Pots'), Pot(76, 6, PotItem.Heart, 'Eastern Dark Pots'),
0xBA: [Pot(100, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(88, 8, PotItem.Nothing, 'Eastern Dark Pots'), Pot(94, 4, PotItem.OneRupee, 'Eastern Dark Pots'), Pot(76, 6, PotItem.Heart, 'Eastern Dark Pots'),
Pot(112, 6, PotItem.Key, 'Eastern Dark Pots'), Pot(76, 10, PotItem.Heart, 'Eastern Dark Pots'), Pot(112, 10, PotItem.SmallMagic, 'Eastern Dark Pots'), Pot(94, 12, PotItem.OneRupee, 'Eastern Dark Pots')],
188: [Pot(86, 4, PotItem.Heart, 'Thieves Hallway'), Pot(102, 4, PotItem.Key, 'Thieves Hallway'), Pot(138, 3, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(178, 3, PotItem.Switch, 'Thieves Conveyor Maze'),
0xBC: [Pot(86, 4, PotItem.Heart, 'Thieves Hallway'), Pot(102, 4, PotItem.Key, 'Thieves Hallway'), Pot(138, 3, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(178, 3, PotItem.Switch, 'Thieves Conveyor Maze'),
Pot(138, 12, PotItem.Heart, 'Thieves Conveyor Maze'), Pot(178, 12, PotItem.Bomb, 'Thieves Conveyor Maze'), Pot(12, 20, PotItem.Nothing, 'Thieves Pot Alcove Mid'), Pot(48, 20, PotItem.Bomb, 'Thieves Pot Alcove Mid'),
Pot(12, 28, PotItem.Bomb, 'Thieves Pot Alcove Mid'), Pot(48, 28, PotItem.Bomb, 'Thieves Pot Alcove Mid'), Pot(28, 21, PotItem.FiveRupees, 'Thieves Pot Alcove Top'), Pot(32, 21, PotItem.FiveRupees, 'Thieves Pot Alcove Top'),
Pot(28, 27, PotItem.FiveRupees, 'Thieves Pot Alcove Bottom'), Pot(32, 27, PotItem.FiveRupees, 'Thieves Pot Alcove Bottom')],
@@ -210,7 +260,10 @@ vanilla_pots = {
191: [Pot(40, 20, PotItem.FiveArrows, 'Ice Refill'), Pot(44, 20, PotItem.Heart, 'Ice Refill'), Pot(48, 20, PotItem.Bomb, 'Ice Refill'), Pot(40, 28, PotItem.SmallMagic, 'Ice Refill'), Pot(44, 28, PotItem.SmallMagic, 'Ice Refill'),
Pot(48, 28, PotItem.SmallMagic, 'Ice Refill')],
192: [Pot(48, 10, PotItem.Bomb, 'Tower Dark Pits'), Pot(12, 14, PotItem.FiveRupees, 'Tower Dark Pits'), Pot(12, 26, PotItem.Heart, 'Tower Dark Pits'), Pot(28, 27, PotItem.OneRupee, 'Tower Dark Pits')],
194: [Pot(180, 7, PotItem.Switch, 'Mire Hub Switch'), Pot(100, 46, PotItem.SmallMagic, 'Mire Hub Right'), Pot(68, 48, PotItem.OneRupee, 'Mire Hub'), Pot(64, 52, PotItem.FiveArrows, 'Mire Hub')],
0xC2: [Pot(180, 7, PotItem.Switch, 'Mire Hub Switch'),
Pot(100, 0xE, PotItem.SmallMagic, 'Mire Hub Right', PotFlags.LowerRegion),
Pot(68, 0x10, PotItem.OneRupee, 'Mire Hub', PotFlags.LowerRegion),
Pot(64, 0x14, PotItem.FiveArrows, 'Mire Hub', PotFlags.LowerRegion)],
196: [Pot(84, 9, PotItem.Bomb, 'TR Crystal Maze Interior'), Pot(24, 14, PotItem.Heart, 'TR Crystal Maze Interior'), Pot(56, 17, PotItem.FiveRupees, 'TR Crystal Maze Interior'), Pot(84, 17, PotItem.Bomb, 'TR Crystal Maze Interior'),
Pot(12, 21, PotItem.FiveArrows, 'TR Crystal Maze Interior'), Pot(76, 23, PotItem.OneRupee, 'TR Crystal Maze Interior'), Pot(48, 25, PotItem.SmallMagic, 'TR Crystal Maze Interior'), Pot(12, 26, PotItem.Heart, 'TR Crystal Maze Interior')],
198: [Pot(12, 7, PotItem.BigMagic, 'TR Hub'), Pot(12, 25, PotItem.Heart, 'TR Hub')],
@@ -219,7 +272,7 @@ vanilla_pots = {
203: [Pot(80, 4, PotItem.Nothing, 'Thieves Ambush'), Pot(80, 28, PotItem.Nothing, 'Thieves Ambush'), Pot(88, 16, PotItem.Heart, 'Thieves Ambush'), Pot(88, 28, PotItem.FiveRupees, 'Thieves Ambush')],
204: [Pot(36, 4, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(36, 28, PotItem.FiveRupees, 'Thieves Rail Ledge'), Pot(112, 4, PotItem.Heart, 'Thieves BK Corner'), Pot(112, 28, PotItem.Bomb, 'Thieves BK Corner')],
206: [Pot(76, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(80, 8, PotItem.SmallMagic, 'Ice Antechamber'), Pot(108, 12, PotItem.Bomb, 'Ice Antechamber'), Pot(112, 12, PotItem.FiveArrows, 'Ice Antechamber'),
Pot(204, 11, PotItem.Hole, 'Ice Antechamber')],
Pot(204, 11, PotItem.Hole, 'Ice Antechamber')], # Pot(0x6c, 8, PotItem.Nothing, 'Ice Antechamber', PotFlags.Block) this one has jellies
208: [Pot(158, 5, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(140, 11, PotItem.OneRupee, 'Tower Dark Maze'), Pot(42, 13, PotItem.SmallMagic, 'Tower Dark Maze'), Pot(48, 16, PotItem.Heart, 'Tower Dark Maze'),
Pot(176, 20, PotItem.OneRupee, 'Tower Dark Maze'), Pot(146, 23, PotItem.FiveRupees, 'Tower Dark Maze'), Pot(12, 28, PotItem.Heart, 'Tower Dark Maze')],
209: [Pot(48, 4, PotItem.BigMagic, 'Mire Conveyor Barrier'), Pot(168, 7, PotItem.OneRupee, 'Mire Conveyor Barrier'), Pot(76, 4, PotItem.OneRupee, 'Mire Neglected Room'), Pot(112, 4, PotItem.FiveArrows, 'Mire Neglected Room'),
@@ -229,55 +282,73 @@ vanilla_pots = {
Pot(202, 12, PotItem.FiveArrows, 'Eastern Duo Eyegores'), Pot(242, 12, PotItem.Heart, 'Eastern Duo Eyegores'), Pot(92, 24, PotItem.Heart, 'Eastern Single Eyegore'), Pot(96, 24, PotItem.FiveArrows, 'Eastern Single Eyegore')],
217: [Pot(92, 20, PotItem.FiveArrows, 'Eastern False Switches'), Pot(92, 28, PotItem.Heart, 'Eastern False Switches')],
218: [Pot(24, 23, PotItem.FiveArrows, 'Eastern Attic Start'), Pot(36, 23, PotItem.FiveArrows, 'Eastern Attic Start'), Pot(24, 25, PotItem.Switch, 'Eastern Attic Start'), Pot(36, 25, PotItem.Heart, 'Eastern Attic Start')],
219: [Pot(12, 4, PotItem.Nothing, 'Thieves Lobby'), Pot(62, 19, PotItem.Nothing, 'Thieves Lobby'), Pot(112, 4, PotItem.FiveRupees, 'Thieves Lobby'), Pot(88, 16, PotItem.Heart, 'Thieves Lobby')],
220: [Pot(56, 4, PotItem.FiveRupees, 'Thieves Compass Room'), Pot(112, 4, PotItem.Bomb, 'Thieves Compass Room'), Pot(68, 16, PotItem.Heart, 'Thieves Compass Room'), Pot(12, 28, PotItem.FiveArrows, 'Thieves Compass Room')],
227: [Pot(88, 55, PotItem.Nothing, 'Bat Cave (right)'), Pot(100, 57, PotItem.OneRupee, 'Bat Cave (right)')],
228: [Pot(32, 9, PotItem.FiveRupees, 'Old Man House'), Pot(112, 10, PotItem.OneRupee, 'Old Man House')],
229: [Pot(48, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(76, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(112, 16, PotItem.OneRupee, 'Old Man House Back'), Pot(64, 18, PotItem.FiveRupees, 'Old Man House Back')],
230: [Pot(108, 12, PotItem.FiveArrows, 'Death Mountain Return Cave'), Pot(88, 16, PotItem.Heart, 'Death Mountain Return Cave'), Pot(72, 20, PotItem.Nothing, 'Death Mountain Return Cave'),
Pot(56, 24, PotItem.OneRupee, 'Death Mountain Return Cave')],
231: [Pot(68, 5, PotItem.OneRupee, 'Death Mountain Return Cave'), Pot(72, 5, PotItem.OneRupee, 'Death Mountain Return Cave')],
232: [Pot(96, 4, PotItem.Heart, 'Superbunny Cave')],
0xDB: [Pot(12, 4, PotItem.Nothing, 'Thieves Lobby'),
Pot(62, 19, PotItem.Nothing, 'Thieves Lobby', PotFlags.LowerRegion),
Pot(112, 4, PotItem.FiveRupees, 'Thieves Lobby'), Pot(88, 16, PotItem.Heart, 'Thieves Lobby')],
0xDC: [Pot(56, 4, PotItem.FiveRupees, 'Thieves Compass Room'), Pot(112, 4, PotItem.Bomb, 'Thieves Compass Room'), Pot(68, 16, PotItem.Heart, 'Thieves Compass Room'), Pot(12, 28, PotItem.FiveArrows, 'Thieves Compass Room')],
0xE3: [Pot(88, 0x17, PotItem.Nothing, 'Bat Cave (right)', PotFlags.LowerRegion),
Pot(100, 0x19, PotItem.OneRupee, 'Bat Cave (right)', PotFlags.LowerRegion)],
0xE4: [Pot(32, 9, PotItem.FiveRupees, 'Old Man House'), Pot(112, 10, PotItem.OneRupee, 'Old Man House')],
0xE5: [Pot(48, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(76, 4, PotItem.OneRupee, 'Old Man House Back'), Pot(112, 16, PotItem.OneRupee, 'Old Man House Back'), Pot(64, 18, PotItem.FiveRupees, 'Old Man House Back')],
0xE6: [Pot(108, 12, PotItem.FiveArrows, 'Death Mountain Return Cave (left)'), Pot(88, 16, PotItem.Heart, 'Death Mountain Return Cave (left)'), Pot(72, 20, PotItem.Nothing, 'Death Mountain Return Cave (left)'),
Pot(56, 24, PotItem.OneRupee, 'Death Mountain Return Cave (left)')],
0xE7: [Pot(68, 5, PotItem.OneRupee, 'Death Mountain Return Cave (right)'), Pot(72, 5, PotItem.OneRupee, 'Death Mountain Return Cave (right)')],
232: [Pot(96, 4, PotItem.Heart, 'Superbunny Cave (Bottom)')],
235: [Pot(206, 8, PotItem.FiveRupees, 'Bumper Cave'), Pot(210, 8, PotItem.FiveRupees, 'Bumper Cave'), Pot(88, 14, PotItem.SmallMagic, 'Bumper Cave'), Pot(92, 14, PotItem.Heart, 'Bumper Cave'), Pot(96, 14, PotItem.SmallMagic, 'Bumper Cave')],
241: [Pot(64, 5, PotItem.Heart, 'Old Man Cave')],
248: [Pot(242, 13, PotItem.BigMagic, 'Superbunny Cave')],
0xF3: [Pot(0x28, 0x14, PotItem.Nothing, 'Elder House'),
Pot(0x2C, 0x14, PotItem.Nothing, 'Elder House'),
Pot(0x30, 0x14, PotItem.Nothing, 'Elder House')],
248: [Pot(242, 13, PotItem.BigMagic, 'Superbunny Cave (Top)')],
253: [Pot(88, 6, PotItem.FiveRupees, 'Fairy Ascension Cave (Top)'), Pot(100, 6, PotItem.FiveRupees, 'Fairy Ascension Cave (Top)'), Pot(84, 23, PotItem.FiveRupees, 'Fairy Ascension Cave (Bottom)'),
Pot(84, 24, PotItem.FiveRupees, 'Fairy Ascension Cave (Bottom)')],
255: [Pot(92, 8, PotItem.Heart, 'Paradox Cave'), Pot(96, 8, PotItem.Heart, 'Paradox Cave'), Pot(112, 28, PotItem.OneRupee, 'Paradox Cave Front')],
255: [Pot(92, 8, PotItem.Heart, 'Paradox Cave Bomb Area'), Pot(96, 8, PotItem.Heart, 'Paradox Cave Bomb Area'), Pot(112, 28, PotItem.OneRupee, 'Paradox Cave Front')],
257: [Pot(12, 20, PotItem.Heart, 'Snitch Lady (East)'), Pot(224, 19, PotItem.Chicken, 'Snitch Lady (West)'), Pot(228, 19, PotItem.Heart, 'Snitch Lady (West)')],
258: [Pot(146, 19, PotItem.Heart, 'Sick Kids House'), Pot(150, 19, PotItem.Heart, 'Sick Kids House')],
259: [Pot(140, 7, PotItem.Chicken, 'Tavern'), Pot(140, 9, PotItem.Nothing, 'Tavern'), Pot(12, 12, PotItem.Heart, 'Tavern (Front)')],
260: [Pot(202, 21, PotItem.Heart, 'Links House'), Pot(202, 22, PotItem.Heart, 'Links House'), Pot(202, 23, PotItem.Heart, 'Links House')],
261: [Pot(30, 20, PotItem.Heart, 'Sahasrahlas Hut'), Pot(28, 21, PotItem.Heart, 'Sahasrahlas Hut'), Pot(32, 21, PotItem.Heart, 'Sahasrahlas Hut')],
0x106: [Pot(0x6c, 0x1b, PotItem.Nothing, 'Brewery')],
263: [Pot(214, 23, PotItem.Bomb, 'Light World Bomb Hut'), Pot(222, 23, PotItem.FiveArrows, 'Light World Bomb Hut'), Pot(230, 23, PotItem.Bomb, 'Light World Bomb Hut'), Pot(214, 25, PotItem.OneRupee, 'Light World Bomb Hut'),
Pot(222, 25, PotItem.Nothing, 'Light World Bomb Hut'), Pot(230, 25, PotItem.OneRupee, 'Light World Bomb Hut'), Pot(214, 27, PotItem.Bomb, 'Light World Bomb Hut'), Pot(230, 27, PotItem.Bomb, 'Light World Bomb Hut')],
264: [Pot(166, 19, PotItem.Chicken, 'Chicken House')],
268: [Pot(88, 14, PotItem.Heart, 'Hookshot Fairy')],
276: [Pot(92, 4, PotItem.Heart, 'Dark Desert Hint'), Pot(96, 4, PotItem.Heart, 'Dark Desert Hint'), Pot(92, 5, PotItem.Bomb, 'Dark Desert Hint'), Pot(96, 5, PotItem.Bomb, 'Dark Desert Hint'), Pot(92, 10, PotItem.FiveArrows, 'Dark Desert Hint'),
Pot(96, 10, PotItem.Heart, 'Dark Desert Hint')],
279: [Pot(138, 3, PotItem.Heart, 'Spike Cave'), Pot(142, 3, PotItem.Heart, 'Spike Cave'), Pot(166, 3, PotItem.Heart, 'Spike Cave'), Pot(170, 3, PotItem.Heart, 'Spike Cave'), Pot(138, 4, PotItem.Heart, 'Spike Cave'),
Pot(142, 4, PotItem.Heart, 'Spike Cave'), Pot(166, 4, PotItem.Heart, 'Spike Cave'), Pot(170, 4, PotItem.Heart, 'Spike Cave')],
0x117: [Pot(138, 3, PotItem.Heart, 'Spike Cave'), Pot(142, 3, PotItem.Heart, 'Spike Cave'),
Pot(166, 3, PotItem.Heart, 'Spike Cave'), Pot(170, 3, PotItem.Heart, 'Spike Cave'),
Pot(138, 4, PotItem.Heart, 'Spike Cave'), Pot(142, 4, PotItem.Heart, 'Spike Cave'),
Pot(166, 4, PotItem.Heart, 'Spike Cave'), Pot(170, 4, PotItem.Heart, 'Spike Cave'),
Pot(0x18, 0x8, PotItem.Nothing, 'Spike Cave', PotFlags.Block)],
281: [Pot(44, 28, PotItem.Heart, 'Blinds Hideout'), Pot(48, 28, PotItem.OneRupee, 'Blinds Hideout'), Pot(76, 28, PotItem.Heart, 'Blinds Hideout'), Pot(80, 28, PotItem.Heart, 'Blinds Hideout')],
282: [Pot(214, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(218, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(226, 10, PotItem.Heart, 'Palace of Darkness Hint'), Pot(230, 10, PotItem.Heart, 'Palace of Darkness Hint')],
283: [Pot(24, 53, PotItem.Nothing, 'Cave 45'), Pot(24, 54, PotItem.Heart, 'Cave 45'), Pot(32, 54, PotItem.Heart, 'Cave 45'), Pot(40, 54, PotItem.Heart, 'Cave 45'), Pot(24, 55, PotItem.Heart, 'Cave 45'), Pot(28, 56, PotItem.Heart, 'Cave 45'),
Pot(92, 22, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 22, PotItem.Heart, 'Graveyard Cave'), Pot(92, 23, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 23, PotItem.Heart, 'Graveyard Cave'), Pot(92, 24, PotItem.Bomb, 'Graveyard Cave'),
Pot(96, 24, PotItem.Heart, 'Graveyard Cave'), Pot(92, 25, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 25, PotItem.Heart, 'Graveyard Cave')],
285: [Pot(60, 6, PotItem.FiveRupees, 'Blinds Hideout'), Pot(64, 6, PotItem.FiveRupees, 'Blinds Hideout'), Pot(60, 7, PotItem.FiveRupees, 'Blinds Hideout'), Pot(64, 7, PotItem.FiveRupees, 'Blinds Hideout'),
Pot(60, 8, PotItem.FiveRupees, 'Blinds Hideout'), Pot(64, 8, PotItem.FiveRupees, 'Blinds Hideout')],
287: [Pot(174, 28, PotItem.Heart, 'Lumberjack House'), Pot(178, 28, PotItem.Heart, 'Lumberjack House')],
0x11B: [Pot(24, 0x15, PotItem.Nothing, 'Cave 45', PotFlags.LowerRegion),
Pot(24, 0x16, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
Pot(32, 0x16, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
Pot(40, 0x16, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
Pot(24, 0x17, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
Pot(28, 0x18, PotItem.Heart, 'Cave 45', PotFlags.LowerRegion),
Pot(92, 22, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 22, PotItem.Heart, 'Graveyard Cave'),
Pot(92, 23, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 23, PotItem.Heart, 'Graveyard Cave'),
Pot(92, 24, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 24, PotItem.Heart, 'Graveyard Cave'),
Pot(92, 25, PotItem.Bomb, 'Graveyard Cave'), Pot(96, 25, PotItem.Heart, 'Graveyard Cave')],
0x11D: [Pot(60, 6, PotItem.FiveRupees, 'Blinds Hideout (Top)'), Pot(64, 6, PotItem.FiveRupees, 'Blinds Hideout (Top)'),
Pot(60, 7, PotItem.FiveRupees, 'Blinds Hideout (Top)'), Pot(64, 7, PotItem.FiveRupees, 'Blinds Hideout (Top)'),
Pot(60, 8, PotItem.FiveRupees, 'Blinds Hideout (Top)'), Pot(64, 8, PotItem.FiveRupees, 'Blinds Hideout (Top)')],
0x11F: [Pot(174, 28, PotItem.Heart, 'Lumberjack House'), Pot(178, 28, PotItem.Heart, 'Lumberjack House')],
292: [Pot(20, 20, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 20, PotItem.FiveRupees, '50 Rupee Cave'), Pot(20, 21, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 21, PotItem.FiveRupees, '50 Rupee Cave'),
Pot(20, 22, PotItem.FiveRupees, '50 Rupee Cave'), Pot(40, 22, PotItem.FiveRupees, '50 Rupee Cave'), Pot(24, 24, PotItem.FiveRupees, '50 Rupee Cave'), Pot(28, 24, PotItem.FiveRupees, '50 Rupee Cave'),
Pot(32, 24, PotItem.FiveRupees, '50 Rupee Cave'), Pot(36, 24, PotItem.FiveRupees, '50 Rupee Cave')],
293: [Pot(24, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(28, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(32, 25, PotItem.FiveRupees, '20 Rupee Cave'), Pot(36, 25, PotItem.FiveRupees, '20 Rupee Cave'),
Pot(88, 22, PotItem.Heart, 'Dev Cave Hint'), Pot(100, 22, PotItem.Heart, 'Dev Cave Hint'), Pot(88, 28, PotItem.Heart, 'Dev Cave Hint'), Pot(100, 28, PotItem.Heart, 'Dev Cave Hint')],
295: [Pot(24, 25, PotItem.Nothing, 'Hammer Pegs Cave'), Pot(28, 25, PotItem.Nothing, 'Hammer Pegs Cave'), Pot(32, 25, PotItem.Nothing, 'Hammer Pegs Cave'), Pot(36, 25, PotItem.Nothing, 'Hammer Pegs Cave')],
Pot(88, 22, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave'), Pot(100, 22, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave'), Pot(88, 28, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave'), Pot(100, 28, PotItem.Heart, 'Dark Lake Hylia Ledge Spike Cave')],
295: [Pot(24, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave'), Pot(28, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave'), Pot(32, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave'), Pot(36, 25, PotItem.Nothing, 'Dark World Hammer Peg Cave')],
}
def shuffle_pots(world, player):
import RaceRandom as random
new_pot_contents = {}
new_pot_contents = PotSecretTable()
for supertile in vanilla_pots:
old_pots = vanilla_pots[supertile]
@@ -295,7 +366,7 @@ def shuffle_pots(world, player):
elif old_pot.item == PotItem.Switch:
available_pots = (pot for pot in new_pots if (pot.room == old_pot.room or pot.room in movable_switch_rooms[old_pot.room]) and not (pot.flags & PotFlags.NoSwitch))
elif old_pot.item == PotItem.Key:
if world.doorShuffle[player] == 'vanilla' and not world.retro[player] and not world.keydropshuffle[player] and world.logic[player] != 'nologic':
if world.doorShuffle[player] == 'vanilla' and not world.retro[player] and world.keydropshuffle[player] == 'none' and world.logic[player] != 'nologic':
available_pots = (pot for pot in new_pots if pot.room not in invalid_key_rooms)
else:
available_pots = new_pots
@@ -328,8 +399,80 @@ def shuffle_pots(world, player):
# Rule is created based on barrier
world.get_door('Thieves Attic ES', player).barrier(CrystalBarrier.Orange)
else:
raise Exception("Switch locattion in room %s requires logic change" % new_pot.room)
raise Exception("Switch location in room %s requires logic change" % new_pot.room)
new_pot_contents[supertile] = new_pots
new_pot_contents.room_map[supertile] = new_pots
world.pot_contents[player] = new_pot_contents
key_drop_data = {
'Hyrule Castle - Map Guard Key Drop': ['Drop', (0x09E20C, 0x72), 'in Hyrule Castle', 'Small Key (Escape)'],
'Hyrule Castle - Boomerang Guard Key Drop': ['Drop', (0x09E204, 0x71), 'in Hyrule Castle', 'Small Key (Escape)'],
'Hyrule Castle - Key Rat Key Drop': ['Drop', (0x09DB80, 0x21), 'in Hyrule Castle', 'Small Key (Escape)'],
'Hyrule Castle - Big Key Drop': ['Drop', (0x09E327, 0x80), 'in Hyrule Castle', 'Big Key (Escape)'],
'Eastern Palace - Dark Square Pot Key': ['Pot', 0xBA, 'in Eastern Palace', 'Small Key (Eastern Palace)'],
'Eastern Palace - Dark Eyegore Key Drop': ['Drop', (0x09E4F8, 0x99), 'in Eastern Palace', 'Small Key (Eastern Palace)'],
'Desert Palace - Desert Tiles 1 Pot Key': ['Pot', 0x63, 'in Desert Palace', 'Small Key (Desert Palace)'],
'Desert Palace - Beamos Hall Pot Key': ['Pot', 0x53, 'in Desert Palace', 'Small Key (Desert Palace)'],
'Desert Palace - Desert Tiles 2 Pot Key': ['Pot', 0x43, 'in Desert Palace', 'Small Key (Desert Palace)'],
'Castle Tower - Dark Archer Key Drop': ['Drop', (0x09E7C9, 0xC0), 'in Castle Tower', 'Small Key (Agahnims Tower)'],
'Castle Tower - Circle of Pots Key Drop': ['Drop', (0x09E688, 0xB0), 'in Castle Tower', 'Small Key (Agahnims Tower)'],
'Swamp Palace - Pot Row Pot Key': ['Pot', 0x38, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Trench 1 Pot Key': ['Pot', 0x37, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Hookshot Pot Key': ['Pot', 0x36, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Trench 2 Pot Key': ['Pot', 0x35, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Waterway Pot Key': ['Pot', 0x16, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Skull Woods - West Lobby Pot Key': ['Pot', 0x56, 'in Skull Woods', 'Small Key (Skull Woods)'],
'Skull Woods - Spike Corner Key Drop': ['Drop', (0x09DD74, 0x39), 'near Mothula', 'Small Key (Skull Woods)'],
"Thieves' Town - Hallway Pot Key": ['Pot', 0xBC, "in Thieves' Town", 'Small Key (Thieves Town)'],
"Thieves' Town - Spike Switch Pot Key": ['Pot', 0xAB, "in Thieves' Town", 'Small Key (Thieves Town)'],
'Ice Palace - Jelly Key Drop': ['Drop', (0x09DA21, 0xE), 'in Ice Palace', 'Small Key (Ice Palace)'],
'Ice Palace - Conveyor Key Drop': ['Drop', (0x09DE08, 0x3E), 'in Ice Palace', 'Small Key (Ice Palace)'],
'Ice Palace - Hammer Block Key Drop': ['Pot', 0x3F, 'in Ice Palace', 'Small Key (Ice Palace)'],
'Ice Palace - Many Pots Pot Key': ['Pot', 0x9F, 'in Ice Palace', 'Small Key (Ice Palace)'],
'Misery Mire - Spikes Pot Key': ['Pot', 0xB3, 'in Misery Mire', 'Small Key (Misery Mire)'],
'Misery Mire - Fishbone Pot Key': ['Pot', 0xA1, 'in forgotten Mire', 'Small Key (Misery Mire)'],
'Misery Mire - Conveyor Crystal Key Drop': ['Drop', (0x09E7FB, 0xC1), 'in Misery Mire', 'Small Key (Misery Mire)'],
'Turtle Rock - Pokey 1 Key Drop': ['Drop', (0x09E70D, 0xB6), 'in Turtle Rock', 'Small Key (Turtle Rock)'],
'Turtle Rock - Pokey 2 Key Drop': ['Drop', (0x09DA5D, 0x13), 'in Turtle Rock', 'Small Key (Turtle Rock)'],
'Ganons Tower - Conveyor Cross Pot Key': ['Pot', 0x8B, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
'Ganons Tower - Double Switch Pot Key': ['Pot', 0x9B, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
'Ganons Tower - Conveyor Star Pits Pot Key': ['Pot', 0x7B, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
'Ganons Tower - Mini Helmasaur Key Drop': ['Drop', (0x09DDC4, 0x3D), "atop Ganon's Tower", 'Small Key (Ganons Tower)']
}
class PotSecretTable(object):
def __init__(self):
self.room_map = defaultdict(list)
def write_pot_data_to_rom(self, rom):
pointer_address = 0x140000 # pots currently in bank 28
pointer_offset = 0x128 * 2
empty_address = (pointer_address + pointer_offset - 2)
empty_pointer = pc_to_snes(empty_address) & 0xFFFF
data_pointer = pointer_address + pointer_offset
for room in range(0, 0x128):
if room in self.room_map and any(p for p in self.room_map[room] if not p.empty()):
list_idx = 0
data_address = pc_to_snes(data_pointer) & 0xFFFF
rom.write_bytes(pointer_address + room * 2, int16_as_bytes(data_address))
for pot in self.room_map[room]:
if not pot.empty():
rom.write_bytes(data_pointer + list_idx * 3, pot.pot_data())
list_idx += 1
rom.write_bytes(data_pointer + list_idx * 3, [0xFF, 0xFF])
data_pointer += 3 * list_idx + 2
else:
rom.write_bytes(pointer_address + room * 2, int16_as_bytes(empty_pointer))
rom.write_bytes(empty_address, [0xFF, 0xFF])
def size(self):
size = 0x128 * 2
for room in range(0, 0x128):
if room in self.room_map:
pot_list = [p for p in self.room_map[room] if not p.empty()]
if pot_list:
size += len(pot_list) * 3 + 2
return size

View File

@@ -1,6 +1,7 @@
import collections
from Items import ItemFactory
from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType
from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType, LocationType, PotItem, PotFlags
from PotShuffle import key_drop_data, vanilla_pots, PotSecretTable
def create_regions(world, player):
@@ -18,11 +19,13 @@ def create_regions(world, player):
'Bonk Fairy (Light)', '50 Rupee Cave', 'Fortune Teller (Light)', 'Lake Hylia Fairy', 'Light Hype Fairy', 'Desert Fairy', 'Lumberjack House', 'Lake Hylia Fortune Teller', 'Kakariko Gamble Game', 'Top of Pyramid']),
create_lw_region(player, 'Death Mountain Entrance', None, ['Old Man Cave (West)', 'Death Mountain Entrance Drop']),
create_lw_region(player, 'Lake Hylia Central Island', None, ['Capacity Upgrade', 'Lake Hylia Central Island Teleporter']),
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', ["Blind\'s Hideout - Top",
"Blind\'s Hideout - Left",
"Blind\'s Hideout - Right",
"Blind\'s Hideout - Far Left",
"Blind\'s Hideout - Far Right"]),
create_cave_region(player, 'Blinds Hideout', 'a bounty of five items', [
"Blind's Hideout - Left",
"Blind's Hideout - Right",
"Blind's Hideout - Far Left",
"Blind's Hideout - Far Right"],
['Blinds Hideout N']),
create_cave_region(player, 'Blinds Hideout (Top)', 'a bounty of five items', ["Blind's Hideout - Top"]),
create_cave_region(player, 'Hyrule Castle Secret Entrance', 'a drop\'s exit', ['Link\'s Uncle', 'Secret Passage'], ['Hyrule Castle Secret Entrance Exit']),
create_lw_region(player, 'Zoras River', ['King Zora', 'Zora\'s Ledge']),
create_cave_region(player, 'Waterfall of Wishing', 'a cave with two chests', ['Waterfall Fairy - Left', 'Waterfall Fairy - Right']),
@@ -55,8 +58,11 @@ def create_regions(world, player):
create_cave_region(player, 'Chicken House', 'a house with a chest', ['Chicken House']),
create_cave_region(player, 'Aginahs Cave', 'a cave with a chest', ['Aginah\'s Cave']),
create_cave_region(player, 'Sahasrahlas Hut', 'Sahasrahla', ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right', 'Sahasrahla']),
create_cave_region(player, 'Kakariko Well (top)', 'a drop\'s exit', ['Kakariko Well - Top', 'Kakariko Well - Left', 'Kakariko Well - Middle',
'Kakariko Well - Right', 'Kakariko Well - Bottom'], ['Kakariko Well (top to bottom)']),
create_cave_region(player, 'Kakariko Well (top)', 'a drop\'s exit',
['Kakariko Well - Left', 'Kakariko Well - Middle', 'Kakariko Well - Right',
'Kakariko Well - Bottom'],
['Kakariko Well (top to bottom)', 'Kakariko Well (top to back)']),
create_cave_region(player, 'Kakariko Well (back)', 'a drop\'s exit', ['Kakariko Well - Top']),
create_cave_region(player, 'Kakariko Well (bottom)', 'a drop\'s exit', None, ['Kakariko Well Exit']),
create_cave_region(player, 'Blacksmiths Hut', 'the smith', ['Blacksmith', 'Missing Smith']),
create_lw_region(player, 'Bat Cave Drop Ledge', None, ['Bat Cave Drop']),
@@ -106,7 +112,8 @@ def create_regions(world, player):
create_cave_region(player, 'Old Man House', 'a connector', None, ['Old Man House Exit (Bottom)', 'Old Man House Front to Back']),
create_cave_region(player, 'Old Man House Back', 'a connector', None, ['Old Man House Exit (Top)', 'Old Man House Back to Front']),
create_lw_region(player, 'Death Mountain', None, ['Old Man Cave (East)', 'Old Man House (Bottom)', 'Old Man House (Top)', 'Death Mountain Return Cave (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Teleporter']),
create_cave_region(player, 'Death Mountain Return Cave', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave Exit (East)']),
create_cave_region(player, 'Death Mountain Return Cave (left)', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave E']),
create_cave_region(player, 'Death Mountain Return Cave (right)', 'a connector', None, ['Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave W']),
create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)']),
create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']),
create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']),
@@ -119,9 +126,10 @@ def create_regions(world, player):
'Paradox Cave Lower - Right',
'Paradox Cave Lower - Far Right',
'Paradox Cave Lower - Middle',
'Paradox Cave Upper - Left',
'Paradox Cave Upper - Right'],
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump']),
],
['Paradox Cave Push Block', 'Paradox Cave Bomb Jump', 'Paradox Cave Chest Area NE']),
create_cave_region(player, 'Paradox Cave Bomb Area', 'a connector', ['Paradox Cave Upper - Left',
'Paradox Cave Upper - Right']),
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', ['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']),
@@ -973,7 +981,8 @@ def create_shops(world, player):
def adjust_locations(world, player):
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
world.pot_contents[player] = PotSecretTable()
for location in key_drop_data.keys():
loc = world.get_location(location, player)
key_item = loc.item
@@ -982,21 +991,46 @@ def adjust_locations(world, player):
loc.forced_item = None
loc.item = None
loc.event = False
loc.address = key_drop_data[location][1]
loc.player_address = key_drop_data[location][0]
item_dungeon = key_item.name.split('(')[1][:-1]
item_dungeon = 'Hyrule Castle' if item_dungeon == 'Escape' else item_dungeon
datum = key_drop_data[location]
# todo: set type of location
if 'Drop' == datum[0]:
loc.type = LocationType.Drop
snes_address, room = datum[1]
loc.address = snes_address
else:
loc.type = LocationType.Pot
pot = next(p for p in vanilla_pots[datum[1]] if p.item == PotItem.Key).copy()
loc.pot = pot
world.pot_contents[player].room_map[datum[1]].append(pot)
item_dungeon = key_item.dungeon
dungeon = world.get_dungeon(item_dungeon, player)
if key_item.smallkey and not world.retro[player]:
dungeon.small_keys.append(key_item)
elif key_item.bigkey:
dungeon.big_key = key_item
if world.keydropshuffle[player] == 'potsanity':
for super_tile, pot_list in vanilla_pots.items():
for pot_index, pot_orig in enumerate(pot_list):
pot = pot_orig.copy()
if pot.item in [PotItem.Hole, PotItem.Switch]:
world.pot_contents[player].room_map[super_tile].append(pot)
elif pot.item != PotItem.Key:
parent = world.get_region(pot.room, player)
descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}'
pot_location = Location(player, f'{pot.room} {descriptor}', player, hint_text='in a pot',
parent=parent)
world.dynamic_locations.append(pot_location)
pot_location.pot = pot
world.pot_contents[player].room_map[super_tile].append(pot)
pot_location.type = LocationType.Pot
parent.locations.append(pot_location)
if world.shopsanity[player]:
index = 0
for shop, location_list in shop_to_location_table.items():
for location in location_list:
world.get_location(location, player).address = 0x400000 + index
loc = world.get_location(location, player)
loc.address = 0x400000 + index
loc.type = LocationType.Shop
# player address? it is in the shop table
index += 1
# unreal events:
@@ -1005,6 +1039,7 @@ def adjust_locations(world, player):
'Revealing Light', 'Ice Block Drop', 'Zelda Pickup', 'Zelda Drop Off']:
location = world.get_location_unsafe(l, player)
if location:
location.type = LocationType.Logical
location.real = False
@@ -1059,42 +1094,6 @@ shop_table_by_location_id = {0x400000+cnt: x for cnt, x in enumerate(flat_normal
shop_table_by_location_id = {**shop_table_by_location_id, **{0x400020+cnt: x for cnt, x in enumerate(flat_retro_shops)}}
shop_table_by_location = {y: x for x, y in shop_table_by_location_id.items()}
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)'],
'Hyrule Castle - Key Rat Key Drop': [0x14000c, 0x14000d, 'in Hyrule Castle', 'Small Key (Escape)'],
'Hyrule Castle - Big Key Drop': [0x14003c, 0x14003d, 'in Hyrule Castle', 'Big Key (Escape)'],
'Eastern Palace - Dark Square Pot Key': [0x14005a, 0x14005b, 'in Eastern Palace', 'Small Key (Eastern Palace)'],
'Eastern Palace - Dark Eyegore Key Drop': [0x140048, 0x140049, 'in Eastern Palace', 'Small Key (Eastern Palace)'],
'Desert Palace - Desert Tiles 1 Pot Key': [0x140030, 0x140031, 'in Desert Palace', 'Small Key (Desert Palace)'],
'Desert Palace - Beamos Hall Pot Key': [0x14002a, 0x14002b, 'in Desert Palace', 'Small Key (Desert Palace)'],
'Desert Palace - Desert Tiles 2 Pot Key': [0x140027, 0x140028, 'in Desert Palace', 'Small Key (Desert Palace)'],
'Castle Tower - Dark Archer Key Drop': [0x140060, 0x140061, 'in Castle Tower', 'Small Key (Agahnims Tower)'],
'Castle Tower - Circle of Pots Key Drop': [0x140051, 0x140052, 'in Castle Tower', 'Small Key (Agahnims Tower)'],
'Swamp Palace - Pot Row Pot Key': [0x140018, 0x140019, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Trench 1 Pot Key': [0x140015, 0x140016, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Hookshot Pot Key': [0x140012, 0x140013, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Trench 2 Pot Key': [0x14000f, 0x140010, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Swamp Palace - Waterway Pot Key': [0x140009, 0x14000a, 'in Swamp Palace', 'Small Key (Swamp Palace)'],
'Skull Woods - West Lobby Pot Key': [0x14002d, 0x14002e, 'in Skull Woods', 'Small Key (Skull Woods)'],
'Skull Woods - Spike Corner Key Drop': [0x14001b, 0x14001c, 'near Mothula', 'Small Key (Skull Woods)'],
"Thieves' Town - Hallway Pot Key": [0x14005d, 0x14005e, "in Thieves' Town", 'Small Key (Thieves Town)'],
"Thieves' Town - Spike Switch Pot Key": [0x14004e, 0x14004f, "in Thieves' Town", 'Small Key (Thieves Town)'],
'Ice Palace - Jelly Key Drop': [0x140003, 0x140004, 'in Ice Palace', 'Small Key (Ice Palace)'],
'Ice Palace - Conveyor Key Drop': [0x140021, 0x140022, 'in Ice Palace', 'Small Key (Ice Palace)'],
'Ice Palace - Hammer Block Key Drop': [0x140024, 0x140025, 'in Ice Palace', 'Small Key (Ice Palace)'],
'Ice Palace - Many Pots Pot Key': [0x140045, 0x140046, 'in Ice Palace', 'Small Key (Ice Palace)'],
'Misery Mire - Spikes Pot Key': [0x140054, 0x140055 , 'in Misery Mire', 'Small Key (Misery Mire)'],
'Misery Mire - Fishbone Pot Key': [0x14004b, 0x14004c, 'in forgotten Mire', 'Small Key (Misery Mire)'],
'Misery Mire - Conveyor Crystal Key Drop': [0x140063, 0x140064 , 'in Misery Mire', 'Small Key (Misery Mire)'],
'Turtle Rock - Pokey 1 Key Drop': [0x140057, 0x140058, 'in Turtle Rock', 'Small Key (Turtle Rock)'],
'Turtle Rock - Pokey 2 Key Drop': [0x140006, 0x140007, 'in Turtle Rock', 'Small Key (Turtle Rock)'],
'Ganons Tower - Conveyor Cross Pot Key': [0x14003f, 0x140040, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
'Ganons Tower - Double Switch Pot Key': [0x140042, 0x140043, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
'Ganons Tower - Conveyor Star Pits Pot Key': [0x140039, 0x14003a, "in Ganon's Tower", 'Small Key (Ganons Tower)'],
'Ganons Tower - Mini Helmasaur Key Drop': [0x14001e, 0x14001f, "atop Ganon's Tower", 'Small Key (Ganons Tower)']
}
dungeon_events = [
'Trench 1 Switch',
'Trench 2 Switch',

140
Rom.py
View File

@@ -1,6 +1,6 @@
import bisect
import collections
import io
import itertools
import json
import hashlib
import logging
@@ -15,7 +15,7 @@ try:
except ImportError:
raise Exception('Could not load BPS module')
from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem
from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem, LocationType
from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals
from Dungeons import dungeon_music_addresses, dungeon_table
from Regions import location_table, shop_to_location_table, retro_shops
@@ -23,16 +23,19 @@ from RoomData import DoorKind
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
from Text import Uncle_texts, Ganon1_texts, Ganon_Phase_3_No_Silvers_texts, TavernMan_texts, Sahasrahla2_texts
from Text import Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts
from Text import LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts
from Text import Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
from Items import ItemFactory
from ItemList import valid_pot_items
from EntranceShuffle import door_addresses, exit_ids, ow_prize_table
from source.classes.SFX import randomize_sfx
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '2cfa164d4b66a15406f53ca4750ef59a'
RANDOMIZERBASEHASH = '3ee527f67af25e860ffd4364d2369f0e'
class JsonRom(object):
@@ -547,6 +550,21 @@ class Sprite(object):
return array_chunk(palette_as_colors, 15)
def handle_native_dungeon(location, itemid):
# Keys in their native dungeon should use the original item code for keys
if location.parent_region.dungeon:
if location.parent_region.dungeon.is_dungeon_item(location.item):
if location.item.bigkey:
return 0x32
if location.item.smallkey:
return 0x24
if location.item.map:
return 0x33
if location.item.compass:
return 0x25
return itemid
def patch_rom(world, rom, player, team, enemized, is_mystery=False):
random.seed(world.rom_seeds[player])
@@ -558,28 +576,47 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
distinguished_prog_bow_loc.item.code = 0x65
# patch items
pot_mw_index = 0
for location in world.get_locations():
if location.player != player:
continue
itemid = location.item.code if location.item is not None else 0x5A
if location.type == LocationType.Pot:
if location.item.name in valid_pot_items and location.item.player == player:
location.pot.item = valid_pot_items[location.item.name]
else:
code = handle_native_dungeon(location, itemid)
standing_item_flag = 0x80
if location.item.player != player:
standing_item_flag |= 0x40
rom.write_byte(0x142800 + pot_mw_index * 2, code)
rom.write_byte(0x142800 + pot_mw_index * 2 + 1, location.item.player)
code = pot_mw_index
pot_mw_index += 1
location.pot.indicator = standing_item_flag
location.pot.standing_item_code = code
continue
elif location.type == LocationType.Drop:
if location.item.player != player:
code = 0xF9
else:
code = 0xF8
sprite_pointer = snes_to_pc(location.address)
if code != 0xE4:
rom.write_byte(sprite_pointer, handle_native_dungeon(location, itemid))
if code == 0xF9:
rom.write_byte(sprite_pointer+1, location.item.player)
else:
rom.write_byte(sprite_pointer+1, 0)
rom.write_byte(sprite_pointer+2, code)
continue
if location.address is None or (type(location.address) is int and location.address >= 0x400000):
continue
if not location.crystal:
if location.item is not None:
# Keys in their native dungeon should use the original item code for keys
if location.parent_region.dungeon:
if location.parent_region.dungeon.is_dungeon_item(location.item):
if location.item.bigkey:
itemid = 0x32
if location.item.smallkey:
itemid = 0x24
if location.item.map:
itemid = 0x33
if location.item.compass:
itemid = 0x25
itemid = handle_native_dungeon(location, itemid)
if world.remote_items[player]:
itemid = list(location_table.keys()).index(location.name) + 1
assert itemid < 0x100
@@ -608,7 +645,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_byte(0x155C9, random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle
if world.pot_contents[player]:
write_pots_to_rom(rom, world.pot_contents[player])
if world.pot_contents[player].size() > 0x2800:
raise Exception('Pot table is too big for current area')
world.pot_contents[player].write_pot_data_to_rom(rom)
# patch entrance/exits/holes
for region in world.regions:
@@ -691,14 +730,19 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
if world.logic[player] != 'nologic':
dr_flags |= DROptions.Fix_EG
my_locations = world.get_filled_locations(player)
valid_locations = [l for l in my_locations if ((l.type == LocationType.Pot and l.pot.indicator)
or (l.type == LocationType.Drop and not l.forced_item)
or (l.type == LocationType.Normal and not l.forced_item)
or (l.type == LocationType.Shop and world.shopsanity[player]))]
# fix hc big key problems (map and compass too)
if world.doorShuffle[player] == 'crossed' or world.keydropshuffle[player]:
if world.doorShuffle[player] == 'crossed' or world.keydropshuffle[player] != 'none':
rom.write_byte(0x151f1, 2)
rom.write_byte(0x15270, 2)
sanctuary = world.get_region('Sanctuary', player)
rom.write_byte(0x1597b, sanctuary.dungeon.dungeon_id*2)
update_compasses(rom, world, player)
update_compasses(rom, valid_locations, world, player)
def should_be_bunny(region, mode):
if mode != 'inverted':
@@ -816,19 +860,12 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
# bot: $7A is 1, 7B is 2, etc so 7D=4, 82=9 (zero unknown...)
return 0x53+int(num), 0x79+int(num)
credits_total = 216
if world.keydropshuffle[player]:
credits_total += 33
if world.shopsanity[player]:
credits_total += 32
if world.retro[player]:
credits_total += 9 if world.shopsanity[player] else 5
credits_total = len(valid_locations)
if world.keydropshuffle[player]:
rom.write_byte(0x140000, 1)
multiClientFlags = ((0x1 if world.keydropshuffle[player] else 0) | (0x2 if world.shopsanity[player] else 0)
| (0x4 if world.retro[player] else 0))
rom.write_byte(0x140001, multiClientFlags)
if world.keydropshuffle[player] != 'none':
rom.write_byte(0x142A50, 1)
rom.write_byte(0x142A51, 1)
rom.write_byte(0x142A52, 216-credits_total) # todo: this is now a delta
write_int16(rom, 0x187010, credits_total) # dynamic credits
if credits_total != 216:
@@ -1153,7 +1190,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
gametype = 0x04 # item
if world.shuffle[player] != 'vanilla' or world.doorShuffle[player] != 'vanilla' or world.keydropshuffle[player]:
if world.shuffle[player] != 'vanilla' or world.doorShuffle[player] != 'vanilla' or world.keydropshuffle[player] != 'none':
gametype |= 0x02 # entrance/door
if enemized:
gametype |= 0x01 # enemizer
@@ -1403,7 +1440,8 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_byte(0x18003C, 0x00)
elif world.dungeon_counters[player] == 'on':
compass_mode = 0x02 # always on
elif world.compassshuffle[player] or world.doorShuffle[player] != 'vanilla' or world.dungeon_counters[player] == 'pickup':
elif (world.compassshuffle[player] or world.doorShuffle[player] != 'vanilla'
or world.dungeon_counters[player] == 'pickup' or world.keydropshuffle != 'none'):
compass_mode = 0x01 # show on pickup
if world.shuffle[player] != 'vanilla' and world.overworld_map[player] != 'default':
compass_mode |= 0x80 # turn on locating dungeons
@@ -1577,7 +1615,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_byte(0xFED31, 0x0E) # preopen bombable exit
rom.write_byte(0xFEE41, 0x0E) # preopen bombable exit
if world.doorShuffle[player] != 'vanilla' or world.keydropshuffle[player]:
if world.doorShuffle[player] != 'vanilla' or world.keydropshuffle[player] != 'none':
for room in world.rooms:
if room.player == player and room.modified:
rom.write_bytes(room.address(), room.rom_data())
@@ -2577,12 +2615,16 @@ def patch_shuffled_dark_sanc(world, rom, player):
rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00])
def update_compasses(rom, world, player):
def update_compasses(rom, valid_locations, world, player):
dungeon_locations = collections.defaultdict(set)
for l in valid_locations:
if l.parent_region.dungeon:
dungeon_locations[l.parent_region.dungeon.name].add(l)
layouts = world.dungeon_layouts[player]
provided_dungeon = False
for name, builder in layouts.items():
dungeon_id = compass_data[name][4]
rom.write_byte(0x187000 + dungeon_id//2, builder.location_cnt)
rom.write_byte(0x187000 + dungeon_id//2, len(dungeon_locations[name]))
if builder.bk_provided:
if provided_dungeon:
logging.getLogger('').warning('Multiple dungeons have forced BKs! Compass code might need updating?')
@@ -2851,29 +2893,3 @@ hash_alphabet = [
"Lamp", "Hammer", "Shovel", "Ocarina", "Bug Net", "Book", "Bottle", "Potion", "Cane", "Cape", "Mirror", "Boots",
"Gloves", "Flippers", "Pearl", "Shield", "Tunic", "Heart", "Map", "Compass", "Key"
]
pot_item_room_table_lookup = 0xDB67
###
# Pointer to pot location and contents for each non-empty pot in a supertile
# Format: [(x, y, item)] FF FF (Note: x,y are bit packed to include layer)
pot_item_table = 0xDDE7
pot_item_table_end = 0xE6B0
def write_pots_to_rom(rom, pot_contents):
n = pot_item_table
rom.write_bytes(n, [0xFF,0xFF])
n += 2
for i in range(0x140):
if i in pot_contents:
pots = [pot for pot in pot_contents[i] if pot.item != PotItem.Nothing]
if len(pots) > 0:
write_int16(rom, pot_item_room_table_lookup + 2*i, n)
rom.write_bytes(n, list(itertools.chain.from_iterable(((pot.x, pot.y, pot.item) for pot in pots))))
n += 3*len(pots) + 2
rom.write_bytes(n - 2, [0xFF,0xFF])
else:
write_int16(rom, pot_item_room_table_lookup + 2*i, n-2)
else:
write_int16(rom, pot_item_room_table_lookup + 2*i, n-2)
assert n <= pot_item_table_end

View File

@@ -3,7 +3,8 @@ import logging
from collections import deque
import OverworldGlitchRules
from BaseClasses import CollectionState, RegionType, DoorType, Entrance, CrystalBarrier, KeyRuleType
from BaseClasses import CollectionState, RegionType, DoorType, Entrance, CrystalBarrier, KeyRuleType, LocationType
from BaseClasses import PotFlags
from Dungeons import dungeon_table
from RoomData import DoorKind
from OverworldGlitchRules import overworld_glitches_rules
@@ -33,6 +34,7 @@ def set_rules(world, player):
raise NotImplementedError('Not implemented yet')
bomb_rules(world, player)
pot_rules(world, player)
if world.logic[player] == 'noglitches':
no_glitches_rules(world, player)
@@ -584,18 +586,19 @@ def global_rules(world, player):
def bomb_rules(world, player):
# todo: kak well, pod hint (bonkable pots), hookshot pot, spike cave pots
bonkable_doors = ['Two Brothers House Exit (West)', 'Two Brothers House Exit (East)'] # Technically this is incorrectly defined, but functionally the same as what is intended.
bombable_doors = ['Ice Rod Cave', 'Light World Bomb Hut', 'Light World Death Mountain Shop', 'Mini Moldorm Cave',
'Hookshot Cave Back to Middle', 'Hookshot Cave Front to Middle', 'Hookshot Cave Middle to Front','Hookshot Cave Middle to Back',
'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery']
'Hookshot Cave Back to Middle', 'Hookshot Cave Front to Middle', 'Hookshot Cave Middle to Front',
'Hookshot Cave Middle to Back', 'Dark Lake Hylia Ledge Fairy', 'Hype Cave', 'Brewery',
'Paradox Cave Chest Area NE', 'Blinds Hideout N', 'Kakariko Well (top to back)']
for entrance in bonkable_doors:
add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player))
for entrance in bombable_doors:
add_rule(world.get_entrance(entrance, player), lambda state: state.can_use_bombs(player))
bonkable_items = ['Sahasrahla\'s Hut - Left', 'Sahasrahla\'s Hut - Middle', 'Sahasrahla\'s Hut - Right']
bombable_items = ['Blind\'s Hideout - Top', 'Kakariko Well - Top', 'Chicken House', 'Aginah\'s Cave', 'Graveyard Cave',
'Paradox Cave Upper - Left', 'Paradox Cave Upper - Right',
bombable_items = ['Chicken House', 'Aginah\'s Cave', 'Graveyard Cave',
'Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', 'Hype Cave - Bottom']
for location in bonkable_items:
add_rule(world.get_location(location, player), lambda state: state.can_use_bombs(player) or state.has_Boots(player))
@@ -694,6 +697,35 @@ def bomb_rules(world, player):
elif door.kind(world) in [DoorKind.Bombable]:
add_rule(door.entrance, lambda state: state.can_use_bombs(player))
def pot_rules(world, player):
if world.keydropshuffle[player] == 'potsanity':
blocks = [l for l in world.get_locations() if l.type == LocationType.Pot and l.pot.flags & PotFlags.Block]
for block_pot in blocks:
add_rule(block_pot, lambda state: state.can_lift_rocks(player))
# todo : hera 5f - crystal config
for l in world.get_region('Hookshot Fairy', player).locations:
if l.type == LocationType.Pot:
add_rule(l, lambda state: state.has('Hookshot', player))
for l in world.get_region('Spike Cave', player).locations:
if l.type == LocationType.Pot:
add_rule(l, lambda state: state.has('Hammer', player) and state.can_lift_rocks(player) and
((state.has('Cape', player) and state.can_extend_magic(player, 16, True)) or
(state.has('Cane of Byrna', player) and
(state.can_extend_magic(player, 12, True) or
(state.world.can_take_damage and (state.has_Boots(player) or state.has_hearts(player, 4)))))))
for l in world.get_region('Dark Desert Hint', player).locations:
if l.type == LocationType.Pot:
add_rule(l, lambda state: state.can_use_bombs(player))
for l in world.get_region('Palace of Darkness Hint', player).locations:
if l.type == LocationType.Pot:
add_rule(l, lambda state: state.can_use_bombs(player) or state.has_Boots(player))
for l in world.get_region('Dark Lake Hylia Ledge Spike Cave', player).locations:
if l.type == LocationType.Pot:
add_rule(l, lambda state: state.world.can_take_damage or state.has('Hookshot', player))
def default_rules(world, player):
# overworld requirements
set_rule(world.get_entrance('Kings Grave', player), lambda state: state.has_Boots(player))
@@ -1070,6 +1102,10 @@ def add_conditional_lamps(world, player):
'Sewers Rope Room': {'sewer': True, 'entrances': ['Sewers Rope Room Up Stairs', 'Sewers Rope Room North Stairs'], 'locations': []},
'Sewers Water': {'sewer': True, 'entrances': ['Sewers Water S', 'Sewers Water W'], 'locations': []},
'Sewers Key Rat': {'sewer': True, 'entrances': ['Sewers Key Rat E', 'Sewers Key Rat Key Door N'], 'locations': ['Hyrule Castle - Key Rat Key Drop']},
'Old Man Cave': {'sewer': False, 'entrances': ['Old Man Cave Exit (East)']},
'Old Man House Back': {'sewer': False, 'entrances': ['Old Man House Back to Front', 'Old Man House Exit (Top)']},
'Death Mountain Return Cave (left)': {'sewer': False, 'entrances': ['Death Mountain Return Cave E', 'Death Mountain Return Cave Exit (West)']},
'Death Mountain Return Cave (right)': {'sewer': False, 'entrances': ['Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave W']},
}
dark_debug_set = set()
@@ -1086,17 +1122,12 @@ def add_conditional_lamps(world, player):
dark_debug_set.add(region)
for ent in info['entrances']:
add_conditional_lamp(ent, region, 'Entrance')
for loc in info['locations']:
r = world.get_region(region, player)
for loc in r.locations:
add_conditional_lamp(loc, region, 'Location')
logging.getLogger('').debug('Non Dark Regions: ' + ', '.join(set(dark_rooms.keys()).difference(dark_debug_set)))
add_conditional_lamp('Old Man', 'Old Man Cave', 'Location')
add_conditional_lamp('Old Man Cave Exit (East)', 'Old Man Cave', 'Entrance')
add_conditional_lamp('Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave', 'Entrance')
add_conditional_lamp('Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave', 'Entrance')
add_conditional_lamp('Old Man House Front to Back', 'Old Man House', 'Entrance')
add_conditional_lamp('Old Man House Back to Front', 'Old Man House', 'Entrance')
def open_rules(world, player):
# softlock protection as you can reach the sewers small key door with a guard drop key

View File

@@ -45,7 +45,7 @@ def main(args=None):
test("Vanilla ", "--shuffle vanilla")
test("Retro ", "--retro --shuffle vanilla")
test("Keysanity ", "--shuffle vanilla --keydropshuffle --keysanity")
test("Keysanity ", "--shuffle vanilla --keydropshuffle drops_only --keysanity")
test("Shopsanity", "--shuffle vanilla --shopsanity")
test("Simple ", "--shuffle simple")
test("Full ", "--shuffle full")

View File

@@ -584,10 +584,11 @@ def extract_data_from_jp_rom(rom):
with open(rom, 'rb') as stream:
rom_data = bytearray(stream.read())
rooms = [0x1c, 0x1d, 0x4e]
rooms = range(0, 0x128)
# rooms = [0x7b, 0x7c, 0x7d, 0x8b, 0x8c, 0x8d, 0x9b, 0x9c, 0x9d]
# rooms = [0x1a, 0x2a, 0xd1]
for room in rooms:
# print(f'Room {room:02x}')
b2idx = room*2
b3idx = room*3
headerptr = 0x271e2 + b2idx
@@ -604,6 +605,7 @@ def extract_data_from_jp_rom(rom):
stop, idx = False, 0
ffcnt = 0
mode = 0
secret_cnt = 0
# first two bytes
b1 = rom_data[objectloc+idx]
b2 = rom_data[objectloc+idx+1]
@@ -625,9 +627,20 @@ def extract_data_from_jp_rom(rom):
idx += 2
elif not mode and ffcnt < 3:
objectdata.append(b3)
if b3 == 0xFA and ((b2 & 0x3) << 2) | (b1 & 0x3) in [0xf, 0xc]:
# potcalc
vram = ((b1 & 0xFC) >> 1) | ((b2 & 0xFC) << 5)
low = vram & 0xFF
high = (vram & 0xFF00) >> 8
if ffcnt == 1:
high |= 0x20
print(f'db {", ".join([f"${low:02x}", f"${high:02x}"])}')
secret_cnt += 1
idx += 3
else:
idx += 2
if secret_cnt:
print(f'Room {room:02x} {secret_cnt}')
spriteptr = 0x4d62e + b2idx
spriteloc = rom_data[spriteptr] + rom_data[spriteptr+1]*0x100 + 0x40000
secretptr = 0xdb67 + b2idx
@@ -651,23 +664,23 @@ def extract_data_from_jp_rom(rom):
else:
secretdata.append(b3)
idx += 3
print(f'Room {room:02x}')
print(f'HeaderPtr {headerptr:06x}')
print(f'HeaderLoc {headerloc:06x}')
print(f'db {",".join([f"${x:02x}" for x in header])}')
print(f'Obj Length: {len(objectdata)}')
print(f'ObjectPtr {objectptr:06x}')
print(f'ObjectLoc {objectloc:06x}')
for i in range(0, len(objectdata)//16 + 1):
slice = objectdata[i*16:i*16+16]
print(f'db {",".join([f"${x:02x}" for x in slice])}')
print(f'SpritePtr {spriteptr:06x}')
print(f'SpriteLoc {spriteloc:06x}')
print_data_block(spritedata)
print(f'SecretPtr {secretptr:06x}')
print(f'SecretLoc {secretloc:06x}')
print_data_block(secretdata)
print()
# print(f'Room {room:02x}')
# print(f'HeaderPtr {headerptr:06x}')
# print(f'HeaderLoc {headerloc:06x}')
# print(f'db {",".join([f"${x:02x}" for x in header])}')
# print(f'Obj Length: {len(objectdata)}')
# print(f'ObjectPtr {objectptr:06x}')
# print(f'ObjectLoc {objectloc:06x}')
# for i in range(0, len(objectdata)//16 + 1):
# slice = objectdata[i*16:i*16+16]
# print(f'db {",".join([f"${x:02x}" for x in slice])}')
# print(f'SpritePtr {spriteptr:06x}')
# print(f'SpriteLoc {spriteloc:06x}')
# print_data_block(spritedata)
# print(f'SecretPtr {secretptr:06x}')
# print(f'SecretLoc {secretloc:06x}')
# print_data_block(secretdata)
# print()
if __name__ == '__main__':

View File

@@ -42,6 +42,3 @@ warnpc $279C00
incsrc doortables.asm
warnpc $288000
; deals with own hooks
incsrc keydropshuffle.asm

View File

@@ -1,181 +0,0 @@
org $06926e ; <- 3126e - sprite_prep.asm : 2664 (LDA $0B9B : STA $0CBA, X)
jsl SpriteKeyPrep : nop #2
org $06d049 ; <- 35049 sprite_absorbable : 31-32 (JSL Sprite_DrawRippleIfInWater : JSR Sprite_DrawAbsorbable)
jsl SpriteKeyDrawGFX : bra + : nop : +
org $06d180
jsl BigKeyGet : bcs $07 : nop #5
org $06d18d ; <- 3518D - sprite_absorbable.asm : 274 (LDA $7EF36F : INC A : STA $7EF36F)
jsl KeyGet
org $06f9f3 ; bank06.asm : 6732 (JSL Sprite_LoadProperties)
jsl LoadProperties_PreserveItemMaybe
org $06d23a
Sprite_DrawAbsorbable:
org $1eff81
Sprite_DrawRippleIfInWater:
org $0db818
Sprite_LoadProperties:
org $288000 ;140000
ShuffleKeyDrops:
db 0
MultiClientFlags: ; 140001 -> stored in SRAM at 7ef33d
db 0
LootTable: ;PC: 140002
db $0e, $00, $24 ;; ice jelly key
db $13, $00, $24 ;; pokey 2
db $16, $00, $24 ;; swamp waterway pot
db $21, $00, $24 ;; key rat
db $35, $00, $24 ;; swamp trench 2 pot
db $36, $00, $24 ;; hookshot pot
db $37, $00, $24 ;; trench 1 pot
db $38, $00, $24 ;; pot row pot
db $39, $00, $24 ;; skull gibdo
db $3d, $00, $24 ;; gt minihelma
db $3e, $00, $24 ;; ice conveyor
db $3f, $00, $24 ;; ice hammer block ??? is this a dungeon secret?
db $43, $00, $24 ;; tiles 2 pot
db $53, $00, $24 ;; beamos hall pot
db $56, $00, $24 ;; skull west lobby pot
db $63, $00, $24 ;; desert tiles 1 pot
db $71, $00, $24 ;; boomerang guard
db $72, $00, $24 ;; hc map guard
db $7b, $00, $24 ;; gt star pits pot
db $80, $00, $32 ;; a big key (for the current dungeon)
db $8b, $00, $24 ;; gt conv cross block
db $9b, $00, $24 ;; gt dlb switch pot
db $9f, $00, $24 ;; ice many pots
db $99, $00, $24 ;; eastern eyegore
db $a1, $00, $24 ;; mire fishbone pot
db $ab, $00, $24 ;; tt spike switch pot
db $b0, $00, $24 ;; tower circle of pots usain
db $b3, $00, $24 ;; mire spikes pot
db $b6, $00, $24 ;; pokey 1
db $ba, $00, $24 ;; eastern dark pot
db $bc, $00, $24 ;; tt hallway pot
db $c0, $00, $24 ;; tower dark archer
db $c1, $00, $24 ;; mire glitchy jelly
db $ff, $00, $ff
;140068
KeyTable:
db $a0, $a0, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $aa, $ab, $ac, $ad
SpriteKeyPrep:
{
lda $0b9b : sta $0cba, x ; what we wrote over
pha
lda.l ShuffleKeyDrops : beq +
phx
ldx #$fd
- inx #3 : lda.l LootTable, x : cmp #$ff : beq ++ : cmp $a0 : bne -
inx : lda.l LootTable, x : sta !MULTIWORLD_SPRITEITEM_PLAYER_ID
inx : lda.l LootTable, x
plx : sta $0e80, x
cmp #$24 : bne +++
lda $a0 : cmp #$80 : bne + : lda #$24
+++ jsl PrepDynamicTile : bra +
++ plx : lda #$24 : sta $0e80, x
+ pla
rtl
}
SpriteKeyDrawGFX:
{
jsl Sprite_DrawRippleIfInWater
pha
lda.l ShuffleKeyDrops : bne +
- pla
phk : pea.w .jslrtsreturn-1
pea.w $068014 ; an rtl address - 1 in Bank06
jml Sprite_DrawAbsorbable
.jslrtsreturn
rtl
+ lda $0e80, x
cmp #$24 : bne +
lda $a0 : cmp #$80 : bne - : lda #$24
+ jsl DrawDynamicTile ; see DrawHeartPieceGFX if problems
cmp #$03 : bne +
pha : lda $0e60, x : ora.b #$20 : sta $0E60, x : pla
+
jsl.l Sprite_DrawShadowLong
pla : rtl
}
KeyGet:
{
lda $7ef36f ; what we wrote over
pha
lda.l ShuffleKeyDrops : bne +
- pla : rtl
+ ldy $0e80, x
lda $a0 : cmp #$87 : bne +
jsr ShouldKeyBeCountedForDungeon : bcc -
jsl CountChestKeyLong : bra -
+ sty $00
jsr KeyGetPlayer : sta !MULTIWORLD_ITEM_PLAYER_ID
lda !MULTIWORLD_ITEM_PLAYER_ID : bne .receive
phx
lda $040c : lsr : tax
lda $00 : CMP.l KeyTable, x : bne +
- JSL.l FullInventoryExternal : jsl CountChestKeyLong : plx : pla : rtl
+ cmp #$af : beq - ; universal key
cmp #$24 : beq - ; small key for this dungeon
plx
.receive
jsl.l $0791b3 ; Player_HaltDashAttackLong
jsl.l Link_ReceiveItem
pla : dec : rtl
}
; Input Y - the item type
ShouldKeyBeCountedForDungeon:
{
phx
lda $040c : lsr : tax
tya : cmp KeyTable, x : bne +
- plx : sec : rts
+ cmp #$24 : beq -
plx : clc : rts
}
BigKeyGet:
{
lda.l ShuffleKeyDrops : bne +
- stz $02e9 : ldy.b #$32 ; what we wrote over
phx : jsl Link_ReceiveItem : plx ; what we wrote over
clc : rtl
+
ldy $0e80, x
cpy #$32 : beq -
+ sec : rtl
}
KeyGetPlayer:
{
phx
ldx #$fd
- inx #3 : lda.l LootTable, x : cmp #$ff : beq ++ : cmp $a0 : bne -
++ inx : lda.l LootTable, x
plx
rts
}
LoadProperties_PreserveItemMaybe:
{
lda.l ShuffleKeyDrops : bne +
JML Sprite_LoadProperties
+ lda $0e80, x : pha
jsl Sprite_LoadProperties
pla : sta $0e80, x
rtl
}

Binary file not shown.

View File

@@ -8,8 +8,9 @@
2: 2
3: 4
keydropshuffle:
on: 1
off: 1
none: 1
keydrops: 1
potsanity: 1
shopsanity:
on: 1
off: 1

View File

@@ -65,8 +65,11 @@
"type": "bool"
},
"keydropshuffle" : {
"action": "store_true",
"type": "bool"
"choices": [
"none",
"keydrops",
"potsanity"
]
},
"mixed_travel" : {
"choices": [

View File

@@ -254,7 +254,11 @@
"keyshuffle": [ "Small Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ],
"bigkeyshuffle": [ "Big Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ],
"shopsanity": ["Shop contents are shuffle in the main item pool and other items can take their place. (default: %(default)s)"],
"keydropshuffle": [ "Key Drops (Pots and Enemies) are shuffled and other items can take their place (default: %(default)s)" ],
"keydropshuffle": [ "Key Drops (Pots and Enemies) are shuffled and other items can take their place:",
"None: No pots or enemies are included",
"Keydrops: Only key drops are included",
"Potsanity: All key drops and all normal pots are included"
],
"mixed_travel": [
"How to handle potential traversal between dungeon in Crossed door shuffle",
"Prevent: Rails are placed to prevent bombs jump and hovering from changing dungeon except with glitched logic settings",

View File

@@ -53,7 +53,10 @@
"randomizer.dungeon.compassshuffle": "Compasses",
"randomizer.dungeon.smallkeyshuffle": "Small Keys",
"randomizer.dungeon.bigkeyshuffle": "Big Keys",
"randomizer.dungeon.keydropshuffle": "Key Drops (pots and enemies)",
"randomizer.dungeon.keydropshuffle": "Drops and Pots",
"randomizer.dungeon.keydropshuffle.none": "None",
"randomizer.dungeon.keydropshuffle.keydrops": "Only Key Drops",
"randomizer.dungeon.keydropshuffle.potsanity": "All Pots and Key Drops",
"randomizer.dungeon.dungeondoorshuffle": "Dungeon Door Shuffle",
"randomizer.dungeon.dungeondoorshuffle.vanilla": "Vanilla",

View File

@@ -3,7 +3,6 @@
"mapshuffle": { "type": "checkbox" },
"compassshuffle": { "type": "checkbox" },
"smallkeyshuffle": { "type": "checkbox" },
"bigkeyshuffle": { "type": "checkbox" },
"keydropshuffle": { "type": "checkbox" }
"bigkeyshuffle": { "type": "checkbox" }
}
}

View File

@@ -22,6 +22,15 @@
"width": 45
}
},
"keydropshuffle": {
"type": "selectbox",
"default": "none",
"options": [
"none",
"keydrops",
"potsanity"
]
},
"potshuffle": { "type": "checkbox" },
"experimental": { "type": "checkbox" },
"dungeon_counters": {

View File

@@ -65,7 +65,7 @@ def create_item_pool_config(world):
config.location_groups = {}
for player in range(1, world.players + 1):
config.static_placement[player] = vanilla_mapping.copy()
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
for item, locs in keydrop_vanilla_mapping.items():
if item in config.static_placement[player]:
config.static_placement[player][item].extend(locs)
@@ -88,7 +88,7 @@ def create_item_pool_config(world):
for item, locs in vanilla_mapping.items():
if 'Small Key' in item:
universal_key_locations.extend(locs)
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
for item, locs in keydrop_vanilla_mapping.items():
if 'Small Key' in item:
universal_key_locations.extend(locs)
@@ -117,11 +117,11 @@ def create_item_pool_config(world):
groups = LocationGroup('Major').locs(init_set)
if world.bigkeyshuffle[player]:
groups.locations.extend(mode_grouping['Big Keys'])
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
groups.locations.extend(mode_grouping['Big Key Drops'])
if world.keyshuffle[player]:
groups.locations.extend(mode_grouping['Small Keys'])
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
groups.locations.extend(mode_grouping['Key Drops'])
if world.compassshuffle[player]:
groups.locations.extend(mode_grouping['Compasses'])
@@ -322,13 +322,13 @@ def count_major_items(world, player):
major_item_set = 52
if world.bigkeyshuffle[player]:
major_item_set += 11
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
major_item_set += 1
if world.doorShuffle[player] == 'crossed':
major_item_set += 1
if world.keyshuffle[player]:
major_item_set += 29
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
major_item_set += 32
if world.compassshuffle[player]:
major_item_set += 11
@@ -381,11 +381,11 @@ def calc_dungeon_limits(world, player):
val -= 1
if b:
val += 1 if info.bk_present else 0
if k:
if k != 'none':
val += 1 if info.bk_drops else 0
if s or r:
val += info.key_num
if k:
if k != 'none':
val += info.key_drops
if c:
val += 1 if info.compass_present else 0
@@ -396,11 +396,11 @@ def calc_dungeon_limits(world, player):
limits = 60
if world.bigkeyshuffle[player]:
limits += 11
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
limits += 1
if world.keyshuffle[player] or world.retro[player]:
limits += 29
if world.keydropshuffle[player]:
if world.keydropshuffle[player] != 'none':
limits += 32
if world.compassshuffle[player]:
limits += 11
@@ -847,11 +847,15 @@ trash_items = {
'Small Heart': 2,
'Bee': 2,
'Arrows (5)': 2,
'Chicken': 2,
'Bombs (3)': 3,
'Arrows (10)': 3,
'Bombs (10)': 3,
'Small Magic': 3,
'Big Magic': 4,
'Red Potion': 4,
'Blue Shield': 4,
'Rupees (50)': 4,