Core: Fix playthrough only checking half of the sphere 0 items (#4268)

* Core: Fix playthrough only checking half of the sphere 0 items

The lists of precollected items were being mutated while iterating those
same lists, causing playthrough to skip checking half of the sphere 0
advancement items.

This patch ensures the lists are copied before they are iterated.

* Replace chain.from_iterable with two for loops for better clarity

Added a comment to `multiworld.push_precollected(item)` to explain that
it is also modifying `precollected_items`.
This commit is contained in:
Mysteryem 2024-11-29 00:38:17 +00:00 committed by GitHub
parent 5d30d16e09
commit 3cb5219e09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 15 additions and 8 deletions

View File

@ -1384,11 +1384,18 @@ class Spoiler:
# second phase, sphere 0 # second phase, sphere 0
removed_precollected: List[Item] = [] removed_precollected: List[Item] = []
for item in (i for i in chain.from_iterable(multiworld.precollected_items.values()) if i.advancement):
for precollected_items in multiworld.precollected_items.values():
# The list of items is mutated by removing one item at a time to determine if each item is required to beat
# the game, and re-adding that item if it was required, so a copy needs to be made before iterating.
for item in precollected_items.copy():
if not item.advancement:
continue
logging.debug('Checking if %s (Player %d) is required to beat the game.', item.name, item.player) logging.debug('Checking if %s (Player %d) is required to beat the game.', item.name, item.player)
multiworld.precollected_items[item.player].remove(item) precollected_items.remove(item)
multiworld.state.remove(item) multiworld.state.remove(item)
if not multiworld.can_beat_game(): if not multiworld.can_beat_game():
# Add the item back into `precollected_items` and collect it into `multiworld.state`.
multiworld.push_precollected(item) multiworld.push_precollected(item)
else: else:
removed_precollected.append(item) removed_precollected.append(item)