Stardew Valley: Added rules requiring museum access to make donations (#2107)
This commit is contained in:
		| @@ -43,8 +43,8 @@ class MuseumItem(GameItem): | |||||||
|  |  | ||||||
| unlikely = () | unlikely = () | ||||||
|  |  | ||||||
| all_artifact_items: List[MuseumItem] = [] | all_museum_artifacts: List[MuseumItem] = [] | ||||||
| all_mineral_items: List[MuseumItem] = [] | all_museum_minerals: List[MuseumItem] = [] | ||||||
|  |  | ||||||
| all_museum_items: List[MuseumItem] = [] | all_museum_items: List[MuseumItem] = [] | ||||||
|  |  | ||||||
| @@ -56,7 +56,7 @@ def create_artifact(name: str, | |||||||
|                     geodes: Union[str, Tuple[str, ...]] = (), |                     geodes: Union[str, Tuple[str, ...]] = (), | ||||||
|                     monsters: Union[str, Tuple[str, ...]] = ()) -> MuseumItem: |                     monsters: Union[str, Tuple[str, ...]] = ()) -> MuseumItem: | ||||||
|     artifact_item = MuseumItem.of(name, item_id, difficulty, locations, geodes, monsters) |     artifact_item = MuseumItem.of(name, item_id, difficulty, locations, geodes, monsters) | ||||||
|     all_artifact_items.append(artifact_item) |     all_museum_artifacts.append(artifact_item) | ||||||
|     all_museum_items.append(artifact_item) |     all_museum_items.append(artifact_item) | ||||||
|     return artifact_item |     return artifact_item | ||||||
|  |  | ||||||
| @@ -79,7 +79,7 @@ def create_mineral(name: str, | |||||||
|             difficulty += 31.0 / 2750.0 * 100 |             difficulty += 31.0 / 2750.0 * 100 | ||||||
|  |  | ||||||
|     mineral_item = MuseumItem.of(name, item_id, difficulty, locations, geodes, monsters) |     mineral_item = MuseumItem.of(name, item_id, difficulty, locations, geodes, monsters) | ||||||
|     all_mineral_items.append(mineral_item) |     all_museum_minerals.append(mineral_item) | ||||||
|     all_museum_items.append(mineral_item) |     all_museum_items.append(mineral_item) | ||||||
|     return mineral_item |     return mineral_item | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ from .data import all_fish, FishItem, all_purchasable_seeds, SeedItem, all_crops | |||||||
| from .data.bundle_data import BundleItem | from .data.bundle_data import BundleItem | ||||||
| from .data.crops_data import crops_by_name | from .data.crops_data import crops_by_name | ||||||
| from .data.fish_data import island_fish | from .data.fish_data import island_fish | ||||||
| from .data.museum_data import all_museum_items, MuseumItem, all_artifact_items, dwarf_scrolls | from .data.museum_data import all_museum_items, MuseumItem, all_museum_artifacts, dwarf_scrolls, all_museum_minerals | ||||||
| from .data.recipe_data import all_cooking_recipes, CookingRecipe, RecipeSource, FriendshipSource, QueenOfSauceSource, \ | from .data.recipe_data import all_cooking_recipes, CookingRecipe, RecipeSource, FriendshipSource, QueenOfSauceSource, \ | ||||||
|     StarterSource, ShopSource, SkillSource |     StarterSource, ShopSource, SkillSource | ||||||
| from .data.villagers_data import all_villagers_by_name, Villager | from .data.villagers_data import all_villagers_by_name, Villager | ||||||
| @@ -475,8 +475,8 @@ class StardewLogic: | |||||||
|             FestivalCheck.mermaid_pearl: self.has_season(Season.winter) & self.can_reach_region(Region.beach), |             FestivalCheck.mermaid_pearl: self.has_season(Season.winter) & self.can_reach_region(Region.beach), | ||||||
|             FestivalCheck.cone_hat: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(2500), |             FestivalCheck.cone_hat: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(2500), | ||||||
|             FestivalCheck.iridium_fireplace: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(15000), |             FestivalCheck.iridium_fireplace: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(15000), | ||||||
|             FestivalCheck.rarecrow_7: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(5000) & self.can_find_museum_artifacts(20), |             FestivalCheck.rarecrow_7: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(5000) & self.can_donate_museum_artifacts(20), | ||||||
|             FestivalCheck.rarecrow_8: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(5000) & self.can_find_museum_items(40), |             FestivalCheck.rarecrow_8: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(5000) & self.can_donate_museum_items(40), | ||||||
|             FestivalCheck.lupini_red_eagle: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(1200), |             FestivalCheck.lupini_red_eagle: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(1200), | ||||||
|             FestivalCheck.lupini_portrait_mermaid: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(1200), |             FestivalCheck.lupini_portrait_mermaid: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(1200), | ||||||
|             FestivalCheck.lupini_solar_kingdom: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(1200), |             FestivalCheck.lupini_solar_kingdom: self.has_season(Season.winter) & self.can_reach_region(Region.beach) & self.can_spend_money(1200), | ||||||
| @@ -1213,7 +1213,7 @@ class StardewLogic: | |||||||
|                                self.can_have_earned_total_money(1000000),  # 1 000 000g second point |                                self.can_have_earned_total_money(1000000),  # 1 000 000g second point | ||||||
|                                self.has_total_skill_level(30),  # Total Skills: 30 |                                self.has_total_skill_level(30),  # Total Skills: 30 | ||||||
|                                self.has_total_skill_level(50),  # Total Skills: 50 |                                self.has_total_skill_level(50),  # Total Skills: 50 | ||||||
|                                # Completing the museum not expected |                                self.can_complete_museum(),  # Completing the museum for a point | ||||||
|                                # Catching every fish not expected |                                # Catching every fish not expected | ||||||
|                                # Shipping every item not expected |                                # Shipping every item not expected | ||||||
|                                self.can_get_married() & self.has_house(2), |                                self.can_get_married() & self.has_house(2), | ||||||
| @@ -1224,7 +1224,7 @@ class StardewLogic: | |||||||
|                                self.can_complete_community_center(),  # CC Ceremony first point |                                self.can_complete_community_center(),  # CC Ceremony first point | ||||||
|                                self.can_complete_community_center(),  # CC Ceremony second point |                                self.can_complete_community_center(),  # CC Ceremony second point | ||||||
|                                self.received(Wallet.skull_key),  # Skull Key obtained |                                self.received(Wallet.skull_key),  # Skull Key obtained | ||||||
|                                self.has_rusty_key(),  # Rusty key not expected |                                self.has_rusty_key(),  # Rusty key obtained | ||||||
|                                ] |                                ] | ||||||
|         return Count(12, rules_worth_a_point) |         return Count(12, rules_worth_a_point) | ||||||
|  |  | ||||||
| @@ -1266,9 +1266,21 @@ class StardewLogic: | |||||||
|  |  | ||||||
|     def can_speak_dwarf(self) -> StardewRule: |     def can_speak_dwarf(self) -> StardewRule: | ||||||
|         if self.options[options.Museumsanity] == options.Museumsanity.option_none: |         if self.options[options.Museumsanity] == options.Museumsanity.option_none: | ||||||
|             return self.has([item.name for item in dwarf_scrolls]) |             return And([self.can_donate_museum_item(item) for item in dwarf_scrolls]) | ||||||
|         return self.received("Dwarvish Translation Guide") |         return self.received("Dwarvish Translation Guide") | ||||||
|  |  | ||||||
|  |     def can_donate_museum_item(self, item: MuseumItem) -> StardewRule: | ||||||
|  |         return self.can_reach_region(Region.museum) & self.can_find_museum_item(item) | ||||||
|  |  | ||||||
|  |     def can_donate_museum_items(self, number: int) -> StardewRule: | ||||||
|  |         return self.can_reach_region(Region.museum) & self.can_find_museum_items(number) | ||||||
|  |  | ||||||
|  |     def can_donate_museum_artifacts(self, number: int) -> StardewRule: | ||||||
|  |         return self.can_reach_region(Region.museum) & self.can_find_museum_artifacts(number) | ||||||
|  |  | ||||||
|  |     def can_donate_museum_minerals(self, number: int) -> StardewRule: | ||||||
|  |         return self.can_reach_region(Region.museum) & self.can_find_museum_minerals(number) | ||||||
|  |  | ||||||
|     def can_find_museum_item(self, item: MuseumItem) -> StardewRule: |     def can_find_museum_item(self, item: MuseumItem) -> StardewRule: | ||||||
|         region_rule = self.can_reach_all_regions_except_one(item.locations) |         region_rule = self.can_reach_all_regions_except_one(item.locations) | ||||||
|         geodes_rule = And([self.can_open_geode(geode) for geode in item.geodes]) |         geodes_rule = And([self.can_open_geode(geode) for geode in item.geodes]) | ||||||
| @@ -1281,9 +1293,15 @@ class StardewLogic: | |||||||
|  |  | ||||||
|     def can_find_museum_artifacts(self, number: int) -> StardewRule: |     def can_find_museum_artifacts(self, number: int) -> StardewRule: | ||||||
|         rules = [] |         rules = [] | ||||||
|         for donation in all_museum_items: |         for artifact in all_museum_artifacts: | ||||||
|             if donation in all_artifact_items: |             rules.append(self.can_find_museum_item(artifact)) | ||||||
|                 rules.append(self.can_find_museum_item(donation)) |  | ||||||
|  |         return Count(number, rules) | ||||||
|  |  | ||||||
|  |     def can_find_museum_minerals(self, number: int) -> StardewRule: | ||||||
|  |         rules = [] | ||||||
|  |         for mineral in all_museum_minerals: | ||||||
|  |             rules.append(self.can_find_museum_item(mineral)) | ||||||
|  |  | ||||||
|         return Count(number, rules) |         return Count(number, rules) | ||||||
|  |  | ||||||
| @@ -1295,7 +1313,7 @@ class StardewLogic: | |||||||
|         return Count(number, rules) |         return Count(number, rules) | ||||||
|  |  | ||||||
|     def can_complete_museum(self) -> StardewRule: |     def can_complete_museum(self) -> StardewRule: | ||||||
|         rules = [self.can_mine_perfectly()] |         rules = [self.can_reach_region(Region.museum), self.can_mine_perfectly()] | ||||||
|  |  | ||||||
|         if self.options[options.Museumsanity] != options.Museumsanity.option_none: |         if self.options[options.Museumsanity] != options.Museumsanity.option_none: | ||||||
|             rules.append(self.received("Traveling Merchant Metal Detector", 4)) |             rules.append(self.received("Traveling Merchant Metal Detector", 4)) | ||||||
|   | |||||||
| @@ -5,15 +5,14 @@ from BaseClasses import MultiWorld | |||||||
| from worlds.generic import Rules as MultiWorldRules | from worlds.generic import Rules as MultiWorldRules | ||||||
| from . import options, locations | from . import options, locations | ||||||
| from .bundles import Bundle | from .bundles import Bundle | ||||||
| from .data.crops_data import crops_by_name |  | ||||||
| from .strings.entrance_names import dig_to_mines_floor, dig_to_skull_floor, Entrance, move_to_woods_depth, \ | from .strings.entrance_names import dig_to_mines_floor, dig_to_skull_floor, Entrance, move_to_woods_depth, \ | ||||||
|     DeepWoodsEntrance, AlecEntrance, MagicEntrance |     DeepWoodsEntrance, AlecEntrance, MagicEntrance | ||||||
| from .data.museum_data import all_museum_items, all_mineral_items, all_artifact_items, \ | from .data.museum_data import all_museum_items, all_museum_minerals, all_museum_artifacts, \ | ||||||
|     dwarf_scrolls, skeleton_front, \ |     dwarf_scrolls, skeleton_front, \ | ||||||
|     skeleton_middle, skeleton_back, all_museum_items_by_name |     skeleton_middle, skeleton_back, all_museum_items_by_name, Artifact | ||||||
| from .strings.region_names import Region | from .strings.region_names import Region | ||||||
| from .mods.mod_data import ModNames | from .mods.mod_data import ModNames | ||||||
| from .mods.logic import magic, skills, deepwoods | from .mods.logic import magic, deepwoods | ||||||
| from .locations import LocationTags | from .locations import LocationTags | ||||||
| from .logic import StardewLogic, And, tool_upgrade_prices | from .logic import StardewLogic, And, tool_upgrade_prices | ||||||
| from .options import StardewOptions | from .options import StardewOptions | ||||||
| @@ -23,7 +22,6 @@ from .strings.calendar_names import Weekday | |||||||
| from .strings.craftable_names import Craftable | from .strings.craftable_names import Craftable | ||||||
| from .strings.material_names import Material | from .strings.material_names import Material | ||||||
| from .strings.metal_names import MetalBar | from .strings.metal_names import MetalBar | ||||||
| from .strings.spells import MagicSpell |  | ||||||
| from .strings.skill_names import ModSkill, Skill | from .strings.skill_names import ModSkill, Skill | ||||||
| from .strings.tool_names import Tool, ToolMaterial | from .strings.tool_names import Tool, ToolMaterial | ||||||
| from .strings.villager_names import NPC, ModNPC | from .strings.villager_names import NPC, ModNPC | ||||||
| @@ -432,7 +430,7 @@ def set_museum_individual_donations_rules(all_location_names, logic: StardewLogi | |||||||
|         if museum_location.name in all_location_names: |         if museum_location.name in all_location_names: | ||||||
|             donation_name = museum_location.name[len(museum_prefix):] |             donation_name = museum_location.name[len(museum_prefix):] | ||||||
|             required_detectors = counter * 5 // number_donations |             required_detectors = counter * 5 // number_donations | ||||||
|             rule = logic.has(donation_name) & logic.received("Traveling Merchant Metal Detector", required_detectors) |             rule = logic.can_donate_museum_item(all_museum_items_by_name[donation_name]) & logic.received("Traveling Merchant Metal Detector", required_detectors) | ||||||
|             MultiWorldRules.set_rule(multi_world.get_location(museum_location.name, player), |             MultiWorldRules.set_rule(multi_world.get_location(museum_location.name, player), | ||||||
|                                      rule.simplify()) |                                      rule.simplify()) | ||||||
|         counter += 1 |         counter += 1 | ||||||
| @@ -447,31 +445,31 @@ def set_museum_milestone_rule(logic: StardewLogic, multi_world: MultiWorld, muse | |||||||
|     metal_detector = "Traveling Merchant Metal Detector" |     metal_detector = "Traveling Merchant Metal Detector" | ||||||
|     rule = None |     rule = None | ||||||
|     if milestone_name.endswith(donations_suffix): |     if milestone_name.endswith(donations_suffix): | ||||||
|         rule = get_museum_item_count_rule(logic, donations_suffix, milestone_name, all_museum_items) |         rule = get_museum_item_count_rule(logic, donations_suffix, milestone_name, all_museum_items, logic.can_donate_museum_items) | ||||||
|     elif milestone_name.endswith(minerals_suffix): |     elif milestone_name.endswith(minerals_suffix): | ||||||
|         rule = get_museum_item_count_rule(logic, minerals_suffix, milestone_name, all_mineral_items) |         rule = get_museum_item_count_rule(logic, minerals_suffix, milestone_name, all_museum_minerals, logic.can_donate_museum_minerals) | ||||||
|     elif milestone_name.endswith(artifacts_suffix): |     elif milestone_name.endswith(artifacts_suffix): | ||||||
|         rule = get_museum_item_count_rule(logic, artifacts_suffix, milestone_name, all_artifact_items) |         rule = get_museum_item_count_rule(logic, artifacts_suffix, milestone_name, all_museum_artifacts, logic.can_donate_museum_artifacts) | ||||||
|     elif milestone_name == "Dwarf Scrolls": |     elif milestone_name == "Dwarf Scrolls": | ||||||
|         rule = logic.has([item.name for item in dwarf_scrolls]) & logic.received(metal_detector, 4) |         rule = And([logic.can_donate_museum_item(item) for item in dwarf_scrolls]) & logic.received(metal_detector, 4) | ||||||
|     elif milestone_name == "Skeleton Front": |     elif milestone_name == "Skeleton Front": | ||||||
|         rule = logic.has([item.name for item in skeleton_front]) & logic.received(metal_detector, 4) |         rule = And([logic.can_donate_museum_item(item) for item in skeleton_front]) & logic.received(metal_detector, 4) | ||||||
|     elif milestone_name == "Skeleton Middle": |     elif milestone_name == "Skeleton Middle": | ||||||
|         rule = logic.has([item.name for item in skeleton_middle]) & logic.received(metal_detector, 4) |         rule = And([logic.can_donate_museum_item(item) for item in skeleton_middle]) & logic.received(metal_detector, 4) | ||||||
|     elif milestone_name == "Skeleton Back": |     elif milestone_name == "Skeleton Back": | ||||||
|         rule = logic.has([item.name for item in skeleton_back]) & logic.received(metal_detector, 4) |         rule = And([logic.can_donate_museum_item(item) for item in skeleton_back]) & logic.received(metal_detector, 4) | ||||||
|     elif milestone_name == "Ancient Seed": |     elif milestone_name == "Ancient Seed": | ||||||
|         rule = logic.has("Ancient Seed") & logic.received(metal_detector, 4) |         rule = logic.can_donate_museum_item(Artifact.ancient_seed) & logic.received(metal_detector, 4) | ||||||
|     if rule is None: |     if rule is None: | ||||||
|         return |         return | ||||||
|     MultiWorldRules.set_rule(multi_world.get_location(museum_milestone.name, player), rule.simplify()) |     MultiWorldRules.set_rule(multi_world.get_location(museum_milestone.name, player), rule.simplify()) | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_museum_item_count_rule(logic: StardewLogic, suffix, milestone_name, accepted_items): | def get_museum_item_count_rule(logic: StardewLogic, suffix, milestone_name, accepted_items, donation_func): | ||||||
|     metal_detector = "Traveling Merchant Metal Detector" |     metal_detector = "Traveling Merchant Metal Detector" | ||||||
|     num = int(milestone_name[:milestone_name.index(suffix)]) |     num = int(milestone_name[:milestone_name.index(suffix)]) | ||||||
|     required_detectors = (num - 1) * 5 // len(accepted_items) |     required_detectors = (num - 1) * 5 // len(accepted_items) | ||||||
|     rule = logic.has([item.name for item in accepted_items], num) & logic.received(metal_detector, required_detectors) |     rule = donation_func(num) & logic.received(metal_detector, required_detectors) | ||||||
|     return rule |     return rule | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,10 +2,12 @@ from collections import Counter | |||||||
|  |  | ||||||
| from . import SVTestBase | from . import SVTestBase | ||||||
| from .. import options | from .. import options | ||||||
|  | from ..locations import locations_by_tag, LocationTags, location_table | ||||||
| from ..strings.animal_names import Animal | from ..strings.animal_names import Animal | ||||||
| from ..strings.animal_product_names import AnimalProduct | from ..strings.animal_product_names import AnimalProduct | ||||||
| from ..strings.artisan_good_names import ArtisanGood | from ..strings.artisan_good_names import ArtisanGood | ||||||
| from ..strings.crop_names import Vegetable | from ..strings.crop_names import Vegetable | ||||||
|  | from ..strings.entrance_names import Entrance | ||||||
| from ..strings.food_names import Meal | from ..strings.food_names import Meal | ||||||
| from ..strings.ingredient_names import Ingredient | from ..strings.ingredient_names import Ingredient | ||||||
| from ..strings.machine_names import Machine | from ..strings.machine_names import Machine | ||||||
| @@ -369,3 +371,76 @@ class TestRecipeLogic(SVTestBase): | |||||||
|     #     self.assertTrue(logic.has(Machine.cheese_press)(self.multiworld.state)) |     #     self.assertTrue(logic.has(Machine.cheese_press)(self.multiworld.state)) | ||||||
|     #     self.assertTrue(logic.has(ArtisanGood.cheese)(self.multiworld.state)) |     #     self.assertTrue(logic.has(ArtisanGood.cheese)(self.multiworld.state)) | ||||||
|     #     self.assertTrue(logic.has(Meal.pizza)(self.multiworld.state)) |     #     self.assertTrue(logic.has(Meal.pizza)(self.multiworld.state)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestDonationLogicAll(SVTestBase): | ||||||
|  |     options = { | ||||||
|  |         options.Museumsanity.internal_name: options.Museumsanity.option_all | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     def test_cannot_make_any_donation_without_museum_access(self): | ||||||
|  |         guild_item = "Adventurer's Guild" | ||||||
|  |         swap_museum_and_guild(self.multiworld, self.player) | ||||||
|  |         collect_all_except(self.multiworld, guild_item) | ||||||
|  |  | ||||||
|  |         for donation in locations_by_tag[LocationTags.MUSEUM_DONATIONS]: | ||||||
|  |             self.assertFalse(self.world.logic.can_reach_location(donation.name)(self.multiworld.state)) | ||||||
|  |  | ||||||
|  |         self.multiworld.state.collect(self.world.create_item(guild_item), event=True) | ||||||
|  |  | ||||||
|  |         for donation in locations_by_tag[LocationTags.MUSEUM_DONATIONS]: | ||||||
|  |             self.assertTrue(self.world.logic.can_reach_location(donation.name)(self.multiworld.state)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestDonationLogicRandomized(SVTestBase): | ||||||
|  |     options = { | ||||||
|  |         options.Museumsanity.internal_name: options.Museumsanity.option_randomized | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     def test_cannot_make_any_donation_without_museum_access(self): | ||||||
|  |         guild_item = "Adventurer's Guild" | ||||||
|  |         swap_museum_and_guild(self.multiworld, self.player) | ||||||
|  |         collect_all_except(self.multiworld, guild_item) | ||||||
|  |         donation_locations = [location for location in self.multiworld.get_locations() if not location.event and LocationTags.MUSEUM_DONATIONS in location_table[location.name].tags] | ||||||
|  |  | ||||||
|  |         for donation in donation_locations: | ||||||
|  |             self.assertFalse(self.world.logic.can_reach_location(donation.name)(self.multiworld.state)) | ||||||
|  |  | ||||||
|  |         self.multiworld.state.collect(self.world.create_item(guild_item), event=True) | ||||||
|  |  | ||||||
|  |         for donation in donation_locations: | ||||||
|  |             self.assertTrue(self.world.logic.can_reach_location(donation.name)(self.multiworld.state)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestDonationLogicMilestones(SVTestBase): | ||||||
|  |     options = { | ||||||
|  |         options.Museumsanity.internal_name: options.Museumsanity.option_milestones | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     def test_cannot_make_any_donation_without_museum_access(self): | ||||||
|  |         guild_item = "Adventurer's Guild" | ||||||
|  |         swap_museum_and_guild(self.multiworld, self.player) | ||||||
|  |         collect_all_except(self.multiworld, guild_item) | ||||||
|  |  | ||||||
|  |         for donation in locations_by_tag[LocationTags.MUSEUM_MILESTONES]: | ||||||
|  |             self.assertFalse(self.world.logic.can_reach_location(donation.name)(self.multiworld.state)) | ||||||
|  |  | ||||||
|  |         self.multiworld.state.collect(self.world.create_item(guild_item), event=True) | ||||||
|  |  | ||||||
|  |         for donation in locations_by_tag[LocationTags.MUSEUM_MILESTONES]: | ||||||
|  |             self.assertTrue(self.world.logic.can_reach_location(donation.name)(self.multiworld.state)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def swap_museum_and_guild(multiworld, player): | ||||||
|  |     museum_region = multiworld.get_region(Region.museum, player) | ||||||
|  |     guild_region = multiworld.get_region(Region.adventurer_guild, player) | ||||||
|  |     museum_entrance = multiworld.get_entrance(Entrance.town_to_museum, player) | ||||||
|  |     guild_entrance = multiworld.get_entrance(Entrance.mountain_to_adventurer_guild, player) | ||||||
|  |     museum_entrance.connect(guild_region) | ||||||
|  |     guild_entrance.connect(museum_region) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def collect_all_except(multiworld, item_to_not_collect: str): | ||||||
|  |     for item in multiworld.get_items(): | ||||||
|  |         if item.name != item_to_not_collect: | ||||||
|  |             multiworld.state.collect(item) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 agilbert1412
					agilbert1412