Files
dockipelago/worlds/tloz_oos/generation/PreFill.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

78 lines
4.2 KiB
Python

from BaseClasses import MultiWorld
from Fill import fill_restrictive
from ..World import OracleOfSeasonsWorld
from ..data import LOCATIONS_DATA
from ..data.Constants import DUNGEON_NAMES
def stage_pre_fill_dungeon_items(multiworld: MultiWorld):
# If keysanity is off, dungeon items can only be put inside local dungeon locations, and there are not so many
# of those which makes them pretty crowded.
# This usually ends up with generator not having anywhere to place a few small keys, making the seed unbeatable.
# To circumvent this, we perform a restricted pre-fills here, placing only those dungeon items
# before anything else.
oos_players = multiworld.get_game_players(OracleOfSeasonsWorld.game)
base_all_state = multiworld.get_all_state(False, collect_pre_fill_items=False, perform_sweep=False)
# Collect all pre_fill_items except our OoS's and then sweep. This gives more accurate results in cases of item
# plando being used to remove items from the item pool and placing them into locations locked behind pre_fill
# items.
for player in multiworld.player_ids:
if player in oos_players:
continue
subworld = multiworld.worlds[player]
for item in subworld.get_pre_fill_items():
subworld.collect(base_all_state, item)
base_all_state.sweep_for_advancements()
for filling_player in oos_players:
# Create a player-specific state for just the player that is filling dungeons.
per_player_base_all_state = base_all_state.copy()
# Collect the pre_fill_items() of all other OoS players into the state.
for other_player in oos_players:
if other_player == filling_player:
continue
subworld = multiworld.worlds[other_player]
for item in subworld.get_pre_fill_items():
subworld.collect(per_player_base_all_state, item)
# And then sweep the state to pick up pre-placed items.
per_player_base_all_state.sweep_for_advancements()
# Get the world for the player that is filling.
filling_world = multiworld.worlds[filling_player]
# Fill each of this world's dungeons.
for i in range(0, 10):
if i == 9:
i = 11
# Build a list of locations in this dungeon
dungeon_location_names = [name for name, loc in LOCATIONS_DATA.items()
if "dungeon" in loc and loc["dungeon"] == i]
dungeon_locations = [loc for loc in multiworld.get_locations(filling_player)
if loc.name in dungeon_location_names and not loc.locked]
# From the list of all dungeon items that needs to be placed restrictively, only filter the ones for the
# dungeon we are currently processing.
confined_dungeon_items = [item for item in filling_world.pre_fill_items
if item.name.endswith(f"({DUNGEON_NAMES[i]})")]
if len(confined_dungeon_items) == 0:
continue # This list might be empty with some keysanity options
# Remove from the pre_fill_items the items we're about to place
for item in confined_dungeon_items:
filling_world.pre_fill_items.remove(item)
collection_state = per_player_base_all_state.copy()
# Collect the remaining pre_fill_items into the state.
for item in filling_world.get_pre_fill_items():
collection_state.collect(item, True)
# Sweep the copied state across the entire multiworld to again account for unusual item plando. It is
# also beneficial to pass as maximal a state as possible to fill_restrictive to reduce how much sweeping
# fill_restrictive must do.
collection_state.sweep_for_advancements()
# Perform a prefill to place confined items inside locations of this dungeon
filling_world.random.shuffle(dungeon_locations)
fill_restrictive(multiworld, collection_state, dungeon_locations, confined_dungeon_items,
single_player_placement=True, lock=True, allow_excluded=True)
for item in confined_dungeon_items:
assert item.location is not None