LttP: deterministic shop_shuffle

This commit is contained in:
Fabian Dill 2023-05-18 16:01:39 +02:00 committed by Fabian Dill
parent 97ba631b80
commit a2ddd5c9e8
1 changed files with 18 additions and 17 deletions

View File

@ -150,6 +150,7 @@ class TakeAny(Shop):
2: "" 2: ""
} }
class UpgradeShop(Shop): class UpgradeShop(Shop):
type = ShopType.UpgradeShop type = ShopType.UpgradeShop
# Potions break due to VRAM flags set in 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 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_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} for location in shop_locations if location.shop_slot is not None}
removed = set() removed = set()
@ -199,8 +200,8 @@ def ShopSlotFill(world):
blacklist_word in item_name for blacklist_word in blacklist_words)} blacklist_word in item_name for blacklist_word in blacklist_words)}
blacklist_words.add("Bee") blacklist_words.add("Bee")
locations_per_sphere = list( locations_per_sphere = [sorted(sphere, key=lambda location: (location.name, location.player))
sorted(sphere, key=lambda location: location.name) for sphere in world.get_spheres()) for sphere in multiworld.get_spheres()]
# currently special care needs to be taken so that Shop.region.locations.item is identical to Shop.inventory # 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 # Potentially create Locations as needed and make inventory the only source, to prevent divergence
@ -226,7 +227,7 @@ def ShopSlotFill(world):
x = 0 x = 0
cumu_weights.append(len(current_candidates) + x) cumu_weights.append(len(current_candidates) + x)
world.random.shuffle(current_candidates) multiworld.random.shuffle(current_candidates)
del locations_per_sphere 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 # 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) candidates = [(location, i) for i, candidates in enumerate(candidates_per_sphere[i:], start=i)
for location in candidates] for location in candidates]
world.random.shuffle(candidates) multiworld.random.shuffle(candidates)
for location in current_shop_slots: for location in current_shop_slots:
shop: Shop = location.parent_region.shop shop: Shop = location.parent_region.shop
for index, (c, swapping_sphere_id) in enumerate(candidates): # chosen item locations for index, (c, swapping_sphere_id) in enumerate(candidates): # chosen item locations
if c.item_rule(location.item) and location.item_rule(c.item): if c.item_rule(location.item) and location.item_rule(c.item):
swap_location_item(c, location, check_locked=False) 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 # remove candidate
candidates_per_sphere[swapping_sphere_id].remove(c) candidates_per_sphere[swapping_sphere_id].remove(c)
candidates.pop(index) candidates.pop(index)
@ -256,26 +257,26 @@ def ShopSlotFill(world):
item_name = location.item.name item_name = location.item.name
if location.item.game != "A Link to the Past": if location.item.game != "A Link to the Past":
if location.item.advancement: if location.item.advancement:
price = world.random.randrange(8, 56) price = multiworld.random.randrange(8, 56)
elif location.item.useful: elif location.item.useful:
price = world.random.randrange(4, 28) price = multiworld.random.randrange(4, 28)
else: else:
price = world.random.randrange(2, 14) price = multiworld.random.randrange(2, 14)
elif any(x in item_name for x in elif any(x in item_name for x in
['Compass', 'Map', 'Single Bomb', 'Single Arrow', 'Piece of Heart']): ['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']): 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']): 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: else:
price = world.random.randrange(8, 56) price = multiworld.random.randrange(8, 56)
shop.push_inventory(location.shop_slot, item_name, 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) location.item.player if location.item.player != location.player else 0)
if 'P' in world.shop_shuffle[location.player]: if 'P' in multiworld.shop_shuffle[location.player]:
price_to_funny_price(world, shop.inventory[location.shop_slot], location.player) price_to_funny_price(multiworld, shop.inventory[location.shop_slot], location.player)
def create_shops(world, player: int): def create_shops(world, player: int):