diff --git a/BaseClasses.py b/BaseClasses.py index 3eed0a3e..3e99cbac 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -868,7 +868,7 @@ class Entrance(object): class Dungeon(object): - def __init__(self, name, regions, big_key, small_keys, dungeon_items, player: int): + def __init__(self, name: str, regions, big_key, small_keys, dungeon_items, player: int): self.name = name self.regions = regions self.big_key = big_key @@ -894,9 +894,12 @@ class Dungeon(object): def all_items(self): return self.dungeon_items + self.keys - def is_dungeon_item(self, item): + def is_dungeon_item(self, item: Item) -> bool: return item.player == self.player and item.name in [dungeon_item.name for dungeon_item in self.all_items] + def __eq__(self, other: Item) -> bool: + return self.name == other.name and self.player == other.player + def __repr__(self): return self.__str__() diff --git a/Fill.py b/Fill.py index 9478bf55..b668a119 100644 --- a/Fill.py +++ b/Fill.py @@ -219,9 +219,24 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None # get items to distribute random.shuffle(world.itempool) - progitempool = [item for item in world.itempool if item.advancement] - prioitempool = [item for item in world.itempool if not item.advancement and item.priority] - restitempool = [item for item in world.itempool if not item.advancement and not item.priority] + progitempool = [] + localprioitempool = {player: [] for player in range(1, world.players + 1)} + localrestitempool = {player: [] for player in range(1, world.players + 1)} + prioitempool = [] + restitempool = [] + + for item in world.itempool: + if item.advancement: + progitempool.append(item) + elif item.name in world.local_items[item.player]: + if item.priority: + localprioitempool[item.player].append(item) + else: + localrestitempool[item.player].append(item) + elif item.priority: + prioitempool.append(item) + else: + restitempool.append(item) # fill in gtower locations with trash first for player in range(1, world.players + 1): @@ -232,12 +247,24 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None random.randint(15, 50) if world.goal[player] in {'triforcehunt', 'localtriforcehunt'} else random.randint(0, 15)) - gtower_locations = [location for location in fill_locations if 'Ganons Tower' in location.name and location.player == player] + gtower_locations = [location for location in fill_locations if + 'Ganons Tower' in location.name and location.player == player] random.shuffle(gtower_locations) trashcnt = 0 - while gtower_locations and restitempool and trashcnt < gftower_trash_count: + localrest = localrestitempool[player] + if localrest: + gt_item_pool = restitempool + localrest + random.shuffle(gt_item_pool) + else: + gt_item_pool = restitempool.copy() + + while gtower_locations and gt_item_pool and trashcnt < gftower_trash_count: spot_to_fill = gtower_locations.pop() - item_to_place = restitempool.pop() + item_to_place = gt_item_pool.pop() + if item_to_place in localrest: + localrest.remove(item_to_place) + else: + restitempool.remove(item_to_place) world.push_item(spot_to_fill, item_to_place, False) fill_locations.remove(spot_to_fill) trashcnt += 1 @@ -246,24 +273,43 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None fill_locations.reverse() # Make sure the escape small key is placed first in standard with key shuffle to prevent running out of spots - progitempool.sort(key=lambda item: 1 if item.name == 'Small Key (Escape)' and world.mode[item.player] == 'standard' and world.keyshuffle[item.player] else 0) + progitempool.sort( + key=lambda item: 1 if item.name == 'Small Key (Escape)' and world.mode[item.player] == 'standard' and + world.keyshuffle[item.player] else 0) fill_restrictive(world, world.state, fill_locations, progitempool) + if any( + localprioitempool.values() or localrestitempool.values()): # we need to make sure some fills are limited to certain worlds + for player, items in localprioitempool.items(): # already shuffled + local_locations = [location for location in fill_locations if location.player == player] + random.shuffle(local_locations) + for item_to_place in items: + spot_to_fill = local_locations.pop() + world.push_item(spot_to_fill, item_to_place, False) + fill_locations.remove(spot_to_fill) + for player, items in localrestitempool.items(): # already shuffled + local_locations = [location for location in fill_locations if location.player == player] + random.shuffle(local_locations) + for item_to_place in items: + spot_to_fill = local_locations.pop() + world.push_item(spot_to_fill, item_to_place, False) + fill_locations.remove(spot_to_fill) + random.shuffle(fill_locations) fast_fill(world, prioitempool, fill_locations) fast_fill(world, restitempool, fill_locations) - logging.getLogger('').debug('Unplaced items: %s - Unfilled Locations: %s', [item.name for item in progitempool + prioitempool + restitempool], [location.name for location in fill_locations]) + logging.getLogger('').debug('Unplaced items: %s - Unfilled Locations: %s', + [item.name for item in progitempool + prioitempool + restitempool], + [location.name for location in fill_locations]) def fast_fill(world, item_pool, fill_locations): while item_pool and fill_locations: - spot_to_fill = fill_locations.pop() - item_to_place = item_pool.pop() - world.push_item(spot_to_fill, item_to_place, False) + world.push_item(fill_locations.pop(), item_pool.pop(), False) def flood_items(world): diff --git a/Items.py b/Items.py index 8c1eafeb..d4cd15ca 100644 --- a/Items.py +++ b/Items.py @@ -185,7 +185,9 @@ lookup_id_to_name = {data[3]: name for name, data in item_table.items()} hint_blacklist = {"Triforce"} -item_name_groups = {"Bows": {"Bow", "Silver Arrows", "Progressive Bow (Alt)", "Progressive Bow"}} +item_name_groups = {"Bows": {"Bow", "Silver Arrows", "Progressive Bow (Alt)", "Progressive Bow"}, + "Gloves": {"Power Glove", "Progressive Glove", "Titans Mitts"}, + "Medallions": {"Ether", "Bombos", "Quake"}} # generic groups, (Name, substring) _simple_groups = {("Swords", "Sword"), @@ -196,7 +198,8 @@ _simple_groups = {("Swords", "Sword"), ("Bottles", "Bottle"), ("Potions", "Potion"), - ("Rupees", "Rupee") + ("Rupees", "Rupee"), + ("Clocks", "Clock") } for basename, substring in _simple_groups: tempset = item_name_groups[basename] = set()