Merge branch 'shop-fill' into multishop-all

This commit is contained in:
pepperpow 2020-12-23 11:29:20 -06:00
commit c66e97faf6
5 changed files with 60 additions and 7 deletions

View File

@ -229,6 +229,7 @@ def flood_items(world):
itempool.remove(item_to_place) itempool.remove(item_to_place)
break break
def balance_multiworld_progression(world): def balance_multiworld_progression(world):
balanceable_players = {player for player in range(1, world.players + 1) if world.progression_balancing[player]} balanceable_players = {player for player in range(1, world.players + 1) if world.progression_balancing[player]}
if not balanceable_players: if not balanceable_players:

32
Main.py
View File

@ -177,6 +177,38 @@ def main(args, seed=None):
elif args.algorithm == 'balanced': elif args.algorithm == 'balanced':
distribute_items_restrictive(world, True) distribute_items_restrictive(world, True)
for x in range(1, world.players + 1):
shop_slot_bad = []
candidates = []
for location in world.get_locations():
if 'Shop Slot' in location.name and location.parent_region.shop is not None:
slot_num = int(location.name[-1]) - 1
shop_item = location.parent_region.shop.inventory[slot_num]
item = location.item
print(item.name, shop_item['item'])
if (shop_item is not None and shop_item['item'] == item.name) or 'Rupee' in item.name or (item.name in ['Bee']):
shop_slot_bad.append(location)
elif location.item.name in ['Progressive Shield', 'Bombs (3)', 'Bombs (10)', 'Bee Trap',
'Arrows (10)', 'Single Bomb', 'Single Arrow', 'Arrow Upgrade (+5)', 'Bomb Upgrade (+5)',
'Shovel', 'Progressive Mail', 'Bug Catching Net', 'Cane of Byrna', 'Triforce Piece'
'Piece of Heart', 'Boss Heart Container', 'Sanctuary Heart Container']:
candidates.append(location)
elif any([x in location.item.name for x in ['Key', 'Map', 'Compass', 'Clock']]):
candidates.append(location)
world.random.shuffle(candidates)
for slot in shop_slot_bad: # shop slot locations with redundant items
for c in candidates: # chosen item locations
if 'Rupee' in c.item.name or 'Shop Slot' in c.name: continue
if c.item_rule(slot.item):
print('Swapping {} with {}:: {} ||| {}'.format(c, slot, c.item, slot.item))
c.item, slot.item = slot.item, c.item
if not world.can_beat_game():
print('NOT GOOD')
c.item, slot.item = slot.item, c.item
else: break
if world.players > 1: if world.players > 1:
balance_multiworld_progression(world) balance_multiworld_progression(world)

View File

@ -416,7 +416,7 @@ def create_shops(world, player: int):
pass pass
else: else:
if my_shop_slots.pop(): if my_shop_slots.pop():
additional_item = world.random.choice(['Rupees (20)', 'Rupees (50)', 'Rupees (100)']) additional_item = world.random.choice(['Rupees (50)', 'Rupees (100)', 'Rupees (300)'])
world.itempool.append(ItemFactory(additional_item, player)) world.itempool.append(ItemFactory(additional_item, player))
slot_name = "{} Shop Slot {}".format(shop.region.name, index+1) slot_name = "{} Shop Slot {}".format(shop.region.name, index+1)
loc = Location(player, slot_name, address=shop_table_by_location[slot_name], parent=shop.region) loc = Location(player, slot_name, address=shop_table_by_location[slot_name], parent=shop.region)
@ -448,7 +448,7 @@ shop_table_by_location_id = {0x400000 + cnt: s for cnt, s in enumerate( [item fo
shop_table_by_location = {y:x for x,y in shop_table_by_location_id.items()} shop_table_by_location = {y:x for x,y in shop_table_by_location_id.items()}
shop_generation_types = { shop_generation_types = {
'default': _basic_shop_defaults + [('Bombs (3)', 20), ('Green Potion', 90), ('Blue Potion', 190), ('Bee', 10), ('Single Arrow', 5)] + [('Red Shield', 500), ('Blue Shield', 50)], 'default': _basic_shop_defaults + [('Bombs (3)', 20), ('Green Potion', 90), ('Blue Potion', 190), ('Bee', 10), ('Single Arrow', 5), ('Single Bomb', 10)] + [('Red Shield', 500), ('Blue Shield', 50)],
'potion': [('Red Potion', 150), ('Green Potion', 90), ('Blue Potion', 190)], 'potion': [('Red Potion', 150), ('Green Potion', 90), ('Blue Potion', 190)],
'discount_potion': [('Red Potion', 120), ('Green Potion', 60), ('Blue Potion', 160)], 'discount_potion': [('Red Potion', 120), ('Green Potion', 60), ('Blue Potion', 160)],
'bottle': [('Bee', 10)], 'bottle': [('Bee', 10)],

22
Rom.py
View File

@ -633,6 +633,8 @@ def patch_rom(world, rom, player, team, enemized):
distinguished_prog_bow_loc.item.code = 0x65 distinguished_prog_bow_loc.item.code = 0x65
# patch items # patch items
shop_items = []
for location in world.get_locations(): for location in world.get_locations():
if location.player != player: if location.player != player:
continue continue
@ -659,9 +661,19 @@ def patch_rom(world, rom, player, team, enemized):
my_item['replacement'] = my_item['item'] my_item['replacement'] = my_item['item']
my_item['replacement_price'] = my_item['price'] my_item['replacement_price'] = my_item['price']
my_item['item'] = item.name my_item['item'] = item.name
my_item['price'] = world.random.randrange(1, 61) * 5 # can probably replace this with a price chart if any([x in my_item['item'] for x in ['Single Bomb', 'Single Arrow']]):
my_item['price'] = world.random.randrange(5,35)
elif any([x in my_item['item'] for x in ['Arrows', 'Bombs', 'Clock']]):
my_item['price'] = world.random.randrange(20,120)
elif any([x in my_item['item'] for x in ['Universal Key', 'Compass', 'Map', 'Small Key', 'Piece of Heart']]):
my_item['price'] = world.random.randrange(50,150)
else:
my_item['price'] = world.random.randrange(50,300)
my_item['max'] = 1 my_item['max'] = 1
my_item['player'] = item.player if item.player != location.player else 0 my_item['player'] = item.player if item.player != location.player else 0
shop_items.append(my_item)
continue continue
if not location.crystal: if not location.crystal:
@ -702,6 +714,14 @@ def patch_rom(world, rom, player, team, enemized):
for music_address in music_addresses: for music_address in music_addresses:
rom.write_byte(music_address, music) rom.write_byte(music_address, music)
my_prices = [my_item['price'] for my_item in shop_items]
price_scale = (80*max(8, len(my_prices)+2))/sum(my_prices)
for i in shop_items:
i['price'] *= price_scale
if i['price'] < 5: i['price'] = 5
else: i['price'] = int((i['price']//5)*5)
if world.mapshuffle[player]: if world.mapshuffle[player]:
rom.write_byte(0x155C9, local_random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle rom.write_byte(0x155C9, local_random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle

View File

@ -13,13 +13,13 @@ general_options:
# Null means nothing, for the server this means to default the value # Null means nothing, for the server this means to default the value
# These overwrite command line arguments! # These overwrite command line arguments!
server_options: server_options:
host: 0.0.0.0 host: null
port: 38281 port: 38281
password: null password: null
multidata: null multidata: null
savefile: null savefile: null
disable_save: false disable_save: false
loglevel: "debug" loglevel: "info"
# Allows for clients to log on and manage the server. If this is null, no remote administration is possible. # Allows for clients to log on and manage the server. If this is null, no remote administration is possible.
server_password: null server_password: null
# Automatically forward the port that is used, then close that port after 24 hours # Automatically forward the port that is used, then close that port after 24 hours
@ -28,9 +28,9 @@ server_options:
disable_item_cheat: false disable_item_cheat: false
# Client hint system # Client hint system
# Points given to a player for each acquired item in their world # Points given to a player for each acquired item in their world
location_check_points: 50 location_check_points: 1
# Point cost to receive a hint via !hint for players # Point cost to receive a hint via !hint for players
hint_cost: 0 # Set to 0 if you want free hints hint_cost: 1000 # Set to 0 if you want free hints
# Forfeit modes # Forfeit modes
# "disabled" -> clients can't forfeit, # "disabled" -> clients can't forfeit,
# "enabled" -> clients can always forfeit # "enabled" -> clients can always forfeit