Merge branch 'OverworldShuffleDev' into OverworldShuffle
This commit is contained in:
@@ -2,24 +2,17 @@
|
||||
name: ⏱️Test/🔨Build/🚀Deploy
|
||||
|
||||
# fire on
|
||||
on: [
|
||||
push,
|
||||
pull_request
|
||||
]
|
||||
|
||||
# on:
|
||||
# push:
|
||||
# branches:
|
||||
# - DoorDevUnstable
|
||||
# - DoorDev
|
||||
# - OverworldShuffleDev
|
||||
# - OverworldShuffle
|
||||
# pull_request:
|
||||
# branches:
|
||||
# - DoorDevUnstable
|
||||
# - DoorDev
|
||||
# - OverworldShuffleDev
|
||||
# - OverworldShuffle
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
# - DoorDevUnstable
|
||||
# - DoorDev
|
||||
- OverworldShuffle
|
||||
pull_request:
|
||||
branches:
|
||||
# - DoorDevUnstable
|
||||
# - DoorDev
|
||||
- OverworldShuffle
|
||||
|
||||
# stuff to do
|
||||
jobs:
|
||||
@@ -43,7 +36,6 @@ jobs:
|
||||
os-name: [
|
||||
# ubuntu-latest, # ubuntu-22.04
|
||||
ubuntu-22.04,
|
||||
ubuntu-20.04,
|
||||
macos-latest, # macos-12
|
||||
windows-latest # windows-2022
|
||||
]
|
||||
@@ -102,7 +94,6 @@ jobs:
|
||||
os-name: [
|
||||
# ubuntu-latest, # ubuntu-22.04
|
||||
ubuntu-22.04,
|
||||
ubuntu-20.04,
|
||||
macos-latest, # macos-12
|
||||
windows-latest # windows-2022
|
||||
]
|
||||
@@ -178,7 +169,6 @@ jobs:
|
||||
os-name: [
|
||||
# ubuntu-latest, # ubuntu-22.04
|
||||
ubuntu-22.04,
|
||||
ubuntu-20.04,
|
||||
macos-latest, # macos-12
|
||||
windows-latest # windows-2022
|
||||
]
|
||||
@@ -220,7 +210,6 @@ jobs:
|
||||
os-name: [
|
||||
# ubuntu-latest, # ubuntu-22.04
|
||||
ubuntu-22.04,
|
||||
ubuntu-20.04,
|
||||
macos-latest, # macos-12
|
||||
windows-latest # windows-2022
|
||||
]
|
||||
@@ -358,8 +347,10 @@ jobs:
|
||||
echo "MacOS Asset: ${{ steps.identify-macos-asset.outputs.asset_macos }}"
|
||||
echo "Windows Asset: ${{ steps.identify-windows-asset.outputs.asset_windows }}"
|
||||
|
||||
# create a release (MASTER)
|
||||
- name: 📀->🚀Create a Release (MASTER)
|
||||
# create a release (OverworldShuffle)
|
||||
# if: contains(github.ref, 'OverworldShuffle') # branch or tag name
|
||||
# if: contains(github.event.head_commit.message, 'Version bump') # commit message
|
||||
- name: 📀->🚀Create a Release (OverworldShuffle)
|
||||
id: create_release
|
||||
uses: actions/create-release@v1.1.4
|
||||
env:
|
||||
@@ -369,11 +360,11 @@ jobs:
|
||||
release_name: ${{ steps.debug_info.outputs.release_name }}
|
||||
body_path: CHANGELOG.md
|
||||
# draft: true
|
||||
if: contains(github.ref, 'OverworldShuffle') && contains(github.event.head_commit.message, 'Version bump') # branch/tag name and commit message
|
||||
if: contains(github.event.head_commit.message, "Merge 'OverworldShuffleDev' into OverworldShuffle") # branch/tag name and commit message
|
||||
|
||||
# upload linux archive asset (MASTER)
|
||||
# upload linux archive asset (OverworldShuffle)
|
||||
#TODO: Make sure we're firing on the proper branches
|
||||
- name: 🔼Upload Linux Archive Asset (MASTER)
|
||||
- name: 🔼Upload Linux Archive Asset (OverworldShuffle)
|
||||
id: upload-linux-asset
|
||||
uses: actions/upload-release-asset@v1.0.2
|
||||
env:
|
||||
@@ -383,11 +374,11 @@ jobs:
|
||||
asset_path: ${{ steps.parentDir.outputs.parentDir }}/deploy/linux/${{ steps.identify-linux-asset.outputs.asset_linux }}
|
||||
asset_name: ${{ steps.debug_info.outputs.asset_prefix }}-linux-focal.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
if: contains(github.ref, 'OverworldShuffle') && contains(github.event.head_commit.message, 'Version bump') # branch/tag name and commit message
|
||||
if: contains(github.event.head_commit.message, "Merge 'OverworldShuffleDev' into OverworldShuffle") # branch/tag name and commit message
|
||||
|
||||
# upload macos archive asset (MASTER)
|
||||
# upload macos archive asset (OverworldShuffle)
|
||||
#TODO: Make sure we're firing on the proper branches
|
||||
- name: 🔼Upload MacOS Archive Asset (MASTER)
|
||||
- name: 🔼Upload MacOS Archive Asset (OverworldShuffle)
|
||||
id: upload-macos-asset
|
||||
uses: actions/upload-release-asset@v1.0.2
|
||||
env:
|
||||
@@ -397,11 +388,11 @@ jobs:
|
||||
asset_path: ${{ steps.parentDir.outputs.parentDir }}/deploy/macos/${{ steps.identify-macos-asset.outputs.asset_macos }}
|
||||
asset_name: ${{ steps.debug_info.outputs.asset_prefix }}-osx.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
if: contains(github.ref, 'OverworldShuffle') && contains(github.event.head_commit.message, 'Version bump') # branch/tag name and commit message
|
||||
if: contains(github.event.head_commit.message, "Merge 'OverworldShuffleDev' into OverworldShuffle") # branch/tag name and commit message
|
||||
|
||||
# upload windows archive asset (MASTER)
|
||||
# upload windows archive asset (OverworldShuffle)
|
||||
#TODO: Make sure we're firing on the proper branches
|
||||
- name: 🔼Upload Windows Archive Asset (MASTER)
|
||||
- name: 🔼Upload Windows Archive Asset (OverworldShuffle)
|
||||
id: upload-windows-asset
|
||||
uses: actions/upload-release-asset@v1.0.2
|
||||
env:
|
||||
@@ -411,4 +402,14 @@ jobs:
|
||||
asset_path: ${{ steps.parentDir.outputs.parentDir }}/deploy/windows/${{ steps.identify-windows-asset.outputs.asset_windows }}
|
||||
asset_name: ${{ steps.debug_info.outputs.asset_prefix }}-windows.zip
|
||||
asset_content_type: application/zip
|
||||
if: contains(github.ref, 'OverworldShuffle') && contains(github.event.head_commit.message, 'Version bump') # branch/tag name and commit message
|
||||
if: contains(github.event.head_commit.message, "Merge 'OverworldShuffleDev' into OverworldShuffle") # branch/tag name and commit message
|
||||
|
||||
- name: 🖳Tag Baserom
|
||||
uses: ./.github/actions/tag-repo
|
||||
env:
|
||||
FINE_PAT: ${{ secrets.ALTTPER_TAGGER }}
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/z3randomizer
|
||||
ref-name: heads/OWMain
|
||||
github-tag: ${{ github.event.release.tag_name }}
|
||||
if: contains(github.event.head_commit.message, "Merge 'OverworldShuffleDev' into OverworldShuffle")
|
||||
|
||||
+21
-6
@@ -642,7 +642,7 @@ class CollectionState(object):
|
||||
queue = deque(old_state.blocked_connections[player].items())
|
||||
|
||||
old_state.traverse_world(queue, rrp, bc, player)
|
||||
if old_state.world.key_logic_algorithm[player] == 'default':
|
||||
if old_state.world.key_logic_algorithm[player] == 'dangerous':
|
||||
unresolved_events = [x for y in old_state.reachable_regions[player] for x in y.locations
|
||||
if x.event and x.item and (x.item.smallkey or x.item.bigkey or x.item.advancement)
|
||||
and x not in old_state.locations_checked and x.can_reach(old_state)]
|
||||
@@ -670,7 +670,7 @@ class CollectionState(object):
|
||||
queue = deque(self.blocked_connections[player].items())
|
||||
|
||||
self.traverse_world(queue, rrp, bc, player)
|
||||
if self.world.key_logic_algorithm[player] == 'default':
|
||||
if self.world.key_logic_algorithm[player] == 'dangerous':
|
||||
unresolved_events = [x for y in self.reachable_regions[player] for x in y.locations
|
||||
if x.event and x.item and (x.item.smallkey or x.item.bigkey or x.item.advancement)
|
||||
and x not in self.locations_checked and x.can_reach(self)]
|
||||
@@ -2651,7 +2651,7 @@ class Location(object):
|
||||
self.recursion_count = 0
|
||||
self.staleness_count = 0
|
||||
self.locked = False
|
||||
self.real = not prize
|
||||
self.real = True
|
||||
self.always_allow = lambda item, state: False
|
||||
self.access_rule = lambda state: True
|
||||
self.verbose_rule = None
|
||||
@@ -2789,7 +2789,7 @@ class Item(object):
|
||||
def explore_region(region):
|
||||
explored_regions.append(region.name)
|
||||
for ent in region.entrances:
|
||||
if ent.parent_region is not None:
|
||||
if ent.parent_region is not None and ent.spot_type != 'OWG':
|
||||
if ent.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld]:
|
||||
return ent
|
||||
elif ent.parent_region.name not in explored_regions:
|
||||
@@ -2989,6 +2989,8 @@ class Spoiler(object):
|
||||
'shuffleganon': self.world.shuffle_ganon,
|
||||
'shufflelinks': self.world.shufflelinks,
|
||||
'shuffletavern': self.world.shuffletavern,
|
||||
'skullwoods': self.world.skullwoods,
|
||||
'linked_drops': self.world.linked_drops,
|
||||
'take_any': self.world.take_any,
|
||||
'overworld_map': self.world.overworld_map,
|
||||
'door_shuffle': self.world.doorShuffle,
|
||||
@@ -3242,6 +3244,9 @@ class Spoiler(object):
|
||||
if self.metadata['shuffle'][player] != 'vanilla':
|
||||
outfile.write('Shuffle Link\'s House:'.ljust(line_width) + '%s\n' % yn(self.metadata['shufflelinks'][player]))
|
||||
outfile.write('Shuffle Back of Tavern:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffletavern'][player]))
|
||||
outfile.write('Skull Woods Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['skullwoods'][player])
|
||||
if self.metadata['linked_drops'] != "unset":
|
||||
outfile.write('Linked Drops Override:'.ljust(line_width) + '%s\n' % self.metadata['linked_drops'][player])
|
||||
outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffleganon'][player]))
|
||||
outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % self.metadata['open_pyramid'][player])
|
||||
outfile.write('Overworld Map:'.ljust(line_width) + '%s\n' % self.metadata['overworld_map'][player])
|
||||
@@ -3641,7 +3646,11 @@ keyshuffle_mode = {'none': 0, 'off': 0, 'wild': 1, 'on': 1, 'universal': 2}
|
||||
# byte 14: POOT TKKK (pseudoboots, overworld_map, trap_door_mode, key_logic_algo)
|
||||
overworld_map_mode = {'default': 0, 'compass': 1, 'map': 2}
|
||||
trap_door_mode = {'vanilla': 0, 'optional': 1, 'boss': 2, 'oneway': 3}
|
||||
key_logic_algo = {'default': 0, 'partial': 1, 'strict': 2}
|
||||
key_logic_algo = {'dangerous': 0, 'partial': 1, 'strict': 2}
|
||||
|
||||
# byte 15: SSDD ???? (skullwoods, linked_drops, 4 free bytes)
|
||||
skullwoods_mode = {'original': 0, 'restricted': 1, 'loose': 2, 'followlinked': 3}
|
||||
linked_drops_mode = {'unset': 0, 'linked': 1, 'independent': 2}
|
||||
|
||||
# sfx_shuffle and other adjust items does not affect settings code
|
||||
|
||||
@@ -3698,6 +3707,8 @@ class Settings(object):
|
||||
|
||||
((0x80 if w.pseudoboots[p] else 0) | overworld_map_mode[w.overworld_map[p]] << 5
|
||||
| trap_door_mode[w.trap_door_mode[p]] << 3 | key_logic_algo[w.key_logic_algorithm[p]]),
|
||||
|
||||
(skullwoods_mode[w.skullwoods[p]] << 6 | linked_drops_mode[w.linked_drops[p]] << 4),
|
||||
])
|
||||
return base64.b64encode(code, "+-".encode()).decode()
|
||||
|
||||
@@ -3705,7 +3716,7 @@ class Settings(object):
|
||||
def adjust_args_from_code(code, player, args):
|
||||
settings, p = base64.b64decode(code.encode(), "+-".encode()), player
|
||||
|
||||
if len(settings) < 14:
|
||||
if len(settings) < 15:
|
||||
raise Exception('Provided code is incompatible with this version')
|
||||
if settings[10] != settings_version:
|
||||
raise Exception('Provided code is incompatible with this version')
|
||||
@@ -3788,6 +3799,10 @@ class Settings(object):
|
||||
args.trap_door_mode[p] = r(trap_door_mode)[(settings[14] & 0x18) >> 3]
|
||||
args.key_logic_algorithm[p] = r(key_logic_algo)[settings[14] & 0x07]
|
||||
|
||||
if len(settings) > 15:
|
||||
args.skullwoods[p] = r(skullwoods_mode)[(settings[15] & 0xc0) >> 6]
|
||||
args.linked_drops[p] = r(linked_drops_mode)[(settings[15] & 0x30) >> 4]
|
||||
|
||||
|
||||
class KeyRuleType(FastEnum):
|
||||
WorstCase = 0
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.0.2
|
||||
- \~Merged in DR v1.4.5~
|
||||
- ER - SW Shuffle Options
|
||||
- ER - Linked Drops Options
|
||||
- Many GFX fixes
|
||||
- Fixes to MSU/music
|
||||
- No longer delete smith with prize shuffle
|
||||
- Fixed screen scroll issue in Zora's Domain
|
||||
- Fixed HUD when drawing A items on DR menu
|
||||
|
||||
## 0.5.0.1
|
||||
- Fixed HP refill interrupting boss cutscenes
|
||||
- Fixed incorrect compass counts in Prize Shuffle
|
||||
|
||||
@@ -139,6 +139,7 @@ def parse_cli(argv, no_defaults=False):
|
||||
'usestartinventory', 'bombbag', 'shuffleganon', 'overworld_map', 'restrict_boss_items',
|
||||
'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max', 'triforce_max_difference',
|
||||
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
|
||||
'skullwoods', 'linked_drops',
|
||||
'pseudoboots', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
||||
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
||||
@@ -203,6 +204,8 @@ def parse_settings():
|
||||
"shuffle": "vanilla",
|
||||
"shufflelinks": False,
|
||||
"shuffletavern": True,
|
||||
'skullwoods': 'original',
|
||||
'linked_drops': 'unset',
|
||||
"overworld_map": "default",
|
||||
"take_any": "none",
|
||||
"pseudoboots": False,
|
||||
|
||||
+1
-1
@@ -2088,7 +2088,7 @@ def shuffle_small_key_doors(door_type_pools, used_doors, start_regions_map, all_
|
||||
if actual_chest_keys == 0:
|
||||
dungeon.small_keys = []
|
||||
else:
|
||||
dungeon.small_keys = [ItemFactory(dungeon_keys[dungeon_name], player)] * actual_chest_keys
|
||||
dungeon.small_keys = [ItemFactory(dungeon_keys[dungeon_name], player) for _ in range(actual_chest_keys)]
|
||||
|
||||
for name, small_list in small_map.items():
|
||||
used_doors.update(flatten_pair_list(small_list))
|
||||
|
||||
+3
-5
@@ -1850,10 +1850,8 @@ def ensure_crystal_switches_reachable(dungeon_map, crystal_switches, polarized_s
|
||||
sector.equations = calc_sector_equations(sector)
|
||||
if sector.is_entrance_sector() and not sector.destination_entrance:
|
||||
need_switch = True
|
||||
for region in sector.get_start_regions():
|
||||
if region.crystal_switch:
|
||||
need_switch = False
|
||||
break
|
||||
if sector.c_switch: # this relies on the fact that Mire Fishbone SE cannot be a portal
|
||||
need_switch = False
|
||||
any_benefit = False
|
||||
for eq in sector.equations:
|
||||
if len(eq.benefit) > 0:
|
||||
@@ -4035,7 +4033,7 @@ def calc_door_equation(door, sector, look_for_entrance, sewers_flag=None):
|
||||
eq = DoorEquation(door)
|
||||
eq.benefit[hook_from_door(door)].append(door)
|
||||
eq.required = True
|
||||
eq.c_switch = door.crystal == CrystalBarrier.Either
|
||||
eq.c_switch = sector.c_switch # Big change - not true for mire fishbone, need to verify for others
|
||||
# exceptions for long entrances ???
|
||||
# if door.name in ['PoD Dark Alley']:
|
||||
eq.entrance_flag = True
|
||||
|
||||
@@ -95,7 +95,7 @@ def fill_dungeons_restrictive(world, shuffled_locations):
|
||||
continue
|
||||
break
|
||||
else:
|
||||
raise FillError(f'Unable to place dungeon prizes {", ".join(list(map(lambda d: d.hint_text, prize_locs)))}')
|
||||
raise FillError(f'Unable to place dungeon prizes: {", ".join(list(map(lambda d: d.name, prizes)))}')
|
||||
|
||||
random.shuffle(shuffled_locations)
|
||||
fill(all_state_base, others, shuffled_locations)
|
||||
|
||||
+10
-2
@@ -69,6 +69,7 @@ class InitialSram:
|
||||
starting_arrow_cap_upgrades = 30
|
||||
starting_bombs = 0
|
||||
starting_arrows = 0
|
||||
starting_magic = 0
|
||||
|
||||
startingstate = CollectionState(world)
|
||||
|
||||
@@ -108,10 +109,10 @@ class InitialSram:
|
||||
|
||||
if startingstate.has('Magic Upgrade (1/4)', player):
|
||||
equip[0x37B] = 2
|
||||
equip[0x36E] = 0x80
|
||||
starting_magic = 0x80
|
||||
elif startingstate.has('Magic Upgrade (1/2)', player):
|
||||
equip[0x37B] = 1
|
||||
equip[0x36E] = 0x80
|
||||
starting_magic = 0x80
|
||||
|
||||
if startingstate.has('Return Old Man', player):
|
||||
self._initial_sram_bytes[0x410] |= 0x01
|
||||
@@ -176,6 +177,7 @@ class InitialSram:
|
||||
arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10}
|
||||
bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10}
|
||||
arrows = {'Single Arrow': 1, 'Arrows (10)': 10}
|
||||
magic = {'Big Magic': 0x80, 'Small Magic': 0x10}
|
||||
|
||||
if item.name in set_table:
|
||||
equip[set_table[item.name][0]] = set_table[item.name][1]
|
||||
@@ -212,13 +214,19 @@ class InitialSram:
|
||||
if item.name != 'Piece of Heart' or equip[0x36B] == 0:
|
||||
equip[0x36C] = min(equip[0x36C] + 0x08, 0xA0)
|
||||
equip[0x36D] = min(equip[0x36D] + 0x08, 0xA0)
|
||||
elif item.name in magic:
|
||||
starting_magic += magic[item.name]
|
||||
else:
|
||||
raise RuntimeError(f'Unsupported item in starting equipment: {item.name}')
|
||||
|
||||
equip[0x36E] = min(starting_magic, 0x80)
|
||||
equip[0x370] = min(starting_bomb_cap_upgrades, 50)
|
||||
equip[0x371] = min(starting_arrow_cap_upgrades, 70)
|
||||
equip[0x343] = min(starting_bombs, equip[0x370])
|
||||
equip[0x377] = min(starting_arrows, equip[0x371])
|
||||
|
||||
if not startingstate.has('Magic Mirror', player) and world.doorShuffle[player] != 'vanilla':
|
||||
equip[0x353] = 1
|
||||
|
||||
# Assertion and copy equip to initial_sram_bytes
|
||||
assert equip[:0x340] == [0] * 0x340
|
||||
|
||||
+23
-1
@@ -11,7 +11,7 @@ from Tables import bonk_prize_lookup
|
||||
from Items import ItemFactory
|
||||
|
||||
from source.dungeon.EnemyList import add_drop_contents
|
||||
from source.overworld.EntranceShuffle2 import connect_entrance
|
||||
from source.overworld.EntranceShuffle2 import exit_ids, door_addresses
|
||||
from source.item.FillUtil import trash_items, pot_items
|
||||
|
||||
import source.classes.constants as CONST
|
||||
@@ -546,6 +546,27 @@ def set_up_take_anys(world, player, skip_adjustments=False):
|
||||
world.initialize_regions()
|
||||
|
||||
|
||||
def connect_entrance(world, entrancename, exitname, player):
|
||||
entrance = world.get_entrance(entrancename, player)
|
||||
# check if we got an entrance or a region to connect to
|
||||
try:
|
||||
region = world.get_region(exitname, player)
|
||||
exit = None
|
||||
except RuntimeError:
|
||||
exit = world.get_entrance(exitname, player)
|
||||
region = exit.parent_region
|
||||
|
||||
# if this was already connected somewhere, remove the backreference
|
||||
if entrance.connected_region is not None:
|
||||
entrance.connected_region.entrances.remove(entrance)
|
||||
|
||||
target = exit_ids[exit.name][0] if exit is not None else exit_ids.get(region.name, None)
|
||||
addresses = door_addresses[entrance.name][0]
|
||||
|
||||
entrance.connect(region, addresses, target)
|
||||
world.spoiler.set_entrance(entrance.name, exit.name if exit is not None else region.name, 'entrance', player)
|
||||
|
||||
|
||||
def create_dynamic_shop_locations(world, player):
|
||||
for shop in world.shops[player]:
|
||||
if shop.region.player == player:
|
||||
@@ -1462,6 +1483,7 @@ def make_customizer_pool(world, player):
|
||||
bow_found = next((i for i in pool if i in {'Bow', 'Progressive Bow'}), None)
|
||||
if not bow_found:
|
||||
missing_items.append('Progressive Bow')
|
||||
missing_items = [i for i in missing_items if all(i != start.name or player != start.player for start in world.precollected_items)]
|
||||
if missing_items:
|
||||
logging.getLogger('').warning(f'The following items are not in the custom item pool {", ".join(missing_items)}')
|
||||
|
||||
|
||||
@@ -20,151 +20,151 @@ def ItemFactory(items, player):
|
||||
|
||||
|
||||
# Format: Name: (Advancement, Priority, Type, ItemCode, BasePrice, Pedestal Hint Text, Pedestal Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text, Hint Text)
|
||||
item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'),
|
||||
'Progressive Bow': (True, False, None, 0x64, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
'Progressive Bow (Alt)': (True, False, None, 0x65, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
item_table = {'Bow': (True, False, None, 0x0B, 200, 'Bow!\nJoin the archer class!', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'),
|
||||
'Progressive Bow': (True, False, None, 0x64, 150, 'Bow!\nJoin the archer class!', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
'Progressive Bow (Alt)': (True, False, None, 0x65, 150, 'Bow!\nJoin the archer class!', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
'Book of Mudora': (True, False, None, 0x1D, 150, 'This is a\nparadox?!', 'and the story book', 'the scholarly kid', 'moon runes for sale', 'drugs for literacy', 'book-worm boy can read again', 'the Book'),
|
||||
'Hammer': (True, False, None, 0x09, 250, 'Stop\nhammer time!', 'and m c hammer', 'hammer-smashing kid', 'm c hammer for sale', 'stop... hammer time', 'stop, hammer time', 'the Hammer'),
|
||||
'Hookshot': (True, False, None, 0x0A, 250, 'BOING!!!\nBOING!!!\nBOING!!!', 'and the tickle beam', 'tickle-monster kid', 'tickle beam for sale', 'witch and tickle boy', 'beam boy tickles again', 'the Hookshot'),
|
||||
'Magic Mirror': (True, False, None, 0x1A, 250, 'Isn\'t your\nreflection so\npretty?', 'the face reflector', 'the narcissistic kid', 'your face for sale', 'trades looking-glass', 'narcissistic boy is happy again', 'the Mirror'),
|
||||
'Ocarina': (True, False, None, 0x14, 250, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'ocarina boy plays again', 'the Flute'),
|
||||
'Ocarina (Activated)': (True, False, None, 0x4A, 250, 'Save the duck\nand fly to\nfreedom!', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'ocarina boy plays again', 'the Flute'),
|
||||
'Pegasus Boots': (True, False, None, 0x4B, 250, 'Gotta go fast!', 'and the sprint shoes', 'the running-man kid', 'sprint shoe for sale', 'shrooms for speed', 'gotta-go-fast boy runs again', 'the Boots'),
|
||||
'Power Glove': (True, False, None, 0x1B, 100, 'Now you can\nlift weak\nstuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the Glove'),
|
||||
'Cape': (True, False, None, 0x19, 50, 'Wear this to\nbecome\ninvisible!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the Cape'),
|
||||
'Mushroom': (True, False, None, 0x29, 50, 'I\'m a fun guy!\n\nI\'m a funghi!', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the Mushroom'),
|
||||
'Shovel': (True, False, None, 0x13, 50, 'Can\n You\n Dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the Shovel'),
|
||||
'Lamp': (True, False, None, 0x12, 150, 'Baby, baby,\nbaby.\nLight my way!', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the Lamp'),
|
||||
'Magic Powder': (True, False, None, 0x0D, 50, 'You can turn\nanti-faeries\ninto faeries', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the Powder'),
|
||||
'Moon Pearl': (True, False, None, 0x1F, 200, ' Bunny Link\n be\n gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the Moon Pearl'),
|
||||
'Cane of Somaria': (True, False, None, 0x15, 250, 'I make blocks\nto hold down\nswitches!', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the Red Cane'),
|
||||
'Fire Rod': (True, False, None, 0x07, 250, 'I\'m the hot\nrod. I make\nthings burn!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the Fire Rod'),
|
||||
'Flippers': (True, False, None, 0x1E, 250, 'Fancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the Flippers'),
|
||||
'Ice Rod': (True, False, None, 0x08, 250, 'I\'m the cold\nrod. I make\nthings freeze!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the Ice Rod'),
|
||||
'Titans Mitts': (True, False, None, 0x1C, 200, 'Now you can\nlift heavy\nstuff!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the Mitts'),
|
||||
'Bombos': (True, False, None, 0x0F, 100, 'Burn, baby,\nburn! Fear my\nring of fire!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'medallion boy melts room again', 'Bombos'),
|
||||
'Ether': (True, False, None, 0x10, 100, 'This magic\ncoin freezes\neverything!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'medallion boy sees floor again', 'Ether'),
|
||||
'Quake': (True, False, None, 0x11, 100, 'Maxing out the\nRichter scale\nis what I do!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'medallion boy shakes dirt again', 'Quake'),
|
||||
'Bottle': (True, False, None, 0x16, 50, 'Now you can\nstore potions\nand stuff!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'bottle boy has terrarium again', 'a bottle'),
|
||||
'Bottle (Red Potion)': (True, False, None, 0x2B, 70, 'Hearty red goop!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a bottle'),
|
||||
'Bottle (Green Potion)': (True, False, None, 0x2C, 60, 'Refreshing green goop!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a bottle'),
|
||||
'Bottle (Blue Potion)': (True, False, None, 0x2D, 80, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a bottle'),
|
||||
'Bottle (Fairy)': (True, False, None, 0x3D, 70, 'Save me and I will revive you', 'and the captive', 'the tingle kid', 'hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a bottle'),
|
||||
'Bottle (Bee)': (True, False, None, 0x3C, 50, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bottle'),
|
||||
'Bottle (Good Bee)': (True, False, None, 0x48, 60, 'I will sting your foes a whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has beetor again', 'a bottle'),
|
||||
'Master Sword': (True, False, 'Sword', 0x50, 100, 'I beat barries and pigs alike', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again', 'the Master Sword'),
|
||||
'Tempered Sword': (True, False, 'Sword', 0x02, 150, 'I stole the\nblacksmith\'s\njob!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'),
|
||||
'Fighter Sword': (True, False, 'Sword', 0x49, 50, 'A pathetic\nsword rests\nhere!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the Fighter Sword'),
|
||||
'Sword and Shield': (True, False, 'Sword', 0x00, 'An uncle\nsword rests\nhere!', 'the sword and shield', 'sword and shield-wielding kid', 'training set for sale', 'fungus for training set', 'sword and shield boy fights again', 'the small sword and shield'),
|
||||
'Golden Sword': (True, False, 'Sword', 0x03, 200, 'The butter\nsword rests\nhere!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'),
|
||||
'Progressive Sword': (True, False, 'Sword', 0x5E, 150, 'A better copy\nof your sword\nfor your time', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again', 'a Sword'),
|
||||
'Progressive Glove': (True, False, None, 0x61, 150, 'A way to lift\nheavier things', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a Glove'),
|
||||
'Silver Arrows': (True, False, None, 0x58, 100, 'Do you fancy\nsilver tipped\narrows?', 'and the ganonsbane', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again', 'the Silver Arrows'),
|
||||
'Green Pendant': (True, False, 'Prize', 0x37, 250, 'A pendant that\nsome old guy\nwill never see', 'and the green pendant', 'pendant kid', 'pendant for sale', 'fungus for pendant', 'pendant boy dabs again', 'a Prize'),
|
||||
'Blue Pendant': (True, False, 'Prize', 0x39, 150, 'A pendant that you\'ll never get', 'and the pendant', 'pendant kid', 'pendant for sale', 'fungus for pendant', 'pendant boy dabs again', 'a Prize'),
|
||||
'Red Pendant': (True, False, 'Prize', 0x38, 150, 'A pendant that you\'ll never get', 'and the pendant', 'pendant kid', 'pendant for sale', 'fungus for pendant', 'pendant boy dabs again', 'a Prize'),
|
||||
'Triforce': (True, False, None, 0x6A, 777, '\n YOU WIN!', 'and the triforce', 'victorious kid', 'victory for sale', 'fungus for the win', 'greedy boy wins game again', 'the Triforce'),
|
||||
'Power Star': (True, False, None, 0x6B, 100, 'A small victory', 'and the power star', 'star-struck kid', 'star for sale', 'see stars with shroom', 'mario powers up again', 'a Power Star'),
|
||||
'Triforce Piece': (True, False, None, 0x6C, 100, 'A small victory', 'and the thirdforce', 'triangular kid', 'triangle for sale', 'fungus for triangle', 'wise boy has triangle again', 'a Triforce piece'),
|
||||
'Crystal 1': (True, False, 'Prize', 0xB1, 200, 'A pretty nice,\nshiny crystal', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 2': (True, False, 'Prize', 0xB4, 200, 'A pretty nice,\nshiny crystal', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 3': (True, False, 'Prize', 0xB6, 200, 'A pretty nice,\nshiny crystal', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 4': (True, False, 'Prize', 0xB5, 200, 'A pretty nice,\nshiny crystal', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 5': (True, False, 'Prize', 0xB2, 250, 'A crystal that\nunlocks a bomb', 'and the red crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 6': (True, False, 'Prize', 0xB0, 250, 'A crystal that\nunlocks a bomb', 'and the red crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 7': (True, False, 'Prize', 0xB3, 200, 'A pretty nice,\nshiny crystal', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Single Arrow': (False, False, None, 0x43, 3, 'A lonely arrow\nsits here.', 'and the arrow', 'stick-collecting kid', 'sewing needle for sale', 'fungus for arrow', 'archer boy sews again', 'an arrow'),
|
||||
'Arrows (10)': (False, False, None, 0x44, 30, 'This will give\nyou ten shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'ten arrows'),
|
||||
'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
|
||||
'Arrow Upgrade (+5)': (False, False, None, 0x53, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
|
||||
'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'),
|
||||
'Arrows (5)': (False, False, None, 0xD5, 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, 0xD4, 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'),
|
||||
'Hookshot': (True, False, None, 0x0A, 250, 'Hookshot!\nBOING!!!\nBOING!!!', 'and the tickle beam', 'tickle-monster kid', 'tickle beam for sale', 'witch and tickle boy', 'beam boy tickles again', 'the Hookshot'),
|
||||
'Magic Mirror': (True, False, None, 0x1A, 250, 'Mirror!\nTake some time to\nreflect on this moment!', 'the face reflector', 'the narcissistic kid', 'your face for sale', 'trades looking-glass', 'narcissistic boy is happy again', 'the Mirror'),
|
||||
'Ocarina': (True, False, None, 0x14, 250, 'Ocarina!\nA Flute by another name', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'ocarina boy plays again', 'the Flute'),
|
||||
'Ocarina (Activated)': (True, False, None, 0x4A, 250, 'Ocarina!\nA Flute by another name', 'and the duck call', 'the duck-call kid', 'duck call for sale', 'duck-calls for trade', 'ocarina boy plays again', 'the Flute'),
|
||||
'Pegasus Boots': (True, False, None, 0x4B, 250, 'Pegasus Boots!\nGotta go fast!', 'and the sprint shoes', 'the running-man kid', 'sprint shoe for sale', 'shrooms for speed', 'gotta-go-fast boy runs again', 'the Boots'),
|
||||
'Power Glove': (True, False, None, 0x1B, 100, 'Glove!\nNow you can\nlift weak stuff!', 'and the grey mittens', 'body-building kid', 'lift glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'the Glove'),
|
||||
'Cape': (True, False, None, 0x19, 50, 'Cape!\nInvisbility cloak activate!', 'the camouflage cape', 'red riding-hood kid', 'red hood for sale', 'hood from a hood', 'dapper boy hides again', 'the Cape'),
|
||||
'Mushroom': (True, False, None, 0x29, 50, 'Mushroom!\nDon\'t eat it. Find a witch.', 'and the legal drugs', 'the drug-dealing kid', 'legal drugs for sale', 'shroom swap', 'shroom boy sells drugs again', 'the Mushroom'),
|
||||
'Shovel': (True, False, None, 0x13, 50, 'Shovel!\nCan you dig it?', 'and the spade', 'archaeologist kid', 'dirt spade for sale', 'can you dig it', 'shovel boy digs again', 'the Shovel'),
|
||||
'Lamp': (True, False, None, 0x12, 150, 'Lamp!\nYou can see in the dark,\nand light torches.', 'and the flashlight', 'light-shining kid', 'flashlight for sale', 'fungus for illumination', 'illuminated boy can see again', 'the Lamp'),
|
||||
'Magic Powder': (True, False, None, 0x0D, 50, 'Powder!\nSprinkle it on a dancing pickle!', 'and the magic sack', 'the sack-holding kid', 'magic sack for sale', 'the witch and assistant', 'magic boy plays marbles again', 'the Powder'),
|
||||
'Moon Pearl': (True, False, None, 0x1F, 200, 'Moon Pearl!\nRabbit Be Gone!', 'and the jaw breaker', 'fortune-telling kid', 'lunar orb for sale', 'shrooms for moon rock', 'moon boy plays ball again', 'the Moon Pearl'),
|
||||
'Cane of Somaria': (True, False, None, 0x15, 250, 'Cane of Somaria!\nMake blocks, throw blocks', 'and the red blocks', 'the block-making kid', 'block stick for sale', 'block stick for trade', 'cane boy makes blocks again', 'the Red Cane'),
|
||||
'Fire Rod': (True, False, None, 0x07, 250, 'Fire Rod!\nI\'m burning for you!', 'and the flamethrower', 'fire-starting kid', 'rage rod for sale', 'fungus for rage-rod', 'firestarter boy burns again', 'the Fire Rod'),
|
||||
'Flippers': (True, False, None, 0x1E, 250, 'Flippers!\nFancy a swim?', 'and the toewebs', 'the swimming kid', 'finger webs for sale', 'shrooms let you swim', 'swimming boy swims again', 'the Flippers'),
|
||||
'Ice Rod': (True, False, None, 0x08, 250, 'Ice Rod!\nActivate Freeze Ray!', 'and the freeze ray', 'the ice-bending kid', 'freeze ray for sale', 'fungus for ice-rod', 'ice-cube boy freezes again', 'the Ice Rod'),
|
||||
'Titans Mitts': (True, False, None, 0x1C, 200, 'Mitts!\nLift ALL the rocks!', 'and the golden glove', 'body-building kid', 'carry glove for sale', 'fungus for bling-gloves', 'body-building boy has gold again', 'the Mitts'),
|
||||
'Bombos': (True, False, None, 0x0F, 100, 'Bombos!\nExplosions! Fire!\nBurn it all!', 'and the swirly coin', 'coin-collecting kid', 'swirly coin for sale', 'shrooms for swirly-coin', 'medallion boy melts room again', 'Bombos'),
|
||||
'Ether': (True, False, None, 0x10, 100, 'Ether!\nLet\'s cool things down!', 'and the bolt coin', 'coin-collecting kid', 'bolt coin for sale', 'shrooms for bolt-coin', 'medallion boy sees floor again', 'Ether'),
|
||||
'Quake': (True, False, None, 0x11, 100, 'Quake!\nLet\'s shake the ground!', 'and the wavy coin', 'coin-collecting kid', 'wavy coin for sale', 'shrooms for wavy-coin', 'medallion boy shakes dirt again', 'Quake'),
|
||||
'Bottle': (True, False, None, 0x16, 50, 'Bottle!\nStore all manner of things!', 'and the terrarium', 'the terrarium kid', 'terrarium for sale', 'special promotion', 'bottle boy has terrarium again', 'a bottle'),
|
||||
'Bottle (Red Potion)': (True, False, None, 0x2B, 70, 'Red Potion!\nFill your hearts!', 'and the red goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has red goo again', 'a bottle'),
|
||||
'Bottle (Green Potion)': (True, False, None, 0x2C, 60, 'Green Potion!\nRestore your magic!', 'and the green goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has green goo again', 'a bottle'),
|
||||
'Bottle (Blue Potion)': (True, False, None, 0x2D, 80, 'Blue Potion!\nHeal and restore!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a bottle'),
|
||||
'Bottle (Fairy)': (True, False, None, 0x3D, 70, 'Fairy Bottle!\nI\'ll save your life!', 'and the captive', 'the tingle kid', 'hostage for sale', 'fairy dust and shrooms', 'bottle boy has friend again', 'a bottle'),
|
||||
'Bottle (Bee)': (True, False, None, 0x3C, 50, 'Bee Bottle!\nI\'ll sting your enemies a bit!', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bottle'),
|
||||
'Bottle (Good Bee)': (True, False, None, 0x48, 60, 'Good Bee Bottle!\nI\'ll sting your enemies\na whole lot!', 'and the sparkle sting', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has beetor again', 'a bottle'),
|
||||
'Master Sword': (True, False, 'Sword', 0x50, 100, 'Master Sword!\nEvil\'s bane!', 'and the master sword', 'sword-wielding kid', 'glow sword for sale', 'fungus for blue slasher', 'sword boy fights again', 'the Master Sword'),
|
||||
'Tempered Sword': (True, False, 'Sword', 0x02, 150, 'Tempered Sword!\nMore slashy!', 'the tempered sword', 'sword-wielding kid', 'flame sword for sale', 'fungus for red slasher', 'sword boy fights again', 'the Tempered Sword'),
|
||||
'Fighter Sword': (True, False, 'Sword', 0x49, 50, 'Fighter Sword!\nStarter level slashy!', 'the tiny sword', 'sword-wielding kid', 'tiny sword for sale', 'fungus for tiny slasher', 'sword boy fights again', 'the Fighter Sword'),
|
||||
'Sword and Shield': (True, False, 'Sword', 0x00, 'Sword and Shield!\nUncle sword ahoy!', 'the sword and shield', 'sword and shield-wielding kid', 'training set for sale', 'fungus for training set', 'sword and shield boy fights again', 'the small sword and shield'),
|
||||
'Golden Sword': (True, False, 'Sword', 0x03, 200, 'Golden Sword!\nBest slashy!', 'and the butter sword', 'sword-wielding kid', 'butter for sale', 'cap churned to butter', 'sword boy fights again', 'the Golden Sword'),
|
||||
'Progressive Sword': (True, False, 'Sword', 0x5E, 150, 'Sword!\nA better sword for your time!', 'the unknown sword', 'sword-wielding kid', 'sword for sale', 'fungus for some slasher', 'sword boy fights again', 'a Sword'),
|
||||
'Progressive Glove': (True, False, None, 0x61, 150, 'Glove!\nLift more than you can now!', 'and the lift upgrade', 'body-building kid', 'some glove for sale', 'fungus for gloves', 'body-building boy lifts again', 'a Glove'),
|
||||
'Silver Arrows': (True, False, None, 0x58, 100, 'Silver Arrows!\nDefeat Ganon faster!', 'and the ganonsbane', 'ganon-killing kid', 'ganon doom for sale', 'fungus for pork', 'archer boy shines again', 'the Silver Arrows'),
|
||||
'Green Pendant': (True, False, 'Prize', 0x37, 250, 'Green Pendant! Too\nbad Sahasrahla\nwill never see it!', 'and the green pendant', 'pendant kid', 'pendant for sale', 'fungus for pendant', 'pendant boy dabs again', 'a Prize'),
|
||||
'Blue Pendant': (True, False, 'Prize', 0x39, 150, 'Blue Pendant!\nBut how?!', 'and the pendant', 'pendant kid', 'pendant for sale', 'fungus for pendant', 'pendant boy dabs again', 'a Prize'),
|
||||
'Red Pendant': (True, False, 'Prize', 0x38, 150, 'Red Pendant!\nBut how?!', 'and the pendant', 'pendant kid', 'pendant for sale', 'fungus for pendant', 'pendant boy dabs again', 'a Prize'),
|
||||
'Triforce': (True, False, None, 0x6A, 777, 'Triforce!\nGrab me to win!', 'and the triforce', 'victorious kid', 'victory for sale', 'fungus for the win', 'greedy boy wins game again', 'the Triforce'),
|
||||
'Power Star': (True, False, None, 0x6B, 100, 'Power Star!\nA small step\ntowards victory!', 'and the power star', 'star-struck kid', 'star for sale', 'see stars with shroom', 'mario powers up again', 'a Power Star'),
|
||||
'Triforce Piece': (True, False, None, 0x6C, 100, 'Triforce Piece!\nA small step\ntowards victory!', 'and the thirdforce', 'triangular kid', 'triangle for sale', 'fungus for triangle', 'wise boy has triangle again', 'a Triforce piece'),
|
||||
'Crystal 1': (True, False, 'Prize', 0xB1, 200, 'Crystal 1! It\'s very shiny!', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 2': (True, False, 'Prize', 0xB4, 200, 'Crystal 2! It\'s very shiny!', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 3': (True, False, 'Prize', 0xB6, 200, 'Crystal 3! It\'s very shiny!', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 4': (True, False, 'Prize', 0xB5, 200, 'Crystal 4! It\'s very shiny!', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 5': (True, False, 'Prize', 0xB2, 250, 'Crystal 5! It unlocks a bomb!', 'and the red crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 6': (True, False, 'Prize', 0xB0, 250, 'Crystal 6! It unlocks a bomb!', 'and the red crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Crystal 7': (True, False, 'Prize', 0xB3, 200, 'Crystal 7! It\'s very shiny!', 'and the crystal', 'crystal kid', 'crystal for sale', 'fungus for crystal', 'crystal boy sparkles again', 'a Prize'),
|
||||
'Single Arrow': (False, False, None, 0x43, 3, 'Single Arrow!\nDestiny awaits!', 'and the arrow', 'stick-collecting kid', 'sewing needle for sale', 'fungus for arrow', 'archer boy sews again', 'an arrow'),
|
||||
'Arrows (10)': (False, False, None, 0x44, 30, '10 Arrows!\nAn archer\'s bailout!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'ten arrows'),
|
||||
'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, '10 Arrow Upgrade!\nGain 10 more arrow capacity!', '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, '5 Arrow Upgrade!\nGain 5 more arrow capacity!', '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, '1 Bomb!\nBoom boom pow!', '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, 0xD5, 15, '5 Arrows!\nAn archer\'s bailout!', '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, 'Magic Decanter!\nJust a little one', '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, 0xD4, 40, 'Magic Decanter!\nFull refill', '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, 0xD3, 5, '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'),
|
||||
'Bomb Upgrade (+5)': (False, False, None, 0x51, 100, 'Increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
|
||||
'Blue Mail': (False, True, None, 0x22, 50, 'Now you\'re a\nblue elf!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the Blue Mail'),
|
||||
'Red Mail': (False, True, None, 0x23, 100, 'Now you\'re a\nred elf!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the Red Mail'),
|
||||
'Progressive Armor': (False, True, None, 0x60, 50, 'Time for a\nchange of\nclothes?', 'and the unknown hat', 'the protected kid', 'new hat for sale', 'the clothing store', 'tailor boy has threads again', 'some armor'),
|
||||
'Blue Boomerang': (True, False, None, 0x0C, 50, 'No matter what\nyou do, blue\nreturns to you', 'and the bluemarang', 'the bat-throwing kid', 'bent stick for sale', 'fungus for puma-stick', 'throwing boy plays fetch again', 'the Blue Boomerang'),
|
||||
'Red Boomerang': (True, False, None, 0x2A, 50, 'No matter what\nyou do, red\nreturns to you', 'and the badmarang', 'the bat-throwing kid', 'air foil for sale', 'fungus for return-stick', 'magical boy plays fetch again', 'the Red Boomerang'),
|
||||
'Blue Shield': (False, True, None, 0x04, 50, 'Now you can\ndefend against\npebbles!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a Blue Shield'),
|
||||
'Red Shield': (False, True, None, 0x05, 500, 'Now you can\ndefend against\nfireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'a Red Shield'),
|
||||
'Mirror Shield': (True, False, None, 0x06, 200, 'Now you can\ndefend against\nlasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the Mirror Shield'),
|
||||
'Progressive Shield': (True, False, None, 0x5F, 50, 'Have a better\nblocker in\nfront of you', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'),
|
||||
'Bug Catching Net': (True, False, None, 0x21, 50, 'Let\'s catch\nsome bees and\nfaeries!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the Bug Net'),
|
||||
'Cane of Byrna': (True, False, None, 0x18, 50, 'Use this to\nbecome\ninvincible!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the Blue Cane'),
|
||||
'Boss Heart Container': (False, True, None, 0x3E, 40, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Sanctuary Heart Container': (False, True, None, 0x3F, 50, 'Maximum health\nincreased!\nYeah!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Piece of Heart': (False, False, None, 0x17, 10, 'Just a little\npiece of love!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'),
|
||||
'Rupee (1)': (False, False, None, 0x34, 0, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'),
|
||||
'Rupees (5)': (False, False, None, 0x35, 2, 'Just pocket\nchange. Move\nright along.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'),
|
||||
'Rupees (20)': (False, False, None, 0x36, 10, 'Just couch\ncash. Move\nright along.', 'and the couch cash', 'the piggy-bank kid', 'life lesson for sale', 'the witch buying drugs', 'destitute boy has lunch again', 'a red rupee'),
|
||||
'Rupees (50)': (False, False, None, 0x41, 25, 'A rupee pile!\nOkay?', 'and the rupee pile', 'the well-off kid', 'life lesson for sale', 'buying okay drugs', 'destitute boy has dinner again', 'fifty rupees'),
|
||||
'Rupees (100)': (False, False, None, 0x40, 50, 'A rupee stash!\nHell yeah!', 'and the rupee stash', 'the kind-of-rich kid', 'life lesson for sale', 'buying good drugs', 'affluent boy goes drinking again', 'one hundred rupees'),
|
||||
'Rupees (300)': (False, False, None, 0x46, 150, 'A rupee hoard!\nHell yeah!', 'and the rupee hoard', 'the really-rich kid', 'life lesson for sale', 'buying the best drugs', 'fat-cat boy is rich again', 'three hundred rupees'),
|
||||
'Rupoor': (False, False, None, 0x59, 0, 'A debt collector', 'and the toll-booth', 'the toll-booth kid', 'double loss for sale', 'witch stole your rupees', 'affluent boy steals rupees', 'a rupoor'),
|
||||
'Red Clock': (False, True, None, 0x5B, 0, 'A waste of time', 'the ruby clock', 'the ruby-time kid', 'red time for sale', 'for ruby time', 'moment boy travels time again', 'a red clock'),
|
||||
'Blue Clock': (False, True, None, 0x5C, 50, 'A bit of time', 'the sapphire clock', 'sapphire-time kid', 'blue time for sale', 'for sapphire time', 'moment boy time travels again', 'a blue clock'),
|
||||
'Green Clock': (False, True, None, 0x5D, 200, 'A lot of time', 'the emerald clock', 'the emerald-time kid', 'green time for sale', 'for emerald time', 'moment boy adjusts time again', 'a red clock'),
|
||||
'Bombs (3)': (False, False, None, 0x28, 15, '3 Bombs!\nExplosions!\nIn a handy 3-pack', '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, '10 Bombs!\nExplosions!\nIn a thrifty 10-pack', '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, '10 Bomb Upgrade!\nGain 10 more bomb capacity!', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
|
||||
'Bomb Upgrade (+5)': (False, False, None, 0x51, 100, '5 Bomb Upgrade!\nGain 5 more bomb capacity!', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
|
||||
'Blue Mail': (False, True, None, 0x22, 50, 'Blue Mail!\nLess damage activate!', 'and the banana hat', 'the protected kid', 'banana hat for sale', 'the clothing store', 'tailor boy banana hatted again', 'the Blue Mail'),
|
||||
'Red Mail': (False, True, None, 0x23, 100, 'Red Mail!\nEven less damage!', 'and the eggplant hat', 'well-protected kid', 'purple hat for sale', 'the nice clothing store', 'tailor boy fears nothing again', 'the Red Mail'),
|
||||
'Progressive Armor': (False, True, None, 0x60, 50, 'Upgrade Mail!\nNot the kind you read!', 'and the unknown hat', 'the protected kid', 'new hat for sale', 'the clothing store', 'tailor boy has threads again', 'some armor'),
|
||||
'Blue Boomerang': (True, False, None, 0x0C, 50, 'Blue Boomerang!\nAlways comes back!', 'and the bluemarang', 'the bat-throwing kid', 'bent stick for sale', 'fungus for puma-stick', 'throwing boy plays fetch again', 'the Blue Boomerang'),
|
||||
'Red Boomerang': (True, False, None, 0x2A, 50, 'Red Boomerang!\nAlways comes back!', 'and the badmarang', 'the bat-throwing kid', 'air foil for sale', 'fungus for return-stick', 'magical boy plays fetch again', 'the Red Boomerang'),
|
||||
'Blue Shield': (False, True, None, 0x04, 50, 'Blue Shield!\nBlock rocks!', 'and the stone blocker', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a blue shield'),
|
||||
'Red Shield': (False, True, None, 0x05, 500, 'Red Shield!\nBlock fireballs!', 'and the shot blocker', 'shield-wielding kid', 'fire shield for sale', 'fungus for fire shield', 'shield boy defends again', 'the Red Shield'),
|
||||
'Mirror Shield': (True, False, None, 0x06, 200, 'Mirror Shield!\nBlock lasers!', 'and the laser blocker', 'shield-wielding kid', 'face shield for sale', 'fungus for face shield', 'shield boy defends again', 'the Mirror Shield'),
|
||||
'Progressive Shield': (True, False, None, 0x5F, 50, 'Shield!\nA better shield for your time!', 'and the new shield', 'shield-wielding kid', 'shield for sale', 'fungus for shield', 'shield boy defends again', 'a shield'),
|
||||
'Bug Catching Net': (True, False, None, 0x21, 50, 'Bug Net!\nCatch all manner\nof things!', 'and the bee catcher', 'the bug-catching kid', 'stick web for sale', 'fungus for butterflies', 'wrong boy catches bees again', 'the Bug Net'),
|
||||
'Cane of Byrna': (True, False, None, 0x18, 50, 'Cane of Byrna!\nSwirly protection!', 'and the bad cane', 'the spark-making kid', 'spark stick for sale', 'spark-stick for trade', 'cane boy encircles again', 'the Blue Cane'),
|
||||
'Boss Heart Container': (False, True, None, 0x3E, 40, 'Heart Container!\nHealth Increased!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Sanctuary Heart Container': (False, True, None, 0x3F, 50, 'Heart Container!\nHealth Increased!', 'and the full heart', 'the life-giving kid', 'love for sale', 'fungus for life', 'life boy feels love again', 'a heart'),
|
||||
'Piece of Heart': (False, False, None, 0x17, 10, 'Heart Piece!\nOne step closer\nto more health!', 'and the broken heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart piece'),
|
||||
'Rupee (1)': (False, False, None, 0x34, 0, 'Rupees!\nJust pocket\nchange.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a green rupee'),
|
||||
'Rupees (5)': (False, False, None, 0x35, 2, 'Rupees!\nJust pocket\nchange.', 'the pocket change', 'poverty-struck kid', 'life lesson for sale', 'buying cheap drugs', 'destitute boy has snack again', 'a blue rupee'),
|
||||
'Rupees (20)': (False, False, None, 0x36, 10, 'Rupees!\nJust couch\ncash.', 'and the couch cash', 'the piggy-bank kid', 'life lesson for sale', 'the witch buying drugs', 'destitute boy has lunch again', 'a red rupee'),
|
||||
'Rupees (50)': (False, False, None, 0x41, 25, 'Rupees!\nA big pile!', 'and the rupee pile', 'the well-off kid', 'life lesson for sale', 'buying okay drugs', 'destitute boy has dinner again', 'fifty rupees'),
|
||||
'Rupees (100)': (False, False, None, 0x40, 50, 'Rupees!\nA big stash!', 'and the rupee stash', 'the kind-of-rich kid', 'life lesson for sale', 'buying good drugs', 'affluent boy goes drinking again', 'one hundred rupees'),
|
||||
'Rupees (300)': (False, False, None, 0x46, 150, 'Rupees!\nA big hoard!', 'and the rupee hoard', 'the really-rich kid', 'life lesson for sale', 'buying the best drugs', 'fat-cat boy is rich again', 'three hundred rupees'),
|
||||
'Rupoor': (False, False, None, 0x59, 0, 'Rupoor!\nI\'ll take your rupees!', 'and the toll-booth', 'the toll-booth kid', 'double loss for sale', 'witch stole your rupees', 'affluent boy steals rupees', 'a rupoor'),
|
||||
'Red Clock': (False, True, None, 0x5B, 0, 'Red Clock!\nA waste of time.', 'the ruby clock', 'the ruby-time kid', 'red time for sale', 'for ruby time', 'moment boy travels time again', 'a red clock'),
|
||||
'Blue Clock': (False, True, None, 0x5C, 50, 'Blue Clock!\nA bit of time!', 'the sapphire clock', 'sapphire-time kid', 'blue time for sale', 'for sapphire time', 'moment boy time travels again', 'a blue clock'),
|
||||
'Green Clock': (False, True, None, 0x5D, 200, 'Green Clock!\nTons of time!', 'the emerald clock', 'the emerald-time kid', 'green time for sale', 'for emerald time', 'moment boy adjusts time again', 'a red clock'),
|
||||
'Single RNG': (False, True, None, 0x62, 300, 'Something you don\'t yet have', None, None, None, None, 'unknown boy somethings again', 'a new mystery'),
|
||||
'Multi RNG': (False, True, None, 0x63, 100, 'Something you may already have', None, None, None, None, 'unknown boy somethings again', 'a total mystery'),
|
||||
'Magic Upgrade (1/2)': (True, False, None, 0x4E, 50, 'Your magic\npower has been\ndoubled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Half Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Magic Upgrade (1/4)': (True, False, None, 0x4F, 100, 'Your magic\npower has been\nquadrupled!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Quarter Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Small Key (Eastern Palace)': (False, False, 'SmallKey', 0xA2, 40, 'A small key to Armos Knights', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Eastern Palace'),
|
||||
'Big Key (Eastern Palace)': (False, False, 'BigKey', 0x9D, 60, 'A big key to Armos Knights', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Eastern Palace'),
|
||||
'Compass (Eastern Palace)': (False, True, 'Compass', 0x8D, 10, 'Now you can find the Armos Knights!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Eastern Palace'),
|
||||
'Map (Eastern Palace)': (False, True, 'Map', 0x7D, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Eastern Palace'),
|
||||
'Small Key (Desert Palace)': (False, False, 'SmallKey', 0xA3, 40, 'A small key to the desert', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Desert Palace'),
|
||||
'Big Key (Desert Palace)': (False, False, 'BigKey', 0x9C, 60, 'A big key to the desert', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Desert Palace'),
|
||||
'Compass (Desert Palace)': (False, True, 'Compass', 0x8C, 10, 'Now you can find Lanmolas!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Desert Palace'),
|
||||
'Map (Desert Palace)': (False, True, 'Map', 0x7C, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Desert Palace'),
|
||||
'Small Key (Tower of Hera)': (False, False, 'SmallKey', 0xAA, 40, 'A small key to Hera', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Tower of Hera'),
|
||||
'Big Key (Tower of Hera)': (False, False, 'BigKey', 0x95, 60, 'A big key to Hera', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Tower of Hera'),
|
||||
'Compass (Tower of Hera)': (False, True, 'Compass', 0x85, 10, 'Now you can find Moldorm!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Tower of Hera'),
|
||||
'Map (Tower of Hera)': (False, True, 'Map', 0x75, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Tower of Hera'),
|
||||
'Small Key (Escape)': (False, False, 'SmallKey', 0xA0, 40, 'A small key to the castle', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Hyrule Castle'),
|
||||
'Big Key (Escape)': (False, False, 'BigKey', 0x9F, 60, 'A big key to the castle', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Hyrule Castle'),
|
||||
'Compass (Escape)': (False, True, 'Compass', 0x8F, 10, 'Now you can find no boss!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a Compass to Hyrule Castle'),
|
||||
'Map (Escape)': (False, True, 'Map', 0x7F, 10, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Hyrule Castle'),
|
||||
'Small Key (Agahnims Tower)': (False, False, 'SmallKey', 0xA4, 40, 'A small key to Agahnim', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Castle Tower'),
|
||||
'Big Key (Agahnims Tower)': (False, False, 'BigKey', 0x9B, 60, 'A big key to Agahnim', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Castle Tower'),
|
||||
'Compass (Agahnims Tower)': (False, True, 'Compass', 0x8B, 10, 'Now you can find Aga1!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a Compass to Castle Tower'),
|
||||
'Map (Agahnims Tower)': (False, True, 'Map', 0x7B, 10, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Castle Tower'),
|
||||
'Small Key (Palace of Darkness)': (False, False, 'SmallKey', 0xA6, 40, 'A small key to darkness', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Palace of Darkness'),
|
||||
'Big Key (Palace of Darkness)': (False, False, 'BigKey', 0x99, 60, 'A big key to darkness', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Palace of Darkness'),
|
||||
'Compass (Palace of Darkness)': (False, True, 'Compass', 0x89, 10, 'Now you can find Helmasaur King!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Palace of Darkness'),
|
||||
'Map (Palace of Darkness)': (False, True, 'Map', 0x79, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Palace of Darkness'),
|
||||
'Small Key (Thieves Town)': (False, False, 'SmallKey', 0xAB, 40, 'A small key to thievery', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Thieves\' Town'),
|
||||
'Big Key (Thieves Town)': (False, False, 'BigKey', 0x94, 60, 'A big key to thievery', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Thieves\' Town'),
|
||||
'Compass (Thieves Town)': (False, True, 'Compass', 0x84, 10, 'Now you can find Blind!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Thieves\' Town'),
|
||||
'Map (Thieves Town)': (False, True, 'Map', 0x74, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Thieves\' Town'),
|
||||
'Small Key (Skull Woods)': (False, False, 'SmallKey', 0xA8, 40, 'A small key to the woods', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Skull Woods'),
|
||||
'Big Key (Skull Woods)': (False, False, 'BigKey', 0x97, 60, 'A big key to the woods', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Skull Woods'),
|
||||
'Compass (Skull Woods)': (False, True, 'Compass', 0x87, 10, 'Now you can find Mothula!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Skull Woods'),
|
||||
'Map (Skull Woods)': (False, True, 'Map', 0x77, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Skull Woods'),
|
||||
'Small Key (Swamp Palace)': (False, False, 'SmallKey', 0xA5, 40, 'A small key to the swamp', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Swamp Palace'),
|
||||
'Big Key (Swamp Palace)': (False, False, 'BigKey', 0x9A, 60, 'A big key to the swamp', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Swamp Palace'),
|
||||
'Compass (Swamp Palace)': (False, True, 'Compass', 0x8A, 10, 'Now you can find Arrghus!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Swamp Palace'),
|
||||
'Map (Swamp Palace)': (False, True, 'Map', 0x7A, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Swamp Palace'),
|
||||
'Small Key (Ice Palace)': (False, False, 'SmallKey', 0xA9, 40, 'A small key to the iceberg', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Ice Palace'),
|
||||
'Big Key (Ice Palace)': (False, False, 'BigKey', 0x96, 60, 'A big key to the iceberg', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Ice Palace'),
|
||||
'Compass (Ice Palace)': (False, True, 'Compass', 0x86, 10, 'Now you can find Kholdstare!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Ice Palace'),
|
||||
'Map (Ice Palace)': (False, True, 'Map', 0x76, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Ice Palace'),
|
||||
'Small Key (Misery Mire)': (False, False, 'SmallKey', 0xA7, 40, 'A small key to the mire', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Misery Mire'),
|
||||
'Big Key (Misery Mire)': (False, False, 'BigKey', 0x98, 60, 'A big key to the mire', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Misery Mire'),
|
||||
'Compass (Misery Mire)': (False, True, 'Compass', 0x88, 10, 'Now you can find Vitreous!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Misery Mire'),
|
||||
'Map (Misery Mire)': (False, True, 'Map', 0x78, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Misery Mire'),
|
||||
'Small Key (Turtle Rock)': (False, False, 'SmallKey', 0xAC, 40, 'A small key to the pipe maze', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Turtle Rock'),
|
||||
'Big Key (Turtle Rock)': (False, False, 'BigKey', 0x93, 60, 'A big key to the pipe maze', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Turtle Rock'),
|
||||
'Compass (Turtle Rock)': (False, True, 'Compass', 0x83, 10, 'Now you can find Trinexx!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Turtle Rock'),
|
||||
'Map (Turtle Rock)': (False, True, 'Map', 0x73, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Turtle Rock'),
|
||||
'Small Key (Ganons Tower)': (False, False, 'SmallKey', 0xAD, 40, 'A small key to the evil tower', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key to Ganon\'s Tower'),
|
||||
'Big Key (Ganons Tower)': (False, False, 'BigKey', 0x92, 60, 'A big key to the evil tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a Big Key to Ganon\'s Tower'),
|
||||
'Compass (Ganons Tower)': (False, True, 'Compass', 0x82, 10, 'Now you can find Agahnim!', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a Compass to Ganon\'s Tower'),
|
||||
'Magic Upgrade (1/2)': (True, False, None, 0x4E, 50, 'Half Magic!\nDouble your magic power!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Half Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Magic Upgrade (1/4)': (True, False, None, 0x4F, 100, 'Quarter Magic!\nMagic is basically free now!', 'and the spell power', 'the magic-saving kid', 'wizardry for sale', 'mekalekahi mekahiney ho', 'magic boy saves magic again', 'Quarter Magic'), # can be required to beat mothula in an open seed in very very rare circumstance
|
||||
'Small Key (Eastern Palace)': (False, False, 'SmallKey', 0xA2, 40, 'A small key for\nEastern Palace', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Eastern Palace'),
|
||||
'Big Key (Eastern Palace)': (False, False, 'BigKey', 0x9D, 60, 'A big key for\nEastern Palace', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Eastern Palace'),
|
||||
'Compass (Eastern Palace)': (False, True, 'Compass', 0x8D, 10, 'A compass for\nEastern Palace', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Eastern Palace'),
|
||||
'Map (Eastern Palace)': (False, True, 'Map', 0x7D, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Eastern Palace'),
|
||||
'Small Key (Desert Palace)': (False, False, 'SmallKey', 0xA3, 40, 'A small key for\nDesert Palace', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Desert Palace'),
|
||||
'Big Key (Desert Palace)': (False, False, 'BigKey', 0x9C, 60, 'A big key for\nDesert Palace', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Desert Palace'),
|
||||
'Compass (Desert Palace)': (False, True, 'Compass', 0x8C, 10, 'A compass for\nDesert Palace', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Desert Palace'),
|
||||
'Map (Desert Palace)': (False, True, 'Map', 0x7C, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Desert Palace'),
|
||||
'Small Key (Tower of Hera)': (False, False, 'SmallKey', 0xAA, 40, 'A small key for\nTower of Hera', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Tower of Hera'),
|
||||
'Big Key (Tower of Hera)': (False, False, 'BigKey', 0x95, 60, 'A big key for\nTower of Hera', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Tower of Hera'),
|
||||
'Compass (Tower of Hera)': (False, True, 'Compass', 0x85, 10, 'A compass for\nTower of Hera', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Tower of Hera'),
|
||||
'Map (Tower of Hera)': (False, True, 'Map', 0x75, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Tower of Hera'),
|
||||
'Small Key (Escape)': (False, False, 'SmallKey', 0xA0, 40, 'A small key for\nHyrule Castle', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Hyrule Castle'),
|
||||
'Big Key (Escape)': (False, False, 'BigKey', 0x9F, 60, 'A big key for\nHyrule Castle', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Hyrule Castle'),
|
||||
'Compass (Escape)': (False, True, 'Compass', 0x8F, 10, 'A compass for\nHyrule Castle', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Hyrule Castle'),
|
||||
'Map (Escape)': (False, True, 'Map', 0x7F, 10, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Hyrule Castle'),
|
||||
'Small Key (Agahnims Tower)': (False, False, 'SmallKey', 0xA4, 40, 'A small key for\nAgahnim\'s Tower', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Castle Tower'),
|
||||
'Big Key (Agahnims Tower)': (False, False, 'BigKey', 0x9B, 60, 'A big key for\nAgahnim\'s Tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Castle Tower'),
|
||||
'Compass (Agahnims Tower)': (False, True, 'Compass', 0x8B, 10, 'A compass for\nAgahnim\'s Tower', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds null again', 'a compass to Castle Tower'),
|
||||
'Map (Agahnims Tower)': (False, True, 'Map', 0x7B, 10, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Castle Tower'),
|
||||
'Small Key (Palace of Darkness)': (False, False, 'SmallKey', 0xA6, 40, 'A small key for\nDark Palace', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Palace of Darkness'),
|
||||
'Big Key (Palace of Darkness)': (False, False, 'BigKey', 0x99, 60, 'A big key for\nDark Palace', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Palace of Darkness'),
|
||||
'Compass (Palace of Darkness)': (False, True, 'Compass', 0x89, 10, 'A compass for\nDark Palace', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Palace of Darkness'),
|
||||
'Map (Palace of Darkness)': (False, True, 'Map', 0x79, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Palace of Darkness'),
|
||||
'Small Key (Thieves Town)': (False, False, 'SmallKey', 0xAB, 40, 'A small key for\nThieves Town', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Thieves\' Town'),
|
||||
'Big Key (Thieves Town)': (False, False, 'BigKey', 0x94, 60, 'A big key for\nThieves Town', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Thieves\' Town'),
|
||||
'Compass (Thieves Town)': (False, True, 'Compass', 0x84, 10, 'A compass for\nThieves Town', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Thieves\' Town'),
|
||||
'Map (Thieves Town)': (False, True, 'Map', 0x74, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Thieves\' Town'),
|
||||
'Small Key (Skull Woods)': (False, False, 'SmallKey', 0xA8, 40, 'A small key for\nSkull Woods', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Skull Woods'),
|
||||
'Big Key (Skull Woods)': (False, False, 'BigKey', 0x97, 60, 'A big key for\nSkull Woods', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Skull Woods'),
|
||||
'Compass (Skull Woods)': (False, True, 'Compass', 0x87, 10, 'A compass for\nSkull Woods', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Skull Woods'),
|
||||
'Map (Skull Woods)': (False, True, 'Map', 0x77, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Skull Woods'),
|
||||
'Small Key (Swamp Palace)': (False, False, 'SmallKey', 0xA5, 40, 'A small key for\nSwamp Palace', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Swamp Palace'),
|
||||
'Big Key (Swamp Palace)': (False, False, 'BigKey', 0x9A, 60, 'A big key for\nSwamp Palace', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Swamp Palace'),
|
||||
'Compass (Swamp Palace)': (False, True, 'Compass', 0x8A, 10, 'A compass for\nSwamp Palace', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Swamp Palace'),
|
||||
'Map (Swamp Palace)': (False, True, 'Map', 0x7A, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Swamp Palace'),
|
||||
'Small Key (Ice Palace)': (False, False, 'SmallKey', 0xA9, 40, 'A small key for\nIce Palace', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ice Palace'),
|
||||
'Big Key (Ice Palace)': (False, False, 'BigKey', 0x96, 60, 'A big key for\nIce Palace', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ice Palace'),
|
||||
'Compass (Ice Palace)': (False, True, 'Compass', 0x86, 10, 'A compass for\nIce Palace', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ice Palace'),
|
||||
'Map (Ice Palace)': (False, True, 'Map', 0x76, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Ice Palace'),
|
||||
'Small Key (Misery Mire)': (False, False, 'SmallKey', 0xA7, 40, 'A small key for\nMisery Mire', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Misery Mire'),
|
||||
'Big Key (Misery Mire)': (False, False, 'BigKey', 0x98, 60, 'A big key for\nMisery Mire', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Misery Mire'),
|
||||
'Compass (Misery Mire)': (False, True, 'Compass', 0x88, 10, 'A compass for\nMisery Mire', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Misery Mire'),
|
||||
'Map (Misery Mire)': (False, True, 'Map', 0x78, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Misery Mire'),
|
||||
'Small Key (Turtle Rock)': (False, False, 'SmallKey', 0xAC, 40, 'A small key for\nTurtle Rock', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Turtle Rock'),
|
||||
'Big Key (Turtle Rock)': (False, False, 'BigKey', 0x93, 60, 'A big key for\nTurtle Rock', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Turtle Rock'),
|
||||
'Compass (Turtle Rock)': (False, True, 'Compass', 0x83, 10, 'A compass for\nTurtle Rock', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Turtle Rock'),
|
||||
'Map (Turtle Rock)': (False, True, 'Map', 0x73, 20, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a map to Turtle Rock'),
|
||||
'Small Key (Ganons Tower)': (False, False, 'SmallKey', 0xAD, 40, 'A small key for\nGanon\'s Tower', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a small key to Ganon\'s Tower'),
|
||||
'Big Key (Ganons Tower)': (False, False, 'BigKey', 0x92, 60, 'A big key for\nGanon\'s Tower', 'and the big key', 'the big-unlock kid', 'big key for sale', 'face key fungus', 'key boy opens chest again', 'a big key to Ganon\'s Tower'),
|
||||
'Compass (Ganons Tower)': (False, True, 'Compass', 0x82, 10, 'A compass for\nGanon\'s Tower', 'and the compass', 'the magnetic kid', 'compass for sale', 'magnetic fungus', 'compass boy finds boss again', 'a compass to Ganon\'s Tower'),
|
||||
'Map (Ganons Tower)': (False, True, 'Map', 0x72, 10, 'A tightly folded map rests here', 'and the map', 'cartography kid', 'map for sale', 'a map to shrooms', 'map boy navigates again', 'a Map to Ganon\'s Tower'),
|
||||
'Small Key (Universal)': (False, True, None, 0xAF, 100, 'A small key for any door', 'and the key', 'the unlocking kid', 'keys for sale', 'unlock the fungus', 'key boy opens door again', 'a Small Key'),
|
||||
'Nothing': (False, False, None, 0x5A, 1, 'Some Hot Air', 'and the Nothing', 'the zen kid', 'outright theft', 'shroom theft', 'empty boy is bored again', 'nothing'),
|
||||
|
||||
+3
-3
@@ -2137,11 +2137,11 @@ def validate_key_placement(key_layout, world, player):
|
||||
if key_layout.prize_relevant:
|
||||
found_prize = any(x for x in counter.important_locations if x.prize)
|
||||
if not found_prize and dungeon_table[key_layout.sector.name].prize:
|
||||
prize_loc = dungeon_table[key_layout.sector.name].prize.location
|
||||
prize_dungeon = [d for d in world.dungeons if d.name == key_layout.sector.name][0]
|
||||
if key_layout.prize_relevant == 'BigBomb':
|
||||
found_prize = prize_loc.item.name not in ['Crystal 5', 'Crystal 6']
|
||||
found_prize = prize_dungeon.prize.name not in ['Crystal 5', 'Crystal 6']
|
||||
elif key_layout.prize_relevant == 'GT':
|
||||
found_prize = 'Crystal' not in prize_loc.item.name or world.crystals_needed_for_gt[player] < 7
|
||||
found_prize = 'Crystal' not in prize_dungeon.prize.name or world.crystals_needed_for_gt[player] < 7
|
||||
else:
|
||||
found_prize = False
|
||||
can_progress = (not counter.big_key_opened and big_found and any(d.bigKey for d in counter.child_doors)) or \
|
||||
|
||||
@@ -40,7 +40,7 @@ from source.enemizer.DamageTables import DamageTable
|
||||
from source.enemizer.Enemizer import randomize_enemies
|
||||
from source.rom.DataTables import init_data_tables
|
||||
|
||||
version_number = '1.4.1.12'
|
||||
version_number = '1.4.5'
|
||||
version_branch = '-u'
|
||||
__version__ = f'{version_number}{version_branch}'
|
||||
|
||||
@@ -161,7 +161,7 @@ def main(args, seed=None, fish=None):
|
||||
if world.spoiler_mode != 'none' and not args.jsonout:
|
||||
logger.info(world.fish.translate("cli", "cli", "create.meta"))
|
||||
world.spoiler.meta_to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
||||
if args.mystery and not (args.suppress_meta or args.create_spoiler):
|
||||
if args.mystery and not (args.suppress_meta or args.spoiler != 'none'):
|
||||
world.spoiler.mystery_meta_to_file(output_path(f'{outfilebase}_meta.txt'))
|
||||
|
||||
for player in range(1, world.players + 1):
|
||||
@@ -362,7 +362,7 @@ def main(args, seed=None, fish=None):
|
||||
with open(output_path('%s_multidata' % outfilebase), 'wb') as f:
|
||||
f.write(multidata)
|
||||
|
||||
if args.mystery and not (args.suppress_meta or args.create_spoiler):
|
||||
if args.mystery and not (args.suppress_meta or args.spoiler not in ['full']):
|
||||
world.spoiler.hashes_to_file(output_path(f'{outfilebase}_meta.txt'))
|
||||
elif world.spoiler_mode != 'none' and not args.jsonout:
|
||||
world.spoiler.hashes_to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
||||
@@ -495,6 +495,8 @@ def init_world(args, fish):
|
||||
world.standardize_palettes = args.standardize_palettes.copy()
|
||||
world.shufflelinks = args.shufflelinks.copy()
|
||||
world.shuffletavern = args.shuffletavern.copy()
|
||||
world.skullwoods = args.skullwoods.copy()
|
||||
world.linked_drops = args.linked_drops.copy()
|
||||
world.pseudoboots = args.pseudoboots.copy()
|
||||
world.overworld_map = args.overworld_map.copy()
|
||||
world.take_any = args.take_any.copy()
|
||||
@@ -522,7 +524,18 @@ def set_starting_inventory(world, args):
|
||||
if inv_list:
|
||||
for inv_item in inv_list:
|
||||
name = inv_item.strip()
|
||||
name = name if name != 'Ocarina' or world.flute_mode[player] != 'active' else 'Ocarina (Activated)'
|
||||
if inv_item == 'RandomWeapon':
|
||||
name = random.choice(['Progressive Bow', 'Hammer', 'Progressive Sword', 'Cane of Somaria', 'Cane of Byrna', 'Fire Rod'])
|
||||
extra = []
|
||||
if name in ['Cane of Somaria', 'Cane of Byrna', 'Fire Rod']:
|
||||
extra.append('Big Magic')
|
||||
if name == 'Progressive Bow':
|
||||
extra.extend(['Arrows (10)'] * 3)
|
||||
for e in extra:
|
||||
item = ItemFactory(e, p)
|
||||
if item:
|
||||
world.push_precollected(item)
|
||||
name = name if name != 'Ocarina' or world.flute_mode[p] != 'active' else 'Ocarina (Activated)'
|
||||
item = ItemFactory(name, p)
|
||||
if item:
|
||||
world.push_precollected(item)
|
||||
|
||||
+2
-2
@@ -344,7 +344,7 @@ location_table_boss = {'Eastern Palace - Prize': 0x2000,
|
||||
'Desert Palace - Prize': 0x1000,
|
||||
'Tower of Hera - Prize': 0x0020,
|
||||
'Palace of Darkness - Prize': 0x0200,
|
||||
'Thieves Town - Prize': 0x0010,
|
||||
'Thieves\' Town - Prize': 0x0010,
|
||||
'Skull Woods - Prize': 0x0080,
|
||||
'Swamp Palace - Prize': 0x0400,
|
||||
'Ice Palace - Prize': 0x0040,
|
||||
@@ -1097,7 +1097,7 @@ async def game_watcher(ctx : Context):
|
||||
|
||||
async def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--snes', default='localhost:8080', help='Address of the QUsb2snes server.')
|
||||
parser.add_argument('--snes', default='localhost:23074', help='Address of the QUsb2snes/SNI server.')
|
||||
parser.add_argument('--connect', default=None, help='Address of the multiworld host.')
|
||||
parser.add_argument('--password', default=None, help='Password of the multiworld host.')
|
||||
parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical'])
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType
|
||||
from OverworldGlitchRules import create_owg_connections
|
||||
from Utils import bidict
|
||||
|
||||
version_number = '0.5.0.1'
|
||||
version_number = '0.5.0.2'
|
||||
# branch indicator is intentionally different across branches
|
||||
version_branch = ''
|
||||
|
||||
@@ -1151,7 +1151,7 @@ def define_tile_groups(world, do_grouped, player):
|
||||
merge_groups([[0x13, 0x14, 0x1b]])
|
||||
|
||||
# sanctuary and grave connector
|
||||
if world.shuffle[player] in ['dungeonssimple', 'dungeonsfull', 'simple', 'restricted', 'full', 'lite']:
|
||||
if world.shuffle[player] in ['dungeonssimple', 'dungeonsfull', 'simple', 'restricted', 'full', 'lite', 'district']:
|
||||
merge_groups([[0x13, 0x14]])
|
||||
|
||||
# cross-screen connector
|
||||
@@ -1499,7 +1499,7 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F
|
||||
elif exit.connected_region.name not in explored_regions \
|
||||
and (exit.connected_region.type == region.type
|
||||
or exit.name in OWExitTypes['OWEdge'] or (cross_world and exit.name in (OWExitTypes['Portal'] + OWExitTypes['Mirror']))) \
|
||||
and (not region_rules or exit.access_rule(blank_state)) and (not ignore_ledges or exit.name not in OWExitTypes['Ledge', 'OWG']):
|
||||
and (not region_rules or exit.access_rule(blank_state)) and (not ignore_ledges or exit.name not in (OWExitTypes['Ledge'] + OWExitTypes['OWG'])):
|
||||
explore_region(exit.connected_region.name, exit.connected_region)
|
||||
|
||||
if build_copy_world:
|
||||
|
||||
@@ -87,7 +87,7 @@ def main(args):
|
||||
outfilebase = 'Plando_%s_%s' % (os.path.splitext(os.path.basename(args.plando))[0], world.seed)
|
||||
|
||||
rom.write_to_file('%s.sfc' % outfilebase)
|
||||
if args.create_spoiler:
|
||||
if args.spoiler != 'none':
|
||||
world.spoiler.to_file('%s_Spoiler.txt' % outfilebase)
|
||||
|
||||
logger.info('Done. Enjoy.')
|
||||
@@ -178,7 +178,7 @@ def prefill_world(world, plando, text_patches):
|
||||
world.fix_trock_exit = {1: trfstr.strip().lower() == 'true'}
|
||||
elif line.startswith('!fix_gtower_exit'):
|
||||
_, gtfstr = line.split(':', 1)
|
||||
world.fix_gtower_exit = gtfstr.strip().lower() == 'true'
|
||||
world.fix_gtower_exit = {1: gtfstr.strip().lower() == 'true'}
|
||||
elif line.startswith('!fix_pod_exit'):
|
||||
_, podestr = line.split(':', 1)
|
||||
world.fix_palaceofdarkness_exit = {1: podestr.strip().lower() == 'true'}
|
||||
@@ -223,7 +223,7 @@ def prefill_world(world, plando, text_patches):
|
||||
|
||||
def start():
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--create_spoiler', help='Output a Spoiler File', action='store_true')
|
||||
parser.add_argument('--spoiler', default='none', help='Output a Spoiler File')
|
||||
parser.add_argument('--ignore_unsolvable', help='Do not abort if seed is deemed unsolvable.', action='store_true')
|
||||
parser.add_argument('--rom', default='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', help='Path to an ALttP JAP(1.0) rom to use as a base.')
|
||||
parser.add_argument('--loglevel', default='info', const='info', nargs='?', choices=['error', 'info', 'warning', 'debug'], help='Select level of logging for output.')
|
||||
|
||||
+6
-5
@@ -1240,11 +1240,12 @@ def adjust_locations(world, player):
|
||||
index += 1
|
||||
setup_enemy_locations(world, player)
|
||||
# disable forced prize locations
|
||||
if world.prizeshuffle[player] != 'none':
|
||||
for l in [name for name, data in location_table.items() if data[2]]:
|
||||
location = world.get_location_unsafe(l, player)
|
||||
if location:
|
||||
location.prize = False
|
||||
prize_on_boss = world.prizeshuffle[player] == 'none'
|
||||
for l in [name for name, data in location_table.items() if data[2]]:
|
||||
location = world.get_location_unsafe(l, player)
|
||||
if location:
|
||||
location.prize = prize_on_boss
|
||||
location.real = not prize_on_boss
|
||||
# unreal events:
|
||||
for l in ['Ganon', 'Zelda Pickup', 'Zelda Drop Off'] + list(location_events):
|
||||
location = world.get_location_unsafe(l, player)
|
||||
|
||||
@@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '87be9d9bd56b6ad8e4b9697ecfc31841'
|
||||
RANDOMIZERBASEHASH = 'c0c4b8166fbe9b637a0aaa82e3f4cb8d'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
@@ -492,6 +492,9 @@ def patch_rom(world, rom, player, team, is_mystery=False):
|
||||
if world.mapshuffle[player]:
|
||||
rom.write_byte(0x155C9, random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle
|
||||
|
||||
if world.doorShuffle[player] != 'vanilla':
|
||||
rom.write_bytes(snes_to_pc(0x0293FE), [0x80, 0x15]) # skip pre-Aga music change
|
||||
|
||||
# fix for swamp drains if necessary
|
||||
swamp1location = world.get_location('Swamp Palace - Trench 1 Pot Key', player)
|
||||
if not swamp1location.pot.indicator:
|
||||
@@ -664,7 +667,7 @@ def patch_rom(world, rom, player, team, is_mystery=False):
|
||||
write_int16(rom, 0x15DB5 + 2 * offset, 0x0640)
|
||||
elif room_id == 0x00d6 and world.fix_trock_exit[player]:
|
||||
write_int16(rom, 0x15DB5 + 2 * offset, 0x0134)
|
||||
elif room_id == 0x000c and world.fix_gtower_exit: # fix ganons tower exit point
|
||||
elif room_id == 0x000c and world.fix_gtower_exit[player]: # fix ganons tower exit point
|
||||
write_int16(rom, 0x15DB5 + 2 * offset, 0x00A4)
|
||||
else:
|
||||
write_int16(rom, 0x15DB5 + 2 * offset, link_y)
|
||||
@@ -889,7 +892,7 @@ def patch_rom(world, rom, player, team, is_mystery=False):
|
||||
rom.write_byte(cr_pc+0x1e, 0xEE) # slash
|
||||
rom.write_byte(cr_pc+0x1f, thousands_bot)
|
||||
# modify stat config
|
||||
stat_address = 0x23978C
|
||||
stat_address = 0x23983E
|
||||
stat_pc = snes_to_pc(stat_address)
|
||||
rom.write_byte(stat_pc, 0xa9) # change to pos 21 (from b1)
|
||||
rom.write_byte(stat_pc+2, 0xc0) # change to 12 bits (from a0)
|
||||
@@ -2704,6 +2707,8 @@ def patch_shuffled_dark_sanc(world, rom, player):
|
||||
dark_sanc = world.get_region('Dark Sanctuary Hint', player)
|
||||
dark_sanc_entrance = str([i for i in dark_sanc.entrances if i.parent_region.name != 'Menu'][0].name)
|
||||
room_id, ow_area, vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x, unknown_1, unknown_2, door_1, door_2 = door_addresses[dark_sanc_entrance][1]
|
||||
if dark_sanc_entrance == 'Tavern North':
|
||||
link_y -= 0x10 # rom code assumes south-facing doors and adds $10 to the y-coordinate
|
||||
door_index = door_addresses[str(dark_sanc_entrance)][0]
|
||||
rom.initial_sram.pre_set_overworld_flag(ow_area, door_addresses[dark_sanc_entrance][2])
|
||||
|
||||
@@ -2719,6 +2724,8 @@ def patch_shuffled_bomb_shop(world, rom, player):
|
||||
bomb_shop = world.get_region('Big Bomb Shop', player)
|
||||
bomb_shop_entrance = str([i for i in bomb_shop.entrances if i.parent_region.name != 'Menu'][0].name)
|
||||
room_id, ow_area, vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x, unknown_1, unknown_2, door_1, door_2 = door_addresses[bomb_shop_entrance][1]
|
||||
if bomb_shop_entrance == 'Tavern North':
|
||||
link_y -= 0x10 # rom code assumes south-facing doors and adds $10 to the y-coordinate
|
||||
door_index = door_addresses[str(bomb_shop_entrance)][0]
|
||||
rom.initial_sram.pre_set_overworld_flag(ow_area, door_addresses[bomb_shop_entrance][2])
|
||||
|
||||
|
||||
@@ -557,11 +557,12 @@ def global_rules(world, player):
|
||||
set_rule(world.get_entrance('Mire Post-Gap Gap', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
||||
set_rule(world.get_entrance('Mire Falling Bridge Hook Path', player), lambda state: state.has_Boots(player) or state.has('Hookshot', player))
|
||||
set_rule(world.get_entrance('Mire Falling Bridge Hook Only Path', player), lambda state: state.has('Hookshot', player))
|
||||
set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.has_sword(player) or
|
||||
(state.has('Fire Rod', player) and (state.can_use_bombs(player) or state.can_extend_magic(player, 9))) or # 9 fr shots or 8 with some bombs
|
||||
(state.has('Ice Rod', player) and state.can_use_bombs(player)) or # freeze popo and throw, bomb to finish
|
||||
state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player)) # need to defeat wizzrobes, bombs don't work ...
|
||||
# byrna could work with sufficient magic
|
||||
# Note: new enemy logic doesn't account for Fire Rod + Bombs or Ice Rod + Bombs yet
|
||||
# set_rule(world.get_entrance('Mire 2 NE', player), lambda state: state.has_sword(player) or
|
||||
# (state.has('Fire Rod', player) and (state.can_use_bombs(player) or state.can_extend_magic(player, 9))) or # 9 fr shots or 8 with some bombs
|
||||
# (state.has('Ice Rod', player) and state.can_use_bombs(player)) or # freeze popo and throw, bomb to finish
|
||||
# state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player)) # need to defeat wizzrobes, bombs don't work ...
|
||||
# byrna could work with sufficient magic
|
||||
set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player))
|
||||
loc = world.get_location('Misery Mire - Spikes Pot Key', player)
|
||||
if loc.pot:
|
||||
@@ -641,10 +642,6 @@ def global_rules(world, player):
|
||||
set_rule(world.get_entrance('GT Ice Armos NE', player), lambda state: world.get_region('GT Ice Armos', player).dungeon.bosses['bottom'].can_defeat(state))
|
||||
set_rule(world.get_entrance('GT Ice Armos WS', player), lambda state: world.get_region('GT Ice Armos', player).dungeon.bosses['bottom'].can_defeat(state))
|
||||
|
||||
set_rule(world.get_entrance('GT Mimics 1 NW', player), lambda state: state.can_shoot_arrows(player))
|
||||
set_rule(world.get_entrance('GT Mimics 1 ES', player), lambda state: state.can_shoot_arrows(player))
|
||||
set_rule(world.get_entrance('GT Mimics 2 WS', player), lambda state: state.can_shoot_arrows(player))
|
||||
set_rule(world.get_entrance('GT Mimics 2 NE', player), lambda state: state.can_shoot_arrows(player))
|
||||
# consider access to refill room - interior doors would need a change
|
||||
set_rule(world.get_entrance('GT Cannonball Bridge SE', player), lambda state: state.has_Boots(player))
|
||||
set_rule(world.get_entrance('GT Lanmolas 2 ES', player), lambda state: world.get_region('GT Lanmolas 2', player).dungeon.bosses['middle'].can_defeat(state))
|
||||
@@ -1531,6 +1528,10 @@ std_kill_rooms = {
|
||||
(['GT Petting Zoo SE'], [], 0x7d, [4, 5, 6, 7, 8, 10]),
|
||||
'GT DMs Room': # Four red stalfos
|
||||
(['GT DMs Room SW'], [], 0x7b, [2, 3, 4, 5, 8, 9, 10]),
|
||||
'GT Mimics 1': # two red mimics
|
||||
(['GT Mimics 1 NW', 'GT Mimics 1 ES'], [], 0x006b, [5, 6, 7, 8, 9]),
|
||||
'GT Mimics 2': # two red mimics
|
||||
(['GT Mimics 2 NE', 'GT Mimics 2 WS'], [], 0x006b, [10, 11, 12, 13]),
|
||||
'GT Gauntlet 1': # Stalfos/zazaks
|
||||
(['GT Gauntlet 1 WN'], [], 0x5d, [3, 4, 5, 6]),
|
||||
'GT Gauntlet 2': # Red stalfos
|
||||
@@ -2017,7 +2018,7 @@ def add_key_logic_rules(world, player):
|
||||
eval_func = eval_small_key_door
|
||||
if world.key_logic_algorithm[player] == 'strict' and world.keyshuffle[player] == 'wild':
|
||||
eval_func = eval_small_key_door_strict
|
||||
elif world.key_logic_algorithm[player] != 'default':
|
||||
elif world.key_logic_algorithm[player] != 'dangerous':
|
||||
eval_func = eval_small_key_door_partial
|
||||
for d_name, d_logic in key_logic.items():
|
||||
for door_name, rule in d_logic.door_rules.items():
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ def main(args=None):
|
||||
['Std ', ' --mode standard'],
|
||||
['Inv ', ' --mode inverted']]:
|
||||
|
||||
basecommand = f"python3.8 DungeonRandomizer.py --door_shuffle {args.dr} --intensity {args.tense} --suppress_rom --suppress_spoiler"
|
||||
basecommand = f"python DungeonRandomizer.py --door_shuffle {args.dr} --intensity {args.tense} --suppress_rom --spoiler none"
|
||||
|
||||
def gen_seed():
|
||||
taskcommand = basecommand + " " + command + mode[1]
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ def main(args=None):
|
||||
alive = 0
|
||||
|
||||
|
||||
basecommand = f'py Mystery.py --suppress_rom --suppress_meta --create_spoiler --outputpath L:/_Work/Zelda/ROMs/Bug/Automate/{datetime.now().strftime("%y%m%d")} --weights L:/_Work/Zelda/ROMs/Bug/Automate/_test.yml'
|
||||
basecommand = f'py Mystery.py --suppress_rom --suppress_meta --spoiler full --outputpath L:/_Work/Zelda/ROMs/Bug/Automate/{datetime.now().strftime("%y%m%d")} --weights L:/_Work/Zelda/ROMs/Bug/Automate/_test.yml'
|
||||
|
||||
def gen_seed():
|
||||
return subprocess.run(basecommand, capture_output=True, shell=True, text=True)
|
||||
|
||||
@@ -1668,50 +1668,50 @@ class TextTable(object):
|
||||
text['potion_shop_no_empty_bottles'] = CompressedTextMapper.convert("Whoa, bucko!\nNo empty bottles.")
|
||||
text['item_get_lamp'] = CompressedTextMapper.convert("Lamp! You can see in the dark, and light torches.")
|
||||
text['item_get_boomerang'] = CompressedTextMapper.convert("Boomerang! Press START to select it.")
|
||||
text['item_get_bow'] = CompressedTextMapper.convert("You're in bow mode now!")
|
||||
text['item_get_shovel'] = CompressedTextMapper.convert("This is my new mop. My friend George, he gave me this mop. It's a pretty good mop. It's not as good as my old mop. I miss my old mop. But it's still a good mop.")
|
||||
text['item_get_magic_cape'] = CompressedTextMapper.convert("Finally! we get to play Invisble Man!")
|
||||
text['item_get_powder'] = CompressedTextMapper.convert("It's the powder. Let's cause some mischief!")
|
||||
text['item_get_flippers'] = CompressedTextMapper.convert("Splish! Splash! Let's go take a bath!")
|
||||
text['item_get_power_gloves'] = CompressedTextMapper.convert("Feel the power! You can now lift light rocks! Rock on!")
|
||||
text['item_get_bow'] = CompressedTextMapper.convert("Bow! Join the archer class!")
|
||||
text['item_get_shovel'] = CompressedTextMapper.convert("Shovel! Can you dig it?")
|
||||
text['item_get_magic_cape'] = CompressedTextMapper.convert("Cape! Invisbility cloak activate!")
|
||||
text['item_get_powder'] = CompressedTextMapper.convert("Powder! Sprinkle it on a dancing pickle!")
|
||||
text['item_get_flippers'] = CompressedTextMapper.convert("Flippers! Time to swim!")
|
||||
text['item_get_power_gloves'] = CompressedTextMapper.convert("Gloves! Lift up those rocks!")
|
||||
text['item_get_pendant_courage'] = CompressedTextMapper.convert("We have the Pendant of Courage! How brave!")
|
||||
text['item_get_pendant_power'] = CompressedTextMapper.convert("We have the Pendant of Power! How robust!")
|
||||
text['item_get_pendant_wisdom'] = CompressedTextMapper.convert("We have the Pendant of Wisdom! How astute!")
|
||||
text['item_get_mushroom'] = CompressedTextMapper.convert("A Mushroom! Don't eat it. Find a witch.")
|
||||
text['item_get_book'] = CompressedTextMapper.convert("It book! U R now litterit!")
|
||||
text['item_get_moonpearl'] = CompressedTextMapper.convert("I found a shiny marble! No more hops!")
|
||||
text['item_get_mushroom'] = CompressedTextMapper.convert("Mushroom! Don't eat it. Find a witch.")
|
||||
text['item_get_book'] = CompressedTextMapper.convert("Book! Are you well read?")
|
||||
text['item_get_moonpearl'] = CompressedTextMapper.convert("Moon Pearl! Rabbit Be Gone!")
|
||||
text['item_get_compass'] = CompressedTextMapper.convert("A compass! I can now find the boss.")
|
||||
# 60
|
||||
text['item_get_map'] = CompressedTextMapper.convert("Yo! You found a MAP! Press X to see it.")
|
||||
text['item_get_ice_rod'] = CompressedTextMapper.convert("It's the Ice Rod! Freeze Ray time.")
|
||||
text['item_get_fire_rod'] = CompressedTextMapper.convert("A Rod that shoots fire? Let's burn all the things!")
|
||||
text['item_get_ether'] = CompressedTextMapper.convert("We can chill out with this!")
|
||||
text['item_get_bombos'] = CompressedTextMapper.convert("Let's set everything on fire, and melt things!")
|
||||
text['item_get_quake'] = CompressedTextMapper.convert("Time to make the earth shake, rattle, and roll!")
|
||||
text['item_get_ice_rod'] = CompressedTextMapper.convert("Ice Rod! Time to chill out!")
|
||||
text['item_get_fire_rod'] = CompressedTextMapper.convert("Fire Rod! I'm burning for you!")
|
||||
text['item_get_ether'] = CompressedTextMapper.convert("Ether! Let's cool things down!")
|
||||
text['item_get_bombos'] = CompressedTextMapper.convert("Bombos! Explosions, fire, burn it all!")
|
||||
text['item_get_quake'] = CompressedTextMapper.convert("Quake! Let's shake the ground!")
|
||||
text['item_get_hammer'] = CompressedTextMapper.convert("STOP!\n\nHammer Time!") # 66
|
||||
text['item_get_ocarina'] = CompressedTextMapper.convert("Finally! We can play the Song of Time!")
|
||||
text['item_get_cane_of_somaria'] = CompressedTextMapper.convert("Make blocks!\nThrow blocks!\nsplode Blocks!")
|
||||
text['item_get_hookshot'] = CompressedTextMapper.convert("BOING!!!\nBOING!!!\nSay no more…")
|
||||
text['item_get_ocarina'] = CompressedTextMapper.convert("Ocarina! A Flute by another name")
|
||||
text['item_get_cane_of_somaria'] = CompressedTextMapper.convert("Somaria! Make blocks, throw blocks")
|
||||
text['item_get_hookshot'] = CompressedTextMapper.convert("Hookshot! Grab all the things!")
|
||||
text['item_get_bombs'] = CompressedTextMapper.convert("BOMBS! Use A to pick 'em up, throw 'em, get hurt!")
|
||||
text['item_get_bottle'] = CompressedTextMapper.convert("It's a terrarium. I hope we find a lizard!")
|
||||
text['item_get_bottle'] = CompressedTextMapper.convert("Bottle! Store all manner of things")
|
||||
text['item_get_big_key'] = CompressedTextMapper.convert("Yo! You got a Big Key!")
|
||||
text['item_get_titans_mitts'] = CompressedTextMapper.convert("So, like, you can now lift anything.\nANYTHING!")
|
||||
text['item_get_magic_mirror'] = CompressedTextMapper.convert("We could stare at this all day or, you know, beat Ganon…")
|
||||
text['item_get_titans_mitts'] = CompressedTextMapper.convert("Mitts! Lift ALL the rocks!")
|
||||
text['item_get_magic_mirror'] = CompressedTextMapper.convert("Mirror! Take some time to reflect on this moment!")
|
||||
text['item_get_fake_mastersword'] = CompressedTextMapper.convert("It's the Master Sword! …or not…\n\n FOOL!")
|
||||
# 70
|
||||
text['post_item_get_mastersword'] = CompressedTextMapper.convert("{NOBORDER}\n{SPEED6}\n@, you got the sword!\n{CHANGEMUSIC}\nNow let's go beat up Agahnim!")
|
||||
text['item_get_red_potion'] = CompressedTextMapper.convert("Red goo to go! Nice!")
|
||||
text['item_get_green_potion'] = CompressedTextMapper.convert("Green goo to go! Nice!")
|
||||
text['item_get_blue_potion'] = CompressedTextMapper.convert("Blue goo to go! Nice!")
|
||||
text['item_get_bug_net'] = CompressedTextMapper.convert("Surprise Net! Let's catch stuff!")
|
||||
text['item_get_blue_mail'] = CompressedTextMapper.convert("Blue threads? Less damage activated!")
|
||||
text['item_get_red_mail'] = CompressedTextMapper.convert("You feel the power of the eggplant on your head.")
|
||||
text['item_get_temperedsword'] = CompressedTextMapper.convert("Nice… I now have a craving for Cheetos.")
|
||||
text['item_get_mirror_shield'] = CompressedTextMapper.convert("Pit would be proud!")
|
||||
text['item_get_cane_of_byrna'] = CompressedTextMapper.convert("It's the Blue Cane. You can now protect yourself with lag!")
|
||||
text['item_get_red_potion'] = CompressedTextMapper.convert("Red Potion! Heal yourself")
|
||||
text['item_get_green_potion'] = CompressedTextMapper.convert("Green Potion! Magic refill!")
|
||||
text['item_get_blue_potion'] = CompressedTextMapper.convert("Blue Potion! Heal and restore!")
|
||||
text['item_get_bug_net'] = CompressedTextMapper.convert("Bug Net! Let's catch stuff!")
|
||||
text['item_get_blue_mail'] = CompressedTextMapper.convert("Blue Mail! Less damage activated!")
|
||||
text['item_get_red_mail'] = CompressedTextMapper.convert("Red Mail! Even less damage!")
|
||||
text['item_get_temperedsword'] = CompressedTextMapper.convert("Tempered Sword! Even more slashy!")
|
||||
text['item_get_mirror_shield'] = CompressedTextMapper.convert("Mirror Shield! Time to reflect")
|
||||
text['item_get_cane_of_byrna'] = CompressedTextMapper.convert("Byrna! Swirly protection!")
|
||||
text['missing_big_key'] = CompressedTextMapper.convert("Something is missing…\nThe Big Key?")
|
||||
text['missing_magic'] = CompressedTextMapper.convert("Something is missing…\nMagic meter?")
|
||||
text['item_get_pegasus_boots'] = CompressedTextMapper.convert("Finally, it's bonking time!\nHold A to dash")
|
||||
text['item_get_pegasus_boots'] = CompressedTextMapper.convert("Pegasus Boots! Finally, it's bonking time!\nHold A to dash")
|
||||
text['talking_tree_info_start'] = CompressedTextMapper.convert("Whoa! I can talk again!")
|
||||
text['talking_tree_info_1'] = CompressedTextMapper.convert("Yank on the pitchfork in the center of town, ya heard it here.")
|
||||
text['talking_tree_info_2'] = CompressedTextMapper.convert("Ganon is such a dingus, no one likes him, ya heard it here.")
|
||||
|
||||
Binary file not shown.
+2
-2
@@ -47,8 +47,8 @@
|
||||
boss: 0
|
||||
oneway: 0
|
||||
key_logic_algorithm:
|
||||
default: 1
|
||||
partial: 0
|
||||
dangerous: 0
|
||||
partial: 1
|
||||
strict: 0
|
||||
decoupledoors: off
|
||||
door_self_loops:
|
||||
|
||||
+10
-1
@@ -25,7 +25,7 @@ trap_door_mode:
|
||||
boss: 1
|
||||
oneway: 1
|
||||
key_logic_algorithm:
|
||||
default: 1
|
||||
dangerous: 1
|
||||
partial: 0
|
||||
strict: 0
|
||||
decoupledoors:
|
||||
@@ -71,6 +71,15 @@ shufflelinks:
|
||||
shuffletavern:
|
||||
on: 1
|
||||
off: 1
|
||||
skullwoods:
|
||||
original: 1
|
||||
restricted: 1
|
||||
loose: 1
|
||||
followlinked: 1
|
||||
linked_drops:
|
||||
unset: 1
|
||||
linked: 1
|
||||
independent: 1
|
||||
world_state:
|
||||
standard: 1
|
||||
open: 1
|
||||
|
||||
@@ -254,7 +254,7 @@
|
||||
},
|
||||
"key_logic_algorithm": {
|
||||
"choices": [
|
||||
"default",
|
||||
"dangerous",
|
||||
"partial",
|
||||
"strict"
|
||||
]
|
||||
@@ -516,6 +516,21 @@
|
||||
"action": "store_true",
|
||||
"type": "bool"
|
||||
},
|
||||
"skullwoods": {
|
||||
"choices": [
|
||||
"original",
|
||||
"restricted",
|
||||
"loose",
|
||||
"followlinked"
|
||||
]
|
||||
},
|
||||
"linked_drops": {
|
||||
"choices": [
|
||||
"unset",
|
||||
"linked",
|
||||
"independent"
|
||||
]
|
||||
},
|
||||
"overworld_map": {
|
||||
"choices": [
|
||||
"default",
|
||||
|
||||
@@ -305,7 +305,7 @@
|
||||
],
|
||||
"key_logic_algorithm": [
|
||||
"Key Logic Algorithm (default: %(default)s)",
|
||||
"default: Balance between safety and randomization",
|
||||
"dangerous: Key usage must follow logic for safety",
|
||||
"partial: Partial protection when using certain minor glitches",
|
||||
"strict: Ensure small keys are available"
|
||||
],
|
||||
@@ -431,6 +431,20 @@
|
||||
"shuffletavern": [
|
||||
"Include the back of the tavern in the entrance shuffle pool. (default: %(default)s)"
|
||||
],
|
||||
"skullwoods": [
|
||||
"Select how to shuffle skull woods (default: %(default)s)",
|
||||
"Original: Skull Woods is shuffled amongst itself",
|
||||
"Restricted: Drops are vanilla. Entrances stay in skull woods",
|
||||
"Loose: Drops are vanilla. Entrances go in the main pool",
|
||||
"Followlinked: If drops are linked, then pinball/left side will be vanilla",
|
||||
" with other drops paired with an entrance. Otherwise, all go into the main pool"
|
||||
],
|
||||
"linked_drops": [
|
||||
"Select how drops are treated in entrance shuffle. (default: %(default)s)",
|
||||
"Unset: The shuffle mode determines the setting.",
|
||||
"Linked: Dropdowns will be linked with entrance caves",
|
||||
"Independent: Dropdowns will not be linked"
|
||||
],
|
||||
"overworld_map": [
|
||||
"Control if and how the overworld map indicators show the locations of dungeons (default: %(default)s)"
|
||||
],
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
"randomizer.dungeon.trap_door_mode.oneway": "Remove All Annoying Traps",
|
||||
|
||||
"randomizer.dungeon.key_logic_algorithm": "Key Logic Algorithm",
|
||||
"randomizer.dungeon.key_logic_algorithm.default": "Default",
|
||||
"randomizer.dungeon.key_logic_algorithm.dangerous": "Dangerous",
|
||||
"randomizer.dungeon.key_logic_algorithm.partial": "Partial Protection",
|
||||
"randomizer.dungeon.key_logic_algorithm.strict": "Strict",
|
||||
|
||||
@@ -195,6 +195,17 @@
|
||||
"randomizer.entrance.entranceshuffle.dungeonsfull": "Dungeons + Full",
|
||||
"randomizer.entrance.entranceshuffle.dungeonssimple": "Dungeons + Simple",
|
||||
|
||||
"randomizer.entrance.skullwoods": "Skull Woods Shuffle",
|
||||
"randomizer.entrance.skullwoods.original": "Original",
|
||||
"randomizer.entrance.skullwoods.restricted": "Vanilla Drops, Entrances Restricted",
|
||||
"randomizer.entrance.skullwoods.loose": "Vanilla Drops, Entrances use Shuffle",
|
||||
"randomizer.entrance.skullwoods.followlinked": "Follow Linked Drops Setting",
|
||||
|
||||
"randomizer.entrance.linked_drops": "Linked Drops Override",
|
||||
"randomizer.entrance.linked_drops.unset": "Determined by Shuffle",
|
||||
"randomizer.entrance.linked_drops.linked": "Always Linked",
|
||||
"randomizer.entrance.linked_drops.independent": "Independent",
|
||||
|
||||
"randomizer.gameoptions.nobgm": "Disable Music & MSU-1",
|
||||
"randomizer.gameoptions.quickswap": "L/R Quickswapping",
|
||||
"randomizer.gameoptions.reduce_flashing": "Reduce Flashing",
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
},
|
||||
"key_logic_algorithm": {
|
||||
"type": "selectbox",
|
||||
"default": "default",
|
||||
"default": "partial",
|
||||
"options": [
|
||||
"default",
|
||||
"partial",
|
||||
"strict"
|
||||
"strict",
|
||||
"dangerous"
|
||||
],
|
||||
"config": {
|
||||
"padx": [20,0],
|
||||
|
||||
@@ -35,6 +35,26 @@
|
||||
"padx": [20,0]
|
||||
}
|
||||
},
|
||||
"skullwoods": {
|
||||
"type": "selectbox",
|
||||
"options": [
|
||||
"original",
|
||||
"restricted",
|
||||
"loose",
|
||||
"followlinked"
|
||||
],
|
||||
"config": {
|
||||
"width": 30
|
||||
}
|
||||
},
|
||||
"linked_drops": {
|
||||
"type": "selectbox",
|
||||
"options": [
|
||||
"unset",
|
||||
"linked",
|
||||
"independent"
|
||||
]
|
||||
},
|
||||
"openpyramid": {
|
||||
"type": "selectbox",
|
||||
"options": [
|
||||
|
||||
@@ -19,7 +19,7 @@ global FILESIZE_CHECK
|
||||
# windows: 2022, 2019
|
||||
# macos: 14, 13, 12, 11
|
||||
DEFAULT_EVENT = "event"
|
||||
DEFAULT_REPO_SLUG = "miketrethewey/ALttPDoorRandomizer"
|
||||
DEFAULT_REPO_SLUG = "codemann8/ALttPDoorRandomizer"
|
||||
FILENAME_CHECKS = [
|
||||
"DungeonRandomizer",
|
||||
"Gui",
|
||||
|
||||
@@ -71,7 +71,7 @@ if len(BUILD_FILENAMES) > 0:
|
||||
# clean the git slate
|
||||
git_clean()
|
||||
|
||||
# mv dirs from source code
|
||||
# mv dirs from source code
|
||||
dirs = [
|
||||
os.path.join(".",".git"),
|
||||
os.path.join(".",".github"),
|
||||
@@ -98,8 +98,8 @@ if len(BUILD_FILENAMES) > 0:
|
||||
if "linux" in env["OS_NAME"] or "ubuntu" in env["OS_NAME"] or "mac" in env["OS_NAME"] or "osx" in env["OS_NAME"]:
|
||||
os.chmod(os.path.join(".",BUILD_FILENAME),0o755)
|
||||
|
||||
# .zip if windows
|
||||
# .tar.gz otherwise
|
||||
# .zip if windows
|
||||
# .tar.gz otherwise
|
||||
if len(BUILD_FILENAMES) > 1:
|
||||
# ZIP_FILENAME = os.path.join("..","deploy",env["REPO_NAME"])
|
||||
ZIP_FILENAME = os.path.join("..","deploy","ALttPOverworldRandomizer")
|
||||
@@ -112,7 +112,7 @@ if len(BUILD_FILENAMES) > 0:
|
||||
make_archive(ZIP_FILENAME,"gztar")
|
||||
ZIP_FILENAME += ".tar.gz"
|
||||
|
||||
# mv dirs back
|
||||
# mv dirs back
|
||||
for dir in dirs:
|
||||
if os.path.isdir(os.path.join("..","build",dir)):
|
||||
move(
|
||||
|
||||
@@ -160,6 +160,8 @@ class CustomSettings(object):
|
||||
args.bombbag[p] = get_setting(settings['bombbag'], args.bombbag[p])
|
||||
args.shufflelinks[p] = get_setting(settings['shufflelinks'], args.shufflelinks[p])
|
||||
args.shuffletavern[p] = get_setting(settings['shuffletavern'], args.shuffletavern[p])
|
||||
args.skullwoods[p] = get_setting(settings['skullwoods'], args.skullwoods[p])
|
||||
args.linked_drops[p] = get_setting(settings['linked_drops'], args.linked_drops[p])
|
||||
args.restrict_boss_items[p] = get_setting(settings['restrict_boss_items'], args.restrict_boss_items[p])
|
||||
args.overworld_map[p] = get_setting(settings['overworld_map'], args.overworld_map[p])
|
||||
args.pseudoboots[p] = get_setting(settings['pseudoboots'], args.pseudoboots[p])
|
||||
@@ -335,6 +337,8 @@ class CustomSettings(object):
|
||||
settings_dict[p]['bombbag'] = world.bombbag[p]
|
||||
settings_dict[p]['shufflelinks'] = world.shufflelinks[p]
|
||||
settings_dict[p]['shuffletavern'] = world.shuffletavern[p]
|
||||
settings_dict[p]['skullwoods'] = world.skullwoods[p]
|
||||
settings_dict[p]['linked_drops'] = world.linked_drops[p]
|
||||
settings_dict[p]['overworld_map'] = world.overworld_map[p]
|
||||
settings_dict[p]['pseudoboots'] = world.pseudoboots[p]
|
||||
settings_dict[p]['triforce_goal'] = world.treasure_hunt_count[p]
|
||||
|
||||
@@ -103,6 +103,8 @@ SETTINGSTOPROCESS = {
|
||||
"shuffleganon": "shuffleganon",
|
||||
"shufflelinks": "shufflelinks",
|
||||
"shuffletavern": "shuffletavern",
|
||||
"skullwoods": "skullwoods",
|
||||
"linked_drops": "linked_drops",
|
||||
"openpyramid": "openpyramid",
|
||||
"overworld_map": "overworld_map",
|
||||
},
|
||||
|
||||
@@ -201,8 +201,7 @@ def find_possible_rules(vln_list, used_resources, world, player):
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'] * 7 / 8)
|
||||
optional_clears[vln_sub_list].append((byrna_rule(world, player, flag), resources))
|
||||
elif damage_type == 'FireRod' and hits + used_resources['Magic'] <= 160:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
flag = flag if flag < 0 else (hits + used_resources['Magic'])
|
||||
flag = hits + used_resources['Magic']
|
||||
optional_clears[vln_sub_list].append((fire_rod_rule(world, player, flag), resources))
|
||||
elif damage_type == 'IceRod' and hits + used_resources['Magic'] <= 160:
|
||||
flag = min(vln[damage_type] for vln in vln_list.values())
|
||||
|
||||
@@ -34,8 +34,9 @@ UwGeneralDeny:
|
||||
- [ 0x001e, 4, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "BigSpike", "Bumper" ] ] #"Ice Palace - Blob Ambush - Red Bari 4"
|
||||
- [ 0x001e, 5, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ice Palace - Blob Ambush - Zol 1"
|
||||
- [ 0x001e, 6, [ "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ice Palace - Blob Ambush - Zol 2"
|
||||
- [ 0x001f, 0, [ "RollerHorizontalRight" ] ] #"Ice Palace - Big Key View - Pengator 1"
|
||||
- [0x001f, 0, ["RollerHorizontalRight", "RollerHorizontalLeft"]] #"Ice Palace - Big Key View - Pengator 1"
|
||||
- [ 0x001f, 3, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||
- [0x001f, 4, ["RollerVerticalDown", "RollerVerticalUp"]] # too large, hits the door
|
||||
- [ 0x0021, 3, [ "RollerVerticalDown", "RollerVerticalUp" ] ] #"Sewers - Dark U - Rat 2"
|
||||
- [ 0x0021, 4, [ "RollerVerticalDown", "RollerVerticalUp" ] ] #"Sewers - Dark U - Rat 3"
|
||||
- [ 0x0024, 6, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||
@@ -54,10 +55,12 @@ UwGeneralDeny:
|
||||
- [0x0028, 2, ["Raven", "Poe", "GreenZirro", "BlueZirro", "Swamola", "Zora"]]
|
||||
- [0x0028, 3, ["Raven", "Poe", "GreenZirro", "BlueZirro", "Swamola", "Zora"]]
|
||||
- [0x0028, 4, ["Raven", "Poe", "GreenZirro", "BlueZirro", "Swamola", "Zora", "RollerVerticalUp"]] #"Swamp Palace - Entrance Ledge - Spike Trap"
|
||||
- [ 0x002a, 2, [ "SparkCW", "SparkCCW", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper"]] #"Palace of Darkness - Arena Main - Hardhat Beetle 1"
|
||||
- [ 0x002a, 3, [ "Statue", "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper" ] ] #"Palace of Darkness - Arena Main - Hardhat Beetle 2"
|
||||
- [0x002a, 1, ["RollerVerticalUp", "RollerVerticalDown"]]
|
||||
- [0x002a, 2, [ "SparkCW", "SparkCCW", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "Chainchomp"]] #"Palace of Darkness - Arena Main - Hardhat Beetle 1"
|
||||
- [0x002a, 3, ["Statue", "SparkCW", "SparkCCW", "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "FirebarCW", "FirebarCCW", "SpikeBlock", "Bumper", "Chainchomp"]] #"Palace of Darkness - Arena Main - Hardhat Beetle 2"
|
||||
- [ 0x002a, 4, [ "Statue", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper", "RollerHorizontalRight", "RollerHorizontalLeft"]]
|
||||
- [ 0x002a, 6, [ "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Palace of Darkness - Arena Main - Hardhat Beetle 5"
|
||||
- [0x002a, 7, ["RollerVerticalUp", "RollerVerticalDown", "Chainchomp"]]
|
||||
- [ 0x002b, 5, [ "RollerHorizontalRight" ] ] #"Palace of Darkness - Fairies - Red Bari 2"
|
||||
- [ 0x002e, 0, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW" ] ] #"Ice Palace - Penguin Chest - Pengator 1"
|
||||
- [ 0x002e, 1, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "BigSpike", "FirebarCW", "FirebarCCW" ] ] #"Ice Palace - Penguin Chest - Pengator 2"
|
||||
@@ -80,6 +83,7 @@ UwGeneralDeny:
|
||||
- [0x0039, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Bumper"]] #"Skull Woods - Play Pen - Hardhat Beetle"
|
||||
- [ 0x0039, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW" ] ] #"Skull Woods - Play Pen - Spike Trap 2"
|
||||
- [ 0x003b, 1, [ "Bumper" ]]
|
||||
- [ 0x003b, 4, ["RollerVerticalUp", "RollerVerticalDown"]]
|
||||
- [ 0x003c, 0, ["BigSpike"]]
|
||||
- [ 0x003c, 1, [ "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Hookshot Cave - Blue Bari 1"
|
||||
- [ 0x003c, 2, [ "SparkCW", "SparkCCW", "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Hookshot Cave - Blue Bari 2"
|
||||
@@ -118,7 +122,7 @@ UwGeneralDeny:
|
||||
- [ 0x0049, 5, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Skull Woods - Bari Pits - Gibdo 2"
|
||||
- [ 0x0049, 7, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Skull Woods - Bari Pits - Gibdo 4"
|
||||
- [ 0x0049, 8, [ "Beamos", "AntiFairyCircle", "Bumper" ] ] #"Skull Woods - Bari Pits - Gibdo 5"
|
||||
- [ 0x004b, 0, [ "Beamos", "AntiFairyCircle", "Bumper" ] ] #"Palace of Darkness - Mimics 1 - Red Eyegore"
|
||||
- [0x004b, 0, ["Beamos", "AntiFairyCircle", "Bumper", "BigSpike"]] #"Palace of Darkness - Mimics 1 - Red Eyegore"
|
||||
- [ 0x004b, 1, [ "RollerHorizontalRight" ] ] #"Palace of Darkness - Warp Hint - Antifairy 1"
|
||||
- [ 0x004b, 5, [ "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Palace of Darkness - Jelly Hall - Blue Bari 1"
|
||||
- [ 0x004b, 6, [ "AntiFairyCircle", "BigSpike" ] ] #"Palace of Darkness - Jelly Hall - Blue Bari 2"
|
||||
@@ -129,6 +133,7 @@ UwGeneralDeny:
|
||||
- [ 0x0050, 0, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Hyrule Castle - North West Passage - Green Guard"
|
||||
- [ 0x0050, 1, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Hyrule Castle - North West Passage - Green Knife Guard 1"
|
||||
- [ 0x0050, 2, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Hyrule Castle - North West Passage - Green Knife Guard 2"
|
||||
- [0x0051, 2, ["Zoro"]] # Zoro clips off and doesn't return
|
||||
- [ 0x0052, 0, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper" ] ] #"Hyrule Castle - North East Passage - Green Guard"
|
||||
- [ 0x0052, 1, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper" ] ] #"Hyrule Castle - North East Passage - Green Knife Guard 1"
|
||||
- [ 0x0052, 2, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper" ] ] #"Hyrule Castle - North East Passage - Green Knife Guard 2"
|
||||
@@ -151,7 +156,7 @@ UwGeneralDeny:
|
||||
- [ 0x0057, 13, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper", "Statue", "BigSpike"]] #"Skull Woods - Big Key Room - Blue Bari 1"
|
||||
- [ 0x0057, 14, [ "RollerVerticalDown", "Beamos", "AntiFairyCircle", "Bumper", "Statue", "BigSpike"]] #"Skull Woods - Big Key Room - Blue Bari 2"
|
||||
- [ 0x0058, 0, ["Statue"]]
|
||||
- [ 0x0058, 1, ["Statue"]]
|
||||
- [0x0058, 1, ["Statue", "RollerHorizontalRight", "RollerHorizontalLeft"]]
|
||||
- [ 0x0058, 2, ["Statue"]]
|
||||
- [ 0x0058, 3, ["Statue"]]
|
||||
- [ 0x0058, 4, ["Statue"]]
|
||||
@@ -205,7 +210,7 @@ UwGeneralDeny:
|
||||
- [ 0x007b, 7, [ "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - DMs Room - Hardhat Beetle"
|
||||
- [ 0x007c, 1, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - Randomizer Room - Fire Bar (Counterclockwise)"
|
||||
- [ 0x007c, 2, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Randomizer Room - Spike Trap"
|
||||
- [ 0x007c, 3, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper", "Statue"]] #"Ganon's Tower - Randomizer Room - Fire Bar (Clockwise)"
|
||||
- [ 0x007c, 3, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper", "Statue", "SpikeBlock"]] #"Ganon's Tower - Randomizer Room - Fire Bar (Clockwise)"
|
||||
- [ 0x007c, 4, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - Randomizer Room - Hardhat Beetle"
|
||||
- [ 0x007d, 0, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - The Zoo - Fire Snake 1"
|
||||
- [ 0x007d, 1, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - The Zoo - Fire Snake 2"
|
||||
@@ -267,6 +272,7 @@ UwGeneralDeny:
|
||||
- [ 0x009c, 3, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - Invisible Floor Maze - Hardhat Beetle 3"
|
||||
- [ 0x009c, 4, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Invisible Floor Maze - Hardhat Beetle 4"
|
||||
- [ 0x009c, 5, [ "RollerVerticalUp", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Invisible Floor Maze - Hardhat Beetle 5"
|
||||
- [0x009d, 2, ["AntiFairyCircle"]]
|
||||
- [ 0x009d, 3, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ganon's Tower - Compass Room - Gibdo 2"
|
||||
- [ 0x009d, 6, [ "RollerHorizontalLeft", "RollerHorizontalRight" ] ] #"Ganon's Tower - Compass Room - Blue Bari 1"
|
||||
- [ 0x009d, 7, [ "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ganon's Tower - Compass Room - Blue Bari 2"
|
||||
@@ -288,7 +294,7 @@ UwGeneralDeny:
|
||||
- [ 0x00ab, 7, [ "RollerVerticalUp", "RollerHorizontalLeft" ] ] #"Thieves' Town - Spike Dodge - Spike Trap 6"
|
||||
- [ 0x00ae, 0, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ice Palace - Ice T - Blue Bari 1"
|
||||
- [ 0x00ae, 1, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Ice Palace - Ice T - Blue Bari 2"
|
||||
- [ 0x00af, 0, [ "RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Ice Palace - Ice Clock - Fire Bar (Clockwise)"
|
||||
- [0x00af, 0, ["RollerHorizontalRight", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper", "Lynel"]] #"Ice Palace - Ice Clock - Fire Bar (Clockwise)"
|
||||
- [0x00b0, 7, [ "StalfosKnight", "Blob", "Stal", "Wizzrobe"]] # blocked, but Geldmen are probably okay
|
||||
- [0x00b0, 8, [ "StalfosKnight", "Blob", "Stal", "Wizzrobe"]] # blocked, but Geldmen are probably okay
|
||||
- [ 0x00b1, 2, [ "RollerVerticalUp", "RollerVerticalDown" ] ] #"Misery Mire - Hourglass - Spike Trap 1"
|
||||
@@ -332,6 +338,7 @@ UwGeneralDeny:
|
||||
- [ 0x00cb, 9, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ]
|
||||
- [ 0x00cb, 10, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ]
|
||||
- [ 0x00cb, 11, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
||||
- [0x00cc, 6, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "Bumper"]] # prevent access around
|
||||
- [ 0x00cc, 8, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #Prevents Pot access (Beamos okay?)
|
||||
- [ 0x00cc, 12, [ "RollerVerticalUp", "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #Prevents Pot access (Beamos okay?)
|
||||
- [ 0x00ce, 0, [ "RollerVerticalDown", "RollerVerticalUp", "RollerHorizontalRight", "RollerHorizontalLeft", "AntiFairyCircle", "Antifairy", "BigSpike", "FirebarCCW", "Bumper", "Chainchomp"]] #"Ice Palace - Over Boss - top - Red Bari 1"
|
||||
@@ -389,7 +396,7 @@ UwGeneralDeny:
|
||||
- [ 0x00e7, 5, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Death Mountain Descent Cave Right - Keese 6"
|
||||
- [ 0x00e7, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Death Mountain Descent Cave Right - Keese 7"
|
||||
- [ 0x00e8, 0, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "AntiFairyCircle", "SpikeBlock", "Bumper" ] ] #"Super Bunny Exit - Hardhat Beetle 1"
|
||||
- [ 0x00e8, 1, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Super Bunny Exit - Hardhat Beetle 2"
|
||||
- [ 0x00e8, 2, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Super Bunny Exit - Hardhat Beetle 2"
|
||||
- [ 0x00ee, 0, [ "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "Bumper" ] ] #"Sprial Cave Top - Mini Moldorm 1"
|
||||
- [ 0x00ee, 1, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Sprial Cave Top - Mini Moldorm 2"
|
||||
- [ 0x00ee, 2, [ "RollerHorizontalLeft", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Sprial Cave Top - Mini Moldorm 3"
|
||||
@@ -402,7 +409,7 @@ UwGeneralDeny:
|
||||
- [ 0x00f1, 3, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight" ] ] #"Old Man Maze - Keese 4"
|
||||
- [ 0x00f1, 4, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight" ] ] #"Old Man Maze - Keese 5"
|
||||
- [ 0x00f1, 5, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight" ] ] #"Old Man Maze - Keese 6"
|
||||
- [ 0x00fd, 0, [ "Bumper" ] ]
|
||||
- [0x00fd, 0, ["Bumper", "AntiFairyCircle"]]
|
||||
- [ 0x0107, 1, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle"]]
|
||||
- [ 0x0107, 2, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle"]]
|
||||
- [0x010b, 6, ["RollerHorizontalRight"]]
|
||||
@@ -449,6 +456,8 @@ OwGeneralDeny:
|
||||
- [0x5e, 18, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 19, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x5e, 20, ["Gibo"]] # kiki eating Gibo
|
||||
- [0x62, 1, ["RollerVerticalUp", "RollerVerticalDown"]] # hard to avoid roller around hammer pegs
|
||||
- [0x62, 3, ["RollerVerticalUp", "RollerVerticalDown"]] # hard to avoid roller around hammer pegs
|
||||
- [0x77, 1, ["Bumper"]] # soft-lock potential near ladder
|
||||
- [0x7f, 1, ["Bumper"]] # soft-lock potential near ladder
|
||||
UwEnemyDrop:
|
||||
|
||||
@@ -26,6 +26,7 @@ class EntrancePool(object):
|
||||
self.decoupled_exits = []
|
||||
self.original_entrances = set()
|
||||
self.original_exits = set()
|
||||
self.same_world_restricted = {}
|
||||
|
||||
self.world = world
|
||||
self.player = player
|
||||
@@ -59,7 +60,6 @@ def link_entrances_new(world, player):
|
||||
avail_pool.entrances = set(i_drop_map.keys()).union(i_entrance_map.keys()).union(i_single_ent_map.keys())
|
||||
avail_pool.exits = set(i_entrance_map.values()).union(i_drop_map.values()).union(i_single_ent_map.values())
|
||||
avail_pool.inverted = world.mode[player] == 'inverted'
|
||||
avail_pool.assumed_loose_caves = world.shuffle[player] == 'district'
|
||||
inverted_substitution(avail_pool, avail_pool.entrances, True, True)
|
||||
inverted_substitution(avail_pool, avail_pool.exits, False, True)
|
||||
avail_pool.original_entrances.update(avail_pool.entrances)
|
||||
@@ -99,8 +99,13 @@ def link_entrances_new(world, player):
|
||||
if mode not in modes:
|
||||
raise RuntimeError(f'Shuffle mode {mode} is not yet supported')
|
||||
mode_cfg = copy.deepcopy(modes[mode])
|
||||
|
||||
if world.linked_drops[player] != 'unset':
|
||||
mode_cfg['keep_drops_together'] = 'on' if world.linked_drops[player] == 'linked' else 'off'
|
||||
|
||||
avail_pool.swapped = mode_cfg['undefined'] == 'swap'
|
||||
avail_pool.keep_drops_together = mode_cfg['keep_drops_together'] == 'on' if 'keep_drops_together' in mode_cfg else True
|
||||
avail_pool.assumed_loose_caves = not avail_pool.keep_drops_together and world.shuffle[player] == 'district'
|
||||
avail_pool.coupled = mode_cfg['decoupled'] != 'on' if 'decoupled' in mode_cfg else True
|
||||
if avail_pool.is_standard():
|
||||
do_standard_connections(avail_pool)
|
||||
@@ -108,11 +113,7 @@ def link_entrances_new(world, player):
|
||||
for pool_name, pool in pool_list.items():
|
||||
special_shuffle = pool['special'] if 'special' in pool else None
|
||||
if special_shuffle == 'drops':
|
||||
holes, targets = find_entrances_and_targets_drops(avail_pool, pool['entrances'])
|
||||
if avail_pool.swapped:
|
||||
connect_swapped(holes, targets, avail_pool)
|
||||
else:
|
||||
connect_random(holes, targets, avail_pool)
|
||||
handle_skull_woods_drops(avail_pool, pool['entrances'], mode_cfg)
|
||||
elif special_shuffle == 'normal_drops':
|
||||
cross_world = mode_cfg['cross_world'] == 'on' if 'cross_world' in mode_cfg else False
|
||||
do_holes_and_linked_drops(set(avail_pool.entrances), set(avail_pool.exits), avail_pool, cross_world)
|
||||
@@ -143,20 +144,7 @@ def link_entrances_new(world, player):
|
||||
entrances, exits = find_entrances_and_exits(avail_pool, entrances+drops)
|
||||
do_main_shuffle(entrances, exits, avail_pool, mode_cfg)
|
||||
elif special_shuffle == 'skull':
|
||||
entrances, exits = find_entrances_and_exits(avail_pool, pool['entrances'])
|
||||
rem_ent = None
|
||||
if avail_pool.world.shuffle[avail_pool.player] in ['dungeonssimple', 'simple', 'restricted'] \
|
||||
and not avail_pool.world.is_tile_swapped(0x00, avail_pool.player):
|
||||
rem_ent = random.choice(['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)'])
|
||||
entrances.remove(rem_ent)
|
||||
exits.remove('Skull Woods First Section Exit')
|
||||
connect_random(entrances, exits, avail_pool, True)
|
||||
entrances, exits = [rem_ent], ['Skull Woods First Section Exit']
|
||||
if avail_pool.swapped:
|
||||
connect_swapped(entrances, exits, avail_pool, True)
|
||||
else:
|
||||
connect_random(entrances, exits, avail_pool, True)
|
||||
avail_pool.skull_handled = True
|
||||
handle_skull_woods_entrances(avail_pool, pool['entrances'])
|
||||
else:
|
||||
entrances, exits = find_entrances_and_exits(avail_pool, pool['entrances'])
|
||||
do_main_shuffle(entrances, exits, avail_pool, mode_cfg)
|
||||
@@ -253,12 +241,21 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
|
||||
# mandatory exits
|
||||
rem_entrances, rem_exits = set(), set()
|
||||
if not cross_world:
|
||||
determine_dungeon_restrictions(avail)
|
||||
mand_exits = figure_out_must_exits_same_world(entrances, exits, avail)
|
||||
must_exit_lw, must_exit_dw, lw_entrances, dw_entrances, multi_exit_caves = mand_exits
|
||||
|
||||
def do_world_mandatory(world_entrances, world_must_exits, restriction):
|
||||
nonlocal multi_exit_caves
|
||||
candidates = filter_restricted_caves(multi_exit_caves, restriction, avail)
|
||||
other_candidates = [x for x in multi_exit_caves if x not in candidates] # remember those not passed in
|
||||
do_mandatory_connections(avail, world_entrances, candidates, world_must_exits)
|
||||
multi_exit_caves = (other_candidates + candidates) if other_candidates else candidates # rebuild list from the candidates and those not passed
|
||||
|
||||
if not avail.inverted:
|
||||
do_mandatory_connections(avail, lw_entrances, multi_exit_caves, must_exit_lw)
|
||||
do_world_mandatory(lw_entrances, must_exit_lw, 'LightWorld')
|
||||
else:
|
||||
do_mandatory_connections(avail, dw_entrances, multi_exit_caves, must_exit_dw)
|
||||
do_world_mandatory(dw_entrances, must_exit_dw, 'DarkWorld')
|
||||
|
||||
new_mec = []
|
||||
for cave_option in multi_exit_caves:
|
||||
@@ -272,9 +269,9 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
|
||||
multi_exit_caves = new_mec
|
||||
|
||||
if not avail.inverted:
|
||||
do_mandatory_connections(avail, dw_entrances, multi_exit_caves, must_exit_dw)
|
||||
do_world_mandatory(dw_entrances, must_exit_dw, 'DarkWorld')
|
||||
else:
|
||||
do_mandatory_connections(avail, lw_entrances, multi_exit_caves, must_exit_lw)
|
||||
do_world_mandatory(lw_entrances, must_exit_lw, 'LightWorld')
|
||||
rem_entrances.update(lw_entrances)
|
||||
rem_entrances.update(dw_entrances)
|
||||
else:
|
||||
@@ -367,6 +364,10 @@ def do_main_shuffle(entrances, exits, avail, mode_def):
|
||||
if bonk_fairy_exception(x):
|
||||
lw_entrances.append(x) if x in LW_Entrances else dw_entrances.append(x)
|
||||
do_same_world_connectors(lw_entrances, dw_entrances, multi_exit_caves, avail)
|
||||
if avail.world.doorShuffle[avail.player] != 'vanilla':
|
||||
determine_dungeon_restrictions(avail)
|
||||
possibles = figure_out_possible_exits(rem_exits)
|
||||
do_same_world_possible_connectors(lw_entrances, dw_entrances, possibles, avail)
|
||||
unused_entrances.update(lw_entrances)
|
||||
unused_entrances.update(dw_entrances)
|
||||
else:
|
||||
@@ -519,12 +520,16 @@ def do_holes_and_linked_drops(entrances, exits, avail, cross_world):
|
||||
|
||||
if not avail.keep_drops_together:
|
||||
targets = [avail.one_way_map[x] for x in holes_to_shuffle]
|
||||
connect_random(holes_to_shuffle, targets, avail)
|
||||
if avail.swapped:
|
||||
connect_swapped(holes_to_shuffle, targets, avail)
|
||||
else:
|
||||
connect_random(holes_to_shuffle, targets, avail)
|
||||
remove_from_list(entrances, holes_to_shuffle)
|
||||
remove_from_list(exits, targets)
|
||||
return # we're done here
|
||||
|
||||
hole_entrances, hole_targets = [], []
|
||||
leftover_hole_entrances, leftover_hole_targets = [], []
|
||||
for hole in drop_map:
|
||||
if hole in avail.original_entrances and hole in linked_drop_map:
|
||||
linked_entrance = linked_drop_map[hole]
|
||||
@@ -534,39 +539,44 @@ def do_holes_and_linked_drops(entrances, exits, avail, cross_world):
|
||||
target_drop = avail.one_way_map[hole]
|
||||
if target_exit in exits and target_drop in exits:
|
||||
hole_targets.append((target_exit, target_drop))
|
||||
else:
|
||||
if hole in avail.original_entrances and hole in entrances:
|
||||
leftover_hole_entrances.append(hole)
|
||||
if drop_map[hole] in exits:
|
||||
leftover_hole_targets.append(drop_map[hole])
|
||||
|
||||
random.shuffle(hole_entrances)
|
||||
if not cross_world and 'Sanctuary Grave' in holes_to_shuffle:
|
||||
hc = avail.world.get_entrance('Hyrule Castle Exit (South)', avail.player)
|
||||
is_hc_in_dw = avail.world.mode[avail.player] == 'inverted'
|
||||
if hc.connected_region:
|
||||
is_hc_in_dw = hc.connected_region.type == RegionType.DarkWorld
|
||||
chosen_entrance = None
|
||||
if is_hc_in_dw:
|
||||
if avail.swapped:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in DW_Entrances and e[0] != 'Sanctuary')
|
||||
if not cross_world:
|
||||
if 'Sanctuary Grave' in holes_to_shuffle:
|
||||
hc = avail.world.get_entrance('Hyrule Castle Exit (South)', avail.player)
|
||||
is_hc_in_opp_world = avail.inverted
|
||||
if hc.connected_region:
|
||||
opp_world = RegionType.LightWorld if avail.inverted else RegionType.DarkWorld
|
||||
is_hc_in_opp_world = hc.connected_region.type == opp_world
|
||||
start_world_entrances = DW_Entrances if avail.inverted else LW_Entrances
|
||||
opp_world_entrances = LW_Entrances if avail.inverted else DW_Entrances
|
||||
chosen_entrance = None
|
||||
if is_hc_in_opp_world:
|
||||
if avail.swapped:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in opp_world_entrances and e[0] != 'Sanctuary')
|
||||
if not chosen_entrance:
|
||||
chosen_entrance = next((e for e in hole_entrances if e[0] in opp_world_entrances), None)
|
||||
if not chosen_entrance:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in DW_Entrances)
|
||||
if not chosen_entrance:
|
||||
if avail.swapped:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in LW_Entrances and e[0] != 'Sanctuary')
|
||||
if not chosen_entrance:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in LW_Entrances)
|
||||
if chosen_entrance:
|
||||
hole_entrances.remove(chosen_entrance)
|
||||
sanc_interior = next(target for target in hole_targets if target[0] == 'Sanctuary Exit')
|
||||
hole_targets.remove(sanc_interior)
|
||||
connect_two_way(chosen_entrance[0], sanc_interior[0], avail) # two-way exit
|
||||
connect_entrance(chosen_entrance[1], sanc_interior[1], avail) # hole
|
||||
remove_from_list(entrances, [chosen_entrance[0], chosen_entrance[1]])
|
||||
remove_from_list(exits, [sanc_interior[0], sanc_interior[1]])
|
||||
if avail.swapped and drop_map[chosen_entrance[1]] != sanc_interior[1]:
|
||||
swap_ent, swap_ext = connect_swap(chosen_entrance[0], sanc_interior[0], avail)
|
||||
swap_drop, swap_tgt = connect_swap(chosen_entrance[1], sanc_interior[1], avail)
|
||||
hole_entrances.remove((swap_ent, swap_drop))
|
||||
hole_targets.remove((swap_ext, swap_tgt))
|
||||
remove_from_list(entrances, [swap_ent, swap_drop])
|
||||
remove_from_list(exits, [swap_ext, swap_tgt])
|
||||
if avail.swapped:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in start_world_entrances and e[0] != 'Sanctuary')
|
||||
if not chosen_entrance:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in start_world_entrances)
|
||||
|
||||
if chosen_entrance:
|
||||
connect_hole_via_interior(chosen_entrance, 'Sanctuary Exit', hole_entrances, hole_targets, entrances, exits, avail)
|
||||
|
||||
sw_world_entrances = DW_Entrances if not avail.world.is_tile_swapped(0x00, avail.player) else LW_Entrances
|
||||
if 'Skull Woods First Section Hole (North)' in holes_to_shuffle:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in sw_world_entrances)
|
||||
connect_hole_via_interior(chosen_entrance, 'Skull Woods First Section Exit', hole_entrances, hole_targets, entrances, exits, avail)
|
||||
if 'Skull Woods Second Section Hole' in holes_to_shuffle:
|
||||
chosen_entrance = next(e for e in hole_entrances if e[0] in sw_world_entrances)
|
||||
connect_hole_via_interior(chosen_entrance, 'Skull Woods Second Section Exit (East)', hole_entrances, hole_targets, entrances, exits, avail)
|
||||
|
||||
random.shuffle(hole_targets)
|
||||
while len(hole_entrances):
|
||||
@@ -588,6 +598,31 @@ def do_holes_and_linked_drops(entrances, exits, avail, cross_world):
|
||||
remove_from_list(entrances, [swap_ent, swap_drop])
|
||||
remove_from_list(exits, [swap_ext, swap_tgt])
|
||||
|
||||
if leftover_hole_entrances and leftover_hole_targets:
|
||||
remove_from_list(entrances, leftover_hole_entrances)
|
||||
remove_from_list(exits, leftover_hole_targets)
|
||||
if avail.swapped:
|
||||
connect_swapped(leftover_hole_entrances, leftover_hole_targets, avail)
|
||||
else:
|
||||
connect_random(leftover_hole_entrances, leftover_hole_targets, avail)
|
||||
|
||||
|
||||
def connect_hole_via_interior(chosen_entrance, interior, hole_entrances, hole_targets, entrances, exits, avail):
|
||||
hole_entrances.remove(chosen_entrance)
|
||||
interior = next(target for target in hole_targets if target[0] == interior)
|
||||
hole_targets.remove(interior)
|
||||
connect_two_way(chosen_entrance[0], interior[0], avail)
|
||||
connect_entrance(chosen_entrance[1], interior[1], avail)
|
||||
remove_from_list(entrances, [chosen_entrance[0], chosen_entrance[1]])
|
||||
remove_from_list(exits, [interior[0], interior[1]])
|
||||
if avail.swapped and drop_map[chosen_entrance[1]] != interior[1]:
|
||||
swap_ent, swap_ext = connect_swap(chosen_entrance[0], interior[0], avail)
|
||||
swap_drop, swap_tgt = connect_swap(chosen_entrance[1], interior[1], avail)
|
||||
hole_entrances.remove((swap_ent, swap_drop))
|
||||
hole_targets.remove((swap_ext, swap_tgt))
|
||||
remove_from_list(entrances, [swap_ent, swap_drop])
|
||||
remove_from_list(exits, [swap_ext, swap_tgt])
|
||||
|
||||
|
||||
def do_dark_sanc(entrances, exits, avail):
|
||||
if avail.world.is_dark_chapel_start(avail.player):
|
||||
@@ -867,14 +902,15 @@ def get_accessible_entrances(start_region, avail, assumed_inventory=[], cross_wo
|
||||
return found_entrances
|
||||
|
||||
|
||||
def figure_out_connectors(exits, avail):
|
||||
def figure_out_connectors(exits, avail, cross_world=True):
|
||||
multi_exit_caves = []
|
||||
cave_list = list(Connector_List)
|
||||
if avail.assumed_loose_caves:
|
||||
sw_list = ['Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)']
|
||||
random.shuffle(sw_list)
|
||||
cave_list.extend([sw_list])
|
||||
cave_list.extend([[entrance_map[e]] for e in linked_drop_map.values() if 'Inverted ' not in e])
|
||||
if avail.assumed_loose_caves or (not avail.skull_handled and (cross_world or not avail.world.is_tile_swapped(0x00, avail.player))):
|
||||
skull_connector = [x for x in ['Skull Woods Second Section Exit (West)', 'Skull Woods Second Section Exit (East)'] if x in exits]
|
||||
cave_list.extend(skull_connector)
|
||||
if avail.assumed_loose_caves or not avail.keep_drops_together:
|
||||
cave_list.extend([[entrance_map[e]] for e in linked_drop_map.values() if 'Inverted ' not in e and 'Skull Woods ' not in e])
|
||||
|
||||
for item in cave_list:
|
||||
if all(x in exits for x in item):
|
||||
remove_from_list(exits, item)
|
||||
@@ -1055,12 +1091,49 @@ def must_exits_helper(avail):
|
||||
return must_exit_lw, must_exit_dw
|
||||
|
||||
|
||||
def figure_out_possible_exits(exits):
|
||||
possible_multi_exit_caves = []
|
||||
for item in doors_possible_connectors:
|
||||
if item in exits:
|
||||
remove_from_list(exits, item)
|
||||
possible_multi_exit_caves.append(item)
|
||||
return possible_multi_exit_caves
|
||||
|
||||
|
||||
def determine_dungeon_restrictions(avail):
|
||||
check_for_hc = (avail.is_standard() or avail.world.doorShuffle[avail.player] != 'vanilla')
|
||||
for check in dungeon_restriction_checks:
|
||||
dungeon_exits, drop_regions = check
|
||||
if check_for_hc and any('Hyrule Castle' in x for x in dungeon_exits):
|
||||
avail.same_world_restricted.update({x: 'LightWorld' for x in dungeon_exits})
|
||||
else:
|
||||
restriction = None
|
||||
for x in dungeon_exits:
|
||||
ent = avail.world.get_entrance(x, avail.player)
|
||||
if ent.connected_region:
|
||||
if ent.connected_region.type == RegionType.LightWorld:
|
||||
restriction = 'LightWorld'
|
||||
elif ent.connected_region.type == RegionType.DarkWorld:
|
||||
restriction = 'DarkWorld'
|
||||
# Holes only restrict
|
||||
for x in drop_regions:
|
||||
region = avail.world.get_region(x, avail.player)
|
||||
ent = next((ent for ent in region.entrances if ent.parent_region and ent.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld]), None)
|
||||
if ent:
|
||||
if ent.parent_region.type == RegionType.LightWorld and not avail.inverted:
|
||||
restriction = 'LightWorld'
|
||||
elif ent.parent_region.type == RegionType.DarkWorld and avail.inverted:
|
||||
restriction = 'DarkWorld'
|
||||
if restriction:
|
||||
avail.same_world_restricted.update({x: restriction for x in dungeon_exits})
|
||||
|
||||
|
||||
def figure_out_must_exits_same_world(entrances, exits, avail):
|
||||
lw_entrances, dw_entrances = [], []
|
||||
|
||||
for x in entrances:
|
||||
lw_entrances.append(x) if x in LW_Entrances else dw_entrances.append(x)
|
||||
multi_exit_caves = figure_out_connectors(exits, avail)
|
||||
multi_exit_caves = figure_out_connectors(exits, avail, False)
|
||||
|
||||
must_exit_lw, must_exit_dw = must_exits_helper(avail)
|
||||
must_exit_lw = must_exit_filter(avail, must_exit_lw, lw_entrances)
|
||||
@@ -1069,8 +1142,26 @@ def figure_out_must_exits_same_world(entrances, exits, avail):
|
||||
return must_exit_lw, must_exit_dw, lw_entrances, dw_entrances, multi_exit_caves
|
||||
|
||||
|
||||
def filter_restricted_caves(multi_exit_caves, restriction, avail):
|
||||
candidates = []
|
||||
for cave in multi_exit_caves:
|
||||
if all(x not in avail.same_world_restricted or avail.same_world_restricted[x] == restriction for x in cave):
|
||||
candidates.append(cave)
|
||||
return candidates
|
||||
|
||||
|
||||
def flatten(list_to_flatten):
|
||||
ret = []
|
||||
for item in list_to_flatten:
|
||||
if isinstance(item, tuple):
|
||||
ret.extend(item)
|
||||
else:
|
||||
ret.append(item)
|
||||
return ret
|
||||
|
||||
|
||||
def figure_out_must_exits_cross_world(entrances, exits, avail):
|
||||
multi_exit_caves = figure_out_connectors(exits, avail)
|
||||
multi_exit_caves = figure_out_connectors(exits, avail, True)
|
||||
|
||||
must_exit_lw, must_exit_dw = must_exits_helper(avail)
|
||||
must_exit = must_exit_filter(avail, must_exit_lw + must_exit_dw, entrances)
|
||||
@@ -1083,7 +1174,7 @@ def do_same_world_connectors(lw_entrances, dw_entrances, caves, avail):
|
||||
random.shuffle(dw_entrances)
|
||||
random.shuffle(caves)
|
||||
while caves:
|
||||
# connect highest exit count caves first, prevent issue where we have 2 or 3 exits across worlds left to fill
|
||||
# connect highest-exit-count caves first, prevent issue where we have 2 or 3 exits across worlds left to fill
|
||||
cave_candidate = (None, 0)
|
||||
for i, cave in enumerate(caves):
|
||||
if isinstance(cave, str):
|
||||
@@ -1092,12 +1183,19 @@ def do_same_world_connectors(lw_entrances, dw_entrances, caves, avail):
|
||||
cave_candidate = (i, len(cave))
|
||||
cave = caves.pop(cave_candidate[0])
|
||||
|
||||
target = lw_entrances if random.randint(0, 1) == 0 else dw_entrances
|
||||
if isinstance(cave, str):
|
||||
cave = (cave,)
|
||||
target, restriction = None, None
|
||||
if any(x in avail.same_world_restricted for x in cave):
|
||||
restriction = next(avail.same_world_restricted[x] for x in cave if x in avail.same_world_restricted)
|
||||
target = lw_entrances if restriction == 'LightWorld' else dw_entrances
|
||||
if target is None:
|
||||
target = lw_entrances if random.randint(0, 1) == 0 else dw_entrances
|
||||
|
||||
# check if we can still fit the cave into our target group
|
||||
if len(target) < len(cave):
|
||||
if restriction:
|
||||
raise Exception('Not enough entrances for restricted cave, algorithm needs revision (main)')
|
||||
# need to use other set
|
||||
target = lw_entrances if target is dw_entrances else dw_entrances
|
||||
|
||||
@@ -1111,6 +1209,18 @@ def do_same_world_connectors(lw_entrances, dw_entrances, caves, avail):
|
||||
connect_two_way(target.pop(), ext, avail)
|
||||
|
||||
|
||||
def do_same_world_possible_connectors(lw_entrances, dw_entrances, possibles, avail):
|
||||
random.shuffle(possibles)
|
||||
while possibles:
|
||||
possible = possibles.pop()
|
||||
target = None
|
||||
if possible in avail.same_world_restricted:
|
||||
target = lw_entrances if avail.same_world_restricted[possible] == 'LightWorld' else dw_entrances
|
||||
if target is None:
|
||||
target = lw_entrances if random.randint(0, 1) == 0 else dw_entrances
|
||||
connect_two_way(target.pop(), possible, avail)
|
||||
determine_dungeon_restrictions(avail)
|
||||
|
||||
def do_cross_world_connectors(entrances, caves, avail):
|
||||
random.shuffle(entrances)
|
||||
random.shuffle(caves)
|
||||
@@ -1158,6 +1268,44 @@ def do_cross_world_connectors(entrances, caves, avail):
|
||||
break
|
||||
|
||||
|
||||
def handle_skull_woods_drops(avail, pool, mode_cfg):
|
||||
skull_woods = avail.world.skullwoods[avail.player]
|
||||
if skull_woods in ['restricted', 'loose']:
|
||||
for drop in pool:
|
||||
target = drop_map[drop]
|
||||
connect_entrance(drop, target, avail)
|
||||
elif skull_woods == 'original':
|
||||
holes, targets = find_entrances_and_targets_drops(avail, pool)
|
||||
if avail.swapped:
|
||||
connect_swapped(holes, targets, avail)
|
||||
else:
|
||||
connect_random(holes, targets, avail)
|
||||
elif skull_woods == 'followlinked':
|
||||
keep_together = mode_cfg['keep_drops_together'] == 'on' if 'keep_drops_together' in mode_cfg else True
|
||||
if keep_together:
|
||||
for drop in ['Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (West)']:
|
||||
target = drop_map[drop]
|
||||
connect_entrance(drop, target, avail)
|
||||
|
||||
|
||||
def handle_skull_woods_entrances(avail, pool):
|
||||
skull_woods = avail.world.skullwoods[avail.player]
|
||||
if skull_woods in ['restricted', 'original']:
|
||||
entrances, exits = find_entrances_and_exits(avail, pool)
|
||||
if avail.world.shuffle[avail.player] in ['dungeonssimple', 'simple', 'restricted'] \
|
||||
and not avail.world.is_tile_swapped(0x00, avail.player):
|
||||
rem_ent = random.choice(['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)'])
|
||||
entrances.remove(rem_ent)
|
||||
exits.remove('Skull Woods First Section Exit')
|
||||
connect_random(entrances, exits, avail, True)
|
||||
entrances, exits = [rem_ent], ['Skull Woods First Section Exit']
|
||||
if avail.swapped:
|
||||
connect_swapped(entrances, exits, avail, True)
|
||||
else:
|
||||
connect_random(entrances, exits, avail, True)
|
||||
avail.skull_handled = True
|
||||
|
||||
|
||||
def do_fixed_shuffle(avail, entrance_list):
|
||||
max_size = 0
|
||||
options = {}
|
||||
@@ -1214,7 +1362,6 @@ def do_same_world_shuffle(avail, pool_def):
|
||||
multi_exit = pool_def['connectors']
|
||||
# complete_entrance_set = set()
|
||||
lw_entrances, dw_entrances, multi_exits_caves, other_exits = [], [], [], []
|
||||
hyrule_forced = None
|
||||
|
||||
single_entrances, single_exits = find_entrances_and_exits(avail, single_exit)
|
||||
other_exits.extend(single_exits)
|
||||
@@ -1224,11 +1371,8 @@ def do_same_world_shuffle(avail, pool_def):
|
||||
for option in multi_exit:
|
||||
multi_entrances, multi_exits = find_entrances_and_exits(avail, option)
|
||||
# complete_entrance_set.update(multi_entrances)
|
||||
if avail.is_sanc_forced_in_hc() and any(x in multi_entrances for x in ['Hyrule Castle Entrance (South)',
|
||||
'Hyrule Castle Entrance (East)',
|
||||
'Hyrule Castle Entrance (West)']):
|
||||
hyrule_forced = [multi_exits]
|
||||
multi_exits_caves.append(multi_exits)
|
||||
if multi_exits:
|
||||
multi_exits_caves.append(multi_exits)
|
||||
for x in multi_entrances:
|
||||
(dw_entrances, lw_entrances)[x in LW_Entrances].append(x)
|
||||
|
||||
@@ -1236,13 +1380,16 @@ def do_same_world_shuffle(avail, pool_def):
|
||||
must_exit_lw = must_exit_filter(avail, must_exit_lw, lw_entrances)
|
||||
must_exit_dw = must_exit_filter(avail, must_exit_dw, dw_entrances)
|
||||
|
||||
do_mandatory_connections(avail, lw_entrances, multi_exits_caves, must_exit_lw)
|
||||
if hyrule_forced and hyrule_forced[0] in multi_exits_caves:
|
||||
remove_from_list(multi_exits_caves, hyrule_forced)
|
||||
do_mandatory_connections(avail, dw_entrances, multi_exits_caves, must_exit_dw)
|
||||
multi_exits_caves.append(hyrule_forced[0])
|
||||
else:
|
||||
do_mandatory_connections(avail, dw_entrances, multi_exits_caves, must_exit_dw)
|
||||
def do_world_mandatory(world_entrances, world_must_exits, restriction):
|
||||
nonlocal multi_exits_caves
|
||||
candidates = filter_restricted_caves(multi_exits_caves, restriction, avail)
|
||||
other_candidates = [x for x in multi_exits_caves if x not in candidates] # remember those not passed in
|
||||
do_mandatory_connections(avail, world_entrances, candidates, world_must_exits)
|
||||
multi_exits_caves = (other_candidates + candidates) if other_candidates else candidates # rebuild list from the candidates and those not passed
|
||||
|
||||
determine_dungeon_restrictions(avail)
|
||||
do_world_mandatory(lw_entrances, must_exit_lw, 'LightWorld')
|
||||
do_world_mandatory(dw_entrances, must_exit_dw, 'DarkWorld')
|
||||
|
||||
# connect caves
|
||||
random.shuffle(lw_entrances)
|
||||
@@ -1250,19 +1397,20 @@ def do_same_world_shuffle(avail, pool_def):
|
||||
random.shuffle(multi_exits_caves)
|
||||
while multi_exits_caves:
|
||||
cave_candidate = (None, 0)
|
||||
if hyrule_forced and hyrule_forced[0] in multi_exits_caves:
|
||||
multi_exits_caves.remove(hyrule_forced[0])
|
||||
cave = hyrule_forced[0]
|
||||
hyrule_forced = None
|
||||
target = lw_entrances
|
||||
else:
|
||||
for i, cave in enumerate(multi_exits_caves):
|
||||
if len(cave) > cave_candidate[1]:
|
||||
cave_candidate = (i, len(cave))
|
||||
cave = multi_exits_caves.pop(cave_candidate[0])
|
||||
target = lw_entrances if random.randint(0, 1) == 0 else dw_entrances
|
||||
for i, cave in enumerate(multi_exits_caves):
|
||||
if len(cave) > cave_candidate[1]:
|
||||
cave_candidate = (i, len(cave))
|
||||
cave = multi_exits_caves.pop(cave_candidate[0])
|
||||
|
||||
target, restriction = None, None
|
||||
if any(x in avail.same_world_restricted for x in cave):
|
||||
restriction = next(avail.same_world_restricted[x] for x in cave if x in avail.same_world_restricted)
|
||||
target = lw_entrances if restriction == 'LightWorld' else dw_entrances
|
||||
if target is None:
|
||||
target = lw_entrances if random.randint(0, 1) == 0 else dw_entrances
|
||||
if len(target) < len(cave): # swap because we ran out of entrances in that world
|
||||
if restriction:
|
||||
raise Exception('Not enough entrances for restricted cave, algorithm needs revision (dungeonsfull)')
|
||||
target = lw_entrances if target is dw_entrances else dw_entrances
|
||||
|
||||
for ext in cave:
|
||||
@@ -1670,7 +1818,7 @@ def connect_swap(entrance, exit, avail):
|
||||
swap_entrance = next(e for e, x in avail.combine_map.items() if x == exit)
|
||||
if swap_entrance in ['Pyramid Entrance', 'Pyramid Hole'] and avail.world.is_tile_swapped(0x1b, avail.player):
|
||||
swap_entrance = 'Inverted ' + swap_entrance
|
||||
if entrance in entrance_map:
|
||||
if swap_exit in entrance_map.values():
|
||||
connect_two_way(swap_entrance, swap_exit, avail)
|
||||
else:
|
||||
connect_entrance(swap_entrance, swap_exit, avail)
|
||||
@@ -1816,6 +1964,12 @@ modes = {
|
||||
'entrances': ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)',
|
||||
'Skull Woods Second Section Door (West)']
|
||||
},
|
||||
'skull_layout': {
|
||||
'special': 'vanilla',
|
||||
'condition': '',
|
||||
'entrances': ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)',
|
||||
'Skull Woods Second Section Door (West)']
|
||||
},
|
||||
'single_entrance_dungeon': {
|
||||
'entrances': ['Eastern Palace', 'Tower of Hera', 'Thieves Town', 'Skull Woods Final Section',
|
||||
'Palace of Darkness', 'Ice Palace', 'Misery Mire', 'Swamp Palace', 'Ganons Tower']
|
||||
@@ -1849,13 +2003,15 @@ modes = {
|
||||
'sanc_flag': 'light_world', # always light world flag
|
||||
'entrances': ['Eastern Palace', 'Tower of Hera', 'Thieves Town', 'Skull Woods Final Section',
|
||||
'Agahnims Tower', 'Palace of Darkness', 'Ice Palace', 'Misery Mire', 'Swamp Palace',
|
||||
'Ganons Tower'],
|
||||
'Ganons Tower', 'Desert Palace Entrance (North)', 'Dark Death Mountain Ledge (East)'],
|
||||
'connectors': [['Hyrule Castle Entrance (South)', 'Hyrule Castle Entrance (East)',
|
||||
'Hyrule Castle Entrance (West)'],
|
||||
['Desert Palace Entrance (South)', 'Desert Palace Entrance (East)',
|
||||
'Desert Palace Entrance (West)', 'Desert Palace Entrance (North)'],
|
||||
'Desert Palace Entrance (West)'],
|
||||
['Turtle Rock', 'Turtle Rock Isolated Ledge Entrance',
|
||||
'Dark Death Mountain Ledge (West)', 'Dark Death Mountain Ledge (East)']]
|
||||
'Dark Death Mountain Ledge (West)'],
|
||||
['Skull Woods Second Section Door (East)', 'Skull Woods Second Section Door (West)',
|
||||
'Skull Woods First Section Door']]
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -1878,7 +2034,8 @@ modes = {
|
||||
'special': 'normal_drops',
|
||||
'entrances': ['Hyrule Castle Secret Entrance Drop', 'Kakariko Well Drop', 'Bat Cave Drop',
|
||||
'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree',
|
||||
'Sanctuary Grave', 'Pyramid Hole']
|
||||
'Sanctuary Grave', 'Pyramid Hole',
|
||||
'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole']
|
||||
},
|
||||
'fixed_non_items': {
|
||||
'special': 'vanilla',
|
||||
@@ -1990,7 +2147,8 @@ modes = {
|
||||
'special': 'normal_drops',
|
||||
'entrances': ['Hyrule Castle Secret Entrance Drop', 'Kakariko Well Drop', 'Bat Cave Drop',
|
||||
'North Fairy Cave Drop', 'Lost Woods Hideout Drop', 'Lumberjack Tree Tree',
|
||||
'Sanctuary Grave', 'Pyramid Hole']
|
||||
'Sanctuary Grave', 'Pyramid Hole',
|
||||
'Skull Woods First Section Hole (North)', 'Skull Woods Second Section Hole']
|
||||
},
|
||||
'fixed_non_items': {
|
||||
'special': 'vanilla',
|
||||
@@ -2081,6 +2239,12 @@ modes = {
|
||||
'entrances': ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)',
|
||||
'Skull Woods Second Section Door (West)']
|
||||
},
|
||||
'skull_layout': {
|
||||
'special': 'vanilla',
|
||||
'condition': '',
|
||||
'entrances': ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)',
|
||||
'Skull Woods Second Section Door (West)']
|
||||
},
|
||||
'single_entrance_dungeon': {
|
||||
'entrances': ['Eastern Palace', 'Tower of Hera', 'Thieves Town', 'Skull Woods Final Section',
|
||||
'Palace of Darkness', 'Ice Palace', 'Misery Mire', 'Swamp Palace', 'Ganons Tower']
|
||||
@@ -2156,6 +2320,12 @@ modes = {
|
||||
'entrances': ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)',
|
||||
'Skull Woods Second Section Door (West)']
|
||||
},
|
||||
'skull_layout': {
|
||||
'special': 'vanilla',
|
||||
'condition': '',
|
||||
'entrances': ['Skull Woods First Section Door', 'Skull Woods Second Section Door (East)',
|
||||
'Skull Woods Second Section Door (West)']
|
||||
},
|
||||
'single_entrance_dungeon': {
|
||||
'entrances': ['Eastern Palace', 'Tower of Hera', 'Thieves Town', 'Skull Woods Final Section',
|
||||
'Palace of Darkness', 'Ice Palace', 'Misery Mire', 'Swamp Palace', 'Ganons Tower']
|
||||
@@ -2408,11 +2578,14 @@ linked_drop_map = {
|
||||
'Lumberjack Tree Tree': 'Lumberjack Tree Cave',
|
||||
'Sanctuary Grave': 'Sanctuary',
|
||||
'Pyramid Hole': 'Pyramid Entrance',
|
||||
'Inverted Pyramid Hole': 'Inverted Pyramid Entrance'
|
||||
'Inverted Pyramid Hole': 'Inverted Pyramid Entrance',
|
||||
|
||||
'Skull Woods First Section Hole (North)': 'Skull Woods First Section Door',
|
||||
'Skull Woods Second Section Hole': 'Skull Woods Second Section Door (East)',
|
||||
}
|
||||
|
||||
sw_linked_drop_map = {
|
||||
'Skull Woods Second Section Hole': 'Skull Woods Second Section Door (West)',
|
||||
'Skull Woods Second Section Hole': 'Skull Woods Second Section Door (East)',
|
||||
'Skull Woods First Section Hole (North)': 'Skull Woods First Section Door',
|
||||
'Skull Woods First Section Hole (West)': 'Skull Woods First Section Door',
|
||||
'Skull Woods First Section Hole (East)': 'Skull Woods First Section Door'
|
||||
@@ -2490,7 +2663,6 @@ entrance_map = {
|
||||
'Paradox Cave (Top)': 'Paradox Cave Exit (Top)'
|
||||
}
|
||||
|
||||
|
||||
single_entrance_map = {
|
||||
'Mimic Cave': 'Mimic Cave', 'Dark Death Mountain Fairy': 'Dark Death Mountain Healer Fairy',
|
||||
'Dark Death Mountain Shop': 'Dark Death Mountain Shop', 'Spike Cave': 'Spike Cave',
|
||||
@@ -2601,6 +2773,19 @@ Dungeon_Exit_Set = {
|
||||
'Turtle Rock Exit (Front)', 'Turtle Rock Isolated Ledge Exit', 'Turtle Rock Ledge Exit (West)'
|
||||
}
|
||||
|
||||
dungeon_restriction_checks = [
|
||||
(['Hyrule Castle Exit (South)', 'Hyrule Castle Exit (West)', 'Hyrule Castle Exit (East)', 'Sanctuary Exit'], ['Sewer Drop']),
|
||||
(['Desert Palace Exit (South)', 'Desert Palace Exit (East)', 'Desert Palace Exit (West)', 'Desert Palace Exit (North)'], []),
|
||||
(['Turtle Rock Exit (Front)', 'Turtle Rock Isolated Ledge Exit', 'Turtle Rock Ledge Exit (West)', 'Turtle Rock Ledge Exit (East)'], []),
|
||||
(['Skull Woods First Section Exit', 'Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)', 'Skull Woods Final Section Exit'],
|
||||
['Skull Pinball', 'Skull Left Drop', 'Skull Pot Circle', 'Skull Back Drop'])
|
||||
]
|
||||
|
||||
doors_possible_connectors = [
|
||||
'Sanctuary Exit', 'Desert Palace Exit (North)', 'Skull Woods First Section Exit',
|
||||
'Skull Woods Second Section Exit (East)', 'Skull Woods Second Section Exit (West)', 'Skull Woods Final Section Exit'
|
||||
]
|
||||
|
||||
# Entrances that cannot be used to access a must_exit entrance - symmetrical to allow reverse lookups
|
||||
Must_Exit_Invalid_Connections = defaultdict(set)
|
||||
|
||||
|
||||
@@ -173,6 +173,8 @@ def roll_settings(weights):
|
||||
ret.shuffleganon = get_choice_bool('shuffleganon')
|
||||
ret.shufflelinks = get_choice_bool('shufflelinks')
|
||||
ret.shuffletavern = get_choice_bool('shuffletavern')
|
||||
ret.skullwoods = get_choice('skullwoods')
|
||||
ret.linked_drops = get_choice('linked_drops')
|
||||
|
||||
ret.crystals_gt = get_choice('tower_open')
|
||||
ret.crystals_ganon = get_choice('ganon_open')
|
||||
|
||||
@@ -136,7 +136,7 @@ if __name__ == "__main__":
|
||||
error[2] = error[2].split("\n")
|
||||
results["errors"].append(error)
|
||||
|
||||
with open("new-test-suite-success.txt", "w") as stream:
|
||||
with open(os.path.join(LOGPATH, "new-test-suite-success.txt"), 'w') as stream:
|
||||
stream.write(str.join("\n", successes))
|
||||
results["success"] = successes
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ meta:
|
||||
players: 1
|
||||
settings:
|
||||
1:
|
||||
key_logic_algorithm: default
|
||||
key_logic_algorithm: dangerous
|
||||
keysanity: True
|
||||
crystals_needed_for_gt: 0 # to skip trash fill
|
||||
placements:
|
||||
|
||||
Reference in New Issue
Block a user