Stardew Valley: Fix Art Of Crabbing Logic and Extract Festival Logic (#3625)

* here you go kaito kid

* here you go kaito kid

* move reward logic in its own method

---------

Co-authored-by: Jouramie <jouramie@hotmail.com>
Co-authored-by: Jérémie Bolduc <16137441+Jouramie@users.noreply.github.com>
This commit is contained in:
agilbert1412 2024-09-21 17:05:00 -04:00 committed by GitHub
parent 69d3db21df
commit 204e940f47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 192 additions and 144 deletions

View File

@ -2,7 +2,7 @@ from ..game_content import ContentPack
from ...data import villagers_data, fish_data
from ...data.game_item import GenericSource, ItemTag, Tag, CustomRuleSource, CompoundSource
from ...data.harvest import ForagingSource, SeasonalForagingSource, ArtifactSpotSource
from ...data.requirement import ToolRequirement, BookRequirement, SkillRequirement, SeasonRequirement
from ...data.requirement import ToolRequirement, BookRequirement, SkillRequirement
from ...data.shop import ShopSource, MysteryBoxSource, ArtifactTroveSource, PrizeMachineSource, FishingTreasureChestSource
from ...strings.book_names import Book
from ...strings.crop_names import Fruit
@ -250,10 +250,7 @@ pelican_town = ContentPack(
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),),
Book.the_art_o_crabbing: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),
GenericSource(regions=(Region.beach,),
other_requirements=(ToolRequirement(Tool.fishing_rod, ToolMaterial.iridium),
SkillRequirement(Skill.fishing, 6),
SeasonRequirement(Season.winter))),
CustomRuleSource(create_rule=lambda logic: logic.festival.has_squidfest_day_1_iridium_reward()),
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),),
Book.treasure_appraisal_guide: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),

View File

@ -474,7 +474,7 @@ id,name,classification,groups,mod_name
507,Resource Pack: 40 Calico Egg,useful,"FESTIVAL",
508,Resource Pack: 35 Calico Egg,useful,"FESTIVAL",
509,Resource Pack: 30 Calico Egg,useful,"FESTIVAL",
510,Book: The Art O' Crabbing,useful,"FESTIVAL",
510,Book: The Art O' Crabbing,progression,"FESTIVAL",
511,Mr Qi's Plane Ride,progression,,
521,Power: Price Catalogue,useful,"BOOK_POWER",
522,Power: Mapping Cave Systems,useful,"BOOK_POWER",

1 id name classification groups mod_name
474 507 Resource Pack: 40 Calico Egg useful FESTIVAL
475 508 Resource Pack: 35 Calico Egg useful FESTIVAL
476 509 Resource Pack: 30 Calico Egg useful FESTIVAL
477 510 Book: The Art O' Crabbing useful progression FESTIVAL
478 511 Mr Qi's Plane Ride progression
479 521 Power: Price Catalogue useful BOOK_POWER
480 522 Power: Mapping Cave Systems useful BOOK_POWER

View File

@ -0,0 +1,186 @@
from typing import Union
from .action_logic import ActionLogicMixin
from .animal_logic import AnimalLogicMixin
from .artisan_logic import ArtisanLogicMixin
from .base_logic import BaseLogicMixin, BaseLogic
from .fishing_logic import FishingLogicMixin
from .gift_logic import GiftLogicMixin
from .has_logic import HasLogicMixin
from .money_logic import MoneyLogicMixin
from .monster_logic import MonsterLogicMixin
from .museum_logic import MuseumLogicMixin
from .received_logic import ReceivedLogicMixin
from .region_logic import RegionLogicMixin
from .relationship_logic import RelationshipLogicMixin
from .skill_logic import SkillLogicMixin
from .time_logic import TimeLogicMixin
from ..options import FestivalLocations
from ..stardew_rule import StardewRule
from ..strings.book_names import Book
from ..strings.craftable_names import Fishing
from ..strings.crop_names import Fruit, Vegetable
from ..strings.festival_check_names import FestivalCheck
from ..strings.fish_names import Fish
from ..strings.forageable_names import Forageable
from ..strings.generic_names import Generic
from ..strings.machine_names import Machine
from ..strings.monster_names import Monster
from ..strings.region_names import Region
class FestivalLogicMixin(BaseLogicMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.festival = FestivalLogic(*args, **kwargs)
class FestivalLogic(BaseLogic[Union[HasLogicMixin, ReceivedLogicMixin, FestivalLogicMixin, ArtisanLogicMixin, AnimalLogicMixin, MoneyLogicMixin, TimeLogicMixin,
SkillLogicMixin, RegionLogicMixin, ActionLogicMixin, MonsterLogicMixin, RelationshipLogicMixin, FishingLogicMixin, MuseumLogicMixin, GiftLogicMixin]]):
def initialize_rules(self):
self.registry.festival_rules.update({
FestivalCheck.egg_hunt: self.logic.festival.can_win_egg_hunt(),
FestivalCheck.strawberry_seeds: self.logic.money.can_spend(1000),
FestivalCheck.dance: self.logic.relationship.has_hearts_with_any_bachelor(4),
FestivalCheck.tub_o_flowers: self.logic.money.can_spend(2000),
FestivalCheck.rarecrow_5: self.logic.money.can_spend(2500),
FestivalCheck.luau_soup: self.logic.festival.can_succeed_luau_soup(),
FestivalCheck.moonlight_jellies: self.logic.true_,
FestivalCheck.moonlight_jellies_banner: self.logic.money.can_spend(800),
FestivalCheck.starport_decal: self.logic.money.can_spend(1000),
FestivalCheck.smashing_stone: self.logic.true_,
FestivalCheck.grange_display: self.logic.festival.can_succeed_grange_display(),
FestivalCheck.rarecrow_1: self.logic.true_, # only cost star tokens
FestivalCheck.fair_stardrop: self.logic.true_, # only cost star tokens
FestivalCheck.spirit_eve_maze: self.logic.true_,
FestivalCheck.jack_o_lantern: self.logic.money.can_spend(2000),
FestivalCheck.rarecrow_2: self.logic.money.can_spend(5000),
FestivalCheck.fishing_competition: self.logic.festival.can_win_fishing_competition(),
FestivalCheck.rarecrow_4: self.logic.money.can_spend(5000),
FestivalCheck.mermaid_pearl: self.logic.has(Forageable.secret_note),
FestivalCheck.cone_hat: self.logic.money.can_spend(2500),
FestivalCheck.iridium_fireplace: self.logic.money.can_spend(15000),
FestivalCheck.rarecrow_7: self.logic.money.can_spend(5000) & self.logic.museum.can_donate_museum_artifacts(20),
FestivalCheck.rarecrow_8: self.logic.money.can_spend(5000) & self.logic.museum.can_donate_museum_items(40),
FestivalCheck.lupini_red_eagle: self.logic.money.can_spend(1200),
FestivalCheck.lupini_portrait_mermaid: self.logic.money.can_spend(1200),
FestivalCheck.lupini_solar_kingdom: self.logic.money.can_spend(1200),
FestivalCheck.lupini_clouds: self.logic.time.has_year_two & self.logic.money.can_spend(1200),
FestivalCheck.lupini_1000_years: self.logic.time.has_year_two & self.logic.money.can_spend(1200),
FestivalCheck.lupini_three_trees: self.logic.time.has_year_two & self.logic.money.can_spend(1200),
FestivalCheck.lupini_the_serpent: self.logic.time.has_year_three & self.logic.money.can_spend(1200),
FestivalCheck.lupini_tropical_fish: self.logic.time.has_year_three & self.logic.money.can_spend(1200),
FestivalCheck.lupini_land_of_clay: self.logic.time.has_year_three & self.logic.money.can_spend(1200),
FestivalCheck.secret_santa: self.logic.gifts.has_any_universal_love,
FestivalCheck.legend_of_the_winter_star: self.logic.true_,
FestivalCheck.rarecrow_3: self.logic.true_,
FestivalCheck.all_rarecrows: self.logic.region.can_reach(Region.farm) & self.logic.festival.has_all_rarecrows(),
FestivalCheck.calico_race: self.logic.true_,
FestivalCheck.mummy_mask: self.logic.true_,
FestivalCheck.calico_statue: self.logic.true_,
FestivalCheck.emily_outfit_service: self.logic.true_,
FestivalCheck.earthy_mousse: self.logic.true_,
FestivalCheck.sweet_bean_cake: self.logic.true_,
FestivalCheck.skull_cave_casserole: self.logic.true_,
FestivalCheck.spicy_tacos: self.logic.true_,
FestivalCheck.mountain_chili: self.logic.true_,
FestivalCheck.crystal_cake: self.logic.true_,
FestivalCheck.cave_kebab: self.logic.true_,
FestivalCheck.hot_log: self.logic.true_,
FestivalCheck.sour_salad: self.logic.true_,
FestivalCheck.superfood_cake: self.logic.true_,
FestivalCheck.warrior_smoothie: self.logic.true_,
FestivalCheck.rumpled_fruit_skin: self.logic.true_,
FestivalCheck.calico_pizza: self.logic.true_,
FestivalCheck.stuffed_mushrooms: self.logic.true_,
FestivalCheck.elf_quesadilla: self.logic.true_,
FestivalCheck.nachos_of_the_desert: self.logic.true_,
FestivalCheck.cloppino: self.logic.true_,
FestivalCheck.rainforest_shrimp: self.logic.true_,
FestivalCheck.shrimp_donut: self.logic.true_,
FestivalCheck.smell_of_the_sea: self.logic.true_,
FestivalCheck.desert_gumbo: self.logic.true_,
FestivalCheck.free_cactis: self.logic.true_,
FestivalCheck.monster_hunt: self.logic.monster.can_kill(Monster.serpent),
FestivalCheck.deep_dive: self.logic.region.can_reach(Region.skull_cavern_50),
FestivalCheck.treasure_hunt: self.logic.region.can_reach(Region.skull_cavern_25),
FestivalCheck.touch_calico_statue: self.logic.region.can_reach(Region.skull_cavern_25),
FestivalCheck.real_calico_egg_hunter: self.logic.region.can_reach(Region.skull_cavern_100),
FestivalCheck.willy_challenge: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.scorpion_carp]),
FestivalCheck.desert_scholar: self.logic.true_,
FestivalCheck.squidfest_day_1_copper: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]),
FestivalCheck.squidfest_day_1_iron: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]) & self.logic.has(Fishing.bait),
FestivalCheck.squidfest_day_1_gold: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]) & self.logic.has(Fishing.deluxe_bait),
FestivalCheck.squidfest_day_1_iridium: self.logic.festival.can_squidfest_day_1_iridium_reward(),
FestivalCheck.squidfest_day_2_copper: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]),
FestivalCheck.squidfest_day_2_iron: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]) & self.logic.has(Fishing.bait),
FestivalCheck.squidfest_day_2_gold: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]) & self.logic.has(Fishing.deluxe_bait),
FestivalCheck.squidfest_day_2_iridium: self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]) &
self.logic.fishing.has_specific_bait(self.content.fishes[Fish.squid]),
})
for i in range(1, 11):
check_name = f"{FestivalCheck.trout_derby_reward_pattern}{i}"
self.registry.festival_rules[check_name] = self.logic.fishing.can_catch_fish(self.content.fishes[Fish.rainbow_trout])
def can_squidfest_day_1_iridium_reward(self) -> StardewRule:
return self.logic.fishing.can_catch_fish(self.content.fishes[Fish.squid]) & self.logic.fishing.has_specific_bait(self.content.fishes[Fish.squid])
def has_squidfest_day_1_iridium_reward(self) -> StardewRule:
if self.options.festival_locations == FestivalLocations.option_disabled:
return self.logic.festival.can_squidfest_day_1_iridium_reward()
else:
return self.logic.received(f"Book: {Book.the_art_o_crabbing}")
def can_win_egg_hunt(self) -> StardewRule:
return self.logic.true_
def can_succeed_luau_soup(self) -> StardewRule:
if self.options.festival_locations != FestivalLocations.option_hard:
return self.logic.true_
eligible_fish = (Fish.blobfish, Fish.crimsonfish, Fish.ice_pip, Fish.lava_eel, Fish.legend, Fish.angler, Fish.catfish, Fish.glacierfish,
Fish.mutant_carp, Fish.spookfish, Fish.stingray, Fish.sturgeon, Fish.super_cucumber)
fish_rule = self.logic.has_any(*(f for f in eligible_fish if f in self.content.fishes)) # To filter stingray
eligible_kegables = (Fruit.ancient_fruit, Fruit.apple, Fruit.banana, Forageable.coconut, Forageable.crystal_fruit, Fruit.mango, Fruit.melon,
Fruit.orange, Fruit.peach, Fruit.pineapple, Fruit.pomegranate, Fruit.rhubarb, Fruit.starfruit, Fruit.strawberry,
Forageable.cactus_fruit, Fruit.cherry, Fruit.cranberries, Fruit.grape, Forageable.spice_berry, Forageable.wild_plum,
Vegetable.hops, Vegetable.wheat)
keg_rules = [self.logic.artisan.can_keg(kegable) for kegable in eligible_kegables if kegable in self.content.game_items]
aged_rule = self.logic.has(Machine.cask) & self.logic.or_(*keg_rules)
# There are a few other valid items, but I don't feel like coding them all
return fish_rule | aged_rule
def can_succeed_grange_display(self) -> StardewRule:
if self.options.festival_locations != FestivalLocations.option_hard:
return self.logic.true_
animal_rule = self.logic.animal.has_animal(Generic.any)
artisan_rule = self.logic.artisan.can_keg(Generic.any) | self.logic.artisan.can_preserves_jar(Generic.any)
cooking_rule = self.logic.money.can_spend_at(Region.saloon, 220) # Salads at the bar are good enough
fish_rule = self.logic.skill.can_fish(difficulty=50)
forage_rule = self.logic.region.can_reach_any((Region.forest, Region.backwoods)) # Hazelnut always available since the grange display is in fall
mineral_rule = self.logic.action.can_open_geode(Generic.any) # More than half the minerals are good enough
good_fruits = (fruit
for fruit in
(Fruit.apple, Fruit.banana, Forageable.coconut, Forageable.crystal_fruit, Fruit.mango, Fruit.orange, Fruit.peach, Fruit.pomegranate,
Fruit.strawberry, Fruit.melon, Fruit.rhubarb, Fruit.pineapple, Fruit.ancient_fruit, Fruit.starfruit)
if fruit in self.content.game_items)
fruit_rule = self.logic.has_any(*good_fruits)
good_vegetables = (vegeteable
for vegeteable in
(Vegetable.amaranth, Vegetable.artichoke, Vegetable.beet, Vegetable.cauliflower, Forageable.fiddlehead_fern, Vegetable.kale,
Vegetable.radish, Vegetable.taro_root, Vegetable.yam, Vegetable.red_cabbage, Vegetable.pumpkin)
if vegeteable in self.content.game_items)
vegetable_rule = self.logic.has_any(*good_vegetables)
return animal_rule & artisan_rule & cooking_rule & fish_rule & \
forage_rule & fruit_rule & mineral_rule & vegetable_rule
def can_win_fishing_competition(self) -> StardewRule:
return self.logic.skill.can_fish(difficulty=60)
def has_all_rarecrows(self) -> StardewRule:
rules = []
for rarecrow_number in range(1, 9):
rules.append(self.logic.received(f"Rarecrow #{rarecrow_number}"))
return self.logic.and_(*rules)

View File

@ -16,6 +16,7 @@ from .combat_logic import CombatLogicMixin
from .cooking_logic import CookingLogicMixin
from .crafting_logic import CraftingLogicMixin
from .farming_logic import FarmingLogicMixin
from .festival_logic import FestivalLogicMixin
from .fishing_logic import FishingLogicMixin
from .gift_logic import GiftLogicMixin
from .grind_logic import GrindLogicMixin
@ -62,7 +63,6 @@ from ..strings.crop_names import Fruit, Vegetable
from ..strings.currency_names import Currency
from ..strings.decoration_names import Decoration
from ..strings.fertilizer_names import Fertilizer, SpeedGro, RetainingSoil
from ..strings.festival_check_names import FestivalCheck
from ..strings.fish_names import Fish, Trash, WaterItem, WaterChest
from ..strings.flower_names import Flower
from ..strings.food_names import Meal, Beverage
@ -94,7 +94,7 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
CombatLogicMixin, MagicLogicMixin, MonsterLogicMixin, ToolLogicMixin, PetLogicMixin, QualityLogicMixin,
SkillLogicMixin, FarmingLogicMixin, BundleLogicMixin, FishingLogicMixin, MineLogicMixin, CookingLogicMixin, AbilityLogicMixin,
SpecialOrderLogicMixin, QuestLogicMixin, CraftingLogicMixin, ModLogicMixin, HarvestingLogicMixin, SourceLogicMixin,
RequirementLogicMixin, BookLogicMixin, GrindLogicMixin, WalnutLogicMixin):
RequirementLogicMixin, BookLogicMixin, GrindLogicMixin, FestivalLogicMixin, WalnutLogicMixin):
player: int
options: StardewValleyOptions
content: StardewContent
@ -363,89 +363,7 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
self.quest.initialize_rules()
self.quest.update_rules(self.mod.quest.get_modded_quest_rules())
self.registry.festival_rules.update({
FestivalCheck.egg_hunt: self.can_win_egg_hunt(),
FestivalCheck.strawberry_seeds: self.money.can_spend(1000),
FestivalCheck.dance: self.relationship.has_hearts_with_any_bachelor(4),
FestivalCheck.tub_o_flowers: self.money.can_spend(2000),
FestivalCheck.rarecrow_5: self.money.can_spend(2500),
FestivalCheck.luau_soup: self.can_succeed_luau_soup(),
FestivalCheck.moonlight_jellies: True_(),
FestivalCheck.moonlight_jellies_banner: self.money.can_spend(800),
FestivalCheck.starport_decal: self.money.can_spend(1000),
FestivalCheck.smashing_stone: True_(),
FestivalCheck.grange_display: self.can_succeed_grange_display(),
FestivalCheck.rarecrow_1: True_(), # only cost star tokens
FestivalCheck.fair_stardrop: True_(), # only cost star tokens
FestivalCheck.spirit_eve_maze: True_(),
FestivalCheck.jack_o_lantern: self.money.can_spend(2000),
FestivalCheck.rarecrow_2: self.money.can_spend(5000),
FestivalCheck.fishing_competition: self.can_win_fishing_competition(),
FestivalCheck.rarecrow_4: self.money.can_spend(5000),
FestivalCheck.mermaid_pearl: self.has(Forageable.secret_note),
FestivalCheck.cone_hat: self.money.can_spend(2500),
FestivalCheck.iridium_fireplace: self.money.can_spend(15000),
FestivalCheck.rarecrow_7: self.money.can_spend(5000) & self.museum.can_donate_museum_artifacts(20),
FestivalCheck.rarecrow_8: self.money.can_spend(5000) & self.museum.can_donate_museum_items(40),
FestivalCheck.lupini_red_eagle: self.money.can_spend(1200),
FestivalCheck.lupini_portrait_mermaid: self.money.can_spend(1200),
FestivalCheck.lupini_solar_kingdom: self.money.can_spend(1200),
FestivalCheck.lupini_clouds: self.time.has_year_two & self.money.can_spend(1200),
FestivalCheck.lupini_1000_years: self.time.has_year_two & self.money.can_spend(1200),
FestivalCheck.lupini_three_trees: self.time.has_year_two & self.money.can_spend(1200),
FestivalCheck.lupini_the_serpent: self.time.has_year_three & self.money.can_spend(1200),
FestivalCheck.lupini_tropical_fish: self.time.has_year_three & self.money.can_spend(1200),
FestivalCheck.lupini_land_of_clay: self.time.has_year_three & self.money.can_spend(1200),
FestivalCheck.secret_santa: self.gifts.has_any_universal_love,
FestivalCheck.legend_of_the_winter_star: True_(),
FestivalCheck.rarecrow_3: True_(),
FestivalCheck.all_rarecrows: self.region.can_reach(Region.farm) & self.has_all_rarecrows(),
FestivalCheck.calico_race: True_(),
FestivalCheck.mummy_mask: True_(),
FestivalCheck.calico_statue: True_(),
FestivalCheck.emily_outfit_service: True_(),
FestivalCheck.earthy_mousse: True_(),
FestivalCheck.sweet_bean_cake: True_(),
FestivalCheck.skull_cave_casserole: True_(),
FestivalCheck.spicy_tacos: True_(),
FestivalCheck.mountain_chili: True_(),
FestivalCheck.crystal_cake: True_(),
FestivalCheck.cave_kebab: True_(),
FestivalCheck.hot_log: True_(),
FestivalCheck.sour_salad: True_(),
FestivalCheck.superfood_cake: True_(),
FestivalCheck.warrior_smoothie: True_(),
FestivalCheck.rumpled_fruit_skin: True_(),
FestivalCheck.calico_pizza: True_(),
FestivalCheck.stuffed_mushrooms: True_(),
FestivalCheck.elf_quesadilla: True_(),
FestivalCheck.nachos_of_the_desert: True_(),
FestivalCheck.cloppino: True_(),
FestivalCheck.rainforest_shrimp: True_(),
FestivalCheck.shrimp_donut: True_(),
FestivalCheck.smell_of_the_sea: True_(),
FestivalCheck.desert_gumbo: True_(),
FestivalCheck.free_cactis: True_(),
FestivalCheck.monster_hunt: self.monster.can_kill(Monster.serpent),
FestivalCheck.deep_dive: self.region.can_reach(Region.skull_cavern_50),
FestivalCheck.treasure_hunt: self.region.can_reach(Region.skull_cavern_25),
FestivalCheck.touch_calico_statue: self.region.can_reach(Region.skull_cavern_25),
FestivalCheck.real_calico_egg_hunter: self.region.can_reach(Region.skull_cavern_100),
FestivalCheck.willy_challenge: self.fishing.can_catch_fish(content.fishes[Fish.scorpion_carp]),
FestivalCheck.desert_scholar: True_(),
FestivalCheck.squidfest_day_1_copper: self.fishing.can_catch_fish(content.fishes[Fish.squid]),
FestivalCheck.squidfest_day_1_iron: self.fishing.can_catch_fish(content.fishes[Fish.squid]) & self.has(Fishing.bait),
FestivalCheck.squidfest_day_1_gold: self.fishing.can_catch_fish(content.fishes[Fish.squid]) & self.has(Fishing.deluxe_bait),
FestivalCheck.squidfest_day_1_iridium: self.fishing.can_catch_fish(content.fishes[Fish.squid]) &
self.fishing.has_specific_bait(content.fishes[Fish.squid]),
FestivalCheck.squidfest_day_2_copper: self.fishing.can_catch_fish(content.fishes[Fish.squid]),
FestivalCheck.squidfest_day_2_iron: self.fishing.can_catch_fish(content.fishes[Fish.squid]) & self.has(Fishing.bait),
FestivalCheck.squidfest_day_2_gold: self.fishing.can_catch_fish(content.fishes[Fish.squid]) & self.has(Fishing.deluxe_bait),
FestivalCheck.squidfest_day_2_iridium: self.fishing.can_catch_fish(content.fishes[Fish.squid]) &
self.fishing.has_specific_bait(content.fishes[Fish.squid]),
})
for i in range(1, 11):
self.registry.festival_rules[f"{FestivalCheck.trout_derby_reward_pattern}{i}"] = self.fishing.can_catch_fish(content.fishes[Fish.rainbow_trout])
self.festival.initialize_rules()
self.special_order.initialize_rules()
self.special_order.update_rules(self.mod.special_order.get_modded_special_orders_rules())
@ -486,53 +404,6 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
]
return self.count(12, *rules_worth_a_point)
def can_win_egg_hunt(self) -> StardewRule:
return True_()
def can_succeed_luau_soup(self) -> StardewRule:
if self.options.festival_locations != FestivalLocations.option_hard:
return True_()
eligible_fish = (Fish.blobfish, Fish.crimsonfish, Fish.ice_pip, Fish.lava_eel, Fish.legend, Fish.angler, Fish.catfish, Fish.glacierfish,
Fish.mutant_carp, Fish.spookfish, Fish.stingray, Fish.sturgeon, Fish.super_cucumber)
fish_rule = self.has_any(*(f for f in eligible_fish if f in self.content.fishes)) # To filter stingray
eligible_kegables = (Fruit.ancient_fruit, Fruit.apple, Fruit.banana, Forageable.coconut, Forageable.crystal_fruit, Fruit.mango, Fruit.melon,
Fruit.orange, Fruit.peach, Fruit.pineapple, Fruit.pomegranate, Fruit.rhubarb, Fruit.starfruit, Fruit.strawberry,
Forageable.cactus_fruit, Fruit.cherry, Fruit.cranberries, Fruit.grape, Forageable.spice_berry, Forageable.wild_plum,
Vegetable.hops, Vegetable.wheat)
keg_rules = [self.artisan.can_keg(kegable) for kegable in eligible_kegables if kegable in self.content.game_items]
aged_rule = self.has(Machine.cask) & self.logic.or_(*keg_rules)
# There are a few other valid items, but I don't feel like coding them all
return fish_rule | aged_rule
def can_succeed_grange_display(self) -> StardewRule:
if self.options.festival_locations != FestivalLocations.option_hard:
return True_()
animal_rule = self.animal.has_animal(Generic.any)
artisan_rule = self.artisan.can_keg(Generic.any) | self.artisan.can_preserves_jar(Generic.any)
cooking_rule = self.money.can_spend_at(Region.saloon, 220) # Salads at the bar are good enough
fish_rule = self.skill.can_fish(difficulty=50)
forage_rule = self.region.can_reach_any((Region.forest, Region.backwoods)) # Hazelnut always available since the grange display is in fall
mineral_rule = self.action.can_open_geode(Generic.any) # More than half the minerals are good enough
good_fruits = (fruit
for fruit in
(Fruit.apple, Fruit.banana, Forageable.coconut, Forageable.crystal_fruit, Fruit.mango, Fruit.orange, Fruit.peach, Fruit.pomegranate,
Fruit.strawberry, Fruit.melon, Fruit.rhubarb, Fruit.pineapple, Fruit.ancient_fruit, Fruit.starfruit)
if fruit in self.content.game_items)
fruit_rule = self.has_any(*good_fruits)
good_vegetables = (vegeteable
for vegeteable in
(Vegetable.amaranth, Vegetable.artichoke, Vegetable.beet, Vegetable.cauliflower, Forageable.fiddlehead_fern, Vegetable.kale,
Vegetable.radish, Vegetable.taro_root, Vegetable.yam, Vegetable.red_cabbage, Vegetable.pumpkin)
if vegeteable in self.content.game_items)
vegetable_rule = self.has_any(*good_vegetables)
return animal_rule & artisan_rule & cooking_rule & fish_rule & \
forage_rule & fruit_rule & mineral_rule & vegetable_rule
def can_win_fishing_competition(self) -> StardewRule:
return self.skill.can_fish(difficulty=60)
def has_island_trader(self) -> StardewRule:
if self.options.exclude_ginger_island == ExcludeGingerIsland.option_true:
return False_()
@ -571,12 +442,6 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
return self.received("Stardrop", number_of_stardrops_to_receive) & self.logic.and_(*other_rules)
def has_all_rarecrows(self) -> StardewRule:
rules = []
for rarecrow_number in range(1, 9):
rules.append(self.received(f"Rarecrow #{rarecrow_number}"))
return self.logic.and_(*rules)
def has_abandoned_jojamart(self) -> StardewRule:
return self.received(CommunityUpgrade.movie_theater, 1)