If any shop shuffle slots are defined, define ALL of them to avoid information leakage.

This commit is contained in:
CaitSith2 2021-01-22 05:40:50 -08:00
parent f02715f988
commit 6095cfc586
3 changed files with 25 additions and 11 deletions

View File

@ -1074,6 +1074,7 @@ class Boss():
class Location():
shop_slot: bool = False
shop_slot_disabled: bool = False
event: bool = False
locked: bool = False

View File

@ -10,7 +10,7 @@ import zlib
import concurrent.futures
from BaseClasses import World, CollectionState, Item, Region, Location
from Shops import ShopSlotFill, create_shops, SHOP_ID_START
from Shops import ShopSlotFill, create_shops, SHOP_ID_START, FillDisabledShopSlots
from Items import ItemFactory, item_table, item_name_groups
from Regions import create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance
from InvertedRegions import create_inverted_regions, mark_dark_world_regions
@ -389,6 +389,8 @@ def main(args, seed=None):
for item in world.precollected_items:
precollected_items[item.player - 1].append(item.code)
FillDisabledShopSlots(world)
def write_multidata(roms):
for future in roms:
rom_name = future.result()

View File

@ -125,6 +125,17 @@ shop_class_mapping = {ShopType.UpgradeShop: UpgradeShop,
ShopType.TakeAny: TakeAny}
def FillDisabledShopSlots(world):
shop_slots: Set[Location] = {location for shop_locations in (shop.region.locations for shop in world.shops)
for location in shop_locations if location.shop_slot and location.shop_slot_disabled}
for location in shop_slots:
location.shop_slot_disabled = True
slot_num = int(location.name[-1]) - 1
shop: Shop = location.parent_region.shop
location.item = ItemFactory(shop.inventory[slot_num]['item'], location.player)
location.item_rule = lambda item: item.name == location.item.name and item.player == location.player
def ShopSlotFill(world):
shop_slots: Set[Location] = {location for shop_locations in (shop.region.locations for shop in world.shops)
for location in shop_locations if location.shop_slot}
@ -132,15 +143,11 @@ def ShopSlotFill(world):
for location in shop_slots:
slot_num = int(location.name[-1]) - 1
shop: Shop = location.parent_region.shop
if not shop.can_push_inventory(slot_num):
if not shop.can_push_inventory(slot_num) or location.shop_slot_disabled:
removed.add(location)
shop.region.locations.remove(location)
if removed:
shop_slots -= removed
# remove locations that may no longer exist from caches, by flushing them entirely
world.clear_location_cache()
world._location_cache = {}
if shop_slots:
from Fill import swap_location_item
@ -168,7 +175,7 @@ def ShopSlotFill(world):
world.random.shuffle(sphere)
for i, sphere in enumerate(candidates_per_sphere):
current_shop_slots = [location for location in sphere if location.shop_slot]
current_shop_slots = [location for location in sphere if location.shop_slot and not location.shop_slot_disabled]
if current_shop_slots:
for location in current_shop_slots:
@ -183,7 +190,7 @@ def ShopSlotFill(world):
else:
# This *should* never happen. But let's fail safely just in case.
logger.warning("Ran out of ShopShuffle Item candidate locations.")
shop.region.locations.remove(location)
location.shop_slot_disabled = True
continue
item_name = location.item.name
if any(x in item_name for x in ['Single Bomb', 'Single Arrow']):
@ -239,14 +246,18 @@ def create_shops(world, player: int):
world.shops.append(shop)
for index, item in enumerate(inventory):
shop.add_inventory(index, *item)
if not locked and single_purchase_slots.pop():
additional_item = 'Rupees (50)' # world.random.choice(['Rupees (50)', 'Rupees (100)', 'Rupees (300)'])
if not locked and num_slots:
slot_name = "{} Slot {}".format(region.name, index + 1)
loc = Location(player, slot_name, address=shop_table_by_location[slot_name],
parent=region, hint_text="for sale")
loc.shop_slot = True
loc.locked = True
loc.item = ItemFactory(additional_item, player)
if single_purchase_slots.pop():
additional_item = 'Rupees (50)' # world.random.choice(['Rupees (50)', 'Rupees (100)', 'Rupees (300)'])
loc.item = ItemFactory(additional_item, player)
else:
loc.item = ItemFactory('Nothing', player)
loc.shop_slot_disabled = True
shop.region.locations.append(loc)
world.dynamic_locations.append(loc)
world.clear_location_cache()