Stardew Valley: Move filler pool generation out of the world class (#4372)

* merge group options so specific handling is not needed when generating filler pool

* fix

* remove unneeded imports

* self review

* remove unneeded imports

* looks like typing was missing woopsi
This commit is contained in:
Jérémie Bolduc
2025-03-08 12:13:33 -05:00
committed by GitHub
parent ce34b60712
commit 4ebabc1208
5 changed files with 43 additions and 30 deletions

View File

@@ -1,4 +1,5 @@
import logging
import typing
from random import Random
from typing import Dict, Any, Iterable, Optional, List, TextIO, cast
@@ -9,14 +10,15 @@ from .bundles.bundle_room import BundleRoom
from .bundles.bundles import get_all_bundles
from .content import StardewContent, create_content
from .early_items import setup_early_items
from .items import item_table, create_items, ItemData, Group, items_by_group, get_all_filler_items, remove_limited_amount_packs
from .items import item_table, create_items, ItemData, Group, items_by_group, generate_filler_choice_pool
from .locations import location_table, create_locations, LocationData, locations_by_tag
from .logic.logic import StardewLogic
from .options import StardewValleyOptions, SeasonRandomization, Goal, BundleRandomization, EnabledFillerBuffs, NumberOfMovementBuffs, \
BuildingProgression, ExcludeGingerIsland, TrapItems, EntranceRandomization, FarmType
BuildingProgression, EntranceRandomization, FarmType
from .options.forced_options import force_change_options_if_incompatible
from .options.option_groups import sv_option_groups
from .options.presets import sv_options_presets
from .options.worlds_group import apply_most_restrictive_options
from .regions import create_regions
from .rules import set_rules
from .stardew_rule import True_, StardewRule, HasProgressionPercent
@@ -89,6 +91,16 @@ class StardewValleyWorld(World):
total_progression_items: int
@classmethod
def create_group(cls, multiworld: MultiWorld, new_player_id: int, players: set[int]) -> World:
world_group = super().create_group(multiworld, new_player_id, players)
group_options = typing.cast(StardewValleyOptions, world_group.options)
worlds_options = [typing.cast(StardewValleyOptions, multiworld.worlds[player].options) for player in players]
apply_most_restrictive_options(group_options, worlds_options)
return world_group
def __init__(self, multiworld: MultiWorld, player: int):
super().__init__(multiworld, player)
self.filler_item_pool_names = []
@@ -299,32 +311,9 @@ class StardewValleyWorld(World):
def get_filler_item_name(self) -> str:
if not self.filler_item_pool_names:
self.generate_filler_item_pool_names()
self.filler_item_pool_names = generate_filler_choice_pool(self.options)
return self.random.choice(self.filler_item_pool_names)
def generate_filler_item_pool_names(self):
include_traps, exclude_island = self.get_filler_item_rules()
available_filler = get_all_filler_items(include_traps, exclude_island)
available_filler = remove_limited_amount_packs(available_filler)
self.filler_item_pool_names = [item.name for item in available_filler]
def get_filler_item_rules(self):
if self.player in self.multiworld.groups:
link_group = self.multiworld.groups[self.player]
include_traps = True
exclude_island = False
for player in link_group["players"]:
if self.multiworld.game[player] != self.game:
continue
player_options = cast(StardewValleyOptions, self.multiworld.worlds[player].options)
if player_options.trap_items == TrapItems.option_no_traps:
include_traps = False
if player_options.exclude_ginger_island == ExcludeGingerIsland.option_true:
exclude_island = True
return include_traps, exclude_island
else:
return self.options.trap_items != TrapItems.option_no_traps, self.options.exclude_ginger_island == ExcludeGingerIsland.option_true
def write_spoiler_header(self, spoiler_handle: TextIO) -> None:
"""Write to the spoiler header. If individual it's right at the end of that player's options,
if as stage it's right under the common header before per-player options."""

View File

@@ -808,6 +808,16 @@ def remove_excluded_items_island_mods(items, exclude_ginger_island: bool, mods:
return mod_filter
def generate_filler_choice_pool(options: StardewValleyOptions) -> list[str]:
include_traps = options.trap_items != TrapItems.option_no_traps
exclude_island = options.exclude_ginger_island == ExcludeGingerIsland.option_true
available_filler = get_all_filler_items(include_traps, exclude_island)
available_filler = remove_limited_amount_packs(available_filler)
return [item.name for item in available_filler]
def remove_limited_amount_packs(packs):
return [pack for pack in packs if Group.MAXIMUM_ONE not in pack.groups and Group.EXACTLY_TWO not in pack.groups]

View File

@@ -0,0 +1,14 @@
from typing import Iterable
from .options import StardewValleyOptions
def apply_most_restrictive_options(group_option: StardewValleyOptions, world_options: Iterable[StardewValleyOptions]) -> None:
"""Merge the options of the worlds member of the group that can impact fillers generation into the option class of the group.
"""
# If at least one world disabled ginger island, disabling it for the whole group
group_option.exclude_ginger_island.value = max(o.exclude_ginger_island.value for o in world_options)
# If at least one world disabled traps, disabling them for the whole group
group_option.trap_items.value = min(o.trap_items.value for o in world_options)

View File

@@ -2,7 +2,7 @@ from unittest import TestCase
from BaseClasses import MultiWorld
from .option_assert import get_stardew_options
from ... import options, ExcludeGingerIsland
from ... import options
def is_goal(multiworld: MultiWorld, goal: int) -> bool:
@@ -36,7 +36,7 @@ def is_not_perfection(multiworld: MultiWorld) -> bool:
class GoalAssertMixin(TestCase):
def assert_ginger_island_is_included(self, multiworld: MultiWorld):
self.assertEqual(get_stardew_options(multiworld).exclude_ginger_island, ExcludeGingerIsland.option_false)
self.assertEqual(get_stardew_options(multiworld).exclude_ginger_island, options.ExcludeGingerIsland.option_false)
def assert_walnut_hunter_world_is_valid(self, multiworld: MultiWorld):
if is_not_walnut_hunter(multiworld):

View File

@@ -2,7 +2,7 @@ from unittest import TestCase
from BaseClasses import MultiWorld
from .world_assert import get_all_item_names, get_all_location_names
from ... import StardewValleyWorld, options, item_table, Group, location_table, ExcludeGingerIsland
from ... import StardewValleyWorld, options, item_table, Group, location_table
from ...locations import LocationTags
from ...strings.ap_names.transport_names import Transportation
@@ -49,7 +49,7 @@ class OptionAssertMixin(TestCase):
def assert_can_reach_island_if_should(self, multiworld: MultiWorld):
stardew_options = get_stardew_options(multiworld)
include_island = stardew_options.exclude_ginger_island.value == ExcludeGingerIsland.option_false
include_island = stardew_options.exclude_ginger_island.value == options.ExcludeGingerIsland.option_false
if include_island:
self.assert_can_reach_island(multiworld)
else: