From 1656e6cfd84e6141f242273bdb5e17ddd800151b Mon Sep 17 00:00:00 2001 From: Alex Gilbert <alexgilbert@yahoo.com> Date: Mon, 5 Aug 2024 16:40:01 -0400 Subject: [PATCH 1/6] - Created a test for the "Mapping Cave Systems" book --- worlds/stardew_valley/test/rules/TestBooks.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 worlds/stardew_valley/test/rules/TestBooks.py diff --git a/worlds/stardew_valley/test/rules/TestBooks.py b/worlds/stardew_valley/test/rules/TestBooks.py new file mode 100644 index 000000000000..41eb86b90f19 --- /dev/null +++ b/worlds/stardew_valley/test/rules/TestBooks.py @@ -0,0 +1,21 @@ +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_all_the_money() + + location = self.multiworld.get_location("Read Mapping Cave Systems", self.player) + + self.assert_reach_location_false(location, self.multiworld.state) + + self.collect("Progressive Weapon") + + self.assert_reach_location_true(location, self.multiworld.state) + + From 25a6754eca638bcd86a1584a1995fcddd54a7132 Mon Sep 17 00:00:00 2001 From: Alex Gilbert <alexgilbert@yahoo.com> Date: Mon, 5 Aug 2024 16:40:13 -0400 Subject: [PATCH 2/6] - Added missing rule to marlon's bedroom --- worlds/stardew_valley/rules.py | 1 + 1 file changed, 1 insertion(+) diff --git a/worlds/stardew_valley/rules.py b/worlds/stardew_valley/rules.py index 89b1cf87c3c1..dfe4bb3d1930 100644 --- a/worlds/stardew_valley/rules.py +++ b/worlds/stardew_valley/rules.py @@ -261,6 +261,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(Monster.green_slime)) def set_dangerous_mine_rules(logic, multiworld, player, world_options: StardewValleyOptions): From 6d9e86b2feede051895c3b678c94cd3f25f89e43 Mon Sep 17 00:00:00 2001 From: Alex Gilbert <alexgilbert@yahoo.com> Date: Mon, 5 Aug 2024 16:41:56 -0400 Subject: [PATCH 3/6] - Can kill any monster, not just green slime --- worlds/stardew_valley/rules.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worlds/stardew_valley/rules.py b/worlds/stardew_valley/rules.py index dfe4bb3d1930..2394fc76df1e 100644 --- a/worlds/stardew_valley/rules.py +++ b/worlds/stardew_valley/rules.py @@ -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 @@ -261,7 +262,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(Monster.green_slime)) + 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): From c1bcf263de8fa0e98a7f4a4f04658497a2448f56 Mon Sep 17 00:00:00 2001 From: Alex Gilbert <alexgilbert@yahoo.com> Date: Mon, 5 Aug 2024 16:44:30 -0400 Subject: [PATCH 4/6] - Added a compound source structure, but I ended up deciding to not use it here. Still keeping it as it will probably be useful eventually --- worlds/stardew_valley/data/game_item.py | 5 +++++ worlds/stardew_valley/logic/source_logic.py | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/worlds/stardew_valley/data/game_item.py b/worlds/stardew_valley/data/game_item.py index 2107ca30d33a..6c8d30ed8e6f 100644 --- a/worlds/stardew_valley/data/game_item.py +++ b/worlds/stardew_valley/data/game_item.py @@ -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, ...] diff --git a/worlds/stardew_valley/logic/source_logic.py b/worlds/stardew_valley/logic/source_logic.py index 0e9b8e976f5b..9ef68a020eef 100644 --- a/worlds/stardew_valley/logic/source_logic.py +++ b/worlds/stardew_valley/logic/source_logic.py @@ -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 @@ -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 = [] @@ -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.") @@ -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) From 3ae94355f6a0c9ac9db60d0f680276425d2aa9b0 Mon Sep 17 00:00:00 2001 From: Alex Gilbert <alexgilbert@yahoo.com> Date: Mon, 5 Aug 2024 17:06:39 -0400 Subject: [PATCH 5/6] - Use the compound source of the monster compoundium (ironic, I know) --- worlds/stardew_valley/content/vanilla/pelican_town.py | 8 +++++--- worlds/stardew_valley/test/__init__.py | 4 ++-- worlds/stardew_valley/test/rules/TestBooks.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/worlds/stardew_valley/content/vanilla/pelican_town.py b/worlds/stardew_valley/content/vanilla/pelican_town.py index 220b46eae2a4..73cc8f119a3e 100644 --- a/worlds/stardew_valley/content/vanilla/pelican_town.py +++ b/worlds/stardew_valley/content/vanilla/pelican_town.py @@ -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 @@ -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)), diff --git a/worlds/stardew_valley/test/__init__.py b/worlds/stardew_valley/test/__init__.py index 4dee0ebf6d66..74ade9696f7d 100644 --- a/worlds/stardew_valley/test/__init__.py +++ b/worlds/stardew_valley/test/__init__.py @@ -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 diff --git a/worlds/stardew_valley/test/rules/TestBooks.py b/worlds/stardew_valley/test/rules/TestBooks.py index 41eb86b90f19..c7872daec6c5 100644 --- a/worlds/stardew_valley/test/rules/TestBooks.py +++ b/worlds/stardew_valley/test/rules/TestBooks.py @@ -8,7 +8,7 @@ class TestBooksLogic(SVTestBase): } def test_need_weapon_for_mapping_cave_systems(self): - self.collect_all_the_money() + self.collect_lots_of_money(0.5) location = self.multiworld.get_location("Read Mapping Cave Systems", self.player) From abad4ba0304084774d20b71c122bfdfed5ad956f Mon Sep 17 00:00:00 2001 From: Alex Gilbert <alexgilbert@yahoo.com> Date: Mon, 5 Aug 2024 17:26:27 -0400 Subject: [PATCH 6/6] - Add required elevators --- worlds/stardew_valley/test/rules/TestBooks.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/worlds/stardew_valley/test/rules/TestBooks.py b/worlds/stardew_valley/test/rules/TestBooks.py index c7872daec6c5..6605e7e645e3 100644 --- a/worlds/stardew_valley/test/rules/TestBooks.py +++ b/worlds/stardew_valley/test/rules/TestBooks.py @@ -14,8 +14,13 @@ def test_need_weapon_for_mapping_cave_systems(self): self.assert_reach_location_false(location, self.multiworld.state) - self.collect("Progressive Weapon") + 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)