diff --git a/Fill.py b/Fill.py index 67cfdf32..0b50dfa8 100644 --- a/Fill.py +++ b/Fill.py @@ -229,6 +229,7 @@ def flood_items(world): itempool.remove(item_to_place) break + def balance_multiworld_progression(world): balanceable_players = {player for player in range(1, world.players + 1) if world.progression_balancing[player]} if not balanceable_players: diff --git a/Main.py b/Main.py index b3f32815..3d4ef43d 100644 --- a/Main.py +++ b/Main.py @@ -177,6 +177,38 @@ def main(args, seed=None): elif args.algorithm == 'balanced': 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: balance_multiworld_progression(world) diff --git a/Regions.py b/Regions.py index 0d6a7a04..72a57046 100644 --- a/Regions.py +++ b/Regions.py @@ -416,7 +416,7 @@ def create_shops(world, player: int): pass else: 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)) 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) @@ -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_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)], 'discount_potion': [('Red Potion', 120), ('Green Potion', 60), ('Blue Potion', 160)], 'bottle': [('Bee', 10)], diff --git a/Rom.py b/Rom.py index 6ed6f388..afc6bd55 100644 --- a/Rom.py +++ b/Rom.py @@ -633,6 +633,8 @@ def patch_rom(world, rom, player, team, enemized): distinguished_prog_bow_loc.item.code = 0x65 # patch items + shop_items = [] + for location in world.get_locations(): if location.player != player: continue @@ -659,9 +661,19 @@ def patch_rom(world, rom, player, team, enemized): my_item['replacement'] = my_item['item'] my_item['replacement_price'] = my_item['price'] 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['player'] = item.player if item.player != location.player else 0 + shop_items.append(my_item) continue if not location.crystal: @@ -702,6 +714,14 @@ def patch_rom(world, rom, player, team, enemized): for music_address in music_addresses: 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]: rom.write_byte(0x155C9, local_random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle diff --git a/host.yaml b/host.yaml index cabacd4f..33e749d0 100644 --- a/host.yaml +++ b/host.yaml @@ -13,13 +13,13 @@ general_options: # Null means nothing, for the server this means to default the value # These overwrite command line arguments! server_options: - host: 0.0.0.0 + host: null port: 38281 password: null multidata: null savefile: null 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. server_password: null # Automatically forward the port that is used, then close that port after 24 hours @@ -28,9 +28,9 @@ server_options: disable_item_cheat: false # Client hint system # 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 - hint_cost: 0 # Set to 0 if you want free hints + hint_cost: 1000 # Set to 0 if you want free hints # Forfeit modes # "disabled" -> clients can't forfeit, # "enabled" -> clients can always forfeit