Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stardew valley: Add Marlon bedroom entrance rule #3735

Merged
8 changes: 5 additions & 3 deletions worlds/stardew_valley/content/vanilla/pelican_town.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from ..game_content import ContentPack
from ...data import villagers_data, fish_data
from ...data.game_item import GenericSource, ItemTag, Tag, CustomRuleSource
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.shop import ShopSource, MysteryBoxSource, ArtifactTroveSource, PrizeMachineSource, FishingTreasureChestSource
Expand Down Expand Up @@ -229,8 +229,10 @@
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),),
Book.mapping_cave_systems: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),
GenericSource(regions=(Region.adventurer_guild_bedroom,)),
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),),
CompoundSource(sources=(
GenericSource(regions=(Region.adventurer_guild_bedroom,)),
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),
))),
Book.monster_compendium: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),
CustomRuleSource(create_rule=lambda logic: logic.monster.can_kill_many(Generic.any)),
Expand Down
5 changes: 5 additions & 0 deletions worlds/stardew_valley/data/game_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ class CustomRuleSource(ItemSource):
create_rule: Callable[[Any], StardewRule]


@dataclass(frozen=True, **kw_only)
class CompoundSource(ItemSource):
sources: Tuple[ItemSource, ...] = ()


class Tag(ItemSource):
"""Not a real source, just a way to add tags to an item. Will be removed from the item sources during unpacking."""
tag: Tuple[ItemTag, ...]
Expand Down
12 changes: 10 additions & 2 deletions worlds/stardew_valley/logic/source_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .requirement_logic import RequirementLogicMixin
from .tool_logic import ToolLogicMixin
from ..data.artisan import MachineSource
from ..data.game_item import GenericSource, ItemSource, GameItem, CustomRuleSource
from ..data.game_item import GenericSource, ItemSource, GameItem, CustomRuleSource, CompoundSource
from ..data.harvest import ForagingSource, FruitBatsSource, MushroomCaveSource, SeasonalForagingSource, \
HarvestCropSource, HarvestFruitTreeSource, ArtifactSpotSource
from ..data.shop import ShopSource, MysteryBoxSource, ArtifactTroveSource, PrizeMachineSource, FishingTreasureChestSource
Expand All @@ -25,7 +25,7 @@ def __init__(self, *args, **kwargs):


class SourceLogic(BaseLogic[Union[SourceLogicMixin, HasLogicMixin, ReceivedLogicMixin, HarvestingLogicMixin, MoneyLogicMixin, RegionLogicMixin,
ArtisanLogicMixin, ToolLogicMixin, RequirementLogicMixin, GrindLogicMixin]]):
ArtisanLogicMixin, ToolLogicMixin, RequirementLogicMixin, GrindLogicMixin]]):

def has_access_to_item(self, item: GameItem):
rules = []
Expand All @@ -40,6 +40,10 @@ def has_access_to_any(self, sources: Iterable[ItemSource]):
return self.logic.or_(*(self.logic.source.has_access_to(source) & self.logic.requirement.meet_all_requirements(source.other_requirements)
for source in sources))

def has_access_to_all(self, sources: Iterable[ItemSource]):
return self.logic.and_(*(self.logic.source.has_access_to(source) & self.logic.requirement.meet_all_requirements(source.other_requirements)
for source in sources))

@functools.singledispatchmethod
def has_access_to(self, source: Any):
raise ValueError(f"Sources of type{type(source)} have no rule registered.")
Expand All @@ -52,6 +56,10 @@ def _(self, source: GenericSource):
def _(self, source: CustomRuleSource):
return source.create_rule(self.logic)

@has_access_to.register
def _(self, source: CompoundSource):
return self.logic.source.has_access_to_all(source.sources)

@has_access_to.register
def _(self, source: ForagingSource):
return self.logic.harvesting.can_forage_from(source)
Expand Down
2 changes: 2 additions & 0 deletions worlds/stardew_valley/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from .strings.entrance_names import dig_to_mines_floor, dig_to_skull_floor, Entrance, move_to_woods_depth, DeepWoodsEntrance, AlecEntrance, \
SVEEntrance, LaceyEntrance, BoardingHouseEntrance, LogicEntrance
from .strings.forageable_names import Forageable
from .strings.generic_names import Generic
from .strings.geode_names import Geode
from .strings.material_names import Material
from .strings.metal_names import MetalBar, Mineral
Expand Down Expand Up @@ -263,6 +264,7 @@ def set_entrance_rules(logic: StardewLogic, multiworld, player, world_options: S
set_entrance_rule(multiworld, player, LogicEntrance.buy_experience_books, logic.time.has_lived_months(2))
set_entrance_rule(multiworld, player, LogicEntrance.buy_year1_books, logic.time.has_year_two)
set_entrance_rule(multiworld, player, LogicEntrance.buy_year3_books, logic.time.has_year_three)
set_entrance_rule(multiworld, player, Entrance.adventurer_guild_to_bedroom, logic.monster.can_kill_max(Generic.any))


def set_dangerous_mine_rules(logic, multiworld, player, world_options: StardewValleyOptions):
Expand Down
4 changes: 2 additions & 2 deletions worlds/stardew_valley/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,10 @@ def run_default_tests(self) -> bool:
return False
return super().run_default_tests

def collect_lots_of_money(self):
def collect_lots_of_money(self, percent: float = 0.25):
self.multiworld.state.collect(self.world.create_item("Shipping Bin"), prevent_sweep=False)
real_total_prog_items = self.multiworld.worlds[self.player].total_progression_items
required_prog_items = int(round(real_total_prog_items * 0.25))
required_prog_items = int(round(real_total_prog_items * percent))
for i in range(required_prog_items):
self.multiworld.state.collect(self.world.create_item("Stardrop"), prevent_sweep=False)
self.multiworld.worlds[self.player].total_progression_items = real_total_prog_items
Expand Down
26 changes: 26 additions & 0 deletions worlds/stardew_valley/test/rules/TestBooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from ... import options
from ...test import SVTestBase


class TestBooksLogic(SVTestBase):
options = {
options.Booksanity.internal_name: options.Booksanity.option_all,
}

def test_need_weapon_for_mapping_cave_systems(self):
self.collect_lots_of_money(0.5)

location = self.multiworld.get_location("Read Mapping Cave Systems", self.player)

self.assert_reach_location_false(location, self.multiworld.state)

self.collect("Progressive Mine Elevator")
self.collect("Progressive Mine Elevator")
self.collect("Progressive Mine Elevator")
self.collect("Progressive Mine Elevator")
self.assert_reach_location_false(location, self.multiworld.state)

self.collect("Progressive Weapon")
self.assert_reach_location_true(location, self.multiworld.state)


Loading