From 2e9fda1936e045c5e3a70f08f4ffebeeac64bb32 Mon Sep 17 00:00:00 2001 From: Aaron Wagener Date: Sat, 4 May 2024 05:42:36 -0500 Subject: [PATCH] Fill: allow for single player fill restrictive placement and sweeping (#2415) * Core: allow for single player state sweeping * Fill: have distribute items use single_player fill when it can * oop * pass locations to sweep_for_events instead of the player * finally found the diff that was breaking swap * LTTP fills everyone's dungeons at once, not just a single player's --------- Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> --- Fill.py | 22 +++++++++++++++------- worlds/alttp/Dungeons.py | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Fill.py b/Fill.py index e65f027408c1..d9919c133847 100644 --- a/Fill.py +++ b/Fill.py @@ -19,11 +19,12 @@ def _log_fill_progress(name: str, placed: int, total_items: int) -> None: logging.info(f"Current fill step ({name}) at {placed}/{total_items} items placed.") -def sweep_from_pool(base_state: CollectionState, itempool: typing.Sequence[Item] = tuple()) -> CollectionState: +def sweep_from_pool(base_state: CollectionState, itempool: typing.Sequence[Item] = tuple(), + locations: typing.Optional[typing.List[Location]] = None) -> CollectionState: new_state = base_state.copy() for item in itempool: new_state.collect(item, True) - new_state.sweep_for_events() + new_state.sweep_for_events(locations=locations) return new_state @@ -66,7 +67,8 @@ def fill_restrictive(multiworld: MultiWorld, base_state: CollectionState, locati item_pool.pop(p) break maximum_exploration_state = sweep_from_pool( - base_state, item_pool + unplaced_items) + base_state, item_pool + unplaced_items, multiworld.get_filled_locations(item.player) + if single_player_placement else None) has_beaten_game = multiworld.has_beaten_game(maximum_exploration_state) @@ -112,7 +114,9 @@ def fill_restrictive(multiworld: MultiWorld, base_state: CollectionState, locati location.item = None placed_item.location = None - swap_state = sweep_from_pool(base_state, [placed_item, *item_pool] if unsafe else item_pool) + swap_state = sweep_from_pool(base_state, [placed_item, *item_pool] if unsafe else item_pool, + multiworld.get_filled_locations(item.player) + if single_player_placement else None) # unsafe means swap_state assumes we can somehow collect placed_item before item_to_place # by continuing to swap, which is not guaranteed. This is unsafe because there is no mechanic # to clean that up later, so there is a chance generation fails. @@ -170,7 +174,9 @@ def fill_restrictive(multiworld: MultiWorld, base_state: CollectionState, locati if cleanup_required: # validate all placements and remove invalid ones - state = sweep_from_pool(base_state, []) + state = sweep_from_pool( + base_state, [], multiworld.get_filled_locations(item.player) + if single_player_placement else None) for placement in placements: if multiworld.worlds[placement.item.player].options.accessibility != "minimal" and not placement.can_reach(state): placement.item.location = None @@ -456,14 +462,16 @@ def mark_for_locking(location: Location): if prioritylocations: # "priority fill" - fill_restrictive(multiworld, multiworld.state, prioritylocations, progitempool, swap=False, on_place=mark_for_locking, + fill_restrictive(multiworld, multiworld.state, prioritylocations, progitempool, + single_player_placement=multiworld.players == 1, swap=False, on_place=mark_for_locking, name="Priority") accessibility_corrections(multiworld, multiworld.state, prioritylocations, progitempool) defaultlocations = prioritylocations + defaultlocations if progitempool: # "advancement/progression fill" - fill_restrictive(multiworld, multiworld.state, defaultlocations, progitempool, name="Progression") + fill_restrictive(multiworld, multiworld.state, defaultlocations, progitempool, single_player_placement=multiworld.players == 1, + name="Progression") if progitempool: raise FillError( f"Not enough locations for progression items. " diff --git a/worlds/alttp/Dungeons.py b/worlds/alttp/Dungeons.py index f0b8c2d971b0..150d52cc6c58 100644 --- a/worlds/alttp/Dungeons.py +++ b/worlds/alttp/Dungeons.py @@ -264,7 +264,7 @@ def fill_dungeons_restrictive(multiworld: MultiWorld): if loc in all_state_base.events: all_state_base.events.remove(loc) - fill_restrictive(multiworld, all_state_base, locations, in_dungeon_items, True, True, allow_excluded=True, + fill_restrictive(multiworld, all_state_base, locations, in_dungeon_items, lock=True, allow_excluded=True, name="LttP Dungeon Items")