mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Stardew Valley: Move progressive tool options handling in features (#4374)
* create tool progression feature and unwrap option * replace option usage with calling feature * add comment explaining why some logic is a weird place * replace item creation logic with feature * self review and add unit tests * rename test cuz I named them too long * add a test for the trash can useful stuff cuz I thought there was a bug but turns out it works * self review again * remove price_multiplier, turns out it's unused during generation * damn it 3.11 why are you like this * use blacksmith region when checking vanilla tools * fix rule * move can mine using in tool logic * remove changes to performance test * properly set the option I guess * properly set options 2 * that's what happen when you code too late
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from . import content_packs
|
from . import content_packs
|
||||||
from .feature import cropsanity, friendsanity, fishsanity, booksanity, skill_progression
|
from .feature import cropsanity, friendsanity, fishsanity, booksanity, skill_progression, tool_progression
|
||||||
from .game_content import ContentPack, StardewContent, StardewFeatures
|
from .game_content import ContentPack, StardewContent, StardewFeatures
|
||||||
from .unpacking import unpack_content
|
from .unpacking import unpack_content
|
||||||
from .. import options
|
from .. import options
|
||||||
@@ -33,6 +33,7 @@ def choose_features(player_options: options.StardewValleyOptions) -> StardewFeat
|
|||||||
choose_fishsanity(player_options.fishsanity),
|
choose_fishsanity(player_options.fishsanity),
|
||||||
choose_friendsanity(player_options.friendsanity, player_options.friendsanity_heart_size),
|
choose_friendsanity(player_options.friendsanity, player_options.friendsanity_heart_size),
|
||||||
choose_skill_progression(player_options.skill_progression),
|
choose_skill_progression(player_options.skill_progression),
|
||||||
|
choose_tool_progression(player_options.tool_progression, player_options.skill_progression),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -122,3 +123,18 @@ def choose_skill_progression(skill_progression_option: options.SkillProgression)
|
|||||||
raise ValueError(f"No skill progression feature mapped to {str(skill_progression_option.value)}")
|
raise ValueError(f"No skill progression feature mapped to {str(skill_progression_option.value)}")
|
||||||
|
|
||||||
return skill_progression_feature
|
return skill_progression_feature
|
||||||
|
|
||||||
|
|
||||||
|
def choose_tool_progression(tool_option: options.ToolProgression, skill_option: options.SkillProgression) -> tool_progression.ToolProgressionFeature:
|
||||||
|
if tool_option.is_vanilla:
|
||||||
|
return tool_progression.ToolProgressionVanilla()
|
||||||
|
|
||||||
|
tools_distribution = tool_progression.get_tools_distribution(
|
||||||
|
progressive_tools_enabled=True,
|
||||||
|
skill_masteries_enabled=skill_option == options.SkillProgression.option_progressive_with_masteries,
|
||||||
|
)
|
||||||
|
|
||||||
|
if tool_option.is_progressive:
|
||||||
|
return tool_progression.ToolProgressionProgressive(tools_distribution)
|
||||||
|
|
||||||
|
raise ValueError(f"No tool progression feature mapped to {str(tool_option.value)}")
|
||||||
|
@@ -3,3 +3,4 @@ from . import cropsanity
|
|||||||
from . import fishsanity
|
from . import fishsanity
|
||||||
from . import friendsanity
|
from . import friendsanity
|
||||||
from . import skill_progression
|
from . import skill_progression
|
||||||
|
from . import tool_progression
|
||||||
|
68
worlds/stardew_valley/content/feature/tool_progression.py
Normal file
68
worlds/stardew_valley/content/feature/tool_progression.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
from abc import ABC
|
||||||
|
from collections import Counter
|
||||||
|
from collections.abc import Mapping
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from functools import cache
|
||||||
|
from types import MappingProxyType
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
|
from ...strings.tool_names import Tool
|
||||||
|
|
||||||
|
|
||||||
|
def to_progressive_item(tool: str) -> str:
|
||||||
|
"""Return the name of the progressive item."""
|
||||||
|
return f"Progressive {tool}"
|
||||||
|
|
||||||
|
|
||||||
|
# The golden scythe is always randomized
|
||||||
|
VANILLA_TOOL_DISTRIBUTION = MappingProxyType({
|
||||||
|
Tool.scythe: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
PROGRESSIVE_TOOL_DISTRIBUTION = MappingProxyType({
|
||||||
|
Tool.axe: 4,
|
||||||
|
Tool.hoe: 4,
|
||||||
|
Tool.pickaxe: 4,
|
||||||
|
Tool.pan: 4,
|
||||||
|
Tool.trash_can: 4,
|
||||||
|
Tool.watering_can: 4,
|
||||||
|
Tool.fishing_rod: 4,
|
||||||
|
})
|
||||||
|
|
||||||
|
# Masteries add another tier to the scythe and the fishing rod
|
||||||
|
SKILL_MASTERIES_TOOL_DISTRIBUTION = MappingProxyType({
|
||||||
|
Tool.scythe: 1,
|
||||||
|
Tool.fishing_rod: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_tools_distribution(progressive_tools_enabled: bool, skill_masteries_enabled: bool) -> Mapping[str, int]:
|
||||||
|
distribution = Counter(VANILLA_TOOL_DISTRIBUTION)
|
||||||
|
|
||||||
|
if progressive_tools_enabled:
|
||||||
|
distribution += PROGRESSIVE_TOOL_DISTRIBUTION
|
||||||
|
|
||||||
|
if skill_masteries_enabled:
|
||||||
|
distribution += SKILL_MASTERIES_TOOL_DISTRIBUTION
|
||||||
|
|
||||||
|
return MappingProxyType(distribution)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ToolProgressionFeature(ABC):
|
||||||
|
is_progressive: ClassVar[bool]
|
||||||
|
tool_distribution: Mapping[str, int]
|
||||||
|
|
||||||
|
to_progressive_item = staticmethod(to_progressive_item)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ToolProgressionVanilla(ToolProgressionFeature):
|
||||||
|
is_progressive = False
|
||||||
|
# FIXME change the default_factory to a simple default when python 3.11 is no longer supported
|
||||||
|
tool_distribution: Mapping[str, int] = field(default_factory=lambda: VANILLA_TOOL_DISTRIBUTION)
|
||||||
|
|
||||||
|
|
||||||
|
class ToolProgressionProgressive(ToolProgressionFeature):
|
||||||
|
is_progressive = True
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Dict, Iterable, Set, Any, Mapping, Type, Tuple, Union
|
from typing import Dict, Iterable, Set, Any, Mapping, Type, Tuple, Union
|
||||||
|
|
||||||
from .feature import booksanity, cropsanity, fishsanity, friendsanity, skill_progression
|
from .feature import booksanity, cropsanity, fishsanity, friendsanity, skill_progression, tool_progression
|
||||||
from ..data.fish_data import FishItem
|
from ..data.fish_data import FishItem
|
||||||
from ..data.game_item import GameItem, ItemSource, ItemTag
|
from ..data.game_item import GameItem, ItemSource, ItemTag
|
||||||
from ..data.skill import Skill
|
from ..data.skill import Skill
|
||||||
@@ -54,6 +54,7 @@ class StardewFeatures:
|
|||||||
fishsanity: fishsanity.FishsanityFeature
|
fishsanity: fishsanity.FishsanityFeature
|
||||||
friendsanity: friendsanity.FriendsanityFeature
|
friendsanity: friendsanity.FriendsanityFeature
|
||||||
skill_progression: skill_progression.SkillProgressionFeature
|
skill_progression: skill_progression.SkillProgressionFeature
|
||||||
|
tool_progression: tool_progression.ToolProgressionFeature
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
|
@@ -32,7 +32,7 @@ def setup_early_items(multiworld, options: stardew_options.StardewValleyOptions,
|
|||||||
if options.backpack_progression == stardew_options.BackpackProgression.option_early_progressive:
|
if options.backpack_progression == stardew_options.BackpackProgression.option_early_progressive:
|
||||||
early_forced.append("Progressive Backpack")
|
early_forced.append("Progressive Backpack")
|
||||||
|
|
||||||
if options.tool_progression & stardew_options.ToolProgression.option_progressive:
|
if content.features.tool_progression.is_progressive:
|
||||||
if content.features.fishsanity.is_enabled:
|
if content.features.fishsanity.is_enabled:
|
||||||
early_candidates.append("Progressive Fishing Rod")
|
early_candidates.append("Progressive Fishing Rod")
|
||||||
early_forced.append("Progressive Pickaxe")
|
early_forced.append("Progressive Pickaxe")
|
||||||
|
@@ -15,7 +15,7 @@ from .data.game_item import ItemTag
|
|||||||
from .logic.logic_event import all_events
|
from .logic.logic_event import all_events
|
||||||
from .mods.mod_data import ModNames
|
from .mods.mod_data import ModNames
|
||||||
from .options import StardewValleyOptions, TrapItems, FestivalLocations, ExcludeGingerIsland, SpecialOrderLocations, SeasonRandomization, Museumsanity, \
|
from .options import StardewValleyOptions, TrapItems, FestivalLocations, ExcludeGingerIsland, SpecialOrderLocations, SeasonRandomization, Museumsanity, \
|
||||||
BuildingProgression, ToolProgression, ElevatorProgression, BackpackProgression, ArcadeMachineLocations, Monstersanity, Goal, \
|
BuildingProgression, ElevatorProgression, BackpackProgression, ArcadeMachineLocations, Monstersanity, Goal, \
|
||||||
Chefsanity, Craftsanity, BundleRandomization, EntranceRandomization, Shipsanity, Walnutsanity, EnabledFillerBuffs
|
Chefsanity, Craftsanity, BundleRandomization, EntranceRandomization, Shipsanity, Walnutsanity, EnabledFillerBuffs
|
||||||
from .strings.ap_names.ap_option_names import BuffOptionName, WalnutsanityOptionName
|
from .strings.ap_names.ap_option_names import BuffOptionName, WalnutsanityOptionName
|
||||||
from .strings.ap_names.ap_weapon_names import APWeapon
|
from .strings.ap_names.ap_weapon_names import APWeapon
|
||||||
@@ -23,6 +23,7 @@ from .strings.ap_names.buff_names import Buff
|
|||||||
from .strings.ap_names.community_upgrade_names import CommunityUpgrade
|
from .strings.ap_names.community_upgrade_names import CommunityUpgrade
|
||||||
from .strings.ap_names.mods.mod_items import SVEQuestItem
|
from .strings.ap_names.mods.mod_items import SVEQuestItem
|
||||||
from .strings.currency_names import Currency
|
from .strings.currency_names import Currency
|
||||||
|
from .strings.tool_names import Tool
|
||||||
from .strings.wallet_item_names import Wallet
|
from .strings.wallet_item_names import Wallet
|
||||||
|
|
||||||
ITEM_CODE_OFFSET = 717000
|
ITEM_CODE_OFFSET = 717000
|
||||||
@@ -119,11 +120,6 @@ class StardewItemFactory(Protocol):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class StardewItemDeleter(Protocol):
|
|
||||||
def __call__(self, item: Item):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
def load_item_csv():
|
def load_item_csv():
|
||||||
from importlib.resources import files
|
from importlib.resources import files
|
||||||
|
|
||||||
@@ -226,7 +222,7 @@ def create_unique_items(item_factory: StardewItemFactory, options: StardewValley
|
|||||||
create_weapons(item_factory, options, items)
|
create_weapons(item_factory, options, items)
|
||||||
items.append(item_factory("Skull Key"))
|
items.append(item_factory("Skull Key"))
|
||||||
create_elevators(item_factory, options, items)
|
create_elevators(item_factory, options, items)
|
||||||
create_tools(item_factory, options, content, items)
|
create_tools(item_factory, content, items)
|
||||||
create_skills(item_factory, content, items)
|
create_skills(item_factory, content, items)
|
||||||
create_wizard_buildings(item_factory, options, items)
|
create_wizard_buildings(item_factory, options, items)
|
||||||
create_carpenter_buildings(item_factory, options, items)
|
create_carpenter_buildings(item_factory, options, items)
|
||||||
@@ -316,23 +312,17 @@ def create_elevators(item_factory: StardewItemFactory, options: StardewValleyOpt
|
|||||||
items.extend([item_factory(item) for item in ["Progressive Skull Cavern Elevator"] * 8])
|
items.extend([item_factory(item) for item in ["Progressive Skull Cavern Elevator"] * 8])
|
||||||
|
|
||||||
|
|
||||||
def create_tools(item_factory: StardewItemFactory, options: StardewValleyOptions, content: StardewContent, items: List[Item]):
|
def create_tools(item_factory: StardewItemFactory, content: StardewContent, items: List[Item]):
|
||||||
if options.tool_progression & ToolProgression.option_progressive:
|
tool_progression = content.features.tool_progression
|
||||||
for item_data in items_by_group[Group.PROGRESSIVE_TOOLS]:
|
for tool, count in tool_progression.tool_distribution.items():
|
||||||
name = item_data.name
|
item = item_table[tool_progression.to_progressive_item(tool)]
|
||||||
if "Trash Can" in name:
|
|
||||||
items.extend([item_factory(item) for item in [item_data] * 3])
|
|
||||||
items.append(item_factory(item_data, ItemClassification.useful))
|
|
||||||
else:
|
|
||||||
items.extend([item_factory(item) for item in [item_data] * 4])
|
|
||||||
|
|
||||||
if content.features.skill_progression.are_masteries_shuffled:
|
# Trash can is only used in tool upgrade logic, so the last trash can is not progression because it basically does not unlock anything.
|
||||||
# Masteries add another tier to the scythe and the fishing rod
|
if tool == Tool.trash_can:
|
||||||
items.append(item_factory("Progressive Scythe"))
|
count -= 1
|
||||||
items.append(item_factory("Progressive Fishing Rod"))
|
items.append(item_factory(item, ItemClassification.useful))
|
||||||
|
|
||||||
# The golden scythe is always randomized
|
items.extend([item_factory(item) for _ in range(count)])
|
||||||
items.append(item_factory("Progressive Scythe"))
|
|
||||||
|
|
||||||
|
|
||||||
def create_skills(item_factory: StardewItemFactory, content: StardewContent, items: List[Item]):
|
def create_skills(item_factory: StardewItemFactory, content: StardewContent, items: List[Item]):
|
||||||
|
@@ -11,7 +11,7 @@ from .data.game_item import ItemTag
|
|||||||
from .data.museum_data import all_museum_items
|
from .data.museum_data import all_museum_items
|
||||||
from .mods.mod_data import ModNames
|
from .mods.mod_data import ModNames
|
||||||
from .options import ExcludeGingerIsland, ArcadeMachineLocations, SpecialOrderLocations, Museumsanity, \
|
from .options import ExcludeGingerIsland, ArcadeMachineLocations, SpecialOrderLocations, Museumsanity, \
|
||||||
FestivalLocations, BuildingProgression, ToolProgression, ElevatorProgression, BackpackProgression, FarmType
|
FestivalLocations, BuildingProgression, ElevatorProgression, BackpackProgression, FarmType
|
||||||
from .options import StardewValleyOptions, Craftsanity, Chefsanity, Cooksanity, Shipsanity, Monstersanity
|
from .options import StardewValleyOptions, Craftsanity, Chefsanity, Cooksanity, Shipsanity, Monstersanity
|
||||||
from .strings.goal_names import Goal
|
from .strings.goal_names import Goal
|
||||||
from .strings.quest_names import ModQuest, Quest
|
from .strings.quest_names import ModQuest, Quest
|
||||||
@@ -473,7 +473,7 @@ def create_locations(location_collector: StardewLocationCollector,
|
|||||||
extend_bundle_locations(randomized_locations, bundle_rooms)
|
extend_bundle_locations(randomized_locations, bundle_rooms)
|
||||||
extend_backpack_locations(randomized_locations, options)
|
extend_backpack_locations(randomized_locations, options)
|
||||||
|
|
||||||
if options.tool_progression & ToolProgression.option_progressive:
|
if content.features.tool_progression.is_progressive:
|
||||||
randomized_locations.extend(locations_by_tag[LocationTags.TOOL_UPGRADE])
|
randomized_locations.extend(locations_by_tag[LocationTags.TOOL_UPGRADE])
|
||||||
|
|
||||||
extend_elevator_locations(randomized_locations, options)
|
extend_elevator_locations(randomized_locations, options)
|
||||||
|
@@ -10,12 +10,11 @@ from .region_logic import RegionLogicMixin
|
|||||||
from .skill_logic import SkillLogicMixin
|
from .skill_logic import SkillLogicMixin
|
||||||
from .tool_logic import ToolLogicMixin
|
from .tool_logic import ToolLogicMixin
|
||||||
from .. import options
|
from .. import options
|
||||||
from ..options import ToolProgression
|
|
||||||
from ..stardew_rule import StardewRule, True_
|
from ..stardew_rule import StardewRule, True_
|
||||||
from ..strings.performance_names import Performance
|
from ..strings.performance_names import Performance
|
||||||
from ..strings.region_names import Region
|
from ..strings.region_names import Region
|
||||||
from ..strings.skill_names import Skill
|
from ..strings.skill_names import Skill
|
||||||
from ..strings.tool_names import Tool, ToolMaterial
|
from ..strings.tool_names import ToolMaterial
|
||||||
|
|
||||||
|
|
||||||
class MineLogicMixin(BaseLogicMixin):
|
class MineLogicMixin(BaseLogicMixin):
|
||||||
@@ -56,11 +55,12 @@ SkillLogicMixin, CookingLogicMixin]]):
|
|||||||
def can_progress_in_the_mines_from_floor(self, floor: int) -> StardewRule:
|
def can_progress_in_the_mines_from_floor(self, floor: int) -> StardewRule:
|
||||||
tier = floor // 40
|
tier = floor // 40
|
||||||
rules = []
|
rules = []
|
||||||
|
|
||||||
weapon_rule = self.logic.mine.get_weapon_rule_for_floor_tier(tier)
|
weapon_rule = self.logic.mine.get_weapon_rule_for_floor_tier(tier)
|
||||||
rules.append(weapon_rule)
|
rules.append(weapon_rule)
|
||||||
|
|
||||||
if self.options.tool_progression & ToolProgression.option_progressive:
|
tool_rule = self.logic.tool.can_mine_using(ToolMaterial.tiers[tier])
|
||||||
rules.append(self.logic.tool.has_tool(Tool.pickaxe, ToolMaterial.tiers[tier]))
|
rules.append(tool_rule)
|
||||||
|
|
||||||
# No alternative for vanilla because we assume that you will grind the levels in the mines.
|
# No alternative for vanilla because we assume that you will grind the levels in the mines.
|
||||||
if self.content.features.skill_progression.is_progressive:
|
if self.content.features.skill_progression.is_progressive:
|
||||||
@@ -85,11 +85,12 @@ SkillLogicMixin, CookingLogicMixin]]):
|
|||||||
def can_progress_in_the_skull_cavern_from_floor(self, floor: int) -> StardewRule:
|
def can_progress_in_the_skull_cavern_from_floor(self, floor: int) -> StardewRule:
|
||||||
tier = floor // 50
|
tier = floor // 50
|
||||||
rules = []
|
rules = []
|
||||||
|
|
||||||
weapon_rule = self.logic.combat.has_great_weapon
|
weapon_rule = self.logic.combat.has_great_weapon
|
||||||
rules.append(weapon_rule)
|
rules.append(weapon_rule)
|
||||||
|
|
||||||
if self.options.tool_progression & ToolProgression.option_progressive:
|
tool_rule = self.logic.tool.can_mine_using(ToolMaterial.tiers[min(4, max(0, tier + 2))])
|
||||||
rules.append(self.logic.received("Progressive Pickaxe", min(4, max(0, tier + 2))))
|
rules.append(tool_rule)
|
||||||
|
|
||||||
# No alternative for vanilla because we assume that you will grind the levels in the mines.
|
# No alternative for vanilla because we assume that you will grind the levels in the mines.
|
||||||
if self.content.features.skill_progression.is_progressive:
|
if self.content.features.skill_progression.is_progressive:
|
||||||
|
@@ -8,12 +8,11 @@ from .received_logic import ReceivedLogicMixin
|
|||||||
from .region_logic import RegionLogicMixin
|
from .region_logic import RegionLogicMixin
|
||||||
from .season_logic import SeasonLogicMixin
|
from .season_logic import SeasonLogicMixin
|
||||||
from ..mods.logic.magic_logic import MagicLogicMixin
|
from ..mods.logic.magic_logic import MagicLogicMixin
|
||||||
from ..options import ToolProgression
|
|
||||||
from ..stardew_rule import StardewRule, True_, False_
|
from ..stardew_rule import StardewRule, True_, False_
|
||||||
from ..strings.ap_names.skill_level_names import ModSkillLevel
|
from ..strings.ap_names.skill_level_names import ModSkillLevel
|
||||||
from ..strings.region_names import Region
|
from ..strings.region_names import Region, LogicRegion
|
||||||
from ..strings.spells import MagicSpell
|
from ..strings.spells import MagicSpell
|
||||||
from ..strings.tool_names import ToolMaterial, Tool
|
from ..strings.tool_names import ToolMaterial, Tool, APTool
|
||||||
|
|
||||||
fishing_rod_prices = {
|
fishing_rod_prices = {
|
||||||
3: 1800,
|
3: 1800,
|
||||||
@@ -57,10 +56,10 @@ class ToolLogic(BaseLogic[Union[ToolLogicMixin, HasLogicMixin, ReceivedLogicMixi
|
|||||||
if material == ToolMaterial.basic or tool == Tool.scythe:
|
if material == ToolMaterial.basic or tool == Tool.scythe:
|
||||||
return True_()
|
return True_()
|
||||||
|
|
||||||
if self.options.tool_progression & ToolProgression.option_progressive:
|
if self.content.features.tool_progression.is_progressive:
|
||||||
return self.logic.received(f"Progressive {tool}", tool_materials[material])
|
return self.logic.received(f"Progressive {tool}", tool_materials[material])
|
||||||
|
|
||||||
can_upgrade_rule = self.logic.has(f"{material} Bar") & self.logic.money.can_spend_at(Region.blacksmith, tool_upgrade_prices[material])
|
can_upgrade_rule = self.logic.tool._can_purchase_upgrade(material)
|
||||||
if tool == Tool.pan:
|
if tool == Tool.pan:
|
||||||
has_base_pan = self.logic.received("Glittering Boulder Removed") & self.logic.region.can_reach(Region.mountain)
|
has_base_pan = self.logic.received("Glittering Boulder Removed") & self.logic.region.can_reach(Region.mountain)
|
||||||
if material == ToolMaterial.copper:
|
if material == ToolMaterial.copper:
|
||||||
@@ -69,6 +68,20 @@ class ToolLogic(BaseLogic[Union[ToolLogicMixin, HasLogicMixin, ReceivedLogicMixi
|
|||||||
|
|
||||||
return can_upgrade_rule
|
return can_upgrade_rule
|
||||||
|
|
||||||
|
@cache_self1
|
||||||
|
def can_mine_using(self, material: str) -> StardewRule:
|
||||||
|
if material == ToolMaterial.basic:
|
||||||
|
return self.logic.true_
|
||||||
|
|
||||||
|
if self.content.features.tool_progression.is_progressive:
|
||||||
|
return self.logic.received(APTool.pickaxe, tool_materials[material])
|
||||||
|
else:
|
||||||
|
return self.logic.tool._can_purchase_upgrade(material)
|
||||||
|
|
||||||
|
@cache_self1
|
||||||
|
def _can_purchase_upgrade(self, material: str) -> StardewRule:
|
||||||
|
return self.logic.region.can_reach(LogicRegion.blacksmith_upgrade(material))
|
||||||
|
|
||||||
def can_use_tool_at(self, tool: str, material: str, region: str) -> StardewRule:
|
def can_use_tool_at(self, tool: str, material: str, region: str) -> StardewRule:
|
||||||
return self.has_tool(tool, material) & self.logic.region.can_reach(region)
|
return self.has_tool(tool, material) & self.logic.region.can_reach(region)
|
||||||
|
|
||||||
@@ -76,8 +89,8 @@ class ToolLogic(BaseLogic[Union[ToolLogicMixin, HasLogicMixin, ReceivedLogicMixi
|
|||||||
def has_fishing_rod(self, level: int) -> StardewRule:
|
def has_fishing_rod(self, level: int) -> StardewRule:
|
||||||
assert 1 <= level <= 4, "Fishing rod 0 isn't real, it can't hurt you. Training is 1, Bamboo is 2, Fiberglass is 3 and Iridium is 4."
|
assert 1 <= level <= 4, "Fishing rod 0 isn't real, it can't hurt you. Training is 1, Bamboo is 2, Fiberglass is 3 and Iridium is 4."
|
||||||
|
|
||||||
if self.options.tool_progression & ToolProgression.option_progressive:
|
if self.content.features.tool_progression.is_progressive:
|
||||||
return self.logic.received(f"Progressive {Tool.fishing_rod}", level)
|
return self.logic.received(APTool.fishing_rod, level)
|
||||||
|
|
||||||
if level <= 2:
|
if level <= 2:
|
||||||
# We assume you always have access to the Bamboo pole, because mod side there is a builtin way to get it back.
|
# We assume you always have access to the Bamboo pole, because mod side there is a builtin way to get it back.
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
from typing import Dict, Union
|
from typing import Dict, Union
|
||||||
|
|
||||||
from ..mod_data import ModNames
|
from ..mod_data import ModNames
|
||||||
from ... import options
|
|
||||||
from ...logic.base_logic import BaseLogicMixin, BaseLogic
|
from ...logic.base_logic import BaseLogicMixin, BaseLogic
|
||||||
from ...logic.combat_logic import CombatLogicMixin
|
from ...logic.combat_logic import CombatLogicMixin
|
||||||
from ...logic.cooking_logic import CookingLogicMixin
|
from ...logic.cooking_logic import CookingLogicMixin
|
||||||
@@ -80,7 +79,7 @@ FarmingLogicMixin]]):
|
|||||||
# Gingerbread House
|
# Gingerbread House
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.options.tool_progression & options.ToolProgression.option_progressive:
|
if self.content.features.tool_progression.is_progressive:
|
||||||
options_to_update.update({
|
options_to_update.update({
|
||||||
Ore.iridium: items[Ore.iridium] | self.logic.tool.can_use_tool_at(Tool.axe, ToolMaterial.iridium, DeepWoodsRegion.floor_50), # Iridium Tree
|
Ore.iridium: items[Ore.iridium] | self.logic.tool.can_use_tool_at(Tool.axe, ToolMaterial.iridium, DeepWoodsRegion.floor_50), # Iridium Tree
|
||||||
})
|
})
|
||||||
|
@@ -247,6 +247,14 @@ class ToolProgression(Choice):
|
|||||||
option_progressive_cheap = 0b011 # 3
|
option_progressive_cheap = 0b011 # 3
|
||||||
option_progressive_very_cheap = 0b101 # 5
|
option_progressive_very_cheap = 0b101 # 5
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_vanilla(self):
|
||||||
|
return not self.is_progressive
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_progressive(self):
|
||||||
|
return bool(self.value & self.option_progressive)
|
||||||
|
|
||||||
|
|
||||||
class ElevatorProgression(Choice):
|
class ElevatorProgression(Choice):
|
||||||
"""Shuffle the elevator?
|
"""Shuffle the elevator?
|
||||||
|
@@ -19,9 +19,8 @@ from .logic.logic import StardewLogic
|
|||||||
from .logic.time_logic import MAX_MONTHS
|
from .logic.time_logic import MAX_MONTHS
|
||||||
from .logic.tool_logic import tool_upgrade_prices
|
from .logic.tool_logic import tool_upgrade_prices
|
||||||
from .mods.mod_data import ModNames
|
from .mods.mod_data import ModNames
|
||||||
from .options import StardewValleyOptions, Walnutsanity
|
from .options import BuildingProgression, ExcludeGingerIsland, SpecialOrderLocations, Museumsanity, BackpackProgression, Shipsanity, \
|
||||||
from .options import ToolProgression, BuildingProgression, ExcludeGingerIsland, SpecialOrderLocations, Museumsanity, BackpackProgression, Shipsanity, \
|
Monstersanity, Chefsanity, Craftsanity, ArcadeMachineLocations, Cooksanity, StardewValleyOptions, Walnutsanity
|
||||||
Monstersanity, Chefsanity, Craftsanity, ArcadeMachineLocations, Cooksanity
|
|
||||||
from .stardew_rule import And, StardewRule, true_
|
from .stardew_rule import And, StardewRule, true_
|
||||||
from .stardew_rule.indirect_connection import look_for_indirect_connection
|
from .stardew_rule.indirect_connection import look_for_indirect_connection
|
||||||
from .stardew_rule.rule_explain import explain
|
from .stardew_rule.rule_explain import explain
|
||||||
@@ -69,7 +68,7 @@ def set_rules(world):
|
|||||||
set_entrance_rules(logic, multiworld, player, world_options)
|
set_entrance_rules(logic, multiworld, player, world_options)
|
||||||
set_ginger_island_rules(logic, multiworld, player, world_options)
|
set_ginger_island_rules(logic, multiworld, player, world_options)
|
||||||
|
|
||||||
set_tool_rules(logic, multiworld, player, world_options)
|
set_tool_rules(logic, multiworld, player, world_content)
|
||||||
set_skills_rules(logic, multiworld, player, world_content)
|
set_skills_rules(logic, multiworld, player, world_content)
|
||||||
set_bundle_rules(bundle_rooms, logic, multiworld, player, world_options)
|
set_bundle_rules(bundle_rooms, logic, multiworld, player, world_options)
|
||||||
set_building_rules(logic, multiworld, player, world_options)
|
set_building_rules(logic, multiworld, player, world_options)
|
||||||
@@ -111,8 +110,8 @@ def set_isolated_locations_rules(logic: StardewLogic, multiworld, player):
|
|||||||
logic.season.has(Season.spring))
|
logic.season.has(Season.spring))
|
||||||
|
|
||||||
|
|
||||||
def set_tool_rules(logic: StardewLogic, multiworld, player, world_options: StardewValleyOptions):
|
def set_tool_rules(logic: StardewLogic, multiworld, player, content: StardewContent):
|
||||||
if not world_options.tool_progression & ToolProgression.option_progressive:
|
if not content.features.tool_progression.is_progressive:
|
||||||
return
|
return
|
||||||
|
|
||||||
MultiWorldRules.add_rule(multiworld.get_location("Purchase Fiberglass Rod", player),
|
MultiWorldRules.add_rule(multiworld.get_location("Purchase Fiberglass Rod", player),
|
||||||
@@ -281,13 +280,6 @@ def set_skull_cavern_floor_entrance_rules(logic, multiworld, player):
|
|||||||
set_entrance_rule(multiworld, player, dig_to_skull_floor(floor), rule)
|
set_entrance_rule(multiworld, player, dig_to_skull_floor(floor), rule)
|
||||||
|
|
||||||
|
|
||||||
def set_blacksmith_entrance_rules(logic, multiworld, player):
|
|
||||||
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_copper, MetalBar.copper, ToolMaterial.copper)
|
|
||||||
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_iron, MetalBar.iron, ToolMaterial.iron)
|
|
||||||
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_gold, MetalBar.gold, ToolMaterial.gold)
|
|
||||||
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_iridium, MetalBar.iridium, ToolMaterial.iridium)
|
|
||||||
|
|
||||||
|
|
||||||
def set_skill_entrance_rules(logic, multiworld, player, world_options: StardewValleyOptions):
|
def set_skill_entrance_rules(logic, multiworld, player, world_options: StardewValleyOptions):
|
||||||
set_entrance_rule(multiworld, player, LogicEntrance.grow_spring_crops, logic.farming.has_farming_tools & logic.season.has_spring)
|
set_entrance_rule(multiworld, player, LogicEntrance.grow_spring_crops, logic.farming.has_farming_tools & logic.season.has_spring)
|
||||||
set_entrance_rule(multiworld, player, LogicEntrance.grow_summer_crops, logic.farming.has_farming_tools & logic.season.has_summer)
|
set_entrance_rule(multiworld, player, LogicEntrance.grow_summer_crops, logic.farming.has_farming_tools & logic.season.has_summer)
|
||||||
@@ -306,6 +298,13 @@ def set_skill_entrance_rules(logic, multiworld, player, world_options: StardewVa
|
|||||||
set_entrance_rule(multiworld, player, LogicEntrance.fishing, logic.skill.can_get_fishing_xp)
|
set_entrance_rule(multiworld, player, LogicEntrance.fishing, logic.skill.can_get_fishing_xp)
|
||||||
|
|
||||||
|
|
||||||
|
def set_blacksmith_entrance_rules(logic, multiworld, player):
|
||||||
|
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_copper, MetalBar.copper, ToolMaterial.copper)
|
||||||
|
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_iron, MetalBar.iron, ToolMaterial.iron)
|
||||||
|
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_gold, MetalBar.gold, ToolMaterial.gold)
|
||||||
|
set_blacksmith_upgrade_rule(logic, multiworld, player, LogicEntrance.blacksmith_iridium, MetalBar.iridium, ToolMaterial.iridium)
|
||||||
|
|
||||||
|
|
||||||
def set_blacksmith_upgrade_rule(logic, multiworld, player, entrance_name: str, item_name: str, tool_material: str):
|
def set_blacksmith_upgrade_rule(logic, multiworld, player, entrance_name: str, item_name: str, tool_material: str):
|
||||||
upgrade_rule = logic.has(item_name) & logic.money.can_spend(tool_upgrade_prices[tool_material])
|
upgrade_rule = logic.has(item_name) & logic.money.can_spend(tool_upgrade_prices[tool_material])
|
||||||
set_entrance_rule(multiworld, player, entrance_name, upgrade_rule)
|
set_entrance_rule(multiworld, player, entrance_name, upgrade_rule)
|
||||||
|
@@ -194,10 +194,15 @@ class LogicEntrance:
|
|||||||
island_cooking = "Island Cooking"
|
island_cooking = "Island Cooking"
|
||||||
shipping = "Use Shipping Bin"
|
shipping = "Use Shipping Bin"
|
||||||
watch_queen_of_sauce = "Watch Queen of Sauce"
|
watch_queen_of_sauce = "Watch Queen of Sauce"
|
||||||
blacksmith_copper = "Upgrade Copper Tools"
|
|
||||||
blacksmith_iron = "Upgrade Iron Tools"
|
@staticmethod
|
||||||
blacksmith_gold = "Upgrade Gold Tools"
|
def blacksmith_upgrade(material: str) -> str:
|
||||||
blacksmith_iridium = "Upgrade Iridium Tools"
|
return f"Upgrade {material} Tools"
|
||||||
|
|
||||||
|
blacksmith_copper = blacksmith_upgrade("Copper")
|
||||||
|
blacksmith_iron = blacksmith_upgrade("Iron")
|
||||||
|
blacksmith_gold = blacksmith_upgrade("Gold")
|
||||||
|
blacksmith_iridium = blacksmith_upgrade("Iridium")
|
||||||
|
|
||||||
grow_spring_crops = "Grow Spring Crops"
|
grow_spring_crops = "Grow Spring Crops"
|
||||||
grow_summer_crops = "Grow Summer Crops"
|
grow_summer_crops = "Grow Summer Crops"
|
||||||
|
@@ -159,10 +159,15 @@ class LogicRegion:
|
|||||||
kitchen = "Kitchen"
|
kitchen = "Kitchen"
|
||||||
shipping = "Shipping"
|
shipping = "Shipping"
|
||||||
queen_of_sauce = "The Queen of Sauce"
|
queen_of_sauce = "The Queen of Sauce"
|
||||||
blacksmith_copper = "Blacksmith Copper Upgrades"
|
|
||||||
blacksmith_iron = "Blacksmith Iron Upgrades"
|
@staticmethod
|
||||||
blacksmith_gold = "Blacksmith Gold Upgrades"
|
def blacksmith_upgrade(material: str) -> str:
|
||||||
blacksmith_iridium = "Blacksmith Iridium Upgrades"
|
return f"Blacksmith {material} Upgrades"
|
||||||
|
|
||||||
|
blacksmith_copper = blacksmith_upgrade("Copper")
|
||||||
|
blacksmith_iron = blacksmith_upgrade("Iron")
|
||||||
|
blacksmith_gold = blacksmith_upgrade("Gold")
|
||||||
|
blacksmith_iridium = blacksmith_upgrade("Iridium")
|
||||||
|
|
||||||
spring_farming = "Spring Farming"
|
spring_farming = "Spring Farming"
|
||||||
summer_farming = "Summer Farming"
|
summer_farming = "Summer Farming"
|
||||||
|
@@ -5,8 +5,8 @@ from . import SVTestBase
|
|||||||
from .. import items, location_table, options
|
from .. import items, location_table, options
|
||||||
from ..items import Group
|
from ..items import Group
|
||||||
from ..locations import LocationTags
|
from ..locations import LocationTags
|
||||||
from ..options import Friendsanity, SpecialOrderLocations, Shipsanity, Chefsanity, SeasonRandomization, Craftsanity, ExcludeGingerIsland, ToolProgression, \
|
from ..options import Friendsanity, SpecialOrderLocations, Shipsanity, Chefsanity, SeasonRandomization, Craftsanity, ExcludeGingerIsland, SkillProgression, \
|
||||||
SkillProgression, Booksanity, Walnutsanity
|
Booksanity, Walnutsanity
|
||||||
from ..strings.region_names import Region
|
from ..strings.region_names import Region
|
||||||
|
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ class TestProgressiveElevator(SVTestBase):
|
|||||||
class TestSkullCavernLogic(SVTestBase):
|
class TestSkullCavernLogic(SVTestBase):
|
||||||
options = {
|
options = {
|
||||||
options.ElevatorProgression.internal_name: options.ElevatorProgression.option_vanilla,
|
options.ElevatorProgression.internal_name: options.ElevatorProgression.option_vanilla,
|
||||||
ToolProgression.internal_name: ToolProgression.option_progressive,
|
options.ToolProgression.internal_name: options.ToolProgression.option_progressive,
|
||||||
options.SkillProgression.internal_name: options.SkillProgression.option_progressive,
|
options.SkillProgression.internal_name: options.SkillProgression.option_progressive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ class TestBitFlagsVanilla(SVTestBase):
|
|||||||
|
|
||||||
def test_options_are_not_detected_as_progressive(self):
|
def test_options_are_not_detected_as_progressive(self):
|
||||||
world_options = self.world.options
|
world_options = self.world.options
|
||||||
tool_progressive = world_options.tool_progression & ToolProgression.option_progressive
|
tool_progressive = self.world.content.features.tool_progression.is_progressive
|
||||||
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
||||||
self.assertFalse(tool_progressive)
|
self.assertFalse(tool_progressive)
|
||||||
self.assertFalse(building_progressive)
|
self.assertFalse(building_progressive)
|
||||||
@@ -26,7 +26,7 @@ class TestBitFlagsVanillaCheap(SVTestBase):
|
|||||||
|
|
||||||
def test_options_are_not_detected_as_progressive(self):
|
def test_options_are_not_detected_as_progressive(self):
|
||||||
world_options = self.world.options
|
world_options = self.world.options
|
||||||
tool_progressive = world_options.tool_progression & ToolProgression.option_progressive
|
tool_progressive = self.world.content.features.tool_progression.is_progressive
|
||||||
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
||||||
self.assertFalse(tool_progressive)
|
self.assertFalse(tool_progressive)
|
||||||
self.assertFalse(building_progressive)
|
self.assertFalse(building_progressive)
|
||||||
@@ -43,7 +43,7 @@ class TestBitFlagsVanillaVeryCheap(SVTestBase):
|
|||||||
|
|
||||||
def test_options_are_not_detected_as_progressive(self):
|
def test_options_are_not_detected_as_progressive(self):
|
||||||
world_options = self.world.options
|
world_options = self.world.options
|
||||||
tool_progressive = world_options.tool_progression & ToolProgression.option_progressive
|
tool_progressive = self.world.content.features.tool_progression.is_progressive
|
||||||
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
||||||
self.assertFalse(tool_progressive)
|
self.assertFalse(tool_progressive)
|
||||||
self.assertFalse(building_progressive)
|
self.assertFalse(building_progressive)
|
||||||
@@ -60,7 +60,7 @@ class TestBitFlagsProgressive(SVTestBase):
|
|||||||
|
|
||||||
def test_options_are_detected_as_progressive(self):
|
def test_options_are_detected_as_progressive(self):
|
||||||
world_options = self.world.options
|
world_options = self.world.options
|
||||||
tool_progressive = world_options.tool_progression & ToolProgression.option_progressive
|
tool_progressive = self.world.content.features.tool_progression.is_progressive
|
||||||
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
||||||
self.assertTrue(tool_progressive)
|
self.assertTrue(tool_progressive)
|
||||||
self.assertTrue(building_progressive)
|
self.assertTrue(building_progressive)
|
||||||
@@ -77,7 +77,7 @@ class TestBitFlagsProgressiveCheap(SVTestBase):
|
|||||||
|
|
||||||
def test_options_are_detected_as_progressive(self):
|
def test_options_are_detected_as_progressive(self):
|
||||||
world_options = self.world.options
|
world_options = self.world.options
|
||||||
tool_progressive = world_options.tool_progression & ToolProgression.option_progressive
|
tool_progressive = self.world.content.features.tool_progression.is_progressive
|
||||||
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
||||||
self.assertTrue(tool_progressive)
|
self.assertTrue(tool_progressive)
|
||||||
self.assertTrue(building_progressive)
|
self.assertTrue(building_progressive)
|
||||||
@@ -94,7 +94,7 @@ class TestBitFlagsProgressiveVeryCheap(SVTestBase):
|
|||||||
|
|
||||||
def test_options_are_detected_as_progressive(self):
|
def test_options_are_detected_as_progressive(self):
|
||||||
world_options = self.world.options
|
world_options = self.world.options
|
||||||
tool_progressive = world_options.tool_progression & ToolProgression.option_progressive
|
tool_progressive = self.world.content.features.tool_progression.is_progressive
|
||||||
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
building_progressive = world_options.building_progression & BuildingProgression.option_progressive
|
||||||
self.assertTrue(tool_progressive)
|
self.assertTrue(tool_progressive)
|
||||||
self.assertTrue(building_progressive)
|
self.assertTrue(building_progressive)
|
||||||
|
@@ -1,17 +1,17 @@
|
|||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
from BaseClasses import ItemClassification
|
||||||
from Options import NamedRange
|
from Options import NamedRange
|
||||||
from . import SVTestCase, allsanity_no_mods_6_x_x, allsanity_mods_6_x_x, solo_multiworld
|
from . import SVTestCase, allsanity_no_mods_6_x_x, allsanity_mods_6_x_x, solo_multiworld, SVTestBase
|
||||||
from .assertion import WorldAssertMixin
|
from .assertion import WorldAssertMixin
|
||||||
from .long.option_names import all_option_choices
|
from .long.option_names import all_option_choices
|
||||||
from .. import items_by_group, Group, StardewValleyWorld
|
from .. import items_by_group, Group, StardewValleyWorld
|
||||||
from ..locations import locations_by_tag, LocationTags, location_table
|
from ..locations import locations_by_tag, LocationTags, location_table
|
||||||
from ..options import ExcludeGingerIsland, ToolProgression, Goal, SeasonRandomization, TrapItems, SpecialOrderLocations, ArcadeMachineLocations, \
|
from ..options import ExcludeGingerIsland, ToolProgression, Goal, SeasonRandomization, TrapItems, SpecialOrderLocations, ArcadeMachineLocations
|
||||||
SkillProgression
|
|
||||||
from ..strings.goal_names import Goal as GoalName
|
from ..strings.goal_names import Goal as GoalName
|
||||||
from ..strings.season_names import Season
|
from ..strings.season_names import Season
|
||||||
from ..strings.special_order_names import SpecialOrder
|
from ..strings.special_order_names import SpecialOrder
|
||||||
from ..strings.tool_names import ToolMaterial, Tool
|
from ..strings.tool_names import ToolMaterial, Tool, APTool
|
||||||
|
|
||||||
SEASONS = {Season.spring, Season.summer, Season.fall, Season.winter}
|
SEASONS = {Season.spring, Season.summer, Season.fall, Season.winter}
|
||||||
TOOLS = {"Hoe", "Pickaxe", "Axe", "Watering Can", "Trash Can", "Fishing Rod"}
|
TOOLS = {"Hoe", "Pickaxe", "Axe", "Watering Can", "Trash Can", "Fishing Rod"}
|
||||||
@@ -77,52 +77,30 @@ class TestSeasonRandomization(SVTestCase):
|
|||||||
self.assertEqual(items.count(Season.progressive), 3)
|
self.assertEqual(items.count(Season.progressive), 3)
|
||||||
|
|
||||||
|
|
||||||
class TestToolProgression(SVTestCase):
|
class TestToolProgression(SVTestBase):
|
||||||
def test_given_vanilla_when_generate_then_no_tool_in_pool(self):
|
options = {
|
||||||
world_options = {ToolProgression.internal_name: ToolProgression.option_vanilla}
|
ToolProgression.internal_name: ToolProgression.option_progressive,
|
||||||
with solo_multiworld(world_options) as (multi_world, _):
|
}
|
||||||
items = {item.name for item in multi_world.get_items()}
|
|
||||||
for tool in TOOLS:
|
|
||||||
self.assertNotIn(tool, items)
|
|
||||||
|
|
||||||
def test_given_progressive_when_generate_then_each_tool_is_in_pool_4_times(self):
|
|
||||||
world_options = {ToolProgression.internal_name: ToolProgression.option_progressive,
|
|
||||||
SkillProgression.internal_name: SkillProgression.option_progressive}
|
|
||||||
with solo_multiworld(world_options) as (multi_world, _):
|
|
||||||
items = [item.name for item in multi_world.get_items()]
|
|
||||||
for tool in TOOLS:
|
|
||||||
count = items.count("Progressive " + tool)
|
|
||||||
self.assertEqual(count, 4, f"Progressive {tool} was there {count} times")
|
|
||||||
scythe_count = items.count("Progressive Scythe")
|
|
||||||
self.assertEqual(scythe_count, 1, f"Progressive Scythe was there {scythe_count} times")
|
|
||||||
self.assertEqual(items.count("Golden Scythe"), 0, f"Golden Scythe is deprecated")
|
|
||||||
|
|
||||||
def test_given_progressive_with_masteries_when_generate_then_fishing_rod_is_in_the_pool_5_times(self):
|
|
||||||
world_options = {ToolProgression.internal_name: ToolProgression.option_progressive,
|
|
||||||
SkillProgression.internal_name: SkillProgression.option_progressive_with_masteries}
|
|
||||||
with solo_multiworld(world_options) as (multi_world, _):
|
|
||||||
items = [item.name for item in multi_world.get_items()]
|
|
||||||
for tool in TOOLS:
|
|
||||||
count = items.count("Progressive " + tool)
|
|
||||||
expected_count = 5 if tool == "Fishing Rod" else 4
|
|
||||||
self.assertEqual(count, expected_count, f"Progressive {tool} was there {count} times")
|
|
||||||
scythe_count = items.count("Progressive Scythe")
|
|
||||||
self.assertEqual(scythe_count, 2, f"Progressive Scythe was there {scythe_count} times")
|
|
||||||
self.assertEqual(items.count("Golden Scythe"), 0, f"Golden Scythe is deprecated")
|
|
||||||
|
|
||||||
def test_given_progressive_when_generate_then_tool_upgrades_are_locations(self):
|
def test_given_progressive_when_generate_then_tool_upgrades_are_locations(self):
|
||||||
world_options = {ToolProgression.internal_name: ToolProgression.option_progressive}
|
locations = set(self.get_real_location_names())
|
||||||
with solo_multiworld(world_options) as (multi_world, _):
|
for material, tool in itertools.product(ToolMaterial.tiers.values(),
|
||||||
locations = {locations.name for locations in multi_world.get_locations(1)}
|
[Tool.hoe, Tool.pickaxe, Tool.axe, Tool.watering_can, Tool.trash_can]):
|
||||||
for material, tool in itertools.product(ToolMaterial.tiers.values(),
|
if material == ToolMaterial.basic:
|
||||||
[Tool.hoe, Tool.pickaxe, Tool.axe, Tool.watering_can, Tool.trash_can]):
|
continue
|
||||||
if material == ToolMaterial.basic:
|
self.assertIn(f"{material} {tool} Upgrade", locations)
|
||||||
continue
|
self.assertIn("Purchase Training Rod", locations)
|
||||||
self.assertIn(f"{material} {tool} Upgrade", locations)
|
self.assertIn("Bamboo Pole Cutscene", locations)
|
||||||
self.assertIn("Purchase Training Rod", locations)
|
self.assertIn("Purchase Fiberglass Rod", locations)
|
||||||
self.assertIn("Bamboo Pole Cutscene", locations)
|
self.assertIn("Purchase Iridium Rod", locations)
|
||||||
self.assertIn("Purchase Fiberglass Rod", locations)
|
|
||||||
self.assertIn("Purchase Iridium Rod", locations)
|
def test_given_progressive_when_generate_then_only_3_trash_can_are_progressive(self):
|
||||||
|
trash_cans = self.get_items_by_name(APTool.trash_can)
|
||||||
|
progressive_count = sum([1 for item in trash_cans if item.classification == ItemClassification.progression])
|
||||||
|
useful_count = sum([1 for item in trash_cans if item.classification == ItemClassification.useful])
|
||||||
|
|
||||||
|
self.assertEqual(progressive_count, 3)
|
||||||
|
self.assertEqual(useful_count, 1)
|
||||||
|
|
||||||
|
|
||||||
class TestGenerateAllOptionsWithExcludeGingerIsland(WorldAssertMixin, SVTestCase):
|
class TestGenerateAllOptionsWithExcludeGingerIsland(WorldAssertMixin, SVTestCase):
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
from . import SVTestBase
|
from . import SVTestBase
|
||||||
from ..options import ExcludeGingerIsland, Walnutsanity
|
from ..options import ExcludeGingerIsland, Walnutsanity, ToolProgression, SkillProgression
|
||||||
from ..strings.ap_names.ap_option_names import WalnutsanityOptionName
|
from ..strings.ap_names.ap_option_names import WalnutsanityOptionName
|
||||||
|
|
||||||
|
|
||||||
@@ -7,6 +7,8 @@ class TestWalnutsanityNone(SVTestBase):
|
|||||||
options = {
|
options = {
|
||||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||||
Walnutsanity: Walnutsanity.preset_none,
|
Walnutsanity: Walnutsanity.preset_none,
|
||||||
|
SkillProgression: ToolProgression.option_progressive,
|
||||||
|
ToolProgression: ToolProgression.option_progressive,
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_no_walnut_locations(self):
|
def test_no_walnut_locations(self):
|
||||||
@@ -50,6 +52,8 @@ class TestWalnutsanityPuzzles(SVTestBase):
|
|||||||
options = {
|
options = {
|
||||||
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
ExcludeGingerIsland: ExcludeGingerIsland.option_false,
|
||||||
Walnutsanity: frozenset({WalnutsanityOptionName.puzzles}),
|
Walnutsanity: frozenset({WalnutsanityOptionName.puzzles}),
|
||||||
|
SkillProgression: ToolProgression.option_progressive,
|
||||||
|
ToolProgression: ToolProgression.option_progressive,
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_only_puzzle_walnut_locations(self):
|
def test_only_puzzle_walnut_locations(self):
|
||||||
|
@@ -9,6 +9,7 @@ default_features = StardewFeatures(
|
|||||||
feature.fishsanity.FishsanityNone(),
|
feature.fishsanity.FishsanityNone(),
|
||||||
feature.friendsanity.FriendsanityNone(),
|
feature.friendsanity.FriendsanityNone(),
|
||||||
feature.skill_progression.SkillProgressionVanilla(),
|
feature.skill_progression.SkillProgressionVanilla(),
|
||||||
|
feature.tool_progression.ToolProgressionVanilla()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -0,0 +1,52 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from ....content import choose_tool_progression
|
||||||
|
from ....options import ToolProgression, SkillProgression
|
||||||
|
from ....strings.tool_names import Tool
|
||||||
|
|
||||||
|
|
||||||
|
class TestToolDistribution(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_given_vanilla_tool_progression_when_create_feature_then_only_one_scythe_is_randomized(self):
|
||||||
|
tool_progression = ToolProgression(ToolProgression.option_vanilla)
|
||||||
|
skill_progression = SkillProgression.from_text("random")
|
||||||
|
|
||||||
|
feature = choose_tool_progression(tool_progression, skill_progression)
|
||||||
|
|
||||||
|
self.assertEqual(feature.tool_distribution, {
|
||||||
|
Tool.scythe: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_given_progressive_tool_when_create_feature_then_all_tool_upgrades_are_randomized(self):
|
||||||
|
tool_progression = ToolProgression(ToolProgression.option_progressive)
|
||||||
|
skill_progression = SkillProgression(SkillProgression.option_progressive)
|
||||||
|
|
||||||
|
feature = choose_tool_progression(tool_progression, skill_progression)
|
||||||
|
|
||||||
|
self.assertEqual(feature.tool_distribution, {
|
||||||
|
Tool.scythe: 1,
|
||||||
|
Tool.pickaxe: 4,
|
||||||
|
Tool.axe: 4,
|
||||||
|
Tool.hoe: 4,
|
||||||
|
Tool.watering_can: 4,
|
||||||
|
Tool.trash_can: 4,
|
||||||
|
Tool.pan: 4,
|
||||||
|
Tool.fishing_rod: 4,
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_given_progressive_tool_and_skill_masteries_when_create_feature_then_additional_scythe_and_fishing_rod_are_randomized(self):
|
||||||
|
tool_progression = ToolProgression(ToolProgression.option_progressive)
|
||||||
|
skill_progression = SkillProgression(SkillProgression.option_progressive_with_masteries)
|
||||||
|
|
||||||
|
feature = choose_tool_progression(tool_progression, skill_progression)
|
||||||
|
|
||||||
|
self.assertEqual(feature.tool_distribution, {
|
||||||
|
Tool.scythe: 2,
|
||||||
|
Tool.pickaxe: 4,
|
||||||
|
Tool.axe: 4,
|
||||||
|
Tool.hoe: 4,
|
||||||
|
Tool.watering_can: 4,
|
||||||
|
Tool.trash_can: 4,
|
||||||
|
Tool.pan: 4,
|
||||||
|
Tool.fishing_rod: 5,
|
||||||
|
})
|
Reference in New Issue
Block a user