| 
									
										
										
										
											2024-03-15 15:05:14 +03:00
										 |  |  | from __future__ import annotations | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from dataclasses import dataclass | 
					
						
							|  |  |  | from typing import Collection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .ability_logic import AbilityLogicMixin | 
					
						
							|  |  |  | from .action_logic import ActionLogicMixin | 
					
						
							|  |  |  | from .animal_logic import AnimalLogicMixin | 
					
						
							|  |  |  | from .arcade_logic import ArcadeLogicMixin | 
					
						
							|  |  |  | from .artisan_logic import ArtisanLogicMixin | 
					
						
							|  |  |  | from .base_logic import LogicRegistry | 
					
						
							|  |  |  | from .buff_logic import BuffLogicMixin | 
					
						
							|  |  |  | from .building_logic import BuildingLogicMixin | 
					
						
							|  |  |  | from .bundle_logic import BundleLogicMixin | 
					
						
							|  |  |  | from .combat_logic import CombatLogicMixin | 
					
						
							|  |  |  | from .cooking_logic import CookingLogicMixin | 
					
						
							|  |  |  | from .crafting_logic import CraftingLogicMixin | 
					
						
							|  |  |  | from .crop_logic import CropLogicMixin | 
					
						
							|  |  |  | from .farming_logic import FarmingLogicMixin | 
					
						
							|  |  |  | from .fishing_logic import FishingLogicMixin | 
					
						
							|  |  |  | from .gift_logic import GiftLogicMixin | 
					
						
							|  |  |  | from .has_logic import HasLogicMixin | 
					
						
							|  |  |  | from .mine_logic import MineLogicMixin | 
					
						
							|  |  |  | from .money_logic import MoneyLogicMixin | 
					
						
							|  |  |  | from .monster_logic import MonsterLogicMixin | 
					
						
							|  |  |  | from .museum_logic import MuseumLogicMixin | 
					
						
							|  |  |  | from .pet_logic import PetLogicMixin | 
					
						
							|  |  |  | from .quest_logic import QuestLogicMixin | 
					
						
							|  |  |  | from .received_logic import ReceivedLogicMixin | 
					
						
							|  |  |  | from .region_logic import RegionLogicMixin | 
					
						
							|  |  |  | from .relationship_logic import RelationshipLogicMixin | 
					
						
							|  |  |  | from .season_logic import SeasonLogicMixin | 
					
						
							|  |  |  | from .shipping_logic import ShippingLogicMixin | 
					
						
							|  |  |  | from .skill_logic import SkillLogicMixin | 
					
						
							|  |  |  | from .special_order_logic import SpecialOrderLogicMixin | 
					
						
							|  |  |  | from .time_logic import TimeLogicMixin | 
					
						
							|  |  |  | from .tool_logic import ToolLogicMixin | 
					
						
							|  |  |  | from .traveling_merchant_logic import TravelingMerchantLogicMixin | 
					
						
							|  |  |  | from .wallet_logic import WalletLogicMixin | 
					
						
							|  |  |  | from ..data import all_purchasable_seeds, all_crops | 
					
						
							|  |  |  | from ..data.craftable_data import all_crafting_recipes | 
					
						
							|  |  |  | from ..data.crops_data import crops_by_name | 
					
						
							|  |  |  | from ..data.fish_data import get_fish_for_mods | 
					
						
							|  |  |  | from ..data.museum_data import all_museum_items | 
					
						
							|  |  |  | from ..data.recipe_data import all_cooking_recipes | 
					
						
							|  |  |  | from ..mods.logic.magic_logic import MagicLogicMixin | 
					
						
							|  |  |  | from ..mods.logic.mod_logic import ModLogicMixin | 
					
						
							|  |  |  | from ..mods.mod_data import ModNames | 
					
						
							|  |  |  | from ..options import Cropsanity, SpecialOrderLocations, ExcludeGingerIsland, FestivalLocations, Fishsanity, Friendsanity, StardewValleyOptions | 
					
						
							|  |  |  | from ..stardew_rule import False_, Or, True_, And, StardewRule | 
					
						
							|  |  |  | from ..strings.animal_names import Animal | 
					
						
							|  |  |  | from ..strings.animal_product_names import AnimalProduct | 
					
						
							|  |  |  | from ..strings.ap_names.ap_weapon_names import APWeapon | 
					
						
							|  |  |  | from ..strings.ap_names.buff_names import Buff | 
					
						
							|  |  |  | from ..strings.ap_names.community_upgrade_names import CommunityUpgrade | 
					
						
							|  |  |  | from ..strings.artisan_good_names import ArtisanGood | 
					
						
							|  |  |  | from ..strings.building_names import Building | 
					
						
							|  |  |  | from ..strings.craftable_names import Consumable, Furniture, Ring, Fishing, Lighting, WildSeeds | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | from ..strings.forageable_names import Forageable | 
					
						
							|  |  |  | from ..strings.fruit_tree_names import Sapling | 
					
						
							|  |  |  | from ..strings.generic_names import Generic | 
					
						
							|  |  |  | from ..strings.geode_names import Geode | 
					
						
							|  |  |  | from ..strings.gift_names import Gift | 
					
						
							|  |  |  | from ..strings.ingredient_names import Ingredient | 
					
						
							|  |  |  | from ..strings.machine_names import Machine | 
					
						
							|  |  |  | from ..strings.material_names import Material | 
					
						
							|  |  |  | from ..strings.metal_names import Ore, MetalBar, Mineral, Fossil | 
					
						
							|  |  |  | from ..strings.monster_drop_names import Loot | 
					
						
							|  |  |  | from ..strings.monster_names import Monster | 
					
						
							|  |  |  | from ..strings.region_names import Region | 
					
						
							|  |  |  | from ..strings.season_names import Season | 
					
						
							|  |  |  | from ..strings.seed_names import Seed, TreeSeed | 
					
						
							|  |  |  | from ..strings.skill_names import Skill | 
					
						
							|  |  |  | from ..strings.tool_names import Tool, ToolMaterial | 
					
						
							|  |  |  | from ..strings.villager_names import NPC | 
					
						
							|  |  |  | from ..strings.wallet_item_names import Wallet | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @dataclass(frozen=False, repr=False) | 
					
						
							|  |  |  | class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, BuffLogicMixin, TravelingMerchantLogicMixin, TimeLogicMixin, | 
					
						
							|  |  |  |                    SeasonLogicMixin, MoneyLogicMixin, ActionLogicMixin, ArcadeLogicMixin, ArtisanLogicMixin, GiftLogicMixin, | 
					
						
							|  |  |  |                    BuildingLogicMixin, ShippingLogicMixin, RelationshipLogicMixin, MuseumLogicMixin, WalletLogicMixin, AnimalLogicMixin, | 
					
						
							|  |  |  |                    CombatLogicMixin, MagicLogicMixin, MonsterLogicMixin, ToolLogicMixin, PetLogicMixin, CropLogicMixin, | 
					
						
							|  |  |  |                    SkillLogicMixin, FarmingLogicMixin, BundleLogicMixin, FishingLogicMixin, MineLogicMixin, CookingLogicMixin, AbilityLogicMixin, | 
					
						
							|  |  |  |                    SpecialOrderLogicMixin, QuestLogicMixin, CraftingLogicMixin, ModLogicMixin): | 
					
						
							|  |  |  |     player: int | 
					
						
							|  |  |  |     options: StardewValleyOptions | 
					
						
							|  |  |  |     regions: Collection[str] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, player: int, options: StardewValleyOptions, regions: Collection[str]): | 
					
						
							|  |  |  |         self.registry = LogicRegistry() | 
					
						
							|  |  |  |         super().__init__(player, self.registry, options, regions, self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.registry.fish_rules.update({fish.name: self.fishing.can_catch_fish(fish) for fish in get_fish_for_mods(self.options.mods.value)}) | 
					
						
							|  |  |  |         self.registry.museum_rules.update({donation.item_name: self.museum.can_find_museum_item(donation) for donation in all_museum_items}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for recipe in all_cooking_recipes: | 
					
						
							|  |  |  |             if recipe.mod_name and recipe.mod_name not in self.options.mods: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             can_cook_rule = self.cooking.can_cook(recipe) | 
					
						
							|  |  |  |             if recipe.meal in self.registry.cooking_rules: | 
					
						
							|  |  |  |                 can_cook_rule = can_cook_rule | self.registry.cooking_rules[recipe.meal] | 
					
						
							|  |  |  |             self.registry.cooking_rules[recipe.meal] = can_cook_rule | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for recipe in all_crafting_recipes: | 
					
						
							|  |  |  |             if recipe.mod_name and recipe.mod_name not in self.options.mods: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             can_craft_rule = self.crafting.can_craft(recipe) | 
					
						
							|  |  |  |             if recipe.item in self.registry.crafting_rules: | 
					
						
							|  |  |  |                 can_craft_rule = can_craft_rule | self.registry.crafting_rules[recipe.item] | 
					
						
							|  |  |  |             self.registry.crafting_rules[recipe.item] = can_craft_rule | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.registry.sapling_rules.update({ | 
					
						
							|  |  |  |             Sapling.apple: self.can_buy_sapling(Fruit.apple), | 
					
						
							|  |  |  |             Sapling.apricot: self.can_buy_sapling(Fruit.apricot), | 
					
						
							|  |  |  |             Sapling.cherry: self.can_buy_sapling(Fruit.cherry), | 
					
						
							|  |  |  |             Sapling.orange: self.can_buy_sapling(Fruit.orange), | 
					
						
							|  |  |  |             Sapling.peach: self.can_buy_sapling(Fruit.peach), | 
					
						
							|  |  |  |             Sapling.pomegranate: self.can_buy_sapling(Fruit.pomegranate), | 
					
						
							|  |  |  |             Sapling.banana: self.can_buy_sapling(Fruit.banana), | 
					
						
							|  |  |  |             Sapling.mango: self.can_buy_sapling(Fruit.mango), | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.registry.tree_fruit_rules.update({ | 
					
						
							|  |  |  |             Fruit.apple: self.crop.can_plant_and_grow_item(Season.fall), | 
					
						
							|  |  |  |             Fruit.apricot: self.crop.can_plant_and_grow_item(Season.spring), | 
					
						
							|  |  |  |             Fruit.cherry: self.crop.can_plant_and_grow_item(Season.spring), | 
					
						
							|  |  |  |             Fruit.orange: self.crop.can_plant_and_grow_item(Season.summer), | 
					
						
							|  |  |  |             Fruit.peach: self.crop.can_plant_and_grow_item(Season.summer), | 
					
						
							|  |  |  |             Fruit.pomegranate: self.crop.can_plant_and_grow_item(Season.fall), | 
					
						
							|  |  |  |             Fruit.banana: self.crop.can_plant_and_grow_item(Season.summer), | 
					
						
							|  |  |  |             Fruit.mango: self.crop.can_plant_and_grow_item(Season.summer), | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for tree_fruit in self.registry.tree_fruit_rules: | 
					
						
							|  |  |  |             existing_rules = self.registry.tree_fruit_rules[tree_fruit] | 
					
						
							|  |  |  |             sapling = f"{tree_fruit} Sapling" | 
					
						
							|  |  |  |             self.registry.tree_fruit_rules[tree_fruit] = existing_rules & self.has(sapling) & self.time.has_lived_months(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.registry.seed_rules.update({seed.name: self.crop.can_buy_seed(seed) for seed in all_purchasable_seeds}) | 
					
						
							|  |  |  |         self.registry.crop_rules.update({crop.name: self.crop.can_grow(crop) for crop in all_crops}) | 
					
						
							|  |  |  |         self.registry.crop_rules.update({ | 
					
						
							|  |  |  |             Seed.coffee: (self.season.has(Season.spring) | self.season.has(Season.summer)) & self.crop.can_buy_seed(crops_by_name[Seed.coffee].seed), | 
					
						
							|  |  |  |             Fruit.ancient_fruit: (self.received("Ancient Seeds") | self.received("Ancient Seeds Recipe")) & | 
					
						
							|  |  |  |                                  self.region.can_reach(Region.greenhouse) & self.has(Machine.seed_maker), | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # @formatter:off | 
					
						
							|  |  |  |         self.registry.item_rules.update({ | 
					
						
							|  |  |  |             "Energy Tonic": self.money.can_spend_at(Region.hospital, 1000), | 
					
						
							|  |  |  |             WaterChest.fishing_chest: self.fishing.can_fish_chests(), | 
					
						
							|  |  |  |             WaterChest.treasure: self.fishing.can_fish_chests(), | 
					
						
							|  |  |  |             Ring.hot_java_ring: self.region.can_reach(Region.volcano_floor_10), | 
					
						
							|  |  |  |             "Galaxy Soul": self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 40), | 
					
						
							|  |  |  |             "JotPK Big Buff": self.arcade.has_jotpk_power_level(7), | 
					
						
							|  |  |  |             "JotPK Max Buff": self.arcade.has_jotpk_power_level(9), | 
					
						
							|  |  |  |             "JotPK Medium Buff": self.arcade.has_jotpk_power_level(4), | 
					
						
							|  |  |  |             "JotPK Small Buff": self.arcade.has_jotpk_power_level(2), | 
					
						
							|  |  |  |             "Junimo Kart Big Buff": self.arcade.has_junimo_kart_power_level(6), | 
					
						
							|  |  |  |             "Junimo Kart Max Buff": self.arcade.has_junimo_kart_power_level(8), | 
					
						
							|  |  |  |             "Junimo Kart Medium Buff": self.arcade.has_junimo_kart_power_level(4), | 
					
						
							|  |  |  |             "Junimo Kart Small Buff": self.arcade.has_junimo_kart_power_level(2), | 
					
						
							|  |  |  |             "Magic Rock Candy": self.region.can_reach(Region.desert) & self.has("Prismatic Shard"), | 
					
						
							|  |  |  |             "Muscle Remedy": self.money.can_spend_at(Region.hospital, 1000), | 
					
						
							|  |  |  |             # self.has(Ingredient.vinegar)), | 
					
						
							|  |  |  |             # self.received("Deluxe Fertilizer Recipe") & self.has(MetalBar.iridium) & self.has(SVItem.sap), | 
					
						
							|  |  |  |             # | (self.ability.can_cook() & self.relationship.has_hearts(NPC.emily, 3) & self.has(Forageable.leek) & self.has(Forageable.dandelion) & | 
					
						
							|  |  |  |             # | (self.ability.can_cook() & self.relationship.has_hearts(NPC.jodi, 7) & self.has(AnimalProduct.cow_milk) & self.has(Ingredient.sugar)), | 
					
						
							|  |  |  |             Animal.chicken: self.animal.can_buy_animal(Animal.chicken), | 
					
						
							|  |  |  |             Animal.cow: self.animal.can_buy_animal(Animal.cow), | 
					
						
							|  |  |  |             Animal.dinosaur: self.building.has_building(Building.big_coop) & self.has(AnimalProduct.dinosaur_egg), | 
					
						
							|  |  |  |             Animal.duck: self.animal.can_buy_animal(Animal.duck), | 
					
						
							|  |  |  |             Animal.goat: self.animal.can_buy_animal(Animal.goat), | 
					
						
							|  |  |  |             Animal.ostrich: self.building.has_building(Building.barn) & self.has(AnimalProduct.ostrich_egg) & self.has(Machine.ostrich_incubator), | 
					
						
							|  |  |  |             Animal.pig: self.animal.can_buy_animal(Animal.pig), | 
					
						
							|  |  |  |             Animal.rabbit: self.animal.can_buy_animal(Animal.rabbit), | 
					
						
							|  |  |  |             Animal.sheep: self.animal.can_buy_animal(Animal.sheep), | 
					
						
							|  |  |  |             AnimalProduct.any_egg: self.has_any(AnimalProduct.chicken_egg, AnimalProduct.duck_egg), | 
					
						
							|  |  |  |             AnimalProduct.brown_egg: self.animal.has_animal(Animal.chicken), | 
					
						
							|  |  |  |             AnimalProduct.chicken_egg: self.has_any(AnimalProduct.egg, AnimalProduct.brown_egg, AnimalProduct.large_egg, AnimalProduct.large_brown_egg), | 
					
						
							|  |  |  |             AnimalProduct.cow_milk: self.has_any(AnimalProduct.milk, AnimalProduct.large_milk), | 
					
						
							|  |  |  |             AnimalProduct.duck_egg: self.animal.has_animal(Animal.duck), | 
					
						
							|  |  |  |             AnimalProduct.duck_feather: self.animal.has_happy_animal(Animal.duck), | 
					
						
							|  |  |  |             AnimalProduct.egg: self.animal.has_animal(Animal.chicken), | 
					
						
							|  |  |  |             AnimalProduct.goat_milk: self.has(Animal.goat), | 
					
						
							|  |  |  |             AnimalProduct.golden_egg: self.received(AnimalProduct.golden_egg) & (self.money.can_spend_at(Region.ranch, 100000) | self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 100)), | 
					
						
							|  |  |  |             AnimalProduct.large_brown_egg: self.animal.has_happy_animal(Animal.chicken), | 
					
						
							|  |  |  |             AnimalProduct.large_egg: self.animal.has_happy_animal(Animal.chicken), | 
					
						
							|  |  |  |             AnimalProduct.large_goat_milk: self.animal.has_happy_animal(Animal.goat), | 
					
						
							|  |  |  |             AnimalProduct.large_milk: self.animal.has_happy_animal(Animal.cow), | 
					
						
							|  |  |  |             AnimalProduct.milk: self.animal.has_animal(Animal.cow), | 
					
						
							|  |  |  |             AnimalProduct.ostrich_egg: self.tool.can_forage(Generic.any, Region.island_north, True), | 
					
						
							|  |  |  |             AnimalProduct.rabbit_foot: self.animal.has_happy_animal(Animal.rabbit), | 
					
						
							|  |  |  |             AnimalProduct.roe: self.skill.can_fish() & self.building.has_building(Building.fish_pond), | 
					
						
							|  |  |  |             AnimalProduct.squid_ink: self.mine.can_mine_in_the_mines_floor_81_120() | (self.building.has_building(Building.fish_pond) & self.has(Fish.squid)), | 
					
						
							|  |  |  |             AnimalProduct.sturgeon_roe: self.has(Fish.sturgeon) & self.building.has_building(Building.fish_pond), | 
					
						
							|  |  |  |             AnimalProduct.truffle: self.animal.has_animal(Animal.pig) & self.season.has_any_not_winter(), | 
					
						
							|  |  |  |             AnimalProduct.void_egg: self.money.can_spend_at(Region.sewer, 5000) | (self.building.has_building(Building.fish_pond) & self.has(Fish.void_salmon)), | 
					
						
							|  |  |  |             AnimalProduct.wool: self.animal.has_animal(Animal.rabbit) | self.animal.has_animal(Animal.sheep), | 
					
						
							|  |  |  |             AnimalProduct.slime_egg_green: self.has(Machine.slime_egg_press) & self.has(Loot.slime), | 
					
						
							|  |  |  |             AnimalProduct.slime_egg_blue: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(3), | 
					
						
							|  |  |  |             AnimalProduct.slime_egg_red: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(6), | 
					
						
							|  |  |  |             AnimalProduct.slime_egg_purple: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(9), | 
					
						
							|  |  |  |             AnimalProduct.slime_egg_tiger: self.has(Fish.lionfish) & self.building.has_building(Building.fish_pond), | 
					
						
							|  |  |  |             ArtisanGood.aged_roe: self.artisan.can_preserves_jar(AnimalProduct.roe), | 
					
						
							|  |  |  |             ArtisanGood.battery_pack: (self.has(Machine.lightning_rod) & self.season.has_any_not_winter()) | self.has(Machine.solar_panel), | 
					
						
							|  |  |  |             ArtisanGood.caviar: self.artisan.can_preserves_jar(AnimalProduct.sturgeon_roe), | 
					
						
							|  |  |  |             ArtisanGood.cheese: (self.has(AnimalProduct.cow_milk) & self.has(Machine.cheese_press)) | (self.region.can_reach(Region.desert) & self.has(Mineral.emerald)), | 
					
						
							|  |  |  |             ArtisanGood.cloth: (self.has(AnimalProduct.wool) & self.has(Machine.loom)) | (self.region.can_reach(Region.desert) & self.has(Mineral.aquamarine)), | 
					
						
							|  |  |  |             ArtisanGood.dinosaur_mayonnaise: self.artisan.can_mayonnaise(AnimalProduct.dinosaur_egg), | 
					
						
							|  |  |  |             ArtisanGood.duck_mayonnaise: self.artisan.can_mayonnaise(AnimalProduct.duck_egg), | 
					
						
							|  |  |  |             ArtisanGood.goat_cheese: self.has(AnimalProduct.goat_milk) & self.has(Machine.cheese_press), | 
					
						
							|  |  |  |             ArtisanGood.green_tea: self.artisan.can_keg(Vegetable.tea_leaves), | 
					
						
							|  |  |  |             ArtisanGood.honey: self.money.can_spend_at(Region.oasis, 200) | (self.has(Machine.bee_house) & self.season.has_any_not_winter()), | 
					
						
							|  |  |  |             ArtisanGood.jelly: self.artisan.has_jelly(), | 
					
						
							|  |  |  |             ArtisanGood.juice: self.artisan.has_juice(), | 
					
						
							|  |  |  |             ArtisanGood.maple_syrup: self.has(Machine.tapper), | 
					
						
							|  |  |  |             ArtisanGood.mayonnaise: self.artisan.can_mayonnaise(AnimalProduct.chicken_egg), | 
					
						
							|  |  |  |             ArtisanGood.mead: self.artisan.can_keg(ArtisanGood.honey), | 
					
						
							|  |  |  |             ArtisanGood.oak_resin: self.has(Machine.tapper), | 
					
						
							|  |  |  |             ArtisanGood.pale_ale: self.artisan.can_keg(Vegetable.hops), | 
					
						
							|  |  |  |             ArtisanGood.pickles: self.artisan.has_pickle(), | 
					
						
							|  |  |  |             ArtisanGood.pine_tar: self.has(Machine.tapper), | 
					
						
							|  |  |  |             ArtisanGood.truffle_oil: self.has(AnimalProduct.truffle) & self.has(Machine.oil_maker), | 
					
						
							|  |  |  |             ArtisanGood.void_mayonnaise: (self.skill.can_fish(Region.witch_swamp)) | (self.artisan.can_mayonnaise(AnimalProduct.void_egg)), | 
					
						
							|  |  |  |             ArtisanGood.wine: self.artisan.has_wine(), | 
					
						
							|  |  |  |             Beverage.beer: self.artisan.can_keg(Vegetable.wheat) | self.money.can_spend_at(Region.saloon, 400), | 
					
						
							|  |  |  |             Beverage.coffee: self.artisan.can_keg(Seed.coffee) | self.has(Machine.coffee_maker) | (self.money.can_spend_at(Region.saloon, 300)) | self.has("Hot Java Ring"), | 
					
						
							|  |  |  |             Beverage.pina_colada: self.money.can_spend_at(Region.island_resort, 600), | 
					
						
							|  |  |  |             Beverage.triple_shot_espresso: self.has("Hot Java Ring"), | 
					
						
							|  |  |  |             Decoration.rotten_plant: self.has(Lighting.jack_o_lantern) & self.season.has(Season.winter), | 
					
						
							|  |  |  |             Fertilizer.basic: self.money.can_spend_at(Region.pierre_store, 100), | 
					
						
							|  |  |  |             Fertilizer.quality: self.time.has_year_two & self.money.can_spend_at(Region.pierre_store, 150), | 
					
						
							|  |  |  |             Fertilizer.tree: self.skill.has_level(Skill.foraging, 7) & self.has(Material.fiber) & self.has(Material.stone), | 
					
						
							|  |  |  |             Fish.any: Or(*(self.fishing.can_catch_fish(fish) for fish in get_fish_for_mods(self.options.mods.value))), | 
					
						
							|  |  |  |             Fish.crab: self.skill.can_crab_pot_at(Region.beach), | 
					
						
							|  |  |  |             Fish.crayfish: self.skill.can_crab_pot_at(Region.town), | 
					
						
							|  |  |  |             Fish.lobster: self.skill.can_crab_pot_at(Region.beach), | 
					
						
							|  |  |  |             Fish.mussel: self.tool.can_forage(Generic.any, Region.beach) or self.has(Fish.mussel_node), | 
					
						
							|  |  |  |             Fish.mussel_node: self.region.can_reach(Region.island_west), | 
					
						
							|  |  |  |             Fish.oyster: self.tool.can_forage(Generic.any, Region.beach), | 
					
						
							|  |  |  |             Fish.periwinkle: self.skill.can_crab_pot_at(Region.town), | 
					
						
							|  |  |  |             Fish.shrimp: self.skill.can_crab_pot_at(Region.beach), | 
					
						
							|  |  |  |             Fish.snail: self.skill.can_crab_pot_at(Region.town), | 
					
						
							|  |  |  |             Fishing.curiosity_lure: self.monster.can_kill(self.monster.all_monsters_by_name[Monster.mummy]), | 
					
						
							|  |  |  |             Fishing.lead_bobber: self.skill.has_level(Skill.fishing, 6) & self.money.can_spend_at(Region.fish_shop, 200), | 
					
						
							|  |  |  |             Forageable.blackberry: self.tool.can_forage(Season.fall) | self.has_fruit_bats(), | 
					
						
							|  |  |  |             Forageable.cactus_fruit: self.tool.can_forage(Generic.any, Region.desert), | 
					
						
							|  |  |  |             Forageable.cave_carrot: self.tool.can_forage(Generic.any, Region.mines_floor_10, True), | 
					
						
							|  |  |  |             Forageable.chanterelle: self.tool.can_forage(Season.fall, Region.secret_woods) | self.has_mushroom_cave(), | 
					
						
							|  |  |  |             Forageable.coconut: self.tool.can_forage(Generic.any, Region.desert), | 
					
						
							|  |  |  |             Forageable.common_mushroom: self.tool.can_forage(Season.fall) | (self.tool.can_forage(Season.spring, Region.secret_woods)) | self.has_mushroom_cave(), | 
					
						
							|  |  |  |             Forageable.crocus: self.tool.can_forage(Season.winter), | 
					
						
							|  |  |  |             Forageable.crystal_fruit: self.tool.can_forage(Season.winter), | 
					
						
							|  |  |  |             Forageable.daffodil: self.tool.can_forage(Season.spring), | 
					
						
							|  |  |  |             Forageable.dandelion: self.tool.can_forage(Season.spring), | 
					
						
							|  |  |  |             Forageable.dragon_tooth: self.tool.can_forage(Generic.any, Region.volcano_floor_10), | 
					
						
							|  |  |  |             Forageable.fiddlehead_fern: self.tool.can_forage(Season.summer, Region.secret_woods), | 
					
						
							|  |  |  |             Forageable.ginger: self.tool.can_forage(Generic.any, Region.island_west, True), | 
					
						
							|  |  |  |             Forageable.hay: self.building.has_building(Building.silo) & self.tool.has_tool(Tool.scythe), | 
					
						
							|  |  |  |             Forageable.hazelnut: self.tool.can_forage(Season.fall), | 
					
						
							|  |  |  |             Forageable.holly: self.tool.can_forage(Season.winter), | 
					
						
							|  |  |  |             Forageable.journal_scrap: self.region.can_reach_all((Region.island_west, Region.island_north, Region.island_south, Region.volcano_floor_10)) & self.quest.has_magnifying_glass() & (self.ability.can_chop_trees() | self.mine.can_mine_in_the_mines_floor_1_40()), | 
					
						
							|  |  |  |             Forageable.leek: self.tool.can_forage(Season.spring), | 
					
						
							|  |  |  |             Forageable.magma_cap: self.tool.can_forage(Generic.any, Region.volcano_floor_5), | 
					
						
							|  |  |  |             Forageable.morel: self.tool.can_forage(Season.spring, Region.secret_woods) | self.has_mushroom_cave(), | 
					
						
							|  |  |  |             Forageable.purple_mushroom: self.tool.can_forage(Generic.any, Region.mines_floor_95) | self.tool.can_forage(Generic.any, Region.skull_cavern_25) | self.has_mushroom_cave(), | 
					
						
							|  |  |  |             Forageable.rainbow_shell: self.tool.can_forage(Season.summer, Region.beach), | 
					
						
							|  |  |  |             Forageable.red_mushroom: self.tool.can_forage(Season.summer, Region.secret_woods) | self.tool.can_forage(Season.fall, Region.secret_woods) | self.has_mushroom_cave(), | 
					
						
							|  |  |  |             Forageable.salmonberry: self.tool.can_forage(Season.spring) | self.has_fruit_bats(), | 
					
						
							|  |  |  |             Forageable.secret_note: self.quest.has_magnifying_glass() & (self.ability.can_chop_trees() | self.mine.can_mine_in_the_mines_floor_1_40()), | 
					
						
							|  |  |  |             Forageable.snow_yam: self.tool.can_forage(Season.winter, Region.beach, True), | 
					
						
							|  |  |  |             Forageable.spice_berry: self.tool.can_forage(Season.summer) | self.has_fruit_bats(), | 
					
						
							|  |  |  |             Forageable.spring_onion: self.tool.can_forage(Season.spring), | 
					
						
							|  |  |  |             Forageable.sweet_pea: self.tool.can_forage(Season.summer), | 
					
						
							|  |  |  |             Forageable.wild_horseradish: self.tool.can_forage(Season.spring), | 
					
						
							|  |  |  |             Forageable.wild_plum: self.tool.can_forage(Season.fall) | self.has_fruit_bats(), | 
					
						
							|  |  |  |             Forageable.winter_root: self.tool.can_forage(Season.winter, Region.forest, True), | 
					
						
							|  |  |  |             Fossil.bone_fragment: (self.region.can_reach(Region.dig_site) & self.tool.has_tool(Tool.pickaxe)) | self.monster.can_kill(Monster.skeleton), | 
					
						
							|  |  |  |             Fossil.fossilized_leg: self.region.can_reach(Region.dig_site) & self.tool.has_tool(Tool.pickaxe), | 
					
						
							|  |  |  |             Fossil.fossilized_ribs: self.region.can_reach(Region.island_south) & self.tool.has_tool(Tool.hoe), | 
					
						
							|  |  |  |             Fossil.fossilized_skull: self.action.can_open_geode(Geode.golden_coconut), | 
					
						
							|  |  |  |             Fossil.fossilized_spine: self.skill.can_fish(Region.dig_site), | 
					
						
							|  |  |  |             Fossil.fossilized_tail: self.action.can_pan_at(Region.dig_site), | 
					
						
							|  |  |  |             Fossil.mummified_bat: self.region.can_reach(Region.volcano_floor_10), | 
					
						
							|  |  |  |             Fossil.mummified_frog: self.region.can_reach(Region.island_east) & self.tool.has_tool(Tool.scythe), | 
					
						
							|  |  |  |             Fossil.snake_skull: self.region.can_reach(Region.dig_site) & self.tool.has_tool(Tool.hoe), | 
					
						
							|  |  |  |             Fossil.snake_vertebrae: self.region.can_reach(Region.island_west) & self.tool.has_tool(Tool.hoe), | 
					
						
							|  |  |  |             Geode.artifact_trove: self.has(Geode.omni) & self.region.can_reach(Region.desert), | 
					
						
							|  |  |  |             Geode.frozen: self.mine.can_mine_in_the_mines_floor_41_80(), | 
					
						
							|  |  |  |             Geode.geode: self.mine.can_mine_in_the_mines_floor_1_40(), | 
					
						
							|  |  |  |             Geode.golden_coconut: self.region.can_reach(Region.island_north), | 
					
						
							|  |  |  |             Geode.magma: self.mine.can_mine_in_the_mines_floor_81_120() | (self.has(Fish.lava_eel) & self.building.has_building(Building.fish_pond)), | 
					
						
							|  |  |  |             Geode.omni: self.mine.can_mine_in_the_mines_floor_41_80() | self.region.can_reach(Region.desert) | self.action.can_pan() | self.received(Wallet.rusty_key) | (self.has(Fish.octopus) & self.building.has_building(Building.fish_pond)) | self.region.can_reach(Region.volcano_floor_10), | 
					
						
							|  |  |  |             Gift.bouquet: self.relationship.has_hearts(Generic.bachelor, 8) & self.money.can_spend_at(Region.pierre_store, 100), | 
					
						
							|  |  |  |             Gift.golden_pumpkin: self.season.has(Season.fall) | self.action.can_open_geode(Geode.artifact_trove), | 
					
						
							|  |  |  |             Gift.mermaid_pendant: self.region.can_reach(Region.tide_pools) & self.relationship.has_hearts(Generic.bachelor, 10) & self.building.has_house(1) & self.has(Consumable.rain_totem), | 
					
						
							|  |  |  |             Gift.movie_ticket: self.money.can_spend_at(Region.movie_ticket_stand, 1000), | 
					
						
							|  |  |  |             Gift.pearl: (self.has(Fish.blobfish) & self.building.has_building(Building.fish_pond)) | self.action.can_open_geode(Geode.artifact_trove), | 
					
						
							|  |  |  |             Gift.tea_set: self.season.has(Season.winter) & self.time.has_lived_max_months, | 
					
						
							|  |  |  |             Gift.void_ghost_pendant: self.money.can_trade_at(Region.desert, Loot.void_essence, 200) & self.relationship.has_hearts(NPC.krobus, 10), | 
					
						
							|  |  |  |             Gift.wilted_bouquet: self.has(Machine.furnace) & self.has(Gift.bouquet) & self.has(Material.coal), | 
					
						
							|  |  |  |             Ingredient.oil: self.money.can_spend_at(Region.pierre_store, 200) | (self.has(Machine.oil_maker) & (self.has(Vegetable.corn) | self.has(Flower.sunflower) | self.has(Seed.sunflower))), | 
					
						
							|  |  |  |             Ingredient.qi_seasoning: self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 10), | 
					
						
							|  |  |  |             Ingredient.rice: self.money.can_spend_at(Region.pierre_store, 200) | (self.building.has_building(Building.mill) & self.has(Vegetable.unmilled_rice)), | 
					
						
							|  |  |  |             Ingredient.sugar: self.money.can_spend_at(Region.pierre_store, 100) | (self.building.has_building(Building.mill) & self.has(Vegetable.beet)), | 
					
						
							|  |  |  |             Ingredient.vinegar: self.money.can_spend_at(Region.pierre_store, 200), | 
					
						
							|  |  |  |             Ingredient.wheat_flour: self.money.can_spend_at(Region.pierre_store, 100) | (self.building.has_building(Building.mill) & self.has(Vegetable.wheat)), | 
					
						
							|  |  |  |             Loot.bat_wing: self.mine.can_mine_in_the_mines_floor_41_80() | self.mine.can_mine_in_the_skull_cavern(), | 
					
						
							|  |  |  |             Loot.bug_meat: self.mine.can_mine_in_the_mines_floor_1_40(), | 
					
						
							|  |  |  |             Loot.slime: self.mine.can_mine_in_the_mines_floor_1_40(), | 
					
						
							|  |  |  |             Loot.solar_essence: self.mine.can_mine_in_the_mines_floor_41_80() | self.mine.can_mine_in_the_skull_cavern(), | 
					
						
							|  |  |  |             Loot.void_essence: self.mine.can_mine_in_the_mines_floor_81_120() | self.mine.can_mine_in_the_skull_cavern(), | 
					
						
							|  |  |  |             Machine.bee_house: self.skill.has_farming_level(3) & self.has(MetalBar.iron) & self.has(ArtisanGood.maple_syrup) & self.has(Material.coal) & self.has(Material.wood), | 
					
						
							|  |  |  |             Machine.cask: self.building.has_house(3) & self.region.can_reach(Region.cellar) & self.has(Material.wood) & self.has(Material.hardwood), | 
					
						
							|  |  |  |             Machine.cheese_press: self.skill.has_farming_level(6) & self.has(Material.wood) & self.has(Material.stone) & self.has(Material.hardwood) & self.has(MetalBar.copper), | 
					
						
							|  |  |  |             Machine.coffee_maker: self.received(Machine.coffee_maker), | 
					
						
							|  |  |  |             Machine.crab_pot: self.skill.has_level(Skill.fishing, 3) & (self.money.can_spend_at(Region.fish_shop, 1500) | (self.has(MetalBar.iron) & self.has(Material.wood))), | 
					
						
							|  |  |  |             Machine.furnace: self.has(Material.stone) & self.has(Ore.copper), | 
					
						
							|  |  |  |             Machine.keg: self.skill.has_farming_level(8) & self.has(Material.wood) & self.has(MetalBar.iron) & self.has(MetalBar.copper) & self.has(ArtisanGood.oak_resin), | 
					
						
							|  |  |  |             Machine.lightning_rod: self.skill.has_level(Skill.foraging, 6) & self.has(MetalBar.iron) & self.has(MetalBar.quartz) & self.has(Loot.bat_wing), | 
					
						
							|  |  |  |             Machine.loom: self.skill.has_farming_level(7) & self.has(Material.wood) & self.has(Material.fiber) & self.has(ArtisanGood.pine_tar), | 
					
						
							|  |  |  |             Machine.mayonnaise_machine: self.skill.has_farming_level(2) & self.has(Material.wood) & self.has(Material.stone) & self.has("Earth Crystal") & self.has(MetalBar.copper), | 
					
						
							|  |  |  |             Machine.ostrich_incubator: self.received("Ostrich Incubator Recipe") & self.has(Fossil.bone_fragment) & self.has(Material.hardwood) & self.has(Material.cinder_shard), | 
					
						
							|  |  |  |             Machine.preserves_jar: self.skill.has_farming_level(4) & self.has(Material.wood) & self.has(Material.stone) & self.has(Material.coal), | 
					
						
							|  |  |  |             Machine.recycling_machine: self.skill.has_level(Skill.fishing, 4) & self.has(Material.wood) & self.has(Material.stone) & self.has(MetalBar.iron), | 
					
						
							|  |  |  |             Machine.seed_maker: self.skill.has_farming_level(9) & self.has(Material.wood) & self.has(MetalBar.gold) & self.has(Material.coal), | 
					
						
							|  |  |  |             Machine.solar_panel: self.received("Solar Panel Recipe") & self.has(MetalBar.quartz) & self.has(MetalBar.iron) & self.has(MetalBar.gold), | 
					
						
							|  |  |  |             Machine.tapper: self.skill.has_level(Skill.foraging, 3) & self.has(Material.wood) & self.has(MetalBar.copper), | 
					
						
							|  |  |  |             Machine.worm_bin: self.skill.has_level(Skill.fishing, 8) & self.has(Material.hardwood) & self.has(MetalBar.gold) & self.has(MetalBar.iron) & self.has(Material.fiber), | 
					
						
							|  |  |  |             Machine.enricher: self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 20), | 
					
						
							|  |  |  |             Machine.pressure_nozzle: self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 20), | 
					
						
							|  |  |  |             Material.cinder_shard: self.region.can_reach(Region.volcano_floor_5), | 
					
						
							|  |  |  |             Material.clay: self.region.can_reach_any((Region.farm, Region.beach, Region.quarry)) & self.tool.has_tool(Tool.hoe), | 
					
						
							|  |  |  |             Material.coal: self.mine.can_mine_in_the_mines_floor_41_80() | self.action.can_pan(), | 
					
						
							|  |  |  |             Material.fiber: True_(), | 
					
						
							|  |  |  |             Material.hardwood: self.tool.has_tool(Tool.axe, ToolMaterial.copper) & (self.region.can_reach(Region.secret_woods) | self.region.can_reach(Region.island_west)), | 
					
						
							|  |  |  |             Material.sap: self.ability.can_chop_trees(), | 
					
						
							|  |  |  |             Material.stone: self.tool.has_tool(Tool.pickaxe), | 
					
						
							|  |  |  |             Material.wood: self.tool.has_tool(Tool.axe), | 
					
						
							|  |  |  |             Meal.bread: self.money.can_spend_at(Region.saloon, 120), | 
					
						
							|  |  |  |             Meal.ice_cream: (self.season.has(Season.summer) & self.money.can_spend_at(Region.town, 250)) | self.money.can_spend_at(Region.oasis, 240), | 
					
						
							|  |  |  |             Meal.pizza: self.money.can_spend_at(Region.saloon, 600), | 
					
						
							|  |  |  |             Meal.salad: self.money.can_spend_at(Region.saloon, 220), | 
					
						
							|  |  |  |             Meal.spaghetti: self.money.can_spend_at(Region.saloon, 240), | 
					
						
							|  |  |  |             Meal.strange_bun: self.relationship.has_hearts(NPC.shane, 7) & self.has(Ingredient.wheat_flour) & self.has(Fish.periwinkle) & self.has(ArtisanGood.void_mayonnaise), | 
					
						
							|  |  |  |             MetalBar.copper: self.can_smelt(Ore.copper), | 
					
						
							|  |  |  |             MetalBar.gold: self.can_smelt(Ore.gold), | 
					
						
							|  |  |  |             MetalBar.iridium: self.can_smelt(Ore.iridium), | 
					
						
							|  |  |  |             MetalBar.iron: self.can_smelt(Ore.iron), | 
					
						
							|  |  |  |             MetalBar.quartz: self.can_smelt(Mineral.quartz) | self.can_smelt("Fire Quartz") | (self.has(Machine.recycling_machine) & (self.has(Trash.broken_cd) | self.has(Trash.broken_glasses))), | 
					
						
							|  |  |  |             MetalBar.radioactive: self.can_smelt(Ore.radioactive), | 
					
						
							|  |  |  |             Ore.copper: self.mine.can_mine_in_the_mines_floor_1_40() | self.mine.can_mine_in_the_skull_cavern() | self.action.can_pan(), | 
					
						
							|  |  |  |             Ore.gold: self.mine.can_mine_in_the_mines_floor_81_120() | self.mine.can_mine_in_the_skull_cavern() | self.action.can_pan(), | 
					
						
							|  |  |  |             Ore.iridium: self.mine.can_mine_in_the_skull_cavern() | self.can_fish_pond(Fish.super_cucumber), | 
					
						
							|  |  |  |             Ore.iron: self.mine.can_mine_in_the_mines_floor_41_80() | self.mine.can_mine_in_the_skull_cavern() | self.action.can_pan(), | 
					
						
							|  |  |  |             Ore.radioactive: self.ability.can_mine_perfectly() & self.region.can_reach(Region.qi_walnut_room), | 
					
						
							|  |  |  |             RetainingSoil.basic: self.money.can_spend_at(Region.pierre_store, 100), | 
					
						
							|  |  |  |             RetainingSoil.quality: self.time.has_year_two & self.money.can_spend_at(Region.pierre_store, 150), | 
					
						
							|  |  |  |             Sapling.tea: self.relationship.has_hearts(NPC.caroline, 2) & self.has(Material.fiber) & self.has(Material.wood), | 
					
						
							|  |  |  |             Seed.mixed: self.tool.has_tool(Tool.scythe) & self.region.can_reach_all((Region.farm, Region.forest, Region.town)), | 
					
						
							|  |  |  |             SpeedGro.basic: self.money.can_spend_at(Region.pierre_store, 100), | 
					
						
							|  |  |  |             SpeedGro.deluxe: self.time.has_year_two & self.money.can_spend_at(Region.pierre_store, 150), | 
					
						
							|  |  |  |             Trash.broken_cd: self.skill.can_crab_pot, | 
					
						
							|  |  |  |             Trash.broken_glasses: self.skill.can_crab_pot, | 
					
						
							|  |  |  |             Trash.driftwood: self.skill.can_crab_pot, | 
					
						
							|  |  |  |             Trash.joja_cola: self.money.can_spend_at(Region.saloon, 75), | 
					
						
							|  |  |  |             Trash.soggy_newspaper: self.skill.can_crab_pot, | 
					
						
							|  |  |  |             Trash.trash: self.skill.can_crab_pot, | 
					
						
							|  |  |  |             TreeSeed.acorn: self.skill.has_level(Skill.foraging, 1) & self.ability.can_chop_trees(), | 
					
						
							|  |  |  |             TreeSeed.mahogany: self.region.can_reach(Region.secret_woods) & self.tool.has_tool(Tool.axe, ToolMaterial.iron) & self.skill.has_level(Skill.foraging, 1), | 
					
						
							|  |  |  |             TreeSeed.maple: self.skill.has_level(Skill.foraging, 1) & self.ability.can_chop_trees(), | 
					
						
							|  |  |  |             TreeSeed.mushroom: self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 5), | 
					
						
							|  |  |  |             TreeSeed.pine: self.skill.has_level(Skill.foraging, 1) & self.ability.can_chop_trees(), | 
					
						
							|  |  |  |             Vegetable.tea_leaves: self.has(Sapling.tea) & self.time.has_lived_months(2) & self.season.has_any_not_winter(), | 
					
						
							|  |  |  |             Fish.clam: self.tool.can_forage(Generic.any, Region.beach), | 
					
						
							|  |  |  |             Fish.cockle: self.tool.can_forage(Generic.any, Region.beach), | 
					
						
							|  |  |  |             WaterItem.coral: self.tool.can_forage(Generic.any, Region.tide_pools) | self.tool.can_forage(Season.summer, Region.beach), | 
					
						
							|  |  |  |             WaterItem.green_algae: self.fishing.can_fish_in_freshwater(), | 
					
						
							|  |  |  |             WaterItem.nautilus_shell: self.tool.can_forage(Season.winter, Region.beach), | 
					
						
							|  |  |  |             WaterItem.sea_urchin: self.tool.can_forage(Generic.any, Region.tide_pools), | 
					
						
							|  |  |  |             WaterItem.seaweed: self.skill.can_fish(Region.tide_pools), | 
					
						
							|  |  |  |             WaterItem.white_algae: self.skill.can_fish(Region.mines_floor_20), | 
					
						
							|  |  |  |             WildSeeds.grass_starter: self.money.can_spend_at(Region.pierre_store, 100), | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         # @formatter:on | 
					
						
							|  |  |  |         self.registry.item_rules.update(self.registry.fish_rules) | 
					
						
							|  |  |  |         self.registry.item_rules.update(self.registry.museum_rules) | 
					
						
							|  |  |  |         self.registry.item_rules.update(self.registry.sapling_rules) | 
					
						
							|  |  |  |         self.registry.item_rules.update(self.registry.tree_fruit_rules) | 
					
						
							|  |  |  |         self.registry.item_rules.update(self.registry.seed_rules) | 
					
						
							|  |  |  |         self.registry.item_rules.update(self.registry.crop_rules) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.registry.item_rules.update(self.mod.item.get_modded_item_rules()) | 
					
						
							|  |  |  |         self.mod.item.modify_vanilla_item_rules_with_mod_additions(self.registry.item_rules)  # New regions and content means new ways to obtain old items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # For some recipes, the cooked item can be obtained directly, so we either cook it or get it | 
					
						
							|  |  |  |         for recipe in self.registry.cooking_rules: | 
					
						
							|  |  |  |             cooking_rule = self.registry.cooking_rules[recipe] | 
					
						
							|  |  |  |             obtention_rule = self.registry.item_rules[recipe] if recipe in self.registry.item_rules else False_() | 
					
						
							|  |  |  |             self.registry.item_rules[recipe] = obtention_rule | cooking_rule | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # For some recipes, the crafted item can be obtained directly, so we either craft it or get it | 
					
						
							|  |  |  |         for recipe in self.registry.crafting_rules: | 
					
						
							|  |  |  |             crafting_rule = self.registry.crafting_rules[recipe] | 
					
						
							|  |  |  |             obtention_rule = self.registry.item_rules[recipe] if recipe in self.registry.item_rules else False_() | 
					
						
							|  |  |  |             self.registry.item_rules[recipe] = obtention_rule | crafting_rule | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.building.initialize_rules() | 
					
						
							|  |  |  |         self.building.update_rules(self.mod.building.get_modded_building_rules()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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(Generic.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(), | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.special_order.initialize_rules() | 
					
						
							|  |  |  |         self.special_order.update_rules(self.mod.special_order.get_modded_special_orders_rules()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_buy_sapling(self, fruit: str) -> StardewRule: | 
					
						
							|  |  |  |         sapling_prices = {Fruit.apple: 4000, Fruit.apricot: 2000, Fruit.cherry: 3400, Fruit.orange: 4000, | 
					
						
							|  |  |  |                           Fruit.peach: 6000, | 
					
						
							|  |  |  |                           Fruit.pomegranate: 6000, Fruit.banana: 0, Fruit.mango: 0} | 
					
						
							|  |  |  |         received_sapling = self.received(f"{fruit} Sapling") | 
					
						
							|  |  |  |         if self.options.cropsanity == Cropsanity.option_disabled: | 
					
						
							|  |  |  |             allowed_buy_sapling = True_() | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             allowed_buy_sapling = received_sapling | 
					
						
							|  |  |  |         can_buy_sapling = self.money.can_spend_at(Region.pierre_store, sapling_prices[fruit]) | 
					
						
							|  |  |  |         if fruit == Fruit.banana: | 
					
						
							|  |  |  |             can_buy_sapling = self.has_island_trader() & self.has(Forageable.dragon_tooth) | 
					
						
							|  |  |  |         elif fruit == Fruit.mango: | 
					
						
							|  |  |  |             can_buy_sapling = self.has_island_trader() & self.has(Fish.mussel_node) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return allowed_buy_sapling & can_buy_sapling | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_smelt(self, item: str) -> StardewRule: | 
					
						
							|  |  |  |         return self.has(Machine.furnace) & self.has(item) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_complete_field_office(self) -> StardewRule: | 
					
						
							|  |  |  |         field_office = self.region.can_reach(Region.field_office) | 
					
						
							|  |  |  |         professor_snail = self.received("Open Professor Snail Cave") | 
					
						
							|  |  |  |         tools = self.tool.has_tool(Tool.pickaxe) & self.tool.has_tool(Tool.hoe) & self.tool.has_tool(Tool.scythe) | 
					
						
							|  |  |  |         leg_and_snake_skull = self.has_all(Fossil.fossilized_leg, Fossil.snake_skull) | 
					
						
							|  |  |  |         ribs_and_spine = self.has_all(Fossil.fossilized_ribs, Fossil.fossilized_spine) | 
					
						
							|  |  |  |         skull = self.has(Fossil.fossilized_skull) | 
					
						
							|  |  |  |         tail = self.has(Fossil.fossilized_tail) | 
					
						
							|  |  |  |         frog = self.has(Fossil.mummified_frog) | 
					
						
							|  |  |  |         bat = self.has(Fossil.mummified_bat) | 
					
						
							|  |  |  |         snake_vertebrae = self.has(Fossil.snake_vertebrae) | 
					
						
							|  |  |  |         return field_office & professor_snail & tools & leg_and_snake_skull & ribs_and_spine & skull & tail & frog & bat & snake_vertebrae | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_finish_grandpa_evaluation(self) -> StardewRule: | 
					
						
							|  |  |  |         # https://stardewvalleywiki.com/Grandpa | 
					
						
							|  |  |  |         rules_worth_a_point = [ | 
					
						
							|  |  |  |             self.money.can_have_earned_total(50000),  # 50 000g | 
					
						
							|  |  |  |             self.money.can_have_earned_total(100000),  # 100 000g | 
					
						
							|  |  |  |             self.money.can_have_earned_total(200000),  # 200 000g | 
					
						
							|  |  |  |             self.money.can_have_earned_total(300000),  # 300 000g | 
					
						
							|  |  |  |             self.money.can_have_earned_total(500000),  # 500 000g | 
					
						
							|  |  |  |             self.money.can_have_earned_total(1000000),  # 1 000 000g first point | 
					
						
							|  |  |  |             self.money.can_have_earned_total(1000000),  # 1 000 000g second point | 
					
						
							|  |  |  |             self.skill.has_total_level(30),  # Total Skills: 30 | 
					
						
							|  |  |  |             self.skill.has_total_level(50),  # Total Skills: 50 | 
					
						
							|  |  |  |             self.museum.can_complete_museum(),  # Completing the museum for a point | 
					
						
							|  |  |  |             # Catching every fish not expected | 
					
						
							|  |  |  |             # Shipping every item not expected | 
					
						
							|  |  |  |             self.relationship.can_get_married() & self.building.has_house(2), | 
					
						
							|  |  |  |             self.relationship.has_hearts("5", 8),  # 5 Friends | 
					
						
							|  |  |  |             self.relationship.has_hearts("10", 8),  # 10 friends | 
					
						
							|  |  |  |             self.pet.has_hearts(5),  # Max Pet | 
					
						
							|  |  |  |             self.bundle.can_complete_community_center,  # Community Center Completion | 
					
						
							|  |  |  |             self.bundle.can_complete_community_center,  # CC Ceremony first point | 
					
						
							|  |  |  |             self.bundle.can_complete_community_center,  # CC Ceremony second point | 
					
						
							|  |  |  |             self.received(Wallet.skull_key),  # Skull Key obtained | 
					
						
							|  |  |  |             self.wallet.has_rusty_key(),  # Rusty key obtained | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         return self.count(12, *rules_worth_a_point) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_win_egg_hunt(self) -> StardewRule: | 
					
						
							|  |  |  |         number_of_movement_buffs = self.options.movement_buff_number | 
					
						
							|  |  |  |         if self.options.festival_locations == FestivalLocations.option_hard or number_of_movement_buffs < 2: | 
					
						
							|  |  |  |             return True_() | 
					
						
							|  |  |  |         return self.received(Buff.movement, number_of_movement_buffs // 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_succeed_luau_soup(self) -> StardewRule: | 
					
						
							|  |  |  |         if self.options.festival_locations != FestivalLocations.option_hard: | 
					
						
							|  |  |  |             return True_() | 
					
						
							|  |  |  |         eligible_fish = [Fish.blobfish, Fish.crimsonfish, "Ice Pip", Fish.lava_eel, Fish.legend, Fish.angler, Fish.catfish, Fish.glacierfish, Fish.mutant_carp, | 
					
						
							|  |  |  |                          Fish.spookfish, Fish.stingray, Fish.sturgeon, "Super Cucumber"] | 
					
						
							|  |  |  |         fish_rule = self.has_any(*eligible_fish) | 
					
						
							|  |  |  |         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] | 
					
						
							|  |  |  |         aged_rule = self.has(Machine.cask) & 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_() | 
					
						
							| 
									
										
										
										
											2024-03-28 04:27:49 -04:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2024-03-15 15:05:14 +03:00
										 |  |  |         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.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, ] | 
					
						
							|  |  |  |         fruit_rule = self.has_any(*good_fruits) | 
					
						
							|  |  |  |         good_vegetables = [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] | 
					
						
							|  |  |  |         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_() | 
					
						
							|  |  |  |         return self.region.can_reach(Region.island_trader) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_walnut(self, number: int) -> StardewRule: | 
					
						
							|  |  |  |         if self.options.exclude_ginger_island == ExcludeGingerIsland.option_true: | 
					
						
							|  |  |  |             return False_() | 
					
						
							|  |  |  |         if number <= 0: | 
					
						
							|  |  |  |             return True_() | 
					
						
							|  |  |  |         # https://stardewcommunitywiki.com/Golden_Walnut#Walnut_Locations | 
					
						
							|  |  |  |         reach_south = self.region.can_reach(Region.island_south) | 
					
						
							|  |  |  |         reach_north = self.region.can_reach(Region.island_north) | 
					
						
							|  |  |  |         reach_west = self.region.can_reach(Region.island_west) | 
					
						
							|  |  |  |         reach_hut = self.region.can_reach(Region.leo_hut) | 
					
						
							|  |  |  |         reach_southeast = self.region.can_reach(Region.island_south_east) | 
					
						
							|  |  |  |         reach_field_office = self.region.can_reach(Region.field_office) | 
					
						
							|  |  |  |         reach_pirate_cove = self.region.can_reach(Region.pirate_cove) | 
					
						
							|  |  |  |         reach_outside_areas = And(reach_south, reach_north, reach_west, reach_hut) | 
					
						
							|  |  |  |         reach_volcano_regions = [self.region.can_reach(Region.volcano), | 
					
						
							|  |  |  |                                  self.region.can_reach(Region.volcano_secret_beach), | 
					
						
							|  |  |  |                                  self.region.can_reach(Region.volcano_floor_5), | 
					
						
							|  |  |  |                                  self.region.can_reach(Region.volcano_floor_10)] | 
					
						
							|  |  |  |         reach_volcano = Or(*reach_volcano_regions) | 
					
						
							|  |  |  |         reach_all_volcano = And(*reach_volcano_regions) | 
					
						
							|  |  |  |         reach_walnut_regions = [reach_south, reach_north, reach_west, reach_volcano, reach_field_office] | 
					
						
							|  |  |  |         reach_caves = And(self.region.can_reach(Region.qi_walnut_room), self.region.can_reach(Region.dig_site), | 
					
						
							|  |  |  |                           self.region.can_reach(Region.gourmand_frog_cave), | 
					
						
							|  |  |  |                           self.region.can_reach(Region.colored_crystals_cave), | 
					
						
							|  |  |  |                           self.region.can_reach(Region.shipwreck), self.received(APWeapon.slingshot)) | 
					
						
							|  |  |  |         reach_entire_island = And(reach_outside_areas, reach_all_volcano, | 
					
						
							|  |  |  |                                   reach_caves, reach_southeast, reach_field_office, reach_pirate_cove) | 
					
						
							|  |  |  |         if number <= 5: | 
					
						
							|  |  |  |             return Or(reach_south, reach_north, reach_west, reach_volcano) | 
					
						
							|  |  |  |         if number <= 10: | 
					
						
							|  |  |  |             return self.count(2, *reach_walnut_regions) | 
					
						
							|  |  |  |         if number <= 15: | 
					
						
							|  |  |  |             return self.count(3, *reach_walnut_regions) | 
					
						
							|  |  |  |         if number <= 20: | 
					
						
							|  |  |  |             return And(*reach_walnut_regions) | 
					
						
							|  |  |  |         if number <= 50: | 
					
						
							|  |  |  |             return reach_entire_island | 
					
						
							|  |  |  |         gems = (Mineral.amethyst, Mineral.aquamarine, Mineral.emerald, Mineral.ruby, Mineral.topaz) | 
					
						
							|  |  |  |         return reach_entire_island & self.has(Fruit.banana) & self.has_all(*gems) & self.ability.can_mine_perfectly() & \ | 
					
						
							|  |  |  |             self.ability.can_fish_perfectly() & self.has(Furniture.flute_block) & self.has(Seed.melon) & self.has(Seed.wheat) & self.has(Seed.garlic) & \ | 
					
						
							|  |  |  |             self.can_complete_field_office() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_all_stardrops(self) -> StardewRule: | 
					
						
							|  |  |  |         other_rules = [] | 
					
						
							|  |  |  |         number_of_stardrops_to_receive = 0 | 
					
						
							|  |  |  |         number_of_stardrops_to_receive += 1  # The Mines level 100 | 
					
						
							|  |  |  |         number_of_stardrops_to_receive += 1  # Old Master Cannoli | 
					
						
							|  |  |  |         number_of_stardrops_to_receive += 1  # Museum Stardrop | 
					
						
							|  |  |  |         number_of_stardrops_to_receive += 1  # Krobus Stardrop | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.options.fishsanity == Fishsanity.option_none:  # Master Angler Stardrop | 
					
						
							|  |  |  |             other_rules.append(self.fishing.can_catch_every_fish()) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             number_of_stardrops_to_receive += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.options.festival_locations == FestivalLocations.option_disabled:  # Fair Stardrop | 
					
						
							|  |  |  |             other_rules.append(self.season.has(Season.fall)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             number_of_stardrops_to_receive += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.options.friendsanity == Friendsanity.option_none:  # Spouse Stardrop | 
					
						
							|  |  |  |             other_rules.append(self.relationship.has_hearts(Generic.bachelor, 13)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             number_of_stardrops_to_receive += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ModNames.deepwoods in self.options.mods:  # Petting the Unicorn | 
					
						
							|  |  |  |             number_of_stardrops_to_receive += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not other_rules: | 
					
						
							|  |  |  |             return self.received("Stardrop", number_of_stardrops_to_receive) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return self.received("Stardrop", number_of_stardrops_to_receive) & And(*other_rules) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_prismatic_jelly_reward_access(self) -> StardewRule: | 
					
						
							|  |  |  |         if self.options.special_order_locations == SpecialOrderLocations.option_disabled: | 
					
						
							|  |  |  |             return self.special_order.can_complete_special_order("Prismatic Jelly") | 
					
						
							|  |  |  |         return self.received("Monster Musk Recipe") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_all_rarecrows(self) -> StardewRule: | 
					
						
							|  |  |  |         rules = [] | 
					
						
							|  |  |  |         for rarecrow_number in range(1, 9): | 
					
						
							|  |  |  |             rules.append(self.received(f"Rarecrow #{rarecrow_number}")) | 
					
						
							|  |  |  |         return And(*rules) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_abandoned_jojamart(self) -> StardewRule: | 
					
						
							|  |  |  |         return self.received(CommunityUpgrade.movie_theater, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_movie_theater(self) -> StardewRule: | 
					
						
							|  |  |  |         return self.received(CommunityUpgrade.movie_theater, 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_use_obelisk(self, obelisk: str) -> StardewRule: | 
					
						
							|  |  |  |         return self.region.can_reach(Region.farm) & self.received(obelisk) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_fruit_bats(self) -> StardewRule: | 
					
						
							|  |  |  |         return self.region.can_reach(Region.farm_cave) & self.received(CommunityUpgrade.fruit_bats) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def has_mushroom_cave(self) -> StardewRule: | 
					
						
							|  |  |  |         return self.region.can_reach(Region.farm_cave) & self.received(CommunityUpgrade.mushroom_boxes) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def can_fish_pond(self, fish: str) -> StardewRule: | 
					
						
							|  |  |  |         return self.building.has_building(Building.fish_pond) & self.has(fish) |