From a2ddd5c9e85cf22ea9d59d9f609c8dd1207a35e5 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Thu, 18 May 2023 16:01:39 +0200 Subject: [PATCH] LttP: deterministic shop_shuffle --- worlds/alttp/Shops.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/worlds/alttp/Shops.py b/worlds/alttp/Shops.py index b067634d..53a880d0 100644 --- a/worlds/alttp/Shops.py +++ b/worlds/alttp/Shops.py @@ -150,6 +150,7 @@ class TakeAny(Shop): 2: "" } + class UpgradeShop(Shop): type = ShopType.UpgradeShop # Potions break due to VRAM flags set in UpgradeShop. @@ -173,9 +174,9 @@ def FillDisabledShopSlots(world): location.item_rule = lambda item: item.name == location.item.name and item.player == location.player -def ShopSlotFill(world): +def ShopSlotFill(multiworld): shop_slots: Set[ALttPLocation] = {location for shop_locations in - (shop.region.locations for shop in world.shops if shop.type != ShopType.TakeAny) + (shop.region.locations for shop in multiworld.shops if shop.type != ShopType.TakeAny) for location in shop_locations if location.shop_slot is not None} removed = set() @@ -199,8 +200,8 @@ def ShopSlotFill(world): blacklist_word in item_name for blacklist_word in blacklist_words)} blacklist_words.add("Bee") - locations_per_sphere = list( - sorted(sphere, key=lambda location: location.name) for sphere in world.get_spheres()) + locations_per_sphere = [sorted(sphere, key=lambda location: (location.name, location.player)) + for sphere in multiworld.get_spheres()] # currently special care needs to be taken so that Shop.region.locations.item is identical to Shop.inventory # Potentially create Locations as needed and make inventory the only source, to prevent divergence @@ -226,7 +227,7 @@ def ShopSlotFill(world): x = 0 cumu_weights.append(len(current_candidates) + x) - world.random.shuffle(current_candidates) + multiworld.random.shuffle(current_candidates) del locations_per_sphere @@ -235,13 +236,13 @@ def ShopSlotFill(world): # getting all candidates and shuffling them feels cpu expensive, there may be a better method candidates = [(location, i) for i, candidates in enumerate(candidates_per_sphere[i:], start=i) for location in candidates] - world.random.shuffle(candidates) + multiworld.random.shuffle(candidates) for location in current_shop_slots: shop: Shop = location.parent_region.shop for index, (c, swapping_sphere_id) in enumerate(candidates): # chosen item locations if c.item_rule(location.item) and location.item_rule(c.item): swap_location_item(c, location, check_locked=False) - logger.debug(f'Swapping {c} into {location}:: {location.item}') + logger.debug(f"Swapping {c} into {location}:: {location.item}") # remove candidate candidates_per_sphere[swapping_sphere_id].remove(c) candidates.pop(index) @@ -256,26 +257,26 @@ def ShopSlotFill(world): item_name = location.item.name if location.item.game != "A Link to the Past": if location.item.advancement: - price = world.random.randrange(8, 56) + price = multiworld.random.randrange(8, 56) elif location.item.useful: - price = world.random.randrange(4, 28) + price = multiworld.random.randrange(4, 28) else: - price = world.random.randrange(2, 14) + price = multiworld.random.randrange(2, 14) elif any(x in item_name for x in ['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']): - price = world.random.randrange(1, 7) + price = multiworld.random.randrange(1, 7) elif any(x in item_name for x in ['Arrow', 'Bomb', 'Clock']): - price = world.random.randrange(2, 14) + price = multiworld.random.randrange(2, 14) elif any(x in item_name for x in ['Small Key', 'Heart']): - price = world.random.randrange(4, 28) + price = multiworld.random.randrange(4, 28) else: - price = world.random.randrange(8, 56) + price = multiworld.random.randrange(8, 56) shop.push_inventory(location.shop_slot, item_name, - min(int(price * world.shop_price_modifier[location.player] / 100) * 5, 9999), 1, + min(int(price * multiworld.shop_price_modifier[location.player] / 100) * 5, 9999), 1, location.item.player if location.item.player != location.player else 0) - if 'P' in world.shop_shuffle[location.player]: - price_to_funny_price(world, shop.inventory[location.shop_slot], location.player) + if 'P' in multiworld.shop_shuffle[location.player]: + price_to_funny_price(multiworld, shop.inventory[location.shop_slot], location.player) def create_shops(world, player: int):