From 2af510328e742a3c52ec3592565c7c4953817cf5 Mon Sep 17 00:00:00 2001 From: alwaysintreble Date: Mon, 31 Oct 2022 21:41:21 -0500 Subject: [PATCH] Core: rename `world` to `multiworld` (#931) * rename references to `Multiworld` in core to `multiworld` instead of `world` * fix smz3 * fix oot * fix low hanging fruit * revert mysteriously broken spacing in world api.md * fix more randomly broken spacing * hate * that better be all of it * begrudgingly move over smw * ._. * missed some worlds * this is getting tedious now * Missed some self.world definitions Co-authored-by: espeon65536 Co-authored-by: Zach Parks --- BaseClasses.py | 230 ++++++++--------- docs/world api.md | 70 +++--- test/TestBase.py | 24 +- test/dungeons/TestDungeon.py | 42 ++-- test/general/TestFill.py | 8 +- test/general/__init__.py | 16 +- test/inverted/TestInverted.py | 34 +-- test/inverted/TestInvertedBombRules.py | 26 +- .../TestInvertedMinor.py | 36 +-- test/inverted_owg/TestInvertedOWG.py | 40 +-- test/minecraft/TestMinecraft.py | 34 +-- test/minor_glitches/TestMinor.py | 30 +-- test/owg/TestVanillaOWG.py | 34 +-- test/vanilla/TestVanilla.py | 30 +-- test/worlds/test_base.py | 40 +-- test/worlds/zillion/TestOptions.py | 4 +- test/worlds/zillion/__init__.py | 2 +- worlds/AutoWorld.py | 6 +- worlds/alttp/Bosses.py | 8 +- worlds/alttp/Dungeons.py | 2 +- worlds/alttp/ItemPool.py | 4 +- worlds/alttp/Rules.py | 36 +-- worlds/alttp/__init__.py | 60 ++--- worlds/archipidle/__init__.py | 20 +- worlds/checksfinder/__init__.py | 22 +- worlds/dark_souls_3/__init__.py | 112 ++++----- worlds/dkc3/Regions.py | 2 +- worlds/dkc3/__init__.py | 44 ++-- worlds/factorio/Mod.py | 2 +- worlds/factorio/Shapes.py | 2 +- worlds/factorio/__init__.py | 108 ++++---- worlds/ff1/__init__.py | 26 +- worlds/generic/Rules.py | 2 +- worlds/generic/__init__.py | 2 +- worlds/hk/Rules.py | 4 +- worlds/hk/__init__.py | 84 +++---- worlds/hylics2/Rules.py | 2 +- worlds/hylics2/__init__.py | 104 ++++---- worlds/meritous/__init__.py | 38 +-- worlds/minecraft/Rules.py | 10 +- worlds/minecraft/__init__.py | 66 ++--- worlds/oot/Cosmetics.py | 2 +- worlds/oot/Dungeon.py | 4 +- worlds/oot/Entrance.py | 6 +- worlds/oot/EntranceShuffle.py | 20 +- worlds/oot/Hints.py | 28 +-- worlds/oot/ItemPool.py | 18 +- worlds/oot/Messages.py | 4 +- worlds/oot/Patches.py | 22 +- worlds/oot/RuleParser.py | 30 +-- worlds/oot/Rules.py | 14 +- worlds/oot/__init__.py | 158 ++++++------ worlds/oribf/Rules.py | 4 +- worlds/oribf/__init__.py | 8 +- worlds/overcooked2/Overcooked2Levels.py | 12 +- worlds/overcooked2/__init__.py | 28 +-- worlds/pokemon_rb/__init__.py | 96 +++---- worlds/pokemon_rb/logic.py | 26 +- worlds/pokemon_rb/regions.py | 24 +- worlds/pokemon_rb/rom.py | 236 +++++++++--------- worlds/pokemon_rb/rules.py | 4 +- worlds/raft/Rules.py | 4 +- worlds/raft/__init__.py | 60 ++--- worlds/rogue_legacy/Regions.py | 2 +- worlds/rogue_legacy/Rules.py | 8 +- worlds/rogue_legacy/__init__.py | 36 +-- worlds/ror2/__init__.py | 66 ++--- worlds/sa2b/Regions.py | 2 +- worlds/sa2b/__init__.py | 80 +++--- worlds/sc2wol/Regions.py | 2 +- worlds/sc2wol/__init__.py | 20 +- worlds/sm/__init__.py | 116 ++++----- worlds/sm64ex/__init__.py | 142 +++++------ worlds/smw/__init__.py | 62 ++--- worlds/smz3/__init__.py | 126 +++++----- worlds/soe/__init__.py | 92 +++---- worlds/spire/__init__.py | 26 +- worlds/subnautica/Rules.py | 2 +- worlds/subnautica/__init__.py | 42 ++-- worlds/timespinner/Regions.py | 2 +- worlds/timespinner/__init__.py | 38 +-- worlds/v6/__init__.py | 22 +- worlds/witness/__init__.py | 46 ++-- worlds/zillion/__init__.py | 34 +-- worlds/zillion/logic.py | 4 +- 85 files changed, 1623 insertions(+), 1621 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 016c80ec..41c5ab81 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -312,7 +312,7 @@ class MultiWorld(): def initialize_regions(self, regions=None): for region in regions if regions else self.regions: - region.world = self + region.multiworld = self self._region_cache[region.player][region.name] = region @functools.cached_property @@ -602,7 +602,7 @@ PathValue = Tuple[str, Optional["PathValue"]] class CollectionState(): prog_items: typing.Counter[Tuple[str, int]] - world: MultiWorld + multiworld: MultiWorld reachable_regions: Dict[int, Set[Region]] blocked_connections: Dict[int, Set[Entrance]] events: Set[Location] @@ -614,7 +614,7 @@ class CollectionState(): def __init__(self, parent: MultiWorld): self.prog_items = Counter() - self.world = parent + self.multiworld = parent self.reachable_regions = {player: set() for player in parent.get_all_ids()} self.blocked_connections = {player: set() for player in parent.get_all_ids()} self.events = set() @@ -632,7 +632,7 @@ class CollectionState(): rrp = self.reachable_regions[player] bc = self.blocked_connections[player] queue = deque(self.blocked_connections[player]) - start = self.world.get_region('Menu', player) + start = self.multiworld.get_region('Menu', player) # init on first call - this can't be done on construction since the regions don't exist yet if start not in rrp: @@ -655,12 +655,12 @@ class CollectionState(): self.path[new_region] = (new_region.name, self.path.get(connection, None)) # Retry connections if the new region can unblock them - for new_entrance in self.world.indirect_connections.get(new_region, set()): + for new_entrance in self.multiworld.indirect_connections.get(new_region, set()): if new_entrance in bc and new_entrance not in queue: queue.append(new_entrance) def copy(self) -> CollectionState: - ret = CollectionState(self.world) + ret = CollectionState(self.multiworld) ret.prog_items = self.prog_items.copy() ret.reachable_regions = {player: copy.copy(self.reachable_regions[player]) for player in self.reachable_regions} @@ -681,17 +681,17 @@ class CollectionState(): assert isinstance(player, int), "can_reach: player is required if spot is str" # try to resolve a name if resolution_hint == 'Location': - spot = self.world.get_location(spot, player) + spot = self.multiworld.get_location(spot, player) elif resolution_hint == 'Entrance': - spot = self.world.get_entrance(spot, player) + spot = self.multiworld.get_entrance(spot, player) else: # default to Region - spot = self.world.get_region(spot, player) + spot = self.multiworld.get_region(spot, player) return spot.can_reach(self) def sweep_for_events(self, key_only: bool = False, locations: Optional[Iterable[Location]] = None) -> None: if locations is None: - locations = self.world.get_filled_locations() + locations = self.multiworld.get_filled_locations() reachable_events = True # since the loop has a good chance to run more than once, only filter the events once locations = {location for location in locations if location.event and location not in self.events and @@ -718,7 +718,7 @@ class CollectionState(): def has_group(self, item_name_group: str, player: int, count: int = 1) -> bool: found: int = 0 - for item_name in self.world.worlds[player].item_name_groups[item_name_group]: + for item_name in self.multiworld.worlds[player].item_name_groups[item_name_group]: found += self.prog_items[item_name, player] if found >= count: return True @@ -726,17 +726,17 @@ class CollectionState(): def count_group(self, item_name_group: str, player: int) -> int: found: int = 0 - for item_name in self.world.worlds[player].item_name_groups[item_name_group]: + for item_name in self.multiworld.worlds[player].item_name_groups[item_name_group]: found += self.prog_items[item_name, player] return found def can_buy_unlimited(self, item: str, player: int) -> bool: return any(shop.region.player == player and shop.has_unlimited(item) and shop.region.can_reach(self) for - shop in self.world.shops) + shop in self.multiworld.shops) def can_buy(self, item: str, player: int) -> bool: return any(shop.region.player == player and shop.has(item) and shop.region.can_reach(self) for - shop in self.world.shops) + shop in self.multiworld.shops) def item_count(self, item: str, player: int) -> int: return self.prog_items[item, player] @@ -756,7 +756,7 @@ class CollectionState(): return self.has('Power Glove', player) or self.has('Titans Mitts', player) def bottle_count(self, player: int) -> int: - return min(self.world.difficulty_requirements[player].progressive_bottle_limit, + return min(self.multiworld.difficulty_requirements[player].progressive_bottle_limit, self.count_group("Bottles", player)) def has_hearts(self, player: int, count: int) -> int: @@ -765,7 +765,7 @@ class CollectionState(): def heart_count(self, player: int) -> int: # Warning: This only considers items that are marked as advancement items - diff = self.world.difficulty_requirements[player] + diff = self.multiworld.difficulty_requirements[player] return min(self.item_count('Boss Heart Container', player), diff.boss_heart_container_limit) \ + self.item_count('Sanctuary Heart Container', player) \ + min(self.item_count('Piece of Heart', player), diff.heart_piece_limit) // 4 \ @@ -782,9 +782,9 @@ class CollectionState(): elif self.has('Magic Upgrade (1/2)', player): basemagic = 16 if self.can_buy_unlimited('Green Potion', player) or self.can_buy_unlimited('Blue Potion', player): - if self.world.item_functionality[player] == 'hard' and not fullrefill: + if self.multiworld.item_functionality[player] == 'hard' and not fullrefill: basemagic = basemagic + int(basemagic * 0.5 * self.bottle_count(player)) - elif self.world.item_functionality[player] == 'expert' and not fullrefill: + elif self.multiworld.item_functionality[player] == 'expert' and not fullrefill: basemagic = basemagic + int(basemagic * 0.25 * self.bottle_count(player)) else: basemagic = basemagic + basemagic * self.bottle_count(player) @@ -799,12 +799,12 @@ class CollectionState(): or (self.has('Bombs (10)', player) and enemies < 6)) def can_shoot_arrows(self, player: int) -> bool: - if self.world.retro_bow[player]: + if self.multiworld.retro_bow[player]: return (self.has('Bow', player) or self.has('Silver Bow', player)) and self.can_buy('Single Arrow', player) return self.has('Bow', player) or self.has('Silver Bow', player) def can_get_good_bee(self, player: int) -> bool: - cave = self.world.get_region('Good Bee Cave', player) + cave = self.multiworld.get_region('Good Bee Cave', player) return ( self.has_group("Bottles", player) and self.has('Bug Catching Net', player) and @@ -815,7 +815,7 @@ class CollectionState(): def can_retrieve_tablet(self, player: int) -> bool: return self.has('Book of Mudora', player) and (self.has_beam_sword(player) or - (self.world.swordless[player] and + (self.multiworld.swordless[player] and self.has("Hammer", player))) def has_sword(self, player: int) -> bool: @@ -837,7 +837,7 @@ class CollectionState(): def can_melt_things(self, player: int) -> bool: return self.has('Fire Rod', player) or \ (self.has('Bombos', player) and - (self.world.swordless[player] or + (self.multiworld.swordless[player] or self.has_sword(player))) def can_avoid_lasers(self, player: int) -> bool: @@ -847,7 +847,7 @@ class CollectionState(): if self.has('Moon Pearl', player): return True - return region.is_light_world if self.world.mode[player] != 'inverted' else region.is_dark_world + return region.is_light_world if self.multiworld.mode[player] != 'inverted' else region.is_dark_world def can_reach_light_world(self, player: int) -> bool: if True in [i.is_light_world for i in self.reachable_regions[player]]: @@ -860,24 +860,24 @@ class CollectionState(): return False def has_misery_mire_medallion(self, player: int) -> bool: - return self.has(self.world.required_medallions[player][0], player) + return self.has(self.multiworld.required_medallions[player][0], player) def has_turtle_rock_medallion(self, player: int) -> bool: - return self.has(self.world.required_medallions[player][1], player) + return self.has(self.multiworld.required_medallions[player][1], player) def can_boots_clip_lw(self, player: int) -> bool: - if self.world.mode[player] == 'inverted': + if self.multiworld.mode[player] == 'inverted': return self.has('Pegasus Boots', player) and self.has('Moon Pearl', player) return self.has('Pegasus Boots', player) def can_boots_clip_dw(self, player: int) -> bool: - if self.world.mode[player] != 'inverted': + if self.multiworld.mode[player] != 'inverted': return self.has('Pegasus Boots', player) and self.has('Moon Pearl', player) return self.has('Pegasus Boots', player) def can_get_glitched_speed_lw(self, player: int) -> bool: rules = [self.has('Pegasus Boots', player), any([self.has('Hookshot', player), self.has_sword(player)])] - if self.world.mode[player] == 'inverted': + if self.multiworld.mode[player] == 'inverted': rules.append(self.has('Moon Pearl', player)) return all(rules) @@ -886,7 +886,7 @@ class CollectionState(): def can_get_glitched_speed_dw(self, player: int) -> bool: rules = [self.has('Pegasus Boots', player), any([self.has('Hookshot', player), self.has_sword(player)])] - if self.world.mode[player] != 'inverted': + if self.multiworld.mode[player] != 'inverted': rules.append(self.has('Moon Pearl', player)) return all(rules) @@ -897,7 +897,7 @@ class CollectionState(): if location: self.locations_checked.add(location) - changed = self.world.worlds[item.player].collect(self, item) + changed = self.multiworld.worlds[item.player].collect(self, item) if not changed and event: self.prog_items[item.name, item.player] += 1 @@ -911,7 +911,7 @@ class CollectionState(): return changed def remove(self, item: Item): - changed = self.world.worlds[item.player].remove(self, item) + changed = self.multiworld.worlds[item.player].remove(self, item) if changed: # invalidate caches, nothing can be trusted anymore now self.reachable_regions[item.player] = set() @@ -938,7 +938,7 @@ class Region: type: RegionType hint_text: str player: int - world: Optional[MultiWorld] + multiworld: Optional[MultiWorld] entrances: List[Entrance] exits: List[Entrance] locations: List[Location] @@ -956,7 +956,7 @@ class Region: self.entrances = [] self.exits = [] self.locations = [] - self.world = world + self.multiworld = world self.hint_text = hint self.player = player @@ -984,7 +984,7 @@ class Region: return self.__str__() def __str__(self): - return self.world.get_name_string_for_object(self) if self.world else f'{self.name} (Player {self.player})' + return self.multiworld.get_name_string_for_object(self) if self.multiworld else f'{self.name} (Player {self.player})' class Entrance: @@ -1021,7 +1021,7 @@ class Entrance: return self.__str__() def __str__(self): - world = self.parent_region.world if self.parent_region else None + world = self.parent_region.multiworld if self.parent_region else None return world.get_name_string_for_object(self) if world else f'{self.name} (Player {self.player})' @@ -1035,7 +1035,7 @@ class Dungeon(object): self.dungeon_items = dungeon_items self.bosses = dict() self.player = player - self.world = None + self.multiworld = None @property def boss(self) -> Optional[Boss]: @@ -1065,7 +1065,7 @@ class Dungeon(object): return self.__str__() def __str__(self): - return self.world.get_name_string_for_object(self) if self.world else f'{self.name} (Player {self.player})' + return self.multiworld.get_name_string_for_object(self) if self.multiworld else f'{self.name} (Player {self.player})' class Boss(): @@ -1130,7 +1130,7 @@ class Location: return self.__str__() def __str__(self): - world = self.parent_region.world if self.parent_region and self.parent_region.world else None + world = self.parent_region.multiworld if self.parent_region and self.parent_region.multiworld else None return world.get_name_string_for_object(self) if world else f'{self.name} (Player {self.player})' def __hash__(self): @@ -1227,17 +1227,17 @@ class Item: return self.__str__() def __str__(self) -> str: - if self.location and self.location.parent_region and self.location.parent_region.world: - return self.location.parent_region.world.get_name_string_for_object(self) + if self.location and self.location.parent_region and self.location.parent_region.multiworld: + return self.location.parent_region.multiworld.get_name_string_for_object(self) return f"{self.name} (Player {self.player})" class Spoiler(): - world: MultiWorld + multiworld: MultiWorld unreachables: Set[Location] def __init__(self, world): - self.world = world + self.multiworld = world self.hashes = {} self.entrances = OrderedDict() self.medallions = {} @@ -1249,7 +1249,7 @@ class Spoiler(): self.bosses = OrderedDict() def set_entrance(self, entrance: str, exit_: str, direction: str, player: int): - if self.world.players == 1: + if self.multiworld.players == 1: self.entrances[(entrance, direction, player)] = OrderedDict( [('entrance', entrance), ('exit', exit_), ('direction', direction)]) else: @@ -1258,45 +1258,45 @@ class Spoiler(): def parse_data(self): self.medallions = OrderedDict() - for player in self.world.get_game_players("A Link to the Past"): - self.medallions[f'Misery Mire ({self.world.get_player_name(player)})'] = \ - self.world.required_medallions[player][0] - self.medallions[f'Turtle Rock ({self.world.get_player_name(player)})'] = \ - self.world.required_medallions[player][1] + for player in self.multiworld.get_game_players("A Link to the Past"): + self.medallions[f'Misery Mire ({self.multiworld.get_player_name(player)})'] = \ + self.multiworld.required_medallions[player][0] + self.medallions[f'Turtle Rock ({self.multiworld.get_player_name(player)})'] = \ + self.multiworld.required_medallions[player][1] self.locations = OrderedDict() listed_locations = set() - lw_locations = [loc for loc in self.world.get_locations() if + lw_locations = [loc for loc in self.multiworld.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.LightWorld and loc.show_in_spoiler] self.locations['Light World'] = OrderedDict( [(str(location), str(location.item) if location.item is not None else 'Nothing') for location in lw_locations]) listed_locations.update(lw_locations) - dw_locations = [loc for loc in self.world.get_locations() if + dw_locations = [loc for loc in self.multiworld.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.DarkWorld and loc.show_in_spoiler] self.locations['Dark World'] = OrderedDict( [(str(location), str(location.item) if location.item is not None else 'Nothing') for location in dw_locations]) listed_locations.update(dw_locations) - cave_locations = [loc for loc in self.world.get_locations() if + cave_locations = [loc for loc in self.multiworld.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.Cave and loc.show_in_spoiler] self.locations['Caves'] = OrderedDict( [(str(location), str(location.item) if location.item is not None else 'Nothing') for location in cave_locations]) listed_locations.update(cave_locations) - for dungeon in self.world.dungeons.values(): - dungeon_locations = [loc for loc in self.world.get_locations() if + for dungeon in self.multiworld.dungeons.values(): + dungeon_locations = [loc for loc in self.multiworld.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and loc.show_in_spoiler] self.locations[str(dungeon)] = OrderedDict( [(str(location), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations]) listed_locations.update(dungeon_locations) - other_locations = [loc for loc in self.world.get_locations() if + other_locations = [loc for loc in self.multiworld.get_locations() if loc not in listed_locations and loc.show_in_spoiler] if other_locations: self.locations['Other Locations'] = OrderedDict( @@ -1306,7 +1306,7 @@ class Spoiler(): self.shops = [] from worlds.alttp.Shops import ShopType, price_type_display_name, price_rate_display - for shop in self.world.shops: + for shop in self.multiworld.shops: if not shop.custom: continue shopdata = { @@ -1335,34 +1335,34 @@ class Spoiler(): index)] += f", {item['replacement']} - {item['replacement_price']} {price_type_display_name[item['replacement_price_type']]}" self.shops.append(shopdata) - for player in self.world.get_game_players("A Link to the Past"): + for player in self.multiworld.get_game_players("A Link to the Past"): self.bosses[str(player)] = OrderedDict() - self.bosses[str(player)]["Eastern Palace"] = self.world.get_dungeon("Eastern Palace", player).boss.name - self.bosses[str(player)]["Desert Palace"] = self.world.get_dungeon("Desert Palace", player).boss.name - self.bosses[str(player)]["Tower Of Hera"] = self.world.get_dungeon("Tower of Hera", player).boss.name + self.bosses[str(player)]["Eastern Palace"] = self.multiworld.get_dungeon("Eastern Palace", player).boss.name + self.bosses[str(player)]["Desert Palace"] = self.multiworld.get_dungeon("Desert Palace", player).boss.name + self.bosses[str(player)]["Tower Of Hera"] = self.multiworld.get_dungeon("Tower of Hera", player).boss.name self.bosses[str(player)]["Hyrule Castle"] = "Agahnim" - self.bosses[str(player)]["Palace Of Darkness"] = self.world.get_dungeon("Palace of Darkness", - player).boss.name - self.bosses[str(player)]["Swamp Palace"] = self.world.get_dungeon("Swamp Palace", player).boss.name - self.bosses[str(player)]["Skull Woods"] = self.world.get_dungeon("Skull Woods", player).boss.name - self.bosses[str(player)]["Thieves Town"] = self.world.get_dungeon("Thieves Town", player).boss.name - self.bosses[str(player)]["Ice Palace"] = self.world.get_dungeon("Ice Palace", player).boss.name - self.bosses[str(player)]["Misery Mire"] = self.world.get_dungeon("Misery Mire", player).boss.name - self.bosses[str(player)]["Turtle Rock"] = self.world.get_dungeon("Turtle Rock", player).boss.name - if self.world.mode[player] != 'inverted': + self.bosses[str(player)]["Palace Of Darkness"] = self.multiworld.get_dungeon("Palace of Darkness", + player).boss.name + self.bosses[str(player)]["Swamp Palace"] = self.multiworld.get_dungeon("Swamp Palace", player).boss.name + self.bosses[str(player)]["Skull Woods"] = self.multiworld.get_dungeon("Skull Woods", player).boss.name + self.bosses[str(player)]["Thieves Town"] = self.multiworld.get_dungeon("Thieves Town", player).boss.name + self.bosses[str(player)]["Ice Palace"] = self.multiworld.get_dungeon("Ice Palace", player).boss.name + self.bosses[str(player)]["Misery Mire"] = self.multiworld.get_dungeon("Misery Mire", player).boss.name + self.bosses[str(player)]["Turtle Rock"] = self.multiworld.get_dungeon("Turtle Rock", player).boss.name + if self.multiworld.mode[player] != 'inverted': self.bosses[str(player)]["Ganons Tower Basement"] = \ - self.world.get_dungeon('Ganons Tower', player).bosses['bottom'].name - self.bosses[str(player)]["Ganons Tower Middle"] = self.world.get_dungeon('Ganons Tower', player).bosses[ + self.multiworld.get_dungeon('Ganons Tower', player).bosses['bottom'].name + self.bosses[str(player)]["Ganons Tower Middle"] = self.multiworld.get_dungeon('Ganons Tower', player).bosses[ 'middle'].name - self.bosses[str(player)]["Ganons Tower Top"] = self.world.get_dungeon('Ganons Tower', player).bosses[ + self.bosses[str(player)]["Ganons Tower Top"] = self.multiworld.get_dungeon('Ganons Tower', player).bosses[ 'top'].name else: self.bosses[str(player)]["Ganons Tower Basement"] = \ - self.world.get_dungeon('Inverted Ganons Tower', player).bosses['bottom'].name + self.multiworld.get_dungeon('Inverted Ganons Tower', player).bosses['bottom'].name self.bosses[str(player)]["Ganons Tower Middle"] = \ - self.world.get_dungeon('Inverted Ganons Tower', player).bosses['middle'].name + self.multiworld.get_dungeon('Inverted Ganons Tower', player).bosses['middle'].name self.bosses[str(player)]["Ganons Tower Top"] = \ - self.world.get_dungeon('Inverted Ganons Tower', player).bosses['top'].name + self.multiworld.get_dungeon('Inverted Ganons Tower', player).bosses['top'].name self.bosses[str(player)]["Ganons Tower"] = "Agahnim 2" self.bosses[str(player)]["Ganon"] = "Ganon" @@ -1392,7 +1392,7 @@ class Spoiler(): return 'Yes' if variable else 'No' def write_option(option_key: str, option_obj: type(Options.Option)): - res = getattr(self.world, option_key)[player] + res = getattr(self.multiworld, option_key)[player] display_name = getattr(option_obj, "display_name", option_key) try: outfile.write(f'{display_name + ":":33}{res.get_current_option_name()}\n') @@ -1402,59 +1402,59 @@ class Spoiler(): with open(filename, 'w', encoding="utf-8-sig") as outfile: outfile.write( 'Archipelago Version %s - Seed: %s\n\n' % ( - Utils.__version__, self.world.seed)) - outfile.write('Filling Algorithm: %s\n' % self.world.algorithm) - outfile.write('Players: %d\n' % self.world.players) - AutoWorld.call_stage(self.world, "write_spoiler_header", outfile) + Utils.__version__, self.multiworld.seed)) + outfile.write('Filling Algorithm: %s\n' % self.multiworld.algorithm) + outfile.write('Players: %d\n' % self.multiworld.players) + AutoWorld.call_stage(self.multiworld, "write_spoiler_header", outfile) - for player in range(1, self.world.players + 1): - if self.world.players > 1: - outfile.write('\nPlayer %d: %s\n' % (player, self.world.get_player_name(player))) - outfile.write('Game: %s\n' % self.world.game[player]) + for player in range(1, self.multiworld.players + 1): + if self.multiworld.players > 1: + outfile.write('\nPlayer %d: %s\n' % (player, self.multiworld.get_player_name(player))) + outfile.write('Game: %s\n' % self.multiworld.game[player]) for f_option, option in Options.per_game_common_options.items(): write_option(f_option, option) - options = self.world.worlds[player].option_definitions + options = self.multiworld.worlds[player].option_definitions if options: for f_option, option in options.items(): write_option(f_option, option) - AutoWorld.call_single(self.world, "write_spoiler_header", player, outfile) + AutoWorld.call_single(self.multiworld, "write_spoiler_header", player, outfile) - if player in self.world.get_game_players("A Link to the Past"): + if player in self.multiworld.get_game_players("A Link to the Past"): outfile.write('%s%s\n' % ('Hash: ', self.hashes[player])) - outfile.write('Logic: %s\n' % self.world.logic[player]) - outfile.write('Dark Room Logic: %s\n' % self.world.dark_room_logic[player]) - outfile.write('Mode: %s\n' % self.world.mode[player]) - outfile.write('Goal: %s\n' % self.world.goal[player]) - if "triforce" in self.world.goal[player]: # triforce hunt + outfile.write('Logic: %s\n' % self.multiworld.logic[player]) + outfile.write('Dark Room Logic: %s\n' % self.multiworld.dark_room_logic[player]) + outfile.write('Mode: %s\n' % self.multiworld.mode[player]) + outfile.write('Goal: %s\n' % self.multiworld.goal[player]) + if "triforce" in self.multiworld.goal[player]: # triforce hunt outfile.write("Pieces available for Triforce: %s\n" % - self.world.triforce_pieces_available[player]) + self.multiworld.triforce_pieces_available[player]) outfile.write("Pieces required for Triforce: %s\n" % - self.world.triforce_pieces_required[player]) - outfile.write('Difficulty: %s\n' % self.world.difficulty[player]) - outfile.write('Item Functionality: %s\n' % self.world.item_functionality[player]) - outfile.write('Entrance Shuffle: %s\n' % self.world.shuffle[player]) - if self.world.shuffle[player] != "vanilla": - outfile.write('Entrance Shuffle Seed %s\n' % self.world.worlds[player].er_seed) + self.multiworld.triforce_pieces_required[player]) + outfile.write('Difficulty: %s\n' % self.multiworld.difficulty[player]) + outfile.write('Item Functionality: %s\n' % self.multiworld.item_functionality[player]) + outfile.write('Entrance Shuffle: %s\n' % self.multiworld.shuffle[player]) + if self.multiworld.shuffle[player] != "vanilla": + outfile.write('Entrance Shuffle Seed %s\n' % self.multiworld.worlds[player].er_seed) outfile.write('Shop inventory shuffle: %s\n' % - bool_to_text("i" in self.world.shop_shuffle[player])) + bool_to_text("i" in self.multiworld.shop_shuffle[player])) outfile.write('Shop price shuffle: %s\n' % - bool_to_text("p" in self.world.shop_shuffle[player])) + bool_to_text("p" in self.multiworld.shop_shuffle[player])) outfile.write('Shop upgrade shuffle: %s\n' % - bool_to_text("u" in self.world.shop_shuffle[player])) + bool_to_text("u" in self.multiworld.shop_shuffle[player])) outfile.write('New Shop inventory: %s\n' % - bool_to_text("g" in self.world.shop_shuffle[player] or - "f" in self.world.shop_shuffle[player])) + bool_to_text("g" in self.multiworld.shop_shuffle[player] or + "f" in self.multiworld.shop_shuffle[player])) outfile.write('Custom Potion Shop: %s\n' % - bool_to_text("w" in self.world.shop_shuffle[player])) - outfile.write('Enemy health: %s\n' % self.world.enemy_health[player]) - outfile.write('Enemy damage: %s\n' % self.world.enemy_damage[player]) + bool_to_text("w" in self.multiworld.shop_shuffle[player])) + outfile.write('Enemy health: %s\n' % self.multiworld.enemy_health[player]) + outfile.write('Enemy damage: %s\n' % self.multiworld.enemy_damage[player]) outfile.write('Prize shuffle %s\n' % - self.world.shuffle_prizes[player]) + self.multiworld.shuffle_prizes[player]) if self.entrances: outfile.write('\n\nEntrances:\n\n') - outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_name(entry["player"])}: ' - if self.world.players > 1 else '', entry['entrance'], + outfile.write('\n'.join(['%s%s %s %s' % (f'{self.multiworld.get_player_name(entry["player"])}: ' + if self.multiworld.players > 1 else '', entry['entrance'], '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', entry['exit']) for entry in self.entrances.values()])) @@ -1464,7 +1464,7 @@ class Spoiler(): for dungeon, medallion in self.medallions.items(): outfile.write(f'\n{dungeon}: {medallion}') - AutoWorld.call_all(self.world, "write_spoiler", outfile) + AutoWorld.call_all(self.multiworld, "write_spoiler", outfile) outfile.write('\n\nLocations:\n\n') outfile.write('\n'.join( @@ -1477,11 +1477,11 @@ class Spoiler(): item for item in [shop.get('item_0', None), shop.get('item_1', None), shop.get('item_2', None)] if item)) for shop in self.shops)) - for player in self.world.get_game_players("A Link to the Past"): - if self.world.boss_shuffle[player] != 'none': - bossmap = self.bosses[str(player)] if self.world.players > 1 else self.bosses + for player in self.multiworld.get_game_players("A Link to the Past"): + if self.multiworld.boss_shuffle[player] != 'none': + bossmap = self.bosses[str(player)] if self.multiworld.players > 1 else self.bosses outfile.write( - f'\n\nBosses{(f" ({self.world.get_player_name(player)})" if self.world.players > 1 else "")}:\n') + f'\n\nBosses{(f" ({self.multiworld.get_player_name(player)})" if self.multiworld.players > 1 else "")}:\n') outfile.write(' ' + '\n '.join([f'{x}: {y}' for x, y in bossmap.items()])) outfile.write('\n\nPlaythrough:\n\n') outfile.write('\n'.join(['%s: {\n%s\n}' % (sphere_nr, '\n'.join( @@ -1505,7 +1505,7 @@ class Spoiler(): path_listings.append("{}\n {}".format(location, "\n => ".join(path_lines))) outfile.write('\n'.join(path_listings)) - AutoWorld.call_all(self.world, "write_spoiler_end", outfile) + AutoWorld.call_all(self.multiworld, "write_spoiler_end", outfile) class Tutorial(NamedTuple): diff --git a/docs/world api.md b/docs/world api.md index cf26cfd9..a43d61e5 100644 --- a/docs/world api.md +++ b/docs/world api.md @@ -455,7 +455,7 @@ In addition, the following methods can be implemented and attributes can be set ```python def generate_early(self) -> None: # read player settings to world instance - self.final_boss_hp = self.world.final_boss_hp[self.player].value + self.final_boss_hp = self.multiworld.final_boss_hp[self.player].value ``` #### create_item @@ -490,19 +490,19 @@ def create_items(self) -> None: # If an item can't have duplicates it has to be excluded manually. # List of items to exclude, as a copy since it will be destroyed below - exclude = [item for item in self.world.precollected_items[self.player]] + exclude = [item for item in self.multiworld.precollected_items[self.player]] for item in map(self.create_item, mygame_items): if item in exclude: exclude.remove(item) # this is destructive. create unique list above - self.world.itempool.append(self.create_item("nothing")) + self.multiworld.itempool.append(self.create_item("nothing")) else: - self.world.itempool.append(item) + self.multiworld.itempool.append(item) # itempool and number of locations should match up. # If this is not the case we want to fill the itempool with junk. junk = 0 # calculate this based on player settings - self.world.itempool += [self.create_item("nothing") for _ in range(junk)] + self.multiworld.itempool += [self.create_item("nothing") for _ in range(junk)] ``` #### create_regions @@ -511,30 +511,30 @@ def create_items(self) -> None: def create_regions(self) -> None: # Add regions to the multiworld. "Menu" is the required starting point. # Arguments to Region() are name, type, human_readable_name, player, world - r = Region("Menu", RegionType.Generic, "Menu", self.player, self.world) + r = Region("Menu", RegionType.Generic, "Menu", self.player, self.multiworld) # Set Region.exits to a list of entrances that are reachable from region r.exits = [Entrance(self.player, "New game", r)] # or use r.exits.append # Append region to MultiWorld's regions - self.world.regions.append(r) # or use += [r...] + self.multiworld.regions.append(r) # or use += [r...] - r = Region("Main Area", RegionType.Generic, "Main Area", self.player, self.world) + r = Region("Main Area", RegionType.Generic, "Main Area", self.player, self.multiworld) # Add main area's locations to main area (all but final boss) r.locations = [MyGameLocation(self.player, location.name, self.location_name_to_id[location.name], r)] r.exits = [Entrance(self.player, "Boss Door", r)] - self.world.regions.append(r) + self.multiworld.regions.append(r) - r = Region("Boss Room", RegionType.Generic, "Boss Room", self.player, self.world) + r = Region("Boss Room", RegionType.Generic, "Boss Room", self.player, self.multiworld) # add event to Boss Room r.locations = [MyGameLocation(self.player, "Final Boss", None, r)] - self.world.regions.append(r) + self.multiworld.regions.append(r) # If entrances are not randomized, they should be connected here, otherwise # they can also be connected at a later stage. - self.world.get_entrance("New Game", self.player)\ - .connect(self.world.get_region("Main Area", self.player)) - self.world.get_entrance("Boss Door", self.player)\ - .connect(self.world.get_region("Boss Room", self.player)) + self.multiworld.get_entrance("New Game", self.player) + .connect(self.multiworld.get_region("Main Area", self.player)) + self.multiworld.get_entrance("Boss Door", self.player) + .connect(self.multiworld.get_region("Boss Room", self.player)) # If setting location access rules from data is easier here, set_rules can # possibly omitted. @@ -545,14 +545,14 @@ def create_regions(self) -> None: ```python def generate_basic(self) -> None: # place "Victory" at "Final Boss" and set collection as win condition - self.world.get_location("Final Boss", self.player)\ + self.multiworld.get_location("Final Boss", self.player) .place_locked_item(self.create_event("Victory")) - self.world.completion_condition[self.player] = \ + self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) # place item Herb into location Chest1 for some reason item = self.create_item("Herb") - self.world.get_location("Chest1", self.player).place_locked_item(item) + self.multiworld.get_location("Chest1", self.player).place_locked_item(item) # in most cases it's better to do this at the same time the itempool is # filled to avoid accidental duplicates: # manually placed and still in the itempool @@ -564,41 +564,42 @@ def generate_basic(self) -> None: from worlds.generic.Rules import add_rule, set_rule, forbid_item from Items import get_item_type + def set_rules(self) -> None: # For some worlds this step can be omitted if either a Logic mixin # (see below) is used, it's easier to apply the rules from data during # location generation or everything is in generate_basic # set a simple rule for an region - set_rule(self.world.get_entrance("Boss Door", self.player), + set_rule(self.multiworld.get_entrance("Boss Door", self.player), lambda state: state.has("Boss Key", self.player)) # combine rules to require two items - add_rule(self.world.get_location("Chest2", self.player), + add_rule(self.multiworld.get_location("Chest2", self.player), lambda state: state.has("Sword", self.player)) - add_rule(self.world.get_location("Chest2", self.player), + add_rule(self.multiworld.get_location("Chest2", self.player), lambda state: state.has("Shield", self.player)) # or simply combine yourself - set_rule(self.world.get_location("Chest2", self.player), + set_rule(self.multiworld.get_location("Chest2", self.player), lambda state: state.has("Sword", self.player) and state.has("Shield", self.player)) # require two of an item - set_rule(self.world.get_location("Chest3", self.player), + set_rule(self.multiworld.get_location("Chest3", self.player), lambda state: state.has("Key", self.player, 2)) # require one item from an item group - add_rule(self.world.get_location("Chest3", self.player), + add_rule(self.multiworld.get_location("Chest3", self.player), lambda state: state.has_group("weapons", self.player)) # state also has .item_count() for items, .has_any() and.has_all() for sets # and .count_group() for groups # set_rule is likely to be a bit faster than add_rule # disallow placing a specific local item at a specific location - forbid_item(self.world.get_location("Chest4", self.player), "Sword") + forbid_item(self.multiworld.get_location("Chest4", self.player), "Sword") # disallow placing items with a specific property - add_item_rule(self.world.get_location("Chest5", self.player), + add_item_rule(self.multiworld.get_location("Chest5", self.player), lambda item: get_item_type(item) == "weapon") # get_item_type needs to take player/world into account # if MyGameItem has a type property, a more direct implementation would be - add_item_rule(self.world.get_location("Chest5", self.player), + add_item_rule(self.multiworld.get_location("Chest5", self.player), lambda item: item.player != self.player or\ item.my_type == "weapon") # location.item_rule = ... is likely to be a bit faster @@ -659,32 +660,33 @@ class MyGameWorld(World): ```python from .Mod import generate_mod + def generate_output(self, output_directory: str): # How to generate the mod or ROM highly depends on the game # if the mod is written in Lua, Jinja can be used to fill a template # if the mod reads a json file, `json.dump()` can be used to generate that # code below is a dummy data = { - "seed": self.world.seed_name, # to verify the server's multiworld - "slot": self.world.player_name[self.player], # to connect to server + "seed": self.multiworld.seed_name, # to verify the server's multiworld + "slot": self.multiworld.player_name[self.player], # to connect to server "items": {location.name: location.item.name if location.item.player == self.player else "Remote" - for location in self.world.get_filled_locations(self.player)}, + for location in self.multiworld.get_filled_locations(self.player)}, # store start_inventory from player's .yaml "starter_items": [item.name for item - in self.world.precollected_items[self.player]], + in self.multiworld.precollected_items[self.player]], "final_boss_hp": self.final_boss_hp, # store option name "easy", "normal" or "hard" for difficuly - "difficulty": self.world.difficulty[self.player].current_key, + "difficulty": self.multiworld.difficulty[self.player].current_key, # store option value True or False for fixing a glitch - "fix_xyz_glitch": self.world.fix_xyz_glitch[self.player].value + "fix_xyz_glitch": self.multiworld.fix_xyz_glitch[self.player].value } # point to a ROM specified by the installation src = Utils.get_options()["mygame_options"]["rom_file"] # or point to worlds/mygame/data/mod_template src = os.path.join(os.path.dirname(__file__), "data", "mod_template") # generate output path - mod_name = f"AP-{self.world.seed_name}-P{self.player}-{self.world.player_name[self.player]}" + mod_name = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.multiworld.player_name[self.player]}" out_file = os.path.join(output_directory, mod_name + ".zip") # generate the file generate_mod(src, out_file, data) diff --git a/test/TestBase.py b/test/TestBase.py index 351ffb40..754f38db 100644 --- a/test/TestBase.py +++ b/test/TestBase.py @@ -11,18 +11,18 @@ from worlds.alttp.Items import ItemFactory class TestBase(unittest.TestCase): - world: MultiWorld + multiworld: MultiWorld _state_cache = {} def get_state(self, items): - if (self.world, tuple(items)) in self._state_cache: - return self._state_cache[self.world, tuple(items)] - state = CollectionState(self.world) + if (self.multiworld, tuple(items)) in self._state_cache: + return self._state_cache[self.multiworld, tuple(items)] + state = CollectionState(self.multiworld) for item in items: item.classification = ItemClassification.progression state.collect(item) state.sweep_for_events() - self._state_cache[self.world, tuple(items)] = state + self._state_cache[self.multiworld, tuple(items)] = state return state def get_path(self, state, region): @@ -44,11 +44,11 @@ class TestBase(unittest.TestCase): items = item_pool[0] all_except = item_pool[1] if len(item_pool) > 1 else None state = self._get_items(item_pool, all_except) - path = self.get_path(state, self.world.get_location(location, 1).parent_region) + path = self.get_path(state, self.multiworld.get_location(location, 1).parent_region) with self.subTest(msg="Reach Location", location=location, access=access, items=items, all_except=all_except, path=path, entry=i): - self.assertEqual(self.world.get_location(location, 1).can_reach(state), access) + self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), access) # check for partial solution if not all_except and access: # we are not supposed to be able to reach location with partial inventory @@ -56,18 +56,18 @@ class TestBase(unittest.TestCase): with self.subTest(msg="Location reachable without required item", location=location, items=item_pool[0], missing_item=missing_item, entry=i): state = self._get_items_partial(item_pool, missing_item) - self.assertEqual(self.world.get_location(location, 1).can_reach(state), False) + self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), False) def run_entrance_tests(self, access_pool): for i, (entrance, access, *item_pool) in enumerate(access_pool): items = item_pool[0] all_except = item_pool[1] if len(item_pool) > 1 else None state = self._get_items(item_pool, all_except) - path = self.get_path(state, self.world.get_entrance(entrance, 1).parent_region) + path = self.get_path(state, self.multiworld.get_entrance(entrance, 1).parent_region) with self.subTest(msg="Reach Entrance", entrance=entrance, access=access, items=items, all_except=all_except, path=path, entry=i): - self.assertEqual(self.world.get_entrance(entrance, 1).can_reach(state), access) + self.assertEqual(self.multiworld.get_entrance(entrance, 1).can_reach(state), access) # check for partial solution if not all_except and access: # we are not supposed to be able to reach location with partial inventory @@ -75,11 +75,11 @@ class TestBase(unittest.TestCase): with self.subTest(msg="Entrance reachable without required item", entrance=entrance, items=item_pool[0], missing_item=missing_item, entry=i): state = self._get_items_partial(item_pool, missing_item) - self.assertEqual(self.world.get_entrance(entrance, 1).can_reach(state), False) + self.assertEqual(self.multiworld.get_entrance(entrance, 1).can_reach(state), False) def _get_items(self, item_pool, all_except): if all_except and len(all_except) > 0: - items = self.world.itempool[:] + items = self.multiworld.itempool[:] items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)] items.extend(ItemFactory(item_pool[0], 1)) diff --git a/test/dungeons/TestDungeon.py b/test/dungeons/TestDungeon.py index 0568e799..ba1752bf 100644 --- a/test/dungeons/TestDungeon.py +++ b/test/dungeons/TestDungeon.py @@ -14,46 +14,46 @@ from worlds import AutoWorld class TestDungeon(unittest.TestCase): def setUp(self): - self.world = MultiWorld(1) + self.multiworld = MultiWorld(1) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() self.starting_regions = [] # Where to start exploring self.remove_exits = [] # Block dungeon exits - self.world.difficulty_requirements[1] = difficulties['normal'] - create_regions(self.world, 1) - create_dungeons(self.world, 1) - create_shops(self.world, 1) + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + create_regions(self.multiworld, 1) + create_dungeons(self.multiworld, 1) + create_shops(self.multiworld, 1) for exitname, regionname in mandatory_connections: - connect_simple(self.world, exitname, regionname, 1) - connect_simple(self.world, 'Big Bomb Shop', 'Big Bomb Shop', 1) - self.world.get_region('Menu', 1).exits = [] - self.world.swamp_patch_required[1] = True - self.world.worlds[1].set_rules() - self.world.worlds[1].create_items() - self.world.itempool.extend(get_dungeon_item_pool(self.world)) - self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + connect_simple(self.multiworld, exitname, regionname, 1) + connect_simple(self.multiworld, 'Big Bomb Shop', 'Big Bomb Shop', 1) + self.multiworld.get_region('Menu', 1).exits = [] + self.multiworld.swamp_patch_required[1] = True + self.multiworld.worlds[1].set_rules() + self.multiworld.worlds[1].create_items() + self.multiworld.itempool.extend(get_dungeon_item_pool(self.multiworld)) + self.multiworld.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) def run_tests(self, access_pool): for exit in self.remove_exits: - self.world.get_entrance(exit, 1).connected_region = self.world.get_region('Menu', 1) + self.multiworld.get_entrance(exit, 1).connected_region = self.multiworld.get_region('Menu', 1) for location, access, *item_pool in access_pool: items = item_pool[0] all_except = item_pool[1] if len(item_pool) > 1 else None with self.subTest(location=location, access=access, items=items, all_except=all_except): if all_except and len(all_except) > 0: - items = self.world.itempool[:] + items = self.multiworld.itempool[:] items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)] items.extend(ItemFactory(item_pool[0], 1)) else: items = ItemFactory(items, 1) - state = CollectionState(self.world) - state.reachable_regions[1].add(self.world.get_region('Menu', 1)) + state = CollectionState(self.multiworld) + state.reachable_regions[1].add(self.multiworld.get_region('Menu', 1)) for region_name in self.starting_regions: - region = self.world.get_region(region_name, 1) + region = self.multiworld.get_region(region_name, 1) state.reachable_regions[1].add(region) for exit in region.exits: if exit.connected_region is not None: @@ -63,4 +63,4 @@ class TestDungeon(unittest.TestCase): item.classification = ItemClassification.progression state.collect(item) - self.assertEqual(self.world.get_location(location, 1).can_reach(state), access) \ No newline at end of file + self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), access) \ No newline at end of file diff --git a/test/general/TestFill.py b/test/general/TestFill.py index 86d86a22..646fc3c8 100644 --- a/test/general/TestFill.py +++ b/test/general/TestFill.py @@ -27,7 +27,7 @@ def generate_multi_world(players: int = 1) -> MultiWorld: class PlayerDefinition(object): - world: MultiWorld + multiworld: MultiWorld id: int menu: Region locations: List[Location] @@ -36,7 +36,7 @@ class PlayerDefinition(object): regions: List[Region] def __init__(self, world: MultiWorld, id: int, menu: Region, locations: List[Location] = [], prog_items: List[Item] = [], basic_items: List[Item] = []): - self.world = world + self.multiworld = world self.id = id self.menu = menu self.locations = locations @@ -48,7 +48,7 @@ class PlayerDefinition(object): region_tag = "_region" + str(len(self.regions)) region_name = "player" + str(self.id) + region_tag region = Region("player" + str(self.id) + region_tag, RegionType.Generic, - "Region Hint", self.id, self.world) + "Region Hint", self.id, self.multiworld) self.locations += generate_locations(size, self.id, None, region, region_tag) entrance = Entrance(self.id, region_name + "_entrance", parent) @@ -57,7 +57,7 @@ class PlayerDefinition(object): entrance.access_rule = access_rule self.regions.append(region) - self.world.regions.append(region) + self.multiworld.regions.append(region) return region diff --git a/test/general/__init__.py b/test/general/__init__.py index 479f4af5..247b135c 100644 --- a/test/general/__init__.py +++ b/test/general/__init__.py @@ -7,15 +7,15 @@ gen_steps = ["generate_early", "create_regions", "create_items", "set_rules", "g def setup_default_world(world_type) -> MultiWorld: - world = MultiWorld(1) - world.game[1] = world_type.game - world.player_name = {1: "Tester"} - world.set_seed() + multiworld = MultiWorld(1) + multiworld.game[1] = world_type.game + multiworld.player_name = {1: "Tester"} + multiworld.set_seed() args = Namespace() for name, option in world_type.option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - world.set_options(args) - world.set_default_common_options() + multiworld.set_options(args) + multiworld.set_default_common_options() for step in gen_steps: - call_all(world, step) - return world + call_all(multiworld, step) + return multiworld diff --git a/test/inverted/TestInverted.py b/test/inverted/TestInverted.py index 0c96f0b2..309a34d5 100644 --- a/test/inverted/TestInverted.py +++ b/test/inverted/TestInverted.py @@ -14,23 +14,23 @@ from worlds import AutoWorld class TestInverted(TestBase): def setUp(self): - self.world = MultiWorld(1) + self.multiworld = MultiWorld(1) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() - self.world.difficulty_requirements[1] = difficulties['normal'] - self.world.mode[1] = "inverted" - create_inverted_regions(self.world, 1) - create_dungeons(self.world, 1) - create_shops(self.world, 1) - link_inverted_entrances(self.world, 1) - self.world.worlds[1].create_items() - self.world.required_medallions[1] = ['Ether', 'Quake'] - self.world.itempool.extend(get_dungeon_item_pool(self.world)) - self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) - self.world.get_location('Agahnim 1', 1).item = None - self.world.get_location('Agahnim 2', 1).item = None - mark_light_world_regions(self.world, 1) - self.world.worlds[1].set_rules() + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + self.multiworld.mode[1] = "inverted" + create_inverted_regions(self.multiworld, 1) + create_dungeons(self.multiworld, 1) + create_shops(self.multiworld, 1) + link_inverted_entrances(self.multiworld, 1) + self.multiworld.worlds[1].create_items() + self.multiworld.required_medallions[1] = ['Ether', 'Quake'] + self.multiworld.itempool.extend(get_dungeon_item_pool(self.multiworld)) + self.multiworld.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.multiworld.get_location('Agahnim 1', 1).item = None + self.multiworld.get_location('Agahnim 2', 1).item = None + mark_light_world_regions(self.multiworld, 1) + self.multiworld.worlds[1].set_rules() diff --git a/test/inverted/TestInvertedBombRules.py b/test/inverted/TestInvertedBombRules.py index f6afa9d0..47e177dd 100644 --- a/test/inverted/TestInvertedBombRules.py +++ b/test/inverted/TestInvertedBombRules.py @@ -14,16 +14,16 @@ from worlds import AutoWorld class TestInvertedBombRules(unittest.TestCase): def setUp(self): - self.world = MultiWorld(1) - self.world.mode[1] = "inverted" + self.multiworld = MultiWorld(1) + self.multiworld.mode[1] = "inverted" args = Namespace for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() - self.world.difficulty_requirements[1] = difficulties['normal'] - create_inverted_regions(self.world, 1) - create_dungeons(self.world, 1) + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + create_inverted_regions(self.multiworld, 1) + create_dungeons(self.multiworld, 1) #TODO: Just making sure I haven't missed an entrance. It would be good to test the rules make sense as well. def testInvertedBombRulesAreComplete(self): @@ -31,9 +31,9 @@ class TestInvertedBombRules(unittest.TestCase): must_exits = list(Inverted_LW_Entrances_Must_Exit + Inverted_LW_Dungeon_Entrances_Must_Exit) for entrance_name in (entrances + must_exits): if entrance_name not in ['Desert Palace Entrance (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave (Bottom)']: - entrance = self.world.get_entrance(entrance_name, 1) - connect_entrance(self.world, entrance_name, 'Inverted Big Bomb Shop', 1) - set_inverted_big_bomb_rules(self.world, 1) + entrance = self.multiworld.get_entrance(entrance_name, 1) + connect_entrance(self.multiworld, entrance_name, 'Inverted Big Bomb Shop', 1) + set_inverted_big_bomb_rules(self.multiworld, 1) entrance.connected_region.entrances.remove(entrance) entrance.connected_region = None @@ -45,9 +45,9 @@ class TestInvertedBombRules(unittest.TestCase): def testInvalidEntrances(self): for entrance_name in ['Desert Palace Entrance (East)', 'Spectacle Rock Cave', 'Spectacle Rock Cave (Bottom)']: - entrance = self.world.get_entrance(entrance_name, 1) - connect_entrance(self.world, entrance_name, 'Inverted Big Bomb Shop', 1) + entrance = self.multiworld.get_entrance(entrance_name, 1) + connect_entrance(self.multiworld, entrance_name, 'Inverted Big Bomb Shop', 1) with self.assertRaises(Exception): - set_inverted_big_bomb_rules(self.world, 1) + set_inverted_big_bomb_rules(self.multiworld, 1) entrance.connected_region.entrances.remove(entrance) entrance.connected_region = None diff --git a/test/inverted_minor_glitches/TestInvertedMinor.py b/test/inverted_minor_glitches/TestInvertedMinor.py index 42e7c942..7ea7980b 100644 --- a/test/inverted_minor_glitches/TestInvertedMinor.py +++ b/test/inverted_minor_glitches/TestInvertedMinor.py @@ -15,24 +15,24 @@ from worlds import AutoWorld class TestInvertedMinor(TestBase): def setUp(self): - self.world = MultiWorld(1) + self.multiworld = MultiWorld(1) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() - self.world.mode[1] = "inverted" - self.world.logic[1] = "minorglitches" - self.world.difficulty_requirements[1] = difficulties['normal'] - create_inverted_regions(self.world, 1) - create_dungeons(self.world, 1) - create_shops(self.world, 1) - link_inverted_entrances(self.world, 1) - self.world.worlds[1].create_items() - self.world.required_medallions[1] = ['Ether', 'Quake'] - self.world.itempool.extend(get_dungeon_item_pool(self.world)) - self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) - self.world.get_location('Agahnim 1', 1).item = None - self.world.get_location('Agahnim 2', 1).item = None - mark_light_world_regions(self.world, 1) - self.world.worlds[1].set_rules() + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() + self.multiworld.mode[1] = "inverted" + self.multiworld.logic[1] = "minorglitches" + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + create_inverted_regions(self.multiworld, 1) + create_dungeons(self.multiworld, 1) + create_shops(self.multiworld, 1) + link_inverted_entrances(self.multiworld, 1) + self.multiworld.worlds[1].create_items() + self.multiworld.required_medallions[1] = ['Ether', 'Quake'] + self.multiworld.itempool.extend(get_dungeon_item_pool(self.multiworld)) + self.multiworld.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.multiworld.get_location('Agahnim 1', 1).item = None + self.multiworld.get_location('Agahnim 2', 1).item = None + mark_light_world_regions(self.multiworld, 1) + self.multiworld.worlds[1].set_rules() diff --git a/test/inverted_owg/TestInvertedOWG.py b/test/inverted_owg/TestInvertedOWG.py index 064dd9e0..7dae3589 100644 --- a/test/inverted_owg/TestInvertedOWG.py +++ b/test/inverted_owg/TestInvertedOWG.py @@ -16,26 +16,26 @@ from worlds import AutoWorld class TestInvertedOWG(TestBase): def setUp(self): - self.world = MultiWorld(1) + self.multiworld = MultiWorld(1) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() - self.world.logic[1] = "owglitches" - self.world.mode[1] = "inverted" - self.world.difficulty_requirements[1] = difficulties['normal'] - create_inverted_regions(self.world, 1) - create_dungeons(self.world, 1) - create_shops(self.world, 1) - link_inverted_entrances(self.world, 1) - self.world.worlds[1].create_items() - self.world.required_medallions[1] = ['Ether', 'Quake'] - self.world.itempool.extend(get_dungeon_item_pool(self.world)) - self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) - self.world.get_location('Agahnim 1', 1).item = None - self.world.get_location('Agahnim 2', 1).item = None - self.world.precollected_items[1].clear() - self.world.itempool.append(ItemFactory('Pegasus Boots', 1)) - mark_light_world_regions(self.world, 1) - self.world.worlds[1].set_rules() + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() + self.multiworld.logic[1] = "owglitches" + self.multiworld.mode[1] = "inverted" + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + create_inverted_regions(self.multiworld, 1) + create_dungeons(self.multiworld, 1) + create_shops(self.multiworld, 1) + link_inverted_entrances(self.multiworld, 1) + self.multiworld.worlds[1].create_items() + self.multiworld.required_medallions[1] = ['Ether', 'Quake'] + self.multiworld.itempool.extend(get_dungeon_item_pool(self.multiworld)) + self.multiworld.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.multiworld.get_location('Agahnim 1', 1).item = None + self.multiworld.get_location('Agahnim 2', 1).item = None + self.multiworld.precollected_items[1].clear() + self.multiworld.itempool.append(ItemFactory('Pegasus Boots', 1)) + mark_light_world_regions(self.multiworld, 1) + self.multiworld.worlds[1].set_rules() diff --git a/test/minecraft/TestMinecraft.py b/test/minecraft/TestMinecraft.py index ea849dc7..cd87296c 100644 --- a/test/minecraft/TestMinecraft.py +++ b/test/minecraft/TestMinecraft.py @@ -30,28 +30,28 @@ def MCItemFactory(items, player: int): class TestMinecraft(TestBase): def setUp(self): - self.world = MultiWorld(1) - self.world.game[1] = "Minecraft" - self.world.worlds[1] = MinecraftWorld(self.world, 1) + self.multiworld = MultiWorld(1) + self.multiworld.game[1] = "Minecraft" + self.multiworld.worlds[1] = MinecraftWorld(self.multiworld, 1) exclusion_pools = ['hard', 'unreasonable', 'postgame'] for pool in exclusion_pools: - setattr(self.world, f"include_{pool}_advancements", {1: False}) - setattr(self.world, "advancement_goal", {1: AdvancementGoal(30)}) - setattr(self.world, "egg_shards_required", {1: EggShardsRequired(0)}) - setattr(self.world, "egg_shards_available", {1: EggShardsAvailable(0)}) - setattr(self.world, "required_bosses", {1: BossGoal(1)}) # ender dragon - setattr(self.world, "shuffle_structures", {1: ShuffleStructures(False)}) - setattr(self.world, "bee_traps", {1: BeeTraps(0)}) - setattr(self.world, "combat_difficulty", {1: CombatDifficulty(1)}) # normal - setattr(self.world, "structure_compasses", {1: Toggle(False)}) - setattr(self.world, "death_link", {1: Toggle(False)}) - AutoWorld.call_single(self.world, "create_regions", 1) - AutoWorld.call_single(self.world, "generate_basic", 1) - AutoWorld.call_single(self.world, "set_rules", 1) + setattr(self.multiworld, f"include_{pool}_advancements", {1: False}) + setattr(self.multiworld, "advancement_goal", {1: AdvancementGoal(30)}) + setattr(self.multiworld, "egg_shards_required", {1: EggShardsRequired(0)}) + setattr(self.multiworld, "egg_shards_available", {1: EggShardsAvailable(0)}) + setattr(self.multiworld, "required_bosses", {1: BossGoal(1)}) # ender dragon + setattr(self.multiworld, "shuffle_structures", {1: ShuffleStructures(False)}) + setattr(self.multiworld, "bee_traps", {1: BeeTraps(0)}) + setattr(self.multiworld, "combat_difficulty", {1: CombatDifficulty(1)}) # normal + setattr(self.multiworld, "structure_compasses", {1: Toggle(False)}) + setattr(self.multiworld, "death_link", {1: Toggle(False)}) + AutoWorld.call_single(self.multiworld, "create_regions", 1) + AutoWorld.call_single(self.multiworld, "generate_basic", 1) + AutoWorld.call_single(self.multiworld, "set_rules", 1) def _get_items(self, item_pool, all_except): if all_except and len(all_except) > 0: - items = self.world.itempool[:] + items = self.multiworld.itempool[:] items = [item for item in items if item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)] items.extend(MCItemFactory(item_pool[0], 1)) diff --git a/test/minor_glitches/TestMinor.py b/test/minor_glitches/TestMinor.py index 41cb1316..de19a717 100644 --- a/test/minor_glitches/TestMinor.py +++ b/test/minor_glitches/TestMinor.py @@ -15,23 +15,23 @@ from worlds import AutoWorld class TestMinor(TestBase): def setUp(self): - self.world = MultiWorld(1) + self.multiworld = MultiWorld(1) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() - self.world.logic[1] = "minorglitches" - self.world.difficulty_requirements[1] = difficulties['normal'] - self.world.worlds[1].er_seed = 0 - self.world.worlds[1].create_regions() - self.world.worlds[1].create_items() - self.world.required_medallions[1] = ['Ether', 'Quake'] - self.world.itempool.extend(get_dungeon_item_pool(self.world)) - self.world.itempool.extend(ItemFactory( + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() + self.multiworld.logic[1] = "minorglitches" + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + self.multiworld.worlds[1].er_seed = 0 + self.multiworld.worlds[1].create_regions() + self.multiworld.worlds[1].create_items() + self.multiworld.required_medallions[1] = ['Ether', 'Quake'] + self.multiworld.itempool.extend(get_dungeon_item_pool(self.multiworld)) + self.multiworld.itempool.extend(ItemFactory( ['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) - self.world.get_location('Agahnim 1', 1).item = None - self.world.get_location('Agahnim 2', 1).item = None - mark_dark_world_regions(self.world, 1) - self.world.worlds[1].set_rules() + self.multiworld.get_location('Agahnim 1', 1).item = None + self.multiworld.get_location('Agahnim 2', 1).item = None + mark_dark_world_regions(self.multiworld, 1) + self.multiworld.worlds[1].set_rules() diff --git a/test/owg/TestVanillaOWG.py b/test/owg/TestVanillaOWG.py index a4367fb5..a12679b8 100644 --- a/test/owg/TestVanillaOWG.py +++ b/test/owg/TestVanillaOWG.py @@ -16,23 +16,23 @@ from worlds import AutoWorld class TestVanillaOWG(TestBase): def setUp(self): - self.world = MultiWorld(1) + self.multiworld = MultiWorld(1) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() - self.world.difficulty_requirements[1] = difficulties['normal'] - self.world.logic[1] = "owglitches" - self.world.worlds[1].er_seed = 0 - self.world.worlds[1].create_regions() - self.world.worlds[1].create_items() - self.world.required_medallions[1] = ['Ether', 'Quake'] - self.world.itempool.extend(get_dungeon_item_pool(self.world)) - self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) - self.world.get_location('Agahnim 1', 1).item = None - self.world.get_location('Agahnim 2', 1).item = None - self.world.precollected_items[1].clear() - self.world.itempool.append(ItemFactory('Pegasus Boots', 1)) - mark_dark_world_regions(self.world, 1) - self.world.worlds[1].set_rules() \ No newline at end of file + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + self.multiworld.logic[1] = "owglitches" + self.multiworld.worlds[1].er_seed = 0 + self.multiworld.worlds[1].create_regions() + self.multiworld.worlds[1].create_items() + self.multiworld.required_medallions[1] = ['Ether', 'Quake'] + self.multiworld.itempool.extend(get_dungeon_item_pool(self.multiworld)) + self.multiworld.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.multiworld.get_location('Agahnim 1', 1).item = None + self.multiworld.get_location('Agahnim 2', 1).item = None + self.multiworld.precollected_items[1].clear() + self.multiworld.itempool.append(ItemFactory('Pegasus Boots', 1)) + mark_dark_world_regions(self.multiworld, 1) + self.multiworld.worlds[1].set_rules() \ No newline at end of file diff --git a/test/vanilla/TestVanilla.py b/test/vanilla/TestVanilla.py index c9fa3f76..32c9c618 100644 --- a/test/vanilla/TestVanilla.py +++ b/test/vanilla/TestVanilla.py @@ -14,21 +14,21 @@ from worlds import AutoWorld class TestVanilla(TestBase): def setUp(self): - self.world = MultiWorld(1) + self.multiworld = MultiWorld(1) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types["A Link to the Past"].option_definitions.items(): setattr(args, name, {1: option.from_any(option.default)}) - self.world.set_options(args) - self.world.set_default_common_options() - self.world.logic[1] = "noglitches" - self.world.difficulty_requirements[1] = difficulties['normal'] - self.world.worlds[1].er_seed = 0 - self.world.worlds[1].create_regions() - self.world.worlds[1].create_items() - self.world.required_medallions[1] = ['Ether', 'Quake'] - self.world.itempool.extend(get_dungeon_item_pool(self.world)) - self.world.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) - self.world.get_location('Agahnim 1', 1).item = None - self.world.get_location('Agahnim 2', 1).item = None - mark_dark_world_regions(self.world, 1) - self.world.worlds[1].set_rules() \ No newline at end of file + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() + self.multiworld.logic[1] = "noglitches" + self.multiworld.difficulty_requirements[1] = difficulties['normal'] + self.multiworld.worlds[1].er_seed = 0 + self.multiworld.worlds[1].create_regions() + self.multiworld.worlds[1].create_items() + self.multiworld.required_medallions[1] = ['Ether', 'Quake'] + self.multiworld.itempool.extend(get_dungeon_item_pool(self.multiworld)) + self.multiworld.itempool.extend(ItemFactory(['Green Pendant', 'Red Pendant', 'Blue Pendant', 'Beat Agahnim 1', 'Beat Agahnim 2', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'], 1)) + self.multiworld.get_location('Agahnim 1', 1).item = None + self.multiworld.get_location('Agahnim 2', 1).item = None + mark_dark_world_regions(self.multiworld, 1) + self.multiworld.worlds[1].set_rules() \ No newline at end of file diff --git a/test/worlds/test_base.py b/test/worlds/test_base.py index 0d7272be..22e92c6f 100644 --- a/test/worlds/test_base.py +++ b/test/worlds/test_base.py @@ -22,29 +22,29 @@ class WorldTestBase(unittest.TestCase): def world_setup(self, seed: typing.Optional[int] = None) -> None: if not hasattr(self, "game"): raise NotImplementedError("didn't define game name") - self.world = MultiWorld(1) - self.world.game[1] = self.game - self.world.player_name = {1: "Tester"} - self.world.set_seed(seed) + self.multiworld = MultiWorld(1) + self.multiworld.game[1] = self.game + self.multiworld.player_name = {1: "Tester"} + self.multiworld.set_seed(seed) args = Namespace() for name, option in AutoWorld.AutoWorldRegister.world_types[self.game].option_definitions.items(): setattr(args, name, { 1: option.from_any(self.options.get(name, getattr(option, "default"))) }) - self.world.set_options(args) - self.world.set_default_common_options() + self.multiworld.set_options(args) + self.multiworld.set_default_common_options() for step in gen_steps: - call_all(self.world, step) + call_all(self.multiworld, step) def collect_all_but(self, item_names: typing.Union[str, typing.Iterable[str]]) -> None: if isinstance(item_names, str): item_names = (item_names,) - for item in self.world.get_items(): + for item in self.multiworld.get_items(): if item.name not in item_names: - self.world.state.collect(item) + self.multiworld.state.collect(item) def get_item_by_name(self, item_name: str) -> Item: - for item in self.world.get_items(): + for item in self.multiworld.get_items(): if item.name == item_name: return item raise ValueError("No such item") @@ -52,7 +52,7 @@ class WorldTestBase(unittest.TestCase): def get_items_by_name(self, item_names: typing.Union[str, typing.Iterable[str]]) -> typing.List[Item]: if isinstance(item_names, str): item_names = (item_names,) - return [item for item in self.world.itempool if item.name in item_names] + return [item for item in self.multiworld.itempool if item.name in item_names] def collect_by_name(self, item_names: typing.Union[str, typing.Iterable[str]]) -> typing.List[Item]: """ collect all of the items in the item pool that have the given names """ @@ -64,21 +64,21 @@ class WorldTestBase(unittest.TestCase): if isinstance(items, Item): items = (items,) for item in items: - self.world.state.collect(item) + self.multiworld.state.collect(item) def remove(self, items: typing.Union[Item, typing.Iterable[Item]]) -> None: if isinstance(items, Item): items = (items,) for item in items: - if item.location and item.location.event and item.location in self.world.state.events: - self.world.state.events.remove(item.location) - self.world.state.remove(item) + if item.location and item.location.event and item.location in self.multiworld.state.events: + self.multiworld.state.events.remove(item.location) + self.multiworld.state.remove(item) def can_reach_location(self, location: str) -> bool: - return self.world.state.can_reach(location, "Location", 1) + return self.multiworld.state.can_reach(location, "Location", 1) def count(self, item_name: str) -> int: - return self.world.state.count(item_name, 1) + return self.multiworld.state.count(item_name, 1) def assertAccessDependency(self, locations: typing.List[str], @@ -86,8 +86,8 @@ class WorldTestBase(unittest.TestCase): all_items = [item_name for item_names in possible_items for item_name in item_names] self.collect_all_but(all_items) - for location in self.world.get_locations(): - self.assertEqual(self.world.state.can_reach(location), location.name not in locations) + for location in self.multiworld.get_locations(): + self.assertEqual(self.multiworld.state.can_reach(location), location.name not in locations) for item_names in possible_items: items = self.collect_by_name(item_names) for location in locations: @@ -95,4 +95,4 @@ class WorldTestBase(unittest.TestCase): self.remove(items) def assertBeatable(self, beatable: bool): - self.assertEqual(self.world.can_beat_game(self.world.state), beatable) + self.assertEqual(self.multiworld.can_beat_game(self.multiworld.state), beatable) diff --git a/test/worlds/zillion/TestOptions.py b/test/worlds/zillion/TestOptions.py index 20397a4e..b00c70f7 100644 --- a/test/worlds/zillion/TestOptions.py +++ b/test/worlds/zillion/TestOptions.py @@ -9,7 +9,7 @@ class OptionsTest(ZillionTestBase): def test_validate_default(self) -> None: self.world_setup() - validate(self.world, 1) + validate(self.multiworld, 1) def test_vblr_ap_to_zz(self) -> None: """ all of the valid values for the AP options map to valid values for ZZ options """ @@ -20,7 +20,7 @@ class OptionsTest(ZillionTestBase): for value in vblr_class.name_lookup.values(): self.options = {option_name: value} self.world_setup() - zz_options, _item_counts = validate(self.world, 1) + zz_options, _item_counts = validate(self.multiworld, 1) assert getattr(zz_options, option_name) in VBLR_CHOICES # TODO: test validate with invalid combinations of options diff --git a/test/worlds/zillion/__init__.py b/test/worlds/zillion/__init__.py index fb81bda5..1b3c2b42 100644 --- a/test/worlds/zillion/__init__.py +++ b/test/worlds/zillion/__init__.py @@ -13,7 +13,7 @@ class ZillionTestBase(WorldTestBase): This makes sure that gun 3 is required by making all the canisters in O-7 (including key word canisters) require gun 3. """ - zz_world = cast(ZillionWorld, self.world.worlds[1]) + zz_world = cast(ZillionWorld, self.multiworld.worlds[1]) assert zz_world.zz_system.randomizer for zz_loc_name, zz_loc in zz_world.zz_system.randomizer.locations.items(): if zz_loc_name.startswith("r15c6"): diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py index 37cf5300..00588a01 100644 --- a/worlds/AutoWorld.py +++ b/worlds/AutoWorld.py @@ -182,7 +182,7 @@ class World(metaclass=AutoWorldRegister): web: WebWorld = WebWorld() # autoset on creation: - world: "MultiWorld" + multiworld: "MultiWorld" player: int # automatically generated @@ -196,7 +196,7 @@ class World(metaclass=AutoWorldRegister): __file__: str # path it was loaded from def __init__(self, world: "MultiWorld", player: int): - self.world = world + self.multiworld = world self.player = player # overridable methods that get called by Main.py, sorted by execution order @@ -287,7 +287,7 @@ class World(metaclass=AutoWorldRegister): def get_filler_item_name(self) -> str: """Called when the item pool needs to be filled with additional items to match location count.""" logging.warning(f"World {self} is generating a filler item without custom filler pool.") - return self.world.random.choice(tuple(self.item_name_to_id.keys())) + return self.multiworld.random.choice(tuple(self.item_name_to_id.keys())) # decent place to implement progressive items, in most cases can stay as-is def collect_item(self, state: "CollectionState", item: "Item", remove: bool = False) -> Optional[str]: diff --git a/worlds/alttp/Bosses.py b/worlds/alttp/Bosses.py index 870b3c7c..5f915a33 100644 --- a/worlds/alttp/Bosses.py +++ b/worlds/alttp/Bosses.py @@ -81,7 +81,7 @@ def KholdstareDefeatRule(state, player: int) -> bool: state.has('Fire Rod', player) or ( state.has('Bombos', player) and - (state.has_sword(player) or state.world.swordless[player]) + (state.has_sword(player) or state.multiworld.swordless[player]) ) ) and ( @@ -90,7 +90,7 @@ def KholdstareDefeatRule(state, player: int) -> bool: ( state.has('Fire Rod', player) and state.has('Bombos', player) and - state.world.swordless[player] and + state.multiworld.swordless[player] and state.can_extend_magic(player, 16) ) ) @@ -114,7 +114,7 @@ def AgahnimDefeatRule(state, player: int) -> bool: def GanonDefeatRule(state, player: int) -> bool: - if state.world.swordless[player]: + if state.multiworld.swordless[player]: return state.has('Hammer', player) and \ state.has_fire_source(player) and \ state.has('Silver Bow', player) and \ @@ -123,7 +123,7 @@ def GanonDefeatRule(state, player: int) -> bool: can_hurt = state.has_beam_sword(player) common = can_hurt and state.has_fire_source(player) # silverless ganon may be needed in anything higher than no glitches - if state.world.logic[player] != 'noglitches': + if state.multiworld.logic[player] != 'noglitches': # need to light torch a sufficient amount of times return common and (state.has('Tempered Sword', player) or state.has('Golden Sword', player) or ( state.has('Silver Bow', player) and state.can_shoot_arrows(player)) or diff --git a/worlds/alttp/Dungeons.py b/worlds/alttp/Dungeons.py index 8850786b..866eb3e0 100644 --- a/worlds/alttp/Dungeons.py +++ b/worlds/alttp/Dungeons.py @@ -18,7 +18,7 @@ def create_dungeons(world, player): dungeon.boss = BossFactory(default_boss, player) if default_boss else None for region in dungeon.regions: world.get_region(region, player).dungeon = dungeon - dungeon.world = world + dungeon.multiworld = world return dungeon ES = make_dungeon('Hyrule Castle', None, ['Hyrule Castle', 'Sewers', 'Sewer Drop', 'Sewers (Dark)', 'Sanctuary'], diff --git a/worlds/alttp/ItemPool.py b/worlds/alttp/ItemPool.py index aa8d7ef3..a00a423a 100644 --- a/worlds/alttp/ItemPool.py +++ b/worlds/alttp/ItemPool.py @@ -224,7 +224,7 @@ for diff in {'easy', 'normal', 'hard', 'expert'}: def generate_itempool(world): player = world.player - world = world.world + world = world.multiworld if world.difficulty[player] not in difficulties: raise NotImplementedError(f"Diffulty {world.difficulty[player]}") @@ -286,7 +286,7 @@ def generate_itempool(world): region = world.get_region('Light World', player) loc = ALttPLocation(player, "Murahdahla", parent=region) - loc.access_rule = lambda state: state.has_triforce_pieces(state.world.treasure_hunt_count[player], player) + loc.access_rule = lambda state: state.has_triforce_pieces(state.multiworld.treasure_hunt_count[player], player) region.locations.append(loc) world.clear_location_cache() diff --git a/worlds/alttp/Rules.py b/worlds/alttp/Rules.py index 36e16cf5..d1413e21 100644 --- a/worlds/alttp/Rules.py +++ b/worlds/alttp/Rules.py @@ -13,7 +13,7 @@ from worlds.alttp.Options import smallkey_shuffle def set_rules(world): player = world.player - world = world.world + world = world.multiworld if world.logic[player] == 'nologic': if player == next(player_id for player_id in world.get_game_players("A Link to the Past") if world.logic[player_id] == 'nologic'): # only warn one time @@ -81,7 +81,7 @@ def set_rules(world): set_big_bomb_rules(world, player) if world.logic[player] in {'owglitches', 'hybridglitches', 'nologic'} and world.shuffle[player] not in {'insanity', 'insanity_legacy', 'madness'}: path_to_courtyard = mirrorless_path_to_castle_courtyard(world, player) - add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.world.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or') + add_rule(world.get_entrance('Pyramid Fairy', player), lambda state: state.multiworld.get_entrance('Dark Death Mountain Offset Mirror', player).can_reach(state) and all(rule(state) for rule in path_to_courtyard), 'or') else: set_inverted_big_bomb_rules(world, player) @@ -97,9 +97,9 @@ def set_rules(world): set_trock_key_rules(world, player) - set_rule(ganons_tower, lambda state: state.has_crystals(state.world.crystals_needed_for_gt[player], player)) + set_rule(ganons_tower, lambda state: state.has_crystals(state.multiworld.crystals_needed_for_gt[player], player)) if world.mode[player] != 'inverted' and world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']: - add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.world.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or') + add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.multiworld.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or') set_bunny_rules(world, player, world.mode[player] == 'inverted') @@ -204,7 +204,7 @@ def global_rules(world, player): ((state.has('Cape', player) and state.can_extend_magic(player, 16, True)) or (state.has('Cane of Byrna', player) and (state.can_extend_magic(player, 12, True) or - (state.world.can_take_damage[player] and (state.has('Pegasus Boots', player) or state.has_hearts(player, 4)))))) + (state.multiworld.can_take_damage[player] and (state.has('Pegasus Boots', player) or state.has_hearts(player, 4)))))) ) set_rule(world.get_location('Hookshot Cave - Top Right', player), lambda state: state.has('Hookshot', player)) @@ -242,12 +242,12 @@ def global_rules(world, player): set_rule(world.get_location('Desert Palace - Big Chest', player), lambda state: state.has('Big Key (Desert Palace)', player)) set_rule(world.get_location('Desert Palace - Torch', player), lambda state: state.has('Pegasus Boots', player)) set_rule(world.get_entrance('Desert Palace East Wing', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player)) - set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and state.world.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) - set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and state.world.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) + set_rule(world.get_location('Desert Palace - Prize', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and state.multiworld.get_location('Desert Palace - Prize', player).parent_region.dungeon.boss.can_defeat(state)) + set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state._lttp_has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and state.multiworld.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state)) # logic patch to prevent placing a crystal in Desert that's required to reach the required keys if not (world.smallkey_shuffle[player] and world.bigkey_shuffle[player]): - add_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.world.get_region('Desert Palace Main (Outer)', player).can_reach(state)) + add_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.multiworld.get_region('Desert Palace Main (Outer)', player).can_reach(state)) set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state._lttp_has_key('Small Key (Tower of Hera)', player) or item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player)) set_rule(world.get_entrance('Tower of Hera Big Key Door', player), lambda state: state.has('Big Key (Tower of Hera)', player)) @@ -286,12 +286,12 @@ def global_rules(world, player): set_rule(world.get_location('Ice Palace - Big Chest', player), lambda state: state.has('Big Key (Ice Palace)', player)) set_rule(world.get_entrance('Ice Palace (Kholdstare)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player) and state.has('Big Key (Ice Palace)', player) and (state._lttp_has_key('Small Key (Ice Palace)', player, 2) or (state.has('Cane of Somaria', player) and state._lttp_has_key('Small Key (Ice Palace)', player, 1)))) set_rule(world.get_entrance('Ice Palace (East)', player), lambda state: (state.has('Hookshot', player) or ( - item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state._lttp_has_key('Small Key (Ice Palace)', player))) and (state.world.can_take_damage[player] or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) + item_in_locations(state, 'Big Key (Ice Palace)', player, [('Ice Palace - Spike Room', player), ('Ice Palace - Big Key Chest', player), ('Ice Palace - Map Chest', player)]) and state._lttp_has_key('Small Key (Ice Palace)', player))) and (state.multiworld.can_take_damage[player] or state.has('Hookshot', player) or state.has('Cape', player) or state.has('Cane of Byrna', player))) set_rule(world.get_entrance('Ice Palace (East Top)', player), lambda state: state.can_lift_rocks(player) and state.has('Hammer', player)) set_rule(world.get_entrance('Misery Mire Entrance Gap', player), lambda state: (state.has('Pegasus Boots', player) or state.has('Hookshot', player)) and (state.has_sword(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Hammer', player) or state.has('Cane of Somaria', player) or state.can_shoot_arrows(player))) # need to defeat wizzrobes, bombs don't work ... set_rule(world.get_location('Misery Mire - Big Chest', player), lambda state: state.has('Big Key (Misery Mire)', player)) - set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.world.can_take_damage[player] and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) + set_rule(world.get_location('Misery Mire - Spike Chest', player), lambda state: (state.multiworld.can_take_damage[player] and state.has_hearts(player, 4)) or state.has('Cane of Byrna', player) or state.has('Cape', player)) set_rule(world.get_entrance('Misery Mire Big Key Door', player), lambda state: state.has('Big Key (Misery Mire)', player)) # you can squander the free small key from the pot by opening the south door to the north west switch room, locking you out of accessing a color switch ... # big key gives backdoor access to that from the teleporter in the north west @@ -377,11 +377,11 @@ def global_rules(world, player): set_rule(world.get_location('Ganons Tower - Big Chest', player), lambda state: state.has('Big Key (Ganons Tower)', player)) set_rule(world.get_location('Ganons Tower - Big Key Room - Left', player), - lambda state: state.world.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + lambda state: state.multiworld.get_location('Ganons Tower - Big Key Room - Left', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) set_rule(world.get_location('Ganons Tower - Big Key Chest', player), - lambda state: state.world.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + lambda state: state.multiworld.get_location('Ganons Tower - Big Key Chest', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) set_rule(world.get_location('Ganons Tower - Big Key Room - Right', player), - lambda state: state.world.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) + lambda state: state.multiworld.get_location('Ganons Tower - Big Key Room - Right', player).parent_region.dungeon.bosses['bottom'].can_defeat(state)) if world.enemy_shuffle[player]: set_rule(world.get_entrance('Ganons Tower Big Key Door', player), lambda state: state.has('Big Key (Ganons Tower)', player)) @@ -389,22 +389,22 @@ def global_rules(world, player): set_rule(world.get_entrance('Ganons Tower Big Key Door', player), lambda state: state.has('Big Key (Ganons Tower)', player) and state.can_shoot_arrows(player)) set_rule(world.get_entrance('Ganons Tower Torch Rooms', player), - lambda state: state.has_fire_source(player) and state.world.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) + lambda state: state.has_fire_source(player) and state.multiworld.get_entrance('Ganons Tower Torch Rooms', player).parent_region.dungeon.bosses['middle'].can_defeat(state)) set_rule(world.get_location('Ganons Tower - Pre-Moldorm Chest', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 3)) set_rule(world.get_entrance('Ganons Tower Moldorm Door', player), lambda state: state._lttp_has_key('Small Key (Ganons Tower)', player, 4)) set_rule(world.get_entrance('Ganons Tower Moldorm Gap', player), - lambda state: state.has('Hookshot', player) and state.world.get_entrance('Ganons Tower Moldorm Gap', player).parent_region.dungeon.bosses['top'].can_defeat(state)) + lambda state: state.has('Hookshot', player) and state.multiworld.get_entrance('Ganons Tower Moldorm Gap', player).parent_region.dungeon.bosses['top'].can_defeat(state)) set_defeat_dungeon_boss_rule(world.get_location('Agahnim 2', player)) ganon = world.get_location('Ganon', player) set_rule(ganon, lambda state: GanonDefeatRule(state, player)) if world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']: - add_rule(ganon, lambda state: state.has_triforce_pieces(state.world.treasure_hunt_count[player], player)) + add_rule(ganon, lambda state: state.has_triforce_pieces(state.multiworld.treasure_hunt_count[player], player)) elif world.goal[player] == 'ganonpedestal': add_rule(world.get_location('Ganon', player), lambda state: state.can_reach('Master Sword Pedestal', 'Location', player)) else: - add_rule(ganon, lambda state: state.has_crystals(state.world.crystals_needed_for_ganon[player], player)) + add_rule(ganon, lambda state: state.has_crystals(state.multiworld.crystals_needed_for_ganon[player], player)) set_rule(world.get_entrance('Ganon Drop', player), lambda state: state.has_beam_sword(player)) # need to damage ganon to get tiles to drop set_rule(world.get_location('Flute Activation Spot', player), lambda state: state.has('Flute', player)) @@ -942,7 +942,7 @@ def set_trock_key_rules(world, player): if world.accessibility[player] != 'locations': set_always_allow(world.get_location('Turtle Rock - Big Key Chest', player), lambda state, item: item.name == 'Small Key (Turtle Rock)' and item.player == player - and state.can_reach(state.world.get_region('Turtle Rock (Second Section)', player))) + and state.can_reach(state.multiworld.get_region('Turtle Rock (Second Section)', player))) def set_big_bomb_rules(world, player): diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py index 8431af9a..93e0b02b 100644 --- a/worlds/alttp/__init__.py +++ b/worlds/alttp/__init__.py @@ -163,7 +163,7 @@ class ALTTPWorld(World): check_enemizer(self.enemizer_path) player = self.player - world = self.world + world = self.multiworld # system for sharing ER layouts self.er_seed = str(world.random.randint(0, 2 ** 64)) @@ -195,7 +195,7 @@ class ALTTPWorld(World): def create_regions(self): player = self.player - world = self.world + world = self.multiworld world.triforce_pieces_available[player] = max(world.triforce_pieces_available[player], world.triforce_pieces_required[player]) @@ -219,21 +219,21 @@ class ALTTPWorld(World): link_entrances(world, player) mark_light_world_regions(world, player) for region_name, entrance_name in indirect_connections_not_inverted.items(): - world.register_indirect_condition(self.world.get_region(region_name, player), - self.world.get_entrance(entrance_name, player)) + world.register_indirect_condition(world.get_region(region_name, player), + world.get_entrance(entrance_name, player)) else: link_inverted_entrances(world, player) mark_dark_world_regions(world, player) for region_name, entrance_name in indirect_connections_inverted.items(): - world.register_indirect_condition(self.world.get_region(region_name, player), - self.world.get_entrance(entrance_name, player)) + world.register_indirect_condition(world.get_region(region_name, player), + world.get_entrance(entrance_name, player)) world.random = old_random plando_connect(world, player) for region_name, entrance_name in indirect_connections.items(): - world.register_indirect_condition(self.world.get_region(region_name, player), - self.world.get_entrance(entrance_name, player)) + world.register_indirect_condition(world.get_region(region_name, player), + world.get_entrance(entrance_name, player)) def collect_item(self, state: CollectionState, item: Item, remove=False): @@ -278,15 +278,15 @@ class ALTTPWorld(World): if 'Sword' in item_name: if state.has('Golden Sword', item.player): pass - elif state.has('Tempered Sword', item.player) and self.world.difficulty_requirements[ + elif state.has('Tempered Sword', item.player) and self.multiworld.difficulty_requirements[ item.player].progressive_sword_limit >= 4: return 'Golden Sword' - elif state.has('Master Sword', item.player) and self.world.difficulty_requirements[ + elif state.has('Master Sword', item.player) and self.multiworld.difficulty_requirements[ item.player].progressive_sword_limit >= 3: return 'Tempered Sword' - elif state.has('Fighter Sword', item.player) and self.world.difficulty_requirements[item.player].progressive_sword_limit >= 2: + elif state.has('Fighter Sword', item.player) and self.multiworld.difficulty_requirements[item.player].progressive_sword_limit >= 2: return 'Master Sword' - elif self.world.difficulty_requirements[item.player].progressive_sword_limit >= 1: + elif self.multiworld.difficulty_requirements[item.player].progressive_sword_limit >= 1: return 'Fighter Sword' elif 'Glove' in item_name: if state.has('Titans Mitts', item.player): @@ -298,20 +298,20 @@ class ALTTPWorld(World): elif 'Shield' in item_name: if state.has('Mirror Shield', item.player): return - elif state.has('Red Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 3: + elif state.has('Red Shield', item.player) and self.multiworld.difficulty_requirements[item.player].progressive_shield_limit >= 3: return 'Mirror Shield' - elif state.has('Blue Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 2: + elif state.has('Blue Shield', item.player) and self.multiworld.difficulty_requirements[item.player].progressive_shield_limit >= 2: return 'Red Shield' - elif self.world.difficulty_requirements[item.player].progressive_shield_limit >= 1: + elif self.multiworld.difficulty_requirements[item.player].progressive_shield_limit >= 1: return 'Blue Shield' elif 'Bow' in item_name: if state.has('Silver Bow', item.player): return - elif state.has('Bow', item.player) and (self.world.difficulty_requirements[item.player].progressive_bow_limit >= 2 - or self.world.logic[item.player] == 'noglitches' - or self.world.swordless[item.player]): # modes where silver bow is always required for ganon + elif state.has('Bow', item.player) and (self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 2 + or self.multiworld.logic[item.player] == 'noglitches' + or self.multiworld.swordless[item.player]): # modes where silver bow is always required for ganon return 'Silver Bow' - elif self.world.difficulty_requirements[item.player].progressive_bow_limit >= 1: + elif self.multiworld.difficulty_requirements[item.player].progressive_bow_limit >= 1: return 'Bow' elif item.advancement: return item_name @@ -319,7 +319,7 @@ class ALTTPWorld(World): def pre_fill(self): from Fill import fill_restrictive, FillError attempts = 5 - world = self.world + world = self.multiworld player = self.player all_state = world.get_all_state(use_cache=True) 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']] @@ -362,7 +362,7 @@ class ALTTPWorld(World): ShopSlotFill(world) def use_enemizer(self): - world = self.world + world = self.multiworld player = self.player return (world.boss_shuffle[player] or world.enemy_shuffle[player] or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default' @@ -370,7 +370,7 @@ class ALTTPWorld(World): or world.killable_thieves[player]) def generate_output(self, output_directory: str): - world = self.world + world = self.multiworld player = self.player try: use_enemizer = self.use_enemizer() @@ -409,7 +409,7 @@ class ALTTPWorld(World): deathlink=world.death_link[player], allowcollect=world.allow_collect[player]) - rompath = os.path.join(output_directory, f"{self.world.get_out_file_name_base(self.player)}.sfc") + rompath = os.path.join(output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}.sfc") rom.write_to_file(rompath) patch = LttPDeltaPatch(os.path.splitext(rompath)[0]+LttPDeltaPatch.patch_file_ending, player=player, player_name=world.player_name[player], patched_path=rompath) @@ -443,7 +443,7 @@ class ALTTPWorld(World): # 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() - multidata["connect_names"][new_name] = multidata["connect_names"][self.world.player_name[self.player]] + multidata["connect_names"][new_name] = multidata["connect_names"][self.multiworld.player_name[self.player]] def create_item(self, name: str) -> Item: return ALttPItem(name, self.player, **item_init_table[name]) @@ -510,16 +510,16 @@ class ALTTPWorld(World): logging.warning(f"Could not trash fill Ganon's Tower for player {player}.") def get_filler_item_name(self) -> str: - if self.world.goal[self.player] == "icerodhunt": + if self.multiworld.goal[self.player] == "icerodhunt": item = "Nothing" else: - item = self.world.random.choice(extras_list) - return GetBeemizerItem(self.world, self.player, item) + item = self.multiworld.random.choice(extras_list) + return GetBeemizerItem(self.multiworld, self.player, item) def get_pre_fill_items(self): res = [] if self.dungeon_local_item_names: - for (name, player), dungeon in self.world.dungeons.items(): + for (name, player), dungeon in self.multiworld.dungeons.items(): if player == self.player: for item in dungeon.all_items: if item.name in self.dungeon_local_item_names: @@ -538,8 +538,8 @@ def get_same_seed(world, seed_def: tuple) -> str: class ALttPLogic(LogicMixin): def _lttp_has_key(self, item, player, count: int = 1): - if self.world.logic[player] == 'nologic': + if self.multiworld.logic[player] == 'nologic': return True - if self.world.smallkey_shuffle[player] == smallkey_shuffle.option_universal: + if self.multiworld.smallkey_shuffle[player] == smallkey_shuffle.option_universal: return self.can_buy_unlimited('Small Key (Universal)', player) return self.prog_items[item, player] >= count diff --git a/worlds/archipidle/__init__.py b/worlds/archipidle/__init__.py index 8b1061b5..50e2912d 100644 --- a/worlds/archipidle/__init__.py +++ b/worlds/archipidle/__init__.py @@ -43,7 +43,7 @@ class ArchipIDLEWorld(World): def generate_basic(self): item_table_copy = list(item_table) - self.world.random.shuffle(item_table_copy) + self.multiworld.random.shuffle(item_table_copy) item_pool = [] for i in range(100): @@ -55,31 +55,31 @@ class ArchipIDLEWorld(World): ) item_pool.append(item) - self.world.itempool += item_pool + self.multiworld.itempool += item_pool def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def create_item(self, name: str) -> Item: return Item(name, ItemClassification.progression, self.item_name_to_id[name], self.player) def create_regions(self): - self.world.regions += [ - create_region(self.world, self.player, 'Menu', None, ['Entrance to IDLE Zone']), - create_region(self.world, self.player, 'IDLE Zone', self.location_name_to_id) + self.multiworld.regions += [ + create_region(self.multiworld, self.player, 'Menu', None, ['Entrance to IDLE Zone']), + create_region(self.multiworld, self.player, 'IDLE Zone', self.location_name_to_id) ] # link up our region with the entrance we just made - self.world.get_entrance('Entrance to IDLE Zone', self.player)\ - .connect(self.world.get_region('IDLE Zone', self.player)) + self.multiworld.get_entrance('Entrance to IDLE Zone', self.player)\ + .connect(self.multiworld.get_region('IDLE Zone', self.player)) def get_filler_item_name(self) -> str: - return self.world.random.choice(item_table) + return self.multiworld.random.choice(item_table) def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None): region = Region(name, RegionType.Generic, name, player) - region.world = world + region.multiworld = world if locations: for location_name in locations.keys(): location = ArchipIDLELocation(player, location_name, locations[location_name], region) diff --git a/worlds/checksfinder/__init__.py b/worlds/checksfinder/__init__.py index ec9091c3..5dce1b8e 100644 --- a/worlds/checksfinder/__init__.py +++ b/worlds/checksfinder/__init__.py @@ -38,12 +38,12 @@ class ChecksFinderWorld(World): def _get_checksfinder_data(self): return { - 'world_seed': self.world.slot_seeds[self.player].getrandbits(32), - 'seed_name': self.world.seed_name, - 'player_name': self.world.get_player_name(self.player), + 'world_seed': self.multiworld.slot_seeds[self.player].getrandbits(32), + 'seed_name': self.multiworld.seed_name, + 'player_name': self.multiworld.get_player_name(self.player), 'player_id': self.player, 'client_version': client_version, - 'race': self.world.is_race, + 'race': self.multiworld.is_race, } def generate_basic(self): @@ -61,15 +61,15 @@ class ChecksFinderWorld(World): # Convert itempool into real items itempool = [item for item in map(lambda name: self.create_item(name), itempool)] - self.world.itempool += itempool + self.multiworld.itempool += itempool def set_rules(self): - set_rules(self.world, self.player) - set_completion_rules(self.world, self.player) + set_rules(self.multiworld, self.player) + set_completion_rules(self.multiworld, self.player) def create_regions(self): def ChecksFinderRegion(region_name: str, exits=[]): - ret = Region(region_name, RegionType.Generic, region_name, self.player, self.world) + ret = Region(region_name, RegionType.Generic, region_name, self.player, self.multiworld) ret.locations = [ChecksFinderAdvancement(self.player, loc_name, loc_data.id, ret) for loc_name, loc_data in advancement_table.items() if loc_data.region == region_name] @@ -77,13 +77,13 @@ class ChecksFinderWorld(World): ret.exits.append(Entrance(self.player, exit, ret)) return ret - self.world.regions += [ChecksFinderRegion(*r) for r in checksfinder_regions] - link_checksfinder_structures(self.world, self.player) + self.multiworld.regions += [ChecksFinderRegion(*r) for r in checksfinder_regions] + link_checksfinder_structures(self.multiworld, self.player) def fill_slot_data(self): slot_data = self._get_checksfinder_data() for option_name in checksfinder_options: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] if slot_data.get(option_name, None) is None and type(option.value) in {str, int}: slot_data[option_name] = int(option.value) return slot_data diff --git a/worlds/dark_souls_3/__init__.py b/worlds/dark_souls_3/__init__.py index df56306c..0b062b3a 100644 --- a/worlds/dark_souls_3/__init__.py +++ b/worlds/dark_souls_3/__init__.py @@ -79,7 +79,7 @@ class DarkSouls3World(World): def create_regions(self): menu_region = Region("Menu", RegionType.Generic, "Menu", self.player) - self.world.regions.append(menu_region) + self.multiworld.regions.append(menu_region) # Create all Vanilla regions of Dark Souls III firelink_shrine_region = self.create_region("Firelink Shrine", fire_link_shrine_table) @@ -106,71 +106,71 @@ class DarkSouls3World(World): # Create the entrance to connect those regions menu_region.exits.append(Entrance(self.player, "New Game", menu_region)) - self.world.get_entrance("New Game", self.player).connect(firelink_shrine_region) + self.multiworld.get_entrance("New Game", self.player).connect(firelink_shrine_region) firelink_shrine_region.exits.append(Entrance(self.player, "Goto High Wall of Lothric", firelink_shrine_region)) firelink_shrine_region.exits.append(Entrance(self.player, "Goto Kiln Of The First Flame", firelink_shrine_region)) firelink_shrine_region.exits.append(Entrance(self.player, "Goto Bell Tower", firelink_shrine_region)) - self.world.get_entrance("Goto High Wall of Lothric", self.player).connect(high_wall_of_lothric_region) - self.world.get_entrance("Goto Kiln Of The First Flame", self.player).connect(kiln_of_the_first_flame_region) - self.world.get_entrance("Goto Bell Tower", self.player).connect(firelink_shrine_bell_tower_region) + self.multiworld.get_entrance("Goto High Wall of Lothric", self.player).connect(high_wall_of_lothric_region) + self.multiworld.get_entrance("Goto Kiln Of The First Flame", self.player).connect(kiln_of_the_first_flame_region) + self.multiworld.get_entrance("Goto Bell Tower", self.player).connect(firelink_shrine_bell_tower_region) high_wall_of_lothric_region.exits.append(Entrance(self.player, "Goto Undead Settlement", high_wall_of_lothric_region)) high_wall_of_lothric_region.exits.append(Entrance(self.player, "Goto Lothric Castle", high_wall_of_lothric_region)) - self.world.get_entrance("Goto Undead Settlement", self.player).connect(undead_settlement_region) - self.world.get_entrance("Goto Lothric Castle", self.player).connect(lothric_castle_region) + self.multiworld.get_entrance("Goto Undead Settlement", self.player).connect(undead_settlement_region) + self.multiworld.get_entrance("Goto Lothric Castle", self.player).connect(lothric_castle_region) undead_settlement_region.exits.append(Entrance(self.player, "Goto Road Of Sacrifices", undead_settlement_region)) - self.world.get_entrance("Goto Road Of Sacrifices", self.player).connect(road_of_sacrifices_region) + self.multiworld.get_entrance("Goto Road Of Sacrifices", self.player).connect(road_of_sacrifices_region) road_of_sacrifices_region.exits.append(Entrance(self.player, "Goto Cathedral", road_of_sacrifices_region)) road_of_sacrifices_region.exits.append(Entrance(self.player, "Goto Farron keep", road_of_sacrifices_region)) - self.world.get_entrance("Goto Cathedral", self.player).connect(cathedral_of_the_deep_region) - self.world.get_entrance("Goto Farron keep", self.player).connect(farron_keep_region) + self.multiworld.get_entrance("Goto Cathedral", self.player).connect(cathedral_of_the_deep_region) + self.multiworld.get_entrance("Goto Farron keep", self.player).connect(farron_keep_region) farron_keep_region.exits.append(Entrance(self.player, "Goto Carthus catacombs", farron_keep_region)) - self.world.get_entrance("Goto Carthus catacombs", self.player).connect(catacombs_of_carthus_region) + self.multiworld.get_entrance("Goto Carthus catacombs", self.player).connect(catacombs_of_carthus_region) catacombs_of_carthus_region.exits.append(Entrance(self.player, "Goto Irithyll of the boreal", catacombs_of_carthus_region)) catacombs_of_carthus_region.exits.append(Entrance(self.player, "Goto Smouldering Lake", catacombs_of_carthus_region)) - self.world.get_entrance("Goto Irithyll of the boreal", self.player).\ + self.multiworld.get_entrance("Goto Irithyll of the boreal", self.player).\ connect(irithyll_of_the_boreal_valley_region) - self.world.get_entrance("Goto Smouldering Lake", self.player).connect(smouldering_lake_region) + self.multiworld.get_entrance("Goto Smouldering Lake", self.player).connect(smouldering_lake_region) irithyll_of_the_boreal_valley_region.exits.append(Entrance(self.player, "Goto Irithyll dungeon", irithyll_of_the_boreal_valley_region)) irithyll_of_the_boreal_valley_region.exits.append(Entrance(self.player, "Goto Anor Londo", irithyll_of_the_boreal_valley_region)) - self.world.get_entrance("Goto Irithyll dungeon", self.player).connect(irithyll_dungeon_region) - self.world.get_entrance("Goto Anor Londo", self.player).connect(anor_londo_region) + self.multiworld.get_entrance("Goto Irithyll dungeon", self.player).connect(irithyll_dungeon_region) + self.multiworld.get_entrance("Goto Anor Londo", self.player).connect(anor_londo_region) irithyll_dungeon_region.exits.append(Entrance(self.player, "Goto Archdragon peak", irithyll_dungeon_region)) irithyll_dungeon_region.exits.append(Entrance(self.player, "Goto Profaned capital", irithyll_dungeon_region)) - self.world.get_entrance("Goto Archdragon peak", self.player).connect(archdragon_peak_region) - self.world.get_entrance("Goto Profaned capital", self.player).connect(profaned_capital_region) + self.multiworld.get_entrance("Goto Archdragon peak", self.player).connect(archdragon_peak_region) + self.multiworld.get_entrance("Goto Profaned capital", self.player).connect(profaned_capital_region) lothric_castle_region.exits.append(Entrance(self.player, "Goto Consumed King Garden", lothric_castle_region)) lothric_castle_region.exits.append(Entrance(self.player, "Goto Grand Archives", lothric_castle_region)) - self.world.get_entrance("Goto Consumed King Garden", self.player).connect(consumed_king_garden_region) - self.world.get_entrance("Goto Grand Archives", self.player).connect(grand_archives_region) + self.multiworld.get_entrance("Goto Consumed King Garden", self.player).connect(consumed_king_garden_region) + self.multiworld.get_entrance("Goto Grand Archives", self.player).connect(grand_archives_region) consumed_king_garden_region.exits.append(Entrance(self.player, "Goto Untended Graves", consumed_king_garden_region)) - self.world.get_entrance("Goto Untended Graves", self.player).connect(untended_graves_region) + self.multiworld.get_entrance("Goto Untended Graves", self.player).connect(untended_graves_region) # For each region, add the associated locations retrieved from the corresponding location_table def create_region(self, region_name, location_table) -> Region: - new_region = Region(region_name, RegionType.Generic, region_name, self.player, self.world) + new_region = Region(region_name, RegionType.Generic, region_name, self.player, self.multiworld) if location_table: for name, address in location_table.items(): location = DarkSouls3Location(self.player, name, self.location_name_to_id[name], new_region) new_region.locations.append(location) - self.world.regions.append(new_region) + self.multiworld.regions.append(new_region) return new_region def create_items(self): for name, address in self.item_name_to_id.items(): # Specific items will be included in the item pool under certain conditions. See generate_basic if name != "Basin of Vows": - self.world.itempool += [self.create_item(name)] + self.multiworld.itempool += [self.create_item(name)] def generate_early(self): pass @@ -178,46 +178,46 @@ class DarkSouls3World(World): def set_rules(self) -> None: # Define the access rules to the entrances - set_rule(self.world.get_entrance("Goto Bell Tower", self.player), + set_rule(self.multiworld.get_entrance("Goto Bell Tower", self.player), lambda state: state.has("Tower Key", self.player)) - set_rule(self.world.get_entrance("Goto Undead Settlement", self.player), + set_rule(self.multiworld.get_entrance("Goto Undead Settlement", self.player), lambda state: state.has("Small Lothric Banner", self.player)) - set_rule(self.world.get_entrance("Goto Lothric Castle", self.player), + set_rule(self.multiworld.get_entrance("Goto Lothric Castle", self.player), lambda state: state.has("Basin of Vows", self.player)) - set_rule(self.world.get_entrance("Goto Irithyll of the boreal", self.player), + set_rule(self.multiworld.get_entrance("Goto Irithyll of the boreal", self.player), lambda state: state.has("Small Doll", self.player)) - set_rule(self.world.get_entrance("Goto Archdragon peak", self.player), + set_rule(self.multiworld.get_entrance("Goto Archdragon peak", self.player), lambda state: state.can_reach("CKG: Soul of Consumed Oceiros", "Location", self.player)) - set_rule(self.world.get_entrance("Goto Profaned capital", self.player), + set_rule(self.multiworld.get_entrance("Goto Profaned capital", self.player), lambda state: state.has("Storm Ruler", self.player)) - set_rule(self.world.get_entrance("Goto Grand Archives", self.player), + set_rule(self.multiworld.get_entrance("Goto Grand Archives", self.player), lambda state: state.has("Grand Archives Key", self.player)) - set_rule(self.world.get_entrance("Goto Kiln Of The First Flame", self.player), + set_rule(self.multiworld.get_entrance("Goto Kiln Of The First Flame", self.player), lambda state: state.has("Cinders of a Lord - Abyss Watcher", self.player) and state.has("Cinders of a Lord - Yhorm the Giant", self.player) and state.has("Cinders of a Lord - Aldrich", self.player) and state.has("Cinders of a Lord - Lothric Prince", self.player)) # Define the access rules to some specific locations - set_rule(self.world.get_location("HWL: Soul of the Dancer", self.player), + set_rule(self.multiworld.get_location("HWL: Soul of the Dancer", self.player), lambda state: state.has("Basin of Vows", self.player)) - set_rule(self.world.get_location("HWL: Greirat's Ashes", self.player), + set_rule(self.multiworld.get_location("HWL: Greirat's Ashes", self.player), lambda state: state.has("Cell Key", self.player)) - set_rule(self.world.get_location("ID: Bellowing Dragoncrest Ring", self.player), + set_rule(self.multiworld.get_location("ID: Bellowing Dragoncrest Ring", self.player), lambda state: state.has("Jailbreaker's Key", self.player)) - set_rule(self.world.get_location("ID: Prisoner Chief's Ashes", self.player), + set_rule(self.multiworld.get_location("ID: Prisoner Chief's Ashes", self.player), lambda state: state.has("Jailer's Key Ring", self.player)) - set_rule(self.world.get_location("ID: Covetous Gold Serpent Ring", self.player), + set_rule(self.multiworld.get_location("ID: Covetous Gold Serpent Ring", self.player), lambda state: state.has("Old Cell Key", self.player)) - set_rule(self.world.get_location("ID: Karla's Ashes", self.player), + set_rule(self.multiworld.get_location("ID: Karla's Ashes", self.player), lambda state: state.has("Jailer's Key Ring", self.player)) black_hand_gotthard_corpse_rule = lambda state: \ (state.can_reach("AL: Cinders of a Lord - Aldrich", "Location", self.player) and state.can_reach("PC: Cinders of a Lord - Yhorm the Giant", "Location", self.player)) - set_rule(self.world.get_location("LC: Grand Archives Key", self.player), black_hand_gotthard_corpse_rule) - set_rule(self.world.get_location("LC: Gotthard Twinswords", self.player), black_hand_gotthard_corpse_rule) + set_rule(self.multiworld.get_location("LC: Grand Archives Key", self.player), black_hand_gotthard_corpse_rule) + set_rule(self.multiworld.get_location("LC: Gotthard Twinswords", self.player), black_hand_gotthard_corpse_rule) - self.world.completion_condition[self.player] = lambda state: \ + self.multiworld.completion_condition[self.player] = lambda state: \ state.has("Cinders of a Lord - Abyss Watcher", self.player) and \ state.has("Cinders of a Lord - Yhorm the Giant", self.player) and \ state.has("Cinders of a Lord - Aldrich", self.player) and \ @@ -226,30 +226,30 @@ class DarkSouls3World(World): def generate_basic(self): # Depending on the specified option, add the Basin of Vows to a specific location or to the item pool item = self.create_item("Basin of Vows") - if self.world.late_basin_of_vows[self.player]: - self.world.get_location("IBV: Soul of Pontiff Sulyvahn", self.player).place_locked_item(item) + if self.multiworld.late_basin_of_vows[self.player]: + self.multiworld.get_location("IBV: Soul of Pontiff Sulyvahn", self.player).place_locked_item(item) else: - self.world.itempool += [item] + self.multiworld.itempool += [item] # Fill item pool with additional items item_pool_len = self.item_name_to_id.__len__() total_required_locations = self.location_name_to_id.__len__() for i in range(item_pool_len, total_required_locations): - self.world.itempool += [self.create_item("Soul of an Intrepid Hero")] + self.multiworld.itempool += [self.create_item("Soul of an Intrepid Hero")] def generate_output(self, output_directory: str): # Depending on the specified option, modify items hexadecimal value to add an upgrade level item_dictionary_copy = item_dictionary.copy() - if self.world.randomize_weapons_level[self.player]: + if self.multiworld.randomize_weapons_level[self.player]: # Randomize some weapons upgrades for name in weapons_upgrade_5_table.keys(): - if self.world.random.randint(0, 100) < 33: - value = self.world.random.randint(1, 5) + if self.multiworld.random.randint(0, 100) < 33: + value = self.multiworld.random.randint(1, 5) item_dictionary_copy[name] += value for name in weapons_upgrade_10_table.keys(): - if self.world.random.randint(0, 100) < 33: - value = self.world.random.randint(1, 10) + if self.multiworld.random.randint(0, 100) < 33: + value = self.multiworld.random.randint(1, 10) item_dictionary_copy[name] += value # Create the mandatory lists to generate the player's output file @@ -258,7 +258,7 @@ class DarkSouls3World(World): locations_id = [] locations_address = [] locations_target = [] - for location in self.world.get_filled_locations(): + for location in self.multiworld.get_filled_locations(): if location.item.player == self.player: items_id.append(location.item.code) items_address.append(item_dictionary[location.item.name]) @@ -273,12 +273,12 @@ class DarkSouls3World(World): data = { "options": { - "auto_equip": self.world.auto_equip[self.player].value, - "lock_equip": self.world.lock_equip[self.player].value, - "no_weapon_requirements": self.world.no_weapon_requirements[self.player].value, + "auto_equip": self.multiworld.auto_equip[self.player].value, + "lock_equip": self.multiworld.lock_equip[self.player].value, + "no_weapon_requirements": self.multiworld.no_weapon_requirements[self.player].value, }, - "seed": self.world.seed_name, # to verify the server's multiworld - "slot": self.world.player_name[self.player], # to connect to server + "seed": self.multiworld.seed_name, # to verify the server's multiworld + "slot": self.multiworld.player_name[self.player], # to connect to server "base_id": self.base_id, # to merge location and items lists "locationsId": locations_id, "locationsAddress": locations_address, @@ -288,6 +288,6 @@ class DarkSouls3World(World): } # generate the file - filename = f"AP-{self.world.seed_name}-P{self.player}-{self.world.player_name[self.player]}.json" + filename = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.multiworld.player_name[self.player]}.json" with open(os.path.join(output_directory, filename), 'w') as outfile: json.dump(data, outfile) diff --git a/worlds/dkc3/Regions.py b/worlds/dkc3/Regions.py index e33ff38c..f29c4eb2 100644 --- a/worlds/dkc3/Regions.py +++ b/worlds/dkc3/Regions.py @@ -913,7 +913,7 @@ def connect_regions(world, player, level_list): def create_region(world: MultiWorld, player: int, active_locations, name: str, locations=None, exits=None): # Shamelessly stolen from the ROR2 definition ret = Region(name, None, name, player) - ret.world = world + ret.multiworld = world if locations: for locationName, locationData in locations.items(): loc_id = active_locations.get(locationName, 0) diff --git a/worlds/dkc3/__init__.py b/worlds/dkc3/__init__.py index 332f23e4..9e2f9e67 100644 --- a/worlds/dkc3/__init__.py +++ b/worlds/dkc3/__init__.py @@ -69,13 +69,13 @@ class DKC3World(World): def fill_slot_data(self) -> dict: slot_data = self._get_slot_data() for option_name in dkc3_options: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] slot_data[option_name] = option.value return slot_data def generate_basic(self): - self.topology_present = self.world.level_shuffle[self.player].value + self.topology_present = self.multiworld.level_shuffle[self.player].value itempool: typing.List[DKC3Item] = [] # Levels @@ -85,14 +85,14 @@ class DKC3World(World): # Rocket Rush Cog total_required_locations -= 1 number_of_cogs = 4 - self.world.get_location(LocationName.rocket_rush_flag, self.player).place_locked_item(self.create_item(ItemName.krematoa_cog)) + self.multiworld.get_location(LocationName.rocket_rush_flag, self.player).place_locked_item(self.create_item(ItemName.krematoa_cog)) number_of_bosses = 8 - if self.world.goal[self.player] == "knautilus": - self.world.get_location(LocationName.kastle_kaos, self.player).place_locked_item(self.create_item(ItemName.victory)) + if self.multiworld.goal[self.player] == "knautilus": + self.multiworld.get_location(LocationName.kastle_kaos, self.player).place_locked_item(self.create_item(ItemName.victory)) number_of_bosses = 7 else: - self.world.get_location(LocationName.banana_bird_mother, self.player).place_locked_item(self.create_item(ItemName.victory)) - number_of_banana_birds = self.world.number_of_banana_birds[self.player] + self.multiworld.get_location(LocationName.banana_bird_mother, self.player).place_locked_item(self.create_item(ItemName.victory)) + number_of_banana_birds = self.multiworld.number_of_banana_birds[self.player] # Bosses total_required_locations += number_of_bosses @@ -100,15 +100,15 @@ class DKC3World(World): # Secret Caves total_required_locations += 13 - if self.world.kongsanity[self.player]: + if self.multiworld.kongsanity[self.player]: total_required_locations += 39 ## Brothers Bear if False:#self.world.include_trade_sequence[self.player]: total_required_locations += 10 - number_of_bonus_coins = (self.world.krematoa_bonus_coin_cost[self.player] * 5) - number_of_bonus_coins += math.ceil((85 - number_of_bonus_coins) * self.world.percentage_of_extra_bonus_coins[self.player] / 100) + number_of_bonus_coins = (self.multiworld.krematoa_bonus_coin_cost[self.player] * 5) + number_of_bonus_coins += math.ceil((85 - number_of_bonus_coins) * self.multiworld.percentage_of_extra_bonus_coins[self.player] / 100) itempool += [self.create_item(ItemName.bonus_coin) for _ in range(number_of_bonus_coins)] itempool += [self.create_item(ItemName.dk_coin) for _ in range(41)] @@ -119,27 +119,27 @@ class DKC3World(World): total_junk_count = total_required_locations - len(itempool) junk_pool = [] - for item_name in self.world.random.choices(list(junk_table.keys()), k=total_junk_count): + for item_name in self.multiworld.random.choices(list(junk_table.keys()), k=total_junk_count): junk_pool.append(self.create_item(item_name)) itempool += junk_pool self.active_level_list = level_list.copy() - if self.world.level_shuffle[self.player]: - self.world.random.shuffle(self.active_level_list) + if self.multiworld.level_shuffle[self.player]: + self.multiworld.random.shuffle(self.active_level_list) - connect_regions(self.world, self.player, self.active_level_list) + connect_regions(self.multiworld, self.player, self.active_level_list) - self.world.itempool += itempool + self.multiworld.itempool += itempool def generate_output(self, output_directory: str): try: - world = self.world + world = self.multiworld player = self.player rom = LocalRom(get_base_rom_path()) - patch_rom(self.world, rom, self.player, self.active_level_list) + patch_rom(self.multiworld, rom, self.player, self.active_level_list) self.active_level_list.append(LocationName.rocket_rush_region) @@ -165,7 +165,7 @@ class DKC3World(World): # 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() - multidata["connect_names"][new_name] = multidata["connect_names"][self.world.player_name[self.player]] + multidata["connect_names"][new_name] = multidata["connect_names"][self.multiworld.player_name[self.player]] if self.topology_present: world_names = [ @@ -181,14 +181,14 @@ class DKC3World(World): er_hint_data = {} for world_index in range(len(world_names)): for level_index in range(5): - level_region = self.world.get_region(self.active_level_list[world_index * 5 + level_index], self.player) + level_region = self.multiworld.get_region(self.active_level_list[world_index * 5 + level_index], self.player) for location in level_region.locations: er_hint_data[location.address] = world_names[world_index] multidata['er_hint_data'][self.player] = er_hint_data def create_regions(self): - location_table = setup_locations(self.world, self.player) - create_regions(self.world, self.player, location_table) + location_table = setup_locations(self.multiworld, self.player) + create_regions(self.multiworld, self.player, location_table) def create_item(self, name: str, force_non_progression=False) -> Item: data = item_table[name] @@ -205,4 +205,4 @@ class DKC3World(World): return created_item def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) diff --git a/worlds/factorio/Mod.py b/worlds/factorio/Mod.py index 33e3b75a..495218ef 100644 --- a/worlds/factorio/Mod.py +++ b/worlds/factorio/Mod.py @@ -77,7 +77,7 @@ class FactorioModFile(worlds.Files.APContainer): def generate_mod(world: "Factorio", output_directory: str): player = world.player - multiworld = world.world + multiworld = world.multiworld global data_final_template, locale_template, control_template, data_template, settings_template with template_load_lock: if not data_final_template: diff --git a/worlds/factorio/Shapes.py b/worlds/factorio/Shapes.py index 4f093c3a..7ec6f07a 100644 --- a/worlds/factorio/Shapes.py +++ b/worlds/factorio/Shapes.py @@ -20,7 +20,7 @@ def _sorter(location: "FactorioScienceLocation"): def get_shapes(factorio_world: "Factorio") -> Dict["FactorioScienceLocation", Set["FactorioScienceLocation"]]: - world = factorio_world.world + world = factorio_world.multiworld player = factorio_world.player prerequisites: Dict["FactorioScienceLocation", Set["FactorioScienceLocation"]] = {} layout = world.tech_tree_layout[player].value diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index b07c21ec..c533d425 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -73,32 +73,32 @@ class Factorio(World): generate_output = generate_mod def generate_early(self) -> None: - self.world.max_tech_cost[self.player] = max(self.world.max_tech_cost[self.player], - self.world.min_tech_cost[self.player]) - self.tech_mix = self.world.tech_cost_mix[self.player] - self.skip_silo = self.world.silo[self.player].value == Silo.option_spawn + self.multiworld.max_tech_cost[self.player] = max(self.multiworld.max_tech_cost[self.player], + self.multiworld.min_tech_cost[self.player]) + self.tech_mix = self.multiworld.tech_cost_mix[self.player] + self.skip_silo = self.multiworld.silo[self.player].value == Silo.option_spawn def create_regions(self): player = self.player - random = self.world.random - menu = Region("Menu", RegionType.Generic, "Menu", player, self.world) + random = self.multiworld.random + menu = Region("Menu", RegionType.Generic, "Menu", player, self.multiworld) crash = Entrance(player, "Crash Land", menu) menu.exits.append(crash) - nauvis = Region("Nauvis", RegionType.Generic, "Nauvis", player, self.world) + nauvis = Region("Nauvis", RegionType.Generic, "Nauvis", player, self.multiworld) location_count = len(base_tech_table) - len(useless_technologies) - self.skip_silo + \ - self.world.evolution_traps[player].value + self.world.attack_traps[player].value + self.multiworld.evolution_traps[player].value + self.multiworld.attack_traps[player].value location_pool = [] - for pack in sorted(self.world.max_science_pack[self.player].get_allowed_packs()): + for pack in sorted(self.multiworld.max_science_pack[self.player].get_allowed_packs()): location_pool.extend(location_pools[pack]) - location_names = self.world.random.sample(location_pool, location_count) + location_names = self.multiworld.random.sample(location_pool, location_count) self.locations = [FactorioScienceLocation(player, loc_name, self.location_name_to_id[loc_name], nauvis) for loc_name in location_names] - rand_values = sorted(random.randint(self.world.min_tech_cost[self.player], - self.world.max_tech_cost[self.player]) for _ in self.locations) + rand_values = sorted(random.randint(self.multiworld.min_tech_cost[self.player], + self.multiworld.max_tech_cost[self.player]) for _ in self.locations) for i, location in enumerate(sorted(self.locations, key=lambda loc: loc.rel_cost)): location.count = rand_values[i] del rand_values @@ -108,27 +108,27 @@ class Factorio(World): event = FactorioItem("Victory", ItemClassification.progression, None, player) location.place_locked_item(event) - for ingredient in sorted(self.world.max_science_pack[self.player].get_allowed_packs()): + for ingredient in sorted(self.multiworld.max_science_pack[self.player].get_allowed_packs()): location = FactorioLocation(player, f"Automate {ingredient}", None, nauvis) nauvis.locations.append(location) event = FactorioItem(f"Automated {ingredient}", ItemClassification.progression, None, player) location.place_locked_item(event) crash.connect(nauvis) - self.world.regions += [menu, nauvis] + self.multiworld.regions += [menu, nauvis] def set_rules(self): - world = self.world + world = self.multiworld player = self.player self.custom_technologies = self.set_custom_technologies() self.set_custom_recipes() shapes = get_shapes(self) if world.logic[player] != 'nologic': from worlds.generic import Rules - for ingredient in self.world.max_science_pack[self.player].get_allowed_packs(): + for ingredient in self.multiworld.max_science_pack[self.player].get_allowed_packs(): location = world.get_location(f"Automate {ingredient}", player) - if self.world.recipe_ingredients[self.player]: + if self.multiworld.recipe_ingredients[self.player]: custom_recipe = self.custom_recipes[ingredient] location.access_rule = lambda state, ingredient=ingredient, custom_recipe=custom_recipe: \ @@ -148,12 +148,12 @@ class Factorio(World): prerequisites: all(state.can_reach(loc) for loc in locations)) silo_recipe = None - if self.world.silo[self.player] == Silo.option_spawn: + if self.multiworld.silo[self.player] == Silo.option_spawn: silo_recipe = self.custom_recipes["rocket-silo"] if "rocket-silo" in self.custom_recipes \ else next(iter(all_product_sources.get("rocket-silo"))) part_recipe = self.custom_recipes["rocket-part"] satellite_recipe = None - if self.world.goal[self.player] == Goal.option_satellite: + if self.multiworld.goal[self.player] == Goal.option_satellite: satellite_recipe = self.custom_recipes["satellite"] if "satellite" in self.custom_recipes \ else next(iter(all_product_sources.get("satellite"))) victory_tech_names = get_rocket_requirements(silo_recipe, part_recipe, satellite_recipe) @@ -165,12 +165,12 @@ class Factorio(World): def generate_basic(self): player = self.player - want_progressives = collections.defaultdict(lambda: self.world.progressive[player]. - want_progressives(self.world.random)) - self.world.itempool.extend(self.create_item("Evolution Trap") for _ in - range(self.world.evolution_traps[player].value)) - self.world.itempool.extend(self.create_item("Attack Trap") for _ in - range(self.world.attack_traps[player].value)) + want_progressives = collections.defaultdict(lambda: self.multiworld.progressive[player]. + want_progressives(self.multiworld.random)) + self.multiworld.itempool.extend(self.create_item("Evolution Trap") for _ in + range(self.multiworld.evolution_traps[player].value)) + self.multiworld.itempool.extend(self.create_item("Attack Trap") for _ in + range(self.multiworld.attack_traps[player].value)) cost_sorted_locations = sorted(self.locations, key=lambda location: location.name) special_index = {"automation": 0, @@ -189,19 +189,19 @@ class Factorio(World): tech_item = self.create_item(item_name) index = special_index.get(tech_name, None) if index is None: - self.world.itempool.append(tech_item) + self.multiworld.itempool.append(tech_item) else: loc = cost_sorted_locations[index] loc.place_locked_item(tech_item) loc.revealed = True - map_basic_settings = self.world.world_gen[player].value["basic"] + map_basic_settings = self.multiworld.world_gen[player].value["basic"] if map_basic_settings.get("seed", None) is None: # allow seed 0 - map_basic_settings["seed"] = self.world.slot_seeds[player].randint(0, 2 ** 32 - 1) # 32 bit uint + map_basic_settings["seed"] = self.multiworld.slot_seeds[player].randint(0, 2 ** 32 - 1) # 32 bit uint - if self.world.tech_tree_information[player] == TechTreeInformation.option_full: + if self.multiworld.tech_tree_information[player] == TechTreeInformation.option_full: # mark all locations as pre-hinted - self.world.start_location_hints[self.player].value.update(base_tech_table) + self.multiworld.start_location_hints[self.player].value.update(base_tech_table) for loc in self.locations: loc.revealed = True @@ -259,7 +259,7 @@ class Factorio(World): # have to first sort for determinism, while filtering out non-stacking items pool: typing.List[str] = sorted(pool & valid_ingredients) # then sort with random data to shuffle - self.world.random.shuffle(pool) + self.multiworld.random.shuffle(pool) target_raw = int(sum((count for ingredient, count in original.base_cost.items())) * factor) target_energy = original.total_energy * factor target_num_ingredients = len(original.ingredients) @@ -303,7 +303,7 @@ class Factorio(World): if min_num > max_num: fallback_pool.append(ingredient) continue # can't use that ingredient - num = self.world.random.randint(min_num, max_num) + num = self.multiworld.random.randint(min_num, max_num) new_ingredients[ingredient] = num remaining_raw -= num * ingredient_raw remaining_energy -= num * ingredient_energy @@ -347,58 +347,58 @@ class Factorio(World): def set_custom_technologies(self): custom_technologies = {} - allowed_packs = self.world.max_science_pack[self.player].get_allowed_packs() + allowed_packs = self.multiworld.max_science_pack[self.player].get_allowed_packs() for technology_name, technology in base_technology_table.items(): - custom_technologies[technology_name] = technology.get_custom(self.world, allowed_packs, self.player) + custom_technologies[technology_name] = technology.get_custom(self.multiworld, allowed_packs, self.player) return custom_technologies def set_custom_recipes(self): original_rocket_part = recipes["rocket-part"] science_pack_pools = get_science_pack_pools() - valid_pool = sorted(science_pack_pools[self.world.max_science_pack[self.player].get_max_pack()] & valid_ingredients) - self.world.random.shuffle(valid_pool) + valid_pool = sorted(science_pack_pools[self.multiworld.max_science_pack[self.player].get_max_pack()] & valid_ingredients) + self.multiworld.random.shuffle(valid_pool) self.custom_recipes = {"rocket-part": Recipe("rocket-part", original_rocket_part.category, {valid_pool[x]: 10 for x in range(3)}, original_rocket_part.products, original_rocket_part.energy)} - if self.world.recipe_ingredients[self.player]: + if self.multiworld.recipe_ingredients[self.player]: valid_pool = [] - for pack in self.world.max_science_pack[self.player].get_ordered_science_packs(): + for pack in self.multiworld.max_science_pack[self.player].get_ordered_science_packs(): valid_pool += sorted(science_pack_pools[pack]) - self.world.random.shuffle(valid_pool) + self.multiworld.random.shuffle(valid_pool) if pack in recipes: # skips over space science pack new_recipe = self.make_quick_recipe(recipes[pack], valid_pool) self.custom_recipes[pack] = new_recipe - if self.world.silo[self.player].value == Silo.option_randomize_recipe \ - or self.world.satellite[self.player].value == Satellite.option_randomize_recipe: + if self.multiworld.silo[self.player].value == Silo.option_randomize_recipe \ + or self.multiworld.satellite[self.player].value == Satellite.option_randomize_recipe: valid_pool = set() - for pack in sorted(self.world.max_science_pack[self.player].get_allowed_packs()): + for pack in sorted(self.multiworld.max_science_pack[self.player].get_allowed_packs()): valid_pool |= science_pack_pools[pack] - if self.world.silo[self.player].value == Silo.option_randomize_recipe: + if self.multiworld.silo[self.player].value == Silo.option_randomize_recipe: new_recipe = self.make_balanced_recipe(recipes["rocket-silo"], valid_pool, - factor=(self.world.max_science_pack[self.player].value + 1) / 7) + factor=(self.multiworld.max_science_pack[self.player].value + 1) / 7) self.custom_recipes["rocket-silo"] = new_recipe - if self.world.satellite[self.player].value == Satellite.option_randomize_recipe: + if self.multiworld.satellite[self.player].value == Satellite.option_randomize_recipe: new_recipe = self.make_balanced_recipe(recipes["satellite"], valid_pool, - factor=(self.world.max_science_pack[self.player].value + 1) / 7) + factor=(self.multiworld.max_science_pack[self.player].value + 1) / 7) self.custom_recipes["satellite"] = new_recipe bridge = "ap-energy-bridge" new_recipe = self.make_quick_recipe( Recipe(bridge, "crafting", {"replace_1": 1, "replace_2": 1, "replace_3": 1}, {bridge: 1}, 10), - sorted(science_pack_pools[self.world.max_science_pack[self.player].get_ordered_science_packs()[0]])) + sorted(science_pack_pools[self.multiworld.max_science_pack[self.player].get_ordered_science_packs()[0]])) for ingredient_name in new_recipe.ingredients: - new_recipe.ingredients[ingredient_name] = self.world.random.randint(10, 100) + new_recipe.ingredients[ingredient_name] = self.multiworld.random.randint(10, 100) self.custom_recipes[bridge] = new_recipe - needed_recipes = self.world.max_science_pack[self.player].get_allowed_packs() | {"rocket-part"} - if self.world.silo[self.player] != Silo.option_spawn: + needed_recipes = self.multiworld.max_science_pack[self.player].get_allowed_packs() | {"rocket-part"} + if self.multiworld.silo[self.player] != Silo.option_spawn: needed_recipes |= {"rocket-silo"} - if self.world.goal[self.player].value == Goal.option_satellite: + if self.multiworld.goal[self.player].value == Goal.option_satellite: needed_recipes |= {"satellite"} for recipe in needed_recipes: @@ -448,10 +448,10 @@ class FactorioScienceLocation(FactorioLocation): self.ingredients = {Factorio.ordered_science_packs[self.complexity]: 1} for complexity in range(self.complexity): - if parent.world.tech_cost_mix[self.player] > parent.world.random.randint(0, 99): + if parent.multiworld.tech_cost_mix[self.player] > parent.multiworld.random.randint(0, 99): self.ingredients[Factorio.ordered_science_packs[complexity]] = 1 - self.count = parent.world.random.randint(parent.world.min_tech_cost[self.player], - parent.world.max_tech_cost[self.player]) + self.count = parent.multiworld.random.randint(parent.multiworld.min_tech_cost[self.player], + parent.multiworld.max_tech_cost[self.player]) @property def factorio_ingredients(self) -> typing.List[typing.Tuple[str, int]]: diff --git a/worlds/ff1/__init__.py b/worlds/ff1/__init__.py index 24b8e708..5eeb3b1b 100644 --- a/worlds/ff1/__init__.py +++ b/worlds/ff1/__init__.py @@ -51,15 +51,15 @@ class FF1World(World): return def create_regions(self): - locations = get_options(self.world, 'locations', self.player) - rules = get_options(self.world, 'rules', self.player) + locations = get_options(self.multiworld, 'locations', self.player) + rules = get_options(self.multiworld, 'rules', self.player) menu_region = self.ff1_locations.create_menu_region(self.player, locations, rules) - menu_region.world = self.world + menu_region.multiworld = self.multiworld terminated_event = Location(self.player, CHAOS_TERMINATED_EVENT, EventId, menu_region) terminated_item = Item(CHAOS_TERMINATED_EVENT, ItemClassification.progression, EventId, self.player) terminated_event.place_locked_item(terminated_item) - items = get_options(self.world, 'items', self.player) + items = get_options(self.multiworld, 'items', self.player) goal_rule = generate_rule([[name for name in items.keys() if name in FF1_PROGRESSION_LIST and name != "Shard"]], self.player) if "Shard" in items.keys(): @@ -71,22 +71,22 @@ class FF1World(World): raise Exception("FFR Noverworld seeds must be generated on an older version of FFR. Please ensure you generated the settings using " "4-4-0.finalfantasyrandomizer.com") menu_region.locations.append(terminated_event) - self.world.regions += [menu_region] + self.multiworld.regions += [menu_region] def create_item(self, name: str) -> Item: return self.ff1_items.generate_item(name, self.player) def set_rules(self): - self.world.completion_condition[self.player] = lambda state: state.has(CHAOS_TERMINATED_EVENT, self.player) + self.multiworld.completion_condition[self.player] = lambda state: state.has(CHAOS_TERMINATED_EVENT, self.player) def generate_basic(self): - items = get_options(self.world, 'items', self.player) + items = get_options(self.multiworld, 'items', self.player) if FF1_BRIDGE in items.keys(): self._place_locked_item_in_sphere0(FF1_BRIDGE) if items: possible_early_items = [name for name in FF1_STARTER_ITEMS if name in items.keys()] if possible_early_items: - progression_item = self.world.random.choice(possible_early_items) + progression_item = self.multiworld.random.choice(possible_early_items) self._place_locked_item_in_sphere0(progression_item) else: # Fail generation if there are no items in the pool @@ -96,16 +96,16 @@ class FF1World(World): items = [self.create_item(name) for name, data in items.items() for x in range(data['count']) if name not in self.locked_items] - self.world.itempool += items + self.multiworld.itempool += items def _place_locked_item_in_sphere0(self, progression_item: str): if progression_item: - rules = get_options(self.world, 'rules', self.player) + rules = get_options(self.multiworld, 'rules', self.player) sphere_0_locations = [name for name, rules in rules.items() if rules and len(rules[0]) == 0 and name not in self.locked_locations] if sphere_0_locations: - initial_location = self.world.random.choice(sphere_0_locations) - locked_location = self.world.get_location(initial_location, self.player) + initial_location = self.multiworld.random.choice(sphere_0_locations) + locked_location = self.multiworld.get_location(initial_location, self.player) locked_location.place_locked_item(self.create_item(progression_item)) self.locked_items.append(progression_item) self.locked_locations.append(locked_location.name) @@ -116,7 +116,7 @@ class FF1World(World): return slot_data def get_filler_item_name(self) -> str: - return self.world.random.choice(["Heal", "Pure", "Soft", "Tent", "Cabin", "House"]) + return self.multiworld.random.choice(["Heal", "Pure", "Soft", "Tent", "Cabin", "House"]) def get_options(world: MultiWorld, name: str, player: int): diff --git a/worlds/generic/Rules.py b/worlds/generic/Rules.py index e69a34c5..865dc395 100644 --- a/worlds/generic/Rules.py +++ b/worlds/generic/Rules.py @@ -151,7 +151,7 @@ def item_in_locations(state: "BaseClasses.CollectionState", item: str, player: i def item_name(state: "BaseClasses.CollectionState", location: str, player: int) -> \ typing.Optional[typing.Tuple[str, int]]: - location = state.world.get_location(location, player) + location = state.multiworld.get_location(location, player) if location.item is None: return None return location.item.name, location.item.player diff --git a/worlds/generic/__init__.py b/worlds/generic/__init__.py index 0d8a220d..4c7c14c4 100644 --- a/worlds/generic/__init__.py +++ b/worlds/generic/__init__.py @@ -44,7 +44,7 @@ class GenericWorld(World): web = GenericWeb() def generate_early(self): - self.world.player_types[self.player] = SlotType.spectator # mark as spectator + self.multiworld.player_types[self.player] = SlotType.spectator # mark as spectator def create_item(self, name: str) -> Item: if name == "Nothing": diff --git a/worlds/hk/Rules.py b/worlds/hk/Rules.py index 50c0572e..4fe4160b 100644 --- a/worlds/hk/Rules.py +++ b/worlds/hk/Rules.py @@ -29,7 +29,7 @@ def hk_set_rule(hk_world: World, location: str, rule): locations = hk_world.created_multi_locations.get(location) if locations is None: try: - locations = [hk_world.world.get_location(location, player)] + locations = [hk_world.multiworld.get_location(location, player)] except KeyError: return @@ -39,7 +39,7 @@ def hk_set_rule(hk_world: World, location: str, rule): def set_rules(hk_world: World): player = hk_world.player - world = hk_world.world + world = hk_world.multiworld set_generated_rules(hk_world, hk_set_rule) # Shop costs diff --git a/worlds/hk/__init__.py b/worlds/hk/__init__.py index 9ed0c929..6a1000b6 100644 --- a/worlds/hk/__init__.py +++ b/worlds/hk/__init__.py @@ -166,7 +166,7 @@ class HKWorld(World): self.vanilla_shop_costs = deepcopy(vanilla_shop_costs) def generate_early(self): - world = self.world + world = self.multiworld charm_costs = world.RandomCharmCosts[self.player].get_costs(world.random) self.charm_costs = world.PlandoCharmCosts[self.player].get_costs(charm_costs) # world.exclude_locations[self.player].value.update(white_palace_locations) @@ -182,22 +182,22 @@ class HKWorld(World): def white_palace_exclusions(self): exclusions = set() - wp = self.world.WhitePalace[self.player] + wp = self.multiworld.WhitePalace[self.player] if wp <= WhitePalace.option_nopathofpain: exclusions.update(path_of_pain_locations) if wp <= WhitePalace.option_kingfragment: exclusions.update(white_palace_checks) if wp == WhitePalace.option_exclude: exclusions.add("King_Fragment") - if self.world.RandomizeCharms[self.player]: + if self.multiworld.RandomizeCharms[self.player]: # If charms are randomized, this will be junk-filled -- so transitions and events are not progression exclusions.update(white_palace_transitions) exclusions.update(white_palace_events) return exclusions def create_regions(self): - menu_region: Region = create_region(self.world, self.player, 'Menu') - self.world.regions.append(menu_region) + menu_region: Region = create_region(self.multiworld, self.player, 'Menu') + self.multiworld.regions.append(menu_region) # wp_exclusions = self.white_palace_exclusions() # Link regions @@ -226,12 +226,12 @@ class HKWorld(World): pool: typing.List[HKItem] = [] wp_exclusions = self.white_palace_exclusions() junk_replace: typing.Set[str] = set() - if self.world.RemoveSpellUpgrades[self.player]: + if self.multiworld.RemoveSpellUpgrades[self.player]: junk_replace.update(("Abyss_Shriek", "Shade_Soul", "Descending_Dark")) randomized_starting_items = set() for attr, items in randomizable_starting_items.items(): - if getattr(self.world, attr)[self.player]: + if getattr(self.multiworld, attr)[self.player]: randomized_starting_items.update(items) # noinspection PyShadowingNames @@ -262,7 +262,7 @@ class HKWorld(World): unfilled_locations += 1 pool.append(item) else: - self.world.push_precollected(item) + self.multiworld.push_precollected(item) return if vanilla: @@ -277,49 +277,49 @@ class HKWorld(World): location.progress_type = LocationProgressType.EXCLUDED for option_key, option in hollow_knight_randomize_options.items(): - randomized = getattr(self.world, option_key)[self.player] + randomized = getattr(self.multiworld, option_key)[self.player] for item_name, location_name in zip(option.items, option.locations): if item_name in junk_replace: item_name = self.get_filler_item_name() - if (item_name == "Crystal_Heart" and self.world.SplitCrystalHeart[self.player]) or \ - (item_name == "Mothwing_Cloak" and self.world.SplitMothwingCloak[self.player]): + if (item_name == "Crystal_Heart" and self.multiworld.SplitCrystalHeart[self.player]) or \ + (item_name == "Mothwing_Cloak" and self.multiworld.SplitMothwingCloak[self.player]): _add("Left_" + item_name, location_name) _add("Right_" + item_name, "Split_" + location_name) continue - if item_name == "Mantis_Claw" and self.world.SplitMantisClaw[self.player]: + if item_name == "Mantis_Claw" and self.multiworld.SplitMantisClaw[self.player]: _add("Left_" + item_name, "Left_" + location_name) _add("Right_" + item_name, "Right_" + location_name) continue - if item_name == "Shade_Cloak" and self.world.SplitMothwingCloak[self.player]: - if self.world.random.randint(0, 1): + if item_name == "Shade_Cloak" and self.multiworld.SplitMothwingCloak[self.player]: + if self.multiworld.random.randint(0, 1): item_name = "Left_Mothwing_Cloak" else: item_name = "Right_Mothwing_Cloak" _add(item_name, location_name) - if self.world.RandomizeElevatorPass[self.player]: + if self.multiworld.RandomizeElevatorPass[self.player]: randomized = True _add("Elevator_Pass", "Elevator_Pass") for shop, locations in self.created_multi_locations.items(): - for _ in range(len(locations), getattr(self.world, shop_to_option[shop])[self.player].value): + for _ in range(len(locations), getattr(self.multiworld, shop_to_option[shop])[self.player].value): loc = self.create_location(shop) unfilled_locations += 1 # Balance the pool item_count = len(pool) - additional_shop_items = max(item_count - unfilled_locations, self.world.ExtraShopSlots[self.player].value) + additional_shop_items = max(item_count - unfilled_locations, self.multiworld.ExtraShopSlots[self.player].value) # Add additional shop items, as needed. if additional_shop_items > 0: shops = list(shop for shop, locations in self.created_multi_locations.items() if len(locations) < 16) - if not self.world.EggShopSlots[self.player].value: # No eggshop, so don't place items there + if not self.multiworld.EggShopSlots[self.player].value: # No eggshop, so don't place items there shops.remove('Egg_Shop') for _ in range(additional_shop_items): - shop = self.world.random.choice(shops) + shop = self.multiworld.random.choice(shops) loc = self.create_location(shop) unfilled_locations += 1 if len(self.created_multi_locations[shop]) >= 16: @@ -330,7 +330,7 @@ class HKWorld(World): # Create filler items, if needed if item_count < unfilled_locations: pool.extend(self.create_item(self.get_filler_item_name()) for _ in range(unfilled_locations - item_count)) - self.world.itempool += pool + self.multiworld.itempool += pool self.apply_costsanity() self.sort_shops_by_cost() @@ -345,24 +345,24 @@ class HKWorld(World): loc.costs = costs def apply_costsanity(self): - setting = self.world.CostSanity[self.player].value + setting = self.multiworld.CostSanity[self.player].value if not setting: return # noop def _compute_weights(weights: dict, desc: str) -> typing.Dict[str, int]: if all(x == 0 for x in weights.values()): logger.warning( - f"All {desc} weights were zero for {self.world.player_name[self.player]}." + f"All {desc} weights were zero for {self.multiworld.player_name[self.player]}." f" Setting them to one instead." ) weights = {k: 1 for k in weights} return {k: v for k, v in weights.items() if v} - random = self.world.random - hybrid_chance = getattr(self.world, f"CostSanityHybridChance")[self.player].value + random = self.multiworld.random + hybrid_chance = getattr(self.multiworld, f"CostSanityHybridChance")[self.player].value weights = { - data.term: getattr(self.world, f"CostSanity{data.option}Weight")[self.player].value + data.term: getattr(self.multiworld, f"CostSanity{data.option}Weight")[self.player].value for data in cost_terms.values() } weights_geoless = dict(weights) @@ -374,16 +374,16 @@ class HKWorld(World): if hybrid_chance > 0: if len(weights) == 1: logger.warning( - f"Only one cost type is available for CostSanity in {self.world.player_name[self.player]}'s world." + f"Only one cost type is available for CostSanity in {self.multiworld.player_name[self.player]}'s world." f" CostSanityHybridChance will not trigger." ) if len(weights_geoless) == 1: logger.warning( - f"Only one cost type is available for CostSanity in {self.world.player_name[self.player]}'s world." + f"Only one cost type is available for CostSanity in {self.multiworld.player_name[self.player]}'s world." f" CostSanityHybridChance will not trigger in geoless locations." ) - for region in self.world.get_regions(self.player): + for region in self.multiworld.get_regions(self.player): for location in region.locations: if location.vanilla: continue @@ -417,7 +417,7 @@ class HKWorld(World): location.sort_costs() def set_rules(self): - world = self.world + world = self.multiworld player = self.player if world.logic[player] != 'nologic': goal = world.Goal[player] @@ -436,7 +436,7 @@ class HKWorld(World): options = slot_data["options"] = {} for option_name in self.option_definitions: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] try: optionvalue = int(option.value) except TypeError: @@ -445,10 +445,10 @@ class HKWorld(World): options[option_name] = optionvalue # 32 bit int - slot_data["seed"] = self.world.slot_seeds[self.player].randint(-2147483647, 2147483646) + slot_data["seed"] = self.multiworld.slot_seeds[self.player].randint(-2147483647, 2147483646) # Backwards compatibility for shop cost data (HKAP < 0.1.0) - if not self.world.CostSanity[self.player]: + if not self.multiworld.CostSanity[self.player]: for shop, terms in shop_cost_types.items(): unit = cost_terms[next(iter(terms))].option if unit == "Geo": @@ -460,7 +460,7 @@ class HKWorld(World): # HKAP 0.1.0 and later cost data. location_costs = {} - for region in self.world.get_regions(self.player): + for region in self.multiworld.get_regions(self.player): for location in region.locations: if location.costs: location_costs[location.name] = location.costs @@ -479,7 +479,7 @@ class HKWorld(World): basename = name if name in shop_cost_types: costs = { - term: self.world.random.randint(*self.ranges[term]) + term: self.multiworld.random.randint(*self.ranges[term]) for term in shop_cost_types[name] } elif name in vanilla_location_costs: @@ -491,7 +491,7 @@ class HKWorld(World): i = len(multi) + 1 name = f"{name}_{i}" - region = self.world.get_region("Menu", self.player) + region = self.multiworld.get_region("Menu", self.player) loc = HKLocation(self.player, name, self.location_name_to_id[name], region, costs=costs, vanilla=vanilla, basename=basename) @@ -577,16 +577,16 @@ class HKWorld(World): 'RandomizeGeoRocks', 'RandomizeSoulTotems', 'RandomizeLoreTablets', 'RandomizeJunkPitChests', 'RandomizeRancidEggs' ): - if getattr(self.world, group): + if getattr(self.multiworld, group): fillers.extend(item for item in hollow_knight_randomize_options[group].items if item not in exclusions) self.cached_filler_items[self.player] = fillers - return self.world.random.choice(self.cached_filler_items[self.player]) + return self.multiworld.random.choice(self.cached_filler_items[self.player]) def create_region(world: MultiWorld, player: int, name: str, location_names=None, exits=None) -> Region: ret = Region(name, RegionType.Generic, name, player) - ret.world = world + ret.multiworld = world if location_names: for location in location_names: loc_id = HKWorld.location_name_to_id.get(location, None) @@ -654,16 +654,16 @@ class HKItem(Item): class HKLogicMixin(LogicMixin): - world: MultiWorld + multiworld: MultiWorld def _hk_notches(self, player: int, *notches: int) -> int: - return sum(self.world.worlds[player].charm_costs[notch] for notch in notches) + return sum(self.multiworld.worlds[player].charm_costs[notch] for notch in notches) def _hk_option(self, player: int, option_name: str) -> int: - return getattr(self.world, option_name)[player].value + return getattr(self.multiworld, option_name)[player].value def _hk_start(self, player, start_location: str) -> bool: - return self.world.StartLocation[player] == start_location + return self.multiworld.StartLocation[player] == start_location def _hk_nail_combat(self, player: int) -> bool: return self.has_any({'LFFTSLASH', 'RIGHTSLASH', 'UPSLASH'}, player) diff --git a/worlds/hylics2/Rules.py b/worlds/hylics2/Rules.py index be38e102..4b804386 100644 --- a/worlds/hylics2/Rules.py +++ b/worlds/hylics2/Rules.py @@ -89,7 +89,7 @@ class Hylics2Logic(LogicMixin): def set_rules(hylics2world): - world = hylics2world.world + world = hylics2world.multiworld player = hylics2world.player # Afterlife diff --git a/worlds/hylics2/__init__.py b/worlds/hylics2/__init__.py index b429eb6a..80c80a0d 100644 --- a/worlds/hylics2/__init__.py +++ b/worlds/hylics2/__init__.py @@ -64,8 +64,8 @@ class Hylics2World(World): # set random starting location if option is enabled def generate_early(self): - if self.world.random_start[self.player]: - i = self.world.random.randint(0, 3) + if self.multiworld.random_start[self.player]: + i = self.multiworld.random.randint(0, 3) if i == 0: self.start_location = "Waynehouse" elif i == 1: @@ -77,12 +77,12 @@ class Hylics2World(World): def generate_basic(self): # create location for beating the game and place Victory event there - loc = Location(self.player, "Defeat Gibby", None, self.world.get_region("Hylemxylem", self.player)) + loc = Location(self.player, "Defeat Gibby", None, self.multiworld.get_region("Hylemxylem", self.player)) loc.place_locked_item(self.create_event("Victory")) set_rule(loc, lambda state: state._hylics2_has_upper_chamber_key(self.player) and state._hylics2_has_vessel_room_key(self.player)) - self.world.get_region("Hylemxylem", self.player).locations.append(loc) - self.world.completion_condition[self.player] = lambda state: state.has("Victory", self.player) + self.multiworld.get_region("Hylemxylem", self.player).locations.append(loc) + self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) # create item pool pool = [] @@ -94,53 +94,53 @@ class Hylics2World(World): pool.append(self.add_item(data["name"], data["classification"], i)) # add party members if option is enabled - if self.world.party_shuffle[self.player]: + if self.multiworld.party_shuffle[self.player]: for i, data in Items.party_item_table.items(): pool.append(self.add_item(data["name"], data["classification"], i)) # handle gesture shuffle options - if self.world.gesture_shuffle[self.player] == 2: # vanilla locations + if self.multiworld.gesture_shuffle[self.player] == 2: # vanilla locations gestures = Items.gesture_item_table - self.world.get_location("Waynehouse: TV", self.player)\ + self.multiworld.get_location("Waynehouse: TV", self.player)\ .place_locked_item(self.add_item(gestures[200678]["name"], gestures[200678]["classification"], 200678)) - self.world.get_location("Afterlife: TV", self.player)\ + self.multiworld.get_location("Afterlife: TV", self.player)\ .place_locked_item(self.add_item(gestures[200683]["name"], gestures[200683]["classification"], 200683)) - self.world.get_location("New Muldul: TV", self.player)\ + self.multiworld.get_location("New Muldul: TV", self.player)\ .place_locked_item(self.add_item(gestures[200679]["name"], gestures[200679]["classification"], 200679)) - self.world.get_location("Viewax's Edifice: TV", self.player)\ + self.multiworld.get_location("Viewax's Edifice: TV", self.player)\ .place_locked_item(self.add_item(gestures[200680]["name"], gestures[200680]["classification"], 200680)) - self.world.get_location("TV Island: TV", self.player)\ + self.multiworld.get_location("TV Island: TV", self.player)\ .place_locked_item(self.add_item(gestures[200681]["name"], gestures[200681]["classification"], 200681)) - self.world.get_location("Juice Ranch: TV", self.player)\ + self.multiworld.get_location("Juice Ranch: TV", self.player)\ .place_locked_item(self.add_item(gestures[200682]["name"], gestures[200682]["classification"], 200682)) - self.world.get_location("Foglast: TV", self.player)\ + self.multiworld.get_location("Foglast: TV", self.player)\ .place_locked_item(self.add_item(gestures[200684]["name"], gestures[200684]["classification"], 200684)) - self.world.get_location("Drill Castle: TV", self.player)\ + self.multiworld.get_location("Drill Castle: TV", self.player)\ .place_locked_item(self.add_item(gestures[200688]["name"], gestures[200688]["classification"], 200688)) - self.world.get_location("Sage Airship: TV", self.player)\ + self.multiworld.get_location("Sage Airship: TV", self.player)\ .place_locked_item(self.add_item(gestures[200685]["name"], gestures[200685]["classification"], 200685)) - elif self.world.gesture_shuffle[self.player] == 1: # TVs only + elif self.multiworld.gesture_shuffle[self.player] == 1: # TVs only gestures = list(Items.gesture_item_table.items()) tvs = list(Locations.tv_location_table.items()) # if Extra Items in Logic is enabled place CHARGE UP first and make sure it doesn't get # placed at Sage Airship: TV - if self.world.extra_items_in_logic[self.player]: - tv = self.world.random.choice(tvs) + if self.multiworld.extra_items_in_logic[self.player]: + tv = self.multiworld.random.choice(tvs) gest = gestures.index((200681, Items.gesture_item_table[200681])) while tv[1]["name"] == "Sage Airship: TV": - tv = self.world.random.choice(tvs) - self.world.get_location(tv[1]["name"], self.player)\ + tv = self.multiworld.random.choice(tvs) + self.multiworld.get_location(tv[1]["name"], self.player)\ .place_locked_item(self.add_item(gestures[gest][1]["name"], gestures[gest][1]["classification"], gestures[gest])) gestures.remove(gestures[gest]) tvs.remove(tv) for i in range(len(gestures)): - gest = self.world.random.choice(gestures) - tv = self.world.random.choice(tvs) - self.world.get_location(tv[1]["name"], self.player)\ + gest = self.multiworld.random.choice(gestures) + tv = self.multiworld.random.choice(tvs) + self.multiworld.get_location(tv[1]["name"], self.player)\ .place_locked_item(self.add_item(gest[1]["name"], gest[1]["classification"], gest[1])) gestures.remove(gest) tvs.remove(tv) @@ -150,22 +150,22 @@ class Hylics2World(World): pool.append(self.add_item(data["name"], data["classification"], i)) # add '10 Bones' items if medallion shuffle is enabled - if self.world.medallion_shuffle[self.player]: + if self.multiworld.medallion_shuffle[self.player]: for i, data in Items.medallion_item_table.items(): for j in range(data["count"]): pool.append(self.add_item(data["name"], data["classification"], i)) # add to world's pool - self.world.itempool += pool + self.multiworld.itempool += pool def fill_slot_data(self) -> Dict[str, Any]: slot_data: Dict[str, Any] = { - "party_shuffle": self.world.party_shuffle[self.player].value, - "medallion_shuffle": self.world.medallion_shuffle[self.player].value, - "random_start" : self.world.random_start[self.player].value, + "party_shuffle": self.multiworld.party_shuffle[self.player].value, + "medallion_shuffle": self.multiworld.medallion_shuffle[self.player].value, + "random_start" : self.multiworld.random_start[self.player].value, "start_location" : self.start_location, - "death_link": self.world.death_link[self.player].value + "death_link": self.multiworld.death_link[self.player].value } return slot_data @@ -173,29 +173,29 @@ class Hylics2World(World): def create_regions(self) -> None: region_table: Dict[int, Region] = { - 0: Region("Menu", RegionType.Generic, "Menu", self.player, self.world), - 1: Region("Afterlife", RegionType.Generic, "Afterlife", self.player, self.world), - 2: Region("Waynehouse", RegionType.Generic, "Waynehouse", self.player, self.world), - 3: Region("World", RegionType.Generic, "World", self.player, self.world), - 4: Region("New Muldul", RegionType.Generic, "New Muldul", self.player, self.world), - 5: Region("New Muldul Vault", RegionType.Generic, "New Muldul Vault", self.player, self.world), - 6: Region("Viewax", RegionType.Generic, "Viewax's Edifice", self.player, self.world), - 7: Region("Airship", RegionType.Generic, "Airship", self.player, self.world), - 8: Region("Arcade Island", RegionType.Generic, "Arcade Island", self.player, self.world), - 9: Region("TV Island", RegionType.Generic, "TV Island", self.player, self.world), - 10: Region("Juice Ranch", RegionType.Generic, "Juice Ranch", self.player, self.world), - 11: Region("Shield Facility", RegionType.Generic, "Shield Facility", self.player, self.world), - 12: Region("Worm Pod", RegionType.Generic, "Worm Pod", self.player, self.world), - 13: Region("Foglast", RegionType.Generic, "Foglast", self.player, self.world), - 14: Region("Drill Castle", RegionType.Generic, "Drill Castle", self.player, self.world), - 15: Region("Sage Labyrinth", RegionType.Generic, "Sage Labyrinth", self.player, self.world), - 16: Region("Sage Airship", RegionType.Generic, "Sage Airship", self.player, self.world), - 17: Region("Hylemxylem", RegionType.Generic, "Hylemxylem", self.player, self.world) + 0: Region("Menu", RegionType.Generic, "Menu", self.player, self.multiworld), + 1: Region("Afterlife", RegionType.Generic, "Afterlife", self.player, self.multiworld), + 2: Region("Waynehouse", RegionType.Generic, "Waynehouse", self.player, self.multiworld), + 3: Region("World", RegionType.Generic, "World", self.player, self.multiworld), + 4: Region("New Muldul", RegionType.Generic, "New Muldul", self.player, self.multiworld), + 5: Region("New Muldul Vault", RegionType.Generic, "New Muldul Vault", self.player, self.multiworld), + 6: Region("Viewax", RegionType.Generic, "Viewax's Edifice", self.player, self.multiworld), + 7: Region("Airship", RegionType.Generic, "Airship", self.player, self.multiworld), + 8: Region("Arcade Island", RegionType.Generic, "Arcade Island", self.player, self.multiworld), + 9: Region("TV Island", RegionType.Generic, "TV Island", self.player, self.multiworld), + 10: Region("Juice Ranch", RegionType.Generic, "Juice Ranch", self.player, self.multiworld), + 11: Region("Shield Facility", RegionType.Generic, "Shield Facility", self.player, self.multiworld), + 12: Region("Worm Pod", RegionType.Generic, "Worm Pod", self.player, self.multiworld), + 13: Region("Foglast", RegionType.Generic, "Foglast", self.player, self.multiworld), + 14: Region("Drill Castle", RegionType.Generic, "Drill Castle", self.player, self.multiworld), + 15: Region("Sage Labyrinth", RegionType.Generic, "Sage Labyrinth", self.player, self.multiworld), + 16: Region("Sage Airship", RegionType.Generic, "Sage Airship", self.player, self.multiworld), + 17: Region("Hylemxylem", RegionType.Generic, "Hylemxylem", self.player, self.multiworld) } # create regions from table for i, reg in region_table.items(): - self.world.regions.append(reg) + self.multiworld.regions.append(reg) # get all exits per region for j, exits in Exits.region_exit_table.items(): if j == i: @@ -203,7 +203,7 @@ class Hylics2World(World): # create entrance and connect it to parent and destination regions ent = Entrance(self.player, k, reg) reg.exits.append(ent) - if k == "New Game" and self.world.random_start[self.player]: + if k == "New Game" and self.multiworld.random_start[self.player]: if self.start_location == "Waynehouse": ent.connect(region_table[2]) elif self.start_location == "Viewax's Edifice": @@ -226,13 +226,13 @@ class Hylics2World(World): .append(Hylics2Location(self.player, data["name"], i, region_table[data["region"]])) # add party member locations if option is enabled - if self.world.party_shuffle[self.player]: + if self.multiworld.party_shuffle[self.player]: for i, data in Locations.party_location_table.items(): region_table[data["region"]].locations\ .append(Hylics2Location(self.player, data["name"], i, region_table[data["region"]])) # add medallion locations if option is enabled - if self.world.medallion_shuffle[self.player]: + if self.multiworld.medallion_shuffle[self.player]: for i, data in Locations.medallion_location_table.items(): region_table[data["region"]].locations\ .append(Hylics2Location(self.player, data["name"], i, region_table[data["region"]])) diff --git a/worlds/meritous/__init__.py b/worlds/meritous/__init__.py index d0d076da..1bf1bfc0 100644 --- a/worlds/meritous/__init__.py +++ b/worlds/meritous/__init__.py @@ -88,7 +88,7 @@ class MeritousWorld(World): return crystal_pool def get_filler_item_name(self) -> str: - rand_crystals = self.world.random.randrange(0, 32) + rand_crystals = self.multiworld.random.randrange(0, 32) if rand_crystals < 16: return "Crystals x500" elif rand_crystals < 28: @@ -97,14 +97,14 @@ class MeritousWorld(World): return "Crystals x2000" def generate_early(self): - self.goal = self.world.goal[self.player].value - self.include_evolution_traps = self.world.include_evolution_traps[self.player].value - self.include_psi_keys = self.world.include_psi_keys[self.player].value - self.item_cache_cost = self.world.item_cache_cost[self.player].value - self.death_link = self.world.death_link[self.player].value + self.goal = self.multiworld.goal[self.player].value + self.include_evolution_traps = self.multiworld.include_evolution_traps[self.player].value + self.include_psi_keys = self.multiworld.include_psi_keys[self.player].value + self.item_cache_cost = self.multiworld.item_cache_cost[self.player].value + self.death_link = self.multiworld.death_link[self.player].value def create_regions(self): - create_regions(self.world, self.player) + create_regions(self.multiworld, self.player) def create_items(self): frequencies = [0, # Nothing [0] @@ -133,22 +133,22 @@ class MeritousWorld(World): if len(item_pool) < location_count: item_pool += self._make_crystals(location_count - len(item_pool)) - self.world.itempool += item_pool + self.multiworld.itempool += item_pool def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def generate_basic(self): - self.world.get_location("Place of Power", self.player).place_locked_item( + self.multiworld.get_location("Place of Power", self.player).place_locked_item( self.create_item("Cursed Seal")) - self.world.get_location("The Last Place You'll Look", self.player).place_locked_item( + self.multiworld.get_location("The Last Place You'll Look", self.player).place_locked_item( self.create_item("Agate Knife")) - self.world.get_location("Wervyn Anixil", self.player).place_locked_item( + self.multiworld.get_location("Wervyn Anixil", self.player).place_locked_item( self.create_event("Victory")) - self.world.get_location("Wervyn Anixil?", self.player).place_locked_item( + self.multiworld.get_location("Wervyn Anixil?", self.player).place_locked_item( self.create_event("Full Victory")) for boss in ["Meridian", "Ataraxia", "Merodach"]: - self.world.get_location(f"{boss} Defeat", self.player).place_locked_item( + self.multiworld.get_location(f"{boss} Defeat", self.player).place_locked_item( self.create_event(f"{boss} Defeated")) if not self.include_psi_keys: @@ -156,22 +156,22 @@ class MeritousWorld(World): psi_key_storage = [] for i in range(0, 3): psi_keys += [self.create_item(f"PSI Key {i + 1}")] - psi_key_storage += [self.world.get_location( + psi_key_storage += [self.multiworld.get_location( f"PSI Key Storage {i + 1}", self.player)] - fill_restrictive(self.world, self.world.get_all_state( + fill_restrictive(self.multiworld, self.multiworld.get_all_state( False), psi_key_storage, psi_keys) if not self.include_evolution_traps: for boss in ["Meridian", "Ataraxia", "Merodach"]: - self.world.get_location(boss, self.player).place_locked_item( + self.multiworld.get_location(boss, self.player).place_locked_item( self.create_item("Evolution Trap")) if self.goal == 0: - self.world.completion_condition[self.player] = lambda state: state.has_any( + self.multiworld.completion_condition[self.player] = lambda state: state.has_any( ["Victory", "Full Victory"], self.player) else: - self.world.completion_condition[self.player] = lambda state: state.has( + self.multiworld.completion_condition[self.player] = lambda state: state.has( "Full Victory", self.player) def fill_slot_data(self) -> dict: diff --git a/worlds/minecraft/Rules.py b/worlds/minecraft/Rules.py index 06576d70..2ec95237 100644 --- a/worlds/minecraft/Rules.py +++ b/worlds/minecraft/Rules.py @@ -45,7 +45,7 @@ class MinecraftLogic(LogicMixin): self.can_reach('Bastion Remnant', 'Region', player)) def _mc_overworld_villager(self, player: int): - village_region = self.world.get_region('Village', player).entrances[0].parent_region.name + village_region = self.multiworld.get_region('Village', player).entrances[0].parent_region.name if village_region == 'The Nether': # 2 options: cure zombie villager or build portal in village return (self.can_reach('Zombie Doctor', 'Location', player) or (self._mc_has_diamond_pickaxe(player) and self.can_reach('Village', 'Region', player))) @@ -58,10 +58,10 @@ class MinecraftLogic(LogicMixin): # Difficulty-dependent functions def _mc_combat_difficulty(self, player: int): - return self.world.combat_difficulty[player].current_key + return self.multiworld.combat_difficulty[player].current_key def _mc_can_adventure(self, player: int): - death_link_check = not self.world.death_link[player] or self.has('Bed', player) + death_link_check = not self.multiworld.death_link[player] or self.has('Bed', player) if self._mc_combat_difficulty(player) == 'easy': return self.has('Progressive Weapons', player, 2) and self._mc_has_iron_ingots(player) and death_link_check elif self._mc_combat_difficulty(player) == 'hard': @@ -112,9 +112,9 @@ class MinecraftLogic(LogicMixin): return self.has('Progressive Weapons', player, 2) and self.has('Progressive Armor', player) and self.has('Archery', player) def _mc_has_structure_compass(self, entrance_name: str, player: int): - if not self.world.structure_compasses[player]: + if not self.multiworld.structure_compasses[player]: return True - return self.has(f"Structure Compass ({self.world.get_entrance(entrance_name, player).connected_region.name})", player) + return self.has(f"Structure Compass ({self.multiworld.get_entrance(entrance_name, player).connected_region.name})", player) # Sets rules on entrances and advancements that are always applied def set_advancement_rules(world: MultiWorld, player: int): diff --git a/worlds/minecraft/__init__.py b/worlds/minecraft/__init__.py index fd5752bd..f94a1159 100644 --- a/worlds/minecraft/__init__.py +++ b/worlds/minecraft/__init__.py @@ -70,21 +70,21 @@ class MinecraftWorld(World): def _get_mc_data(self): exits = [connection[0] for connection in default_connections] return { - 'world_seed': self.world.slot_seeds[self.player].getrandbits(32), - 'seed_name': self.world.seed_name, - 'player_name': self.world.get_player_name(self.player), + 'world_seed': self.multiworld.slot_seeds[self.player].getrandbits(32), + 'seed_name': self.multiworld.seed_name, + 'player_name': self.multiworld.get_player_name(self.player), 'player_id': self.player, 'client_version': client_version, - 'structures': {exit: self.world.get_entrance(exit, self.player).connected_region.name for exit in exits}, - 'advancement_goal': self.world.advancement_goal[self.player].value, - 'egg_shards_required': min(self.world.egg_shards_required[self.player].value, - self.world.egg_shards_available[self.player].value), - 'egg_shards_available': self.world.egg_shards_available[self.player].value, - 'required_bosses': self.world.required_bosses[self.player].current_key, - 'MC35': bool(self.world.send_defeated_mobs[self.player].value), - 'death_link': bool(self.world.death_link[self.player].value), - 'starting_items': str(self.world.starting_items[self.player].value), - 'race': self.world.is_race, + 'structures': {exit: self.multiworld.get_entrance(exit, self.player).connected_region.name for exit in exits}, + 'advancement_goal': self.multiworld.advancement_goal[self.player].value, + 'egg_shards_required': min(self.multiworld.egg_shards_required[self.player].value, + self.multiworld.egg_shards_available[self.player].value), + 'egg_shards_available': self.multiworld.egg_shards_available[self.player].value, + 'required_bosses': self.multiworld.required_bosses[self.player].current_key, + 'MC35': bool(self.multiworld.send_defeated_mobs[self.player].value), + 'death_link': bool(self.multiworld.death_link[self.player].value), + 'starting_items': str(self.multiworld.starting_items[self.player].value), + 'race': self.multiworld.is_race, } def generate_basic(self): @@ -96,18 +96,18 @@ class MinecraftWorld(World): for (name, num) in required_items.items(): itempool += [name] * num # Add structure compasses if desired - if self.world.structure_compasses[self.player]: + if self.multiworld.structure_compasses[self.player]: structures = [connection[1] for connection in default_connections] for struct_name in structures: itempool.append(f"Structure Compass ({struct_name})") # Add dragon egg shards - if self.world.egg_shards_required[self.player] > 0: - itempool += ["Dragon Egg Shard"] * self.world.egg_shards_available[self.player] + if self.multiworld.egg_shards_required[self.player] > 0: + itempool += ["Dragon Egg Shard"] * self.multiworld.egg_shards_available[self.player] # Add bee traps if desired - bee_trap_quantity = ceil(self.world.bee_traps[self.player] * (len(self.location_names)-len(itempool)) * 0.01) + bee_trap_quantity = ceil(self.multiworld.bee_traps[self.player] * (len(self.location_names) - len(itempool)) * 0.01) itempool += ["Bee Trap"] * bee_trap_quantity # Fill remaining items with randomly generated junk - itempool += self.world.random.choices(list(junk_pool.keys()), weights=list(junk_pool.values()), k=len(self.location_names)-len(itempool)) + itempool += self.multiworld.random.choices(list(junk_pool.keys()), weights=list(junk_pool.values()), k=len(self.location_names) - len(itempool)) # Convert itempool into real items itempool = [item for item in map(lambda name: self.create_item(name), itempool)] @@ -115,29 +115,29 @@ class MinecraftWorld(World): exclusion_pool = set() exclusion_types = ['hard', 'unreasonable'] for key in exclusion_types: - if not getattr(self.world, f"include_{key}_advancements")[self.player]: + if not getattr(self.multiworld, f"include_{key}_advancements")[self.player]: exclusion_pool.update(exclusion_table[key]) # For postgame advancements, check with the boss goal - exclusion_pool.update(get_postgame_advancements(self.world.required_bosses[self.player].current_key)) - exclusion_rules(self.world, self.player, exclusion_pool) + exclusion_pool.update(get_postgame_advancements(self.multiworld.required_bosses[self.player].current_key)) + exclusion_rules(self.multiworld, self.player, exclusion_pool) # Prefill event locations with their events - self.world.get_location("Blaze Spawner", self.player).place_locked_item(self.create_item("Blaze Rods")) - self.world.get_location("Ender Dragon", self.player).place_locked_item(self.create_item("Defeat Ender Dragon")) - self.world.get_location("Wither", self.player).place_locked_item(self.create_item("Defeat Wither")) + self.multiworld.get_location("Blaze Spawner", self.player).place_locked_item(self.create_item("Blaze Rods")) + self.multiworld.get_location("Ender Dragon", self.player).place_locked_item(self.create_item("Defeat Ender Dragon")) + self.multiworld.get_location("Wither", self.player).place_locked_item(self.create_item("Defeat Wither")) - self.world.itempool += itempool + self.multiworld.itempool += itempool def get_filler_item_name(self) -> str: - return self.world.random.choices(list(junk_weights.keys()), weights=list(junk_weights.values()))[0] + return self.multiworld.random.choices(list(junk_weights.keys()), weights=list(junk_weights.values()))[0] def set_rules(self): - set_advancement_rules(self.world, self.player) - set_completion_rules(self.world, self.player) + set_advancement_rules(self.multiworld, self.player) + set_completion_rules(self.multiworld, self.player) def create_regions(self): def MCRegion(region_name: str, exits=[]): - ret = Region(region_name, None, region_name, self.player, self.world) + ret = Region(region_name, None, region_name, self.player, self.multiworld) ret.locations = [MinecraftAdvancement(self.player, loc_name, loc_data.id, ret) for loc_name, loc_data in advancement_table.items() if loc_data.region == region_name] @@ -145,19 +145,19 @@ class MinecraftWorld(World): ret.exits.append(Entrance(self.player, exit, ret)) return ret - self.world.regions += [MCRegion(*r) for r in mc_regions] - link_minecraft_structures(self.world, self.player) + self.multiworld.regions += [MCRegion(*r) for r in mc_regions] + link_minecraft_structures(self.multiworld, self.player) def generate_output(self, output_directory: str): data = self._get_mc_data() - filename = f"{self.world.get_out_file_name_base(self.player)}.apmc" + filename = f"AP_{self.multiworld.get_out_file_name_base(self.player)}.apmc" with open(os.path.join(output_directory, filename), 'wb') as f: f.write(b64encode(bytes(json.dumps(data), 'utf-8'))) def fill_slot_data(self): slot_data = self._get_mc_data() for option_name in minecraft_options: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] if slot_data.get(option_name, None) is None and type(option.value) in {str, int}: slot_data[option_name] = int(option.value) return slot_data diff --git a/worlds/oot/Cosmetics.py b/worlds/oot/Cosmetics.py index b91b4606..520641db 100644 --- a/worlds/oot/Cosmetics.py +++ b/worlds/oot/Cosmetics.py @@ -768,7 +768,7 @@ patch_sets = { def patch_cosmetics(ootworld, rom): # Use the world's slot seed for cosmetics - random.seed(ootworld.world.slot_seeds[ootworld.player]) + random.seed(ootworld.multiworld.slot_seeds[ootworld.player]) # try to detect the cosmetic patch data format versioned_patch_set = None diff --git a/worlds/oot/Dungeon.py b/worlds/oot/Dungeon.py index 50285013..98da609f 100644 --- a/worlds/oot/Dungeon.py +++ b/worlds/oot/Dungeon.py @@ -9,7 +9,7 @@ class Dungeon(object): else: return [obj] - self.world = world + self.multiworld = world self.name = name self.hint_text = hint self.font_color = font_color @@ -18,7 +18,7 @@ class Dungeon(object): self.small_keys = to_array(small_keys) self.dungeon_items = to_array(dungeon_items) - for region in world.world.regions: + for region in world.multiworld.regions: if region.player == world.player and region.dungeon == self.name: region.dungeon = self self.regions.append(region) diff --git a/worlds/oot/Entrance.py b/worlds/oot/Entrance.py index 4e11083e..e480c957 100644 --- a/worlds/oot/Entrance.py +++ b/worlds/oot/Entrance.py @@ -7,7 +7,7 @@ class OOTEntrance(Entrance): def __init__(self, player, world, name='', parent=None): super(OOTEntrance, self).__init__(player, name, parent) - self.world = world + self.multiworld = world self.access_rules = [] self.reverse = None self.replaces = None @@ -30,8 +30,8 @@ class OOTEntrance(Entrance): return previously_connected def get_new_target(self): - root = self.world.get_region('Root Exits', self.player) - target_entrance = OOTEntrance(self.player, self.world, 'Root -> ' + self.connected_region.name, root) + root = self.multiworld.get_region('Root Exits', self.player) + target_entrance = OOTEntrance(self.player, self.multiworld, 'Root -> ' + self.connected_region.name, root) target_entrance.connect(self.connected_region) target_entrance.replaces = self root.exits.append(target_entrance) diff --git a/worlds/oot/EntranceShuffle.py b/worlds/oot/EntranceShuffle.py index bd06a3d8..cfe1a5da 100644 --- a/worlds/oot/EntranceShuffle.py +++ b/worlds/oot/EntranceShuffle.py @@ -369,7 +369,7 @@ class EntranceShuffleError(Exception): def shuffle_random_entrances(ootworld): - world = ootworld.world + world = ootworld.multiworld player = ootworld.player # Gather locations to keep reachable for validation @@ -593,7 +593,7 @@ def place_one_way_priority_entrance(ootworld, priority_name, allowed_regions, al all_state, none_state, one_way_entrance_pools, one_way_target_entrance_pools): avail_pool = list(chain.from_iterable(one_way_entrance_pools[t] for t in allowed_types if t in one_way_entrance_pools)) - ootworld.world.random.shuffle(avail_pool) + ootworld.multiworld.random.shuffle(avail_pool) for entrance in avail_pool: if entrance.replaces: @@ -643,11 +643,11 @@ def shuffle_entrance_pool(ootworld, pool_type, entrance_pool, target_entrances, raise EntranceShuffleError(f'Entrance placement attempt count exceeded for world {ootworld.player}') def shuffle_entrances(ootworld, pool_type, entrances, target_entrances, rollbacks, locations_to_ensure_reachable, all_state, none_state): - ootworld.world.random.shuffle(entrances) + ootworld.multiworld.random.shuffle(entrances) for entrance in entrances: if entrance.connected_region != None: continue - ootworld.world.random.shuffle(target_entrances) + ootworld.multiworld.random.shuffle(target_entrances) # Here we deliberately introduce bias by prioritizing certain interiors, i.e. the ones most likely to cause problems. # success rate over randomization if pool_type in {'InteriorSoft', 'MixedSoft'}: @@ -662,7 +662,7 @@ def shuffle_entrances(ootworld, pool_type, entrances, target_entrances, rollback def split_entrances_by_requirements(ootworld, entrances_to_split, assumed_entrances): - world = ootworld.world + world = ootworld.multiworld player = ootworld.player # Disconnect all root assumed entrances and save original connections @@ -704,7 +704,7 @@ def split_entrances_by_requirements(ootworld, entrances_to_split, assumed_entran # TODO: improve this function def validate_world(ootworld, entrance_placed, locations_to_ensure_reachable, all_state_orig, none_state_orig): - world = ootworld.world + world = ootworld.multiworld player = ootworld.player all_state = all_state_orig.copy() @@ -827,7 +827,7 @@ def same_hint_area(first, second): return False def get_entrance_replacing(region, entrance_name, player): - original_entrance = region.world.get_entrance(entrance_name, player) + original_entrance = region.multiworld.get_entrance(entrance_name, player) if not original_entrance.shuffled: return original_entrance @@ -842,14 +842,14 @@ def get_entrance_replacing(region, entrance_name, player): def change_connections(entrance, target): entrance.connect(target.disconnect()) entrance.replaces = target.replaces - if entrance.reverse and not entrance.world.worlds[entrance.player].decouple_entrances: + if entrance.reverse and not entrance.multiworld.worlds[entrance.player].decouple_entrances: target.replaces.reverse.connect(entrance.reverse.assumed.disconnect()) target.replaces.reverse.replaces = entrance.reverse def restore_connections(entrance, target): target.connect(entrance.disconnect()) entrance.replaces = None - if entrance.reverse and not entrance.world.worlds[entrance.player].decouple_entrances: + if entrance.reverse and not entrance.multiworld.worlds[entrance.player].decouple_entrances: entrance.reverse.assumed.connect(target.replaces.reverse.disconnect()) target.replaces.reverse.replaces = None @@ -866,7 +866,7 @@ def check_entrances_compatibility(entrance, target, rollbacks): def confirm_replacement(entrance, target): delete_target_entrance(target) logging.getLogger('').debug(f'Connected {entrance} to {entrance.connected_region}') - if entrance.reverse and not entrance.world.worlds[entrance.player].decouple_entrances: + if entrance.reverse and not entrance.multiworld.worlds[entrance.player].decouple_entrances: replaced_reverse = target.replaces.reverse delete_target_entrance(entrance.reverse.assumed) logging.getLogger('').debug(f'Connected {replaced_reverse} to {replaced_reverse.connected_region}') diff --git a/worlds/oot/Hints.py b/worlds/oot/Hints.py index aaafeb20..3c3f5cc3 100644 --- a/worlds/oot/Hints.py +++ b/worlds/oot/Hints.py @@ -131,13 +131,13 @@ def getItemGenericName(item): def isRestrictedDungeonItem(dungeon, item): if not isinstance(item, OOTItem): return False - if (item.map or item.compass) and dungeon.world.shuffle_mapcompass == 'dungeon': + if (item.map or item.compass) and dungeon.multiworld.shuffle_mapcompass == 'dungeon': return item in dungeon.dungeon_items - if item.type == 'SmallKey' and dungeon.world.shuffle_smallkeys == 'dungeon': + if item.type == 'SmallKey' and dungeon.multiworld.shuffle_smallkeys == 'dungeon': return item in dungeon.small_keys - if item.type == 'BossKey' and dungeon.world.shuffle_bosskeys == 'dungeon': + if item.type == 'BossKey' and dungeon.multiworld.shuffle_bosskeys == 'dungeon': return item in dungeon.boss_key - if item.type == 'GanonBossKey' and dungeon.world.shuffle_ganon_bosskey == 'dungeon': + if item.type == 'GanonBossKey' and dungeon.multiworld.shuffle_ganon_bosskey == 'dungeon': return item in dungeon.boss_key return False @@ -148,7 +148,7 @@ def isRestrictedDungeonItem(dungeon, item): def attach_name(text, hinted_object, world): if hinted_object.player == world.player: return text - return f"{text} for {world.world.get_player_name(hinted_object.player)}" + return f"{text} for {world.multiworld.get_player_name(hinted_object.player)}" def add_hint(world, groups, gossip_text, count, location=None, force_reachable=False): @@ -439,7 +439,7 @@ def get_specific_item_hint(world, checked): itemname = world.named_item_pool.pop(0) if itemname == "Bottle" and world.hint_dist == "bingo": locations = [ - location for location in world.world.get_filled_locations() + location for location in world.multiworld.get_filled_locations() if (is_not_checked(location, checked) and location.name not in world.hint_exclusions and location.item.name in bingoBottlesForHints @@ -448,7 +448,7 @@ def get_specific_item_hint(world, checked): ] else: locations = [ - location for location in world.world.get_filled_locations() + location for location in world.multiworld.get_filled_locations() if (is_not_checked(location, checked) and location.name not in world.hint_exclusions and location.item.name == itemname @@ -489,7 +489,7 @@ def get_random_location_hint(world, checked): and location.name not in world.hint_exclusions and location.name not in world.hint_type_overrides['item'] and location.item.name not in world.item_hint_type_overrides['item'], - world.world.get_filled_locations(world.player))) + world.multiworld.get_filled_locations(world.player))) if not locations: return None @@ -639,13 +639,13 @@ def buildWorldGossipHints(world, checkedLocations=None): world.woth_dungeon = 0 if checkedLocations is None: - checkedLocations = {player: set() for player in world.world.get_all_ids()} + checkedLocations = {player: set() for player in world.multiworld.get_all_ids()} # If Ganondorf hints Light Arrows and is reachable without them, add to checkedLocations to prevent extra hinting # Can only be forced with vanilla bridge or trials if world.bridge != 'vanilla' and world.trials == 0 and world.misc_hints: try: - light_arrow_location = world.world.find_item("Light Arrows", world.player) + light_arrow_location = world.multiworld.find_item("Light Arrows", world.player) checkedLocations[light_arrow_location.player].add(light_arrow_location.name) except StopIteration: # start with them pass @@ -885,7 +885,7 @@ def buildAltarHints(world, messages, include_rewards=True, include_wincons=True) # pulls text string from hintlist for reward after sending the location to hintlist. def buildBossString(reward, color, world): - for location in world.world.get_filled_locations(world.player): + for location in world.multiworld.get_filled_locations(world.player): if location.item.name == reward: item_icon = chr(location.item.special['item_id']) location_text = getHint(location.name, world.clearer_hints).text @@ -956,18 +956,18 @@ def buildGanonText(world, messages): text += "\x05\x42your pocket\x05\x40" else: try: - find_light_arrows = world.world.find_item('Light Arrows', world.player) + find_light_arrows = world.multiworld.find_item('Light Arrows', world.player) text = get_raw_text(getHint('Light Arrow Location', world.clearer_hints).text) location = find_light_arrows location_hint = get_hint_area(location) if world.player != location.player: - text += "\x05\x42%s's\x05\x40 %s" % (world.world.get_player_name(location.player), get_raw_text(location_hint)) + text += "\x05\x42%s's\x05\x40 %s" % (world.multiworld.get_player_name(location.player), get_raw_text(location_hint)) else: location_hint = location_hint.replace('Ganon\'s Castle', 'my castle') text += get_raw_text(location_hint) except StopIteration: text = get_raw_text(getHint('Validation Line', world.clearer_hints).text) - for location in world.world.get_filled_locations(world.player): + for location in world.multiworld.get_filled_locations(world.player): if location.name == 'Ganons Tower Boss Key Chest': text += get_raw_text(getHint(getItemGenericName(location.item), world.clearer_hints).text) break diff --git a/worlds/oot/ItemPool.py b/worlds/oot/ItemPool.py index 12c9c262..e1b9ae7b 100644 --- a/worlds/oot/ItemPool.py +++ b/worlds/oot/ItemPool.py @@ -748,7 +748,7 @@ def replace_max_item(items, item, max): def generate_itempool(ootworld): - world = ootworld.world + world = ootworld.multiworld player = ootworld.player global random random = world.random @@ -1280,32 +1280,32 @@ def get_pool_core(world): if world.free_scarecrow: item = world.create_item('Scarecrow Song') - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) if world.no_epona_race: item = world.create_item('Epona') - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) if world.shuffle_mapcompass == 'remove' or world.shuffle_mapcompass == 'startwith': for item in [item for dungeon in world.dungeons for item in dungeon.dungeon_items]: - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) pool.extend(get_junk_item()) if world.shuffle_smallkeys == 'remove': for item in [item for dungeon in world.dungeons for item in dungeon.small_keys]: - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) pool.extend(get_junk_item()) if world.shuffle_bosskeys == 'remove': for item in [item for dungeon in world.dungeons if dungeon.name != 'Ganons Castle' for item in dungeon.boss_key]: - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) pool.extend(get_junk_item()) if world.shuffle_ganon_bosskey in ['remove', 'triforce']: for item in [item for dungeon in world.dungeons if dungeon.name == 'Ganons Castle' for item in dungeon.boss_key]: - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) pool.extend(get_junk_item()) @@ -1331,7 +1331,7 @@ def get_pool_core(world): # Yes somehow you need 3 keys. This dungeon is bonkers items = [world.create_item('Small Key (Spirit Temple)') for i in range(3)] for item in items: - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) #if not world.dungeon_mq['Fire Temple']: # world.state.collect(ItemFactory('Small Key (Fire Temple)')) @@ -1346,7 +1346,7 @@ def get_pool_core(world): if not world.keysanity and not world.dungeon_mq['Fire Temple']: item = world.create_item('Small Key (Fire Temple)') - world.world.push_precollected(item) + world.multiworld.push_precollected(item) world.remove_from_start_inventory.append(item.name) if world.triforce_hunt: diff --git a/worlds/oot/Messages.py b/worlds/oot/Messages.py index e576b96b..a1a50549 100644 --- a/worlds/oot/Messages.py +++ b/worlds/oot/Messages.py @@ -882,7 +882,7 @@ def make_player_message(text): def update_item_messages(messages, world): new_item_messages = {**ITEM_MESSAGES, **KEYSANITY_MESSAGES} for id, text in new_item_messages.items(): - if len(world.world.worlds) > 1: + if len(world.multiworld.worlds) > 1: update_message_by_id(messages, id, make_player_message(text), 0x23) else: update_message_by_id(messages, id, text, 0x23) @@ -1020,7 +1020,7 @@ def update_warp_song_text(messages, ootworld): } for id, entr in msg_list.items(): - destination = ootworld.world.get_entrance(entr, ootworld.player).connected_region + destination = ootworld.multiworld.get_entrance(entr, ootworld.player).connected_region if destination.pretty_name: destination_name = destination.pretty_name diff --git a/worlds/oot/Patches.py b/worlds/oot/Patches.py index 322d2d83..31e57311 100644 --- a/worlds/oot/Patches.py +++ b/worlds/oot/Patches.py @@ -1326,7 +1326,7 @@ def patch_rom(world, rom): override_table = get_override_table(world) rom.write_bytes(rom.sym('cfg_item_overrides'), get_override_table_bytes(override_table)) rom.write_byte(rom.sym('PLAYER_ID'), min(world.player, 255)) # Write player ID - rom.write_bytes(rom.sym('AP_PLAYER_NAME'), bytearray(world.world.get_player_name(world.player), 'ascii')) + rom.write_bytes(rom.sym('AP_PLAYER_NAME'), bytearray(world.multiworld.get_player_name(world.player), 'ascii')) if world.death_link: rom.write_byte(rom.sym('DEATH_LINK'), 0x01) @@ -1359,7 +1359,7 @@ def patch_rom(world, rom): rom.write_byte(rom.sym('CFG_DAMAGE_MULTIPLYER'), 3) # Patch songs and boss rewards - for location in world.world.get_filled_locations(world.player): + for location in world.multiworld.get_filled_locations(world.player): item = location.item special = item.special if item.game == 'Ocarina of Time' else {} # this shouldn't matter hopefully locationaddress = location.address1 @@ -1686,7 +1686,7 @@ def patch_rom(world, rom): pass elif dungeon in ['Bottom of the Well', 'Ice Cavern']: dungeon_name, boss_name, compass_id, map_id = dungeon_list[dungeon] - if len(world.world.worlds) > 1: + if len(world.multiworld.worlds) > 1: map_message = "\x13\x76\x08\x05\x42\x0F\x05\x40 found the \x05\x41Dungeon Map\x05\x40\x01for %s\x05\x40!\x09" % (dungeon_name) else: map_message = "\x13\x76\x08You found the \x05\x41Dungeon Map\x05\x40\x01for %s\x05\x40!\x01It\'s %s!\x09" % (dungeon_name, "masterful" if world.dungeon_mq[dungeon] else "ordinary") @@ -1696,13 +1696,13 @@ def patch_rom(world, rom): else: dungeon_name, boss_name, compass_id, map_id = dungeon_list[dungeon] dungeon_reward = reward_list[world.get_location(boss_name).item.name] - if len(world.world.worlds) > 1: + if len(world.multiworld.worlds) > 1: compass_message = "\x13\x75\x08\x05\x42\x0F\x05\x40 found the \x05\x41Compass\x05\x40\x01for %s\x05\x40!\x09" % (dungeon_name) else: compass_message = "\x13\x75\x08You found the \x05\x41Compass\x05\x40\x01for %s\x05\x40!\x01It holds the %s!\x09" % (dungeon_name, dungeon_reward) update_message_by_id(messages, compass_id, compass_message) if world.mq_dungeons_random or world.mq_dungeons != 0 and world.mq_dungeons != 12: - if len(world.world.worlds) > 1: + if len(world.multiworld.worlds) > 1: map_message = "\x13\x76\x08\x05\x42\x0F\x05\x40 found the \x05\x41Dungeon Map\x05\x40\x01for %s\x05\x40!\x09" % (dungeon_name) else: map_message = "\x13\x76\x08You found the \x05\x41Dungeon Map\x05\x40\x01for %s\x05\x40!\x01It\'s %s!\x09" % (dungeon_name, "masterful" if world.dungeon_mq[dungeon] else "ordinary") @@ -1730,7 +1730,7 @@ def patch_rom(world, rom): rom.write_int16(0xB6D57E, 0x0003) rom.write_int16(0xB6EC52, 999) tycoon_message = "\x08\x13\x57You got a \x05\x43Tycoon's Wallet\x05\x40!\x01Now you can hold\x01up to \x05\x46999\x05\x40 \x05\x46Rupees\x05\x40." - if len(world.world.worlds) > 1: + if len(world.multiworld.worlds) > 1: tycoon_message = make_player_message(tycoon_message) update_message_by_id(messages, 0x00F8, tycoon_message, 0x23) @@ -1844,7 +1844,7 @@ def write_rom_item(rom, item_id, item): def get_override_table(world): - return list(filter(lambda val: val != None, map(partial(get_override_entry, world), world.world.get_filled_locations(world.player)))) + return list(filter(lambda val: val != None, map(partial(get_override_entry, world), world.multiworld.get_filled_locations(world.player)))) override_struct = struct.Struct('>xBBBHBB') # match override_t in get_items.c @@ -2154,8 +2154,8 @@ def place_shop_items(rom, world, shop_items, messages, locations, init_shop_id=F if location.item.name == 'Ice Trap': split_item_name[0] = create_fake_name(split_item_name[0]) - if len(world.world.worlds) > 1: # OOTWorld.MultiWorld.AutoWorld[] - description_text = '\x08\x05\x41%s %d Rupees\x01%s\x01\x05\x42%s\x05\x40\x01Special deal! ONE LEFT!\x09\x0A\x02' % (split_item_name[0], location.price, split_item_name[1], world.world.get_player_name(location.item.player)) + if len(world.multiworld.worlds) > 1: # OOTWorld.MultiWorld.AutoWorld[] + description_text = '\x08\x05\x41%s %d Rupees\x01%s\x01\x05\x42%s\x05\x40\x01Special deal! ONE LEFT!\x09\x0A\x02' % (split_item_name[0], location.price, split_item_name[1], world.multiworld.get_player_name(location.item.player)) else: description_text = '\x08\x05\x41%s %d Rupees\x01%s\x01\x05\x40Special deal! ONE LEFT!\x01Get it while it lasts!\x09\x0A\x02' % (split_item_name[0], location.price, split_item_name[1]) purchase_text = '\x08%s %d Rupees\x09\x01%s\x01\x1B\x05\x42Buy\x01Don\'t buy\x05\x40\x02' % (split_item_name[0], location.price, split_item_name[1]) @@ -2168,10 +2168,10 @@ def place_shop_items(rom, world, shop_items, messages, locations, init_shop_id=F if location.item.trap: shop_item_name = create_fake_name(shop_item_name) - if len(world.world.worlds) > 1: + if len(world.multiworld.worlds) > 1: shop_item_name = ''.join(filter(lambda char: char in character_table, shop_item_name)) do_line_break = sum(character_table[char] for char in f"{shop_item_name} {location.price} Rupees") > NORMAL_LINE_WIDTH - description_text = '\x08\x05\x41%s%s%d Rupees\x01\x05\x42%s\x05\x40\x01Special deal! ONE LEFT!\x09\x0A\x02' % (shop_item_name, '\x01' if do_line_break else ' ', location.price, world.world.get_player_name(location.item.player)) + description_text = '\x08\x05\x41%s%s%d Rupees\x01\x05\x42%s\x05\x40\x01Special deal! ONE LEFT!\x09\x0A\x02' % (shop_item_name, '\x01' if do_line_break else ' ', location.price, world.multiworld.get_player_name(location.item.player)) else: description_text = '\x08\x05\x41%s %d Rupees\x01\x05\x40Special deal! ONE LEFT!\x01Get it while it lasts!\x09\x0A\x02' % (shop_item_name, location.price) purchase_text = '\x08%s %d Rupees\x09\x01\x01\x1B\x05\x42Buy\x01Don\'t buy\x05\x40\x02' % (shop_item_name, location.price) diff --git a/worlds/oot/RuleParser.py b/worlds/oot/RuleParser.py index 6f972447..e6de2460 100644 --- a/worlds/oot/RuleParser.py +++ b/worlds/oot/RuleParser.py @@ -53,7 +53,7 @@ def isliteral(expr): class Rule_AST_Transformer(ast.NodeTransformer): def __init__(self, world, player): - self.world = world + self.multiworld = world self.player = player self.events = set() # map Region -> rule ast string -> item name @@ -86,9 +86,9 @@ class Rule_AST_Transformer(ast.NodeTransformer): ctx=ast.Load()), args=[ast.Str(escaped_items[node.id]), ast.Constant(self.player)], keywords=[]) - elif node.id in self.world.__dict__: + elif node.id in self.multiworld.__dict__: # Settings are constant - return ast.parse('%r' % self.world.__dict__[node.id], mode='eval').body + return ast.parse('%r' % self.multiworld.__dict__[node.id], mode='eval').body elif node.id in State.__dict__: return self.make_call(node, node.id, [], []) elif node.id in self.kwarg_defaults or node.id in allowed_globals: @@ -137,7 +137,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): if isinstance(count, ast.Name): # Must be a settings constant - count = ast.parse('%r' % self.world.__dict__[count.id], mode='eval').body + count = ast.parse('%r' % self.multiworld.__dict__[count.id], mode='eval').body if iname in escaped_items: iname = escaped_items[iname] @@ -182,7 +182,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): new_args = [] for child in node.args: if isinstance(child, ast.Name): - if child.id in self.world.__dict__: + if child.id in self.multiworld.__dict__: # child = ast.Attribute( # value=ast.Attribute( # value=ast.Name(id='state', ctx=ast.Load()), @@ -190,7 +190,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): # ctx=ast.Load()), # attr=child.id, # ctx=ast.Load()) - child = ast.Constant(getattr(self.world, child.id)) + child = ast.Constant(getattr(self.multiworld, child.id)) elif child.id in rule_aliases: child = self.visit(child) elif child.id in escaped_items: @@ -217,7 +217,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): value=ast.Attribute( value=ast.Attribute( value=ast.Name(id='state', ctx=ast.Load()), - attr='world', + attr='multiworld', ctx=ast.Load()), attr='worlds', ctx=ast.Load()), @@ -242,7 +242,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): # Fast check for json can_use if (len(node.ops) == 1 and isinstance(node.ops[0], ast.Eq) and isinstance(node.left, ast.Name) and isinstance(node.comparators[0], ast.Name) - and node.left.id not in self.world.__dict__ and node.comparators[0].id not in self.world.__dict__): + and node.left.id not in self.multiworld.__dict__ and node.comparators[0].id not in self.multiworld.__dict__): return ast.NameConstant(node.left.id == node.comparators[0].id) node.left = escape_or_string(node.left) @@ -378,7 +378,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): # Requires the target regions have been defined in the world. def create_delayed_rules(self): for region_name, node, subrule_name in self.delayed_rules: - region = self.world.world.get_region(region_name, self.player) + region = self.multiworld.multiworld.get_region(region_name, self.player) event = OOTLocation(self.player, subrule_name, type='Event', parent=region, internal=True) event.show_in_spoiler = False @@ -395,7 +395,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): set_rule(event, access_rule) region.locations.append(event) - self.world.make_event_item(subrule_name, event) + self.multiworld.make_event_item(subrule_name, event) # Safeguard in case this is called multiple times per world self.delayed_rules.clear() @@ -448,7 +448,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): ## Handlers for compile-time optimizations (former State functions) def at_day(self, node): - if self.world.ensure_tod_access: + if self.multiworld.ensure_tod_access: # tod has DAY or (tod == NONE and (ss or find a path from a provider)) # parsing is better than constructing this expression by hand r = self.current_spot if type(self.current_spot) == OOTRegion else self.current_spot.parent_region @@ -456,7 +456,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): return ast.NameConstant(True) def at_dampe_time(self, node): - if self.world.ensure_tod_access: + if self.multiworld.ensure_tod_access: # tod has DAMPE or (tod == NONE and (find a path from a provider)) # parsing is better than constructing this expression by hand r = self.current_spot if type(self.current_spot) == OOTRegion else self.current_spot.parent_region @@ -464,10 +464,10 @@ class Rule_AST_Transformer(ast.NodeTransformer): return ast.NameConstant(True) def at_night(self, node): - if self.current_spot.type == 'GS Token' and self.world.logic_no_night_tokens_without_suns_song: + if self.current_spot.type == 'GS Token' and self.multiworld.logic_no_night_tokens_without_suns_song: # Using visit here to resolve 'can_play' rule return self.visit(ast.parse('can_play(Suns_Song)', mode='eval').body) - if self.world.ensure_tod_access: + if self.multiworld.ensure_tod_access: # tod has DAMPE or (tod == NONE and (ss or find a path from a provider)) # parsing is better than constructing this expression by hand r = self.current_spot if type(self.current_spot) == OOTRegion else self.current_spot.parent_region @@ -501,7 +501,7 @@ class Rule_AST_Transformer(ast.NodeTransformer): return ast.parse(f"state._oot_reach_as_age('{r.name}', 'adult', {self.player})", mode='eval').body def current_spot_starting_age_access(self, node): - return self.current_spot_child_access(node) if self.world.starting_age == 'child' else self.current_spot_adult_access(node) + return self.current_spot_child_access(node) if self.multiworld.starting_age == 'child' else self.current_spot_adult_access(node) def has_bottle(self, node): return ast.parse(f"state._oot_has_bottle({self.player})", mode='eval').body diff --git a/worlds/oot/Rules.py b/worlds/oot/Rules.py index 915aae77..46b8b69c 100644 --- a/worlds/oot/Rules.py +++ b/worlds/oot/Rules.py @@ -26,7 +26,7 @@ class OOTLogic(LogicMixin): # Used for fall damage and other situations where damage is unavoidable def _oot_can_live_dmg(self, player, hearts): - mult = self.world.worlds[player].damage_multiplier + mult = self.multiworld.worlds[player].damage_multiplier if hearts*4 >= 3: return mult != 'ohko' and mult != 'quadruple' else: @@ -39,7 +39,7 @@ class OOTLogic(LogicMixin): def _oot_reach_as_age(self, regionname, age, player): if self.age[player] is None: self.age[player] = age - can_reach = self.world.get_region(regionname, player).can_reach(self) + can_reach = self.multiworld.get_region(regionname, player).can_reach(self) self.age[player] = None return can_reach return self.age[player] == age @@ -52,7 +52,7 @@ class OOTLogic(LogicMixin): } if regionname in name_map[tod]: return True - region = self.world.get_region(regionname, player) + region = self.multiworld.get_region(regionname, player) if region.provides_time == TimeOfDay.ALL or regionname == 'Root': self.day_reachable_regions[player].add(regionname) self.dampe_reachable_regions[player].add(regionname) @@ -82,7 +82,7 @@ class OOTLogic(LogicMixin): rrp = getattr(self, f'{age}_reachable_regions')[player] bc = getattr(self, f'{age}_blocked_connections')[player] queue = deque(getattr(self, f'{age}_blocked_connections')[player]) - start = self.world.get_region('Menu', player) + start = self.multiworld.get_region('Menu', player) # init on first call - this can't be done on construction since the regions don't exist yet if not start in rrp: @@ -110,7 +110,7 @@ class OOTLogic(LogicMixin): def set_rules(ootworld): logger = logging.getLogger('') - world = ootworld.world + world = ootworld.multiworld player = ootworld.player if ootworld.logic_rules != 'no_logic': @@ -213,10 +213,10 @@ def set_shop_rules(ootworld): # The goal is to automatically set item rules based on age requirements in case entrances were shuffled def set_entrances_based_rules(ootworld): - if ootworld.world.accessibility == 'beatable': + if ootworld.multiworld.accessibility == 'beatable': return - all_state = ootworld.world.get_all_state(False) + all_state = ootworld.multiworld.get_all_state(False) for location in filter(lambda location: location.type == 'Shop', ootworld.get_locations()): # If a shop is not reachable as adult, it can't have Goron Tunic or Zora Tunic as child can't buy these diff --git a/worlds/oot/__init__.py b/worlds/oot/__init__.py index c985ea13..2f351506 100644 --- a/worlds/oot/__init__.py +++ b/worlds/oot/__init__.py @@ -118,14 +118,14 @@ class OOTWorld(World): def generate_early(self): # Player name MUST be at most 16 bytes ascii-encoded, otherwise won't write to ROM correctly - if len(bytes(self.world.get_player_name(self.player), 'ascii')) > 16: + if len(bytes(self.multiworld.get_player_name(self.player), 'ascii')) > 16: raise Exception( - f"OoT: Player {self.player}'s name ({self.world.get_player_name(self.player)}) must be ASCII-compatible") + f"OoT: Player {self.player}'s name ({self.multiworld.get_player_name(self.player)}) must be ASCII-compatible") self.parser = Rule_AST_Transformer(self, self.player) for (option_name, option) in oot_options.items(): - result = getattr(self.world, option_name)[self.player] + result = getattr(self.multiworld, option_name)[self.player] if isinstance(result, Range): option_value = int(result) elif isinstance(result, Toggle): @@ -141,7 +141,7 @@ class OOTWorld(World): self.remove_from_start_inventory = [] # some items will be precollected but not in the inventory self.starting_items = Counter() self.starting_songs = False # whether starting_items contains a song - self.file_hash = [self.world.random.randint(0, 31) for i in range(5)] + self.file_hash = [self.multiworld.random.randint(0, 31) for i in range(5)] self.item_name_groups = { "medallions": {"Light Medallion", "Forest Medallion", "Fire Medallion", "Water Medallion", @@ -185,13 +185,13 @@ class OOTWorld(World): # Determine skipped trials in GT # This needs to be done before the logic rules in GT are parsed trial_list = ['Forest', 'Fire', 'Water', 'Spirit', 'Shadow', 'Light'] - chosen_trials = self.world.random.sample(trial_list, self.trials) # chooses a list of trials to NOT skip + chosen_trials = self.multiworld.random.sample(trial_list, self.trials) # chooses a list of trials to NOT skip self.skipped_trials = {trial: (trial not in chosen_trials) for trial in trial_list} # Determine which dungeons are MQ # Possible future plan: allow user to pick which dungeons are MQ if self.logic_rules == 'glitchless': - mq_dungeons = self.world.random.sample(dungeon_table, self.mq_dungeons) + mq_dungeons = self.multiworld.random.sample(dungeon_table, self.mq_dungeons) else: self.mq_dungeons = 0 mq_dungeons = [] @@ -208,8 +208,8 @@ class OOTWorld(World): # No Logic forces all tricks on, prog balancing off and beatable-only elif self.logic_rules == 'no_logic': - self.world.progression_balancing[self.player].value = False - self.world.accessibility[self.player] = self.world.accessibility[self.player].from_text("minimal") + self.multiworld.progression_balancing[self.player].value = False + self.multiworld.accessibility[self.player] = self.multiworld.accessibility[self.player].from_text("minimal") for trick in normalized_name_tricks.values(): setattr(self, trick['name'], True) @@ -310,7 +310,7 @@ class OOTWorld(World): for region in region_json: new_region = OOTRegion(region['region_name'], RegionType.Generic, None, self.player) - new_region.world = self.world + new_region.multiworld = self.multiworld if 'pretty_name' in region: new_region.pretty_name = region['pretty_name'] if 'font_color' in region: @@ -355,19 +355,19 @@ class OOTWorld(World): new_location.show_in_spoiler = False if 'exits' in region: for exit, rule in region['exits'].items(): - new_exit = OOTEntrance(self.player, self.world, '%s -> %s' % (new_region.name, exit), new_region) + new_exit = OOTEntrance(self.player, self.multiworld, '%s -> %s' % (new_region.name, exit), new_region) new_exit.vanilla_connected_region = exit new_exit.rule_string = rule - if self.world.logic_rules != 'none': + if self.multiworld.logic_rules != 'none': self.parser.parse_spot_rule(new_exit) if new_exit.never: logger.debug('Dropping unreachable exit: %s', new_exit.name) else: new_region.exits.append(new_exit) - self.world.regions.append(new_region) + self.multiworld.regions.append(new_region) self.regions.append(new_region) - self.world._recache() + self.multiworld._recache() def set_scrub_prices(self): # Get Deku Scrub Locations @@ -387,7 +387,7 @@ class OOTWorld(World): elif self.shuffle_scrubs == 'random': # this is a random value between 0-99 # average value is ~33 rupees - price = int(self.world.random.betavariate(1, 2) * 99) + price = int(self.multiworld.random.betavariate(1, 2) * 99) # Set price in the dictionary as well as the location. self.scrub_prices[scrub_item] = price @@ -402,14 +402,14 @@ class OOTWorld(World): self.shop_prices = {} for region in self.regions: if self.shopsanity == 'random': - shop_item_count = self.world.random.randint(0, 4) + shop_item_count = self.multiworld.random.randint(0, 4) else: shop_item_count = int(self.shopsanity) for location in region.locations: if location.type == 'Shop': if location.name[-1:] in shop_item_indexes[:shop_item_count]: - self.shop_prices[location.name] = int(self.world.random.betavariate(1.5, 2) * 60) * 5 + self.shop_prices[location.name] = int(self.multiworld.random.betavariate(1.5, 2) * 60) * 5 def fill_bosses(self, bossCount=9): boss_location_names = ( @@ -424,7 +424,7 @@ class OOTWorld(World): 'Links Pocket' ) boss_rewards = [item for item in self.itempool if item.type == 'DungeonReward'] - boss_locations = [self.world.get_location(loc, self.player) for loc in boss_location_names] + boss_locations = [self.multiworld.get_location(loc, self.player) for loc in boss_location_names] placed_prizes = [loc.item.name for loc in boss_locations if loc.item is not None] prizepool = [item for item in boss_rewards if item.name not in placed_prizes] @@ -432,12 +432,12 @@ class OOTWorld(World): while bossCount: bossCount -= 1 - self.world.random.shuffle(prizepool) - self.world.random.shuffle(prize_locs) + self.multiworld.random.shuffle(prizepool) + self.multiworld.random.shuffle(prize_locs) item = prizepool.pop() loc = prize_locs.pop() loc.place_locked_item(item) - self.world.itempool.remove(item) + self.multiworld.itempool.remove(item) def create_item(self, name: str): if name in item_table: @@ -449,7 +449,7 @@ class OOTWorld(World): def make_event_item(self, name, location, item=None): if item is None: item = self.create_item(name) - self.world.push_item(location, item, collect=False) + self.multiworld.push_item(location, item, collect=False) location.locked = True location.event = True if name not in item_table: @@ -463,11 +463,11 @@ class OOTWorld(World): world_type = 'Glitched World' overworld_data_path = data_path(world_type, 'Overworld.json') menu = OOTRegion('Menu', None, None, self.player) - start = OOTEntrance(self.player, self.world, 'New Game', menu) + start = OOTEntrance(self.player, self.multiworld, 'New Game', menu) menu.exits.append(start) - self.world.regions.append(menu) + self.multiworld.regions.append(menu) self.load_regions_from_json(overworld_data_path) - start.connect(self.world.get_region('Root', self.player)) + start.connect(self.multiworld.get_region('Root', self.player)) create_dungeons(self) self.parser.create_delayed_rules() @@ -478,7 +478,7 @@ class OOTWorld(World): # Bind entrances to vanilla for region in self.regions: for exit in region.exits: - exit.connect(self.world.get_region(exit.vanilla_connected_region, self.player)) + exit.connect(self.multiworld.get_region(exit.vanilla_connected_region, self.player)) def create_items(self): # Generate itempool @@ -491,7 +491,7 @@ class OOTWorld(World): junk_pool = get_junk_pool(self) removed_items = [] # Determine starting items - for item in self.world.precollected_items[self.player]: + for item in self.multiworld.precollected_items[self.player]: if item.name in self.remove_from_start_inventory: self.remove_from_start_inventory.remove(item.name) removed_items.append(item.name) @@ -512,7 +512,7 @@ class OOTWorld(World): if self.start_with_rupees: self.starting_items['Rupees'] = 999 - self.world.itempool += self.itempool + self.multiworld.itempool += self.itempool self.remove_from_start_inventory.extend(removed_items) def set_rules(self): @@ -533,7 +533,7 @@ class OOTWorld(World): for entrance in self.get_shuffled_entrances(): if entrance.connected_region is not None: entrance.disconnect() - entrance.connect(self.world.get_region(entrance.vanilla_connected_region, self.player)) + entrance.connect(self.multiworld.get_region(entrance.vanilla_connected_region, self.player)) if entrance.assumed: assumed_entrance = entrance.assumed if assumed_entrance.connected_region is not None: @@ -570,27 +570,27 @@ class OOTWorld(World): # Kill unreachable events that can't be gotten even with all items # Make sure to only kill actual internal events, not in-game "events" - all_state = self.world.get_all_state(False) + all_state = self.multiworld.get_all_state(False) all_locations = self.get_locations() - reachable = self.world.get_reachable_locations(all_state, self.player) + reachable = self.multiworld.get_reachable_locations(all_state, self.player) unreachable = [loc for loc in all_locations if (loc.internal or loc.type == 'Drop') and loc.event and loc.locked and loc not in reachable] for loc in unreachable: loc.parent_region.locations.remove(loc) # Exception: Sell Big Poe is an event which is only reachable if Bottle with Big Poe is in the item pool. # We allow it to be removed only if Bottle with Big Poe is not in the itempool. - bigpoe = self.world.get_location('Sell Big Poe from Market Guard House', self.player) + bigpoe = self.multiworld.get_location('Sell Big Poe from Market Guard House', self.player) if not all_state.has('Bottle with Big Poe', self.player) and bigpoe not in reachable: bigpoe.parent_region.locations.remove(bigpoe) - self.world.clear_location_cache() + self.multiworld.clear_location_cache() # If fast scarecrow then we need to kill the Pierre location as it will be unreachable if self.free_scarecrow: - loc = self.world.get_location("Pierre", self.player) + loc = self.multiworld.get_location("Pierre", self.player) loc.parent_region.locations.remove(loc) # If open zora's domain then we need to kill Deliver Rutos Letter if self.zora_fountain == 'open': - loc = self.world.get_location("Deliver Rutos Letter", self.player) + loc = self.multiworld.get_location("Deliver Rutos Letter", self.player) loc.parent_region.locations.remove(loc) def pre_fill(self): @@ -641,11 +641,11 @@ class OOTWorld(World): if loc.item is None and ( self.shuffle_song_items != 'dungeon' or loc.name not in dungeon_song_locations)] if itempools['dungeon']: # only do this if there's anything to shuffle - dungeon_itempool = [item for item in self.world.itempool if item.player == self.player and item.name in itempools['dungeon']] + dungeon_itempool = [item for item in self.multiworld.itempool if item.player == self.player and item.name in itempools['dungeon']] for item in dungeon_itempool: - self.world.itempool.remove(item) - self.world.random.shuffle(dungeon_locations) - fill_restrictive(self.world, self.world.get_all_state(False), dungeon_locations, + self.multiworld.itempool.remove(item) + self.multiworld.random.shuffle(dungeon_locations) + fill_restrictive(self.multiworld, self.multiworld.get_all_state(False), dungeon_locations, dungeon_itempool, True, True) any_dungeon_locations.extend(dungeon_locations) # adds only the unfilled locations @@ -653,22 +653,22 @@ class OOTWorld(World): if self.shuffle_fortresskeys == 'any_dungeon': itempools['any_dungeon'].add('Small Key (Thieves Hideout)') if itempools['any_dungeon']: - any_dungeon_itempool = [item for item in self.world.itempool if item.player == self.player and item.name in itempools['any_dungeon']] + any_dungeon_itempool = [item for item in self.multiworld.itempool if item.player == self.player and item.name in itempools['any_dungeon']] for item in any_dungeon_itempool: - self.world.itempool.remove(item) + self.multiworld.itempool.remove(item) any_dungeon_itempool.sort(key=lambda item: {'GanonBossKey': 4, 'BossKey': 3, 'SmallKey': 2, 'HideoutSmallKey': 1}.get(item.type, 0)) - self.world.random.shuffle(any_dungeon_locations) - fill_restrictive(self.world, self.world.get_all_state(False), any_dungeon_locations, + self.multiworld.random.shuffle(any_dungeon_locations) + fill_restrictive(self.multiworld, self.multiworld.get_all_state(False), any_dungeon_locations, any_dungeon_itempool, True, True) # If anything is overworld-only, fill into local non-dungeon locations if self.shuffle_fortresskeys == 'overworld': itempools['overworld'].add('Small Key (Thieves Hideout)') if itempools['overworld']: - overworld_itempool = [item for item in self.world.itempool if item.player == self.player and item.name in itempools['overworld']] + overworld_itempool = [item for item in self.multiworld.itempool if item.player == self.player and item.name in itempools['overworld']] for item in overworld_itempool: - self.world.itempool.remove(item) + self.multiworld.itempool.remove(item) overworld_itempool.sort(key=lambda item: {'GanonBossKey': 4, 'BossKey': 3, 'SmallKey': 2, 'HideoutSmallKey': 1}.get(item.type, 0)) non_dungeon_locations = [loc for loc in self.get_locations() if @@ -676,8 +676,8 @@ class OOTWorld(World): (loc.type != 'Shop' or loc.name in self.shop_prices) and (loc.type != 'Song' or self.shuffle_song_items != 'song') and (loc.name not in dungeon_song_locations or self.shuffle_song_items != 'dungeon')] - self.world.random.shuffle(non_dungeon_locations) - fill_restrictive(self.world, self.world.get_all_state(False), non_dungeon_locations, + self.multiworld.random.shuffle(non_dungeon_locations) + fill_restrictive(self.multiworld, self.multiworld.get_all_state(False), non_dungeon_locations, overworld_itempool, True, True) # Place songs @@ -686,16 +686,16 @@ class OOTWorld(World): tries = 5 if self.shuffle_song_items == 'song': song_locations = list(filter(lambda location: location.type == 'Song', - self.world.get_unfilled_locations(player=self.player))) + self.multiworld.get_unfilled_locations(player=self.player))) elif self.shuffle_song_items == 'dungeon': song_locations = list(filter(lambda location: location.name in dungeon_song_locations, - self.world.get_unfilled_locations(player=self.player))) + self.multiworld.get_unfilled_locations(player=self.player))) else: raise Exception(f"Unknown song shuffle type: {self.shuffle_song_items}") - songs = list(filter(lambda item: item.player == self.player and item.type == 'Song', self.world.itempool)) + songs = list(filter(lambda item: item.player == self.player and item.type == 'Song', self.multiworld.itempool)) for song in songs: - self.world.itempool.remove(song) + self.multiworld.itempool.remove(song) important_warps = (self.shuffle_special_interior_entrances or self.shuffle_overworld_entrances or self.warp_songs or self.spawn_positions) @@ -717,8 +717,8 @@ class OOTWorld(World): while tries: try: - self.world.random.shuffle(song_locations) - fill_restrictive(self.world, self.world.get_all_state(False), song_locations[:], songs[:], + self.multiworld.random.shuffle(song_locations) + fill_restrictive(self.multiworld, self.multiworld.get_all_state(False), song_locations[:], songs[:], True, True) logger.debug(f"Successfully placed songs for player {self.player} after {6 - tries} attempt(s)") except FillError as e: @@ -741,33 +741,33 @@ class OOTWorld(World): # fast fill will fail because there is some logic on the shop items. we'll gather them up and place the shop items if self.shopsanity != 'off': shop_items = list( - filter(lambda item: item.player == self.player and item.type == 'Shop', self.world.itempool)) + filter(lambda item: item.player == self.player and item.type == 'Shop', self.multiworld.itempool)) shop_locations = list( filter(lambda location: location.type == 'Shop' and location.name not in self.shop_prices, - self.world.get_unfilled_locations(player=self.player))) + self.multiworld.get_unfilled_locations(player=self.player))) shop_items.sort(key=lambda item: { 'Buy Deku Shield': 3 * int(self.open_forest == 'closed'), 'Buy Goron Tunic': 2, 'Buy Zora Tunic': 2 }.get(item.name, int(item.advancement))) # place Deku Shields if needed, then tunics, then other advancement, then junk - self.world.random.shuffle(shop_locations) + self.multiworld.random.shuffle(shop_locations) for item in shop_items: - self.world.itempool.remove(item) - fill_restrictive(self.world, self.world.get_all_state(False), shop_locations, shop_items, True, True) + self.multiworld.itempool.remove(item) + fill_restrictive(self.multiworld, self.multiworld.get_all_state(False), shop_locations, shop_items, True, True) set_shop_rules(self) # sets wallet requirements on shop items, must be done after they are filled # If skip child zelda is active and Song from Impa is unfilled, put a local giveable item into it. - impa = self.world.get_location("Song from Impa", self.player) + impa = self.multiworld.get_location("Song from Impa", self.player) if self.skip_child_zelda: if impa.item is None: - item_to_place = self.world.random.choice(list(item for item in self.world.itempool if - item.player == self.player and item.name in SaveContext.giveable_items)) + item_to_place = self.multiworld.random.choice(list(item for item in self.multiworld.itempool if + item.player == self.player and item.name in SaveContext.giveable_items)) impa.place_locked_item(item_to_place) - self.world.itempool.remove(item_to_place) + self.multiworld.itempool.remove(item_to_place) # Give items to startinventory - self.world.push_precollected(impa.item) - self.world.push_precollected(self.create_item("Zeldas Letter")) + self.multiworld.push_precollected(impa.item) + self.multiworld.push_precollected(self.create_item("Zeldas Letter")) # Exclude locations in Ganon's Castle proportional to the number of items required to make the bridge # Check for dungeon ER later @@ -789,8 +789,8 @@ class OOTWorld(World): gc = next(filter(lambda dungeon: dungeon.name == 'Ganons Castle', self.dungeons)) locations = [loc.name for region in gc.regions for loc in region.locations if loc.item is None] - junk_fill_locations = self.world.random.sample(locations, round(len(locations) * ganon_junk_fill)) - exclusion_rules(self.world, self.player, junk_fill_locations) + junk_fill_locations = self.multiworld.random.sample(locations, round(len(locations) * ganon_junk_fill)) + exclusion_rules(self.multiworld, self.player, junk_fill_locations) # Locations which are not sendable must be converted to events # This includes all locations for which show_in_spoiler is false, and shuffled shop items. @@ -813,12 +813,12 @@ class OOTWorld(World): trap_location_ids = [loc.address for loc in self.get_locations() if loc.item.trap] self.trap_appearances = {} for loc_id in trap_location_ids: - self.trap_appearances[loc_id] = self.create_item(self.world.slot_seeds[self.player].choice(self.fake_items).name) + self.trap_appearances[loc_id] = self.create_item(self.multiworld.slot_seeds[self.player].choice(self.fake_items).name) # Seed hint RNG, used for ganon text lines also - self.hint_rng = self.world.slot_seeds[self.player] + self.hint_rng = self.multiworld.slot_seeds[self.player] - outfile_name = self.world.get_out_file_name_base(self.player) + outfile_name = self.multiworld.get_out_file_name_base(self.player) rom = Rom(file=get_options()['oot_options']['rom_file']) if self.hints != 'none': buildWorldGossipHints(self) @@ -841,17 +841,17 @@ class OOTWorld(World): else: entrance = loadzone.reverse if entrance.reverse is not None: - self.world.spoiler.set_entrance(entrance, entrance.replaces.reverse, 'both', self.player) + self.multiworld.spoiler.set_entrance(entrance, entrance.replaces.reverse, 'both', self.player) else: - self.world.spoiler.set_entrance(entrance, entrance.replaces, 'entrance', self.player) + self.multiworld.spoiler.set_entrance(entrance, entrance.replaces, 'entrance', self.player) else: reverse = loadzone.replaces.reverse if reverse in all_entrances: all_entrances.remove(reverse) - self.world.spoiler.set_entrance(loadzone, reverse, 'both', self.player) + self.multiworld.spoiler.set_entrance(loadzone, reverse, 'both', self.player) else: for entrance in all_entrances: - self.world.spoiler.set_entrance(entrance, entrance.replaces, 'entrance', self.player) + self.multiworld.spoiler.set_entrance(entrance, entrance.replaces, 'entrance', self.player) # Gathers hint data for OoT. Loops over all world locations for woth, barren, and major item locations. @classmethod @@ -979,9 +979,9 @@ class OOTWorld(World): # Helper functions def get_shufflable_entrances(self, type=None, only_primary=False): - return [entrance for entrance in self.world.get_entrances() if (entrance.player == self.player and - (type == None or entrance.type == type) and - (not only_primary or entrance.primary))] + return [entrance for entrance in self.multiworld.get_entrances() if (entrance.player == self.player and + (type == None or entrance.type == type) and + (not only_primary or entrance.primary))] def get_shuffled_entrances(self, type=None, only_primary=False): return [entrance for entrance in self.get_shufflable_entrances(type=type, only_primary=only_primary) if @@ -993,13 +993,13 @@ class OOTWorld(World): yield loc def get_location(self, location): - return self.world.get_location(location, self.player) + return self.multiworld.get_location(location, self.player) def get_region(self, region): - return self.world.get_region(region, self.player) + return self.multiworld.get_region(region, self.player) def get_entrance(self, entrance): - return self.world.get_entrance(entrance, self.player) + return self.multiworld.get_entrance(entrance, self.player) def is_major_item(self, item: OOTItem): if item.type == 'Token': @@ -1030,7 +1030,7 @@ class OOTWorld(World): # Specifically ensures that only real items are gotten, not any events. # In particular, ensures that Time Travel needs to be found. def get_state_with_complete_itempool(self): - all_state = self.world.get_all_state(use_cache=False) + all_state = self.multiworld.get_all_state(use_cache=False) # Remove event progression items for item, player in all_state.prog_items: if player == self.player and (item not in item_table or (item_table[item][2] is None and item_table[item][0] != 'DungeonReward')): diff --git a/worlds/oribf/Rules.py b/worlds/oribf/Rules.py index fdf8a54d..dea4d05c 100644 --- a/worlds/oribf/Rules.py +++ b/worlds/oribf/Rules.py @@ -6,9 +6,9 @@ from BaseClasses import Location # TODO: implement Mapstone counting, Open, OpenWorld, connection rules def set_rules(world): - temp_base_rule(world.world, world.player) + temp_base_rule(world.multiworld, world.player) for logicset in world.logic_sets: - apply_or_ruleset(world.world, world.player, logicset) + apply_or_ruleset(world.multiworld, world.player, logicset) def tautology(state): diff --git a/worlds/oribf/__init__.py b/worlds/oribf/__init__.py index 45e666ef..485efdf6 100644 --- a/worlds/oribf/__init__.py +++ b/worlds/oribf/__init__.py @@ -24,17 +24,17 @@ class OriBlindForest(World): def generate_early(self): logic_sets = {"casual-core"} for logic_set in location_rules: - if logic_set != "casual-core" and getattr(self.world, logic_set.replace("-", "_")): + if logic_set != "casual-core" and getattr(self.multiworld, logic_set.replace("-", "_")): logic_sets.add(logic_set) self.logic_sets = logic_sets set_rules = set_rules def create_region(self, name: str): - return Region(name, RegionType.Generic, name, self.player, self.world) + return Region(name, RegionType.Generic, name, self.player, self.multiworld) def create_regions(self): - world = self.world + world = self.multiworld menu = self.create_region("Menu") world.regions.append(menu) start = Entrance(self.player, "Start Game", menu) @@ -62,7 +62,7 @@ class OriBlindForest(World): def generate_basic(self): for item_name, count in default_pool.items(): - self.world.itempool.extend([self.create_item(item_name) for _ in range(count)]) + self.multiworld.itempool.extend([self.create_item(item_name) for _ in range(count)]) def create_item(self, name: str) -> Item: return Item(name, diff --git a/worlds/overcooked2/Overcooked2Levels.py b/worlds/overcooked2/Overcooked2Levels.py index aac9ea0c..720ab66b 100644 --- a/worlds/overcooked2/Overcooked2Levels.py +++ b/worlds/overcooked2/Overcooked2Levels.py @@ -159,7 +159,7 @@ class Overcooked2Level: sublevel: int def __init__(self): - self.world = Overcooked2GameWorld.ONE + self.multiworld = Overcooked2GameWorld.ONE self.sublevel = 0 def __iter__(self): @@ -167,21 +167,21 @@ class Overcooked2Level: def __next__(self): self.sublevel += 1 - if self.sublevel > self.world.sublevel_count: - if self.world == Overcooked2GameWorld.KEVIN: + if self.sublevel > self.multiworld.sublevel_count: + if self.multiworld == Overcooked2GameWorld.KEVIN: raise StopIteration - self.world = Overcooked2GameWorld(self.world.value + 1) + self.multiworld = Overcooked2GameWorld(self.multiworld.value + 1) self.sublevel = 1 return self @property def level_id(self) -> int: - return self.world.base_id + (self.sublevel - 1) + return self.multiworld.base_id + (self.sublevel - 1) @property def level_name(self) -> str: - return self.world.as_str + "-" + str(self.sublevel) + return self.multiworld.as_str + "-" + str(self.sublevel) @property def location_name_item(self) -> str: diff --git a/worlds/overcooked2/__init__.py b/worlds/overcooked2/__init__.py index c47b755f..6f1e1281 100644 --- a/worlds/overcooked2/__init__.py +++ b/worlds/overcooked2/__init__.py @@ -79,7 +79,7 @@ class Overcooked2World(World): def place_event(self, location_name: str, item_name: str, classification: ItemClassification = ItemClassification.progression_skip_balancing): - location: Location = self.world.get_location(location_name, self.player) + location: Location = self.multiworld.get_location(location_name, self.player) location.place_locked_item(self.create_event(item_name, classification)) def add_region(self, region_name: str): @@ -88,13 +88,13 @@ class Overcooked2World(World): RegionType.Generic, region_name, self.player, - self.world, + self.multiworld, ) - self.world.regions.append(region) + self.multiworld.regions.append(region) def connect_regions(self, source: str, target: str, rule: Optional[Callable[[CollectionState], bool]] = None): - sourceRegion = self.world.get_region(source, self.player) - targetRegion = self.world.get_region(target, self.player) + sourceRegion = self.multiworld.get_region(source, self.player) + targetRegion = self.multiworld.get_region(target, self.player) connection = Entrance(self.player, '', sourceRegion) if rule: @@ -117,7 +117,7 @@ class Overcooked2World(World): else: location_id = level_id - region = self.world.get_region(region_name, self.player) + region = self.multiworld.get_region(region_name, self.player) location = Overcooked2Location( self.player, location_name, @@ -145,8 +145,8 @@ class Overcooked2World(World): ) def get_options(self) -> Dict[str, Any]: - return OC2Options({option.__name__: getattr(self.world, name)[self.player].result - if issubclass(option, OC2OnToggle) else getattr(self.world, name)[self.player].value + return OC2Options({option.__name__: getattr(self.multiworld, name)[self.player].result + if issubclass(option, OC2OnToggle) else getattr(self.multiworld, name)[self.player].value for name, option in overcooked_options.items()}) # Helper Data @@ -170,7 +170,7 @@ class Overcooked2World(World): if self.options["ShuffleLevelOrder"]: self.level_mapping = \ level_shuffle_factory( - self.world.random, + self.multiworld.random, self.options["PrepLevels"] != PrepLevelMode.excluded.value, self.options["IncludeHordeLevels"], ) @@ -246,7 +246,7 @@ class Overcooked2World(World): completion_condition: Callable[[CollectionState], bool] = lambda state: \ state.has("Victory", self.player) - self.world.completion_condition[self.player] = completion_condition + self.multiworld.completion_condition[self.player] = completion_condition def create_items(self): self.itempool = [] @@ -298,7 +298,7 @@ class Overcooked2World(World): while len(self.itempool) < pool_count: self.itempool.append(self.create_item("Bonus Star", ItemClassification.useful)) - self.world.itempool += self.itempool + self.multiworld.itempool += self.itempool def set_rules(self): pass @@ -324,7 +324,7 @@ class Overcooked2World(World): # Items get distributed to locations def fill_json_data(self) -> Dict[str, Any]: - mod_name = f"AP-{self.world.seed_name}-P{self.player}-{self.world.player_name[self.player]}" + mod_name = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.multiworld.player_name[self.player]}" # Serialize Level Order story_level_order = dict() @@ -363,7 +363,7 @@ class Overcooked2World(World): # Set Kevin Unlock Requirements if self.options["KevinLevels"]: def kevin_level_to_keyholder_level_id(level_id: int) -> Optional[int]: - location = self.world.find_item(f"Kevin-{level_id-36}", self.player) + location = self.multiworld.find_item(f"Kevin-{level_id-36}", self.player) if location.player != self.player: return None # This kevin level will be unlocked by the server at runtime level_id = oc2_location_name_to_id[location.name] @@ -376,7 +376,7 @@ class Overcooked2World(World): # Place Items at Level Completion Screens (local only) on_level_completed: Dict[str, list[Dict[str, str]]] = dict() - regions = self.world.get_regions(self.player) + regions = self.multiworld.get_regions(self.player) for region in regions: for location in region.locations: if location.item is None: diff --git a/worlds/pokemon_rb/__init__.py b/worlds/pokemon_rb/__init__.py index 4c37db84..2f65f301 100644 --- a/worlds/pokemon_rb/__init__.py +++ b/worlds/pokemon_rb/__init__.py @@ -73,22 +73,22 @@ class PokemonRedBlueWorld(World): def encode_name(name, t): try: if len(encode_text(name)) > 7: - raise IndexError(f"{t} name too long for player {self.world.player_name[self.player]}. Must be 7 characters or fewer.") + raise IndexError(f"{t} name too long for player {self.multiworld.player_name[self.player]}. Must be 7 characters or fewer.") return encode_text(name, length=8, whitespace="@", safety=True) except KeyError as e: - raise KeyError(f"Invalid character(s) in {t} name for player {self.world.player_name[self.player]}") from e - self.trainer_name = encode_name(self.world.trainer_name[self.player].value, "Player") - self.rival_name = encode_name(self.world.rival_name[self.player].value, "Rival") + raise KeyError(f"Invalid character(s) in {t} name for player {self.multiworld.player_name[self.player]}") from e + self.trainer_name = encode_name(self.multiworld.trainer_name[self.player].value, "Player") + self.rival_name = encode_name(self.multiworld.rival_name[self.player].value, "Rival") - if self.world.badges_needed_for_hm_moves[self.player].value >= 2: + if self.multiworld.badges_needed_for_hm_moves[self.player].value >= 2: badges_to_add = ["Marsh Badge", "Volcano Badge", "Earth Badge"] - if self.world.badges_needed_for_hm_moves[self.player].value == 3: + if self.multiworld.badges_needed_for_hm_moves[self.player].value == 3: badges = ["Boulder Badge", "Cascade Badge", "Thunder Badge", "Rainbow Badge", "Marsh Badge", "Soul Badge", "Volcano Badge", "Earth Badge"] - self.world.random.shuffle(badges) + self.multiworld.random.shuffle(badges) badges_to_add += [badges.pop(), badges.pop()] hm_moves = ["Cut", "Fly", "Surf", "Strength", "Flash"] - self.world.random.shuffle(hm_moves) + self.multiworld.random.shuffle(hm_moves) self.extra_badges = {} for badge in badges_to_add: self.extra_badges[hm_moves.pop()] = badge @@ -99,21 +99,21 @@ class PokemonRedBlueWorld(World): locations = [location for location in location_data if location.type == "Item"] item_pool = [] for location in locations: - if "Hidden" in location.name and not self.world.randomize_hidden_items[self.player].value: + if "Hidden" in location.name and not self.multiworld.randomize_hidden_items[self.player].value: continue - if "Rock Tunnel B1F" in location.region and not self.world.extra_key_items[self.player].value: + if "Rock Tunnel B1F" in location.region and not self.multiworld.extra_key_items[self.player].value: continue - if location.name == "Celadon City - Mansion Lady" and not self.world.tea[self.player].value: + if location.name == "Celadon City - Mansion Lady" and not self.multiworld.tea[self.player].value: continue item = self.create_item(location.original_item) if location.event: - self.world.get_location(location.name, self.player).place_locked_item(item) - elif ("Badge" not in item.name or self.world.badgesanity[self.player].value) and \ - (item.name != "Oak's Parcel" or self.world.old_man[self.player].value != 1): + self.multiworld.get_location(location.name, self.player).place_locked_item(item) + elif ("Badge" not in item.name or self.multiworld.badgesanity[self.player].value) and \ + (item.name != "Oak's Parcel" or self.multiworld.old_man[self.player].value != 1): item_pool.append(item) - self.world.random.shuffle(item_pool) + self.multiworld.random.shuffle(item_pool) - self.world.itempool += item_pool + self.multiworld.itempool += item_pool def pre_fill(self): @@ -121,17 +121,17 @@ class PokemonRedBlueWorld(World): process_wild_pokemon(self) process_static_pokemon(self) - if self.world.old_man[self.player].value == 1: + if self.multiworld.old_man[self.player].value == 1: item = self.create_item("Oak's Parcel") locations = [] - for location in self.world.get_locations(): - if location.player == self.player and location.item is None and location.can_reach(self.world.state) \ + for location in self.multiworld.get_locations(): + if location.player == self.player and location.item is None and location.can_reach(self.multiworld.state) \ and location.item_rule(item): locations.append(location) - self.world.random.choice(locations).place_locked_item(item) + self.multiworld.random.choice(locations).place_locked_item(item) - if not self.world.badgesanity[self.player].value: - self.world.non_local_items[self.player].value -= self.item_name_groups["Badges"] + if not self.multiworld.badgesanity[self.player].value: + self.multiworld.non_local_items[self.player].value -= self.item_name_groups["Badges"] for i in range(5): try: badges = [] @@ -142,11 +142,11 @@ class PokemonRedBlueWorld(World): for loc in ["Pewter Gym - Brock 1", "Cerulean Gym - Misty 1", "Vermilion Gym - Lt. Surge 1", "Celadon Gym - Erika 1", "Fuchsia Gym - Koga 1", "Saffron Gym - Sabrina 1", "Cinnabar Gym - Blaine 1", "Viridian Gym - Giovanni 1"]: - badgelocs.append(self.world.get_location(loc, self.player)) - state = self.world.get_all_state(False) - self.world.random.shuffle(badges) - self.world.random.shuffle(badgelocs) - fill_restrictive(self.world, state, badgelocs.copy(), badges, True, True) + badgelocs.append(self.multiworld.get_location(loc, self.player)) + state = self.multiworld.get_all_state(False) + self.multiworld.random.shuffle(badges) + self.multiworld.random.shuffle(badgelocs) + fill_restrictive(self.multiworld, state, badgelocs.copy(), badges, True, True) except FillError: for location in badgelocs: location.item = None @@ -155,36 +155,36 @@ class PokemonRedBlueWorld(World): else: raise FillError(f"Failed to place badges for player {self.player}") - locs = [self.world.get_location("Fossil - Choice A", self.player), - self.world.get_location("Fossil - Choice B", self.player)] + locs = [self.multiworld.get_location("Fossil - Choice A", self.player), + self.multiworld.get_location("Fossil - Choice B", self.player)] for loc in locs: add_item_rule(loc, lambda i: i.advancement or i.name in self.item_name_groups["Unique"] or i.name == "Master Ball") - loc = self.world.get_location("Pallet Town - Player's PC", self.player) + loc = self.multiworld.get_location("Pallet Town - Player's PC", self.player) if loc.item is None: locs.append(loc) for loc in locs: unplaced_items = [] - if loc.name in self.world.priority_locations[self.player].value: + if loc.name in self.multiworld.priority_locations[self.player].value: add_item_rule(loc, lambda i: i.advancement) - for item in self.world.itempool: + for item in self.multiworld.itempool: if item.player == self.player and loc.item_rule(item): - self.world.itempool.remove(item) - state = sweep_from_pool(self.world.state, self.world.itempool + unplaced_items) + self.multiworld.itempool.remove(item) + state = sweep_from_pool(self.multiworld.state, self.multiworld.itempool + unplaced_items) if state.can_reach(loc, "Location", self.player): loc.place_locked_item(item) break else: unplaced_items.append(item) - self.world.itempool += unplaced_items + self.multiworld.itempool += unplaced_items intervene = False - test_state = self.world.get_all_state(False) + test_state = self.multiworld.get_all_state(False) if not test_state.pokemon_rb_can_surf(self.player) or not test_state.pokemon_rb_can_strength(self.player): intervene = True - elif self.world.accessibility[self.player].current_key != "minimal": + elif self.multiworld.accessibility[self.player].current_key != "minimal": if not test_state.pokemon_rb_can_cut(self.player) or not test_state.pokemon_rb_can_flash(self.player): intervene = True if intervene: @@ -192,12 +192,12 @@ class PokemonRedBlueWorld(World): # let you choose the exact weights for HM compatibility logging.warning( f"HM-compatible Pokémon possibly missing, placing Mew on Route 1 for player {self.player}") - loc = self.world.get_location("Route 1 - Wild Pokemon - 1", self.player) + loc = self.multiworld.get_location("Route 1 - Wild Pokemon - 1", self.player) loc.item = self.create_item("Mew") def create_regions(self): - if self.world.free_fly_location[self.player].value: - fly_map_code = self.world.random.randint(5, 9) + if self.multiworld.free_fly_location[self.player].value: + fly_map_code = self.multiworld.random.randint(5, 9) if fly_map_code == 9: fly_map_code = 10 if fly_map_code == 5: @@ -208,11 +208,11 @@ class PokemonRedBlueWorld(World): "Vermilion City", "Celadon City", "Fuchsia City", "Cinnabar Island", "Indigo Plateau", "Saffron City"][fly_map_code] self.fly_map_code = fly_map_code - create_regions(self.world, self.player) - self.world.completion_condition[self.player] = lambda state, player=self.player: state.has("Become Champion", player=player) + create_regions(self.multiworld, self.player) + self.multiworld.completion_condition[self.player] = lambda state, player=self.player: state.has("Become Champion", player=player) def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def create_item(self, name: str) -> Item: return PokemonRBItem(name, self.player) @@ -221,21 +221,21 @@ class PokemonRedBlueWorld(World): generate_output(self, output_directory) def write_spoiler_header(self, spoiler_handle: TextIO): - if self.world.free_fly_location[self.player].value: + if self.multiworld.free_fly_location[self.player].value: spoiler_handle.write('Fly unlocks: %s\n' % self.fly_map) if self.extra_badges: for hm_move, badge in self.extra_badges.items(): spoiler_handle.write(hm_move + " enabled by: " + (" " * 20)[:20 - len(hm_move)] + badge + "\n") def write_spoiler(self, spoiler_handle): - if self.world.randomize_type_matchup_types[self.player].value or \ - self.world.randomize_type_matchup_type_effectiveness[self.player].value: - spoiler_handle.write(f"\n\nType matchups ({self.world.player_name[self.player]}):\n\n") + if self.multiworld.randomize_type_matchup_types[self.player].value or \ + self.multiworld.randomize_type_matchup_type_effectiveness[self.player].value: + spoiler_handle.write(f"\n\nType matchups ({self.multiworld.player_name[self.player]}):\n\n") for matchup in self.type_chart: spoiler_handle.write(f"{matchup[0]} deals {matchup[2] * 10}% damage to {matchup[1]}\n") def get_filler_item_name(self) -> str: - return self.world.random.choice([item for item in item_table if item_table[item].classification in + return self.multiworld.random.choice([item for item in item_table if item_table[item].classification in [ItemClassification.filler, ItemClassification.trap]]) diff --git a/worlds/pokemon_rb/logic.py b/worlds/pokemon_rb/logic.py index 3b1a3594..8b60bd8b 100644 --- a/worlds/pokemon_rb/logic.py +++ b/worlds/pokemon_rb/logic.py @@ -6,39 +6,39 @@ class PokemonLogic(LogicMixin): def pokemon_rb_can_surf(self, player): return (((self.has("HM03 Surf", player) and self.can_learn_hm("10000", player)) or self.has("Flippers", player)) and (self.has("Soul Badge", player) or - self.has(self.world.worlds[player].extra_badges.get("Surf"), player) - or self.world.badges_needed_for_hm_moves[player].value == 0)) + self.has(self.multiworld.worlds[player].extra_badges.get("Surf"), player) + or self.multiworld.badges_needed_for_hm_moves[player].value == 0)) def pokemon_rb_can_cut(self, player): return ((self.has("HM01 Cut", player) and self.can_learn_hm("100", player) or self.has("Master Sword", player)) and (self.has("Cascade Badge", player) or - self.has(self.world.worlds[player].extra_badges.get("Cut"), player) or - self.world.badges_needed_for_hm_moves[player].value == 0)) + self.has(self.multiworld.worlds[player].extra_badges.get("Cut"), player) or + self.multiworld.badges_needed_for_hm_moves[player].value == 0)) def pokemon_rb_can_fly(self, player): return (((self.has("HM02 Fly", player) and self.can_learn_hm("1000", player)) or self.has("Flute", player)) and - (self.has("Thunder Badge", player) or self.has(self.world.worlds[player].extra_badges.get("Fly"), player) - or self.world.badges_needed_for_hm_moves[player].value == 0)) + (self.has("Thunder Badge", player) or self.has(self.multiworld.worlds[player].extra_badges.get("Fly"), player) + or self.multiworld.badges_needed_for_hm_moves[player].value == 0)) def pokemon_rb_can_strength(self, player): return ((self.has("HM04 Strength", player) and self.can_learn_hm("100000", player)) or self.has("Titan's Mitt", player)) and (self.has("Rainbow Badge", player) or - self.has(self.world.worlds[player].extra_badges.get("Strength"), player) - or self.world.badges_needed_for_hm_moves[player].value == 0) + self.has(self.multiworld.worlds[player].extra_badges.get("Strength"), player) + or self.multiworld.badges_needed_for_hm_moves[player].value == 0) def pokemon_rb_can_flash(self, player): return (((self.has("HM05 Flash", player) and self.can_learn_hm("1000000", player)) or self.has("Lamp", player)) - and (self.has("Boulder Badge", player) or self.has(self.world.worlds[player].extra_badges.get("Flash"), - player) or self.world.badges_needed_for_hm_moves[player].value == 0)) + and (self.has("Boulder Badge", player) or self.has(self.multiworld.worlds[player].extra_badges.get("Flash"), + player) or self.multiworld.badges_needed_for_hm_moves[player].value == 0)) def can_learn_hm(self, move, player): - for pokemon, data in self.world.worlds[player].local_poke_data.items(): + for pokemon, data in self.multiworld.worlds[player].local_poke_data.items(): if self.has(pokemon, player) and data["tms"][6] & int(move, 2): return True return False def pokemon_rb_can_get_hidden_items(self, player): - return self.has("Item Finder", player) or not self.world.require_item_finder[player].value + return self.has("Item Finder", player) or not self.multiworld.require_item_finder[player].value def pokemon_rb_cerulean_cave(self, count, player): return len([item for item in @@ -49,7 +49,7 @@ class PokemonLogic(LogicMixin): "HM04 Strength", "HM05 Flash"] if self.has(item, player)]) >= count def pokemon_rb_can_pass_guards(self, player): - if self.world.tea[player].value: + if self.multiworld.tea[player].value: return self.has("Tea", player) else: # this could just be "True", but you never know what weird options I might introduce later ;) diff --git a/worlds/pokemon_rb/regions.py b/worlds/pokemon_rb/regions.py index 1650e640..1b537904 100644 --- a/worlds/pokemon_rb/regions.py +++ b/worlds/pokemon_rb/regions.py @@ -150,15 +150,15 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "Menu", "Anywhere", one_way=True) connect(world, player, "Menu", "Pallet Town", one_way=True) connect(world, player, "Menu", "Fossil", lambda state: state.pokemon_rb_fossil_checks( - state.world.second_fossil_check_condition[player].value, player), one_way=True) + state.multiworld.second_fossil_check_condition[player].value, player), one_way=True) connect(world, player, "Pallet Town", "Route 1") connect(world, player, "Route 1", "Viridian City") connect(world, player, "Viridian City", "Route 22") connect(world, player, "Route 22", "Route 23 South", - lambda state: state.pokemon_rb_has_badges(state.world.victory_road_condition[player].value, player)) + lambda state: state.pokemon_rb_has_badges(state.multiworld.victory_road_condition[player].value, player)) connect(world, player, "Route 23 South", "Route 23 North", lambda state: state.pokemon_rb_can_surf(player)) connect(world, player, "Viridian City North", "Viridian Gym", lambda state: - state.pokemon_rb_has_badges(state.world.viridian_gym_condition[player].value, player), one_way=True) + state.pokemon_rb_has_badges(state.multiworld.viridian_gym_condition[player].value, player), one_way=True) connect(world, player, "Route 2", "Route 2 East", lambda state: state.pokemon_rb_can_cut(player)) connect(world, player, "Route 2 East", "Diglett's Cave", lambda state: state.pokemon_rb_can_cut(player)) connect(world, player, "Route 2", "Viridian City North") @@ -178,7 +178,7 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "Route 9", "Route 10 North") connect(world, player, "Route 10 North", "Rock Tunnel 1F", lambda state: state.pokemon_rb_can_flash(player)) connect(world, player, "Route 10 North", "Power Plant", lambda state: state.pokemon_rb_can_surf(player) and - (state.has("Plant Key", player) or not state.world.extra_key_items[player].value), one_way=True) + (state.has("Plant Key", player) or not state.multiworld.extra_key_items[player].value), one_way=True) connect(world, player, "Rock Tunnel 1F", "Route 10 South", lambda state: state.pokemon_rb_can_flash(player)) connect(world, player, "Rock Tunnel 1F", "Rock Tunnel B1F") connect(world, player, "Lavender Town", "Pokemon Tower 1F", one_way=True) @@ -205,7 +205,7 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "S.S. Anne 1F", "S.S. Anne B1F", one_way=True) connect(world, player, "Vermilion City", "Route 11") connect(world, player, "Vermilion City", "Diglett's Cave") - connect(world, player, "Route 12 West", "Route 11 East", lambda state: state.pokemon_rb_can_strength(player) or not state.world.extra_strength_boulders[player].value) + connect(world, player, "Route 12 West", "Route 11 East", lambda state: state.pokemon_rb_can_strength(player) or not state.multiworld.extra_strength_boulders[player].value) connect(world, player, "Route 12 North", "Route 12 South", lambda state: state.has("Poke Flute", player) or state.pokemon_rb_can_surf( player)) connect(world, player, "Route 12 West", "Route 12 North", lambda state: state.has("Poke Flute", player)) connect(world, player, "Route 12 West", "Route 12 South", lambda state: state.has("Poke Flute", player)) @@ -227,25 +227,25 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "Fuchsia City", "Fuchsia Gym", one_way=True) connect(world, player, "Fuchsia City", "Route 18") connect(world, player, "Fuchsia City", "Safari Zone Gate", one_way=True) - connect(world, player, "Safari Zone Gate", "Safari Zone Center", lambda state: state.has("Safari Pass", player) or not state.world.extra_key_items[player].value, one_way=True) + connect(world, player, "Safari Zone Gate", "Safari Zone Center", lambda state: state.has("Safari Pass", player) or not state.multiworld.extra_key_items[player].value, one_way=True) connect(world, player, "Safari Zone Center", "Safari Zone East", one_way=True) connect(world, player, "Safari Zone Center", "Safari Zone West", one_way=True) connect(world, player, "Safari Zone Center", "Safari Zone North", one_way=True) connect(world, player, "Fuchsia City", "Route 15") connect(world, player, "Route 15", "Route 14") connect(world, player, "Route 14", "Route 13") - connect(world, player, "Route 13", "Route 12 South", lambda state: state.pokemon_rb_can_strength(player) or state.pokemon_rb_can_surf(player) or not state.world.extra_strength_boulders[player].value) + connect(world, player, "Route 13", "Route 12 South", lambda state: state.pokemon_rb_can_strength(player) or state.pokemon_rb_can_surf(player) or not state.multiworld.extra_strength_boulders[player].value) connect(world, player, "Fuchsia City", "Route 19", lambda state: state.pokemon_rb_can_surf(player)) connect(world, player, "Route 20 East", "Route 19") connect(world, player, "Route 20 West", "Cinnabar Island", lambda state: state.pokemon_rb_can_surf(player)) connect(world, player, "Route 20 West", "Seafoam Islands 1F") connect(world, player, "Route 20 East", "Seafoam Islands 1F", one_way=True) connect(world, player, "Seafoam Islands 1F", "Route 20 East", lambda state: state.pokemon_rb_can_strength(player), one_way=True) - connect(world, player, "Viridian City", "Viridian City North", lambda state: state.has("Oak's Parcel", player) or state.world.old_man[player].value == 2 or state.pokemon_rb_can_cut(player)) + connect(world, player, "Viridian City", "Viridian City North", lambda state: state.has("Oak's Parcel", player) or state.multiworld.old_man[player].value == 2 or state.pokemon_rb_can_cut(player)) connect(world, player, "Route 3", "Mt Moon 1F", one_way=True) connect(world, player, "Route 11", "Route 11 East", lambda state: state.pokemon_rb_can_strength(player)) connect(world, player, "Cinnabar Island", "Cinnabar Gym", lambda state: state.has("Secret Key", player), one_way=True) - connect(world, player, "Cinnabar Island", "Pokemon Mansion 1F", lambda state: state.has("Mansion Key", player) or not state.world.extra_key_items[player].value, one_way=True) + connect(world, player, "Cinnabar Island", "Pokemon Mansion 1F", lambda state: state.has("Mansion Key", player) or not state.multiworld.extra_key_items[player].value, one_way=True) connect(world, player, "Seafoam Islands 1F", "Seafoam Islands B1F", one_way=True) connect(world, player, "Seafoam Islands B1F", "Seafoam Islands B2F", one_way=True) connect(world, player, "Seafoam Islands B2F", "Seafoam Islands B3F", one_way=True) @@ -263,7 +263,7 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "Silph Co 8F", "Silph Co 9F", one_way=True) connect(world, player, "Silph Co 9F", "Silph Co 10F", one_way=True) connect(world, player, "Silph Co 10F", "Silph Co 11F", one_way=True) - connect(world, player, "Celadon City", "Rocket Hideout B1F", lambda state: state.has("Hideout Key", player) or not state.world.extra_key_items[player].value, one_way=True) + connect(world, player, "Celadon City", "Rocket Hideout B1F", lambda state: state.has("Hideout Key", player) or not state.multiworld.extra_key_items[player].value, one_way=True) connect(world, player, "Rocket Hideout B1F", "Rocket Hideout B2F", one_way=True) connect(world, player, "Rocket Hideout B2F", "Rocket Hideout B3F", one_way=True) connect(world, player, "Rocket Hideout B3F", "Rocket Hideout B4F", one_way=True) @@ -273,9 +273,9 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "Route 23 North", "Victory Road 1F", lambda state: state.pokemon_rb_can_strength(player), one_way=True) connect(world, player, "Victory Road 1F", "Victory Road 2F", one_way=True) connect(world, player, "Victory Road 2F", "Victory Road 3F", one_way=True) - connect(world, player, "Victory Road 2F", "Indigo Plateau", lambda state: state.pokemon_rb_has_badges(state.world.elite_four_condition[player], player), one_way=True) + connect(world, player, "Victory Road 2F", "Indigo Plateau", lambda state: state.pokemon_rb_has_badges(state.multiworld.elite_four_condition[player], player), one_way=True) connect(world, player, "Cerulean City", "Cerulean Cave 1F", lambda state: - state.pokemon_rb_cerulean_cave(state.world.cerulean_cave_condition[player].value + (state.world.extra_key_items[player].value * 4), player) and + state.pokemon_rb_cerulean_cave(state.multiworld.cerulean_cave_condition[player].value + (state.multiworld.extra_key_items[player].value * 4), player) and state.pokemon_rb_can_surf(player), one_way=True) connect(world, player, "Cerulean Cave 1F", "Cerulean Cave 2F", one_way=True) connect(world, player, "Cerulean Cave 1F", "Cerulean Cave B1F", lambda state: state.pokemon_rb_can_surf(player), one_way=True) diff --git a/worlds/pokemon_rb/rom.py b/worlds/pokemon_rb/rom.py index 04873873..9e3c567f 100644 --- a/worlds/pokemon_rb/rom.py +++ b/worlds/pokemon_rb/rom.py @@ -43,7 +43,7 @@ def get_encounter_slots(self): for location in encounter_slots: if isinstance(location.original_item, list): - location.original_item = location.original_item[not self.world.game_version[self.player].value] + location.original_item = location.original_item[not self.multiworld.game_version[self.player].value] return encounter_slots @@ -64,19 +64,19 @@ def randomize_pokemon(self, mon, mons_list, randomize_type): if randomize_type == 3: stat_base = get_base_stat_total(mon) type_mons.sort(key=lambda mon: abs(get_base_stat_total(mon) - stat_base)) - mon = type_mons[round(self.world.random.triangular(0, len(type_mons) - 1, 0))] + mon = type_mons[round(self.multiworld.random.triangular(0, len(type_mons) - 1, 0))] if randomize_type == 2: stat_base = get_base_stat_total(mon) mons_list.sort(key=lambda mon: abs(get_base_stat_total(mon) - stat_base)) - mon = mons_list[round(self.world.random.triangular(0, 50, 0))] + mon = mons_list[round(self.multiworld.random.triangular(0, 50, 0))] elif randomize_type == 4: - mon = self.world.random.choice(mons_list) + mon = self.multiworld.random.choice(mons_list) return mon def process_trainer_data(self, data): mons_list = [pokemon for pokemon in poke_data.pokemon_data.keys() if pokemon not in poke_data.legendary_pokemon - or self.world.trainer_legendaries[self.player].value] + or self.multiworld.trainer_legendaries[self.player].value] address = rom_addresses["Trainer_Data"] while address < rom_addresses["Trainer_Data_End"]: if data[address] == 255: @@ -93,14 +93,14 @@ def process_trainer_data(self, data): for i in range(1, 4): for l in ["A", "B", "C", "D", "E", "F", "G", "H"]: if rom_addresses[f"Rival_Starter{i}_{l}"] == address: - mon = " ".join(self.world.get_location(f"Pallet Town - Starter {i}", self.player).item.name.split()[1:]) + mon = " ".join(self.multiworld.get_location(f"Pallet Town - Starter {i}", self.player).item.name.split()[1:]) if l in ["D", "E", "F", "G", "H"] and mon in poke_data.evolves_to: mon = poke_data.evolves_to[mon] if l in ["F", "G", "H"] and mon in poke_data.evolves_to: mon = poke_data.evolves_to[mon] - if mon is None and self.world.randomize_trainer_parties[self.player].value: + if mon is None and self.multiworld.randomize_trainer_parties[self.player].value: mon = poke_data.id_to_mon[data[address]] - mon = randomize_pokemon(self, mon, mons_list, self.world.randomize_trainer_parties[self.player].value) + mon = randomize_pokemon(self, mon, mons_list, self.multiworld.randomize_trainer_parties[self.player].value) if mon is not None: data[address] = poke_data.pokemon_data[mon]["id"] @@ -114,22 +114,22 @@ def process_static_pokemon(self): tower_6F_mons = set() for i in range(1, 11): - tower_6F_mons.add(self.world.get_location(f"Pokemon Tower 6F - Wild Pokemon - {i}", self.player).item.name) + tower_6F_mons.add(self.multiworld.get_location(f"Pokemon Tower 6F - Wild Pokemon - {i}", self.player).item.name) mons_list = [pokemon for pokemon in poke_data.first_stage_pokemon if pokemon not in poke_data.legendary_pokemon - or self.world.randomize_legendary_pokemon[self.player].value == 3] - if self.world.randomize_legendary_pokemon[self.player].value == 0: + or self.multiworld.randomize_legendary_pokemon[self.player].value == 3] + if self.multiworld.randomize_legendary_pokemon[self.player].value == 0: for slot in legendary_slots: - location = self.world.get_location(slot.name, self.player) + location = self.multiworld.get_location(slot.name, self.player) location.place_locked_item(self.create_item("Missable " + slot.original_item)) - elif self.world.randomize_legendary_pokemon[self.player].value == 1: - self.world.random.shuffle(legendary_mons) + elif self.multiworld.randomize_legendary_pokemon[self.player].value == 1: + self.multiworld.random.shuffle(legendary_mons) for slot in legendary_slots: - location = self.world.get_location(slot.name, self.player) + location = self.multiworld.get_location(slot.name, self.player) location.place_locked_item(self.create_item("Missable " + legendary_mons.pop())) - elif self.world.randomize_legendary_pokemon[self.player].value == 2: + elif self.multiworld.randomize_legendary_pokemon[self.player].value == 2: static_slots = static_slots + legendary_slots - self.world.random.shuffle(static_slots) + self.multiworld.random.shuffle(static_slots) static_slots.sort(key=lambda s: 0 if s.name == "Pokemon Tower 6F - Restless Soul" else 1) while legendary_slots: swap_slot = legendary_slots.pop() @@ -137,15 +137,15 @@ def process_static_pokemon(self): slot_type = slot.type.split()[0] if slot_type == "Legendary": slot_type = "Missable" - location = self.world.get_location(slot.name, self.player) + location = self.multiworld.get_location(slot.name, self.player) location.place_locked_item(self.create_item(slot_type + " " + swap_slot.original_item)) swap_slot.original_item = slot.original_item - elif self.world.randomize_legendary_pokemon[self.player].value == 3: + elif self.multiworld.randomize_legendary_pokemon[self.player].value == 3: static_slots = static_slots + legendary_slots for slot in static_slots: - location = self.world.get_location(slot.name, self.player) - randomize_type = self.world.randomize_static_pokemon[self.player].value + location = self.multiworld.get_location(slot.name, self.player) + randomize_type = self.multiworld.randomize_static_pokemon[self.player].value slot_type = slot.type.split()[0] if slot_type == "Legendary": slot_type = "Missable" @@ -160,8 +160,8 @@ def process_static_pokemon(self): location.place_locked_item(mon) for slot in starter_slots: - location = self.world.get_location(slot.name, self.player) - randomize_type = self.world.randomize_starter_pokemon[self.player].value + location = self.multiworld.get_location(slot.name, self.player) + randomize_type = self.multiworld.randomize_starter_pokemon[self.player].value slot_type = "Missable" if not randomize_type: location.place_locked_item(self.create_item(slot_type + " " + slot.original_item)) @@ -175,21 +175,21 @@ def process_wild_pokemon(self): encounter_slots = get_encounter_slots(self) placed_mons = {pokemon: 0 for pokemon in poke_data.pokemon_data.keys()} - if self.world.randomize_wild_pokemon[self.player].value: + if self.multiworld.randomize_wild_pokemon[self.player].value: mons_list = [pokemon for pokemon in poke_data.pokemon_data.keys() if pokemon not in poke_data.legendary_pokemon - or self.world.randomize_legendary_pokemon[self.player].value == 3] - self.world.random.shuffle(encounter_slots) + or self.multiworld.randomize_legendary_pokemon[self.player].value == 3] + self.multiworld.random.shuffle(encounter_slots) locations = [] for slot in encounter_slots: - mon = randomize_pokemon(self, slot.original_item, mons_list, self.world.randomize_wild_pokemon[self.player].value) + mon = randomize_pokemon(self, slot.original_item, mons_list, self.multiworld.randomize_wild_pokemon[self.player].value) # if static Pokemon are not randomized, we make sure nothing on Pokemon Tower 6F is a Marowak # if static Pokemon are randomized we deal with that during static encounter randomization - while (self.world.randomize_static_pokemon[self.player].value == 0 and mon == "Marowak" + while (self.multiworld.randomize_static_pokemon[self.player].value == 0 and mon == "Marowak" and "Pokemon Tower 6F" in slot.name): # to account for the possibility that only one ground type Pokemon exists, match only stats for this fix mon = randomize_pokemon(self, slot.original_item, mons_list, 2) placed_mons[mon] += 1 - location = self.world.get_location(slot.name, self.player) + location = self.multiworld.get_location(slot.name, self.player) location.item = self.create_item(mon) location.event = True location.locked = True @@ -198,33 +198,33 @@ def process_wild_pokemon(self): mons_to_add = [] remaining_pokemon = [pokemon for pokemon in poke_data.pokemon_data.keys() if placed_mons[pokemon] == 0 and - (pokemon not in poke_data.legendary_pokemon or self.world.randomize_legendary_pokemon[self.player].value == 3)] - if self.world.catch_em_all[self.player].value == 1: + (pokemon not in poke_data.legendary_pokemon or self.multiworld.randomize_legendary_pokemon[self.player].value == 3)] + if self.multiworld.catch_em_all[self.player].value == 1: mons_to_add = [pokemon for pokemon in poke_data.first_stage_pokemon if placed_mons[pokemon] == 0 and - (pokemon not in poke_data.legendary_pokemon or self.world.randomize_legendary_pokemon[self.player].value == 3)] - elif self.world.catch_em_all[self.player].value == 2: + (pokemon not in poke_data.legendary_pokemon or self.multiworld.randomize_legendary_pokemon[self.player].value == 3)] + elif self.multiworld.catch_em_all[self.player].value == 2: mons_to_add = remaining_pokemon.copy() - logic_needed_mons = max(self.world.oaks_aide_rt_2[self.player].value, - self.world.oaks_aide_rt_11[self.player].value, - self.world.oaks_aide_rt_15[self.player].value) - if self.world.accessibility[self.player] == "minimal": + logic_needed_mons = max(self.multiworld.oaks_aide_rt_2[self.player].value, + self.multiworld.oaks_aide_rt_11[self.player].value, + self.multiworld.oaks_aide_rt_15[self.player].value) + if self.multiworld.accessibility[self.player] == "minimal": logic_needed_mons = 0 - self.world.random.shuffle(remaining_pokemon) + self.multiworld.random.shuffle(remaining_pokemon) while (len([pokemon for pokemon in placed_mons if placed_mons[pokemon] > 0]) + len(mons_to_add) < logic_needed_mons): mons_to_add.append(remaining_pokemon.pop()) for mon in mons_to_add: stat_base = get_base_stat_total(mon) candidate_locations = get_encounter_slots(self) - if self.world.randomize_wild_pokemon[self.player].value in [1, 3]: + if self.multiworld.randomize_wild_pokemon[self.player].value in [1, 3]: candidate_locations = [slot for slot in candidate_locations if any([poke_data.pokemon_data[slot.original_item][ "type1"] in [self.local_poke_data[mon]["type1"], self.local_poke_data[mon]["type2"]], poke_data.pokemon_data[slot.original_item]["type2"] in [self.local_poke_data[mon]["type1"], self.local_poke_data[mon]["type2"]]])] if not candidate_locations: candidate_locations = location_data - candidate_locations = [self.world.get_location(location.name, self.player) for location in candidate_locations] + candidate_locations = [self.multiworld.get_location(location.name, self.player) for location in candidate_locations] candidate_locations.sort(key=lambda slot: abs(get_base_stat_total(slot.item.name) - stat_base)) for location in candidate_locations: if placed_mons[location.item.name] > 1 or location.item.name not in poke_data.first_stage_pokemon: @@ -236,7 +236,7 @@ def process_wild_pokemon(self): else: for slot in encounter_slots: - location = self.world.get_location(slot.name, self.player) + location = self.multiworld.get_location(slot.name, self.player) location.item = self.create_item(slot.original_item) location.event = True location.locked = True @@ -250,19 +250,19 @@ def process_pokemon_data(self): learnsets = deepcopy(poke_data.learnsets) for mon, mon_data in local_poke_data.items(): - if self.world.randomize_pokemon_stats[self.player].value == 1: + if self.multiworld.randomize_pokemon_stats[self.player].value == 1: stats = [mon_data["hp"], mon_data["atk"], mon_data["def"], mon_data["spd"], mon_data["spc"]] - self.world.random.shuffle(stats) + self.multiworld.random.shuffle(stats) mon_data["hp"] = stats[0] mon_data["atk"] = stats[1] mon_data["def"] = stats[2] mon_data["spd"] = stats[3] mon_data["spc"] = stats[4] - elif self.world.randomize_pokemon_stats[self.player].value == 2: + elif self.multiworld.randomize_pokemon_stats[self.player].value == 2: old_stats = mon_data["hp"] + mon_data["atk"] + mon_data["def"] + mon_data["spd"] + mon_data["spc"] - 5 stats = [1, 1, 1, 1, 1] while old_stats > 0: - stat = self.world.random.randint(0, 4) + stat = self.multiworld.random.randint(0, 4) if stats[stat] < 255: old_stats -= 1 stats[stat] += 1 @@ -271,30 +271,30 @@ def process_pokemon_data(self): mon_data["def"] = stats[2] mon_data["spd"] = stats[3] mon_data["spc"] = stats[4] - if self.world.randomize_pokemon_types[self.player].value: - if self.world.randomize_pokemon_types[self.player].value == 1 and mon in poke_data.evolves_from: + if self.multiworld.randomize_pokemon_types[self.player].value: + if self.multiworld.randomize_pokemon_types[self.player].value == 1 and mon in poke_data.evolves_from: type1 = local_poke_data[poke_data.evolves_from[mon]]["type1"] type2 = local_poke_data[poke_data.evolves_from[mon]]["type2"] if type1 == type2: - if self.world.secondary_type_chance[self.player].value == -1: + if self.multiworld.secondary_type_chance[self.player].value == -1: if mon_data["type1"] != mon_data["type2"]: while type2 == type1: - type2 = self.world.random.choice(list(poke_data.type_names.values())) - elif self.world.random.randint(1, 100) <= self.world.secondary_type_chance[self.player].value: - type2 = self.world.random.choice(list(poke_data.type_names.values())) + type2 = self.multiworld.random.choice(list(poke_data.type_names.values())) + elif self.multiworld.random.randint(1, 100) <= self.multiworld.secondary_type_chance[self.player].value: + type2 = self.multiworld.random.choice(list(poke_data.type_names.values())) else: - type1 = self.world.random.choice(list(poke_data.type_names.values())) + type1 = self.multiworld.random.choice(list(poke_data.type_names.values())) type2 = type1 - if ((self.world.secondary_type_chance[self.player].value == -1 and mon_data["type1"] - != mon_data["type2"]) or self.world.random.randint(1, 100) - <= self.world.secondary_type_chance[self.player].value): + if ((self.multiworld.secondary_type_chance[self.player].value == -1 and mon_data["type1"] + != mon_data["type2"]) or self.multiworld.random.randint(1, 100) + <= self.multiworld.secondary_type_chance[self.player].value): while type2 == type1: - type2 = self.world.random.choice(list(poke_data.type_names.values())) + type2 = self.multiworld.random.choice(list(poke_data.type_names.values())) mon_data["type1"] = type1 mon_data["type2"] = type2 - if self.world.randomize_pokemon_movesets[self.player].value: - if self.world.randomize_pokemon_movesets[self.player].value == 1: + if self.multiworld.randomize_pokemon_movesets[self.player].value: + if self.multiworld.randomize_pokemon_movesets[self.player].value == 1: if mon_data["type1"] == "Normal" and mon_data["type2"] == "Normal": chances = [[75, "Normal"]] elif mon_data["type1"] == "Normal" or mon_data["type2"] == "Normal": @@ -312,30 +312,30 @@ def process_pokemon_data(self): moves = list(poke_data.moves.keys()) for move in ["No Move"] + poke_data.hm_moves: moves.remove(move) - mon_data["start move 1"] = get_move(moves, chances, self.world.random, True) + mon_data["start move 1"] = get_move(moves, chances, self.multiworld.random, True) for i in range(2, 5): - if mon_data[f"start move {i}"] != "No Move" or self.world.start_with_four_moves[ + if mon_data[f"start move {i}"] != "No Move" or self.multiworld.start_with_four_moves[ self.player].value == 1: - mon_data[f"start move {i}"] = get_move(moves, chances, self.world.random) + mon_data[f"start move {i}"] = get_move(moves, chances, self.multiworld.random) if mon in learnsets: for move_num in range(0, len(learnsets[mon])): - learnsets[mon][move_num] = get_move(moves, chances, self.world.random) - if self.world.randomize_pokemon_catch_rates[self.player].value: - mon_data["catch rate"] = self.world.random.randint(self.world.minimum_catch_rate[self.player], 255) + learnsets[mon][move_num] = get_move(moves, chances, self.multiworld.random) + if self.multiworld.randomize_pokemon_catch_rates[self.player].value: + mon_data["catch rate"] = self.multiworld.random.randint(self.multiworld.minimum_catch_rate[self.player], 255) else: - mon_data["catch rate"] = max(self.world.minimum_catch_rate[self.player], mon_data["catch rate"]) + mon_data["catch rate"] = max(self.multiworld.minimum_catch_rate[self.player], mon_data["catch rate"]) if mon in poke_data.evolves_from.keys() and mon_data["type1"] == local_poke_data[poke_data.evolves_from[mon]]["type1"] and mon_data["type2"] == local_poke_data[poke_data.evolves_from[mon]]["type2"]: mon_data["tms"] = local_poke_data[poke_data.evolves_from[mon]]["tms"] elif mon != "Mew": tms_hms = poke_data.tm_moves + poke_data.hm_moves for flag, tm_move in enumerate(tms_hms): - if (flag < 50 and self.world.tm_compatibility[self.player].value == 1) or (flag >= 50 and self.world.hm_compatibility[self.player].value == 1): + if (flag < 50 and self.multiworld.tm_compatibility[self.player].value == 1) or (flag >= 50 and self.multiworld.hm_compatibility[self.player].value == 1): type_match = poke_data.moves[tm_move]["type"] in [mon_data["type1"], mon_data["type2"]] - bit = int(self.world.random.randint(1, 100) < [[90, 50, 25], [100, 75, 25]][flag >= 50][0 if type_match else 1 if poke_data.moves[tm_move]["type"] == "Normal" else 2]) - elif (flag < 50 and self.world.tm_compatibility[self.player].value == 2) or (flag >= 50 and self.world.hm_compatibility[self.player].value == 2): - bit = [0, 1][self.world.random.randint(0, 1)] - elif (flag < 50 and self.world.tm_compatibility[self.player].value == 3) or (flag >= 50 and self.world.hm_compatibility[self.player].value == 3): + bit = int(self.multiworld.random.randint(1, 100) < [[90, 50, 25], [100, 75, 25]][flag >= 50][0 if type_match else 1 if poke_data.moves[tm_move]["type"] == "Normal" else 2]) + elif (flag < 50 and self.multiworld.tm_compatibility[self.player].value == 2) or (flag >= 50 and self.multiworld.hm_compatibility[self.player].value == 2): + bit = [0, 1][self.multiworld.random.randint(0, 1)] + elif (flag < 50 and self.multiworld.tm_compatibility[self.player].value == 3) or (flag >= 50 and self.multiworld.hm_compatibility[self.player].value == 3): bit = 1 else: continue @@ -350,14 +350,14 @@ def process_pokemon_data(self): def generate_output(self, output_directory: str): - random = self.world.slot_seeds[self.player] - game_version = self.world.game_version[self.player].current_key + random = self.multiworld.slot_seeds[self.player] + game_version = self.multiworld.game_version[self.player].current_key data = bytearray(get_base_rom_bytes(game_version)) basemd5 = hashlib.md5() basemd5.update(data) - for location in self.world.get_locations(): + for location in self.multiworld.get_locations(): if location.player != self.player or location.rom_address is None: continue if location.item and location.item.player == self.player: @@ -377,42 +377,42 @@ def generate_output(self, output_directory: str): data[location.rom_address] = 0x2C # AP Item data[rom_addresses['Fly_Location']] = self.fly_map_code - if self.world.tea[self.player].value: + if self.multiworld.tea[self.player].value: data[rom_addresses["Option_Tea"]] = 1 data[rom_addresses["Guard_Drink_List"]] = 0x54 data[rom_addresses["Guard_Drink_List"] + 1] = 0 data[rom_addresses["Guard_Drink_List"] + 2] = 0 - if self.world.extra_key_items[self.player].value: + if self.multiworld.extra_key_items[self.player].value: data[rom_addresses['Options']] |= 4 - data[rom_addresses["Option_Blind_Trainers"]] = round(self.world.blind_trainers[self.player].value * 2.55) - data[rom_addresses['Option_Cerulean_Cave_Condition']] = self.world.cerulean_cave_condition[self.player].value - data[rom_addresses['Option_Encounter_Minimum_Steps']] = self.world.minimum_steps_between_encounters[self.player].value - data[rom_addresses['Option_Victory_Road_Badges']] = self.world.victory_road_condition[self.player].value - data[rom_addresses['Option_Pokemon_League_Badges']] = self.world.elite_four_condition[self.player].value - data[rom_addresses['Option_Viridian_Gym_Badges']] = self.world.viridian_gym_condition[self.player].value - data[rom_addresses['Option_EXP_Modifier']] = self.world.exp_modifier[self.player].value - if not self.world.require_item_finder[self.player].value: + data[rom_addresses["Option_Blind_Trainers"]] = round(self.multiworld.blind_trainers[self.player].value * 2.55) + data[rom_addresses['Option_Cerulean_Cave_Condition']] = self.multiworld.cerulean_cave_condition[self.player].value + data[rom_addresses['Option_Encounter_Minimum_Steps']] = self.multiworld.minimum_steps_between_encounters[self.player].value + data[rom_addresses['Option_Victory_Road_Badges']] = self.multiworld.victory_road_condition[self.player].value + data[rom_addresses['Option_Pokemon_League_Badges']] = self.multiworld.elite_four_condition[self.player].value + data[rom_addresses['Option_Viridian_Gym_Badges']] = self.multiworld.viridian_gym_condition[self.player].value + data[rom_addresses['Option_EXP_Modifier']] = self.multiworld.exp_modifier[self.player].value + if not self.multiworld.require_item_finder[self.player].value: data[rom_addresses['Option_Itemfinder']] = 0 - if self.world.extra_strength_boulders[self.player].value: + if self.multiworld.extra_strength_boulders[self.player].value: for i in range(0, 3): data[rom_addresses['Option_Boulders'] + (i * 3)] = 0x15 - if self.world.extra_key_items[self.player].value: + if self.multiworld.extra_key_items[self.player].value: for i in range(0, 4): data[rom_addresses['Option_Rock_Tunnel_Extra_Items'] + (i * 3)] = 0x15 - if self.world.old_man[self.player].value == 2: + if self.multiworld.old_man[self.player].value == 2: data[rom_addresses['Option_Old_Man']] = 0x11 data[rom_addresses['Option_Old_Man_Lying']] = 0x15 - money = str(self.world.starting_money[self.player].value) + money = str(self.multiworld.starting_money[self.player].value) while len(money) < 6: money = "0" + money data[rom_addresses["Starting_Money_High"]] = int(money[:2], 16) data[rom_addresses["Starting_Money_Middle"]] = int(money[2:4], 16) data[rom_addresses["Starting_Money_Low"]] = int(money[4:], 16) data[rom_addresses["Text_Badges_Needed"]] = encode_text( - str(max(self.world.victory_road_condition[self.player].value, - self.world.elite_four_condition[self.player].value)))[0] - if self.world.badges_needed_for_hm_moves[self.player].value == 0: + str(max(self.multiworld.victory_road_condition[self.player].value, + self.multiworld.elite_four_condition[self.player].value)))[0] + if self.multiworld.badges_needed_for_hm_moves[self.player].value == 0: for hm_move in poke_data.hm_moves: write_bytes(data, bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), rom_addresses["HM_" + hm_move + "_Badge_a"]) @@ -437,7 +437,7 @@ def generate_output(self, output_directory: str): write_bytes(data, encode_text("Nothing"), rom_addresses["Badge_Text_" + badge.replace(" ", "_")]) chart = deepcopy(poke_data.type_chart) - if self.world.randomize_type_matchup_types[self.player].value == 1: + if self.multiworld.randomize_type_matchup_types[self.player].value == 1: attacking_types = [] defending_types = [] for matchup in chart: @@ -458,7 +458,7 @@ def generate_output(self, output_directory: str): for matchup, chart_row in zip(matchups, chart): chart_row[0] = matchup[0] chart_row[1] = matchup[1] - elif self.world.randomize_type_matchup_types[self.player].value == 2: + elif self.multiworld.randomize_type_matchup_types[self.player].value == 2: used_matchups = [] for matchup in chart: matchup[0] = random.choice(list(poke_data.type_names.values())) @@ -467,17 +467,17 @@ def generate_output(self, output_directory: str): matchup[0] = random.choice(list(poke_data.type_names.values())) matchup[1] = random.choice(list(poke_data.type_names.values())) used_matchups.append([matchup[0], matchup[1]]) - if self.world.randomize_type_matchup_type_effectiveness[self.player].value == 1: + if self.multiworld.randomize_type_matchup_type_effectiveness[self.player].value == 1: effectiveness_list = [] for matchup in chart: effectiveness_list.append(matchup[2]) random.shuffle(effectiveness_list) for (matchup, effectiveness) in zip(chart, effectiveness_list): matchup[2] = effectiveness - elif self.world.randomize_type_matchup_type_effectiveness[self.player].value == 2: + elif self.multiworld.randomize_type_matchup_type_effectiveness[self.player].value == 2: for matchup in chart: matchup[2] = random.choice([0] + ([5, 20] * 5)) - elif self.world.randomize_type_matchup_type_effectiveness[self.player].value == 3: + elif self.multiworld.randomize_type_matchup_type_effectiveness[self.player].value == 3: for matchup in chart: matchup[2] = random.choice([i for i in range(0, 21) if i != 10]) type_loc = rom_addresses["Type_Chart"] @@ -492,7 +492,7 @@ def generate_output(self, output_directory: str): # to the way effectiveness messages are generated. self.type_chart = sorted(chart, key=lambda matchup: 0 - matchup[2]) - if self.world.normalize_encounter_chances[self.player].value: + if self.multiworld.normalize_encounter_chances[self.player].value: chances = [25, 51, 77, 103, 129, 155, 180, 205, 230, 255] for i, chance in enumerate(chances): data[rom_addresses['Encounter_Chances'] + (i * 2)] = chance @@ -520,14 +520,14 @@ def generate_output(self, output_directory: str): for i, move in enumerate(self.learnsets[mon]): data[(address + 1) + i * 2] = poke_data.moves[move]["id"] - data[rom_addresses["Option_Aide_Rt2"]] = self.world.oaks_aide_rt_2[self.player] - data[rom_addresses["Option_Aide_Rt11"]] = self.world.oaks_aide_rt_11[self.player] - data[rom_addresses["Option_Aide_Rt15"]] = self.world.oaks_aide_rt_15[self.player] + data[rom_addresses["Option_Aide_Rt2"]] = self.multiworld.oaks_aide_rt_2[self.player] + data[rom_addresses["Option_Aide_Rt11"]] = self.multiworld.oaks_aide_rt_11[self.player] + data[rom_addresses["Option_Aide_Rt15"]] = self.multiworld.oaks_aide_rt_15[self.player] - if self.world.safari_zone_normal_battles[self.player].value == 1: + if self.multiworld.safari_zone_normal_battles[self.player].value == 1: data[rom_addresses["Option_Safari_Zone_Battle_Type"]] = 255 - if self.world.reusable_tms[self.player].value: + if self.multiworld.reusable_tms[self.player].value: data[rom_addresses["Option_Reusable_TMs"]] = 0xC9 process_trainer_data(self, data) @@ -537,17 +537,17 @@ def generate_output(self, output_directory: str): data[rom_addresses['Title_Mon_First']] = mons.pop() for mon in range(0, 16): data[rom_addresses['Title_Mons'] + mon] = mons.pop() - if self.world.game_version[self.player].value: - mons.sort(key=lambda mon: 0 if mon == self.world.get_location("Pallet Town - Starter 1", self.player).item.name - else 1 if mon == self.world.get_location("Pallet Town - Starter 2", self.player).item.name else - 2 if mon == self.world.get_location("Pallet Town - Starter 3", self.player).item.name else 3) + if self.multiworld.game_version[self.player].value: + mons.sort(key=lambda mon: 0 if mon == self.multiworld.get_location("Pallet Town - Starter 1", self.player).item.name + else 1 if mon == self.multiworld.get_location("Pallet Town - Starter 2", self.player).item.name else + 2 if mon == self.multiworld.get_location("Pallet Town - Starter 3", self.player).item.name else 3) else: - mons.sort(key=lambda mon: 0 if mon == self.world.get_location("Pallet Town - Starter 2", self.player).item.name - else 1 if mon == self.world.get_location("Pallet Town - Starter 1", self.player).item.name else - 2 if mon == self.world.get_location("Pallet Town - Starter 3", self.player).item.name else 3) - write_bytes(data, encode_text(self.world.seed_name, 20, True), rom_addresses['Title_Seed']) + mons.sort(key=lambda mon: 0 if mon == self.multiworld.get_location("Pallet Town - Starter 2", self.player).item.name + else 1 if mon == self.multiworld.get_location("Pallet Town - Starter 1", self.player).item.name else + 2 if mon == self.multiworld.get_location("Pallet Town - Starter 3", self.player).item.name else 3) + write_bytes(data, encode_text(self.multiworld.seed_name, 20, True), rom_addresses['Title_Seed']) - slot_name = self.world.player_name[self.player] + slot_name = self.multiworld.player_name[self.player] slot_name.replace("@", " ") slot_name.replace("<", " ") slot_name.replace(">", " ") @@ -557,23 +557,23 @@ def generate_output(self, output_directory: str): write_bytes(data, self.rival_name, rom_addresses['Rival_Name']) write_bytes(data, basemd5.digest(), 0xFFCC) - write_bytes(data, self.world.seed_name.encode(), 0xFFDC) - write_bytes(data, self.world.player_name[self.player].encode(), 0xFFF0) + write_bytes(data, self.multiworld.seed_name.encode(), 0xFFDC) + write_bytes(data, self.multiworld.player_name[self.player].encode(), 0xFFF0) outfilepname = f'_P{self.player}' - outfilepname += f"_{self.world.get_file_safe_player_name(self.player).replace(' ', '_')}" \ - if self.world.player_name[self.player] != 'Player%d' % self.player else '' - rompath = os.path.join(output_directory, f'AP_{self.world.seed_name}{outfilepname}.gb') + outfilepname += f"_{self.multiworld.get_file_safe_player_name(self.player).replace(' ', '_')}" \ + if self.multiworld.player_name[self.player] != 'Player%d' % self.player else '' + rompath = os.path.join(output_directory, f'AP_{self.multiworld.seed_name}{outfilepname}.gb') with open(rompath, 'wb') as outfile: outfile.write(data) - if self.world.game_version[self.player].current_key == "red": + if self.multiworld.game_version[self.player].current_key == "red": patch = RedDeltaPatch(os.path.splitext(rompath)[0] + RedDeltaPatch.patch_file_ending, player=self.player, - player_name=self.world.player_name[self.player], patched_path=rompath) + player_name=self.multiworld.player_name[self.player], patched_path=rompath) else: patch = BlueDeltaPatch(os.path.splitext(rompath)[0] + BlueDeltaPatch.patch_file_ending, player=self.player, - player_name=self.world.player_name[self.player], patched_path=rompath) + player_name=self.multiworld.player_name[self.player], patched_path=rompath) patch.write() os.unlink(rompath) diff --git a/worlds/pokemon_rb/rules.py b/worlds/pokemon_rb/rules.py index 0e97b705..2f0e573d 100644 --- a/worlds/pokemon_rb/rules.py +++ b/worlds/pokemon_rb/rules.py @@ -10,13 +10,13 @@ def set_rules(world, player): "Pallet Town - Rival's Sister": lambda state: state.has("Oak's Parcel", player), "Pallet Town - Oak's Post-Route-22-Rival Gift": lambda state: state.has("Oak's Parcel", player), "Viridian City - Sleepy Guy": lambda state: state.pokemon_rb_can_cut(player) or state.pokemon_rb_can_surf(player), - "Route 2 - Oak's Aide": lambda state: state.pokemon_rb_has_pokemon(state.world.oaks_aide_rt_2[player].value + 5, player), + "Route 2 - Oak's Aide": lambda state: state.pokemon_rb_has_pokemon(state.multiworld.oaks_aide_rt_2[player].value + 5, player), "Pewter City - Museum": lambda state: state.pokemon_rb_can_cut(player), "Cerulean City - Bicycle Shop": lambda state: state.has("Bike Voucher", player), "Lavender Town - Mr. Fuji": lambda state: state.has("Fuji Saved", player), "Vermilion Gym - Lt. Surge 1": lambda state: state.pokemon_rb_can_cut(player or state.pokemon_rb_can_surf(player)), "Vermilion Gym - Lt. Surge 2": lambda state: state.pokemon_rb_can_cut(player or state.pokemon_rb_can_surf(player)), - "Route 11 - Oak's Aide": lambda state: state.pokemon_rb_has_pokemon(state.world.oaks_aide_rt_11[player].value + 5, player), + "Route 11 - Oak's Aide": lambda state: state.pokemon_rb_has_pokemon(state.multiworld.oaks_aide_rt_11[player].value + 5, player), "Celadon City - Stranded Man": lambda state: state.pokemon_rb_can_surf(player), "Silph Co 11F - Silph Co President": lambda state: state.has("Card Key", player), "Fuchsia City - Safari Zone Warden": lambda state: state.has("Gold Teeth", player), diff --git a/worlds/raft/Rules.py b/worlds/raft/Rules.py index a55c0ef3..e84068a6 100644 --- a/worlds/raft/Rules.py +++ b/worlds/raft/Rules.py @@ -5,10 +5,10 @@ from ..AutoWorld import LogicMixin class RaftLogic(LogicMixin): def raft_paddleboard_mode_enabled(self, player): - return self.world.paddleboard_mode[player].value + return self.multiworld.paddleboard_mode[player].value def raft_big_islands_available(self, player): - return self.world.big_island_early_crafting[player].value or self.raft_can_access_radio_tower(player) + return self.multiworld.big_island_early_crafting[player].value or self.raft_can_access_radio_tower(player) def raft_can_smelt_items(self, player): return self.has("Smelter", player) diff --git a/worlds/raft/__init__.py b/worlds/raft/__init__.py index 860ba9aa..e326f734 100644 --- a/worlds/raft/__init__.py +++ b/worlds/raft/__init__.py @@ -43,8 +43,8 @@ class RaftWorld(World): required_client_version = (0, 3, 4) def generate_basic(self): - minRPSpecified = self.world.minimum_resource_pack_amount[self.player].value - maxRPSpecified = self.world.maximum_resource_pack_amount[self.player].value + minRPSpecified = self.multiworld.minimum_resource_pack_amount[self.player].value + maxRPSpecified = self.multiworld.maximum_resource_pack_amount[self.player].value minimumResourcePackAmount = min(minRPSpecified, maxRPSpecified) maximumResourcePackAmount = max(minRPSpecified, maxRPSpecified) # Generate item pool @@ -56,21 +56,21 @@ class RaftWorld(World): extraItemNamePool = [] extras = len(location_table) - len(item_table) - 1 # Victory takes up 1 unaccounted-for slot if extras > 0: - if (self.world.filler_item_types[self.player].value != 1): # Use resource packs + if (self.multiworld.filler_item_types[self.player].value != 1): # Use resource packs for packItem in resourcePackItems: for i in range(minimumResourcePackAmount, maximumResourcePackAmount + 1): extraItemNamePool.append(createResourcePackName(i, packItem)) - if self.world.filler_item_types[self.player].value != 0: # Use duplicate items + if self.multiworld.filler_item_types[self.player].value != 0: # Use duplicate items dupeItemPool = item_table.copy() # Remove frequencies if necessary - if self.world.island_frequency_locations[self.player].value != 5: # Not completely random locations + if self.multiworld.island_frequency_locations[self.player].value != 5: # Not completely random locations dupeItemPool = (itm for itm in dupeItemPool if "Frequency" not in itm["name"]) # Remove progression or non-progression items if necessary - if (self.world.duplicate_items[self.player].value == 0): # Progression only + if (self.multiworld.duplicate_items[self.player].value == 0): # Progression only dupeItemPool = (itm for itm in dupeItemPool if itm["progression"] == True) - elif (self.world.duplicate_items[self.player].value == 1): # Non-progression only + elif (self.multiworld.duplicate_items[self.player].value == 1): # Non-progression only dupeItemPool = (itm for itm in dupeItemPool if itm["progression"] == False) dupeItemPool = list(dupeItemPool) @@ -84,23 +84,23 @@ class RaftWorld(World): raft_item = self.create_item_replaceAsNecessary(randomItem) pool.append(raft_item) - self.world.itempool += pool + self.multiworld.itempool += pool def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def create_regions(self): - create_regions(self.world, self.player) + create_regions(self.multiworld, self.player) def get_pre_fill_items(self): - if self.world.island_frequency_locations[self.player] in [0, 1, 2, 3]: - return [loc.item for loc in self.world.get_filled_locations()] + if self.multiworld.island_frequency_locations[self.player] in [0, 1, 2, 3]: + return [loc.item for loc in self.multiworld.get_filled_locations()] return [] def create_item_replaceAsNecessary(self, name: str) -> Item: isFrequency = "Frequency" in name - shouldUseProgressive = ((isFrequency and self.world.island_frequency_locations[self.player].value == 4) - or (not isFrequency and self.world.progressive_items[self.player].value)) + shouldUseProgressive = ((isFrequency and self.multiworld.island_frequency_locations[self.player].value == 4) + or (not isFrequency and self.multiworld.progressive_items[self.player].value)) if shouldUseProgressive and name in progressive_table: name = progressive_table[name] return self.create_item(name) @@ -128,7 +128,7 @@ class RaftWorld(World): return super(RaftWorld, self).collect_item(state, item, remove) def pre_fill(self): - if self.world.island_frequency_locations[self.player] == 0: + if self.multiworld.island_frequency_locations[self.player] == 0: self.setLocationItem("Radio Tower Frequency to Vasagatan", "Vasagatan Frequency") self.setLocationItem("Vasagatan Frequency to Balboa", "Balboa Island Frequency") self.setLocationItem("Relay Station quest", "Caravan Island Frequency") @@ -136,7 +136,7 @@ class RaftWorld(World): self.setLocationItem("Tangaroa Frequency to Varuna Point", "Varuna Point Frequency") self.setLocationItem("Varuna Point Frequency to Temperance", "Temperance Frequency") self.setLocationItem("Temperance Frequency to Utopia", "Utopia Frequency") - elif self.world.island_frequency_locations[self.player] == 1: + elif self.multiworld.island_frequency_locations[self.player] == 1: self.setLocationItemFromRegion("RadioTower", "Vasagatan Frequency") self.setLocationItemFromRegion("Vasagatan", "Balboa Island Frequency") self.setLocationItemFromRegion("BalboaIsland", "Caravan Island Frequency") @@ -144,7 +144,7 @@ class RaftWorld(World): self.setLocationItemFromRegion("Tangaroa", "Varuna Point Frequency") self.setLocationItemFromRegion("Varuna Point", "Temperance Frequency") self.setLocationItemFromRegion("Temperance", "Utopia Frequency") - elif self.world.island_frequency_locations[self.player] in [2, 3]: + elif self.multiworld.island_frequency_locations[self.player] in [2, 3]: locationToFrequencyItemMap = { "Vasagatan": "Vasagatan Frequency", "BalboaIsland": "Balboa Island Frequency", @@ -172,37 +172,37 @@ class RaftWorld(World): else: currentLocation = availableLocationList[0] # Utopia (only one left in list) availableLocationList.remove(currentLocation) - if self.world.island_frequency_locations[self.player] == 2: + if self.multiworld.island_frequency_locations[self.player] == 2: self.setLocationItem(locationToVanillaFrequencyLocationMap[previousLocation], locationToFrequencyItemMap[currentLocation]) - elif self.world.island_frequency_locations[self.player] == 3: + elif self.multiworld.island_frequency_locations[self.player] == 3: self.setLocationItemFromRegion(previousLocation, locationToFrequencyItemMap[currentLocation]) previousLocation = currentLocation # Victory item - self.world.get_location("Utopia Complete", self.player).place_locked_item( + self.multiworld.get_location("Utopia Complete", self.player).place_locked_item( RaftItem("Victory", ItemClassification.progression, None, player=self.player)) def setLocationItem(self, location: str, itemName: str): - itemToUse = next(filter(lambda itm: itm.name == itemName, self.world.itempool)) - self.world.itempool.remove(itemToUse) - self.world.get_location(location, self.player).place_locked_item(itemToUse) + itemToUse = next(filter(lambda itm: itm.name == itemName, self.multiworld.itempool)) + self.multiworld.itempool.remove(itemToUse) + self.multiworld.get_location(location, self.player).place_locked_item(itemToUse) def setLocationItemFromRegion(self, region: str, itemName: str): - itemToUse = next(filter(lambda itm: itm.name == itemName, self.world.itempool)) - self.world.itempool.remove(itemToUse) + itemToUse = next(filter(lambda itm: itm.name == itemName, self.multiworld.itempool)) + self.multiworld.itempool.remove(itemToUse) location = random.choice(list(loc for loc in location_table if loc["region"] == region)) - self.world.get_location(location["name"], self.player).place_locked_item(itemToUse) + self.multiworld.get_location(location["name"], self.player).place_locked_item(itemToUse) def fill_slot_data(self): return { - "IslandGenerationDistance": self.world.island_generation_distance[self.player].value, - "ExpensiveResearch": bool(self.world.expensive_research[self.player].value), - "DeathLink": bool(self.world.death_link[self.player].value) + "IslandGenerationDistance": self.multiworld.island_generation_distance[self.player].value, + "ExpensiveResearch": bool(self.multiworld.expensive_research[self.player].value), + "DeathLink": bool(self.multiworld.death_link[self.player].value) } def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None): ret = Region(name, RegionType.Generic, name, player) - ret.world = world + ret.multiworld = world if locations: for location in locations: loc_id = locations_lookup_name_to_id.get(location, 0) diff --git a/worlds/rogue_legacy/Regions.py b/worlds/rogue_legacy/Regions.py index 3e078418..76cab97d 100644 --- a/worlds/rogue_legacy/Regions.py +++ b/worlds/rogue_legacy/Regions.py @@ -102,7 +102,7 @@ def create_regions(world: MultiWorld, player: int): def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None): ret = Region(name, RegionType.Generic, name, player) - ret.world = world + ret.multiworld = world if locations: for loc_name in locations: loc_data = location_table.get(loc_name) diff --git a/worlds/rogue_legacy/Rules.py b/worlds/rogue_legacy/Rules.py index de328774..b20cdd00 100644 --- a/worlds/rogue_legacy/Rules.py +++ b/worlds/rogue_legacy/Rules.py @@ -15,10 +15,10 @@ class LegacyLogic(LogicMixin): return self.stat_upgrade_count(player) >= amount def total_stat_upgrades_count(self, player: int) -> int: - return int(self.world.health_pool[player]) + \ - int(self.world.mana_pool[player]) + \ - int(self.world.attack_pool[player]) + \ - int(self.world.magic_damage_pool[player]) + return int(self.multiworld.health_pool[player]) + \ + int(self.multiworld.mana_pool[player]) + \ + int(self.multiworld.attack_pool[player]) + \ + int(self.multiworld.magic_damage_pool[player]) def stat_upgrade_count(self: CollectionState, player: int) -> int: return self.item_count("Health Up", player) + self.item_count("Mana Up", player) + \ diff --git a/worlds/rogue_legacy/__init__.py b/worlds/rogue_legacy/__init__.py index 95c1c1c6..91107c75 100644 --- a/worlds/rogue_legacy/__init__.py +++ b/worlds/rogue_legacy/__init__.py @@ -44,7 +44,7 @@ class RLWorld(World): prefill_items: List[RLItem] = [] def setting(self, name: str): - return getattr(self.world, name)[self.player] + return getattr(self.multiworld, name)[self.player] def fill_slot_data(self) -> dict: return {option_name: self.setting(option_name).value for option_name in rl_options} @@ -86,13 +86,13 @@ class RLWorld(World): if self.setting("architect") == "disabled" or self.setting("architect") == "early": continue if self.setting("architect") == "start_unlocked": - self.world.push_precollected(self.create_item(name)) + self.multiworld.push_precollected(self.create_item(name)) continue # Blacksmith and Enchantress if name == "Blacksmith" or name == "Enchantress": if self.setting("vendors") == "start_unlocked": - self.world.push_precollected(self.create_item(name)) + self.multiworld.push_precollected(self.create_item(name)) continue if self.setting("vendors") == "early": continue @@ -195,11 +195,11 @@ class RLWorld(World): while len(self.item_pool) + len(self.prefill_items) < total_locations: self.item_pool.append(self.create_item(self.get_filler_item_name())) - self.world.itempool += self.item_pool + self.multiworld.itempool += self.item_pool def pre_fill(self) -> None: - reachable = [loc for loc in self.world.get_reachable_locations(player=self.player) if not loc.item] - self.world.random.shuffle(reachable) + reachable = [loc for loc in self.multiworld.get_reachable_locations(player=self.player) if not loc.item] + self.multiworld.random.shuffle(reachable) items = self.prefill_items.copy() for item in items: reachable.pop().place_locked_item(item) @@ -210,7 +210,7 @@ class RLWorld(World): def get_filler_item_name(self) -> str: fillers = get_items_by_category("Filler") weights = [data.weight for data in fillers.values()] - return self.world.random.choices([filler for filler in fillers.keys()], weights, k=1)[0] + return self.multiworld.random.choices([filler for filler in fillers.keys()], weights, k=1)[0] def create_item(self, name: str) -> RLItem: data = item_table[name] @@ -221,45 +221,45 @@ class RLWorld(World): return RLItem(name, data.classification, data.code, self.player) def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def create_regions(self): - create_regions(self.world, self.player) + create_regions(self.multiworld, self.player) self._place_events() def _place_events(self): # Fountain - self.world.get_location("Fountain Room", self.player).place_locked_item( + self.multiworld.get_location("Fountain Room", self.player).place_locked_item( self.create_event("Defeat The Fountain")) # Khidr / Neo Khidr if self.setting("khidr") == "vanilla": - self.world.get_location("Castle Hamson Boss Room", self.player).place_locked_item( + self.multiworld.get_location("Castle Hamson Boss Room", self.player).place_locked_item( self.create_event("Defeat Khidr")) else: - self.world.get_location("Castle Hamson Boss Room", self.player).place_locked_item( + self.multiworld.get_location("Castle Hamson Boss Room", self.player).place_locked_item( self.create_event("Defeat Neo Khidr")) # Alexander / Alexander IV if self.setting("alexander") == "vanilla": - self.world.get_location("Forest Abkhazia Boss Room", self.player).place_locked_item( + self.multiworld.get_location("Forest Abkhazia Boss Room", self.player).place_locked_item( self.create_event("Defeat Alexander")) else: - self.world.get_location("Forest Abkhazia Boss Room", self.player).place_locked_item( + self.multiworld.get_location("Forest Abkhazia Boss Room", self.player).place_locked_item( self.create_event("Defeat Alexander IV")) # Ponce de Leon / Ponce de Freon if self.setting("leon") == "vanilla": - self.world.get_location("The Maya Boss Room", self.player).place_locked_item( + self.multiworld.get_location("The Maya Boss Room", self.player).place_locked_item( self.create_event("Defeat Ponce de Leon")) else: - self.world.get_location("The Maya Boss Room", self.player).place_locked_item( + self.multiworld.get_location("The Maya Boss Room", self.player).place_locked_item( self.create_event("Defeat Ponce de Freon")) # Herodotus / Astrodotus if self.setting("herodotus") == "vanilla": - self.world.get_location("Land of Darkness Boss Room", self.player).place_locked_item( + self.multiworld.get_location("Land of Darkness Boss Room", self.player).place_locked_item( self.create_event("Defeat Herodotus")) else: - self.world.get_location("Land of Darkness Boss Room", self.player).place_locked_item( + self.multiworld.get_location("Land of Darkness Boss Room", self.player).place_locked_item( self.create_event("Defeat Astrodotus")) diff --git a/worlds/ror2/__init__.py b/worlds/ror2/__init__.py index af65a15e..0c84f5b1 100644 --- a/worlds/ror2/__init__.py +++ b/worlds/ror2/__init__.py @@ -42,40 +42,40 @@ class RiskOfRainWorld(World): def generate_early(self) -> None: # figure out how many revivals should exist in the pool - self.total_revivals = int(self.world.total_revivals[self.player].value / 100 * - self.world.total_locations[self.player].value) + self.total_revivals = int(self.multiworld.total_revivals[self.player].value / 100 * + self.multiworld.total_locations[self.player].value) def generate_basic(self) -> None: # shortcut for starting_inventory... The start_with_revive option lets you start with a Dio's Best Friend - if self.world.start_with_revive[self.player].value: - self.world.push_precollected(self.world.create_item("Dio's Best Friend", self.player)) + if self.multiworld.start_with_revive[self.player].value: + self.multiworld.push_precollected(self.multiworld.create_item("Dio's Best Friend", self.player)) # if presets are enabled generate junk_pool from the selected preset - pool_option = self.world.item_weights[self.player].value + pool_option = self.multiworld.item_weights[self.player].value junk_pool: Dict[str, int] = {} - if self.world.item_pool_presets[self.player]: + if self.multiworld.item_pool_presets[self.player]: # generate chaos weights if the preset is chosen if pool_option == ItemWeights.option_chaos: for name, max_value in item_pool_weights[pool_option].items(): - junk_pool[name] = self.world.random.randint(0, max_value) + junk_pool[name] = self.multiworld.random.randint(0, max_value) else: junk_pool = item_pool_weights[pool_option].copy() else: # generate junk pool from user created presets junk_pool = { - "Item Scrap, Green": self.world.green_scrap[self.player].value, - "Item Scrap, Red": self.world.red_scrap[self.player].value, - "Item Scrap, Yellow": self.world.yellow_scrap[self.player].value, - "Item Scrap, White": self.world.white_scrap[self.player].value, - "Common Item": self.world.common_item[self.player].value, - "Uncommon Item": self.world.uncommon_item[self.player].value, - "Legendary Item": self.world.legendary_item[self.player].value, - "Boss Item": self.world.boss_item[self.player].value, - "Lunar Item": self.world.lunar_item[self.player].value, - "Equipment": self.world.equipment[self.player].value + "Item Scrap, Green": self.multiworld.green_scrap[self.player].value, + "Item Scrap, Red": self.multiworld.red_scrap[self.player].value, + "Item Scrap, Yellow": self.multiworld.yellow_scrap[self.player].value, + "Item Scrap, White": self.multiworld.white_scrap[self.player].value, + "Common Item": self.multiworld.common_item[self.player].value, + "Uncommon Item": self.multiworld.uncommon_item[self.player].value, + "Legendary Item": self.multiworld.legendary_item[self.player].value, + "Boss Item": self.multiworld.boss_item[self.player].value, + "Lunar Item": self.multiworld.lunar_item[self.player].value, + "Equipment": self.multiworld.equipment[self.player].value } # remove lunar items from the pool if they're disabled in the yaml unless lunartic is rolled - if not (self.world.enable_lunar[self.player] or pool_option == ItemWeights.option_lunartic): + if not (self.multiworld.enable_lunar[self.player] or pool_option == ItemWeights.option_lunartic): junk_pool.pop("Lunar Item") # Generate item pool @@ -84,38 +84,38 @@ class RiskOfRainWorld(World): itempool += ["Dio's Best Friend"] * self.total_revivals # Fill remaining items with randomly generated junk - itempool += self.world.random.choices(list(junk_pool.keys()), weights=list(junk_pool.values()), - k=self.world.total_locations[self.player].value - self.total_revivals) + itempool += self.multiworld.random.choices(list(junk_pool.keys()), weights=list(junk_pool.values()), + k=self.multiworld.total_locations[self.player].value - self.total_revivals) # Convert itempool into real items itempool = list(map(lambda name: self.create_item(name), itempool)) - self.world.itempool += itempool + self.multiworld.itempool += itempool def set_rules(self) -> None: - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def create_regions(self) -> None: - menu = create_region(self.world, self.player, "Menu") - petrichor = create_region(self.world, self.player, "Petrichor V", - [f"ItemPickup{i + 1}" for i in range(self.world.total_locations[self.player].value)]) + menu = create_region(self.multiworld, self.player, "Menu") + petrichor = create_region(self.multiworld, self.player, "Petrichor V", + [f"ItemPickup{i + 1}" for i in range(self.multiworld.total_locations[self.player].value)]) connection = Entrance(self.player, "Lobby", menu) menu.exits.append(connection) connection.connect(petrichor) - self.world.regions += [menu, petrichor] + self.multiworld.regions += [menu, petrichor] - create_events(self.world, self.player) + create_events(self.multiworld, self.player) def fill_slot_data(self): return { - "itemPickupStep": self.world.item_pickup_step[self.player].value, - "seed": "".join(self.world.slot_seeds[self.player].choice(string.digits) for _ in range(16)), - "totalLocations": self.world.total_locations[self.player].value, - "totalRevivals": self.world.total_revivals[self.player].value, - "startWithDio": self.world.start_with_revive[self.player].value, - "FinalStageDeath": self.world.final_stage_death[self.player].value + "itemPickupStep": self.multiworld.item_pickup_step[self.player].value, + "seed": "".join(self.multiworld.slot_seeds[self.player].choice(string.digits) for _ in range(16)), + "totalLocations": self.multiworld.total_locations[self.player].value, + "totalRevivals": self.multiworld.total_revivals[self.player].value, + "startWithDio": self.multiworld.start_with_revive[self.player].value, + "FinalStageDeath": self.multiworld.final_stage_death[self.player].value } def create_item(self, name: str) -> Item: diff --git a/worlds/sa2b/Regions.py b/worlds/sa2b/Regions.py index b39b13c1..dc32bf9e 100644 --- a/worlds/sa2b/Regions.py +++ b/worlds/sa2b/Regions.py @@ -690,7 +690,7 @@ def connect_regions(world, player, gates: typing.List[LevelGate], cannon_core_em def create_region(world: MultiWorld, player: int, active_locations, name: str, locations=None, exits=None): # Shamelessly stolen from the ROR2 definition ret = Region(name, None, name, player) - ret.world = world + ret.multiworld = world if locations: for location in locations: loc_id = active_locations.get(location, 0) diff --git a/worlds/sa2b/__init__.py b/worlds/sa2b/__init__.py index 7269a66c..f341df9e 100644 --- a/worlds/sa2b/__init__.py +++ b/worlds/sa2b/__init__.py @@ -69,15 +69,15 @@ class SA2BWorld(World): return { "ModVersion": 101, "MusicMap": self.music_map, - "MusicShuffle": self.world.music_shuffle[self.player].value, - "RequiredRank": self.world.required_rank[self.player].value, - "ChaoRaceChecks": self.world.chao_race_checks[self.player].value, - "ChaoGardenDifficulty": self.world.chao_garden_difficulty[self.player].value, - "DeathLink": self.world.death_link[self.player].value, - "IncludeMissions": self.world.include_missions[self.player].value, - "EmblemPercentageForCannonsCore": self.world.emblem_percentage_for_cannons_core[self.player].value, - "NumberOfLevelGates": self.world.number_of_level_gates[self.player].value, - "LevelGateDistribution": self.world.level_gate_distribution[self.player].value, + "MusicShuffle": self.multiworld.music_shuffle[self.player].value, + "RequiredRank": self.multiworld.required_rank[self.player].value, + "ChaoRaceChecks": self.multiworld.chao_race_checks[self.player].value, + "ChaoGardenDifficulty": self.multiworld.chao_garden_difficulty[self.player].value, + "DeathLink": self.multiworld.death_link[self.player].value, + "IncludeMissions": self.multiworld.include_missions[self.player].value, + "EmblemPercentageForCannonsCore": self.multiworld.emblem_percentage_for_cannons_core[self.player].value, + "NumberOfLevelGates": self.multiworld.number_of_level_gates[self.player].value, + "LevelGateDistribution": self.multiworld.level_gate_distribution[self.player].value, "EmblemsForCannonsCore": self.emblems_for_cannons_core, "RegionEmblemMap": self.region_emblem_map, "GateCosts": self.gate_costs, @@ -92,14 +92,14 @@ class SA2BWorld(World): slot_data = self._get_slot_data() slot_data["MusicMap"] = self.music_map for option_name in sa2b_options: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] slot_data[option_name] = option.value return slot_data def get_levels_per_gate(self) -> list: levels_per_gate = list() - max_gate_index = self.world.number_of_level_gates[self.player] + max_gate_index = self.multiworld.number_of_level_gates[self.player] average_level_count = 30 / (max_gate_index + 1) levels_added = 0 @@ -112,8 +112,8 @@ class SA2BWorld(World): levels_added += 1 additional_count_iterator += 1 if additional_count_iterator < max_gate_index else -max_gate_index - if self.world.level_gate_distribution[self.player] == 0 or self.world.level_gate_distribution[self.player] == 2: - early_distribution = self.world.level_gate_distribution[self.player] == 0 + if self.multiworld.level_gate_distribution[self.player] == 0 or self.multiworld.level_gate_distribution[self.player] == 2: + early_distribution = self.multiworld.level_gate_distribution[self.player] == 0 levels_to_distribute = 5 gate_index_offset = 0 while levels_to_distribute > 0: @@ -134,10 +134,10 @@ class SA2BWorld(World): return levels_per_gate def generate_early(self): - self.gate_bosses = get_gate_bosses(self.world, self.player) + self.gate_bosses = get_gate_bosses(self.multiworld, self.player) def generate_basic(self): - self.world.get_location(LocationName.biolizard, self.player).place_locked_item(self.create_item(ItemName.maria)) + self.multiworld.get_location(LocationName.biolizard, self.player).place_locked_item(self.create_item(ItemName.maria)) itempool: typing.List[SA2BItem] = [] @@ -155,20 +155,20 @@ class SA2BWorld(World): extra_junk_count = raw_emblem_count - total_emblem_count self.emblems_for_cannons_core = math.floor( - total_emblem_count * (self.world.emblem_percentage_for_cannons_core[self.player].value / 100.0)) + total_emblem_count * (self.multiworld.emblem_percentage_for_cannons_core[self.player].value / 100.0)) gate_cost_mult = 1.0 - if self.world.level_gate_costs[self.player].value == 0: + if self.multiworld.level_gate_costs[self.player].value == 0: gate_cost_mult = 0.6 - elif self.world.level_gate_costs[self.player].value == 1: + elif self.multiworld.level_gate_costs[self.player].value == 1: gate_cost_mult = 0.8 shuffled_region_list = list(range(30)) emblem_requirement_list = list() - self.world.random.shuffle(shuffled_region_list) + self.multiworld.random.shuffle(shuffled_region_list) levels_per_gate = self.get_levels_per_gate() - check_for_impossible_shuffle(shuffled_region_list, math.ceil(levels_per_gate[0]), self.world) + check_for_impossible_shuffle(shuffled_region_list, math.ceil(levels_per_gate[0]), self.multiworld) levels_added_to_gate = 0 total_levels_added = 0 current_gate = 0 @@ -184,8 +184,8 @@ class SA2BWorld(World): total_levels_added += 1 if levels_added_to_gate >= levels_per_gate[current_gate]: current_gate += 1 - if current_gate > self.world.number_of_level_gates[self.player].value: - current_gate = self.world.number_of_level_gates[self.player].value + if current_gate > self.multiworld.number_of_level_gates[self.player].value: + current_gate = self.multiworld.number_of_level_gates[self.player].value else: current_gate_emblems = max( math.floor(total_emblem_count * math.pow(total_levels_added / 30.0, 2.0) * gate_cost_mult), current_gate) @@ -195,60 +195,60 @@ class SA2BWorld(World): self.region_emblem_map = dict(zip(shuffled_region_list, emblem_requirement_list)) - connect_regions(self.world, self.player, gates, self.emblems_for_cannons_core, self.gate_bosses) + connect_regions(self.multiworld, self.player, gates, self.emblems_for_cannons_core, self.gate_bosses) max_required_emblems = max(max(emblem_requirement_list), self.emblems_for_cannons_core) itempool += [self.create_item(ItemName.emblem) for _ in range(max_required_emblems)] non_required_emblems = (total_emblem_count - max_required_emblems) - junk_count = math.floor(non_required_emblems * (self.world.junk_fill_percentage[self.player].value / 100.0)) + junk_count = math.floor(non_required_emblems * (self.multiworld.junk_fill_percentage[self.player].value / 100.0)) itempool += [self.create_item(ItemName.emblem, True) for _ in range(non_required_emblems - junk_count)] # Carve Traps out of junk_count trap_weights = [] - trap_weights += ([ItemName.omochao_trap] * self.world.omochao_trap_weight[self.player].value) - trap_weights += ([ItemName.timestop_trap] * self.world.timestop_trap_weight[self.player].value) - trap_weights += ([ItemName.confuse_trap] * self.world.confusion_trap_weight[self.player].value) - trap_weights += ([ItemName.tiny_trap] * self.world.tiny_trap_weight[self.player].value) + trap_weights += ([ItemName.omochao_trap] * self.multiworld.omochao_trap_weight[self.player].value) + trap_weights += ([ItemName.timestop_trap] * self.multiworld.timestop_trap_weight[self.player].value) + trap_weights += ([ItemName.confuse_trap] * self.multiworld.confusion_trap_weight[self.player].value) + trap_weights += ([ItemName.tiny_trap] * self.multiworld.tiny_trap_weight[self.player].value) junk_count += extra_junk_count - trap_count = 0 if (len(trap_weights) == 0) else math.ceil(junk_count * (self.world.trap_fill_percentage[self.player].value / 100.0)) + trap_count = 0 if (len(trap_weights) == 0) else math.ceil(junk_count * (self.multiworld.trap_fill_percentage[self.player].value / 100.0)) junk_count -= trap_count junk_pool = [] junk_keys = list(junk_table.keys()) for i in range(junk_count): - junk_item = self.world.random.choice(junk_keys) + junk_item = self.multiworld.random.choice(junk_keys) junk_pool.append(self.create_item(junk_item)) itempool += junk_pool trap_pool = [] for i in range(trap_count): - trap_item = self.world.random.choice(trap_weights) + trap_item = self.multiworld.random.choice(trap_weights) trap_pool.append(self.create_item(trap_item)) itempool += trap_pool - self.world.itempool += itempool + self.multiworld.itempool += itempool # Music Shuffle - if self.world.music_shuffle[self.player] == "levels": + if self.multiworld.music_shuffle[self.player] == "levels": musiclist_o = list(range(0, 47)) musiclist_s = musiclist_o.copy() - self.world.random.shuffle(musiclist_s) + self.multiworld.random.shuffle(musiclist_s) self.music_map = dict(zip(musiclist_o, musiclist_s)) - elif self.world.music_shuffle[self.player] == "full": + elif self.multiworld.music_shuffle[self.player] == "full": musiclist_o = list(range(0, 78)) musiclist_s = musiclist_o.copy() - self.world.random.shuffle(musiclist_s) + self.multiworld.random.shuffle(musiclist_s) self.music_map = dict(zip(musiclist_o, musiclist_s)) else: self.music_map = dict() def create_regions(self): - self.location_table = setup_locations(self.world, self.player) - create_regions(self.world, self.player, self.location_table) + self.location_table = setup_locations(self.multiworld, self.player) + create_regions(self.multiworld, self.player, self.location_table) def create_item(self, name: str, force_non_progression=False) -> Item: data = item_table[name] @@ -269,12 +269,12 @@ class SA2BWorld(World): return created_item def set_rules(self): - set_rules(self.world, self.player, self.gate_bosses) + set_rules(self.multiworld, self.player, self.gate_bosses) def write_spoiler(self, spoiler_handle: typing.TextIO): spoiler_handle.write("\n") header_text = "Sonic Adventure 2 Bosses for {}:\n" - header_text = header_text.format(self.world.player_name[self.player]) + header_text = header_text.format(self.multiworld.player_name[self.player]) spoiler_handle.write(header_text) for x in range(len(self.gate_bosses.values())): text = "Gate {0} Boss: {1}\n" diff --git a/worlds/sc2wol/Regions.py b/worlds/sc2wol/Regions.py index b0a3a51e..d42a417b 100644 --- a/worlds/sc2wol/Regions.py +++ b/worlds/sc2wol/Regions.py @@ -236,7 +236,7 @@ def create_location(player: int, location_data: LocationData, region: Region, def create_region(world: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]], location_cache: List[Location], name: str) -> Region: region = Region(name, RegionType.Generic, name, player) - region.world = world + region.multiworld = world if name in locations_per_region: for location_data in locations_per_region[name]: diff --git a/worlds/sc2wol/__init__.py b/worlds/sc2wol/__init__.py index 70226e7a..dc77792d 100644 --- a/worlds/sc2wol/__init__.py +++ b/worlds/sc2wol/__init__.py @@ -59,31 +59,31 @@ class SC2WoLWorld(World): def create_regions(self): self.mission_req_table, self.final_mission_id, self.victory_item = create_regions( - self.world, self.player, get_locations(self.world, self.player), self.location_cache + self.multiworld, self.player, get_locations(self.multiworld, self.player), self.location_cache ) def generate_basic(self): - excluded_items = get_excluded_items(self, self.world, self.player) + excluded_items = get_excluded_items(self, self.multiworld, self.player) - starter_items = assign_starter_items(self.world, self.player, excluded_items, self.locked_locations) + starter_items = assign_starter_items(self.multiworld, self.player, excluded_items, self.locked_locations) - pool = get_item_pool(self.world, self.player, self.mission_req_table, starter_items, excluded_items, self.location_cache) + pool = get_item_pool(self.multiworld, self.player, self.mission_req_table, starter_items, excluded_items, self.location_cache) - fill_item_pool_with_dummy_items(self, self.world, self.player, self.locked_locations, self.location_cache, pool) + fill_item_pool_with_dummy_items(self, self.multiworld, self.player, self.locked_locations, self.location_cache, pool) - self.world.itempool += pool + self.multiworld.itempool += pool def set_rules(self): - setup_events(self.world, self.player, self.locked_locations, self.location_cache) - self.world.completion_condition[self.player] = lambda state: state.has(self.victory_item, self.player) + setup_events(self.multiworld, self.player, self.locked_locations, self.location_cache) + self.multiworld.completion_condition[self.player] = lambda state: state.has(self.victory_item, self.player) def get_filler_item_name(self) -> str: - return self.world.random.choice(filler_items) + return self.multiworld.random.choice(filler_items) def fill_slot_data(self): slot_data = {} for option_name in sc2wol_options: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] if type(option.value) in {str, int}: slot_data[option_name] = int(option.value) slot_req_table = {} diff --git a/worlds/sm/__init__.py b/worlds/sm/__init__.py index fc19b4e1..76f39b75 100644 --- a/worlds/sm/__init__.py +++ b/worlds/sm/__init__.py @@ -111,27 +111,27 @@ class SMWorld(World): def generate_early(self): Logic.factory('vanilla') - self.variaRando = VariaRandomizer(self.world, get_base_rom_path(), self.player) - self.world.state.smbm[self.player] = SMBoolManager(self.player, self.variaRando.maxDifficulty) + self.variaRando = VariaRandomizer(self.multiworld, get_base_rom_path(), self.player) + self.multiworld.state.smbm[self.player] = SMBoolManager(self.player, self.variaRando.maxDifficulty) # keeps Nothing items local so no player will ever pickup Nothing # doing so reduces contribution of this world to the Multiworld the more Nothing there is though - self.world.local_items[self.player].value.add('Nothing') - self.world.local_items[self.player].value.add('No Energy') + self.multiworld.local_items[self.player].value.add('Nothing') + self.multiworld.local_items[self.player].value.add('No Energy') if (self.variaRando.args.morphPlacement == "early"): - self.world.local_items[self.player].value.add('Morph') + self.multiworld.local_items[self.player].value.add('Morph') - self.remote_items = self.world.remote_items[self.player] + self.remote_items = self.multiworld.remote_items[self.player] if (len(self.variaRando.randoExec.setup.restrictedLocs) > 0): - self.world.accessibility[self.player] = self.world.accessibility[self.player].from_text("minimal") - logger.warning(f"accessibility forced to 'minimal' for player {self.world.get_player_name(self.player)} because of 'fun' settings") + self.multiworld.accessibility[self.player] = self.multiworld.accessibility[self.player].from_text("minimal") + logger.warning(f"accessibility forced to 'minimal' for player {self.multiworld.get_player_name(self.player)} because of 'fun' settings") def generate_basic(self): itemPool = self.variaRando.container.itemPool - self.startItems = [variaItem for item in self.world.precollected_items[self.player] for variaItem in ItemManager.Items.values() if variaItem.Name == item.name] - if self.world.start_inventory_removes_from_pool[self.player]: + self.startItems = [variaItem for item in self.multiworld.precollected_items[self.player] for variaItem in ItemManager.Items.values() if variaItem.Name == item.name] + if self.multiworld.start_inventory_removes_from_pool[self.player]: for item in self.startItems: if (item in itemPool): itemPool.remove(item) @@ -175,31 +175,31 @@ class SMWorld(World): else: pool.append(smitem) - self.world.itempool += pool + self.multiworld.itempool += pool for (location, item) in self.locked_items.items(): - self.world.get_location(location, self.player).place_locked_item(item) - self.world.get_location(location, self.player).address = None + self.multiworld.get_location(location, self.player).place_locked_item(item) + self.multiworld.get_location(location, self.player).address = None - startAP = self.world.get_entrance('StartAP', self.player) - startAP.connect(self.world.get_region(self.variaRando.args.startLocation, self.player)) + startAP = self.multiworld.get_entrance('StartAP', self.player) + startAP.connect(self.multiworld.get_region(self.variaRando.args.startLocation, self.player)) for src, dest in self.variaRando.randoExec.areaGraph.InterAreaTransitions: - src_region = self.world.get_region(src.Name, self.player) - dest_region = self.world.get_region(dest.Name, self.player) - if ((src.Name + "->" + dest.Name, self.player) not in self.world._entrance_cache): + src_region = self.multiworld.get_region(src.Name, self.player) + dest_region = self.multiworld.get_region(dest.Name, self.player) + if ((src.Name + "->" + dest.Name, self.player) not in self.multiworld._entrance_cache): src_region.exits.append(Entrance(self.player, src.Name + "->" + dest.Name, src_region)) - srcDestEntrance = self.world.get_entrance(src.Name + "->" + dest.Name, self.player) + srcDestEntrance = self.multiworld.get_entrance(src.Name + "->" + dest.Name, self.player) srcDestEntrance.connect(dest_region) - add_entrance_rule(self.world.get_entrance(src.Name + "->" + dest.Name, self.player), self.player, getAccessPoint(src.Name).traverse) + add_entrance_rule(self.multiworld.get_entrance(src.Name + "->" + dest.Name, self.player), self.player, getAccessPoint(src.Name).traverse) def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def create_regions(self): create_locations(self, self.player) - create_regions(self, self.world, self.player) + create_regions(self, self.multiworld, self.player) def getWordArray(self, w): # little-endian convert a 16-bit number to an array of numbers <= 255 each return [w & 0x00FF, (w & 0xFF00) >> 8] @@ -289,7 +289,7 @@ class SMWorld(World): self.playerIDMap = {} playerIDCount = 0 # 0 is for "Archipelago" server; highest possible = 200 (201 entries) vanillaItemTypesCount = 21 - for itemLoc in self.world.get_locations(): + for itemLoc in self.multiworld.get_locations(): if itemLoc.player == self.player and locationsDict[itemLoc.name].Id != None: # this SM world can find this item: write full item data to tables and assign player data for writing romPlayerID = itemLoc.item.player if itemLoc.item.player <= ROM_PLAYER_LIMIT else 0 @@ -345,7 +345,7 @@ class SMWorld(World): deathLink = [{"sym": symbols["config_deathlink"], "offset": 0, - "values": [self.world.death_link[self.player].value]}] + "values": [self.multiworld.death_link[self.player].value]}] remoteItem = [{"sym": symbols["config_remote_items"], "offset": 0, "values": self.getWordArray(0b001 + (0b010 if self.remote_items else 0b000))}] @@ -364,7 +364,7 @@ class SMWorld(World): for key,value in self.playerIDMap.items(): playerNames.append({"sym": symbols["rando_player_table"], "offset": value * 16, - "values": self.world.player_name[key][:16].upper().center(16).encode()}) + "values": self.multiworld.player_name[key][:16].upper().center(16).encode()}) playerNameIDMap.append({"sym": symbols["rando_player_id_table"], "offset": value * 2, "values": self.getWordArray(key)}) @@ -399,7 +399,7 @@ class SMWorld(World): # set rom name # 21 bytes from Main import __version__ - self.romName = bytearray(f'SM{__version__.replace(".", "")[0:3]}_{self.player}_{self.world.seed:11}', 'utf8')[:21] + self.romName = bytearray(f'SM{__version__.replace(".", "")[0:3]}_{self.player}_{self.multiworld.seed:11}', 'utf8')[:21] self.romName.extend([0] * (21 - len(self.romName))) # clients should read from 0x7FC0, the location of the rom title in the SNES header. # duplicative ROM name at 0x1C4F00 is still written here for now, since people with archipelago pre-0.3.0 client installed will still be depending on this location for connecting to SM @@ -493,12 +493,12 @@ class SMWorld(World): if isinstance(itemLoc.item, SMItem) and itemLoc.item.type in ItemManager.Items else 'ArchipelagoItem'], locationsDict[itemLoc.name], True) - for itemLoc in self.world.get_locations() if itemLoc.player == self.player + for itemLoc in self.multiworld.get_locations() if itemLoc.player == self.player ] romPatcher.writeItemsLocs(itemLocs) - itemLocs = [ItemLocation(ItemManager.Items[itemLoc.item.type], locationsDict[itemLoc.name] if itemLoc.name in locationsDict and itemLoc.player == self.player else self.DummyLocation(self.world.get_player_name(itemLoc.player) + " " + itemLoc.name), True) for itemLoc in self.world.get_locations() if itemLoc.item.player == self.player] - progItemLocs = [ItemLocation(ItemManager.Items[itemLoc.item.type], locationsDict[itemLoc.name] if itemLoc.name in locationsDict and itemLoc.player == self.player else self.DummyLocation(self.world.get_player_name(itemLoc.player) + " " + itemLoc.name), True) for itemLoc in self.world.get_locations() if itemLoc.item.player == self.player and itemLoc.item.advancement == True] + itemLocs = [ItemLocation(ItemManager.Items[itemLoc.item.type], locationsDict[itemLoc.name] if itemLoc.name in locationsDict and itemLoc.player == self.player else self.DummyLocation(self.multiworld.get_player_name(itemLoc.player) + " " + itemLoc.name), True) for itemLoc in self.multiworld.get_locations() if itemLoc.item.player == self.player] + progItemLocs = [ItemLocation(ItemManager.Items[itemLoc.item.type], locationsDict[itemLoc.name] if itemLoc.name in locationsDict and itemLoc.player == self.player else self.DummyLocation(self.multiworld.get_player_name(itemLoc.player) + " " + itemLoc.name), True) for itemLoc in self.multiworld.get_locations() if itemLoc.item.player == self.player and itemLoc.item.advancement == True] # progItemLocs = [ItemLocation(ItemManager.Items[itemLoc.item.type if itemLoc.item.type in ItemManager.Items else 'ArchipelagoItem'], locationsDict[itemLoc.name], True) for itemLoc in self.world.get_locations() if itemLoc.player == self.player and itemLoc.item.player == self.player and itemLoc.item.advancement == True] # romPatcher.writeSplitLocs(self.variaRando.args.majorsSplit, itemLocs, progItemLocs) @@ -506,7 +506,7 @@ class SMWorld(World): romPatcher.writeRandoSettings(self.variaRando.randoExec.randoSettings, itemLocs) def generate_output(self, output_directory: str): - outfilebase = self.world.get_out_file_name_base(self.player) + outfilebase = self.multiworld.get_out_file_name_base(self.player) outputFilename = os.path.join(output_directory, f"{outfilebase}.sfc") try: @@ -516,8 +516,8 @@ class SMWorld(World): except: raise else: - patch = SMDeltaPatch(os.path.splitext(outputFilename)[0]+SMDeltaPatch.patch_file_ending, player=self.player, - player_name=self.world.player_name[self.player], patched_path=outputFilename) + patch = SMDeltaPatch(os.path.splitext(outputFilename)[0] + SMDeltaPatch.patch_file_ending, player=self.player, + player_name=self.multiworld.player_name[self.player], patched_path=outputFilename) patch.write() finally: if os.path.exists(outputFilename): @@ -560,13 +560,13 @@ class SMWorld(World): # 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() - multidata["connect_names"][new_name] = multidata["connect_names"][self.world.player_name[self.player]] + multidata["connect_names"][new_name] = multidata["connect_names"][self.multiworld.player_name[self.player]] def fill_slot_data(self): slot_data = {} - if not self.world.is_race: + if not self.multiworld.is_race: for option_name in self.option_definitions: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] slot_data[option_name] = option.value slot_data["Preset"] = { "Knows": {}, @@ -606,11 +606,11 @@ class SMWorld(World): player=self.player) def get_filler_item_name(self) -> str: - if self.world.random.randint(0, 100) < self.world.minor_qty[self.player].value: - power_bombs = self.world.power_bomb_qty[self.player].value - missiles = self.world.missile_qty[self.player].value - super_missiles = self.world.super_qty[self.player].value - roll = self.world.random.randint(1, power_bombs + missiles + super_missiles) + if self.multiworld.random.randint(0, 100) < self.multiworld.minor_qty[self.player].value: + power_bombs = self.multiworld.power_bomb_qty[self.player].value + missiles = self.multiworld.missile_qty[self.player].value + super_missiles = self.multiworld.super_qty[self.player].value + roll = self.multiworld.random.randint(1, power_bombs + missiles + super_missiles) if roll <= power_bombs: return "Power Bomb" elif roll <= power_bombs + missiles: @@ -621,20 +621,20 @@ class SMWorld(World): return "Nothing" def pre_fill(self): - if (self.variaRando.args.morphPlacement == "early") and next((item for item in self.world.itempool if item.player == self.player and item.name == "Morph Ball"), False): + if (self.variaRando.args.morphPlacement == "early") and next((item for item in self.multiworld.itempool if item.player == self.player and item.name == "Morph Ball"), False): viable = [] - for location in self.world.get_locations(): + for location in self.multiworld.get_locations(): if location.player == self.player \ and location.item is None \ - and location.can_reach(self.world.state): + and location.can_reach(self.multiworld.state): viable.append(location) - self.world.random.shuffle(viable) - key = self.world.create_item("Morph Ball", self.player) + self.multiworld.random.shuffle(viable) + key = self.multiworld.create_item("Morph Ball", self.player) loc = viable.pop() loc.place_locked_item(key) - self.world.itempool[:] = [item for item in self.world.itempool if - item.player != self.player or - item.name != "Morph Ball"] + self.multiworld.itempool[:] = [item for item in self.multiworld.itempool if + item.player != self.player or + item.name != "Morph Ball"] if len(self.NothingPool) > 0: nonChozoLoc = [] @@ -647,8 +647,8 @@ class SMWorld(World): else: nonChozoLoc.append(loc) - self.world.random.shuffle(nonChozoLoc) - self.world.random.shuffle(chozoLoc) + self.multiworld.random.shuffle(nonChozoLoc) + self.multiworld.random.shuffle(chozoLoc) missingCount = len(self.NothingPool) - len(nonChozoLoc) locations = nonChozoLoc if (missingCount > 0): @@ -677,17 +677,17 @@ class SMWorld(World): break def write_spoiler(self, spoiler_handle: TextIO): - if self.world.area_randomization[self.player].value != 0: + if self.multiworld.area_randomization[self.player].value != 0: spoiler_handle.write('\n\nArea Transitions:\n\n') - spoiler_handle.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_name(self.player)}: ' - if self.world.players > 1 else '', src.Name, + spoiler_handle.write('\n'.join(['%s%s %s %s' % (f'{self.multiworld.get_player_name(self.player)}: ' + if self.multiworld.players > 1 else '', src.Name, '<=>', dest.Name) for src, dest in self.variaRando.randoExec.areaGraph.InterAreaTransitions if not src.Boss])) - if self.world.boss_randomization[self.player].value != 0: + if self.multiworld.boss_randomization[self.player].value != 0: spoiler_handle.write('\n\nBoss Transitions:\n\n') - spoiler_handle.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_name(self.player)}: ' - if self.world.players > 1 else '', src.Name, + spoiler_handle.write('\n'.join(['%s%s %s %s' % (f'{self.multiworld.get_player_name(self.player)}: ' + if self.multiworld.players > 1 else '', src.Name, '<=>', dest.Name) for src, dest in self.variaRando.randoExec.areaGraph.InterAreaTransitions if src.Boss])) @@ -698,7 +698,7 @@ def create_locations(self, player: int): def create_region(self, world: MultiWorld, player: int, name: str, locations=None, exits=None): ret = Region(name, RegionType.LightWorld, name, player) - ret.world = world + ret.multiworld = world if locations: for loc in locations: location = self.locations[loc] @@ -720,7 +720,7 @@ class SMLocation(Location): return self.always_allow(state, item) or (self.item_rule(item) and (not check_access or (self.can_reach(state) and self.can_comeback(state, item)))) def can_comeback(self, state: CollectionState, item: Item): - randoExec = state.world.worlds[self.player].variaRando.randoExec + randoExec = state.multiworld.worlds[self.player].variaRando.randoExec for key in locationsDict[self.name].AccessFrom.keys(): if (randoExec.areaGraph.canAccessList( state.smbm[self.player], key, diff --git a/worlds/sm64ex/__init__.py b/worlds/sm64ex/__init__.py index b1eef4ff..f9cae84d 100644 --- a/worlds/sm64ex/__init__.py +++ b/worlds/sm64ex/__init__.py @@ -43,18 +43,18 @@ class SM64World(World): option_definitions = sm64_options def generate_early(self): - self.topology_present = self.world.AreaRandomizer[self.player].value + self.topology_present = self.multiworld.AreaRandomizer[self.player].value def create_regions(self): - create_regions(self.world,self.player) + create_regions(self.multiworld, self.player) def set_rules(self): self.area_connections = {} - set_rules(self.world, self.player, self.area_connections) + set_rules(self.multiworld, self.player, self.area_connections) if self.topology_present: # Write area_connections to spoiler log for entrance, destination in self.area_connections.items(): - self.world.spoiler.set_entrance( + self.multiworld.spoiler.set_entrance( sm64_internalloc_to_string[entrance] + " Entrance", sm64_internalloc_to_string[destination], 'entrance', self.player) @@ -72,74 +72,74 @@ class SM64World(World): return item def generate_basic(self): - starcount = self.world.AmountOfStars[self.player].value - if (not self.world.EnableCoinStars[self.player].value): - starcount = max(35,self.world.AmountOfStars[self.player].value-15) - starcount = max(starcount, self.world.FirstBowserStarDoorCost[self.player].value, - self.world.BasementStarDoorCost[self.player].value, self.world.SecondFloorStarDoorCost[self.player].value, - self.world.MIPS1Cost[self.player].value, self.world.MIPS2Cost[self.player].value, - self.world.StarsToFinish[self.player].value) - self.world.itempool += [self.create_item("Power Star") for i in range(0,starcount)] - self.world.itempool += [self.create_item("1Up Mushroom") for i in range(starcount,120 - (15 if not self.world.EnableCoinStars[self.player].value else 0))] + starcount = self.multiworld.AmountOfStars[self.player].value + if (not self.multiworld.EnableCoinStars[self.player].value): + starcount = max(35,self.multiworld.AmountOfStars[self.player].value-15) + starcount = max(starcount, self.multiworld.FirstBowserStarDoorCost[self.player].value, + self.multiworld.BasementStarDoorCost[self.player].value, self.multiworld.SecondFloorStarDoorCost[self.player].value, + self.multiworld.MIPS1Cost[self.player].value, self.multiworld.MIPS2Cost[self.player].value, + self.multiworld.StarsToFinish[self.player].value) + self.multiworld.itempool += [self.create_item("Power Star") for i in range(0,starcount)] + self.multiworld.itempool += [self.create_item("1Up Mushroom") for i in range(starcount,120 - (15 if not self.multiworld.EnableCoinStars[self.player].value else 0))] - if (not self.world.ProgressiveKeys[self.player].value): + if (not self.multiworld.ProgressiveKeys[self.player].value): key1 = self.create_item("Basement Key") key2 = self.create_item("Second Floor Key") - self.world.itempool += [key1,key2] + self.multiworld.itempool += [key1, key2] else: - self.world.itempool += [self.create_item("Progressive Key") for i in range(0,2)] + self.multiworld.itempool += [self.create_item("Progressive Key") for i in range(0,2)] wingcap = self.create_item("Wing Cap") metalcap = self.create_item("Metal Cap") vanishcap = self.create_item("Vanish Cap") - self.world.itempool += [wingcap,metalcap,vanishcap] + self.multiworld.itempool += [wingcap, metalcap, vanishcap] - if (self.world.BuddyChecks[self.player].value): - self.world.itempool += [self.create_item(name) for name, id in cannon_item_table.items()] + if (self.multiworld.BuddyChecks[self.player].value): + self.multiworld.itempool += [self.create_item(name) for name, id in cannon_item_table.items()] else: - self.world.get_location("BoB: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock BoB")) - self.world.get_location("WF: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock WF")) - self.world.get_location("JRB: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock JRB")) - self.world.get_location("CCM: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock CCM")) - self.world.get_location("SSL: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock SSL")) - self.world.get_location("SL: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock SL")) - self.world.get_location("WDW: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock WDW")) - self.world.get_location("TTM: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock TTM")) - self.world.get_location("THI: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock THI")) - self.world.get_location("RR: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock RR")) + self.multiworld.get_location("BoB: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock BoB")) + self.multiworld.get_location("WF: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock WF")) + self.multiworld.get_location("JRB: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock JRB")) + self.multiworld.get_location("CCM: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock CCM")) + self.multiworld.get_location("SSL: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock SSL")) + self.multiworld.get_location("SL: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock SL")) + self.multiworld.get_location("WDW: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock WDW")) + self.multiworld.get_location("TTM: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock TTM")) + self.multiworld.get_location("THI: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock THI")) + self.multiworld.get_location("RR: Bob-omb Buddy", self.player).place_locked_item(self.create_item("Cannon Unlock RR")) - if (self.world.ExclamationBoxes[self.player].value > 0): - self.world.itempool += [self.create_item("1Up Mushroom") for i in range(0,29)] + if (self.multiworld.ExclamationBoxes[self.player].value > 0): + self.multiworld.itempool += [self.create_item("1Up Mushroom") for i in range(0,29)] else: - self.world.get_location("CCM: 1Up Block Near Snowman", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("CCM: 1Up Block Ice Pillar", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("CCM: 1Up Block Secret Slide", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("BBH: 1Up Block Top of Mansion", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("HMC: 1Up Block above Pit", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("HMC: 1Up Block Past Rolling Rocks", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("SSL: 1Up Block Outside Pyramid", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("SSL: 1Up Block Pyramid Left Path", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("SSL: 1Up Block Pyramid Back", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("SL: 1Up Block Near Moneybags", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("SL: 1Up Block inside Igloo", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("WDW: 1Up Block in Downtown", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("TTM: 1Up Block on Red Mushroom", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("THI: 1Up Block THI Small near Start", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("THI: 1Up Block THI Large near Start", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("THI: 1Up Block Windy Area", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("TTC: 1Up Block Midway Up", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("TTC: 1Up Block at the Top", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("RR: 1Up Block Top of Red Coin Maze", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("RR: 1Up Block Under Fly Guy", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("RR: 1Up Block On House in the Sky", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Bowser in the Dark World 1Up Block on Tower", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Bowser in the Dark World 1Up Block near Goombas", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Cavern of the Metal Cap 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Vanish Cap Under the Moat 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Bowser in the Fire Sea 1Up Block Swaying Stairs", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Bowser in the Fire Sea 1Up Block Near Poles", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Wing Mario Over the Rainbow 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) - self.world.get_location("Bowser in the Sky 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("CCM: 1Up Block Near Snowman", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("CCM: 1Up Block Ice Pillar", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("CCM: 1Up Block Secret Slide", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("BBH: 1Up Block Top of Mansion", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("HMC: 1Up Block above Pit", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("HMC: 1Up Block Past Rolling Rocks", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("SSL: 1Up Block Outside Pyramid", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("SSL: 1Up Block Pyramid Left Path", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("SSL: 1Up Block Pyramid Back", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("SL: 1Up Block Near Moneybags", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("SL: 1Up Block inside Igloo", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("WDW: 1Up Block in Downtown", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("TTM: 1Up Block on Red Mushroom", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("THI: 1Up Block THI Small near Start", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("THI: 1Up Block THI Large near Start", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("THI: 1Up Block Windy Area", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("TTC: 1Up Block Midway Up", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("TTC: 1Up Block at the Top", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("RR: 1Up Block Top of Red Coin Maze", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("RR: 1Up Block Under Fly Guy", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("RR: 1Up Block On House in the Sky", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Bowser in the Dark World 1Up Block on Tower", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Bowser in the Dark World 1Up Block near Goombas", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Cavern of the Metal Cap 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Vanish Cap Under the Moat 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Bowser in the Fire Sea 1Up Block Swaying Stairs", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Bowser in the Fire Sea 1Up Block Near Poles", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Wing Mario Over the Rainbow 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) + self.multiworld.get_location("Bowser in the Sky 1Up Block", self.player).place_locked_item(self.create_item("1Up Mushroom")) def get_filler_item_name(self) -> str: return "1Up Mushroom" @@ -147,21 +147,21 @@ class SM64World(World): def fill_slot_data(self): return { "AreaRando": self.area_connections, - "FirstBowserDoorCost": self.world.FirstBowserStarDoorCost[self.player].value, - "BasementDoorCost": self.world.BasementStarDoorCost[self.player].value, - "SecondFloorDoorCost": self.world.SecondFloorStarDoorCost[self.player].value, - "MIPS1Cost": self.world.MIPS1Cost[self.player].value, - "MIPS2Cost": self.world.MIPS2Cost[self.player].value, - "StarsToFinish": self.world.StarsToFinish[self.player].value, - "DeathLink": self.world.death_link[self.player].value, + "FirstBowserDoorCost": self.multiworld.FirstBowserStarDoorCost[self.player].value, + "BasementDoorCost": self.multiworld.BasementStarDoorCost[self.player].value, + "SecondFloorDoorCost": self.multiworld.SecondFloorStarDoorCost[self.player].value, + "MIPS1Cost": self.multiworld.MIPS1Cost[self.player].value, + "MIPS2Cost": self.multiworld.MIPS2Cost[self.player].value, + "StarsToFinish": self.multiworld.StarsToFinish[self.player].value, + "DeathLink": self.multiworld.death_link[self.player].value, } def generate_output(self, output_directory: str): - if self.world.players != 1: + if self.multiworld.players != 1: return data = { "slot_data": self.fill_slot_data(), - "location_to_item": {self.location_name_to_id[i.name] : item_table[i.item.name] for i in self.world.get_locations()}, + "location_to_item": {self.location_name_to_id[i.name] : item_table[i.item.name] for i in self.multiworld.get_locations()}, "data_package": { "data": { "games": { @@ -173,7 +173,7 @@ class SM64World(World): } } } - filename = f"{self.world.get_out_file_name_base(self.player)}.apsm64ex" + filename = f"{self.multiworld.get_out_file_name_base(self.player)}.apsm64ex" with open(os.path.join(output_directory, filename), 'w') as f: json.dump(data, f) @@ -182,7 +182,7 @@ class SM64World(World): er_hint_data = {} for entrance, destination in self.area_connections.items(): regionid = sm64_internalloc_to_regionid[destination] - region = self.world.get_region(sm64courses[regionid], self.player) + region = self.multiworld.get_region(sm64courses[regionid], self.player) for location in region.locations: er_hint_data[location.address] = sm64_internalloc_to_string[entrance] multidata['er_hint_data'][self.player] = er_hint_data diff --git a/worlds/smw/__init__.py b/worlds/smw/__init__.py index 2e9be535..89cc0a87 100644 --- a/worlds/smw/__init__.py +++ b/worlds/smw/__init__.py @@ -62,14 +62,14 @@ class SMWWorld(World): def _get_slot_data(self): return { - #"death_link": self.world.death_link[self.player].value, + #"death_link": self.multiworld.death_link[self.player].value, "active_levels": self.active_level_dict, } def fill_slot_data(self) -> dict: slot_data = self._get_slot_data() for option_name in smw_options: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] slot_data[option_name] = option.value return slot_data @@ -77,20 +77,20 @@ class SMWWorld(World): def generate_basic(self): itempool: typing.List[SMWItem] = [] - self.active_level_dict = dict(zip(generate_level_list(self.world, self.player), full_level_list)) - self.topology_present = self.world.level_shuffle[self.player] + self.active_level_dict = dict(zip(generate_level_list(self.multiworld, self.player), full_level_list)) + self.topology_present = self.multiworld.level_shuffle[self.player] - connect_regions(self.world, self.player, self.active_level_dict) + connect_regions(self.multiworld, self.player, self.active_level_dict) # Add Boss Token amount requirements for Worlds - add_rule(self.world.get_region(LocationName.donut_plains_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 1)) - add_rule(self.world.get_region(LocationName.vanilla_dome_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 2)) - add_rule(self.world.get_region(LocationName.forest_of_illusion_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 4)) - add_rule(self.world.get_region(LocationName.chocolate_island_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 5)) - add_rule(self.world.get_region(LocationName.valley_of_bowser_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 6)) + add_rule(self.multiworld.get_region(LocationName.donut_plains_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 1)) + add_rule(self.multiworld.get_region(LocationName.vanilla_dome_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 2)) + add_rule(self.multiworld.get_region(LocationName.forest_of_illusion_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 4)) + add_rule(self.multiworld.get_region(LocationName.chocolate_island_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 5)) + add_rule(self.multiworld.get_region(LocationName.valley_of_bowser_1_tile, self.player).entrances[0], lambda state: state.has(ItemName.koopaling, self.player, 6)) total_required_locations = 96 - if self.world.dragon_coin_checks[self.player]: + if self.multiworld.dragon_coin_checks[self.player]: total_required_locations += 49 itempool += [self.create_item(ItemName.mario_run)] @@ -108,24 +108,24 @@ class SMWWorld(World): itempool += [self.create_item(ItemName.red_switch_palace)] itempool += [self.create_item(ItemName.blue_switch_palace)] - if self.world.goal[self.player] == "yoshi_egg_hunt": + if self.multiworld.goal[self.player] == "yoshi_egg_hunt": itempool += [self.create_item(ItemName.yoshi_egg) - for _ in range(self.world.number_of_yoshi_eggs[self.player])] - self.world.get_location(LocationName.yoshis_house, self.player).place_locked_item(self.create_item(ItemName.victory)) + for _ in range(self.multiworld.number_of_yoshi_eggs[self.player])] + self.multiworld.get_location(LocationName.yoshis_house, self.player).place_locked_item(self.create_item(ItemName.victory)) else: - self.world.get_location(LocationName.bowser, self.player).place_locked_item(self.create_item(ItemName.victory)) + self.multiworld.get_location(LocationName.bowser, self.player).place_locked_item(self.create_item(ItemName.victory)) junk_count = total_required_locations - len(itempool) trap_weights = [] - trap_weights += ([ItemName.ice_trap] * self.world.ice_trap_weight[self.player].value) - trap_weights += ([ItemName.stun_trap] * self.world.stun_trap_weight[self.player].value) - trap_weights += ([ItemName.literature_trap] * self.world.literature_trap_weight[self.player].value) - trap_count = 0 if (len(trap_weights) == 0) else math.ceil(junk_count * (self.world.trap_fill_percentage[self.player].value / 100.0)) + trap_weights += ([ItemName.ice_trap] * self.multiworld.ice_trap_weight[self.player].value) + trap_weights += ([ItemName.stun_trap] * self.multiworld.stun_trap_weight[self.player].value) + trap_weights += ([ItemName.literature_trap] * self.multiworld.literature_trap_weight[self.player].value) + trap_count = 0 if (len(trap_weights) == 0) else math.ceil(junk_count * (self.multiworld.trap_fill_percentage[self.player].value / 100.0)) junk_count -= trap_count trap_pool = [] for i in range(trap_count): - trap_item = self.world.random.choice(trap_weights) + trap_item = self.multiworld.random.choice(trap_weights) trap_pool.append(self.create_item(trap_item)) itempool += trap_pool @@ -137,21 +137,21 @@ class SMWWorld(World): LocationName.valley_koopaling, LocationName.vanilla_reznor, LocationName.forest_reznor, LocationName.chocolate_reznor, LocationName.valley_reznor] for location_name in boss_location_names: - self.world.get_location(location_name, self.player).place_locked_item(self.create_item(ItemName.koopaling)) + self.multiworld.get_location(location_name, self.player).place_locked_item(self.create_item(ItemName.koopaling)) - self.world.itempool += itempool + self.multiworld.itempool += itempool def generate_output(self, output_directory: str): rompath = "" # if variable is not declared finally clause may fail try: - world = self.world + world = self.multiworld player = self.player rom = LocalRom(get_base_rom_path()) - patch_rom(self.world, rom, self.player, self.active_level_dict) + patch_rom(self.multiworld, rom, self.player, self.active_level_dict) - rompath = os.path.join(output_directory, f"{self.world.get_out_file_name_base(self.player)}.sfc") + rompath = os.path.join(output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}.sfc") rom.write_to_file(rompath) self.rom_name = rom.name @@ -173,7 +173,7 @@ class SMWWorld(World): # 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() - multidata["connect_names"][new_name] = multidata["connect_names"][self.world.player_name[self.player]] + multidata["connect_names"][new_name] = multidata["connect_names"][self.multiworld.player_name[self.player]] def extend_hint_information(self, hint_data: typing.Dict[int, typing.Dict[int, str]]): if self.topology_present: @@ -212,18 +212,18 @@ class SMWWorld(World): if level_index >= world_cutoffs[i]: continue - if self.world.dragon_coin_checks[self.player].value == 0 and "Dragon Coins" in loc_name: + if self.multiworld.dragon_coin_checks[self.player].value == 0 and "Dragon Coins" in loc_name: continue - location = self.world.get_location(loc_name, self.player) + location = self.multiworld.get_location(loc_name, self.player) er_hint_data[location.address] = world_names[i] break hint_data[self.player] = er_hint_data def create_regions(self): - location_table = setup_locations(self.world, self.player) - create_regions(self.world, self.player, location_table) + location_table = setup_locations(self.multiworld, self.player) + create_regions(self.multiworld, self.player, location_table) def create_item(self, name: str, force_non_progression=False) -> Item: data = item_table[name] @@ -244,4 +244,4 @@ class SMWWorld(World): return created_item def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) diff --git a/worlds/smz3/__init__.py b/worlds/smz3/__init__.py index 320d506f..944cf690 100644 --- a/worlds/smz3/__init__.py +++ b/worlds/smz3/__init__.py @@ -190,24 +190,24 @@ class SMZ3World(World): self.config = Config() self.config.GameMode = GameMode.Multiworld self.config.Z3Logic = Z3Logic.Normal - self.config.SMLogic = SMLogic(self.world.sm_logic[self.player].value) - self.config.SwordLocation = SwordLocation(self.world.sword_location[self.player].value) - self.config.MorphLocation = MorphLocation(self.world.morph_location[self.player].value) - self.config.Goal = Goal(self.world.goal[self.player].value) - self.config.KeyShuffle = KeyShuffle(self.world.key_shuffle[self.player].value) - self.config.OpenTower = OpenTower(self.world.open_tower[self.player].value) - self.config.GanonVulnerable = GanonVulnerable(self.world.ganon_vulnerable[self.player].value) - self.config.OpenTourian = OpenTourian(self.world.open_tourian[self.player].value) + self.config.SMLogic = SMLogic(self.multiworld.sm_logic[self.player].value) + self.config.SwordLocation = SwordLocation(self.multiworld.sword_location[self.player].value) + self.config.MorphLocation = MorphLocation(self.multiworld.morph_location[self.player].value) + self.config.Goal = Goal(self.multiworld.goal[self.player].value) + self.config.KeyShuffle = KeyShuffle(self.multiworld.key_shuffle[self.player].value) + self.config.OpenTower = OpenTower(self.multiworld.open_tower[self.player].value) + self.config.GanonVulnerable = GanonVulnerable(self.multiworld.ganon_vulnerable[self.player].value) + self.config.OpenTourian = OpenTourian(self.multiworld.open_tourian[self.player].value) - self.local_random = random.Random(self.world.random.randint(0, 1000)) - self.smz3World = TotalSMZ3World(self.config, self.world.get_player_name(self.player), self.player, self.world.seed_name) + self.local_random = random.Random(self.multiworld.random.randint(0, 1000)) + self.smz3World = TotalSMZ3World(self.config, self.multiworld.get_player_name(self.player), self.player, self.multiworld.seed_name) self.smz3DungeonItems = [] SMZ3World.location_names = frozenset(self.smz3World.locationLookup.keys()) - self.world.state.smz3state[self.player] = TotalSMZ3Item.Progression([]) + self.multiworld.state.smz3state[self.player] = TotalSMZ3Item.Progression([]) def generate_basic(self): - self.smz3World.Setup(WorldState.Generate(self.config, self.world.random)) + self.smz3World.Setup(WorldState.Generate(self.config, self.multiworld.random)) self.dungeon = TotalSMZ3Item.Item.CreateDungeonPool(self.smz3World) self.dungeon.reverse() self.progression = TotalSMZ3Item.Item.CreateProgressionPool(self.smz3World) @@ -224,25 +224,25 @@ class SMZ3World(World): else: progressionItems = self.progression for item in self.keyCardsItems: - self.world.push_precollected(SMZ3Item(item.Type.name, ItemClassification.filler, item.Type, self.item_name_to_id[item.Type.name], self.player, item)) + self.multiworld.push_precollected(SMZ3Item(item.Type.name, ItemClassification.filler, item.Type, self.item_name_to_id[item.Type.name], self.player, item)) itemPool = [SMZ3Item(item.Type.name, ItemClassification.progression, item.Type, self.item_name_to_id[item.Type.name], self.player, item) for item in progressionItems] + \ [SMZ3Item(item.Type.name, ItemClassification.filler, item.Type, self.item_name_to_id[item.Type.name], self.player, item) for item in allJunkItems] self.smz3DungeonItems = [SMZ3Item(item.Type.name, ItemClassification.progression, item.Type, self.item_name_to_id[item.Type.name], self.player, item) for item in self.dungeon] - self.world.itempool += itemPool + self.multiworld.itempool += itemPool def set_rules(self): # SM G4 is logically required to access Ganon's Tower in SMZ3 - self.world.completion_condition[self.player] = lambda state: \ + self.multiworld.completion_condition[self.player] = lambda state: \ self.smz3World.GetRegion("Ganon's Tower").CanEnter(state.smz3state[self.player]) and \ self.smz3World.GetRegion("Ganon's Tower").TowerAscend(state.smz3state[self.player]) for region in self.smz3World.Regions: - entrance = self.world.get_entrance('Menu' + "->" + region.Name, self.player) + entrance = self.multiworld.get_entrance('Menu' + "->" + region.Name, self.player) set_rule(entrance, lambda state, region=region: region.CanEnter(state.smz3state[self.player])) for loc in region.Locations: l = self.locations[loc.Name] - if self.world.accessibility[self.player] != 'locations': + if self.multiworld.accessibility[self.player] != 'locations': l.always_allow = lambda state, item, loc=loc: \ item.game == "SMZ3" and \ loc.alwaysAllow(TotalSMZ3Item.Item(TotalSMZ3Item.ItemType[item.name], self.smz3World), state.smz3state[self.player]) @@ -255,13 +255,13 @@ class SMZ3World(World): def create_regions(self): self.create_locations(self.player) - startRegion = self.create_region(self.world, self.player, 'Menu') - self.world.regions.append(startRegion) + startRegion = self.create_region(self.multiworld, self.player, 'Menu') + self.multiworld.regions.append(startRegion) for region in self.smz3World.Regions: - currentRegion = self.create_region(self.world, self.player, region.Name, region.locationLookup.keys(), [region.Name + "->" + 'Menu']) - self.world.regions.append(currentRegion) - entrance = self.world.get_entrance(region.Name + "->" + 'Menu', self.player) + currentRegion = self.create_region(self.multiworld, self.player, region.Name, region.locationLookup.keys(), [region.Name + "->" + 'Menu']) + self.multiworld.regions.append(currentRegion) + entrance = self.multiworld.get_entrance(region.Name + "->" + 'Menu', self.player) entrance.connect(startRegion) exit = Entrance(self.player, 'Menu' + "->" + region.Name, startRegion) startRegion.exits.append(exit) @@ -347,7 +347,7 @@ class SMZ3World(World): sm_remote_idx = 0 lttp_remote_idx = 0 for location in self.smz3World.Locations: - if self.world.worlds[location.APLocation.item.player].game != self.game: + if self.multiworld.worlds[location.APLocation.item.player].game != self.game: if location.Type == LocationType.Visible or location.Type == LocationType.Chozo or location.Type == LocationType.Hidden: patch[0x390000 + sm_remote_idx*64] = self.convert_to_sm_item_name(location.APLocation.item.name) sm_remote_idx += 1 @@ -369,12 +369,12 @@ class SMZ3World(World): patch = {} # smSpinjumps - if (self.world.spin_jumps_animation[self.player].value == 1): + if (self.multiworld.spin_jumps_animation[self.player].value == 1): patch[self.SnesCustomization(0x9B93FE)] = bytearray([0x01]) # z3HeartBeep values = [ 0x00, 0x80, 0x40, 0x20, 0x10] - index = self.world.heart_beep_speed[self.player].value + index = self.multiworld.heart_beep_speed[self.player].value patch[0x400033] = bytearray([values[index if index < len(values) else 2]]) # z3HeartColor @@ -384,17 +384,17 @@ class SMZ3World(World): [0x2C, [0xC9, 0x69]], [0x28, [0xBC, 0x02]] ] - index = self.world.heart_color[self.player].value + index = self.multiworld.heart_color[self.player].value (hud, fileSelect) = values[index if index < len(values) else 0] for i in range(0, 20, 2): patch[self.SnesCustomization(0xDFA1E + i)] = bytearray([hud]) patch[self.SnesCustomization(0x1BD6AA)] = bytearray(fileSelect) # z3QuickSwap - patch[0x40004B] = bytearray([0x01 if self.world.quick_swap[self.player].value else 0x00]) + patch[0x40004B] = bytearray([0x01 if self.multiworld.quick_swap[self.player].value else 0x00]) # smEnergyBeepOff - if (self.world.energy_beep[self.player].value == 0): + if (self.multiworld.energy_beep[self.player].value == 0): for ([addr, value]) in [ [0x90EA9B, 0x80], [0x90F337, 0x80], @@ -411,12 +411,12 @@ class SMZ3World(World): base_combined_rom = basepatch.apply(base_combined_rom) patcher = TotalSMZ3Patch(self.smz3World, - [world.smz3World for key, world in self.world.worlds.items() if isinstance(world, SMZ3World) and hasattr(world, "smz3World")], - self.world.seed_name, - self.world.seed, - self.local_random, - {v: k for k, v in self.world.player_name.items()}, - next(iter(loc.player for loc in self.world.get_locations() if (loc.item.name == "SilverArrows" and loc.item.player == self.player)))) + [world.smz3World for key, world in self.multiworld.worlds.items() if isinstance(world, SMZ3World) and hasattr(world, "smz3World")], + self.multiworld.seed_name, + self.multiworld.seed, + self.local_random, + {v: k for k, v in self.multiworld.player_name.items()}, + next(iter(loc.player for loc in self.multiworld.get_locations() if (loc.item.name == "SilverArrows" and loc.item.player == self.player)))) patches = patcher.Create(self.smz3World.Config) patches.update(self.apply_sm_custom_sprite()) patches.update(self.apply_item_names()) @@ -427,13 +427,13 @@ class SMZ3World(World): base_combined_rom[addr + offset] = byte offset += 1 - outfilebase = self.world.get_out_file_name_base(self.player) + outfilebase = self.multiworld.get_out_file_name_base(self.player) filename = os.path.join(output_directory, f"{outfilebase}.sfc") with open(filename, "wb") as binary_file: binary_file.write(base_combined_rom) - patch = SMZ3DeltaPatch(os.path.splitext(filename)[0]+SMZ3DeltaPatch.patch_file_ending, player=self.player, - player_name=self.world.player_name[self.player], patched_path=filename) + patch = SMZ3DeltaPatch(os.path.splitext(filename)[0] + SMZ3DeltaPatch.patch_file_ending, player=self.player, + player_name=self.multiworld.player_name[self.player], patched_path=filename) patch.write() os.remove(filename) self.rom_name = bytearray(patcher.title, 'utf8') @@ -458,7 +458,7 @@ class SMZ3World(World): # 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() - payload = multidata["connect_names"][self.world.player_name[self.player]] + payload = multidata["connect_names"][self.multiworld.player_name[self.player]] multidata["connect_names"][new_name] = payload def fill_slot_data(self): @@ -495,18 +495,18 @@ class SMZ3World(World): if (not self.smz3World.Config.Keysanity): locations = [loc for loc in self.locations.values() if loc.item is None] - self.world.random.shuffle(locations) + self.multiworld.random.shuffle(locations) - all_state = self.world.get_all_state(False) + all_state = self.multiworld.get_all_state(False) for item in self.smz3DungeonItems: all_state.remove(item) all_dungeonItems = self.smz3DungeonItems[:] - fill_restrictive(self.world, all_state, locations, all_dungeonItems, True, True) + fill_restrictive(self.multiworld, all_state, locations, all_dungeonItems, True, True) # some small or big keys (those always_allow) can be unreachable in-game # while logic still collects some of them (probably to simulate the player collecting pot keys in the logic), some others don't # so we need to remove those exceptions as progression items - if self.world.accessibility[self.player] != 'locations': + if self.multiworld.accessibility[self.player] != 'locations': exception_item = [TotalSMZ3Item.ItemType.BigKeySW, TotalSMZ3Item.ItemType.BigKeySP, TotalSMZ3Item.ItemType.KeyTH] for item in self.smz3DungeonItems: if item.item.Type in exception_item and item.location.always_allow(all_state, item) and not all_state.can_reach(item.location): @@ -523,18 +523,18 @@ class SMZ3World(World): return [] def get_filler_item_name(self) -> str: - return self.world.random.choice(self.junkItemsNames) + return self.multiworld.random.choice(self.junkItemsNames) def write_spoiler(self, spoiler_handle: TextIO): - self.world.spoiler.unreachables.update(self.unreachable) + self.multiworld.spoiler.unreachables.update(self.unreachable) def JunkFillGT(self, factor): - poolLength = len(self.world.itempool) - playerGroups = self.world.get_player_groups(self.player) + poolLength = len(self.multiworld.itempool) + playerGroups = self.multiworld.get_player_groups(self.player) playerGroups.add(self.player) - junkPoolIdx = [i for i in range(0, poolLength) - if self.world.itempool[i].classification in (ItemClassification.filler, ItemClassification.trap) and - self.world.itempool[i].player in playerGroups] + junkPoolIdx = [i for i in range(0, poolLength) + if self.multiworld.itempool[i].classification in (ItemClassification.filler, ItemClassification.trap) and + self.multiworld.itempool[i].player in playerGroups] toRemove = [] for loc in self.locations.values(): # commenting this for now since doing a partial GT pre fill would allow for non SMZ3 progression in GT @@ -544,19 +544,19 @@ class SMZ3World(World): if loc.name in self.locationNamesGT and loc.item is None: poolLength = len(junkPoolIdx) # start looking at a random starting index and loop at start if no match found - start = self.world.random.randint(0, poolLength) + start = self.multiworld.random.randint(0, poolLength) for off in range(0, poolLength): i = (start + off) % poolLength - candidate = self.world.itempool[junkPoolIdx[i]] - if junkPoolIdx[i] not in toRemove and loc.can_fill(self.world.state, candidate, False): + candidate = self.multiworld.itempool[junkPoolIdx[i]] + if junkPoolIdx[i] not in toRemove and loc.can_fill(self.multiworld.state, candidate, False): itemFromPool = candidate toRemove.append(junkPoolIdx[i]) break - self.world.push_item(loc, itemFromPool, False) + self.multiworld.push_item(loc, itemFromPool, False) loc.event = False toRemove.sort(reverse = True) for i in toRemove: - self.world.itempool.pop(i) + self.multiworld.itempool.pop(i) def FillItemAtLocation(self, itemPool, itemType, location): itemToPlace = TotalSMZ3Item.Item.Get(itemPool, itemType, self.smz3World) @@ -564,28 +564,28 @@ class SMZ3World(World): raise Exception(f"Tried to place item {itemType} at {location.Name}, but there is no such item in the item pool") else: location.Item = itemToPlace - itemFromPool = next((i for i in self.world.itempool if i.player == self.player and i.name == itemToPlace.Type.name), None) + itemFromPool = next((i for i in self.multiworld.itempool if i.player == self.player and i.name == itemToPlace.Type.name), None) if itemFromPool is not None: - self.world.get_location(location.Name, self.player).place_locked_item(itemFromPool) - self.world.itempool.remove(itemFromPool) + self.multiworld.get_location(location.Name, self.player).place_locked_item(itemFromPool) + self.multiworld.itempool.remove(itemFromPool) else: itemFromPool = next((i for i in self.smz3DungeonItems if i.player == self.player and i.name == itemToPlace.Type.name), None) if itemFromPool is not None: - self.world.get_location(location.Name, self.player).place_locked_item(itemFromPool) + self.multiworld.get_location(location.Name, self.player).place_locked_item(itemFromPool) self.smz3DungeonItems.remove(itemFromPool) itemPool.remove(itemToPlace) def FrontFillItemInOwnWorld(self, itemPool, itemType): item = TotalSMZ3Item.Item.Get(itemPool, itemType, self.smz3World) - location = next(iter(self.world.random.sample(TotalSMZ3Location.AvailableGlobal(TotalSMZ3Location.Empty(self.smz3World.Locations), self.smz3World.Items()), 1)), None) + location = next(iter(self.multiworld.random.sample(TotalSMZ3Location.AvailableGlobal(TotalSMZ3Location.Empty(self.smz3World.Locations), self.smz3World.Items()), 1)), None) if (location == None): raise Exception(f"Tried to front fill {item.Name} in, but no location was available") location.Item = item - itemFromPool = next((i for i in self.world.itempool if i.player == self.player and i.name == item.Type.name and i.advancement == item.Progression), None) + itemFromPool = next((i for i in self.multiworld.itempool if i.player == self.player and i.name == item.Type.name and i.advancement == item.Progression), None) if itemFromPool is not None: - self.world.get_location(location.Name, self.player).place_locked_item(itemFromPool) - self.world.itempool.remove(itemFromPool) + self.multiworld.get_location(location.Name, self.player).place_locked_item(itemFromPool) + self.multiworld.itempool.remove(itemFromPool) itemPool.remove(item) def InitialFillInOwnWorld(self): @@ -621,7 +621,7 @@ class SMZ3World(World): def create_region(self, world: MultiWorld, player: int, name: str, locations=None, exits=None): ret = Region(name, RegionType.LightWorld, name, player) - ret.world = world + ret.multiworld = world if locations: for loc in locations: location = self.locations[loc] diff --git a/worlds/soe/__init__.py b/worlds/soe/__init__.py index 007bc6dc..9f250391 100644 --- a/worlds/soe/__init__.py +++ b/worlds/soe/__init__.py @@ -178,11 +178,11 @@ class SoEWorld(World): def generate_early(self) -> None: # store option values that change logic - self.energy_core = self.world.energy_core[self.player].value - self.required_fragments = self.world.required_fragments[self.player].value - if self.required_fragments > self.world.available_fragments[self.player].value: - self.world.available_fragments[self.player].value = self.required_fragments - self.available_fragments = self.world.available_fragments[self.player].value + self.energy_core = self.multiworld.energy_core[self.player].value + self.required_fragments = self.multiworld.required_fragments[self.player].value + if self.required_fragments > self.multiworld.available_fragments[self.player].value: + self.multiworld.available_fragments[self.player].value = self.required_fragments + self.available_fragments = self.multiworld.available_fragments[self.player].value def create_event(self, event: str) -> Item: return SoEItem(event, ItemClassification.progression, None, self.player) @@ -209,12 +209,12 @@ class SoEWorld(World): def create_regions(self): # exclude 'hidden' on easy - max_difficulty = 1 if self.world.difficulty[self.player] == Difficulty.option_easy else 256 + max_difficulty = 1 if self.multiworld.difficulty[self.player] == Difficulty.option_easy else 256 # TODO: generate *some* regions from locations' requirements? - r = Region('Menu', RegionType.Generic, 'Menu', self.player, self.world) + r = Region('Menu', RegionType.Generic, 'Menu', self.player, self.multiworld) r.exits = [Entrance(self.player, 'New Game', r)] - self.world.regions += [r] + self.multiworld.regions += [r] # group locations into spheres (1, 2, 3+ at index 0, 1, 2) spheres: typing.Dict[int, typing.Dict[int, typing.List[SoELocation]]] = {} @@ -232,8 +232,8 @@ class SoEWorld(World): # mark some as excluded based on numbers above for trash_sphere, fills in trash_fills.items(): for typ, counts in fills.items(): - count = counts[self.world.difficulty[self.player].value] - for location in self.world.random.sample(spheres[trash_sphere][typ], count): + count = counts[self.multiworld.difficulty[self.player].value] + for location in self.multiworld.random.sample(spheres[trash_sphere][typ], count): location.progress_type = LocationProgressType.EXCLUDED # TODO: do we need to set an item rule? @@ -243,7 +243,7 @@ class SoEWorld(World): if item.name in {"Gauge", "Wheel"}: return False # and some more for non-easy, non-mystery - if self.world.difficulty[item.player] not in (Difficulty.option_easy, Difficulty.option_mystery): + if self.multiworld.difficulty[item.player] not in (Difficulty.option_easy, Difficulty.option_mystery): if item.name in {"Laser Lance", "Atom Smasher", "Diamond Eye"}: return False return True @@ -253,16 +253,16 @@ class SoEWorld(World): add_item_rule(location, sphere1_blocked_items_rule) # make some logically late(r) bosses priority locations to increase complexity - if self.world.difficulty[self.player] == Difficulty.option_mystery: - late_count = self.world.random.randint(0, 2) + if self.multiworld.difficulty[self.player] == Difficulty.option_mystery: + late_count = self.multiworld.random.randint(0, 2) else: - late_count = self.world.difficulty[self.player].value + late_count = self.multiworld.difficulty[self.player].value late_bosses = ("Tiny", "Aquagoth", "Megataur", "Rimsala", "Mungola", "Lightning Storm", "Magmar", "Volcano Viper") - late_locations = self.world.random.sample(late_bosses, late_count) + late_locations = self.multiworld.random.sample(late_bosses, late_count) # add locations to the world - r = Region('Ingame', RegionType.Generic, 'Ingame', self.player, self.world) + r = Region('Ingame', RegionType.Generic, 'Ingame', self.player, self.multiworld) for sphere in spheres.values(): for locations in sphere.values(): for location in locations: @@ -271,9 +271,9 @@ class SoEWorld(World): location.progress_type = LocationProgressType.PRIORITY r.locations.append(SoELocation(self.player, 'Done', None, r)) - self.world.regions += [r] + self.multiworld.regions += [r] - self.world.get_entrance('New Game', self.player).connect(self.world.get_region('Ingame', self.player)) + self.multiworld.get_entrance('New Game', self.player).connect(self.multiworld.get_region('Ingame', self.player)) def create_items(self): # add regular items to the pool @@ -298,17 +298,17 @@ class SoEWorld(World): for _ in range(self.available_fragments - 1): if len(ingredients) < 1: break # out of ingredients to replace - r = self.world.random.choice(ingredients) + r = self.multiworld.random.choice(ingredients) ingredients.remove(r) items[r] = self.create_item("Energy Core Fragment") # add traps to the pool - trap_count = self.world.trap_count[self.player].value + trap_count = self.multiworld.trap_count[self.player].value trap_chances = {} trap_names = {} if trap_count > 0: for trap_type in self.trap_types: - trap_option = getattr(self.world, f'trap_chance_{trap_type}')[self.player] + trap_option = getattr(self.multiworld, f'trap_chance_{trap_type}')[self.player] trap_chances[trap_type] = trap_option.value trap_names[trap_type] = trap_option.item_name trap_chances_total = sum(trap_chances.values()) @@ -318,7 +318,7 @@ class SoEWorld(World): trap_chances_total = len(trap_chances) def create_trap() -> Item: - v = self.world.random.randrange(trap_chances_total) + v = self.multiworld.random.randrange(trap_chances_total) for t, c in trap_chances.items(): if v < c: return self.create_item(trap_names[t]) @@ -328,26 +328,26 @@ class SoEWorld(World): for _ in range(trap_count): if len(ingredients) < 1: break # out of ingredients to replace - r = self.world.random.choice(ingredients) + r = self.multiworld.random.choice(ingredients) ingredients.remove(r) items[r] = create_trap() - self.world.itempool += items + self.multiworld.itempool += items def set_rules(self): - self.world.completion_condition[self.player] = lambda state: state.has('Victory', self.player) + self.multiworld.completion_condition[self.player] = lambda state: state.has('Victory', self.player) # set Done from goal option once we have multiple goals - set_rule(self.world.get_location('Done', self.player), - lambda state: state.soe_has(pyevermizer.P_FINAL_BOSS, self.world, self.player)) - set_rule(self.world.get_entrance('New Game', self.player), lambda state: True) + set_rule(self.multiworld.get_location('Done', self.player), + lambda state: state.soe_has(pyevermizer.P_FINAL_BOSS, self.multiworld, self.player)) + set_rule(self.multiworld.get_entrance('New Game', self.player), lambda state: True) for loc in _locations: - location = self.world.get_location(loc.name, self.player) + location = self.multiworld.get_location(loc.name, self.player) set_rule(location, self.make_rule(loc.requires)) def make_rule(self, requires: typing.List[typing.Tuple[int, int]]) -> typing.Callable[[typing.Any], bool]: def rule(state) -> bool: for count, progress in requires: - if not state.soe_has(progress, self.world, self.player, count): + if not state.soe_has(progress, self.multiworld, self.player, count): return False return True @@ -358,20 +358,20 @@ class SoEWorld(World): def generate_basic(self): # place Victory event - self.world.get_location('Done', self.player).place_locked_item(self.create_event('Victory')) + self.multiworld.get_location('Done', self.player).place_locked_item(self.create_event('Victory')) # place wings in halls NE to avoid softlock - wings_location = self.world.random.choice(self._halls_ne_chest_names) + wings_location = self.multiworld.random.choice(self._halls_ne_chest_names) wings_item = self.create_item('Wings') - self.world.get_location(wings_location, self.player).place_locked_item(wings_item) + self.multiworld.get_location(wings_location, self.player).place_locked_item(wings_item) # place energy core at vanilla location for vanilla mode if self.energy_core == EnergyCore.option_vanilla: energy_core = self.create_item('Energy Core') - self.world.get_location('Energy Core #285', self.player).place_locked_item(energy_core) + self.multiworld.get_location('Energy Core #285', self.player).place_locked_item(energy_core) # generate stuff for later - self.evermizer_seed = self.world.random.randint(0, 2 ** 16 - 1) # TODO: make this an option for "full" plando? + self.evermizer_seed = self.multiworld.random.randint(0, 2 ** 16 - 1) # TODO: make this an option for "full" plando? def generate_output(self, output_directory: str): - player_name = self.world.get_player_name(self.player) + player_name = self.multiworld.get_player_name(self.player) self.connect_name = player_name[:32] while len(self.connect_name.encode('utf-8')) > 32: self.connect_name = self.connect_name[:-1] @@ -379,27 +379,27 @@ class SoEWorld(World): placement_file = "" out_file = "" try: - money = self.world.money_modifier[self.player].value - exp = self.world.exp_modifier[self.player].value + money = self.multiworld.money_modifier[self.player].value + exp = self.multiworld.exp_modifier[self.player].value switches: typing.List[str] = [] - if self.world.death_link[self.player].value: + if self.multiworld.death_link[self.player].value: switches.append("--death-link") if self.energy_core == EnergyCore.option_fragments: switches.extend(('--available-fragments', str(self.available_fragments), '--required-fragments', str(self.required_fragments))) rom_file = get_base_rom_path() - out_base = output_path(output_directory, self.world.get_out_file_name_base(self.player)) + out_base = output_path(output_directory, self.multiworld.get_out_file_name_base(self.player)) out_file = out_base + '.sfc' placement_file = out_base + '.txt' patch_file = out_base + '.apsoe' flags = 'l' # spoiler log for option_name in self.option_definitions: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] if hasattr(option, 'to_flag'): flags += option.to_flag() with open(placement_file, "wb") as f: # generate placement file - for location in filter(lambda l: l.player == self.player, self.world.get_locations()): + for location in filter(lambda l: l.player == self.player, self.multiworld.get_locations()): item = location.item assert item is not None, "Can't handle unfilled location" if item.code is None or location.address is None: @@ -414,7 +414,7 @@ class SoEWorld(World): if not os.path.exists(rom_file): raise FileNotFoundError(rom_file) - if (pyevermizer.main(rom_file, out_file, placement_file, self.world.seed_name, self.connect_name, + if (pyevermizer.main(rom_file, out_file, placement_file, self.multiworld.seed_name, self.connect_name, self.evermizer_seed, flags, money, exp, switches)): raise RuntimeError() patch = SoEDeltaPatch(patch_file, player=self.player, @@ -434,12 +434,12 @@ class SoEWorld(World): # wait for self.connect_name to be available. self.connect_name_available_event.wait() # we skip in case of error, so that the original error in the output thread is the one that gets raised - if self.connect_name and self.connect_name != self.world.player_name[self.player]: - payload = multidata["connect_names"][self.world.player_name[self.player]] + if self.connect_name and self.connect_name != self.multiworld.player_name[self.player]: + payload = multidata["connect_names"][self.multiworld.player_name[self.player]] multidata["connect_names"][self.connect_name] = payload def get_filler_item_name(self) -> str: - return self.world.random.choice(list(self.item_name_groups["Ingredients"])) + return self.multiworld.random.choice(list(self.item_name_groups["Ingredients"])) class SoEItem(Item): diff --git a/worlds/spire/__init__.py b/worlds/spire/__init__.py index 476afad8..d923ce75 100644 --- a/worlds/spire/__init__.py +++ b/worlds/spire/__init__.py @@ -40,10 +40,10 @@ class SpireWorld(World): def _get_slot_data(self): return { - 'seed': "".join(self.world.slot_seeds[self.player].choice(string.ascii_letters) for i in range(16)), - 'character': self.world.character[self.player], - 'ascension': self.world.ascension[self.player], - 'heart_run': self.world.heart_run[self.player] + 'seed': "".join(self.multiworld.slot_seeds[self.player].choice(string.ascii_letters) for i in range(16)), + 'character': self.multiworld.character[self.player], + 'ascension': self.multiworld.ascension[self.player], + 'heart_run': self.multiworld.heart_run[self.player] } def generate_basic(self): @@ -55,40 +55,40 @@ class SpireWorld(World): item = SpireItem(name, self.player) pool.append(item) - self.world.itempool += pool + self.multiworld.itempool += pool # Pair up our event locations with our event items for event, item in event_item_pairs.items(): event_item = SpireItem(item, self.player) - self.world.get_location(event, self.player).place_locked_item(event_item) + self.multiworld.get_location(event, self.player).place_locked_item(event_item) - if self.world.logic[self.player] != 'no logic': - self.world.completion_condition[self.player] = lambda state: state.has("Victory", self.player) + if self.multiworld.logic[self.player] != 'no logic': + self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) def set_rules(self): - set_rules(self.world, self.player) + set_rules(self.multiworld, self.player) def create_item(self, name: str) -> Item: return SpireItem(name, self.player) def create_regions(self): - create_regions(self.world, self.player) + create_regions(self.multiworld, self.player) def fill_slot_data(self) -> dict: slot_data = self._get_slot_data() for option_name in spire_options: - option = getattr(self.world, option_name)[self.player] + option = getattr(self.multiworld, option_name)[self.player] slot_data[option_name] = int(option.value) return slot_data def get_filler_item_name(self) -> str: - return self.world.random.choice(["Card Draw", "Card Draw", "Card Draw", "Relic", "Relic"]) + return self.multiworld.random.choice(["Card Draw", "Card Draw", "Card Draw", "Relic", "Relic"]) def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None): ret = Region(name, RegionType.Generic, name, player) - ret.world = world + ret.multiworld = world if locations: for location in locations: loc_id = location_table.get(location, 0) diff --git a/worlds/subnautica/Rules.py b/worlds/subnautica/Rules.py index 8925f1e8..544b9a2b 100644 --- a/worlds/subnautica/Rules.py +++ b/worlds/subnautica/Rules.py @@ -277,7 +277,7 @@ aggression_rules: Dict[int, Callable[["CollectionState", int], bool]] = { def set_rules(subnautica_world: "SubnauticaWorld"): player = subnautica_world.player - world = subnautica_world.world + world = subnautica_world.multiworld for loc in location_table.values(): set_location_rule(world, player, loc) diff --git a/worlds/subnautica/__init__.py b/worlds/subnautica/__init__.py index bd86dc5c..d421fe49 100644 --- a/worlds/subnautica/__init__.py +++ b/worlds/subnautica/__init__.py @@ -47,22 +47,22 @@ class SubnauticaWorld(World): creatures_to_scan: List[str] def generate_early(self) -> None: - if "Seaglide Fragment" not in self.world.early_items[self.player]: - self.world.early_items[self.player].value["Seaglide Fragment"] = 2 + if "Seaglide Fragment" not in self.multiworld.early_items[self.player]: + self.multiworld.early_items[self.player].value["Seaglide Fragment"] = 2 - scan_option: Options.AggressiveScanLogic = self.world.creature_scan_logic[self.player] + scan_option: Options.AggressiveScanLogic = self.multiworld.creature_scan_logic[self.player] creature_pool = scan_option.get_pool() - self.world.creature_scans[self.player].value = min( + self.multiworld.creature_scans[self.player].value = min( len(creature_pool), - self.world.creature_scans[self.player].value + self.multiworld.creature_scans[self.player].value ) - self.creatures_to_scan = self.world.random.sample(creature_pool, - self.world.creature_scans[self.player].value) + self.creatures_to_scan = self.multiworld.random.sample(creature_pool, + self.multiworld.creature_scans[self.player].value) def create_regions(self): - self.world.regions += [ + self.multiworld.regions += [ self.create_region("Menu", None, ["Lifepod 5"]), self.create_region("Planet 4546B", Locations.events + @@ -75,13 +75,13 @@ class SubnauticaWorld(World): def generate_basic(self): # Link regions - self.world.get_entrance("Lifepod 5", self.player).connect(self.world.get_region("Planet 4546B", self.player)) + self.multiworld.get_entrance("Lifepod 5", self.player).connect(self.multiworld.get_region("Planet 4546B", self.player)) # Generate item pool pool = [] neptune_launch_platform = None - extras = self.world.creature_scans[self.player].value - valuable = self.world.item_pool[self.player] == Options.ItemPool.option_valuable + extras = self.multiworld.creature_scans[self.player].value + valuable = self.multiworld.item_pool[self.player] == Options.ItemPool.option_valuable for item in item_table.values(): for i in range(item["count"]): subnautica_item = self.create_item(item["name"]) @@ -92,26 +92,26 @@ class SubnauticaWorld(World): else: pool.append(subnautica_item) - for item_name in self.world.random.choices(sorted(Items.advancement_item_names - {"Neptune Launch Platform"}), - k=extras): + for item_name in self.multiworld.random.choices(sorted(Items.advancement_item_names - {"Neptune Launch Platform"}), + k=extras): item = self.create_item(item_name) item.classification = ItemClassification.filler # as it's an extra, just fast-fill it somewhere pool.append(item) - self.world.itempool += pool + self.multiworld.itempool += pool # Victory item - self.world.get_location("Aurora - Captain Data Terminal", self.player).place_locked_item( + self.multiworld.get_location("Aurora - Captain Data Terminal", self.player).place_locked_item( neptune_launch_platform) for event in Locations.events: - self.world.get_location(event, self.player).place_locked_item( + self.multiworld.get_location(event, self.player).place_locked_item( SubnauticaItem(event, ItemClassification.progression, None, player=self.player)) # make the goal event the victory "item" - self.world.get_location(self.world.goal[self.player].get_event_name(), self.player).item.name = "Victory" + self.multiworld.get_location(self.multiworld.goal[self.player].get_event_name(), self.player).item.name = "Victory" def fill_slot_data(self) -> Dict[str, Any]: - goal: Options.Goal = self.world.goal[self.player] - item_pool: Options.ItemPool = self.world.item_pool[self.player] + goal: Options.Goal = self.multiworld.goal[self.player] + item_pool: Options.ItemPool = self.multiworld.item_pool[self.player] vanilla_tech: List[str] = [] if item_pool == Options.ItemPool.option_valuable: for item in Items.item_table.values(): @@ -122,7 +122,7 @@ class SubnauticaWorld(World): "goal": goal.current_key, "vanilla_tech": vanilla_tech, "creatures_to_scan": self.creatures_to_scan, - "death_link": self.world.death_link[self.player].value, + "death_link": self.multiworld.death_link[self.player].value, } return slot_data @@ -136,7 +136,7 @@ class SubnauticaWorld(World): def create_region(self, name: str, locations=None, exits=None): ret = Region(name, RegionType.Generic, name, self.player) - ret.world = self.world + ret.multiworld = self.multiworld if locations: for location in locations: loc_id = self.location_name_to_id.get(location, None) diff --git a/worlds/timespinner/Regions.py b/worlds/timespinner/Regions.py index 098657b4..cd9c6b4c 100644 --- a/worlds/timespinner/Regions.py +++ b/worlds/timespinner/Regions.py @@ -197,7 +197,7 @@ def create_location(player: int, location_data: LocationData, region: Region, lo def create_region(world: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]], location_cache: List[Location], name: str) -> Region: region = Region(name, RegionType.Generic, name, player) - region.world = world + region.multiworld = world if name in locations_per_region: for location_data in locations_per_region[name]: diff --git a/worlds/timespinner/__init__.py b/worlds/timespinner/__init__.py index c8b94a27..b93f1004 100644 --- a/worlds/timespinner/__init__.py +++ b/worlds/timespinner/__init__.py @@ -64,47 +64,47 @@ class TimespinnerWorld(World): def generate_early(self): # in generate_early the start_inventory isnt copied over to precollected_items yet, so we can still modify the options directly - if self.world.start_inventory[self.player].value.pop('Meyef', 0) > 0: - self.world.StartWithMeyef[self.player].value = self.world.StartWithMeyef[self.player].option_true - if self.world.start_inventory[self.player].value.pop('Talaria Attachment', 0) > 0: - self.world.QuickSeed[self.player].value = self.world.QuickSeed[self.player].option_true - if self.world.start_inventory[self.player].value.pop('Jewelry Box', 0) > 0: - self.world.StartWithJewelryBox[self.player].value = self.world.StartWithJewelryBox[self.player].option_true + if self.multiworld.start_inventory[self.player].value.pop('Meyef', 0) > 0: + self.multiworld.StartWithMeyef[self.player].value = self.multiworld.StartWithMeyef[self.player].option_true + if self.multiworld.start_inventory[self.player].value.pop('Talaria Attachment', 0) > 0: + self.multiworld.QuickSeed[self.player].value = self.multiworld.QuickSeed[self.player].option_true + if self.multiworld.start_inventory[self.player].value.pop('Jewelry Box', 0) > 0: + self.multiworld.StartWithJewelryBox[self.player].value = self.multiworld.StartWithJewelryBox[self.player].option_true def create_regions(self): - create_regions(self.world, self.player, get_locations(self.world, self.player), - self.location_cache, self.pyramid_keys_unlock) + create_regions(self.multiworld, self.player, get_locations(self.multiworld, self.player), + self.location_cache, self.pyramid_keys_unlock) def create_item(self, name: str) -> Item: - return create_item_with_correct_settings(self.world, self.player, name) + return create_item_with_correct_settings(self.multiworld, self.player, name) def get_filler_item_name(self) -> str: - return self.world.random.choice(filler_items) + return self.multiworld.random.choice(filler_items) def set_rules(self): setup_events(self.player, self.locked_locations, self.location_cache) - self.world.completion_condition[self.player] = lambda state: state.has('Killed Nightmare', self.player) + self.multiworld.completion_condition[self.player] = lambda state: state.has('Killed Nightmare', self.player) def generate_basic(self): - excluded_items = get_excluded_items(self, self.world, self.player) + excluded_items = get_excluded_items(self, self.multiworld, self.player) - assign_starter_items(self.world, self.player, excluded_items, self.locked_locations) + assign_starter_items(self.multiworld, self.player, excluded_items, self.locked_locations) - if not is_option_enabled(self.world, self.player, "QuickSeed") and not is_option_enabled(self.world, self.player, "Inverted"): - place_first_progression_item(self.world, self.player, excluded_items, self.locked_locations) + if not is_option_enabled(self.multiworld, self.player, "QuickSeed") and not is_option_enabled(self.multiworld, self.player, "Inverted"): + place_first_progression_item(self.multiworld, self.player, excluded_items, self.locked_locations) - pool = get_item_pool(self.world, self.player, excluded_items) + pool = get_item_pool(self.multiworld, self.player, excluded_items) - fill_item_pool_with_dummy_items(self, self.world, self.player, self.locked_locations, self.location_cache, pool) + fill_item_pool_with_dummy_items(self, self.multiworld, self.player, self.locked_locations, self.location_cache, pool) - self.world.itempool += pool + self.multiworld.itempool += pool def fill_slot_data(self) -> Dict[str, object]: slot_data: Dict[str, object] = {} for option_name in timespinner_options: - slot_data[option_name] = get_option_value(self.world, self.player, option_name) + slot_data[option_name] = get_option_value(self.multiworld, self.player, option_name) slot_data["StinkyMaw"] = True slot_data["ProgressiveVerticalMovement"] = False diff --git a/worlds/v6/__init__.py b/worlds/v6/__init__.py index 9c5fdbc8..5434ceec 100644 --- a/worlds/v6/__init__.py +++ b/worlds/v6/__init__.py @@ -44,42 +44,42 @@ class V6World(World): option_definitions = v6_options def create_regions(self): - create_regions(self.world,self.player) + create_regions(self.multiworld, self.player) def set_rules(self): self.area_connections = {} self.area_cost_map = {} - set_rules(self.world, self.player, self.area_connections, self.area_cost_map) + set_rules(self.multiworld, self.player, self.area_connections, self.area_cost_map) def create_item(self, name: str) -> Item: return V6Item(name, ItemClassification.progression, item_table[name], self.player) def generate_basic(self): trinkets = [self.create_item("Trinket " + str(i+1).zfill(2)) for i in range(0,20)] - self.world.itempool += trinkets + self.multiworld.itempool += trinkets musiclist_o = [1,2,3,4,9,12] musiclist_s = musiclist_o.copy() - if self.world.MusicRandomizer[self.player].value: - self.world.random.shuffle(musiclist_s) + if self.multiworld.MusicRandomizer[self.player].value: + self.multiworld.random.shuffle(musiclist_s) self.music_map = dict(zip(musiclist_o, musiclist_s)) def fill_slot_data(self): return { "MusicRando": self.music_map, "AreaRando": self.area_connections, - "DoorCost": self.world.DoorCost[self.player].value, + "DoorCost": self.multiworld.DoorCost[self.player].value, "AreaCostRando": self.area_cost_map, - "DeathLink": self.world.death_link[self.player].value, - "DeathLink_Amnesty": self.world.DeathLinkAmnesty[self.player].value + "DeathLink": self.multiworld.death_link[self.player].value, + "DeathLink_Amnesty": self.multiworld.DeathLinkAmnesty[self.player].value } def generate_output(self, output_directory: str): - if self.world.players != 1: + if self.multiworld.players != 1: return data = { "slot_data": self.fill_slot_data(), - "location_to_item": {self.location_name_to_id[i.name] : item_table[i.item.name] for i in self.world.get_locations()}, + "location_to_item": {self.location_name_to_id[i.name] : item_table[i.item.name] for i in self.multiworld.get_locations()}, "data_package": { "data": { "games": { @@ -91,6 +91,6 @@ class V6World(World): } } } - filename = f"{self.world.get_out_file_name_base(self.player)}.apv6" + filename = f"{self.multiworld.get_out_file_name_base(self.player)}.apv6" with open(os.path.join(output_directory, filename), 'w') as f: json.dump(data, f) diff --git a/worlds/witness/__init__.py b/worlds/witness/__init__.py index d4e9a597..758870a2 100644 --- a/worlds/witness/__init__.py +++ b/worlds/witness/__init__.py @@ -54,7 +54,7 @@ class WitnessWorld(World): def _get_slot_data(self): return { - 'seed': self.world.random.randint(0, 1000000), + 'seed': self.multiworld.random.randint(0, 1000000), 'victory_location': int(self.player_logic.VICTORY_LOCATION, 16), 'panelhex_to_id': self.locat.CHECK_PANELHEX_TO_ID, 'item_id_to_door_hexes': self.items.ITEM_ID_TO_DOOR_HEX, @@ -66,19 +66,19 @@ class WitnessWorld(World): } def generate_early(self): - if not (is_option_enabled(self.world, self.player, "shuffle_symbols") - or get_option_value(self.world, self.player, "shuffle_doors") - or is_option_enabled(self.world, self.player, "shuffle_lasers")): - if self.world.players == 1: + if not (is_option_enabled(self.multiworld, self.player, "shuffle_symbols") + or get_option_value(self.multiworld, self.player, "shuffle_doors") + or is_option_enabled(self.multiworld, self.player, "shuffle_lasers")): + if self.multiworld.players == 1: warning("This Witness world doesn't have any progression items. Please turn on Symbol Shuffle, Door" " Shuffle or Laser Shuffle if that doesn't seem right.") else: raise Exception("This Witness world doesn't have any progression items. Please turn on Symbol Shuffle," " Door Shuffle or Laser Shuffle.") - self.player_logic = WitnessPlayerLogic(self.world, self.player) - self.locat = WitnessPlayerLocations(self.world, self.player, self.player_logic) - self.items = WitnessPlayerItems(self.locat, self.world, self.player, self.player_logic) + self.player_logic = WitnessPlayerLogic(self.multiworld, self.player) + self.locat = WitnessPlayerLocations(self.multiworld, self.player, self.player_logic) + self.items = WitnessPlayerItems(self.locat, self.multiworld, self.player, self.player_logic) self.regio = WitnessRegions(self.locat) self.log_ids_to_hints = dict() @@ -99,12 +99,12 @@ class WitnessWorld(World): less_junk = 0 # Put good item on first check if symbol shuffle is on - symbols = is_option_enabled(self.world, self.player, "shuffle_symbols") + symbols = is_option_enabled(self.multiworld, self.player, "shuffle_symbols") - if symbols and get_option_value(self.world, self.player, "puzzle_randomization") != 1: - random_good_item = self.world.random.choice(self.items.GOOD_ITEMS) + if symbols and get_option_value(self.multiworld, self.player, "puzzle_randomization") != 1: + random_good_item = self.multiworld.random.choice(self.items.GOOD_ITEMS) - first_check = self.world.get_location( + first_check = self.multiworld.get_location( "Tutorial Gate Open", self.player ) first_check.place_locked_item(items_by_name[random_good_item]) @@ -113,7 +113,7 @@ class WitnessWorld(World): less_junk = 1 for item in self.player_logic.STARTING_INVENTORY: - self.world.push_precollected(items_by_name[item]) + self.multiworld.push_precollected(items_by_name[item]) pool.remove(items_by_name[item]) for item in self.items.EXTRA_AMOUNTS: @@ -133,28 +133,28 @@ class WitnessWorld(World): item_obj = self.create_item( self.player_logic.EVENT_ITEM_PAIRS[event_location] ) - location_obj = self.world.get_location(event_location, self.player) + location_obj = self.multiworld.get_location(event_location, self.player) location_obj.place_locked_item(item_obj) - self.world.itempool += pool + self.multiworld.itempool += pool def create_regions(self): - self.regio.create_regions(self.world, self.player, self.player_logic) + self.regio.create_regions(self.multiworld, self.player, self.player_logic) def set_rules(self): - set_rules(self.world, self.player, self.player_logic, self.locat) + set_rules(self.multiworld, self.player, self.player_logic, self.locat) def fill_slot_data(self) -> dict: - hint_amount = get_option_value(self.world, self.player, "hint_amount") + hint_amount = get_option_value(self.multiworld, self.player, "hint_amount") credits_hint = ("This Randomizer", "is brought to you by", "NewSoupVi, Jarno, jbzdarkid, sigma144", -1) audio_logs = get_audio_logs().copy() if hint_amount != 0: - generated_hints = make_hints(self.world, self.player, hint_amount) + generated_hints = make_hints(self.multiworld, self.player, hint_amount) - self.world.random.shuffle(audio_logs) + self.multiworld.random.shuffle(audio_logs) duplicates = len(audio_logs) // hint_amount @@ -169,7 +169,7 @@ class WitnessWorld(World): audio_log = audio_logs.pop() self.log_ids_to_hints[int(audio_log, 16)] = credits_hint - joke_hints = generate_joke_hints(self.world, len(audio_logs)) + joke_hints = generate_joke_hints(self.multiworld, len(audio_logs)) while audio_logs: audio_log = audio_logs.pop() @@ -181,7 +181,7 @@ class WitnessWorld(World): for option_name in the_witness_options: slot_data[option_name] = get_option_value( - self.world, self.player, option_name + self.multiworld, self.player, option_name ) return slot_data @@ -234,7 +234,7 @@ def create_region(world: MultiWorld, player: int, name: str, """ ret = Region(name, RegionType.Generic, name, player) - ret.world = world + ret.multiworld = world if region_locations: for location in region_locations: loc_id = locat.CHECK_LOCATION_TABLE[location] diff --git a/worlds/zillion/__init__.py b/worlds/zillion/__init__.py index 918b91ec..91e19c6c 100644 --- a/worlds/zillion/__init__.py +++ b/worlds/zillion/__init__.py @@ -121,10 +121,10 @@ class ZillionWorld(World): raise FileNotFoundError(rom_file) def generate_early(self) -> None: - if not hasattr(self.world, "zillion_logic_cache"): - setattr(self.world, "zillion_logic_cache", {}) + if not hasattr(self.multiworld, "zillion_logic_cache"): + setattr(self.multiworld, "zillion_logic_cache", {}) - zz_op, item_counts = validate(self.world, self.player) + zz_op, item_counts = validate(self.multiworld, self.player) self._item_counts = item_counts @@ -148,7 +148,7 @@ class ZillionWorld(World): assert self.zz_system.randomizer, "generate_early hasn't been called" assert self.id_to_zz_item, "generate_early hasn't been called" p = self.player - w = self.world + w = self.multiworld self.my_locations = [] self.zz_system.randomizer.place_canister_gun_reqs() @@ -159,7 +159,7 @@ class ZillionWorld(World): for here_zz_name, zz_r in self.zz_system.randomizer.regions.items(): here_name = "Menu" if here_zz_name == "start" else zz_reg_name_to_reg_name(here_zz_name) all[here_name] = ZillionRegion(zz_r, here_name, RegionType.Generic, here_name, p, w) - self.world.regions.append(all[here_name]) + self.multiworld.regions.append(all[here_name]) limited_skill = Req(gun=3, jump=3, skill=self.zz_system.randomizer.options.skill, hp=940, red=1, floppy=126) queue = deque([start]) @@ -191,7 +191,7 @@ class ZillionWorld(World): loc.access_rule = access_rule if not (limited_skill >= zz_loc.req): loc.progress_type = LocationProgressType.EXCLUDED - self.world.exclude_locations[p].value.add(loc.name) + self.multiworld.exclude_locations[p].value.add(loc.name) here.locations.append(loc) self.my_locations.append(loc) @@ -222,11 +222,11 @@ class ZillionWorld(World): if item_name in item_counts: count = item_counts[item_name] self.logger.debug(f"Zillion Items: {item_name} {count}") - self.world.itempool += [self.create_item(item_name) for _ in range(count)] + self.multiworld.itempool += [self.create_item(item_name) for _ in range(count)] elif item_id < (3 + base_id) and zz_item.code == RESCUE: # One of the 3 rescues will not be in the pool and its zz_item will be 'empty'. self.logger.debug(f"Zillion Items: {item_name} 1") - self.world.itempool.append(self.create_item(item_name)) + self.multiworld.itempool.append(self.create_item(item_name)) def set_rules(self) -> None: # logic for this game is in create_regions @@ -237,9 +237,9 @@ class ZillionWorld(World): # main location name is an alias main_loc_name = self.zz_system.randomizer.loc_name_2_pretty[self.zz_system.randomizer.locations['main'].name] - self.world.get_location(main_loc_name, self.player)\ + self.multiworld.get_location(main_loc_name, self.player)\ .place_locked_item(self.create_item("Win")) - self.world.completion_condition[self.player] = \ + self.multiworld.completion_condition[self.player] = \ lambda state: state.has("Win", self.player) @staticmethod @@ -295,7 +295,7 @@ class ZillionWorld(World): empty = zz_items[4] multi_item = empty # a different patcher method differentiates empty from ap multi item multi_items: Dict[str, Tuple[str, str]] = {} # zz_loc_name to (item_name, player_name) - for loc in self.world.get_locations(): + for loc in self.multiworld.get_locations(): if loc.player == self.player: z_loc = cast(ZillionLocation, loc) # debug_zz_loc_ids[z_loc.zz_loc.name] = id(z_loc.zz_loc) @@ -310,7 +310,7 @@ class ZillionWorld(World): z_loc.zz_loc.item = multi_item multi_items[z_loc.zz_loc.name] = ( z_loc.item.name, - self.world.get_player_name(z_loc.item.player) + self.multiworld.get_player_name(z_loc.item.player) ) # debug_zz_loc_ids.sort() # for name, id_ in debug_zz_loc_ids.items(): @@ -340,7 +340,7 @@ class ZillionWorld(World): zz_patcher.all_fixes_and_options(zz_options) zz_patcher.set_external_item_interface(zz_options.start_char, zz_options.max_level) zz_patcher.set_multiworld_items(multi_items) - game_id = self.world.player_name[self.player].encode() + b'\x00' + self.world.seed_name[-6:].encode() + game_id = self.multiworld.player_name[self.player].encode() + b'\x00' + self.multiworld.seed_name[-6:].encode() zz_patcher.set_rom_to_ram_data(game_id) def generate_output(self, output_directory: str) -> None: @@ -352,7 +352,7 @@ class ZillionWorld(World): # original_rom_bytes = self.zz_patcher.rom patched_rom_bytes = self.zz_system.patcher.get_patched_bytes() - out_file_base = self.world.get_out_file_name_base(self.player) + out_file_base = self.multiworld.get_out_file_name_base(self.player) filename = os.path.join( output_directory, @@ -363,7 +363,7 @@ class ZillionWorld(World): patch = ZillionDeltaPatch( os.path.splitext(filename)[0] + ZillionDeltaPatch.patch_file_ending, player=self.player, - player_name=self.world.player_name[self.player], + player_name=self.multiworld.player_name[self.player], patched_path=filename ) patch.write() @@ -401,7 +401,7 @@ class ZillionWorld(World): # def modify_multidata(self, multidata: Dict[str, Any]) -> None: # """For deeper modification of server multidata.""" # # not modifying multidata, just want to call this at the end of the generation process - # cache = getattr(self.world, "zillion_logic_cache") + # cache = getattr(self.multiworld, "zillion_logic_cache") # import sys # print(sys.getsizeof(cache)) @@ -409,7 +409,7 @@ class ZillionWorld(World): def create_item(self, name: str) -> Item: """Create an item for this world type and player. - Warning: this may be called with self.world = None, for example by MultiServer""" + Warning: this may be called with self.multiworld = None, for example by MultiServer""" item_id = _item_name_to_id[name] if not self.id_to_zz_item: diff --git a/worlds/zillion/logic.py b/worlds/zillion/logic.py index 01ed1434..204f2425 100644 --- a/worlds/zillion/logic.py +++ b/worlds/zillion/logic.py @@ -18,7 +18,7 @@ def set_randomizer_locs(cs: CollectionState, p: int, zz_r: Randomizer) -> int: returns a hash of the player and of the set locations with their items """ - z_world = cs.world.worlds[p] + z_world = cs.multiworld.worlds[p] my_locations = cast(List[ZillionLocation], getattr(z_world, "my_locations")) _hash = p @@ -50,7 +50,7 @@ def cs_to_zz_locs(cs: CollectionState, p: int, zz_r: Randomizer, id_to_zz_item: returns frozenset of accessible zilliandomizer locations """ # caching this function because it would be slow - logic_cache: LogicCacheType = getattr(cs.world, "zillion_logic_cache", {}) + logic_cache: LogicCacheType = getattr(cs.multiworld, "zillion_logic_cache", {}) _hash = set_randomizer_locs(cs, p, zz_r) counts = item_counts(cs, p) _hash += hash(counts)