diff --git a/worlds/stardew_valley/options/forced_options.py b/worlds/stardew_valley/options/forced_options.py index 84cdc936b3f1..373a6d46db5c 100644 --- a/worlds/stardew_valley/options/forced_options.py +++ b/worlds/stardew_valley/options/forced_options.py @@ -9,6 +9,7 @@ def force_change_options_if_incompatible(world_options: options.StardewValleyOptions, player: int, player_name: str) -> None: force_ginger_island_inclusion_when_goal_is_ginger_island_related(world_options, player, player_name) force_walnutsanity_deactivation_when_ginger_island_is_excluded(world_options, player, player_name) + force_qi_special_orders_deactivation_when_ginger_island_is_excluded(world_options, player, player_name) force_accessibility_to_full_when_goal_requires_all_locations(player, player_name, world_options) @@ -35,6 +36,16 @@ def force_walnutsanity_deactivation_when_ginger_island_is_excluded(world_options f"Ginger Island was excluded from {player} ({player_name})'s world, so walnutsanity was force disabled") +def force_qi_special_orders_deactivation_when_ginger_island_is_excluded(world_options: options.StardewValleyOptions, player: int, player_name: str): + ginger_island_is_excluded = world_options.exclude_ginger_island == options.ExcludeGingerIsland.option_true + qi_board_is_active = options.SpecialOrderLocations.value_qi & world_options.special_order_locations.value == options.SpecialOrderLocations.value_qi + + if ginger_island_is_excluded and qi_board_is_active: + world_options.special_order_locations.value = world_options.special_order_locations.value ^ options.SpecialOrderLocations.value_qi + logger.warning(f"Mr. Qi's Special Orders requires Ginger Island. " + f"Ginger Island was excluded from {player} ({player_name})'s world, so Mr. Qi's Special Orders were force disabled") + + def force_accessibility_to_full_when_goal_requires_all_locations(player, player_name, world_options): goal_is_allsanity = world_options.goal == options.Goal.option_allsanity goal_is_perfection = world_options.goal == options.Goal.option_perfection diff --git a/worlds/stardew_valley/test/options/TestForcedOptions.py b/worlds/stardew_valley/test/options/TestForcedOptions.py index 4c8f0f42c389..c32def6c6ca8 100644 --- a/worlds/stardew_valley/test/options/TestForcedOptions.py +++ b/worlds/stardew_valley/test/options/TestForcedOptions.py @@ -82,3 +82,34 @@ def test_given_ginger_island_related_goal_and_ginger_island_excluded_when_genera force_change_options_if_incompatible(world_options, 1, "Tester") self.assertEqual(world_options.walnutsanity.value, original_walnutsanity_choice) + + +class TestGingerIslandExclusionOverridesQisSpecialOrders(unittest.TestCase): + + def test_given_ginger_island_excluded_when_generate_then_qis_special_orders_are_forced_disabled(self): + special_order_options = options.SpecialOrderLocations.options + for special_order in special_order_options.keys(): + with self.subTest(f"Special order: {special_order}"): + world_options = fill_dataclass_with_default({ + options.ExcludeGingerIsland: options.ExcludeGingerIsland.option_true, + options.SpecialOrderLocations: special_order + }) + + force_change_options_if_incompatible(world_options, 1, "Tester") + + self.assertEqual(world_options.special_order_locations.value & options.SpecialOrderLocations.value_qi, 0) + + def test_given_ginger_island_related_goal_and_ginger_island_excluded_when_generate_then_special_orders_is_not_changed(self): + for goal in [options.Goal.option_greatest_walnut_hunter, options.Goal.option_perfection]: + special_order_options = options.SpecialOrderLocations.options + for special_order, original_special_order_value in special_order_options.items(): + with self.subTest(f"Special order: {special_order}"): + world_options = fill_dataclass_with_default({ + options.Goal: goal, + options.ExcludeGingerIsland: options.ExcludeGingerIsland.option_true, + options.SpecialOrderLocations: special_order + }) + + force_change_options_if_incompatible(world_options, 1, "Tester") + + self.assertEqual(world_options.special_order_locations.value, original_special_order_value)