diff --git a/Main.py b/Main.py index 733ede35..fcd401af 100644 --- a/Main.py +++ b/Main.py @@ -12,16 +12,12 @@ from typing import Dict, Tuple from BaseClasses import MultiWorld, CollectionState, Region, Item from worlds.alttp.Items import item_name_groups -from worlds.alttp.Regions import create_regions, mark_light_world_regions, \ - lookup_vanilla_location_to_entrance -from worlds.alttp.InvertedRegions import create_inverted_regions, mark_dark_world_regions -from worlds.alttp.EntranceShuffle import link_entrances, link_inverted_entrances, plando_connect +from worlds.alttp.Regions import lookup_vanilla_location_to_entrance from worlds.alttp.Rom import patch_rom, patch_race_rom, patch_enemizer, apply_rom_settings, LocalRom, get_hash_string -from worlds.alttp.Rules import set_rules -from worlds.alttp.Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive +from worlds.alttp.Dungeons import fill_dungeons, fill_dungeons_restrictive from Fill import distribute_items_restrictive, flood_items, balance_multiworld_progression, distribute_planned -from worlds.alttp.Shops import create_shops, ShopSlotFill, SHOP_ID_START, total_shop_slots, FillDisabledShopSlots -from worlds.alttp.ItemPool import generate_itempool, difficulties, fill_prizes +from worlds.alttp.Shops import ShopSlotFill, SHOP_ID_START, total_shop_slots, FillDisabledShopSlots +from worlds.alttp.ItemPool import difficulties, fill_prizes from Utils import output_path, parse_player_names, get_options, __version__, version_tuple from worlds.generic.Rules import locality_rules, exclusion_rules from worlds import AutoWorld @@ -195,56 +191,11 @@ def main(args, seed=None): # items can't be both local and non-local, prefer local world.non_local_items[player] -= world.local_items[player] + logger.info('Creating World.') AutoWorld.call_all(world, "create_regions") - for player in world.get_game_players("A Link to the Past"): - if world.open_pyramid[player] == 'goal': - world.open_pyramid[player] = world.goal[player] in {'crystals', 'ganontriforcehunt', - 'localganontriforcehunt', 'ganonpedestal'} - elif world.open_pyramid[player] == 'auto': - world.open_pyramid[player] = world.goal[player] in {'crystals', 'ganontriforcehunt', - 'localganontriforcehunt', 'ganonpedestal'} and \ - (world.shuffle[player] in {'vanilla', 'dungeonssimple', 'dungeonsfull', - 'dungeonscrossed'} or not world.shuffle_ganon) - else: - world.open_pyramid[player] = {'on': True, 'off': False, 'yes': True, 'no': False}.get( - world.open_pyramid[player], 'auto') - - world.triforce_pieces_available[player] = max(world.triforce_pieces_available[player], - world.triforce_pieces_required[player]) - - if world.mode[player] != 'inverted': - create_regions(world, player) - else: - create_inverted_regions(world, player) - create_shops(world, player) - create_dungeons(world, player) - - logger.info('Shuffling the World about.') - - for player in world.get_game_players("A Link to the Past"): - if world.logic[player] not in ["noglitches", "minorglitches"] and world.shuffle[player] in \ - {"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}: - world.fix_fake_world[player] = False - - # seeded entrance shuffle - old_random = world.random - world.random = random.Random(world.er_seeds[player]) - - if world.mode[player] != 'inverted': - link_entrances(world, player) - mark_light_world_regions(world, player) - else: - link_inverted_entrances(world, player) - mark_dark_world_regions(world, player) - - world.random = old_random - plando_connect(world, player) - - logger.info('Generating Item Pool.') - - for player in world.get_game_players("A Link to the Past"): - generate_itempool(world, player) + logger.info('Creating Items.') + AutoWorld.call_all(world, "create_items") logger.info('Calculating Access Rules.') if world.players > 1: @@ -253,9 +204,6 @@ def main(args, seed=None): AutoWorld.call_all(world, "set_rules") - for player in world.get_game_players("A Link to the Past"): - set_rules(world, player) - for player in world.player_ids: exclusion_rules(world, player, args.excluded_locations[player]) diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py index ca2529ac..ccbdeb77 100644 --- a/worlds/AutoWorld.py +++ b/worlds/AutoWorld.py @@ -82,13 +82,16 @@ class World(metaclass=AutoWorldRegister): self.world = world self.player = player - # overwritable methods that get called by Main.py, sorted by execution order + # overridable methods that get called by Main.py, sorted by execution order def generate_early(self): pass def create_regions(self): pass + def create_items(self): + pass + def set_rules(self): pass @@ -100,7 +103,7 @@ class World(metaclass=AutoWorldRegister): If you need any last-second randomization, use MultiWorld.slot_seeds[slot] instead.""" pass - def fill_slot_data(self): + def fill_slot_data(self) -> dict: """Fill in the slot_data field in the Connected network package.""" return {} diff --git a/worlds/alttp/ItemPool.py b/worlds/alttp/ItemPool.py index 45103836..4dfa75eb 100644 --- a/worlds/alttp/ItemPool.py +++ b/worlds/alttp/ItemPool.py @@ -222,7 +222,9 @@ for diff in {'easy', 'normal', 'hard', 'expert'}: ) -def generate_itempool(world, player: int): +def generate_itempool(world): + player = world.player + world = world.world if world.difficulty[player] not in difficulties: raise NotImplementedError(f"Diffulty {world.difficulty[player]}") if world.goal[player] not in {'ganon', 'pedestal', 'bosses', 'triforcehunt', 'localtriforcehunt', 'icerodhunt', diff --git a/worlds/alttp/Rules.py b/worlds/alttp/Rules.py index 6cf41d11..49d06400 100644 --- a/worlds/alttp/Rules.py +++ b/worlds/alttp/Rules.py @@ -10,7 +10,9 @@ from worlds.generic.Rules import set_rule, add_rule, forbid_item, add_item_rule, item_name -def set_rules(world, player): +def set_rules(world): + player = world.player + world = world.world if world.logic[player] == 'nologic': logging.info( 'WARNING! Seeds generated under this logic often require major glitches and may be impossible!') diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py index 89a49b01..7a1261eb 100644 --- a/worlds/alttp/__init__.py +++ b/worlds/alttp/__init__.py @@ -1,10 +1,18 @@ +import random + from BaseClasses import Item, CollectionState from .SubClasses import ALttPItem from ..AutoWorld import World from .Options import alttp_options from .Items import as_dict_item_table, item_name_groups, item_table -from .Regions import lookup_name_to_id +from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions +from .Rules import set_rules +from .ItemPool import generate_itempool +from .Shops import create_shops +from .Dungeons import create_dungeons +from .InvertedRegions import create_inverted_regions, mark_dark_world_regions +from .EntranceShuffle import link_entrances, link_inverted_entrances, plando_connect class ALTTPWorld(World): game: str = "A Link to the Past" @@ -21,6 +29,54 @@ class ALTTPWorld(World): data_version = 7 remote_items: bool = False + set_rules = set_rules + + create_items = generate_itempool + + def create_regions(self): + world = self.world + for player in world.get_game_players("A Link to the Past"): + if world.open_pyramid[player] == 'goal': + world.open_pyramid[player] = world.goal[player] in {'crystals', 'ganontriforcehunt', + 'localganontriforcehunt', 'ganonpedestal'} + elif world.open_pyramid[player] == 'auto': + world.open_pyramid[player] = world.goal[player] in {'crystals', 'ganontriforcehunt', + 'localganontriforcehunt', 'ganonpedestal'} and \ + (world.shuffle[player] in {'vanilla', 'dungeonssimple', 'dungeonsfull', + 'dungeonscrossed'} or not world.shuffle_ganon) + else: + world.open_pyramid[player] = {'on': True, 'off': False, 'yes': True, 'no': False}.get( + world.open_pyramid[player], 'auto') + + world.triforce_pieces_available[player] = max(world.triforce_pieces_available[player], + world.triforce_pieces_required[player]) + + if world.mode[player] != 'inverted': + create_regions(world, player) + else: + create_inverted_regions(world, player) + create_shops(world, player) + create_dungeons(world, player) + + for player in world.get_game_players("A Link to the Past"): + if world.logic[player] not in ["noglitches", "minorglitches"] and world.shuffle[player] in \ + {"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}: + world.fix_fake_world[player] = False + + # seeded entrance shuffle + old_random = world.random + world.random = random.Random(world.er_seeds[player]) + + if world.mode[player] != 'inverted': + link_entrances(world, player) + mark_light_world_regions(world, player) + else: + link_inverted_entrances(world, player) + mark_dark_world_regions(world, player) + + world.random = old_random + plando_connect(world, player) + def collect(self, state: CollectionState, item: Item) -> bool: if item.name.startswith('Progressive '): if 'Sword' in item.name: diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index 6d942fca..a98fbc59 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -25,7 +25,7 @@ class Factorio(World): item_name_to_id = tech_table location_name_to_id = base_tech_table - def generate_basic(self): + def create_items(self): for tech_name in base_tech_table: if self.world.progressive: item_name = tech_to_progressive_lookup.get(tech_name, tech_name)