From 4c2887c0a14ead83a5025e17961ea95e8cfe4293 Mon Sep 17 00:00:00 2001 From: aerinon Date: Mon, 15 Nov 2021 16:23:53 -0700 Subject: [PATCH 01/15] Fix baserom --- Rom.py | 2 +- data/base2current.bps | Bin 136415 -> 136173 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index f3b3cb68..ad4ce2d4 100644 --- a/Rom.py +++ b/Rom.py @@ -32,7 +32,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '2cfa164d4b66a15406f53ca4750ef59a' +RANDOMIZERBASEHASH = '7511c811385f87c6ae0909e7bbe379cb' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 328d0f8196c9f52c4e8bb095e2ff83a9157dc2ea..12fb7ccd3056db6ef6002726b78a903d201b0ea0 100644 GIT binary patch delta 8553 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 delta 8925 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 From 500ec0717483bc0bd3b5643fc58f491bd317f945 Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 19 Nov 2021 16:03:41 -0700 Subject: [PATCH 02/15] Add bomb assumptions to certain bosses --- Bosses.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Bosses.py b/Bosses.py index 90acafcf..d577c66d 100644 --- a/Bosses.py +++ b/Bosses.py @@ -32,7 +32,7 @@ def LanmolasDefeatRule(state, player): state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or - state.has('Cane of Byrna', player) or + (state.has('Cane of Byrna', player) and state.can_use_bombs(player)) or state.can_shoot_arrows(player)) def MoldormDefeatRule(state, player): @@ -51,7 +51,7 @@ def ArrghusDefeatRule(state, player): return True return ((state.has('Fire Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 12))) or #assuming mostly gitting two puff with one shot - (state.has('Ice Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 16)))) + (state.has('Ice Rod', player) and state.can_use_bombs(player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 16)))) def MothulaDefeatRule(state, player): @@ -92,7 +92,7 @@ def KholdstareDefeatRule(state, player): ) def VitreousDefeatRule(state, player): - return state.can_shoot_arrows(player) or state.has_blunt_weapon(player) + return (state.can_shoot_arrows(player) and state.can_use_bombs(player)) or state.has_blunt_weapon(player) def TrinexxDefeatRule(state, player): if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)): From 10a440e4ee8280599218a3665ae7cab2c222a43e Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 19 Nov 2021 16:09:00 -0700 Subject: [PATCH 03/15] Potential fix for money balancing --- Fill.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Fill.py b/Fill.py index 2cf1f25e..6a5a8fc9 100644 --- a/Fill.py +++ b/Fill.py @@ -762,9 +762,12 @@ def balance_money_progression(world): if sphere_costs[player] > 0 and sphere_costs[player] > wallet[player]: insolvent.add(player) if len([p for p in solvent if len(locked_by_money[p]) > 0]) == 0: - target_player = min(insolvent, key=lambda p: sphere_costs[p]-wallet[p]) - difference = sphere_costs[target_player]-wallet[target_player] - logger.debug(f'Money balancing needed: Player {target_player} short {difference}') + if len(insolvent) > 0: + target_player = min(insolvent, key=lambda p: sphere_costs[p]-wallet[p]) + difference = sphere_costs[target_player]-wallet[target_player] + logger.debug(f'Money balancing needed: Player {target_player} short {difference}') + else: + difference = 0 while difference > 0: swap_targets = [x for x in unchecked_locations if x not in sphere_locations and x.item.name.startswith('Rupees') and x.item.player == target_player] if len(swap_targets) == 0: From d710e08ea0de507da423c95944ee265a84c7bdf2 Mon Sep 17 00:00:00 2001 From: aerinon Date: Mon, 6 Dec 2021 15:25:55 -0700 Subject: [PATCH 04/15] Rules fixes - TT locations not foribben by default to have big key Can push paradox block with mirror in glitched modes --- Rules.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Rules.py b/Rules.py index cf19fbb1..83a2175b 100644 --- a/Rules.py +++ b/Rules.py @@ -274,9 +274,11 @@ def global_rules(world, player): set_rule(world.get_location('Thieves\' Town - Big Chest', player), lambda state: state.has('Hammer', player)) for entrance in ['Thieves Basement Block Path', 'Thieves Blocked Entry Path', 'Thieves Conveyor Block Path', 'Thieves Conveyor Bridge Block Path']: set_rule(world.get_entrance(entrance, player), lambda state: state.can_lift_rocks(player)) - for location in ['Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']: - forbid_item(world.get_location(location, player), 'Big Key (Thieves Town)', player) - forbid_item(world.get_location('Thieves\' Town - Blind\'s Cell', player), 'Big Key (Thieves Town)', player) + + # I think these rules are unnecessary now - testing needed + # for location in ['Thieves\' Town - Blind\'s Cell', 'Thieves\' Town - Boss']: + # forbid_item(world.get_location(location, player), 'Big Key (Thieves Town)', player) + # forbid_item(world.get_location('Thieves\' Town - Blind\'s Cell', player), 'Big Key (Thieves Town)', player) for location in ['Suspicious Maiden', 'Thieves\' Town - Blind\'s Cell']: set_rule(world.get_location(location, player), lambda state: state.has('Big Key (Thieves Town)', player)) set_rule(world.get_location('Revealing Light', player), lambda state: state.has('Shining Light', player) and state.has('Maiden Rescued', player)) @@ -712,7 +714,8 @@ def default_rules(world, player): set_rule(world.get_entrance('Broken Bridge (East)', player), lambda state: state.has('Hookshot', player)) set_rule(world.get_entrance('East Death Mountain Teleporter', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Fairy Ascension Rocks', player), lambda state: state.can_lift_heavy_rocks(player)) - set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block + # can erase block - overridden in noglitches + set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player)) set_rule(world.get_entrance('Turtle Rock Teleporter', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Hammer', player)) set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player)) @@ -849,7 +852,8 @@ def inverted_rules(world, player): set_rule(world.get_entrance('Broken Bridge (East)', player), lambda state: state.has('Hookshot', player) and state.has_Pearl(player)) set_rule(world.get_entrance('Dark Death Mountain Teleporter (East Bottom)', player), lambda state: state.can_lift_heavy_rocks(player)) set_rule(world.get_entrance('Fairy Ascension Rocks', player), lambda state: state.can_lift_heavy_rocks(player) and state.has_Pearl(player)) - set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has('Mirror', player)) # can erase block + # can erase block - overridden in noglitches + set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: state.has_Mirror(player)) set_rule(world.get_entrance('Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player)) set_rule(world.get_entrance('Dark Death Mountain Teleporter (East)', player), lambda state: state.can_lift_heavy_rocks(player) and state.has('Hammer', player) and state.has_Pearl(player)) # bunny cannot use hammer set_rule(world.get_entrance('East Death Mountain (Top)', player), lambda state: state.has('Hammer', player) and state.has_Pearl(player)) # bunny can not use hammer From 74155ec5ae4e29c8ed326ab7e03a760da007af1e Mon Sep 17 00:00:00 2001 From: aerinon Date: Mon, 6 Dec 2021 15:28:19 -0700 Subject: [PATCH 05/15] Version and release note update --- Main.py | 2 +- RELEASENOTES.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Main.py b/Main.py index 453e33e8..05363732 100644 --- a/Main.py +++ b/Main.py @@ -29,7 +29,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops from Utils import output_path, parse_player_names -__version__ = '0.5.1.5-u' +__version__ = '0.5.1.6-u' from source.classes.BabelFish import BabelFish diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c1a7a62c..eaa45e2b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -15,6 +15,10 @@ CLI: ```--bombbag``` # Bug Fixes and Notes. +* 0.5.1.6 + * Rules fixes for TT (Boss and Cell) can now have TT Big Key if not otherwise required (boss shuffle + crossed dungeon) + * BUg fix for money balancing + * Add some bomb assumptions for bosses in bombbag mode * 0.5.1.5 * Fix for hard pool capacity upgrades missing * Bonk Fairy (Light) is no longer in logic for ER Standard and is forbidden to be a connector, so rain state isn't exitable From 7f871681bb0723ca10cdffb3b5c5f083f4878e96 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 10 Dec 2021 16:42:26 -0600 Subject: [PATCH 06/15] Added dynamic flute spot reservation --- OverworldShuffle.py | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index d6c1e331..62b7d6e4 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -265,6 +265,8 @@ def link_overworld(world, player): assert len(forward_set) == len(back_set) for (forward_edge, back_edge) in zip(forward_set, back_set): connect_two_way(world, forward_edge, back_edge, player, connected_edges) + + world.owsectors[player] = build_sectors(world, player) else: if world.owKeepSimilar[player] and world.owShuffle[player] in ['vanilla', 'parallel']: for exitname, destname in parallelsimilar_connections: @@ -334,6 +336,7 @@ def link_overworld(world, player): assert valid_layout, 'Could not find a valid OW layout' # flute shuffle + logging.getLogger('').debug('Shuffling flute spots') def connect_flutes(flute_destinations): for o in range(0, len(flute_destinations)): owslot = flute_destinations[o] @@ -376,23 +379,37 @@ def link_overworld(world, player): flute_pool.remove(owid) new_spots.append(owid) return True + + # determine sectors (isolated groups of regions) to place flute spots + flute_regions = {(f[0][0] if f[1] not in world.owswaps[player][0] else f[0][1]) : o for o, f in flute_data.items()} + flute_sectors = [(len([r for l in s for r in l]), [r for l in s for r in l if r in flute_regions]) for s in world.owsectors[player]] + flute_sectors = [s for s in flute_sectors if len(s[1]) > 0] + region_total = sum([c for c,_ in flute_sectors]) + sector_total = len(flute_sectors) - # guarantee desert/mire access - addSpot(0x38) + # reserve a number of flute spots for each sector + flute_spots = 8 + for sector in flute_sectors: + sector_total -= 1 + spots_to_place = min(flute_spots - sector_total, max(1, round((sector[0] * (flute_spots - sector_total) / region_total) + 0.5))) + target_spots = len(new_spots) + spots_to_place + + if 'Desert Palace Teleporter Ledge' in sector[1] or 'Misery Mire Teleporter Ledge' in sector[1]: + addSpot(0x38) # guarantee desert/mire access - # guarantee mountain access - if world.owShuffle[player] == 'vanilla': - mountainIds = [0x0b, 0x0e, 0x07] - addSpot(mountainIds[random.randint(0, 2)]) + random.shuffle(sector[1]) + f = 0 + while len(new_spots) < target_spots: + if f >= len(sector[1]): + f = 0 + if sector[1][f] not in new_spots: + addSpot(flute_regions[sector[1][f]]) + f += 1 - random.shuffle(flute_pool) - f = 0 - while len(new_spots) < 8: - if f >= len(flute_pool): - f = 0 - if flute_pool[f] not in new_spots: - addSpot(flute_pool[f]) - f += 1 + region_total -= sector[0] + flute_spots -= spots_to_place + + # connect new flute spots new_spots.sort() world.owflutespots[player] = new_spots connect_flutes(new_spots) From 4ae211e213991175c14e2b6ead0b24687f63b803 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 11 Dec 2021 17:11:58 -0600 Subject: [PATCH 07/15] Fixed spoiler json structure for map output --- BaseClasses.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 9acbaeaf..f28a6d88 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2749,9 +2749,9 @@ class Spoiler(object): if type not in self.maps: self.maps[type] = {} if self.world.players == 1: - self.maps[type][player] = OrderedDict([('text', text), ('data', data)]) + self.maps[(type, player)] = OrderedDict([('type', type), ('text', text), ('data', data)]) else: - self.maps[type][player] = OrderedDict([('player', player), ('text', text), ('data', data)]) + self.maps[(type, player)] = OrderedDict([('player', player), ('type', type), ('text', text), ('data', data)]) def set_entrance(self, entrance, exit, direction, player): if self.world.players == 1: From abfe08ab6ded91cf40563dfc82277cb858c2f4f6 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 13 Dec 2021 23:17:29 -0600 Subject: [PATCH 08/15] Improvement to FF damage fix to insta-warp Link to destination when Link exceeds bounds of current screen --- Rom.py | 2 +- data/base2current.bps | Bin 141395 -> 141422 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 2fe1bdfa..6c57d091 100644 --- a/Rom.py +++ b/Rom.py @@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '607ec23701b1099fdeb64a0caff190b6' +RANDOMIZERBASEHASH = 'c5903112ffe302d1e9a3878ee720d1b3' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 022ded6aaf463776b1c65a008fadf21a177ec305..e229d170797f13706d1ad802e3f48d116ebf9321 100644 GIT binary patch delta 7852 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 delta 7796 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 From c910785211b7cd573620fe29d4cb5ee069352afc Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 16 Dec 2021 14:27:13 -0600 Subject: [PATCH 09/15] Fixed Lake Shop not having Blue Potion in Inverted --- Regions.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Regions.py b/Regions.py index b4a48d73..8f8ee418 100644 --- a/Regions.py +++ b/Regions.py @@ -1121,9 +1121,11 @@ def mark_dark_world_regions(world, player): def create_shops(world, player): world.shops[player] = [] for region_name, (room_id, type, shopkeeper, custom, locked, inventory, sram) in shop_table.items(): - if (world.mode[player] == 'inverted') != (0x35 in world.owswaps[player][0] and world.owMixed[player]) and region_name == 'Dark Lake Hylia Shop': - locked = True - inventory = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)] + if world.mode[player] == 'inverted': + if (0x35 not in world.owswaps[player][0] and region_name == 'Dark Lake Hylia Shop') \ + or (0x35 in world.owswaps[player][0] and region_name == 'Cave Shop (Lake Hylia)'): + locked = True + inventory = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)] region = world.get_region(region_name, player) shop = Shop(region, room_id, type, shopkeeper, custom, locked, sram) region.shop = shop From fdbda7a9c1dc515d34ae1ad5da17ca2ed39bee87 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 16 Dec 2021 15:43:10 -0600 Subject: [PATCH 10/15] Fixed issue with spoiler output of OW Tile Swaps --- BaseClasses.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index f28a6d88..6fd15ba7 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2746,8 +2746,6 @@ class Spoiler(object): self.overworlds[(entrance, direction, player)] = OrderedDict([('player', player), ('entrance', entrance), ('exit', exit), ('direction', direction)]) def set_map(self, type, text, data, player): - if type not in self.maps: - self.maps[type] = {} if self.world.players == 1: self.maps[(type, player)] = OrderedDict([('type', type), ('text', text), ('data', data)]) else: @@ -3032,12 +3030,15 @@ class Spoiler(object): if self.overworlds: outfile.write('\n\nOverworld:\n\n') # overworld tile swaps - if 'swaps' in self.maps: - outfile.write('OW Tile Swaps:\n') - for player in self.maps['swaps']: + for player in range(1, self.world.players + 1): + if ('swaps', player) in self.maps: + outfile.write('OW Tile Swaps:\n') + break + for player in range(1, self.world.players + 1): + if ('swaps', player) in self.maps: if self.world.players > 1: outfile.write(str('(Player ' + str(player) + ')\n')) # player name - outfile.write(self.maps['swaps'][player]['text'] + '\n\n') + outfile.write(self.maps[('swaps', player)]['text'] + '\n\n') # overworld transitions outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta","overworlds",entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta","overworlds",entry['exit'])) for entry in self.overworlds.values()])) From 07a956a3a4d6fc56213244bd70239c07b3820943 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 16 Dec 2021 16:17:51 -0600 Subject: [PATCH 11/15] Fixed issue with logic not correctly placing Blue potion in Dark Lake Shop --- Main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Main.py b/Main.py index 2ef4ccc6..a4dc5d68 100644 --- a/Main.py +++ b/Main.py @@ -175,6 +175,7 @@ def main(args, seed=None, fish=None): for player in range(1, world.players + 1): link_overworld(world, player) + create_shops(world, player) update_world_regions(world, player) create_flute_exits(world, player) From f2600db3f3abdc90a544369a18bfe4ea80418ef6 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 19 Dec 2021 19:55:44 -0600 Subject: [PATCH 12/15] Added new OW Crossed option None (Allowed) to support legacy functionality of when invalid values are used --- README.md | 2 ++ resources/app/cli/args.json | 1 + resources/app/cli/lang/en.json | 1 + resources/app/gui/lang/en.json | 1 + resources/app/gui/randomize/overworld/widgets.json | 1 + 5 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 5eb15aea..bfd37cb6 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ OW Transitions are shuffled within each world separately. This allows OW connections to be shuffled cross-world. +'None (Allowed)' allows entrance connectors and whirlpools to result in cross-world behavior, but edge transitions will not. This isn't a recommended option. + Polar and Grouped both are guaranteed to result in two separated planes of tiles. To navigate to the other plane, you have the following methods: 1) Normal portals 2) Mirroring on DW tiles 3) Fluting to a LW tile that was previously unreachable Limited and Chaos are not bound to follow a two-plane framework. This means that it could be possible to travel on foot to every tile without entering a normal portal. diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 365e40e6..8e10afde 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -119,6 +119,7 @@ "ow_crossed": { "choices": [ "none", + "allowed", "polar", "grouped", "limited", diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index 59d9a9f3..2f5d962d 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -208,6 +208,7 @@ "ow_crossed": [ "This allows cross-world connections to occur on the overworld.", "None: No transitions are cross-world connections.", + "Allowed: Only entrances/whirlpools can end up cross-world.", "Polar: Only used when Mixed is enabled. This retains original", " connections even when overworld tiles are swapped.", "Limited: Exactly nine transitions are randomly chosen as", diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 2e69ba8e..a057e5ab 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -119,6 +119,7 @@ "randomizer.overworld.crossed": "Crossed", "randomizer.overworld.crossed.none": "None", + "randomizer.overworld.crossed.allowed": "None (Allowed)", "randomizer.overworld.crossed.polar": "Polar", "randomizer.overworld.crossed.grouped": "Grouped", "randomizer.overworld.crossed.limited": "Limited", diff --git a/resources/app/gui/randomize/overworld/widgets.json b/resources/app/gui/randomize/overworld/widgets.json index f6751bc2..43dc9394 100644 --- a/resources/app/gui/randomize/overworld/widgets.json +++ b/resources/app/gui/randomize/overworld/widgets.json @@ -14,6 +14,7 @@ "default": "vanilla", "options": [ "none", + "allowed", "polar", "grouped", "limited", From 7699c1fc63474fb46d930c33d4fab35a5fb81143 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 19 Dec 2021 19:56:27 -0600 Subject: [PATCH 13/15] Fixed Blue Potion not showing up in Dark Lake Shop in Inverted --- Regions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Regions.py b/Regions.py index 8f8ee418..f1d372cf 100644 --- a/Regions.py +++ b/Regions.py @@ -1125,6 +1125,7 @@ def create_shops(world, player): if (0x35 not in world.owswaps[player][0] and region_name == 'Dark Lake Hylia Shop') \ or (0x35 in world.owswaps[player][0] and region_name == 'Cave Shop (Lake Hylia)'): locked = True + custom = True inventory = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)] region = world.get_region(region_name, player) shop = Shop(region, room_id, type, shopkeeper, custom, locked, sram) From d79adbf3c87c66f15345820ab4ceab0b5b2c0539 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 19 Dec 2021 19:59:30 -0600 Subject: [PATCH 14/15] Fix deterministic issues in repeat seed generation --- BaseClasses.py | 6 ++++-- DoorShuffle.py | 4 ++-- EntranceShuffle.py | 34 +++++++++++++++++----------------- OverworldShuffle.py | 15 ++++++++------- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 6fd15ba7..0c2925e5 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1658,7 +1658,8 @@ class Entrance(object): from OWEdges import OWTileRegions from OverworldShuffle import ow_connections owid = OWTileRegions[follower_region.name] - (mirror_map, other_world) = ow_connections[owid % 0x40] + (mirror_map_orig, other_world) = ow_connections[owid % 0x40] + mirror_map = list(mirror_map_orig).copy() mirror_map.extend(other_world) mirror_exit = None while len(mirror_map): @@ -1710,7 +1711,8 @@ class Entrance(object): from OWEdges import OWTileRegions from OverworldShuffle import ow_connections owid = OWTileRegions[dest_region.name] - (mirror_map, other_world) = ow_connections[owid % 0x40] + (mirror_map_orig, other_world) = ow_connections.copy()[owid % 0x40] + mirror_map = list(mirror_map_orig).copy() mirror_map.extend(other_world) mirror_map = [(x, d) for (x, d) in mirror_map if x in [e.name for e in dest_region.exits]] # loop thru potential places to leave a mirror portal diff --git a/DoorShuffle.py b/DoorShuffle.py index 6e80d19d..7964755e 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -1820,7 +1820,7 @@ def find_inaccessible_regions(world, player): else: start_regions = ['Links House', 'Dark Sanctuary Hint'] regs = convert_regions(start_regions, world, player) - all_regions = set([r for r in world.regions if r.player == player and r.type is not RegionType.Dungeon]) + all_regions = [r for r in world.regions if r.player == player and r.type is not RegionType.Dungeon] visited_regions = set() queue = deque(regs) while len(queue) > 0: @@ -1836,7 +1836,7 @@ def find_inaccessible_regions(world, player): if connect and connect not in queue and connect not in visited_regions: if connect.type is not RegionType.Dungeon or connect.name.endswith(' Portal'): queue.append(connect) - world.inaccessible_regions[player].extend([r.name for r in all_regions.difference(visited_regions) if valid_inaccessible_region(r)]) + world.inaccessible_regions[player].extend([r.name for r in all_regions if r not in visited_regions and valid_inaccessible_region(r)]) if (world.mode[player] == 'inverted') != (0x1b in world.owswaps[player][0] and world.owMixed[player]): ledge = world.get_region('Hyrule Castle Ledge', player) if any(x for x in ledge.exits if x.connected_region and x.connected_region.name == 'Agahnims Tower Portal'): diff --git a/EntranceShuffle.py b/EntranceShuffle.py index 1017e6d7..2b51eaaf 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -1,5 +1,5 @@ import logging -from collections import defaultdict +from collections import defaultdict, OrderedDict import RaceRandom as random from BaseClasses import CollectionState, RegionType from OverworldShuffle import build_accessible_region_list @@ -432,21 +432,21 @@ def link_entrances(world, player): connector_entrances = [e for e in list(zip(*default_connector_connections + default_dungeon_connections + open_default_dungeon_connections))[0] if e in (dw_entrances if not invFlag else lw_entrances)] connect_inaccessible_regions(world, [], connector_entrances, caves, player) if invFlag: - lw_dungeons = list(set(lw_dungeons) & set(caves)) + lw_dungeons = list(OrderedDict.fromkeys(lw_dungeons + caves)) else: - dw_dungeons = list(set(dw_dungeons) & set(caves)) + dw_dungeons = list(OrderedDict.fromkeys(dw_dungeons + caves)) - caves = list(set(Cave_Base) & set(caves)) + (lw_dungeons if not invFlag else dw_dungeons) + caves = list(OrderedDict.fromkeys(Cave_Base + caves)) + (lw_dungeons if not invFlag else dw_dungeons) connector_entrances = [e for e in list(zip(*default_connector_connections + default_dungeon_connections + open_default_dungeon_connections))[0] if e in (lw_entrances if not invFlag else dw_entrances)] connect_inaccessible_regions(world, connector_entrances, [], caves, player) if not invFlag: - lw_dungeons = list(set(lw_dungeons) & set(caves)) + lw_dungeons = list(OrderedDict.fromkeys(lw_dungeons + caves)) else: - dw_dungeons = list(set(dw_dungeons) & set(caves)) + dw_dungeons = list(OrderedDict.fromkeys(dw_dungeons + caves)) lw_dungeons = lw_dungeons + (Old_Man_House if not invFlag else []) dw_dungeons = dw_dungeons + ([] if not invFlag else Old_Man_House) - caves = list(set(Cave_Base) & set(caves)) + DW_Mid_Dungeon_Exits + caves = list(OrderedDict.fromkeys(Cave_Base + caves)) + DW_Mid_Dungeon_Exits # place old man, has limited options lw_entrances = [e for e in lw_entrances if e in list(zip(*default_connector_connections + default_dungeon_connections + open_default_dungeon_connections))[0] and e in entrance_pool] @@ -1429,10 +1429,10 @@ def place_blacksmith(world, links_house, player): if invFlag: dark_sanc = world.get_entrance('Dark Sanctuary Hint Exit', player).connected_region.name - blacksmith_doors = list(set(blacksmith_doors + list(build_accessible_entrance_list(world, dark_sanc, player, assumed_inventory, False, True, True)))) + blacksmith_doors = list(OrderedDict.fromkeys(blacksmith_doors + list(build_accessible_entrance_list(world, dark_sanc, player, assumed_inventory, False, True, True)))) elif world.doorShuffle[player] == 'vanilla' or world.intensity[player] < 3: sanc_region = world.get_entrance('Sanctuary Exit', player).connected_region.name - blacksmith_doors = list(set(blacksmith_doors + list(build_accessible_entrance_list(world, sanc_region, player, assumed_inventory, False, True, True)))) + blacksmith_doors = list(OrderedDict.fromkeys(blacksmith_doors + list(build_accessible_entrance_list(world, sanc_region, player, assumed_inventory, False, True, True)))) if world.shuffle[player] in ['lite', 'lean']: blacksmith_doors = [e for e in blacksmith_doors if e in list(zip(*(default_item_connections + (default_shop_connections if world.shopsanity[player] else []))))[0]] @@ -1491,7 +1491,7 @@ def junk_fill_inaccessible(world, player): accessible_regions.append(region_name) break for region_name in accessible_regions.copy(): - accessible_regions = list(set(accessible_regions + list(build_accessible_region_list(base_world, region_name, player, False, True, False, False)))) + accessible_regions = list(OrderedDict.fromkeys(accessible_regions + list(build_accessible_region_list(base_world, region_name, player, False, True, False, False)))) world.inaccessible_regions[player] = [r for r in world.inaccessible_regions[player] if r not in accessible_regions] # get inaccessible entrances @@ -1527,7 +1527,7 @@ def connect_inaccessible_regions(world, lw_entrances, dw_entrances, caves, playe accessible_regions.append(region_name) break for region_name in accessible_regions.copy(): - accessible_regions = list(set(accessible_regions + list(build_accessible_region_list(world, region_name, player, True, True, False, False)))) + accessible_regions = list(OrderedDict.fromkeys(accessible_regions + list(build_accessible_region_list(world, region_name, player, True, True, False, False)))) world.inaccessible_regions[player] = [r for r in world.inaccessible_regions[player] if r not in accessible_regions] # split inaccessible into 2 lists for each world @@ -1665,12 +1665,12 @@ def build_accessible_entrance_list(world, start_region, player, assumed_inventor new_regions.append(ledge) explored_regions.extend(new_regions) - entrances = set() + entrances = list() for region_name in explored_regions: region = base_world.get_region(region_name, player) for exit in region.exits: if exit.name in entrance_pool and (not exit_rules or exit.access_rule(blank_state)): - entrances.add(exit.name) + entrances.append(exit.name) return entrances @@ -1798,7 +1798,7 @@ Cave_Three_Exits_Base = [('Spectacle Rock Cave Exit (Peak)', 'Spectacle Rock Cav Old_Man_House_Base = [('Old Man House Exit (Bottom)', 'Old Man House Exit (Top)')] -Entrance_Pool_Base = {'Links House', +Entrance_Pool_Base = ['Links House', 'Desert Palace Entrance (South)', 'Desert Palace Entrance (West)', 'Desert Palace Entrance (East)', @@ -1936,9 +1936,9 @@ Entrance_Pool_Base = {'Links House', 'Skull Woods First Section Hole (West)', 'Skull Woods First Section Hole (East)', 'Skull Woods First Section Hole (North)', - 'Pyramid Hole'} + 'Pyramid Hole'] -Exit_Pool_Base = {'Links House Exit', +Exit_Pool_Base = ['Links House Exit', 'Desert Palace Exit (South)', 'Desert Palace Exit (West)', 'Desert Palace Exit (East)', @@ -2076,7 +2076,7 @@ Exit_Pool_Base = {'Links House Exit', 'Skull Left Drop', 'Skull Pinball', 'Skull Pot Circle', - 'Pyramid'} + 'Pyramid'] # these are connections that cannot be shuffled and always exist. They link together separate parts of the world we need to divide into regions mandatory_connections = [('Links House S&Q', 'Links House'), diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 62b7d6e4..55a063ec 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -1,4 +1,5 @@ import RaceRandom as random, logging, copy +from collections import OrderedDict from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSlot, Entrance from Regions import mark_dark_world_regions, mark_light_world_regions from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel @@ -500,7 +501,7 @@ def shuffle_tiles(world, groups, result_list, player): exist_dw_regions.extend(dw_regions) # check whirlpool parity - valid_whirlpool_parity = world.owCrossed[player] not in ['none', 'grouped'] or len(set(new_results[0]) & set({0x0f, 0x12, 0x15, 0x33, 0x35, 0x3f, 0x55, 0x7f})) % 2 == 0 + valid_whirlpool_parity = world.owCrossed[player] not in ['none', 'grouped'] or len(OrderedDict.fromkeys(new_results[0] + [0x0f, 0x12, 0x15, 0x33, 0x35, 0x3f, 0x55, 0x7f])) % 2 == 0 (exist_owids, exist_lw_regions, exist_dw_regions) = result_list exist_owids.extend(new_results[0]) @@ -809,7 +810,7 @@ def can_reach_smith(world, player): def explore_region(region_name, region=None): nonlocal found - explored_regions.add(region_name) + explored_regions.append(region_name) if not found: if not region: region = world.get_region(region_name, player) @@ -838,7 +839,7 @@ def can_reach_smith(world, player): blank_state.collect(ItemFactory('Titans Mitts', player), True) found = False - explored_regions = set() + explored_regions = list() explore_region('Links House') if not found: if not invFlag: @@ -867,7 +868,7 @@ def build_sectors(world, player): if (any(r in unique_regions for r in explored_regions)): for s in range(len(sectors)): if (any(r in sectors[s] for r in explored_regions)): - sectors[s] = set(list(sectors[s]) + list(explored_regions)) + sectors[s] = list(list(sectors[s]) + list(explored_regions)) break else: sectors.append(explored_regions) @@ -893,7 +894,7 @@ def build_sectors(world, player): if (any(r in unique_regions for r in explored_regions)): for s2 in range(len(sectors2)): if (any(r in sectors2[s2] for r in explored_regions)): - sectors2[s2] = set(list(sectors2[s2]) + list(explored_regions)) + sectors2[s2] = list(sectors2[s2] + explored_regions) break else: sectors2.append(explored_regions) @@ -907,7 +908,7 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F from Items import ItemFactory def explore_region(region_name, region=None): - explored_regions.add(region_name) + explored_regions.append(region_name) if not region: region = base_world.get_region(region_name, player) for exit in region.exits: @@ -936,7 +937,7 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F blank_state = CollectionState(base_world) if base_world.mode[player] == 'standard': blank_state.collect(ItemFactory('Zelda Delivered', player), True) - explored_regions = set() + explored_regions = list() explore_region(start_region) return explored_regions From 5e2bbe68cb0d1806dc9f1b0d7f87a354391fd0b8 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 19 Dec 2021 20:29:31 -0600 Subject: [PATCH 15/15] Version bump 0.2.3.4 --- CHANGELOG.md | 10 ++++++++++ OverworldShuffle.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5860f08..dd9cae91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +### 0.2.3.4 +- Fixed major issue with subsequent seeds using same seed/settings resulting different +- Flute Shuffle now awards separated regions a prorated number of flute spots based on size +- Fixed spoiler log, was missing OW Tile Swap map +- Fixed spoiler log JSON output +- Fake flipper damage fix improved to skip the long delay after the scroll +- Fixed missing Blue Potion in Lake Shop in Inverted +- Added legacy OW Crossed option 'None (Allowed)' to support old behavior when invalid option was used in Mystery +- ~~Merged DR v0.5.1.6 - Money balancing fix/Boss logic fixes with Bombbag~~ + ### 0.2.3.3 - Added OW Layout validation that reduces the cases where some screens are unreachable - Fixed issue with mirror portals showing up in DW in Crossed OW diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 55a063ec..04f2d575 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -4,7 +4,7 @@ from BaseClasses import OWEdge, WorldType, RegionType, Direction, Terrain, PolSl from Regions import mark_dark_world_regions, mark_light_world_regions from OWEdges import OWTileRegions, OWTileGroups, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel -__version__ = '0.2.3.3-u' +__version__ = '0.2.3.4-u' def link_overworld(world, player): # setup mandatory connections