def fill_dungeons_restrictive(world, shuffled_locations): all_state_base = world.get_all_state() # with shuffled dungeon items they are distributed as part of the normal item pool for item in world.get_items(): if (item.smallkey and world.keyshuffle[item.player]) or ( item.bigkey and world.bigkeyshuffle[item.player]): all_state_base.collect(item, True) item.advancement = True elif (item.map and world.mapshuffle[item.player]) or ( item.compass and world.compassshuffle[item.player]): item.priority = True dungeon_items = [ item for item in get_dungeon_item_pool(world) if ((item.smallkey and not world.keyshuffle[item.player]) or ( item.bigkey and not world.bigkeyshuffle[item.player]) or ( item.map and not world.mapshuffle[item.player]) or ( item.compass and not world.compassshuffle[item.player])) ] # sort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items, True)
def test_restrictive_progress(self): multi_world = generate_multi_world() player1 = generate_player_data(multi_world, 1, prog_item_count=25) items = player1.prog_items.copy() multi_world.completion_condition[ player1.id] = lambda state: state.has_all( names(player1.prog_items), player1.id) player1.generate_region(player1.menu, 5) player1.generate_region( player1.menu, 5, lambda state: state.has_all(names(items[2:7]), player1.id)) player1.generate_region( player1.menu, 5, lambda state: state.has_all(names(items[7:12]), player1.id)) player1.generate_region( player1.menu, 5, lambda state: state.has_all(names(items[12:17]), player1.id)) player1.generate_region( player1.menu, 5, lambda state: state.has_all(names(items[17:22]), player1.id)) locations = multi_world.get_unfilled_locations() fill_restrictive(multi_world, multi_world.state, locations, player1.prog_items)
def pre_fill(self): from Fill import fill_restrictive self.InitialFillInOwnWorld() if (not self.smz3World.Config.Keysanity): locations = [loc for loc in self.locations.values() if loc.item is None] self.world.random.shuffle(locations) all_state = self.world.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) # 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': 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): item.classification = ItemClassification.filler item.item.Progression = False item.location.event = False self.unreachable.append(item.location)
def fill_dungeons_restrictive(world, shuffled_locations): all_state_base = world.get_all_state() for player in range(1, world.players + 1): pinball_room = world.get_location('Skull Woods - Pinball Room', player) if world.retro: world.push_item(pinball_room, ItemFactory('Small Key (Universal)', player), False) else: world.push_item(pinball_room, ItemFactory('Small Key (Skull Woods)', player), False) pinball_room.event = True pinball_room.locked = True shuffled_locations.remove(pinball_room) if world.keysanity: #in keysanity dungeon items are distributed as part of the normal item pool for item in world.get_items(): if item.key: item.advancement = True elif item.map or item.compass: item.priority = True return dungeon_items = get_dungeon_item_pool(world) # sort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items)
def fill_dungeons_restrictive(world, shuffled_locations): all_state_base = world.get_all_state() skull_woods_big_chest = world.get_location('Skull Woods - Pinball Room') if world.retro: world.push_item(skull_woods_big_chest, ItemFactory('Small Key (Universal)'), False) else: world.push_item(skull_woods_big_chest, ItemFactory('Small Key (Skull Woods)'), False) skull_woods_big_chest.event = True shuffled_locations.remove(skull_woods_big_chest) if world.keysanity: #in keysanity dungeon items are distributed as part of the normal item pool for item in world.get_items(): if item.key: item.advancement = True elif item.map or item.compass: item.priority = True return dungeon_items = get_dungeon_item_pool(world) # sort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items) world.state.clear_cached_unreachable()
def fill_prizes(world, attempts=15): all_state = world.get_all_state(keys=True) for player in range(1, world.players + 1): crystals = ItemFactory(['Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5', 'Crystal 6'], player) crystal_locations = [world.get_location('Turtle Rock - Prize', player), world.get_location('Eastern Palace - Prize', player), world.get_location('Desert Palace - Prize', player), world.get_location('Tower of Hera - Prize', player), world.get_location('Palace of Darkness - Prize', player), world.get_location('Thieves\' Town - Prize', player), world.get_location('Skull Woods - Prize', player), world.get_location('Swamp Palace - Prize', player), world.get_location('Ice Palace - Prize', player), world.get_location('Misery Mire - Prize', player)] placed_prizes = [loc.item.name for loc in crystal_locations if loc.item is not None] unplaced_prizes = [crystal for crystal in crystals if crystal.name not in placed_prizes] empty_crystal_locations = [loc for loc in crystal_locations if loc.item is None] for attempt in range(attempts): try: prizepool = list(unplaced_prizes) prize_locs = list(empty_crystal_locations) world.random.shuffle(prizepool) world.random.shuffle(prize_locs) fill_restrictive(world, all_state, prize_locs, prizepool, True) except FillError as e: logging.getLogger('').exception("Failed to place dungeon prizes (%s). Will retry %s more times", e, attempts - attempt) for location in empty_crystal_locations: location.item = None continue break else: raise FillError('Unable to place dungeon prizes')
def pre_fill(self): from Fill import fill_restrictive, FillError attempts = 5 world = self.world 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' ] ] crystal_locations = [ world.get_location('Turtle Rock - Prize', player), world.get_location('Eastern Palace - Prize', player), world.get_location('Desert Palace - Prize', player), world.get_location('Tower of Hera - Prize', player), world.get_location('Palace of Darkness - Prize', player), world.get_location('Thieves\' Town - Prize', player), world.get_location('Skull Woods - Prize', player), world.get_location('Swamp Palace - Prize', player), world.get_location('Ice Palace - Prize', player), world.get_location('Misery Mire - Prize', player) ] placed_prizes = { loc.item.name for loc in crystal_locations if loc.item } unplaced_prizes = [ crystal for crystal in crystals if crystal.name not in placed_prizes ] empty_crystal_locations = [ loc for loc in crystal_locations if not loc.item ] for attempt in range(attempts): try: prizepool = unplaced_prizes.copy() prize_locs = empty_crystal_locations.copy() world.random.shuffle(prize_locs) fill_restrictive(world, all_state, prize_locs, prizepool, True, lock=True) except FillError as e: lttp_logger.exception( "Failed to place dungeon prizes (%s). Will retry %s more times", e, attempts - attempt) for location in empty_crystal_locations: location.item = None continue break else: raise FillError('Unable to place dungeon prizes')
def fill_dungeons_restrictive(world, shuffled_locations): all_state_base = world.get_all_state() dungeon_items = get_dungeon_item_pool(world) # sort in the order Boss Key, Small Key, Other before placing dungeon items sort_order = {"BossKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items) world.state.clear_cached_unreachable()
def fill_dungeons_restrictive(world): """Places dungeon-native items into their dungeons, places nothing if everything is shuffled outside.""" localized: set = set() dungeon_specific: set = set() for subworld in world.get_game_worlds("A Link to the Past"): player = subworld.player localized |= {(player, item_name) for item_name in subworld.dungeon_local_item_names} dungeon_specific |= { (player, item_name) for item_name in subworld.dungeon_specific_item_names } if localized: in_dungeon_items = [ item for item in get_dungeon_item_pool(world) if (item.player, item.name) in localized ] if in_dungeon_items: restricted_players = { player for player, restricted in world.restrict_dungeon_item_on_boss.items() if restricted } locations = [ location for location in world.get_unfilled_dungeon_locations() # filter boss if not (location.player in restricted_players and location.name in lookup_boss_drops) ] if dungeon_specific: for location in locations: dungeon = location.parent_region.dungeon orig_rule = location.item_rule location.item_rule = lambda item, dungeon=dungeon, orig_rule=orig_rule: \ (not (item.player, item.name) in dungeon_specific or item.dungeon is dungeon) and orig_rule(item) world.random.shuffle(locations) all_state_base = world.get_all_state(use_cache=True) # Dungeon-locked items have to be placed first, to not run out of spaces for dungeon-locked items # subsort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} in_dungeon_items.sort( key=lambda item: sort_order.get(item.type, 1) + (5 if (item.player, item.name) in dungeon_specific else 0)) for item in in_dungeon_items: all_state_base.remove(item) fill_restrictive(world, all_state_base, locations, in_dungeon_items, True, True)
def test_ordered_fill(self): multi_world = generate_multi_world() player1 = generate_player_data(multi_world, 1, 2, 2) items = player1.prog_items locations = player1.locations multi_world.completion_condition[player1.id] = lambda state: state.has( items[0].name, player1.id) and state.has(items[1].name, player1.id) set_rule(locations[1], lambda state: state.has(items[0].name, player1.id)) fill_restrictive(multi_world, multi_world.state, player1.locations.copy(), player1.prog_items.copy()) self.assertEqual(locations[0].item, items[0]) self.assertEqual(locations[1].item, items[1])
def test_basic_fill(self): multi_world = generate_multi_world() player1 = generate_player_data(multi_world, 1, 2, 2) item0 = player1.prog_items[0] item1 = player1.prog_items[1] loc0 = player1.locations[0] loc1 = player1.locations[1] fill_restrictive(multi_world, multi_world.state, player1.locations, player1.prog_items) self.assertEqual(loc0.item, item1) self.assertEqual(loc1.item, item0) self.assertEqual([], player1.locations) self.assertEqual([], player1.prog_items)
def test_reversed_fill(self): multi_world = generate_multi_world() player1 = generate_player_data(multi_world, 1, 2, 2) item0 = player1.prog_items[0] item1 = player1.prog_items[1] loc0 = player1.locations[0] loc1 = player1.locations[1] multi_world.completion_condition[player1.id] = lambda state: state.has( item0.name, player1.id) and state.has(item1.name, player1.id) set_rule(loc1, lambda state: state.has(item1.name, player1.id)) fill_restrictive(multi_world, multi_world.state, player1.locations, player1.prog_items) self.assertEqual(loc0.item, item1) self.assertEqual(loc1.item, item0)
def fill_dungeons_restrictive(world, shuffled_locations): all_state_base = world.get_all_state() skull_woods_big_chest = world.get_location('Skull Woods - Pinball Room') world.push_item(skull_woods_big_chest, ItemFactory('Small Key (Skull Woods)'), False) skull_woods_big_chest.event = True shuffled_locations.remove(skull_woods_big_chest) dungeon_items = [item for dungeon in world.dungeons for item in dungeon.all_items if item.key or world.place_dungeon_items] # sort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items) world.state._clear_cache()
def generate_basic(self): self.world.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.create_item("Agate Knife")) self.world.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.create_event("Full Victory")) for boss in ["Meridian", "Ataraxia", "Merodach"]: self.world.get_location(f"{boss} Defeat", self.player).place_locked_item( self.create_event(f"{boss} Defeated")) if not self.include_psi_keys: psi_keys = [] 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(f"PSI Key Storage {i + 1}", self.player) ] fill_restrictive(self.world, self.world.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.create_item("Evolution Trap")) if self.goal == 0: self.world.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("Full Victory", self. player)
def fill_dungeons_restrictive(world, shuffled_locations): all_state_base = world.get_all_state() # for player in range(1, world.players + 1): # pinball_room = world.get_location('Skull Woods - Pinball Room', player) # if world.retro[player]: # world.push_item(pinball_room, ItemFactory('Small Key (Universal)', player), False) # else: # world.push_item(pinball_room, ItemFactory('Small Key (Skull Woods)', player), False) # pinball_room.event = True # pinball_room.locked = True # shuffled_locations.remove(pinball_room) # with shuffled dungeon items they are distributed as part of the normal item pool for item in world.get_items(): if (item.smallkey and world.keyshuffle[item.player]) or ( item.bigkey and world.bigkeyshuffle[item.player]): item.advancement = True elif (item.map and world.mapshuffle[item.player]) or ( item.compass and world.compassshuffle[item.player]): item.priority = True dungeon_items = [ item for item in get_dungeon_item_pool(world) if ((item.smallkey and not world.keyshuffle[item.player]) or ( item.bigkey and not world.bigkeyshuffle[item.player]) or ( item.map and not world.mapshuffle[item.player]) or ( item.compass and not world.compassshuffle[item.player])) ] # sort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items, keys_in_itempool={ player: not world.keyshuffle[player] for player in range(1, world.players + 1) }, single_player_placement=True)
def fill_songs(world, attempts=15): songs = ItemFactory(songlist) song_locations = [ world.get_location('Song from Composer Grave'), world.get_location('Impa at Castle'), world.get_location('Song from Malon'), world.get_location('Song from Saria'), world.get_location('Song from Ocarina of Time'), world.get_location('Song at Windmill'), world.get_location('Sheik Forest Song'), world.get_location('Sheik at Temple'), world.get_location('Sheik in Crater'), world.get_location('Sheik in Ice Cavern'), world.get_location('Sheik in Kakariko'), world.get_location('Sheik at Colossus') ] placed_prizes = [ loc.item.name for loc in song_locations if loc.item is not None ] unplaced_prizes = [ song for song in songs if song.name not in placed_prizes ] empty_song_locations = [loc for loc in song_locations if loc.item is None] while attempts: attempts -= 1 try: prizepool = list(unplaced_prizes) prize_locs = list(empty_song_locations) random.shuffle(prizepool) random.shuffle(prize_locs) fill_restrictive( world, world.get_all_state(keys=True), prize_locs, prizepool ) #TODO: Set keys to true once keys are properly implemented except FillError: logging.getLogger('').info( "Failed to place songs. Will retry %s more times", attempts) for location in empty_song_locations: location.item = None continue break else: raise FillError('Unable to place songs')
def fill_dungeons_restrictive(world, shuffled_locations): all_state_base = world.get_all_state() for player in range(1, world.players + 1): if not world.retro[ player] and world.logic == "noglitches" and not world.keyshuffle[ player]: skull_woods = world.get_dungeon('Skull Woods', player) skull_woods.small_keys.pop() pinball_room = world.get_location('Skull Woods - Pinball Room', player) world.push_item(pinball_room, ItemFactory('Small Key (Skull Woods)', player), False) pinball_room.event = True pinball_room.locked = True shuffled_locations.remove(pinball_room) # with shuffled dungeon items they are distributed as part of the normal item pool for item in world.get_items(): if (item.smallkey and world.keyshuffle[item.player]) or ( item.bigkey and world.bigkeyshuffle[item.player]): all_state_base.collect(item, True) item.advancement = True elif (item.map and world.mapshuffle[item.player]) or ( item.compass and world.compassshuffle[item.player]): item.priority = True dungeon_items = [ item for item in get_dungeon_item_pool(world) if ((item.smallkey and not world.keyshuffle[item.player]) or ( item.bigkey and not world.bigkeyshuffle[item.player]) or ( item.map and not world.mapshuffle[item.player]) or ( item.compass and not world.compassshuffle[item.player])) ] # sort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items, True)
def fill_songs(world, attempts=15): songs = ItemFactory(songlist) song_locations = [ world.get_location('Song from Skull Kid'), world.get_location('Song from HMS'), world.get_location('Song from Owl Tablet'), world.get_location('Song from Romani'), world.get_location('Song at Grave'), world.get_location('Song from Monkey'), world.get_location('Song from Baby Goron'), world.get_location('Song from Goron Elder'), world.get_location('Song from Zora Eggs'), world.get_location('Song from Igos'), world.get_location('Song from the Giants') ] placed_prizes = [ loc.item.name for loc in song_locations if loc.item is not None ] unplaced_prizes = [ song for song in songs if song.name not in placed_prizes ] empty_song_locations = [loc for loc in song_locations if loc.item is None] while attempts: attempts -= 1 try: prizepool = list(unplaced_prizes) prize_locs = list(empty_song_locations) random.shuffle(prizepool) random.shuffle(prize_locs) fill_restrictive( world, world.get_all_state(keys=True), prize_locs, prizepool ) #TODO: Set keys to true once keys are properly implemented except FillError: logging.getLogger('').info( "Failed to place songs. Will retry %s more times", attempts) for location in empty_song_locations: location.item = None continue break else: raise FillError('Unable to place songs')
def test_multiplayer_fill(self): multi_world = generate_multi_world(2) player1 = generate_player_data(multi_world, 1, 2, 2) player2 = generate_player_data(multi_world, 2, 2, 2) multi_world.completion_condition[player1.id] = lambda state: state.has( player1.prog_items[0].name, player1.id) and state.has( player1.prog_items[1].name, player1.id) multi_world.completion_condition[player2.id] = lambda state: state.has( player2.prog_items[0].name, player2.id) and state.has( player2.prog_items[1].name, player2.id) fill_restrictive(multi_world, multi_world.state, player1.locations + player2.locations, player1.prog_items + player2.prog_items) self.assertEqual(player1.locations[0].item, player1.prog_items[1]) self.assertEqual(player1.locations[1].item, player2.prog_items[1]) self.assertEqual(player2.locations[0].item, player1.prog_items[0]) self.assertEqual(player2.locations[1].item, player2.prog_items[0])
def test_minimal_fill(self): multi_world = generate_multi_world() player1 = generate_player_data(multi_world, 1, 2, 2) items = player1.prog_items locations = player1.locations multi_world.accessibility[ player1.id].value = multi_world.accessibility[ player1.id].option_minimal multi_world.completion_condition[ player1.id] = lambda state: state.has(items[1].name, player1.id) set_rule(locations[1], lambda state: state.has(items[0].name, player1.id)) fill_restrictive(multi_world, multi_world.state, player1.locations.copy(), player1.prog_items.copy()) self.assertEqual(locations[0].item, items[1]) # Unnecessary unreachable Item self.assertEqual(locations[1].item, items[0])
def fill_dungeons_restrictive(world): """Places dungeon-native items into their dungeons, places nothing if everything is shuffled outside.""" restricted_players = { player for player, restricted in world.restrict_dungeon_item_on_boss.items() if restricted } locations = [ location for location in world.get_unfilled_dungeon_locations() if not (location.player in restricted_players and location.name in lookup_boss_drops) ] # filter boss world.random.shuffle(locations) all_state_base = world.get_all_state() # with shuffled dungeon items they are distributed as part of the normal item pool for item in world.get_items(): if (item.smallkey and world.keyshuffle[item.player]) or ( item.bigkey and world.bigkeyshuffle[item.player]): all_state_base.collect(item, True) item.advancement = True elif (item.map and world.mapshuffle[item.player]) or ( item.compass and world.compassshuffle[item.player]): item.priority = True dungeon_items = [ item for item in get_dungeon_item_pool(world) if ((item.smallkey and not world.keyshuffle[item.player]) or ( item.bigkey and not world.bigkeyshuffle[item.player]) or ( item.map and not world.mapshuffle[item.player]) or ( item.compass and not world.compassshuffle[item.player])) ] if dungeon_items: # sort in the order Big Key, Small Key, Other before placing dungeon items sort_order = {"BigKey": 3, "SmallKey": 2} dungeon_items.sort(key=lambda item: sort_order.get(item.type, 1)) fill_restrictive(world, all_state_base, locations, dungeon_items, True)
def test_partial_fill(self): multi_world = generate_multi_world() player1 = generate_player_data(multi_world, 1, 3, 2) item0 = player1.prog_items[0] item1 = player1.prog_items[1] loc0 = player1.locations[0] loc1 = player1.locations[1] loc2 = player1.locations[2] multi_world.completion_condition[player1.id] = lambda state: state.has( item0.name, player1.id) and state.has(item1.name, player1.id) set_rule(loc1, lambda state: state.has(item0.name, player1.id)) # forces a swap set_rule(loc2, lambda state: state.has(item0.name, player1.id)) fill_restrictive(multi_world, multi_world.state, player1.locations, player1.prog_items) self.assertEqual(loc0.item, item0) self.assertEqual(loc1.item, item1) self.assertEqual(1, len(player1.locations)) self.assertEqual(player1.locations[0], loc2)
def generate_itempool(world): if (world.difficulty not in ['easy', 'normal', 'hard', 'expert', 'insane'] or world.goal not in [ 'ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals' ] or world.mode not in ['open', 'standard', 'swordless'] or world.timer not in [ 'none', 'display', 'timed', 'timed-ohko', 'timed-countdown' ] or world.progressive not in ['on', 'off', 'random']): raise NotImplementedError('Not supported yet') world.push_item('Ganon', ItemFactory('Triforce'), False) world.get_location('Ganon').event = True world.push_item('Agahnim 1', ItemFactory('Beat Agahnim 1'), False) world.get_location('Agahnim 1').event = True world.push_item('Agahnim 2', ItemFactory('Beat Agahnim 2'), False) world.get_location('Agahnim 2').event = True # set up item pool world.itempool = ItemFactory(alwaysitems) if world.progressive == 'on': world.itempool.extend(ItemFactory(progressivegloves)) elif world.progressive == 'off': world.itempool.extend(ItemFactory(basicgloves)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(progressivegloves)) else: world.itempool.extend(ItemFactory(basicgloves)) # insanity shuffle doesn't have fake LW/DW logic so for now guaranteed Mirror and Moon Pearl at the start if world.shuffle == 'insanity': world.push_item('Link\'s House', ItemFactory('Magic Mirror'), False) world.get_location('Link\'s House').event = True world.push_item('Sanctuary', ItemFactory('Moon Pearl'), False) world.get_location('Sanctuary').event = True else: world.itempool.extend(ItemFactory(['Magic Mirror', 'Moon Pearl'])) if world.timer == 'display': world.clock_mode = 'stopwatch' if world.difficulty == 'normal': world.itempool.extend(ItemFactory(normalbaseitems)) for i in range(0, 4): thisbottle = normalbottles[random.randint(0, 6)] world.itempool.append(ItemFactory(thisbottle)) extraitems = 70 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(normaltimedother)) extraitems = extraitems - 40 world.clock_mode = 'stopwatch' if world.timer == 'timed' else 'countdown' elif world.timer == 'timed-ohko': world.itempool.extend(ItemFactory(normaltimedohko)) extraitems = extraitems - 25 world.clock_mode = 'ohko' if world.goal == 'triforcehunt': world.itempool.extend(ItemFactory(normaltriforcehunt)) extraitems = extraitems - 30 world.treasure_hunt_count = 20 world.treasure_hunt_icon = 'Triforce Piece' if extraitems > 0: world.itempool.extend(ItemFactory(normalfirst15extra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(normalsecond15extra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(normalthird10extra)) extraitems = extraitems - 10 if extraitems > 0: world.itempool.extend(ItemFactory(normalfourth5extra)) extraitems = extraitems - 5 if extraitems > 0: world.itempool.extend(ItemFactory(normalfinal25extra)) extraitems = extraitems - 25 if world.progressive == 'on': world.itempool.extend(ItemFactory(normalprogressiveshield)) world.itempool.extend(ItemFactory(normalprogressivearmor)) elif world.progressive == 'off': world.itempool.extend(ItemFactory(normalbasicshield)) world.itempool.extend(ItemFactory(normalbasicarmor)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(normalprogressiveshield)) else: world.itempool.extend(ItemFactory(normalbasicshield)) randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(normalprogressivearmor)) else: world.itempool.extend(ItemFactory(normalbasicarmor)) if world.mode == 'swordless': world.itempool.extend(ItemFactory(normalswordless)) elif world.mode == 'standard': if world.progressive == 'on': world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(normalprogressivesword)) elif world.progressive == 'off': world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(normalbasicsword)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(normalprogressivesword)) else: world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(normalbasicsword)) else: if world.progressive == 'on': world.itempool.extend(ItemFactory(normalprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) elif world.progressive == 'off': world.itempool.extend(ItemFactory(normalbasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(normalprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) else: world.itempool.extend(ItemFactory(normalbasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) elif world.difficulty == 'easy': world.itempool.extend(ItemFactory(easybaseitems)) for i in range(0, 8): thisbottle = normalbottles[random.randint(0, 6)] world.itempool.append(ItemFactory(thisbottle)) extraitems = 70 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(easytimedother)) extraitems = extraitems - 40 world.clock_mode = 'stopwatch' if world.timer == 'timed' else 'countdown' elif world.timer == 'timed-ohko': world.itempool.extend(ItemFactory(easytimedohko)) extraitems = extraitems - 25 world.clock_mode = 'ohko' if world.goal == 'triforcehunt': world.itempool.extend(ItemFactory(easytriforcehunt)) extraitems = extraitems - 30 world.treasure_hunt_count = 10 world.treasure_hunt_icon = 'Triforce Piece' if extraitems == 0: world.itempool.extend(ItemFactory(easylimitedextra)) else: world.itempool.extend(ItemFactory(easyextra)) if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(easytimedotherextra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(easyfirst15extra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(easysecond10extra)) extraitems = extraitems - 10 if extraitems > 0: world.itempool.extend(ItemFactory(easythird5extra)) extraitems = extraitems - 5 if extraitems > 0: world.itempool.extend(ItemFactory(easyfinal25extra)) extraitems = extraitems - 25 if world.progressive == 'on': world.itempool.extend(ItemFactory(easyprogressiveshield)) world.itempool.extend(ItemFactory(easyprogressivearmor)) elif world.progressive == 'off': world.itempool.extend(ItemFactory(easybasicshield)) world.itempool.extend(ItemFactory(easybasicarmor)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(easyprogressiveshield)) else: world.itempool.extend(ItemFactory(easybasicshield)) randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(easyprogressivearmor)) else: world.itempool.extend(ItemFactory(easybasicarmor)) if world.mode == 'swordless': world.itempool.extend(ItemFactory(easyswordless)) elif world.mode == 'standard': if world.progressive == 'on': world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(easyprogressivesword)) elif world.progressive == 'off': world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(easybasicsword)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(easyprogressivesword)) else: world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(easybasicsword)) else: if world.progressive == 'on': world.itempool.extend(ItemFactory(easyprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) elif world.progressive == 'off': world.itempool.extend(ItemFactory(easybasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(easyprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) else: world.itempool.extend(ItemFactory(easybasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) elif world.difficulty == 'hard': world.itempool.extend(ItemFactory(hardbaseitems)) for i in range(0, 4): thisbottle = hardbottles[random.randint(0, 5)] world.itempool.append(ItemFactory(thisbottle)) extraitems = 80 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(hardtimedother)) extraitems = extraitems - 40 world.clock_mode = 'stopwatch' if world.timer == 'timed' else 'countdown' elif world.timer == 'timed-ohko': world.itempool.extend(ItemFactory(hardtimedohko)) extraitems = extraitems - 25 world.clock_mode = 'ohko' if world.goal == 'triforcehunt': world.itempool.extend(ItemFactory(hardtriforcehunt)) extraitems = extraitems - 40 world.treasure_hunt_count = 30 world.treasure_hunt_icon = 'Triforce Piece' if extraitems > 0: world.itempool.extend(ItemFactory(hardfirst20extra)) extraitems = extraitems - 20 if extraitems > 0: world.itempool.extend(ItemFactory(hardsecond20extra)) extraitems = extraitems - 20 if extraitems > 0: world.itempool.extend(ItemFactory(hardthird20extra)) extraitems = extraitems - 20 if extraitems > 0: world.itempool.extend(ItemFactory(hardfinal20extra)) extraitems = extraitems - 20 world.itempool.extend(ItemFactory(hardarmor)) if world.progressive == 'on': world.itempool.extend(ItemFactory(hardprogressiveshield)) elif world.progressive == 'off': world.itempool.extend(ItemFactory(hardbasicshield)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(hardprogressiveshield)) else: world.itempool.extend(ItemFactory(hardbasicshield)) if world.mode == 'swordless': world.itempool.extend(ItemFactory(hardswordless)) elif world.mode == 'standard': if world.progressive == 'on': world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(hardprogressivesword)) elif world.progressive == 'off': world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(hardbasicsword)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(hardprogressivesword)) else: world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(hardbasicsword)) else: if world.progressive == 'on': world.itempool.extend(ItemFactory(hardprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) elif world.progressive == 'off': world.itempool.extend(ItemFactory(hardbasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(hardprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) else: world.itempool.extend(ItemFactory(hardbasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) elif world.difficulty == 'expert': world.itempool.extend(ItemFactory(expertbaseitems)) thisbottle = hardbottles[random.randint(0, 5)] for i in range(0, 4): world.itempool.append(ItemFactory(thisbottle)) extraitems = 80 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(experttimedother)) extraitems = extraitems - 40 world.clock_mode = 'stopwatch' if world.timer == 'timed' else 'countdown' elif world.timer == 'timed-ohko': world.itempool.extend(ItemFactory(experttimedohko)) extraitems = extraitems - 25 world.clock_mode = 'ohko' if world.goal == 'triforcehunt': world.itempool.extend(ItemFactory(experttriforcehunt)) extraitems = extraitems - 40 world.treasure_hunt_count = 40 world.treasure_hunt_icon = 'Triforce Piece' if extraitems > 0: world.itempool.extend(ItemFactory(expertfirst15extra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(expertsecond25extra)) extraitems = extraitems - 25 if extraitems > 0: world.itempool.extend(ItemFactory(expertthird15extra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(expertfinal25extra)) extraitems = extraitems - 25 if world.mode == 'swordless': world.itempool.extend(ItemFactory(expertswordless)) elif world.mode == 'standard': if world.progressive == 'on': world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(expertprogressivesword)) elif world.progressive == 'off': world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(expertbasicsword)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(expertprogressivesword)) else: world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(expertbasicsword)) else: if world.progressive == 'on': world.itempool.extend(ItemFactory(expertprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) elif world.progressive == 'off': world.itempool.extend(ItemFactory(expertbasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(expertprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) else: world.itempool.extend(ItemFactory(expertbasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) elif world.difficulty == 'insane': world.itempool.extend(ItemFactory(insanebaseitems)) thisbottle = hardbottles[random.randint(0, 5)] for i in range(0, 4): world.itempool.append(ItemFactory(thisbottle)) extraitems = 90 if world.timer in ['timed', 'timed-countdown']: world.itempool.extend(ItemFactory(insanetimedother)) extraitems = extraitems - 40 world.clock_mode = 'stopwatch' if world.timer == 'timed' else 'countdown' elif world.timer == 'timed-ohko': world.itempool.extend(ItemFactory(insanetimedohko)) extraitems = extraitems - 25 world.clock_mode = 'ohko' if world.goal == 'triforcehunt': world.itempool.extend(ItemFactory(insanetriforcehunt)) extraitems = extraitems - 50 world.treasure_hunt_count = 50 world.treasure_hunt_icon = 'Triforce Piece' if extraitems > 0: world.itempool.extend(ItemFactory(insanefirst15extra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(insanesecond25extra)) extraitems = extraitems - 25 if extraitems > 0: world.itempool.extend(ItemFactory(insanethird10extra)) extraitems = extraitems - 10 if extraitems > 0: world.itempool.extend(ItemFactory(insanefourth15extra)) extraitems = extraitems - 15 if extraitems > 0: world.itempool.extend(ItemFactory(insanefinal25extra)) extraitems = extraitems - 25 if world.mode == 'swordless': world.itempool.extend(ItemFactory(insaneswordless)) elif world.mode == 'standard': if world.progressive == 'on': world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(insaneprogressivesword)) elif world.progressive == 'off': world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(insanebasicsword)) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.push_item('Link\'s Uncle', ItemFactory('Progressive Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(insaneprogressivesword)) else: world.push_item('Link\'s Uncle', ItemFactory('Fighter Sword'), False) world.get_location('Link\'s Uncle').event = True world.itempool.extend(ItemFactory(insanebasicsword)) else: if world.progressive == 'on': world.itempool.extend(ItemFactory(insaneprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) elif world.progressive == 'off': world.itempool.extend(ItemFactory(insanebasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) else: randvalue = random.randint(0, 1) if (randvalue == 0): world.itempool.extend(ItemFactory(insaneprogressivesword)) world.itempool.extend(ItemFactory(['Progressive Sword'])) else: world.itempool.extend(ItemFactory(insanebasicsword)) world.itempool.extend(ItemFactory(['Fighter Sword'])) if world.goal == 'pedestal': world.push_item('Master Sword Pedestal', ItemFactory('Triforce'), False) world.get_location('Master Sword Pedestal').event = True # shuffle medallions mm_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)] tr_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)] world.required_medallions = (mm_medallion, tr_medallion) # distribute crystals crystals = ItemFactory([ 'Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5', 'Crystal 6' ]) crystal_locations = [ world.get_location('Turtle Rock - Prize'), world.get_location('Eastern Palace - Prize'), world.get_location('Desert Palace - Prize'), world.get_location('Tower of Hera - Prize'), world.get_location('Palace of Darkness - Prize'), world.get_location('Thieves Town - Prize'), world.get_location('Skull Woods - Prize'), world.get_location('Swamp Palace - Prize'), world.get_location('Ice Palace - Prize'), world.get_location('Misery Mire - Prize') ] random.shuffle(crystal_locations) fill_restrictive(world, world.get_all_state(keys=True), crystal_locations, crystals)