Shop Shuffle
- more can be done here, but this works fine as a sometimes fun proof of concept
This commit is contained in:
parent
40e4e3c0c6
commit
26ab3dd69a
|
@ -124,6 +124,7 @@ class World(object):
|
||||||
set_player_attr('local_items', set())
|
set_player_attr('local_items', set())
|
||||||
set_player_attr('triforce_pieces_available', 30)
|
set_player_attr('triforce_pieces_available', 30)
|
||||||
set_player_attr('triforce_pieces_required', 20)
|
set_player_attr('triforce_pieces_required', 20)
|
||||||
|
set_player_attr('shop_shuffle', 'off')
|
||||||
|
|
||||||
def secure(self):
|
def secure(self):
|
||||||
self.random = secrets.SystemRandom()
|
self.random = secrets.SystemRandom()
|
||||||
|
@ -1052,6 +1053,7 @@ class ShopType(Enum):
|
||||||
UpgradeShop = 2
|
UpgradeShop = 2
|
||||||
|
|
||||||
class Shop(object):
|
class Shop(object):
|
||||||
|
slots = 3
|
||||||
def __init__(self, region, room_id, type, shopkeeper_config, custom, locked):
|
def __init__(self, region, room_id, type, shopkeeper_config, custom, locked):
|
||||||
self.region = region
|
self.region = region
|
||||||
self.room_id = room_id
|
self.room_id = room_id
|
||||||
|
|
|
@ -312,6 +312,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
parser.add_argument('--enemy_damage', default=defval('default'), choices=['default', 'shuffled', 'chaos'])
|
parser.add_argument('--enemy_damage', default=defval('default'), choices=['default', 'shuffled', 'chaos'])
|
||||||
parser.add_argument('--shufflepots', default=defval(False), action='store_true')
|
parser.add_argument('--shufflepots', default=defval(False), action='store_true')
|
||||||
parser.add_argument('--beemizer', default=defval(0), type=lambda value: min(max(int(value), 0), 4))
|
parser.add_argument('--beemizer', default=defval(0), type=lambda value: min(max(int(value), 0), 4))
|
||||||
|
parser.add_argument('--shop_shuffle', default='off', choices=['off', 'inventory', 'price', 'inventory_price'])
|
||||||
parser.add_argument('--remote_items', default=defval(False), action='store_true')
|
parser.add_argument('--remote_items', default=defval(False), action='store_true')
|
||||||
parser.add_argument('--multi', default=defval(1), type=lambda value: min(max(int(value), 1), 255))
|
parser.add_argument('--multi', default=defval(1), type=lambda value: min(max(int(value), 1), 255))
|
||||||
parser.add_argument('--names', default=defval(''))
|
parser.add_argument('--names', default=defval(''))
|
||||||
|
@ -355,7 +356,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
'shufflebosses', 'enemy_shuffle', 'enemy_health', 'enemy_damage', 'shufflepots',
|
'shufflebosses', 'enemy_shuffle', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
||||||
'heartbeep', "skip_progression_balancing", "triforce_pieces_available",
|
'heartbeep', "skip_progression_balancing", "triforce_pieces_available",
|
||||||
"triforce_pieces_required",
|
"triforce_pieces_required", "shop_shuffle",
|
||||||
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
||||||
'tile_shuffle', 'bush_shuffle']:
|
'tile_shuffle', 'bush_shuffle']:
|
||||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||||
|
|
15
Gui.py
15
Gui.py
|
@ -344,11 +344,22 @@ def guiMain(args=None):
|
||||||
shuffleFrame = Frame(drowDownFrame)
|
shuffleFrame = Frame(drowDownFrame)
|
||||||
shuffleVar = StringVar()
|
shuffleVar = StringVar()
|
||||||
shuffleVar.set('vanilla')
|
shuffleVar.set('vanilla')
|
||||||
shuffleOptionMenu = OptionMenu(shuffleFrame, shuffleVar, 'vanilla', 'simple', 'restricted', 'full', 'crossed', 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeonsfull', 'dungeonssimple')
|
shuffleOptionMenu = OptionMenu(shuffleFrame, shuffleVar, 'vanilla', 'simple', 'restricted', 'full', 'crossed',
|
||||||
|
'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy',
|
||||||
|
'dungeonsfull', 'dungeonssimple')
|
||||||
shuffleOptionMenu.pack(side=RIGHT)
|
shuffleOptionMenu.pack(side=RIGHT)
|
||||||
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle algorithm')
|
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle algorithm')
|
||||||
shuffleLabel.pack(side=LEFT)
|
shuffleLabel.pack(side=LEFT)
|
||||||
|
|
||||||
|
shop_shuffleFrame = Frame(drowDownFrame)
|
||||||
|
shop_shuffleVar = StringVar()
|
||||||
|
shop_shuffleVar.set('off')
|
||||||
|
shop_shuffleOptionMenu = OptionMenu(shop_shuffleFrame, shop_shuffleVar, 'off', 'inventory', 'price',
|
||||||
|
'price and inventory')
|
||||||
|
shop_shuffleOptionMenu.pack(side=RIGHT)
|
||||||
|
shop_shuffleLabel = Label(shop_shuffleFrame, text='Shop Shuffle')
|
||||||
|
shop_shuffleLabel.pack(side=LEFT)
|
||||||
|
|
||||||
modeFrame.pack(expand=True, anchor=E)
|
modeFrame.pack(expand=True, anchor=E)
|
||||||
logicFrame.pack(expand=True, anchor=E)
|
logicFrame.pack(expand=True, anchor=E)
|
||||||
goalFrame.pack(expand=True, anchor=E)
|
goalFrame.pack(expand=True, anchor=E)
|
||||||
|
@ -363,6 +374,7 @@ def guiMain(args=None):
|
||||||
accessibilityFrame.pack(expand=True, anchor=E)
|
accessibilityFrame.pack(expand=True, anchor=E)
|
||||||
algorithmFrame.pack(expand=True, anchor=E)
|
algorithmFrame.pack(expand=True, anchor=E)
|
||||||
shuffleFrame.pack(expand=True, anchor=E)
|
shuffleFrame.pack(expand=True, anchor=E)
|
||||||
|
shop_shuffleFrame.pack(expand=True, anchor=E)
|
||||||
|
|
||||||
enemizerFrame = LabelFrame(randomizerWindow, text="Enemizer", padx=5, pady=2)
|
enemizerFrame = LabelFrame(randomizerWindow, text="Enemizer", padx=5, pady=2)
|
||||||
|
|
||||||
|
@ -479,6 +491,7 @@ def guiMain(args=None):
|
||||||
guiargs.accessibility = accessibilityVar.get()
|
guiargs.accessibility = accessibilityVar.get()
|
||||||
guiargs.algorithm = algorithmVar.get()
|
guiargs.algorithm = algorithmVar.get()
|
||||||
guiargs.shuffle = shuffleVar.get()
|
guiargs.shuffle = shuffleVar.get()
|
||||||
|
guiargs.shop_shuffle = shop_shuffleVar.get()
|
||||||
guiargs.heartbeep = heartbeepVar.get()
|
guiargs.heartbeep = heartbeepVar.get()
|
||||||
guiargs.heartcolor = heartcolorVar.get()
|
guiargs.heartcolor = heartcolorVar.get()
|
||||||
guiargs.fastmenu = fastMenuVar.get()
|
guiargs.fastmenu = fastMenuVar.get()
|
||||||
|
|
38
ItemPool.py
38
ItemPool.py
|
@ -323,9 +323,45 @@ def generate_itempool(world, player: int):
|
||||||
|
|
||||||
if world.retro[player]:
|
if world.retro[player]:
|
||||||
set_up_take_anys(world, player)
|
set_up_take_anys(world, player)
|
||||||
|
if world.shop_shuffle[player] != 'off':
|
||||||
|
shuffle_shops(world, player)
|
||||||
create_dynamic_shop_locations(world, player)
|
create_dynamic_shop_locations(world, player)
|
||||||
|
|
||||||
|
|
||||||
|
def shuffle_shops(world, player: int):
|
||||||
|
option = world.shop_shuffle[player]
|
||||||
|
shops = []
|
||||||
|
total_inventory = []
|
||||||
|
for shop in world.shops:
|
||||||
|
if shop.type == ShopType.Shop and shop.region.player == player:
|
||||||
|
shops.append(shop)
|
||||||
|
total_inventory.extend(shop.inventory)
|
||||||
|
|
||||||
|
if 'price' in option:
|
||||||
|
def price_adjust(price: int) -> int:
|
||||||
|
# it is important that a base price of 0 always returns 0 as new price!
|
||||||
|
return int(price * (0.5 + world.random.random() * 2))
|
||||||
|
|
||||||
|
for item in total_inventory:
|
||||||
|
if item:
|
||||||
|
item["price"] = price_adjust(item["price"])
|
||||||
|
item['replacement_price'] = price_adjust(item["price"])
|
||||||
|
for shop in world.shops:
|
||||||
|
if shop.type == ShopType.UpgradeShop and shop.region.player == player:
|
||||||
|
for item in shop.inventory:
|
||||||
|
if item:
|
||||||
|
item['price'] = price_adjust(item["price"])
|
||||||
|
item['replacement_price'] = price_adjust(item["price"])
|
||||||
|
|
||||||
|
if 'inventory' in option:
|
||||||
|
world.random.shuffle(total_inventory)
|
||||||
|
i = 0
|
||||||
|
for shop in shops:
|
||||||
|
slots = shop.slots
|
||||||
|
shop.inventory = total_inventory[i:i + slots]
|
||||||
|
i += slots
|
||||||
|
|
||||||
|
|
||||||
take_any_locations = [
|
take_any_locations = [
|
||||||
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
|
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
|
||||||
'Fortune Teller (Light)', 'Lake Hylia Fortune Teller', 'Lumberjack House', 'Bonk Fairy (Light)',
|
'Fortune Teller (Light)', 'Lake Hylia Fortune Teller', 'Lumberjack House', 'Bonk Fairy (Light)',
|
||||||
|
|
1
Main.py
1
Main.py
|
@ -79,6 +79,7 @@ def main(args, seed=None):
|
||||||
world.glitch_boots = args.glitch_boots.copy()
|
world.glitch_boots = args.glitch_boots.copy()
|
||||||
world.triforce_pieces_available = args.triforce_pieces_available.copy()
|
world.triforce_pieces_available = args.triforce_pieces_available.copy()
|
||||||
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
||||||
|
world.shop_shuffle = args.shop_shuffle.copy()
|
||||||
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
||||||
|
|
||||||
world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)}
|
||||||
|
|
|
@ -310,6 +310,10 @@ def roll_settings(weights):
|
||||||
ret.triforce_pieces_required = get_choice('triforce_pieces_required', weights, 20)
|
ret.triforce_pieces_required = get_choice('triforce_pieces_required', weights, 20)
|
||||||
ret.triforce_pieces_required = min(max(1, int(ret.triforce_pieces_required)), 90)
|
ret.triforce_pieces_required = min(max(1, int(ret.triforce_pieces_required)), 90)
|
||||||
|
|
||||||
|
ret.shop_shuffle = get_choice('shop_shuffle', weights, False)
|
||||||
|
if not ret.shop_shuffle:
|
||||||
|
ret.shop_shuffle = 'off'
|
||||||
|
|
||||||
ret.mode = get_choice('world_state', weights, None) # legacy support
|
ret.mode = get_choice('world_state', weights, None) # legacy support
|
||||||
if ret.mode == 'retro':
|
if ret.mode == 'retro':
|
||||||
ret.mode = 'open'
|
ret.mode = 'open'
|
||||||
|
|
|
@ -189,6 +189,11 @@ beemizer: # Remove items from the global item pool and replace them with single
|
||||||
2: 0 # 60% of the non-essential item pool is replaced with bee traps, of which 20% could be single bees
|
2: 0 # 60% of the non-essential item pool is replaced with bee traps, of which 20% could be single bees
|
||||||
3: 0 # 100% of the non-essential item pool is replaced with bee traps, of which 50% could be single bees
|
3: 0 # 100% of the non-essential item pool is replaced with bee traps, of which 50% could be single bees
|
||||||
4: 0 # 100% of the non-essential item pool is replaced with bee traps
|
4: 0 # 100% of the non-essential item pool is replaced with bee traps
|
||||||
|
shop_shuffle:
|
||||||
|
off: 1
|
||||||
|
inventory: 0 # shuffle the inventories of the shops around
|
||||||
|
price: 0 # randomize the prices of the items in shop inventories
|
||||||
|
inventory_price: 0 # shuffle inventories and randomize prices
|
||||||
timer:
|
timer:
|
||||||
none: 1
|
none: 1
|
||||||
timed: 0
|
timed: 0
|
||||||
|
|
Loading…
Reference in New Issue