From 01f0f309d1a7ee669eba3f9ccfa8793814c71b60 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Thu, 15 Jul 2021 08:50:08 +0200 Subject: [PATCH] add AutoWorld.generate_early, optimize Location --- BaseClasses.py | 31 ++++++++++++++++++------------- Main.py | 4 +++- worlds/AutoWorld.py | 3 +++ worlds/factorio/__init__.py | 5 ++--- worlds/minecraft/Regions.py | 2 +- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index e06d9b69..a913026e 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -139,7 +139,6 @@ class MultiWorld(): self.custom_data = {} self.worlds = {} - def set_options(self, args): from worlds import AutoWorld for player in self.player_ids: @@ -564,6 +563,12 @@ class CollectionState(object): def has(self, item, player: int, count: int = 1): return self.prog_items[item, player] >= count + def has_all(self, items: Set[str], player:int): + return all(self.prog_items[item, player] for item in items) + + def has_any(self, items: Set[str], player:int): + return any(self.prog_items[item, player] for item in items) + def has_essence(self, player: int, count: int): return self.prog_items["Dream_Nail", player] # return self.prog_items["Essence", player] >= count @@ -927,7 +932,8 @@ class CollectionState(object): self.stale[item.player] = True @unique -class RegionType(Enum): +class RegionType(int, Enum): + Generic = 0 LightWorld = 1 DarkWorld = 2 Cave = 3 # Also includes Houses @@ -941,7 +947,7 @@ class RegionType(Enum): class Region(object): - def __init__(self, name: str, type, hint, player: int): + def __init__(self, name: str, type, hint, player: int, world: Optional[MultiWorld] = None): self.name = name self.type = type self.entrances = [] @@ -949,7 +955,7 @@ class Region(object): self.locations = [] self.dungeon = None self.shop = None - self.world = None + self.world = world self.is_light_world = False # will be set after making connections. self.is_dark_world = False self.spot_type = 'Region' @@ -957,7 +963,7 @@ class Region(object): self.recursion_count = 0 self.player = player - def can_reach(self, state): + def can_reach(self, state: CollectionState): if state.stale[self.player]: state.update_reachable_regions(self.player) return self in state.reachable_regions[self.player] @@ -1085,17 +1091,16 @@ class Location(): spot_type = 'Location' game: str = "Generic" crystal: bool = False + always_allow = staticmethod(lambda item, state: False) + access_rule = staticmethod(lambda state: True) + item_rule = staticmethod(lambda item: True) def __init__(self, player: int, name: str = '', address:int = None, parent=None): - self.name = name - self.address = address + self.name: str = name + self.address: Optional[int] = address self.parent_region: Region = parent - self.recursion_count = 0 - self.player = player - self.item = None - self.always_allow = lambda item, state: False - self.access_rule = lambda state: True - self.item_rule = lambda item: True + self.player: int = player + self.item: Optional[Item] = None def can_fill(self, state: CollectionState, item: Item, check_access=True) -> bool: return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) diff --git a/Main.py b/Main.py index 7c925337..44f1a6d9 100644 --- a/Main.py +++ b/Main.py @@ -122,9 +122,11 @@ def main(args, seed=None): world.set_options(args) world.glitch_triforce = args.glitch_triforce # This is enabled/disabled globally, no per player option. - world.slot_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in + world.slot_seeds = {player: random.Random(world.random.getrandbits(64)) for player in range(1, world.players + 1)} + AutoWorld.call_all(world, "generate_early") + # system for sharing ER layouts for player in world.alttp_player_ids: world.er_seeds[player] = str(world.random.randint(0, 2 ** 64)) diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py index 0ac75900..220c4418 100644 --- a/worlds/AutoWorld.py +++ b/worlds/AutoWorld.py @@ -69,6 +69,9 @@ class World(metaclass=AutoWorldRegister): self.player = player # overwritable methods that get called by Main.py, sorted by execution order + def generate_early(self): + pass + def create_regions(self): pass diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index 622eaf7a..eaf907a1 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -44,11 +44,10 @@ class Factorio(World): def create_regions(self): player = self.player - menu = Region("Menu", None, "Menu", player) + menu = Region("Menu", None, "Menu", player, self.world) crash = Entrance(player, "Crash Land", menu) menu.exits.append(crash) - nauvis = Region("Nauvis", None, "Nauvis", player) - nauvis.world = menu.world = self.world + nauvis = Region("Nauvis", None, "Nauvis", player, self.world) for tech_name, tech_id in base_tech_table.items(): tech = Location(player, tech_name, tech_id, nauvis) diff --git a/worlds/minecraft/Regions.py b/worlds/minecraft/Regions.py index c35d2b7c..682ad032 100644 --- a/worlds/minecraft/Regions.py +++ b/worlds/minecraft/Regions.py @@ -14,7 +14,7 @@ def link_minecraft_structures(world, player): assert len(exits) == len(structs) except AssertionError as e: # this should never happen raise Exception(f"Could not obtain equal numbers of Minecraft exits and structures for player {player} ({world.player_names[player]})") - num_regions = len(exits) + pairs = {} def set_pair(exit, struct):