diff --git a/BaseClasses.py b/BaseClasses.py index 11a94f2b..9b153e8d 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -13,7 +13,7 @@ class World(object): self.shuffle = shuffle self.logic = logic.copy() self.mode = mode.copy() - self.swords = swords + self.swords = swords.copy() self.difficulty = difficulty self.difficulty_adjustments = difficulty_adjustments self.timer = timer @@ -1080,6 +1080,7 @@ class Spoiler(object): outfile.write('ALttP Entrance Randomizer Version %s - Seed: %s\n\n' % (self.metadata['version'], self.world.seed)) outfile.write('Logic: %s\n' % self.metadata['logic']) outfile.write('Mode: %s\n' % self.metadata['mode']) + outfile.write('Swords: %s\n' % self.metadata['weapons']) outfile.write('Goal: %s\n' % self.metadata['goal']) outfile.write('Difficulty: %s\n' % self.metadata['item_pool']) outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality']) diff --git a/Bosses.py b/Bosses.py index a4b9b313..ff9d0be4 100644 --- a/Bosses.py +++ b/Bosses.py @@ -73,7 +73,7 @@ def KholdstareDefeatRule(state, player): ( state.has('Bombos', player) and # FIXME: the following only actually works for the vanilla location for swordless - (state.has_sword(player) or state.world.swords == 'swordless') + (state.has_sword(player) or state.world.swords[player] == 'swordless') ) ) and ( @@ -83,7 +83,7 @@ def KholdstareDefeatRule(state, player): ( state.has('Fire Rod', player) and state.has('Bombos', player) and - state.world.swords == 'swordless' and + state.world.swords[player] == 'swordless' and state.can_extend_magic(player, 16) ) ) @@ -115,8 +115,8 @@ boss_table = { 'Agahnim2': ('Agahnim2', AgahnimDefeatRule) } -def can_place_boss(world, boss, dungeon_name, level=None): - if world.swords in ['swordless'] and boss == 'Kholdstare' and dungeon_name != 'Ice Palace': +def can_place_boss(world, player, boss, dungeon_name, level=None): + if world.swords[player] in ['swordless'] and boss == 'Kholdstare' and dungeon_name != 'Ice Palace': return False if dungeon_name in ['Ganons Tower', 'Inverted Ganons Tower'] and level == 'top': @@ -179,7 +179,7 @@ def place_bosses(world, player): if world.boss_shuffle in ["basic", "normal"]: # temporary hack for swordless kholdstare: - if world.swords == 'swordless': + if world.swords[player] == 'swordless': world.get_dungeon('Ice Palace', player).boss = BossFactory('Kholdstare', player) logging.getLogger('').debug('Placing boss Kholdstare at Ice Palace') boss_locations.remove(['Ice Palace', None]) @@ -195,7 +195,7 @@ def place_bosses(world, player): random.shuffle(bosses) for [loc, level] in boss_locations: loc_text = loc + (' ('+level+')' if level else '') - boss = next((b for b in bosses if can_place_boss(world, b, loc, level)), None) + boss = next((b for b in bosses if can_place_boss(world, player, b, loc, level)), None) if not boss: raise FillError('Could not place boss for location %s' % loc_text) bosses.remove(boss) @@ -206,7 +206,7 @@ def place_bosses(world, player): for [loc, level] in boss_locations: loc_text = loc + (' ('+level+')' if level else '') try: - boss = random.choice([b for b in placeable_bosses if can_place_boss(world, b, loc, level)]) + boss = random.choice([b for b in placeable_bosses if can_place_boss(world, player, b, loc, level)]) except IndexError: raise FillError('Could not place boss for location %s' % loc_text) diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index bba20536..b0134025 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -278,16 +278,13 @@ def parse_arguments(argv, no_defaults=False): for player in range(1, multiargs.multi + 1): playerargs = parse_arguments(shlex.split(getattr(ret,f"p{player}")), True) - def set_player_arg(name): + for name in ['logic', 'mode', 'swords']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: setattr(ret, name, {1: value}) else: getattr(ret, name)[player] = value - set_player_arg("logic") - set_player_arg("mode") - return ret def start(): diff --git a/ItemList.py b/ItemList.py index 706a7c4a..a9e89d59 100644 --- a/ItemList.py +++ b/ItemList.py @@ -177,10 +177,10 @@ def generate_itempool(world, player): # set up item pool if world.custom: - (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle, world.difficulty, world.timer, world.goal, world.mode[player], world.swords, world.retro, world.customitemarray) + (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive, world.shuffle, world.difficulty, world.timer, world.goal, world.mode[player], world.swords[player], world.retro, world.customitemarray) world.rupoor_cost = min(world.customitemarray[69], 9999) else: - (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle, world.difficulty, world.timer, world.goal, world.mode[player], world.swords, world.retro) + (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = get_pool_core(world.progressive, world.shuffle, world.difficulty, world.timer, world.goal, world.mode[player], world.swords[player], world.retro) for item in precollected_items: world.push_precollected(ItemFactory(item, player)) @@ -191,7 +191,7 @@ def generate_itempool(world, player): possible_weapons = [] for item in pool: if item in ['Progressive Sword', 'Fighter Sword', 'Master Sword', 'Tempered Sword', 'Golden Sword']: - if not found_sword and world.swords != 'swordless': + if not found_sword and world.swords[player] != 'swordless': found_sword = True possible_weapons.append(item) if item in ['Progressive Bow', 'Bow'] and not found_bow: diff --git a/Rom.py b/Rom.py index 44642afc..ff77fd5a 100644 --- a/Rom.py +++ b/Rom.py @@ -706,7 +706,7 @@ def patch_rom(world, player, rom, enemized): difficulty.progressive_bottle_limit, mw_bottle_replacements[difficulty.progressive_bottle_limit] if world.players > 1 else overflow_replacement, difficulty.progressive_bow_limit, mw_bow_replacements[difficulty.progressive_bow_limit] if world.players > 1 else overflow_replacement]) - if difficulty.progressive_bow_limit < 2 and world.swords == 'swordless': + if difficulty.progressive_bow_limit < 2 and world.swords[player] == 'swordless': rom.write_bytes(0x180098, [2, mw_bow_replacements[difficulty.progressive_bow_limit] if world.players > 1 else overflow_replacement]) rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon @@ -826,11 +826,11 @@ def patch_rom(world, player, rom, enemized): rom.write_byte(0x180029, 0x01) # Smithy quick item give # set swordless mode settings - rom.write_byte(0x18003F, 0x01 if world.swords == 'swordless' else 0x00) # hammer can harm ganon - rom.write_byte(0x180040, 0x01 if world.swords == 'swordless' else 0x00) # open curtains - rom.write_byte(0x180041, 0x01 if world.swords == 'swordless' else 0x00) # swordless medallions - rom.write_byte(0x180043, 0xFF if world.swords == 'swordless' else 0x00) # starting sword for link - rom.write_byte(0x180044, 0x01 if world.swords == 'swordless' else 0x00) # hammer activates tablets + rom.write_byte(0x18003F, 0x01 if world.swords[player] == 'swordless' else 0x00) # hammer can harm ganon + rom.write_byte(0x180040, 0x01 if world.swords[player] == 'swordless' else 0x00) # open curtains + rom.write_byte(0x180041, 0x01 if world.swords[player] == 'swordless' else 0x00) # swordless medallions + rom.write_byte(0x180043, 0xFF if world.swords[player] == 'swordless' else 0x00) # starting sword for link + rom.write_byte(0x180044, 0x01 if world.swords[player] == 'swordless' else 0x00) # hammer activates tablets # set up clocks for timed modes if world.shuffle == 'vanilla': diff --git a/Rules.py b/Rules.py index 2e42403d..7027c96c 100644 --- a/Rules.py +++ b/Rules.py @@ -458,7 +458,7 @@ def default_rules(world, player): set_rule(world.get_entrance('Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid) set_rule(world.get_entrance('Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic. - if world.swords == 'swordless': + if world.swords[player] == 'swordless': swordless_rules(world, player) set_trock_key_rules(world, player) @@ -613,7 +613,7 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: state.has('Beat Agahnim 2', player) or world.open_pyramid) set_rule(world.get_entrance('Inverted Ganons Tower', player), lambda state: False) # This is a safety for the TR function below to not require GT entrance in its key logic. - if world.swords == 'swordless': + if world.swords[player] == 'swordless': swordless_rules(world, player) set_trock_key_rules(world, player)