From 30b414429f5b118c9f0b77537d6aac464510615f Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Fri, 29 Nov 2024 05:02:26 +0100 Subject: [PATCH] LTTP: sort of use new options system (#3764) * LttP: switch to dataclass options definition * LttP: write old options onto multiworld LttP: use World.random --- worlds/alttp/Options.py | 166 +++++++++++++++++++-------------------- worlds/alttp/Rom.py | 9 ++- worlds/alttp/__init__.py | 35 +++++---- 3 files changed, 109 insertions(+), 101 deletions(-) diff --git a/worlds/alttp/Options.py b/worlds/alttp/Options.py index bd87cbf2..09745861 100644 --- a/worlds/alttp/Options.py +++ b/worlds/alttp/Options.py @@ -1,7 +1,7 @@ -import typing +from dataclasses import dataclass from BaseClasses import MultiWorld -from Options import Choice, Range, DeathLink, DefaultOnToggle, FreeText, ItemsAccessibility, Option, \ +from Options import Choice, Range, DeathLink, DefaultOnToggle, FreeText, ItemsAccessibility, PerGameCommonOptions, \ PlandoBosses, PlandoConnections, PlandoTexts, Removed, StartInventoryPool, Toggle from .EntranceShuffle import default_connections, default_dungeon_connections, \ inverted_default_connections, inverted_default_dungeon_connections @@ -742,86 +742,86 @@ class ALttPPlandoTexts(PlandoTexts): valid_keys = TextTable.valid_keys -alttp_options: typing.Dict[str, type(Option)] = { - "accessibility": ItemsAccessibility, - "plando_connections": ALttPPlandoConnections, - "plando_texts": ALttPPlandoTexts, - "start_inventory_from_pool": StartInventoryPool, - "goal": Goal, - "mode": Mode, - "glitches_required": GlitchesRequired, - "dark_room_logic": DarkRoomLogic, - "open_pyramid": OpenPyramid, - "crystals_needed_for_gt": CrystalsTower, - "crystals_needed_for_ganon": CrystalsGanon, - "triforce_pieces_mode": TriforcePiecesMode, - "triforce_pieces_percentage": TriforcePiecesPercentage, - "triforce_pieces_required": TriforcePiecesRequired, - "triforce_pieces_available": TriforcePiecesAvailable, - "triforce_pieces_extra": TriforcePiecesExtra, - "entrance_shuffle": EntranceShuffle, - "entrance_shuffle_seed": EntranceShuffleSeed, - "big_key_shuffle": big_key_shuffle, - "small_key_shuffle": small_key_shuffle, - "key_drop_shuffle": key_drop_shuffle, - "compass_shuffle": compass_shuffle, - "map_shuffle": map_shuffle, - "restrict_dungeon_item_on_boss": RestrictBossItem, - "item_pool": ItemPool, - "item_functionality": ItemFunctionality, - "enemy_health": EnemyHealth, - "enemy_damage": EnemyDamage, - "progressive": Progressive, - "swordless": Swordless, - "dungeon_counters": DungeonCounters, - "retro_bow": RetroBow, - "retro_caves": RetroCaves, - "hints": Hints, - "scams": Scams, - "boss_shuffle": LTTPBosses, - "pot_shuffle": PotShuffle, - "enemy_shuffle": EnemyShuffle, - "killable_thieves": KillableThieves, - "bush_shuffle": BushShuffle, - "shop_item_slots": ShopItemSlots, - "randomize_shop_inventories": RandomizeShopInventories, - "shuffle_shop_inventories": ShuffleShopInventories, - "include_witch_hut": IncludeWitchHut, - "randomize_shop_prices": RandomizeShopPrices, - "randomize_cost_types": RandomizeCostTypes, - "shop_price_modifier": ShopPriceModifier, - "shuffle_capacity_upgrades": ShuffleCapacityUpgrades, - "bombless_start": BomblessStart, - "shuffle_prizes": ShufflePrizes, - "tile_shuffle": TileShuffle, - "misery_mire_medallion": MiseryMireMedallion, - "turtle_rock_medallion": TurtleRockMedallion, - "glitch_boots": GlitchBoots, - "beemizer_total_chance": BeemizerTotalChance, - "beemizer_trap_chance": BeemizerTrapChance, - "timer": Timer, - "countdown_start_time": CountdownStartTime, - "red_clock_time": RedClockTime, - "blue_clock_time": BlueClockTime, - "green_clock_time": GreenClockTime, - "death_link": DeathLink, - "allow_collect": AllowCollect, - "ow_palettes": OWPalette, - "uw_palettes": UWPalette, - "hud_palettes": HUDPalette, - "sword_palettes": SwordPalette, - "shield_palettes": ShieldPalette, - # "link_palettes": LinkPalette, - "heartbeep": HeartBeep, - "heartcolor": HeartColor, - "quickswap": QuickSwap, - "menuspeed": MenuSpeed, - "music": Music, - "reduceflashing": ReduceFlashing, - "triforcehud": TriforceHud, +@dataclass +class ALTTPOptions(PerGameCommonOptions): + accessibility: ItemsAccessibility + plando_connections: ALttPPlandoConnections + plando_texts: ALttPPlandoTexts + start_inventory_from_pool: StartInventoryPool + goal: Goal + mode: Mode + glitches_required: GlitchesRequired + dark_room_logic: DarkRoomLogic + open_pyramid: OpenPyramid + crystals_needed_for_gt: CrystalsTower + crystals_needed_for_ganon: CrystalsGanon + triforce_pieces_mode: TriforcePiecesMode + triforce_pieces_percentage: TriforcePiecesPercentage + triforce_pieces_required: TriforcePiecesRequired + triforce_pieces_available: TriforcePiecesAvailable + triforce_pieces_extra: TriforcePiecesExtra + entrance_shuffle: EntranceShuffle + entrance_shuffle_seed: EntranceShuffleSeed + big_key_shuffle: big_key_shuffle + small_key_shuffle: small_key_shuffle + key_drop_shuffle: key_drop_shuffle + compass_shuffle: compass_shuffle + map_shuffle: map_shuffle + restrict_dungeon_item_on_boss: RestrictBossItem + item_pool: ItemPool + item_functionality: ItemFunctionality + enemy_health: EnemyHealth + enemy_damage: EnemyDamage + progressive: Progressive + swordless: Swordless + dungeon_counters: DungeonCounters + retro_bow: RetroBow + retro_caves: RetroCaves + hints: Hints + scams: Scams + boss_shuffle: LTTPBosses + pot_shuffle: PotShuffle + enemy_shuffle: EnemyShuffle + killable_thieves: KillableThieves + bush_shuffle: BushShuffle + shop_item_slots: ShopItemSlots + randomize_shop_inventories: RandomizeShopInventories + shuffle_shop_inventories: ShuffleShopInventories + include_witch_hut: IncludeWitchHut + randomize_shop_prices: RandomizeShopPrices + randomize_cost_types: RandomizeCostTypes + shop_price_modifier: ShopPriceModifier + shuffle_capacity_upgrades: ShuffleCapacityUpgrades + bombless_start: BomblessStart + shuffle_prizes: ShufflePrizes + tile_shuffle: TileShuffle + misery_mire_medallion: MiseryMireMedallion + turtle_rock_medallion: TurtleRockMedallion + glitch_boots: GlitchBoots + beemizer_total_chance: BeemizerTotalChance + beemizer_trap_chance: BeemizerTrapChance + timer: Timer + countdown_start_time: CountdownStartTime + red_clock_time: RedClockTime + blue_clock_time: BlueClockTime + green_clock_time: GreenClockTime + death_link: DeathLink + allow_collect: AllowCollect + ow_palettes: OWPalette + uw_palettes: UWPalette + hud_palettes: HUDPalette + sword_palettes: SwordPalette + shield_palettes: ShieldPalette + # link_palettes: LinkPalette + heartbeep: HeartBeep + heartcolor: HeartColor + quickswap: QuickSwap + menuspeed: MenuSpeed + music: Music + reduceflashing: ReduceFlashing + triforcehud: TriforceHud # removed: - "goals": Removed, - "smallkey_shuffle": Removed, - "bigkey_shuffle": Removed, -} + goals: Removed + smallkey_shuffle: Removed + bigkey_shuffle: Removed diff --git a/worlds/alttp/Rom.py b/worlds/alttp/Rom.py index 224de6aa..73a77b03 100644 --- a/worlds/alttp/Rom.py +++ b/worlds/alttp/Rom.py @@ -782,8 +782,8 @@ def get_nonnative_item_sprite(code: int) -> int: def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool): - local_random = world.per_slot_randoms[player] local_world = world.worlds[player] + local_random = local_world.random # patch items @@ -1867,7 +1867,7 @@ def apply_oof_sfx(rom, oof: str): def apply_rom_settings(rom, beep, color, quickswap, menuspeed, music: bool, sprite: str, oof: str, palettes_options, world=None, player=1, allow_random_on_event=False, reduceflashing=False, triforcehud: str = None, deathlink: bool = False, allowcollect: bool = False): - local_random = random if not world else world.per_slot_randoms[player] + local_random = random if not world else world.worlds[player].random disable_music: bool = not music # enable instant item menu if menuspeed == 'instant': @@ -2197,8 +2197,9 @@ def write_string_to_rom(rom, target, string): def write_strings(rom, world, player): from . import ALTTPWorld - local_random = world.per_slot_randoms[player] + w: ALTTPWorld = world.worlds[player] + local_random = w.random tt = TextTable() tt.removeUnwantedText() @@ -2425,7 +2426,7 @@ def write_strings(rom, world, player): if world.worlds[player].has_progressive_bows and (w.difficulty_requirements.progressive_bow_limit >= 2 or ( world.swordless[player] or world.glitches_required[player] == 'no_glitches')): prog_bow_locs = world.find_item_locations('Progressive Bow', player, True) - world.per_slot_randoms[player].shuffle(prog_bow_locs) + local_random.shuffle(prog_bow_locs) found_bow = False found_bow_alt = False while prog_bow_locs and not (found_bow and found_bow_alt): diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py index f897d376..b5489906 100644 --- a/worlds/alttp/__init__.py +++ b/worlds/alttp/__init__.py @@ -1,28 +1,27 @@ import logging import os import random -import settings import threading import typing -import Utils +import settings from BaseClasses import Item, CollectionState, Tutorial, MultiWorld +from worlds.AutoWorld import World, WebWorld, LogicMixin +from .Client import ALTTPSNIClient from .Dungeons import create_dungeons, Dungeon from .EntranceShuffle import link_entrances, link_inverted_entrances, plando_connect from .InvertedRegions import create_inverted_regions, mark_dark_world_regions from .ItemPool import generate_itempool, difficulties from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem -from .Options import alttp_options, small_key_shuffle +from .Options import ALTTPOptions, small_key_shuffle from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \ is_main_entrance, key_drop_data -from .Client import ALTTPSNIClient from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \ get_hash_string, get_base_rom_path, LttPDeltaPatch from .Rules import set_rules from .Shops import create_shops, Shop, push_shop_inventories, ShopType, price_rate_display, price_type_display_name -from .SubClasses import ALttPItem, LTTPRegionType -from worlds.AutoWorld import World, WebWorld, LogicMixin from .StateHelpers import can_buy_unlimited +from .SubClasses import ALttPItem, LTTPRegionType lttp_logger = logging.getLogger("A Link to the Past") @@ -132,7 +131,8 @@ class ALTTPWorld(World): Ganon! """ game = "A Link to the Past" - option_definitions = alttp_options + options_dataclass = ALTTPOptions + options: ALTTPOptions settings_key = "lttp_options" settings: typing.ClassVar[ALTTPSettings] topology_present = True @@ -286,13 +286,22 @@ class ALTTPWorld(World): if not os.path.exists(rom_file): raise FileNotFoundError(rom_file) if multiworld.is_race: - import xxtea + import xxtea # noqa for player in multiworld.get_game_players(cls.game): if multiworld.worlds[player].use_enemizer: check_enemizer(multiworld.worlds[player].enemizer_path) break def generate_early(self): + # write old options + import dataclasses + is_first = self.player == min(self.multiworld.get_game_players(self.game)) + + for field in dataclasses.fields(self.options_dataclass): + if is_first: + setattr(self.multiworld, field.name, {}) + getattr(self.multiworld, field.name)[self.player] = getattr(self.options, field.name) + # end of old options re-establisher player = self.player multiworld = self.multiworld @@ -536,12 +545,10 @@ class ALTTPWorld(World): @property def use_enemizer(self) -> bool: - world = self.multiworld - player = self.player - return bool(world.boss_shuffle[player] or world.enemy_shuffle[player] - or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default' - or world.pot_shuffle[player] or world.bush_shuffle[player] - or world.killable_thieves[player]) + 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) def generate_output(self, output_directory: str): multiworld = self.multiworld