From dbf2325c015af3adea2007849816080683afebe0 Mon Sep 17 00:00:00 2001 From: Mysteryem Date: Sat, 20 Dec 2025 21:32:12 +0000 Subject: [PATCH] KH2: Fix placing single items onto multiple locations in pre_fill (#5619) `goofy_pre_fill` and `donald_pre_fill` would pick a random `Item` from a `list[Item]` and then use `list.remove()` to remove the picked `Item`, but the lists (at least `donald_weapon_abilities`) could contain multiple items with the same name, so `list.remove()` could remove a different `Item` to the picked `Item`, allowing an `Item` in the list to be picked and placed more than once. This happens because `Item.__eq__` only compares the item's `.name` and `.player`, and `list.remove()` compares by equality, meaning it can remove a different, but equal, instance from the list. This results in `old_location.item` not being cleared, so `old_location.item` and `new_location.item` would refer to the same item. --- worlds/kh2/__init__.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/worlds/kh2/__init__.py b/worlds/kh2/__init__.py index 3068e7bb56..f13dec7265 100644 --- a/worlds/kh2/__init__.py +++ b/worlds/kh2/__init__.py @@ -390,9 +390,9 @@ class KH2World(World): # take one of the 2 out # randomize the list with only for location in goofy_weapon_location_list: - random_ability = self.random.choice(self.goofy_weapon_abilities) + i = self.random.randrange(len(self.goofy_weapon_abilities)) + random_ability = self.goofy_weapon_abilities.pop(i) location.place_locked_item(random_ability) - self.goofy_weapon_abilities.remove(random_ability) if not self.options.DonaldGoofyStatsanity: # plando goofy get bonuses @@ -401,10 +401,9 @@ class KH2World(World): if len(goofy_get_bonus_location_pool) > len(self.goofy_get_bonus_abilities): raise Exception(f"Too little abilities to fill goofy get bonus locations for player {self.player_name}.") for location in goofy_get_bonus_location_pool: - self.random.choice(self.goofy_get_bonus_abilities) - random_ability = self.random.choice(self.goofy_get_bonus_abilities) + i = self.random.randrange(len(self.goofy_get_bonus_abilities)) + random_ability = self.goofy_get_bonus_abilities.pop(i) location.place_locked_item(random_ability) - self.goofy_get_bonus_abilities.remove(random_ability) def donald_pre_fill(self): donald_weapon_location_list = [self.multiworld.get_location(location, self.player) for location in @@ -413,9 +412,9 @@ class KH2World(World): # take one of the 2 out # randomize the list with only for location in donald_weapon_location_list: - random_ability = self.random.choice(self.donald_weapon_abilities) + i = self.random.randrange(len(self.donald_weapon_abilities)) + random_ability = self.donald_weapon_abilities.pop(i) location.place_locked_item(random_ability) - self.donald_weapon_abilities.remove(random_ability) # if option is turned off if not self.options.DonaldGoofyStatsanity: donald_get_bonus_location_pool = [self.multiworld.get_location(location, self.player) for location in @@ -423,9 +422,9 @@ class KH2World(World): if len(donald_get_bonus_location_pool) > len(self.donald_get_bonus_abilities): raise Exception(f"Too little abilities to fill donald get bonus locations for player {self.player_name}.") for location in donald_get_bonus_location_pool: - random_ability = self.random.choice(self.donald_get_bonus_abilities) + i = self.random.randrange(len(self.donald_get_bonus_abilities)) + random_ability = self.donald_get_bonus_abilities.pop(i) location.place_locked_item(random_ability) - self.donald_get_bonus_abilities.remove(random_ability) def keyblade_pre_fill(self): """