Skip to content

Commit

Permalink
Stardew Valley: Move filler pool generation out of the world class (A…
Browse files Browse the repository at this point in the history
  • Loading branch information
Jouramie committed Dec 17, 2024
1 parent bf216fa commit 7bdd21c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 38 deletions.
52 changes: 18 additions & 34 deletions worlds/stardew_valley/__init__.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
import logging
import typing
from random import Random
from typing import Dict, Any, Iterable, Optional, List, TextIO, cast
from typing import Dict, Any, Iterable, Optional, List, TextIO

from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification, MultiWorld, CollectionState
from Options import PerGameCommonOptions
from worlds.AutoWorld import World, WebWorld
from worlds.LauncherComponents import launch_subprocess, components, Component, icon_paths, Type
from . import rules
from .bundles.bundle_room import BundleRoom
from .bundles.bundles import get_all_bundles
from .content import content_packs, StardewContent, unpack_content, create_content
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.bundle_logic import BundleLogic
from .logic.logic import StardewLogic
from .logic.time_logic import MAX_MONTHS
from .options import StardewValleyOptions, SeasonRandomization, Goal, BundleRandomization, EnabledFillerBuffs, NumberOfMovementBuffs, \
BuildingProgression, ExcludeGingerIsland, TrapItems, EntranceRandomization, FarmType, Walnutsanity
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, true_
from .strings.ap_names.event_names import Event
from .strings.entrance_names import Entrance as EntranceName
from .strings.goal_names import Goal as GoalName
from .strings.metal_names import Ore
from .strings.region_names import Region as RegionName, LogicRegion
from .strings.region_names import LogicRegion

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -118,6 +115,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 = []
Expand Down Expand Up @@ -335,32 +342,9 @@ def generate_basic(self):

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."""
Expand Down
10 changes: 10 additions & 0 deletions worlds/stardew_valley/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,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]

Expand Down
14 changes: 14 additions & 0 deletions worlds/stardew_valley/options/worlds_group.py
Original file line number Diff line number Diff line change
@@ -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)
4 changes: 2 additions & 2 deletions worlds/stardew_valley/test/assertion/goal_assert.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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:
Expand Down Expand Up @@ -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):
Expand Down
4 changes: 2 additions & 2 deletions worlds/stardew_valley/test/assertion/option_assert.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

Expand Down Expand Up @@ -49,7 +49,7 @@ def assert_cannot_reach_island(self, multiworld: MultiWorld):

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:
Expand Down

0 comments on commit 7bdd21c

Please sign in to comment.