2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import logging
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import os
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-16 02:40:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import random
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import threading
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import typing
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-22 15:51:50 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-11-29 05:02:26 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import settings
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-14 15:22:39 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from BaseClasses import Item, CollectionState, Tutorial, MultiWorld
							 | 
						
					
						
							
								
									
										
										
										
											2024-11-29 05:02:26 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from worlds.AutoWorld import World, WebWorld, LogicMixin
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from .Client import ALTTPSNIClient
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Dungeons import create_dungeons, Dungeon
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												ALttP: Use auto indirect conditions (#4153)
ALttP makes common use of entrances with access rules that require
another entrance to be accessible. This results in requiring an indirect
condition to be registered for the other entrance's `.parent_region`,
but this indirect condition is often missing.
There are so many missing indirect conditions, and due to the complexity
of some of the chained rules, it is simply not realistic to add all the
missing indirect conditions.
This patch changes ALttP to use automatic indirect conditions instead of
explicit indirect conditions and removes the places that were
registering indirect conditions.
Without this patch, the missing indirect conditions almost never have an
effect on generating with default options, but enabling certain options,
such as `glitches_required` or `entrance_shuffle` can result in
frequently checking entrances that are missing indirect conditions.
Examples of complex chained rules:
`get_rule_to_add()` in `Rules.set_bunny_rules()` can create
rules on entrances that require access to any of a number of different
other entrances, which should require the parent regions of all of those
other entrances to be registered as indirect conditions.
There are entrance access rules that check
`StateHelpers.can_kill_most_things()` (e.g. `Turtle Rock Second Section
Bomb Wall`), which can check `can_extend_magic()`, which checks for
being able to buy unlimited `Blue Potion`, which checks for being able
to reach a shop that sells unlimited `Blue Potion`. This is usually
`Potion Shop`, but there is a yaml option that shuffles shop
inventories, so the shop that sells unlimited `Blue Potion` can be
randomized, meaning that the region that should be registered as an
indirect condition can also be randomized.
Example of many missing indirect conditions:
With `small_key_shuffle: universal`, every single
`ALttPLogic._lttp_has_key()` checks for being able to reach shops that
sell an unlimited number of universal Small Keys. Meaning that every
entrance access rule that uses `_lttp_has_key()` should register all
shop regions that sell unlimited universal small keys as indirect
conditions.
											
										 
										
											2024-11-07 08:29:47 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .EntranceShuffle import link_entrances, link_inverted_entrances, plando_connect
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-16 02:40:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .InvertedRegions import create_inverted_regions, mark_dark_world_regions
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from .ItemPool import generate_itempool, difficulties
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-06 00:49:54 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem
							 | 
						
					
						
							
								
									
										
										
										
											2024-11-29 05:02:26 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Options import ALTTPOptions, small_key_shuffle
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-18 14:30:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \
							 | 
						
					
						
							
								
									
										
										
										
											2023-09-26 23:24:10 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    is_main_entrance, key_drop_data
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-10 13:21:52 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    get_hash_string, get_base_rom_path, LttPDeltaPatch
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-16 02:40:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Rules import set_rules
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-19 19:07:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .Shops import create_shops, Shop, push_shop_inventories, ShopType, price_rate_display, price_type_display_name
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-03 23:23:52 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .StateHelpers import can_buy_unlimited
							 | 
						
					
						
							
								
									
										
										
										
											2024-11-29 05:02:26 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .SubClasses import ALttPItem, LTTPRegionType
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-24 05:38:56 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								lttp_logger = logging.getLogger("A Link to the Past")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-10 07:23:03 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								extras_list = sum(difficulties['normal'].extras[0:5], [])
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-18 14:30:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class ALTTPSettings(settings.Group):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    class RomFile(settings.SNESRomPath):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        """File name of the v1.0 J rom"""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        description = "ALTTP v1.0 J ROM File"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        copy_to = "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        md5s = [LttPDeltaPatch.hash]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    rom_file: RomFile = RomFile(RomFile.copy_to)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class ALTTPWeb(WebWorld):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    setup_en = Tutorial(
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-20 11:22:32 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Multiworld Setup Guide",
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "A guide to setting up the Archipelago ALttP Software on your computer. This guide covers single-player, multiworld, and related software.",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "English",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld_en.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld/en",
							 | 
						
					
						
							
								
									
										
										
										
											2023-06-16 16:26:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        ["Farrak Kilhn", "Berserker"]
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    setup_de = Tutorial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        setup_en.tutorial_name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        setup_en.description,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Deutsch",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld_de.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld/de",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ["Fischfilet"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    setup_es = Tutorial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        setup_en.tutorial_name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        setup_en.description,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Español",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld_es.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld/es",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ["Edos"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    setup_fr = Tutorial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        setup_en.tutorial_name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        setup_en.description,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Français",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld_fr.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "multiworld/fr",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ["Coxla"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    msu = Tutorial(
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-20 11:22:32 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "MSU-1 Setup Guide",
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "A guide to setting up MSU-1, which allows for custom in-game music.",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "English",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "msu1_en.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "msu1/en",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ["Farrak Kilhn"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    msu_es = Tutorial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        msu.tutorial_name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        msu.description,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Español",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "msu1_es.md",
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-25 06:15:57 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "msu1/es",
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        ["Edos"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    msu_fr = Tutorial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        msu.tutorial_name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        msu.description,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Français",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "msu1_fr.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "msu1/fr",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ["Coxla"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    plando = Tutorial(
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-20 11:22:32 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Plando Guide",
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "A guide to creating Multiworld Plandos with LTTP",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "English",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "plando_en.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "plando/en",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ["Berserker"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-10 19:31:57 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    oof_sound = Tutorial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "'OOF' Sound Replacement",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "A guide to customizing Link's 'oof' sound",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "English",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "oof_sound_en.md",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "oof_sound/en",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ["Nyx Edelstein"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    tutorials = [setup_en, setup_de, setup_es, setup_fr, msu, msu_es, msu_fr, plando, oof_sound]
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-04 17:11:45 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    game_info_languages = ["en", "fr"]
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class ALTTPWorld(World):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-31 17:28:46 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    The Legend of Zelda: A Link to the Past is an action/adventure game. Take on the role of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Link, a boy who is destined to save the land of Hyrule. Delve through three palaces and nine
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dungeons on your quest to rescue the descendents of the seven wise men and defeat the evil
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Ganon!
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-26 10:48:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    game = "A Link to the Past"
							 | 
						
					
						
							
								
									
										
										
										
											2024-11-29 05:02:26 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    options_dataclass = ALTTPOptions
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    options: ALTTPOptions
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    settings_key = "lttp_options"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    settings: typing.ClassVar[ALTTPSettings]
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-08 11:07:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    topology_present = True
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												ALttP: Use auto indirect conditions (#4153)
ALttP makes common use of entrances with access rules that require
another entrance to be accessible. This results in requiring an indirect
condition to be registered for the other entrance's `.parent_region`,
but this indirect condition is often missing.
There are so many missing indirect conditions, and due to the complexity
of some of the chained rules, it is simply not realistic to add all the
missing indirect conditions.
This patch changes ALttP to use automatic indirect conditions instead of
explicit indirect conditions and removes the places that were
registering indirect conditions.
Without this patch, the missing indirect conditions almost never have an
effect on generating with default options, but enabling certain options,
such as `glitches_required` or `entrance_shuffle` can result in
frequently checking entrances that are missing indirect conditions.
Examples of complex chained rules:
`get_rule_to_add()` in `Rules.set_bunny_rules()` can create
rules on entrances that require access to any of a number of different
other entrances, which should require the parent regions of all of those
other entrances to be registered as indirect conditions.
There are entrance access rules that check
`StateHelpers.can_kill_most_things()` (e.g. `Turtle Rock Second Section
Bomb Wall`), which can check `can_extend_magic()`, which checks for
being able to buy unlimited `Blue Potion`, which checks for being able
to reach a shop that sells unlimited `Blue Potion`. This is usually
`Potion Shop`, but there is a yaml option that shuffles shop
inventories, so the shop that sells unlimited `Blue Potion` can be
randomized, meaning that the region that should be registered as an
indirect condition can also be randomized.
Example of many missing indirect conditions:
With `small_key_shuffle: universal`, every single
`ALttPLogic._lttp_has_key()` checks for being able to reach shops that
sell an unlimited number of universal Small Keys. Meaning that every
entrance access rule that uses `_lttp_has_key()` should register all
shop regions that sell unlimited universal small keys as indirect
conditions.
											
										 
										
											2024-11-07 08:29:47 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    explicit_indirect_conditions = False
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 13:54:47 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    item_name_groups = item_name_groups
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    location_name_groups = {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Blind's Hideout": {"Blind's Hideout - Top", "Blind's Hideout - Left", "Blind's Hideout - Right",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            "Blind's Hideout - Far Left", "Blind's Hideout - Far Right"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Kakariko Well": {"Kakariko Well - Top", "Kakariko Well - Left", "Kakariko Well - Middle",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Kakariko Well - Right", "Kakariko Well - Bottom"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Mini Moldorm Cave": {"Mini Moldorm Cave - Far Left", "Mini Moldorm Cave - Left", "Mini Moldorm Cave - Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                              "Mini Moldorm Cave - Far Right", "Mini Moldorm Cave - Generous Guy"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Paradox Cave": {"Paradox Cave Lower - Far Left", "Paradox Cave Lower - Left", "Paradox Cave Lower - Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Paradox Cave Lower - Far Right", "Paradox Cave Lower - Middle", "Paradox Cave Upper - Left",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Paradox Cave Upper - Right"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Hype Cave": {"Hype Cave - Top", "Hype Cave - Middle Right", "Hype Cave - Middle Left",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      "Hype Cave - Bottom", "Hype Cave - Generous Guy"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Hookshot Cave": {"Hookshot Cave - Top Right", "Hookshot Cave - Top Left", "Hookshot Cave - Bottom Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Hookshot Cave - Bottom Left"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Hyrule Castle": {"Hyrule Castle - Boomerang Chest", "Hyrule Castle - Map Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          "Hyrule Castle - Zelda's Chest", "Hyrule Castle - Big Key Drop",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Hyrule Castle - Boomerang Guard Key Drop", "Hyrule Castle - Map Guard Key Drop",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Sewers - Dark Cross", "Sewers - Secret Room - Left",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Sewers - Secret Room - Middle", "Sewers - Secret Room - Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Sewers - Key Rat Key Drop"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Eastern Palace": {"Eastern Palace - Compass Chest", "Eastern Palace - Big Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           "Eastern Palace - Cannonball Chest", "Eastern Palace - Big Key Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                           "Eastern Palace - Dark Eyegore Key Drop", "Eastern Palace - Dark Square Pot Key",
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                           "Eastern Palace - Map Chest", "Eastern Palace - Boss"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Desert Palace": {"Desert Palace - Big Chest", "Desert Palace - Torch", "Desert Palace - Map Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          "Desert Palace - Beamos Hall Pot Key", "Desert Palace - Desert Tiles 1 Pot Key",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Desert Palace - Desert Tiles 2 Pot Key", "Desert Palace - Compass Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Desert Palace - Big Key Chest", "Desert Palace - Boss"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Tower of Hera": {"Tower of Hera - Basement Cage", "Tower of Hera - Map Chest", "Tower of Hera - Big Key Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Tower of Hera - Compass Chest", "Tower of Hera - Big Chest", "Tower of Hera - Boss"},
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Castle Tower": {"Castle Tower - Room 03", "Castle Tower - Dark Maze",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Castle Tower - Dark Archer Key Drop", "Castle Tower - Circle of Pots Key Drop"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Palace of Darkness": {"Palace of Darkness - Shooter Room", "Palace of Darkness - The Arena - Bridge",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "Palace of Darkness - Stalfos Basement", "Palace of Darkness - Big Key Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "Palace of Darkness - The Arena - Ledge", "Palace of Darkness - Map Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "Palace of Darkness - Compass Chest", "Palace of Darkness - Dark Basement - Left",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "Palace of Darkness - Dark Basement - Right", "Palace of Darkness - Dark Maze - Top",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "Palace of Darkness - Dark Maze - Bottom", "Palace of Darkness - Big Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "Palace of Darkness - Harmless Hellway", "Palace of Darkness - Boss"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 13:04:20 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Swamp Palace": {"Swamp Palace - Entrance", "Swamp Palace - Map Chest", "Swamp Palace - Big Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Swamp Palace - Compass Chest", "Swamp Palace - Big Key Chest", "Swamp Palace - West Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Swamp Palace - Flooded Room - Left", "Swamp Palace - Flooded Room - Right",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         "Swamp Palace - Hookshot Pot Key", "Swamp Palace - Pot Row Pot Key",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Swamp Palace - Trench 1 Pot Key", "Swamp Palace - Trench 2 Pot Key",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Swamp Palace - Waterway Pot Key", "Swamp Palace - Waterfall Room", "Swamp Palace - Boss"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Thieves' Town": {"Thieves' Town - Big Key Chest", "Thieves' Town - Map Chest", "Thieves' Town - Compass Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Thieves' Town - Ambush Chest", "Thieves' Town - Attic", "Thieves' Town - Big Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          "Thieves' Town - Hallway Pot Key", "Thieves' Town - Spike Switch Pot Key",
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          "Thieves' Town - Blind's Cell", "Thieves' Town - Boss"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Skull Woods": {"Skull Woods - Map Chest", "Skull Woods - Pinball Room", "Skull Woods - Compass Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Skull Woods - Pot Prison", "Skull Woods - Big Chest", "Skull Woods - Big Key Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Skull Woods - Spike Corner Key Drop", "Skull Woods - West Lobby Pot Key",
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Skull Woods - Bridge Room", "Skull Woods - Boss"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Ice Palace": {"Ice Palace - Compass Chest", "Ice Palace - Freezor Chest", "Ice Palace - Big Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                       "Ice Palace - Freezor Chest", "Ice Palace - Big Chest", "Ice Palace - Iced T Room",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                       "Ice Palace - Spike Room", "Ice Palace - Big Key Chest", "Ice Palace - Map Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                       "Ice Palace - Conveyor Key Drop", "Ice Palace - Hammer Block Key Drop",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                       "Ice Palace - Jelly Key Drop", "Ice Palace - Many Pots Pot Key",
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                       "Ice Palace - Boss"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Misery Mire": {"Misery Mire - Big Chest", "Misery Mire - Map Chest", "Misery Mire - Main Lobby",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Misery Mire - Bridge Chest", "Misery Mire - Spike Chest", "Misery Mire - Compass Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Misery Mire - Conveyor Crystal Key Drop", "Misery Mire - Fishbone Pot Key",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Misery Mire - Spikes Pot Key", "Misery Mire - Big Key Chest", "Misery Mire - Boss"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Turtle Rock": {"Turtle Rock - Compass Chest", "Turtle Rock - Roller Room - Left",
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 13:04:20 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Turtle Rock - Roller Room - Right", "Turtle Rock - Chain Chomps", "Turtle Rock - Big Key Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Turtle Rock - Big Chest", "Turtle Rock - Crystaroller Room",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Turtle Rock - Eye Bridge - Bottom Left", "Turtle Rock - Eye Bridge - Bottom Right",
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 13:04:20 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Turtle Rock - Eye Bridge - Top Left", "Turtle Rock - Eye Bridge - Top Right",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Turtle Rock - Pokey 1 Key Drop", "Turtle Rock - Pokey 2 Key Drop",
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 13:04:20 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Turtle Rock - Boss"},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "Ganons Tower": {"Ganons Tower - Bob's Torch", "Ganons Tower - Hope Room - Left",
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Hope Room - Right", "Ganons Tower - Tile Room",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Compass Room - Top Left", "Ganons Tower - Compass Room - Top Right",
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-23 21:36:05 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Compass Room - Bottom Left", "Ganons Tower - Compass Room - Bottom Right",
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - DMs Room - Top Left", "Ganons Tower - DMs Room - Top Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - DMs Room - Bottom Left", "Ganons Tower - DMs Room - Bottom Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Map Chest", "Ganons Tower - Firesnake Room",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Randomizer Room - Top Left", "Ganons Tower - Randomizer Room - Top Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Randomizer Room - Bottom Left", "Ganons Tower - Randomizer Room - Bottom Right",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Bob's Chest", "Ganons Tower - Big Chest", "Ganons Tower - Big Key Room - Left",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Big Key Room - Right", "Ganons Tower - Big Key Chest",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Conveyor Cross Pot Key", "Ganons Tower - Conveyor Star Pits Pot Key",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Double Switch Pot Key", "Ganons Tower - Mini Helmasaur Room - Left",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Mini Helmasaur Room - Right", "Ganons Tower - Pre-Moldorm Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "Ganons Tower - Mini Helmasaur Key Drop", "Ganons Tower - Validation Chest"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        "Ganons Tower Climb": {"Ganons Tower - Mini Helmasaur Room - Left", "Ganons Tower - Mini Helmasaur Room - Right",
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 14:50:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               "Ganons Tower - Mini Helmasaur Key Drop", "Ganons Tower - Pre-Moldorm Chest",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "Ganons Tower - Validation Chest"},
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-08 15:15:28 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    }
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 15:33:20 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    hint_blacklist = {"Triforce"}
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-08 11:07:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    item_name_to_id = {name: data.item_code for name, data in item_table.items() if type(data.item_code) == int}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    location_name_to_id = lookup_name_to_id
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-26 10:48:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    required_client_version = (0, 4, 1)
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    web = ALTTPWeb()
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-13 19:14:57 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-08-01 22:30:30 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    shops: list[Shop]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-06 00:49:54 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    pedestal_credit_texts: typing.Dict[int, str] = \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {data.item_code: data.pedestal_credit for data in item_table.values() if data.pedestal_credit}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    sickkid_credit_texts: typing.Dict[int, str] = \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {data.item_code: data.sick_kid_credit for data in item_table.values() if data.sick_kid_credit}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    zora_credit_texts: typing.Dict[int, str] = \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {data.item_code: data.zora_credit for data in item_table.values() if data.zora_credit}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    magicshop_credit_texts: typing.Dict[int, str] = \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {data.item_code: data.witch_credit for data in item_table.values() if data.witch_credit}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    fluteboy_credit_texts: typing.Dict[int, str] = \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {data.item_code: data.flute_boy_credit for data in item_table.values() if data.flute_boy_credit}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-22 15:51:50 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    set_rules = set_rules
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    create_items = generate_itempool
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    _enemizer_path: typing.ClassVar[typing.Optional[str]] = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    @property
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def enemizer_path(self) -> str:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # TODO: directly use settings
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        cls = self.__class__
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if cls._enemizer_path is None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            cls._enemizer_path = settings.get_settings().generator.enemizer_path
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            assert isinstance(cls._enemizer_path, str)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return cls._enemizer_path
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-30 17:12:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # custom instance vars
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dungeon_local_item_names: typing.Set[str]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dungeon_specific_item_names: typing.Set[str]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    rom_name_available_event: threading.Event
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    has_progressive_bows: bool
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dungeons: typing.Dict[str, Dungeon]
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    waterfall_fairy_bottle_fill: str
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    pyramid_fairy_bottle_fill: str
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    escape_assist: list
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    can_take_damage: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    swamp_patch_required: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    powder_patch_required: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ganon_at_pyramid: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ganonstower_vanilla: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    fix_fake_world: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    clock_mode: str = ""
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-27 19:48:59 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    treasure_hunt_required: int = 0
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    treasure_hunt_total: int = 0
							 | 
						
					
						
							
								
									
										
										
										
											2025-08-01 22:30:30 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    light_world_light_cone: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    dark_world_light_cone: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    save_and_quit_from_boss: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    rupoor_cost: int = 10
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 16:31:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __init__(self, *args, **kwargs):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.dungeon_local_item_names = set()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.dungeon_specific_item_names = set()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.rom_name_available_event = threading.Event()
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-03 19:52:03 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.pushed_shop_inventories = threading.Event()
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-20 01:00:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.has_progressive_bows = False
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.dungeons = {}
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.waterfall_fairy_bottle_fill = "Bottle"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.pyramid_fairy_bottle_fill = "Bottle"
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-14 11:30:40 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.fix_trock_doors = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.fix_skullwoods_exit = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.fix_palaceofdarkness_exit = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.fix_trock_exit = None
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.required_medallions = ["Ether", "Quake"]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.escape_assist = []
							 | 
						
					
						
							
								
									
										
										
										
											2025-08-01 22:30:30 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.shops = []
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 16:31:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        super(ALTTPWorld, self).__init__(*args, **kwargs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-29 20:37:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-14 15:22:39 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def stage_assert_generate(cls, multiworld: MultiWorld):
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-29 20:37:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        rom_file = get_base_rom_path()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not os.path.exists(rom_file):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise FileNotFoundError(rom_file)
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-14 15:22:39 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if multiworld.is_race:
							 | 
						
					
						
							
								
									
										
										
										
											2024-11-29 05:02:26 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            import xxtea  # noqa
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-14 15:22:39 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        for player in multiworld.get_game_players(cls.game):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if multiworld.worlds[player].use_enemizer:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                check_enemizer(multiworld.worlds[player].enemizer_path)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                break
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-29 20:37:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def generate_early(self):
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        multiworld = self.multiworld
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 16:31:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.fix_trock_doors = (self.options.entrance_shuffle != 'vanilla' or self.options.mode == 'inverted')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.fix_skullwoods_exit = self.options.entrance_shuffle not in ['vanilla', 'simple', 'restricted', 'dungeons_simple']
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.fix_palaceofdarkness_exit = self.options.entrance_shuffle not in ['dungeons_simple', 'vanilla', 'simple', 'restricted']
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.fix_trock_exit = self.options.entrance_shuffle not in ['vanilla', 'simple', 'restricted', 'dungeons_simple']
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-14 11:30:40 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # fairy bottle fills
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        bottle_options = [
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            "Bottle (Red Potion)", "Bottle (Green Potion)", "Bottle (Blue Potion)",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            "Bottle (Bee)", "Bottle (Good Bee)"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ]
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.item_pool not in ["hard", "expert"]:
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            bottle_options.append("Bottle (Fairy)")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.waterfall_fairy_bottle_fill = self.random.choice(bottle_options)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.pyramid_fairy_bottle_fill = self.random.choice(bottle_options)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.mode == 'standard':
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if self.options.small_key_shuffle:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if (self.options.small_key_shuffle not in
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        (small_key_shuffle.option_universal, small_key_shuffle.option_own_dungeons,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         small_key_shuffle.option_start_with)):
							 | 
						
					
						
							
								
									
										
										
										
											2023-12-09 13:33:51 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    self.multiworld.local_early_items[self.player]["Small Key (Hyrule Castle)"] = 1
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.options.local_items.value.add("Small Key (Hyrule Castle)")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self.options.non_local_items.value.discard("Small Key (Hyrule Castle)")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if self.options.big_key_shuffle:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self.options.local_items.value.add("Big Key (Hyrule Castle)")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self.options.non_local_items.value.discard("Big Key (Hyrule Castle)")
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-15 09:34:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # system for sharing ER layouts
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.er_seed = str(multiworld.random.randint(0, 2 ** 64))
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.entrance_shuffle != "vanilla" and self.options.entrance_shuffle_seed != "random":
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            shuffle = self.options.entrance_shuffle.current_key
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if shuffle == "vanilla":
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-06 11:32:49 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.er_seed = "vanilla"
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            elif (not self.options.entrance_shuffle_seed.value.isdigit()) or multiworld.is_race:
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.er_seed = get_same_seed(multiworld, (
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    shuffle, self.options.entrance_shuffle_seed.value,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.options.retro_caves,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.options.mode,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.options.glitches_required
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                ))
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            else:  # not a race or group seed, use set seed as is.
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.er_seed = int(self.options.entrance_shuffle_seed.value)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif self.options.entrance_shuffle == "vanilla":
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-06 11:32:49 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            self.er_seed = "vanilla"
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-19 19:07:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for dungeon_item in ["small_key_shuffle", "big_key_shuffle", "compass_shuffle", "map_shuffle"]:
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            option = getattr(self.options, dungeon_item)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 16:31:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if option == "own_world":
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.options.local_items.value |= self.item_name_groups[option.item_name_group]
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 16:31:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            elif option == "different_world":
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.options.non_local_items.value |= self.item_name_groups[option.item_name_group]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if self.options.mode == "standard":
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.options.non_local_items.value -= {"Small Key (Hyrule Castle)"}
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 16:31:56 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            elif option.in_dungeon:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self.dungeon_local_item_names |= self.item_name_groups[option.item_name_group]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if option == "original_dungeon":
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.dungeon_specific_item_names |= self.item_name_groups[option.item_name_group]
							 | 
						
					
						
							
								
									
										
										
										
											2024-08-24 03:54:33 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self.options.local_items.value |= self.dungeon_local_item_names
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.difficulty_requirements = difficulties[self.options.item_pool.current_key]
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-28 07:03:09 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # enforce pre-defined local items.
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.goal in ["local_triforce_hunt", "local_ganon_triforce_hunt"]:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self.options.local_items.value.add('Triforce Piece')
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-28 07:03:09 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Not possible to place crystals outside boss prizes yet (might as well make it consistent with pendants too).
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.options.non_local_items.value -= item_name_groups['Pendants']
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.options.non_local_items.value -= item_name_groups['Crystals']
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-28 07:03:09 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    create_dungeons = create_dungeons
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-22 15:51:50 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def create_regions(self):
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        player = self.player
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        multiworld = self.multiworld
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.mode != 'inverted':
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            create_regions(multiworld, player)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        else:
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            create_inverted_regions(multiworld, player)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        create_shops(multiworld, player)
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.create_dungeons()
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if (self.options.glitches_required not in ["no_glitches", "minor_glitches"] and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self.options.entrance_shuffle in [
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    "vanilla", "dungeons_simple", "dungeons_full", "simple", "restricted", "full"]):
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            self.fix_fake_world = False
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # seeded entrance shuffle
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        old_random = multiworld.random
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        multiworld.random = random.Random(self.er_seed)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.mode != 'inverted':
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            link_entrances(multiworld, player)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            mark_light_world_regions(multiworld, player)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        else:
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            link_inverted_entrances(multiworld, player)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            mark_dark_world_regions(multiworld, player)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-23 12:03:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-03 19:49:39 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        multiworld.random = old_random
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        plando_connect(multiworld, player)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-22 15:51:50 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def collect_item(self, state: CollectionState, item: Item, remove=False):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        item_name = item.name
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if item_name.startswith('Progressive '):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if remove:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if 'Sword' in item_name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Golden Sword', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Golden Sword'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Tempered Sword', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Tempered Sword'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Master Sword', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Master Sword'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Fighter Sword', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Fighter Sword'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif 'Glove' in item.name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Titans Mitts', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Titans Mitts'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Power Glove', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Power Glove'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif 'Shield' in item_name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Mirror Shield', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Mirror Shield'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Red Shield', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Red Shield'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Blue Shield', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Blue Shield'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif 'Bow' in item_name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Silver Bow', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Silver Bow'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Bow', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Bow'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if 'Sword' in item_name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Golden Sword', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        pass
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif (state.has('Tempered Sword', item.player) and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          self.difficulty_requirements.progressive_sword_limit >= 4):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Golden Sword'
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif (state.has('Master Sword', item.player) and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          self.difficulty_requirements.progressive_sword_limit >= 3):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Tempered Sword'
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif (state.has('Fighter Sword', item.player) and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          self.difficulty_requirements.progressive_sword_limit >= 2):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Master Sword'
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif self.difficulty_requirements.progressive_sword_limit >= 1:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Fighter Sword'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif 'Glove' in item_name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Titans Mitts', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Power Glove', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Titans Mitts'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return 'Power Glove'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif 'Shield' in item_name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Mirror Shield', item.player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        return
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif (state.has('Red Shield', item.player) and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          self.difficulty_requirements.progressive_shield_limit >= 3):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Mirror Shield'
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif (state.has('Blue Shield', item.player) and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          self.difficulty_requirements.progressive_shield_limit >= 2):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Red Shield'
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif self.difficulty_requirements.progressive_shield_limit >= 1:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Blue Shield'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif 'Bow' in item_name:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-26 16:03:22 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    if state.has('Silver Bow', item.player):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif state.has('Bow', item.player) and (self.difficulty_requirements.progressive_bow_limit >= 2
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                                            or self.options.glitches_required == 'no_glitches'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                            or self.options.swordless):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # modes where silver bow is always required for ganon
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Silver Bow'
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    elif self.difficulty_requirements.progressive_bow_limit >= 1:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        return 'Bow'
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        elif item.advancement:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return item_name
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-24 05:38:56 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def pre_fill(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        from Fill import fill_restrictive, FillError
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        attempts = 5
							 | 
						
					
						
							
								
									
										
										
										
											2025-07-21 14:53:34 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        all_state = self.multiworld.get_all_state(perform_sweep=False)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        crystals = [self.create_item(name) for name in ['Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5', 'Crystal 6']]
							 | 
						
					
						
							
								
									
										
										
										
											2025-05-10 17:49:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        for crystal in crystals:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            all_state.remove(crystal)
							 | 
						
					
						
							
								
									
										
										
										
											2025-07-21 14:53:34 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        all_state.sweep_for_advancements()
							 | 
						
					
						
							
								
									
										
										
										
											2025-05-10 17:49:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        crystal_locations = [self.get_location('Turtle Rock - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Eastern Palace - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Desert Palace - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Tower of Hera - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Palace of Darkness - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Thieves\' Town - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Skull Woods - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Swamp Palace - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Ice Palace - Prize'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             self.get_location('Misery Mire - Prize')]
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        placed_prizes = {loc.item.name for loc in crystal_locations if loc.item}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        unplaced_prizes = [crystal for crystal in crystals if crystal.name not in placed_prizes]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        empty_crystal_locations = [loc for loc in crystal_locations if not loc.item]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for attempt in range(attempts):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                prizepool = unplaced_prizes.copy()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                prize_locs = empty_crystal_locations.copy()
							 | 
						
					
						
							
								
									
										
										
										
											2025-05-10 17:49:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                self.multiworld.random.shuffle(prize_locs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                fill_restrictive(self.multiworld, all_state, prize_locs, prizepool, True, lock=True,
							 | 
						
					
						
							
								
									
										
										
										
											2023-10-30 01:22:00 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                 name="LttP Dungeon Prizes")
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            except FillError as e:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                lttp_logger.exception("Failed to place dungeon prizes (%s). Will retry %s more times", e,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                attempts - attempt)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                for location in empty_crystal_locations:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    location.item = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            break
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise FillError('Unable to place dungeon prizes')
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.mode == 'standard' and self.options.small_key_shuffle \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                and self.options.small_key_shuffle != small_key_shuffle.option_universal and \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self.options.small_key_shuffle != small_key_shuffle.option_own_dungeons:
							 | 
						
					
						
							
								
									
										
										
										
											2025-05-10 17:49:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            self.multiworld.local_early_items[self.player]["Small Key (Hyrule Castle)"] = 1
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def stage_pre_fill(cls, world):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        from .Dungeons import fill_dungeons_restrictive
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-13 23:02:18 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        fill_dungeons_restrictive(world)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 01:16:04 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-03 19:52:03 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def stage_generate_output(cls, multiworld, output_directory):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        push_shop_inventories(multiworld)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 01:16:04 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-14 15:22:39 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @property
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def use_enemizer(self) -> bool:
							 | 
						
					
						
							
								
									
										
										
										
											2024-11-29 05:02:26 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return bool(self.options.boss_shuffle or self.options.enemy_shuffle
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    or self.options.enemy_health != 'default' or self.options.enemy_damage != 'default'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    or self.options.pot_shuffle or self.options.bush_shuffle
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    or self.options.killable_thieves)
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-10 13:21:52 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def generate_output(self, output_directory: str):
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        multiworld = self.multiworld
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        player = self.player
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-03 19:52:03 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.pushed_shop_inventories.wait()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-14 15:22:39 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            use_enemizer = self.use_enemizer
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-18 22:13:19 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            rom = LocalRom(get_base_rom_path())
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            patch_rom(multiworld, rom, player, use_enemizer)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if use_enemizer:
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                patch_enemizer(self, rom, self.enemizer_path, output_directory)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if multiworld.is_race:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                patch_race_rom(rom, multiworld, player)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            multiworld.spoiler.hashes[player] = get_hash_string(rom.hash)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            palettes_options = {
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                'dungeon': self.options.uw_palettes,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                'overworld': self.options.ow_palettes,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                'hud': self.options.hud_palettes,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                'sword': self.options.sword_palettes,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                'shield': self.options.shield_palettes,
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-07 11:16:32 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                # 'link': world.link_palettes[player]
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            palettes_options = {key: option.current_key for key, option in palettes_options.items()}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            apply_rom_settings(rom, self.options.heartbeep.current_key,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               self.options.heartcolor.current_key,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               self.options.quickswap,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               self.options.menuspeed.current_key,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               self.options.music,
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               multiworld.sprite[player],
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-10 19:31:57 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               None,
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               palettes_options, multiworld, player, True,
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               reduceflashing=self.options.reduceflashing or multiworld.is_race,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               triforcehud=self.options.triforcehud.current_key,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               deathlink=self.options.death_link,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               allowcollect=self.options.allow_collect)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            rompath = os.path.join(output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}.sfc")
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-15 01:02:06 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            rom.write_to_file(rompath)
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            patch = LttPDeltaPatch(os.path.splitext(rompath)[0]+LttPDeltaPatch.patch_file_ending, player=player,
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                   player_name=multiworld.player_name[player], patched_path=rompath)
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            patch.write()
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            os.unlink(rompath)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self.rom_name = rom.name
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self.rom_name_available_event.set() # make sure threading continues and errors are collected
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-18 14:30:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def stage_extend_hint_information(cls, world, hint_data: typing.Dict[int, typing.Dict[int, str]]):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        er_hint_data = {player: {} for player in world.get_game_players("A Link to the Past") if
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        world.worlds[player].options.entrance_shuffle != "vanilla" or world.worlds[player].options.retro_caves}
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-18 14:30:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for region in world.regions:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if region.player in er_hint_data and region.locations:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                main_entrance = region.get_connecting_entrance(is_main_entrance)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                for location in region.locations:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if type(location.address) == int:  # skips events and crystals
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        if lookup_vanilla_location_to_entrance[location.address] != main_entrance.name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            er_hint_data[region.player][location.address] = main_entrance.name
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        hint_data.update(er_hint_data)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-02 13:00:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def stage_modify_multidata(cls, multiworld, multidata: dict):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ordered_areas = (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            'Light World', 'Dark World', 'Hyrule Castle', 'Agahnims Tower', 'Eastern Palace', 'Desert Palace',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            'Tower of Hera', 'Palace of Darkness', 'Swamp Palace', 'Skull Woods', 'Thieves Town', 'Ice Palace',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            'Misery Mire', 'Turtle Rock', 'Ganons Tower', "Total"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        checks_in_area = {player: {area: list() for area in ordered_areas}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          for player in multiworld.get_game_players(cls.game)}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for player in checks_in_area:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            checks_in_area[player]["Total"] = 0
							 | 
						
					
						
							
								
									
										
										
										
											2023-10-29 19:47:37 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            for location in multiworld.get_locations(player):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if location.game == cls.game and type(location.address) is int:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    main_entrance = location.parent_region.get_connecting_entrance(is_main_entrance)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if location.parent_region.dungeon:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        dungeonname = {'Inverted Agahnims Tower': 'Agahnims Tower',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                       'Inverted Ganons Tower': 'Ganons Tower'} \
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            .get(location.parent_region.dungeon.name, location.parent_region.dungeon.name)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        checks_in_area[location.player][dungeonname].append(location.address)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif location.parent_region.type == LTTPRegionType.LightWorld:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        checks_in_area[location.player]["Light World"].append(location.address)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif location.parent_region.type == LTTPRegionType.DarkWorld:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        checks_in_area[location.player]["Dark World"].append(location.address)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif main_entrance.parent_region.type == LTTPRegionType.LightWorld:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        checks_in_area[location.player]["Light World"].append(location.address)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    elif main_entrance.parent_region.type == LTTPRegionType.DarkWorld:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        checks_in_area[location.player]["Dark World"].append(location.address)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        assert False, "Unknown Location area."
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # TODO: remove Total as it's duplicated data and breaks consistent typing
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    checks_in_area[location.player]["Total"] += 1
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-02 13:00:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        multidata["checks_in_area"].update(checks_in_area)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def modify_multidata(self, multidata: dict):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        import base64
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # wait for self.rom_name to be available.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.rom_name_available_event.wait()
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        rom_name = getattr(self, "rom_name", None)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # we skip in case of error, so that the original error in the output thread is the one that gets raised
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if rom_name:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            new_name = base64.b64encode(bytes(self.rom_name)).decode()
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            multidata["connect_names"][new_name] = multidata["connect_names"][self.multiworld.player_name[self.player]]
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 13:54:47 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def create_item(self, name: str) -> Item:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-06 00:49:54 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return ALttPItem(name, self.player, **item_init_table[name])
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 13:54:47 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-11 04:00:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def stage_fill_hook(cls, multiworld, progitempool, usefulitempool, filleritempool, fill_locations):
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        trash_counts = {}
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-11 04:00:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        for player in multiworld.get_game_players("A Link to the Past"):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            world = multiworld.worlds[player]
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if not world.ganonstower_vanilla or \
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-11 04:00:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    world.options.glitches_required.current_key in {'overworld_glitches', 'hybrid_major_glitches', "no_logic"}:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                pass
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-22 15:36:27 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            elif 'triforce_hunt' in world.options.goal.current_key and ('local' in world.options.goal.current_key or multiworld.players == 1):
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-11 04:00:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                trash_counts[player] = multiworld.random.randint(world.options.crystals_needed_for_gt * 2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                            world.options.crystals_needed_for_gt * 4)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            else:
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-11 04:00:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                trash_counts[player] = multiworld.random.randint(0, world.options.crystals_needed_for_gt * 2)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if trash_counts:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            locations_mapping = {player: [] for player in trash_counts}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for location in fill_locations:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if 'Ganons Tower' in location.name and location.player in locations_mapping:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    locations_mapping[location.player].append(location)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for player, trash_count in trash_counts.items():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                gtower_locations = locations_mapping[player]
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-11 04:00:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                multiworld.random.shuffle(gtower_locations)
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-16 20:06:25 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                while gtower_locations and filleritempool and trash_count > 0:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    spot_to_fill = gtower_locations.pop()
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-17 09:52:34 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    for index, item in enumerate(filleritempool):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        if spot_to_fill.item_rule(item):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            filleritempool.pop(index)  # remove from outer fill
							 | 
						
					
						
							
								
									
										
										
										
											2024-03-11 04:00:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            multiworld.push_item(spot_to_fill, item, False)
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-17 09:52:34 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            fill_locations.remove(spot_to_fill)  # very slow, unfortunately
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            trash_count -= 1
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            break
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        logging.warning(f"Could not trash fill Ganon's Tower for player {player}.")
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def write_spoiler_header(self, spoiler_handle: typing.TextIO) -> None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        def bool_to_text(variable: typing.Union[bool, str]) -> str:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if type(variable) == str:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return variable
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return "Yes" if variable else "No"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def write_spoiler(self, spoiler_handle: typing.TextIO) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        player_name = self.multiworld.get_player_name(self.player)
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        spoiler_handle.write("\n\nMedallions:\n")
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        spoiler_handle.write(f"\nMisery Mire ({player_name}):"
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                             f" {self.required_medallions[0]}")
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        spoiler_handle.write(
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            f"\nTurtle Rock ({player_name}):"
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            f" {self.required_medallions[1]}")
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-13 06:50:45 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        spoiler_handle.write("\n\nFairy Fountain Bottle Fill:\n")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        spoiler_handle.write(f"\nPyramid Fairy ({player_name}):"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             f" {self.pyramid_fairy_bottle_fill}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        spoiler_handle.write(f"\nWaterfall Fairy ({player_name}):"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             f" {self.waterfall_fairy_bottle_fill}")
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.options.boss_shuffle != "none":
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            def create_boss_map() -> typing.Dict:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                boss_map = {
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    "Eastern Palace": self.dungeons["Eastern Palace"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Desert Palace": self.dungeons["Desert Palace"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Tower Of Hera": self.dungeons["Tower of Hera"].boss.name,
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    "Hyrule Castle": "Agahnim",
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    "Palace Of Darkness": self.dungeons["Palace of Darkness"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Swamp Palace": self.dungeons["Swamp Palace"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Skull Woods": self.dungeons["Skull Woods"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Thieves Town": self.dungeons["Thieves Town"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Ice Palace": self.dungeons["Ice Palace"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Misery Mire": self.dungeons["Misery Mire"].boss.name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Turtle Rock": self.dungeons["Turtle Rock"].boss.name,
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    "Ganons Tower": "Agahnim 2",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Ganon": "Ganon"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                }
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if self.options.mode != 'inverted':
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    boss_map.update({
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Ganons Tower Basement":
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            self.dungeons["Ganons Tower"].bosses["bottom"].name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Ganons Tower Middle": self.dungeons["Ganons Tower"].bosses[
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            "middle"].name,
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Ganons Tower Top": self.dungeons["Ganons Tower"].bosses[
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            "top"].name
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    })
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    boss_map.update({
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        "Ganons Tower Basement": self.dungeons["Inverted Ganons Tower"].bosses["bottom"].name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Ganons Tower Middle": self.dungeons["Inverted Ganons Tower"].bosses["middle"].name,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Ganons Tower Top": self.dungeons["Inverted Ganons Tower"].bosses["top"].name
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    })
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return boss_map
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            bossmap = create_boss_map()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            spoiler_handle.write(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f'\n\nBosses{(f" ({self.multiworld.get_player_name(self.player)})" if self.multiworld.players > 1 else "")}:\n')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            spoiler_handle.write('    ' + '\n    '.join([f'{x}: {y}' for x, y in bossmap.items()]))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-11 20:15:30 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        def build_shop_info(shop: Shop) -> typing.Dict[str, str]:
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            shop_data = {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "location": str(shop.region),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "type": "Take Any" if shop.type == ShopType.TakeAny else "Shop"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for index, item in enumerate(shop.inventory):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if item is None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                price = item["price"] // price_rate_display.get(item["price_type"], 1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                shop_data["item_{}".format(index)] = f"{item['item']} - {price} {price_type_display_name[item['price_type']]}"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if item["player"]:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    shop_data["item_{}".format(index)] =\
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        shop_data["item_{}".format(index)].replace("—", "(Player {}) — ".format(item["player"]))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if item["max"] == 0:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                shop_data["item_{}".format(index)] += " x {}".format(item["max"])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if item["replacement"] is None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                shop_data["item_{}".format(index)] +=\
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-19 19:07:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    f", {item['replacement']} - {item['replacement_price'] // price_rate_display.get(item['replacement_price_type'], 1)}" \
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    f" {price_type_display_name[item['replacement_price_type']]}"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return shop_data
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-08-01 22:30:30 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if shop_info := [build_shop_info(shop) for shop in self.shops if shop.custom]:
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            spoiler_handle.write('\n\nShops:\n\n')
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-11 20:15:30 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        for shop_data in shop_info:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            spoiler_handle.write("{} [{}]\n    {}\n".format(shop_data['location'], shop_data['type'], "\n    ".join(
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                item for item in [shop_data.get('item_0', None), shop_data.get('item_1', None), shop_data.get('item_2', None)] if
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-11 20:15:30 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                item)))
							 | 
						
					
						
							
								
									
										
										
										
											2023-02-24 21:02:51 -06:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def get_filler_item_name(self) -> str:
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-19 19:07:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        item = self.multiworld.random.choice(extras_list)
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return GetBeemizerItem(self.multiworld, self.player, item)
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-13 23:02:18 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def get_pre_fill_items(self):
							 | 
						
					
						
							
								
									
										
										
										
											2025-05-10 17:49:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        res = [self.create_item(name) for name in ('Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                   'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                   'Crystal 6')]
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-13 23:02:18 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.dungeon_local_item_names:
							 | 
						
					
						
							
								
									
										
										
										
											2023-05-20 19:57:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            for dungeon in self.dungeons.values():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                for item in dungeon.all_items:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if item.name in self.dungeon_local_item_names:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        res.append(item)
							 | 
						
					
						
							
								
									
										
										
										
											2025-05-10 17:49:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-13 23:02:18 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return res
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-31 01:37:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def fill_slot_data(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        slot_data = {}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not self.multiworld.is_race:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # all of these option are NOT used by the SNI- or Text-Client.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # they are used by the alttp-poptracker pack (https://github.com/StripesOO7/alttp-ap-poptracker-pack)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # for convenient auto-tracking of the generated settings and adjusting the tracker accordingly
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            slot_options = ["crystals_needed_for_gt", "crystals_needed_for_ganon", "open_pyramid",
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-19 19:07:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            "big_key_shuffle", "small_key_shuffle", "compass_shuffle", "map_shuffle",
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-31 01:37:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            "progressive", "swordless", "retro_bow", "retro_caves", "shop_item_slots",
							 | 
						
					
						
							
								
									
										
										
										
											2024-02-19 19:07:49 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            "boss_shuffle", "pot_shuffle", "enemy_shuffle", "key_drop_shuffle", "bombless_start",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            "randomize_shop_inventories", "shuffle_shop_inventories", "shuffle_capacity_upgrades",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            "entrance_shuffle", "dark_room_logic", "goal", "mode",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            "triforce_pieces_mode", "triforce_pieces_percentage", "triforce_pieces_required",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            "triforce_pieces_available", "triforce_pieces_extra",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ]
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-31 01:37:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            slot_data = {option_name: getattr(self.options, option_name).value for option_name in slot_options}
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-31 01:37:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            slot_data.update({
							 | 
						
					
						
							
								
									
										
										
										
											2024-04-18 18:33:16 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                'mm_medalion': self.required_medallions[0],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                'tr_medalion': self.required_medallions[1],
							 | 
						
					
						
							
								
									
										
										
										
											2023-07-31 01:37:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                }
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return slot_data
							 | 
						
					
						
							
								
									
										
										
										
											2023-09-26 23:24:10 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-28 00:26:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def get_same_seed(world, seed_def: tuple) -> str:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    seeds: typing.Dict[tuple, str] = getattr(world, "__named_seeds", {})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    if seed_def in seeds:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return seeds[seed_def]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    seeds[seed_def] = str(world.random.randint(0, 2 ** 64))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    world.__named_seeds = seeds
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 19:11:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    return seeds[seed_def]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class ALttPLogic(LogicMixin):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def _lttp_has_key(self, item, player, count: int = 1):
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.multiworld.worlds[player].options.glitches_required == 'no_logic':
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 19:11:12 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return True
							 | 
						
					
						
							
								
									
										
										
										
											2025-04-18 17:41:38 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.multiworld.worlds[player].options.small_key_shuffle == small_key_shuffle.option_universal:
							 | 
						
					
						
							
								
									
										
										
										
											2023-03-03 23:23:52 -08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return can_buy_unlimited(self, 'Small Key (Universal)', player)
							 | 
						
					
						
							
								
									
										
										
										
											2023-11-02 00:41:20 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return self.prog_items[player][item] >= count
							 |