Stardew Valley: Fix a bug where locations in logic would disappear from universal tracker as items get sent (#4230)
Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
This commit is contained in:
parent
492e3a355e
commit
e262c8be9c
|
@ -3,7 +3,7 @@ from random import Random
|
|||
from typing import Dict, Any, Iterable, Optional, Union, List, TextIO
|
||||
|
||||
from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification, MultiWorld, CollectionState
|
||||
from Options import PerGameCommonOptions
|
||||
from Options import PerGameCommonOptions, Accessibility
|
||||
from worlds.AutoWorld import World, WebWorld
|
||||
from . import rules
|
||||
from .bundles.bundle_room import BundleRoom
|
||||
|
@ -91,15 +91,14 @@ class StardewValleyWorld(World):
|
|||
web = StardewWebWorld()
|
||||
modified_bundles: List[BundleRoom]
|
||||
randomized_entrances: Dict[str, str]
|
||||
total_progression_items: int
|
||||
|
||||
# all_progression_items: Dict[str, int] # If you need to debug total_progression_items, uncommenting this will help tremendously
|
||||
total_progression_items: int
|
||||
excluded_from_total_progression_items: List[str] = [Event.received_walnuts]
|
||||
|
||||
def __init__(self, multiworld: MultiWorld, player: int):
|
||||
super().__init__(multiworld, player)
|
||||
self.filler_item_pool_names = []
|
||||
self.total_progression_items = 0
|
||||
# self.all_progression_items = dict()
|
||||
|
||||
# Taking the seed specified in slot data for UT, otherwise just generating the seed.
|
||||
self.seed = getattr(multiworld, "re_gen_passthrough", {}).get(STARDEW_VALLEY, self.random.getrandbits(64))
|
||||
|
@ -121,17 +120,27 @@ class StardewValleyWorld(World):
|
|||
goal_is_perfection = self.options.goal == Goal.option_perfection
|
||||
goal_is_island_related = goal_is_walnut_hunter or goal_is_perfection
|
||||
exclude_ginger_island = self.options.exclude_ginger_island == ExcludeGingerIsland.option_true
|
||||
|
||||
if goal_is_island_related and exclude_ginger_island:
|
||||
self.options.exclude_ginger_island.value = ExcludeGingerIsland.option_false
|
||||
goal_name = self.options.goal.current_key
|
||||
player_name = self.multiworld.player_name[self.player]
|
||||
logger.warning(
|
||||
f"Goal '{goal_name}' requires Ginger Island. Exclude Ginger Island setting forced to 'False' for player {self.player} ({player_name})")
|
||||
f"Goal '{goal_name}' requires Ginger Island. Exclude Ginger Island setting forced to 'False' for player {self.player} ({self.player_name})")
|
||||
|
||||
if exclude_ginger_island and self.options.walnutsanity != Walnutsanity.preset_none:
|
||||
self.options.walnutsanity.value = Walnutsanity.preset_none
|
||||
player_name = self.multiworld.player_name[self.player]
|
||||
logger.warning(
|
||||
f"Walnutsanity requires Ginger Island. Ginger Island was excluded from {self.player} ({player_name})'s world, so walnutsanity was force disabled")
|
||||
f"Walnutsanity requires Ginger Island. Ginger Island was excluded from {self.player} ({self.player_name})'s world, so walnutsanity was force disabled")
|
||||
|
||||
if goal_is_perfection and self.options.accessibility == Accessibility.option_minimal:
|
||||
self.options.accessibility.value = Accessibility.option_full
|
||||
logger.warning(
|
||||
f"Goal 'Perfection' requires full accessibility. Accessibility setting forced to 'Full' for player {self.player} ({self.player_name})")
|
||||
|
||||
elif self.options.goal == Goal.option_allsanity and self.options.accessibility == Accessibility.option_minimal:
|
||||
self.options.accessibility.value = Accessibility.option_full
|
||||
logger.warning(
|
||||
f"Goal 'Allsanity' requires full accessibility. Accessibility setting forced to 'Full' for player {self.player} ({self.player_name})")
|
||||
|
||||
def create_regions(self):
|
||||
def create_region(name: str, exits: Iterable[str]) -> Region:
|
||||
|
@ -171,8 +180,7 @@ class StardewValleyWorld(World):
|
|||
for location in self.multiworld.get_locations(self.player)
|
||||
if location.address is not None])
|
||||
|
||||
created_items = create_items(self.create_item, self.delete_item, locations_count, items_to_exclude, self.options, self.content,
|
||||
self.random)
|
||||
created_items = create_items(self.create_item, locations_count, items_to_exclude, self.options, self.content, self.random)
|
||||
|
||||
self.multiworld.itempool += created_items
|
||||
|
||||
|
@ -180,6 +188,18 @@ class StardewValleyWorld(World):
|
|||
self.setup_player_events()
|
||||
self.setup_victory()
|
||||
|
||||
# This is really a best-effort to get the total progression items count. It is mostly used to spread grinds across spheres are push back locations that
|
||||
# only become available after months or years in game. In most cases, not having the exact count will not impact the logic.
|
||||
#
|
||||
# The actual total can be impacted by the start_inventory_from_pool, when items are removed from the pool but not from the total. The is also a bug
|
||||
# with plando where additional progression items can be created without being accounted for, which impact the real amount of progression items. This can
|
||||
# ultimately create unwinnable seeds where some items (like Blueberry seeds) are locked in Shipsanity: Blueberry, but world is deemed winnable as the
|
||||
# winning rule only check the count of collected progression items.
|
||||
self.total_progression_items += sum(1 for i in self.multiworld.precollected_items[self.player] if i.advancement)
|
||||
self.total_progression_items += sum(1 for i in self.multiworld.get_filled_locations(self.player) if i.advancement)
|
||||
self.total_progression_items += sum(1 for i in created_items if i.advancement)
|
||||
self.total_progression_items -= 1 # -1 for the victory event
|
||||
|
||||
def precollect_starting_season(self):
|
||||
if self.options.season_randomization == SeasonRandomization.option_progressive:
|
||||
return
|
||||
|
@ -304,14 +324,8 @@ class StardewValleyWorld(World):
|
|||
if override_classification is None:
|
||||
override_classification = item.classification
|
||||
|
||||
if override_classification & ItemClassification.progression:
|
||||
self.total_progression_items += 1
|
||||
return StardewItem(item.name, override_classification, item.code, self.player)
|
||||
|
||||
def delete_item(self, item: Item):
|
||||
if item.classification & ItemClassification.progression:
|
||||
self.total_progression_items -= 1
|
||||
|
||||
def create_starting_item(self, item: Union[str, ItemData]) -> StardewItem:
|
||||
if isinstance(item, str):
|
||||
item = item_table[item]
|
||||
|
@ -330,10 +344,6 @@ class StardewValleyWorld(World):
|
|||
region.locations.append(location)
|
||||
location.place_locked_item(StardewItem(item, ItemClassification.progression, None, self.player))
|
||||
|
||||
# This is not ideal, but the rule count them so...
|
||||
if item != Event.victory:
|
||||
self.total_progression_items += 1
|
||||
|
||||
def set_rules(self):
|
||||
set_rules(self)
|
||||
|
||||
|
@ -426,15 +436,25 @@ class StardewValleyWorld(World):
|
|||
|
||||
def collect(self, state: CollectionState, item: StardewItem) -> bool:
|
||||
change = super().collect(state, item)
|
||||
if change:
|
||||
state.prog_items[self.player][Event.received_walnuts] += self.get_walnut_amount(item.name)
|
||||
return change
|
||||
if not change:
|
||||
return False
|
||||
|
||||
walnut_amount = self.get_walnut_amount(item.name)
|
||||
if walnut_amount:
|
||||
state.prog_items[self.player][Event.received_walnuts] += walnut_amount
|
||||
|
||||
return True
|
||||
|
||||
def remove(self, state: CollectionState, item: StardewItem) -> bool:
|
||||
change = super().remove(state, item)
|
||||
if change:
|
||||
state.prog_items[self.player][Event.received_walnuts] -= self.get_walnut_amount(item.name)
|
||||
return change
|
||||
if not change:
|
||||
return False
|
||||
|
||||
walnut_amount = self.get_walnut_amount(item.name)
|
||||
if walnut_amount:
|
||||
state.prog_items[self.player][Event.received_walnuts] -= walnut_amount
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def get_walnut_amount(item_name: str) -> int:
|
||||
|
|
|
@ -169,14 +169,14 @@ def get_too_many_items_error_message(locations_count: int, items_count: int) ->
|
|||
return f"There should be at least as many locations [{locations_count}] as there are mandatory items [{items_count}]"
|
||||
|
||||
|
||||
def create_items(item_factory: StardewItemFactory, item_deleter: StardewItemDeleter, locations_count: int, items_to_exclude: List[Item],
|
||||
def create_items(item_factory: StardewItemFactory, locations_count: int, items_to_exclude: List[Item],
|
||||
options: StardewValleyOptions, content: StardewContent, random: Random) -> List[Item]:
|
||||
items = []
|
||||
unique_items = create_unique_items(item_factory, options, content, random)
|
||||
|
||||
remove_items(item_deleter, items_to_exclude, unique_items)
|
||||
remove_items(items_to_exclude, unique_items)
|
||||
|
||||
remove_items_if_no_room_for_them(item_deleter, unique_items, locations_count, random)
|
||||
remove_items_if_no_room_for_them(unique_items, locations_count, random)
|
||||
|
||||
items += unique_items
|
||||
logger.debug(f"Created {len(unique_items)} unique items")
|
||||
|
@ -192,14 +192,13 @@ def create_items(item_factory: StardewItemFactory, item_deleter: StardewItemDele
|
|||
return items
|
||||
|
||||
|
||||
def remove_items(item_deleter: StardewItemDeleter, items_to_remove, items):
|
||||
def remove_items(items_to_remove, items):
|
||||
for item in items_to_remove:
|
||||
if item in items:
|
||||
items.remove(item)
|
||||
item_deleter(item)
|
||||
|
||||
|
||||
def remove_items_if_no_room_for_them(item_deleter: StardewItemDeleter, unique_items: List[Item], locations_count: int, random: Random):
|
||||
def remove_items_if_no_room_for_them(unique_items: List[Item], locations_count: int, random: Random):
|
||||
if len(unique_items) <= locations_count:
|
||||
return
|
||||
|
||||
|
@ -212,7 +211,7 @@ def remove_items_if_no_room_for_them(item_deleter: StardewItemDeleter, unique_it
|
|||
logger.debug(f"Player has more items than locations, trying to remove {number_of_items_to_remove} random filler items")
|
||||
assert len(removable_items) >= number_of_items_to_remove, get_too_many_items_error_message(locations_count, len(unique_items))
|
||||
items_to_remove = random.sample(removable_items, number_of_items_to_remove)
|
||||
remove_items(item_deleter, items_to_remove, unique_items)
|
||||
remove_items(items_to_remove, unique_items)
|
||||
|
||||
|
||||
def create_unique_items(item_factory: StardewItemFactory, options: StardewValleyOptions, content: StardewContent, random: Random) -> List[Item]:
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import Iterable, Union, List, Tuple, Hashable
|
||||
from typing import Iterable, Union, List, Tuple, Hashable, TYPE_CHECKING
|
||||
|
||||
from BaseClasses import CollectionState
|
||||
from .base import BaseStardewRule, CombinableStardewRule
|
||||
from .protocol import StardewRule
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .. import StardewValleyWorld
|
||||
|
||||
|
||||
class TotalReceived(BaseStardewRule):
|
||||
count: int
|
||||
|
@ -102,16 +105,19 @@ class HasProgressionPercent(CombinableStardewRule):
|
|||
return self.percent
|
||||
|
||||
def __call__(self, state: CollectionState) -> bool:
|
||||
stardew_world = state.multiworld.worlds[self.player]
|
||||
stardew_world: "StardewValleyWorld" = state.multiworld.worlds[self.player]
|
||||
total_count = stardew_world.total_progression_items
|
||||
needed_count = (total_count * self.percent) // 100
|
||||
player_state = state.prog_items[self.player]
|
||||
|
||||
if needed_count <= len(player_state):
|
||||
if needed_count <= len(player_state) - len(stardew_world.excluded_from_total_progression_items):
|
||||
return True
|
||||
|
||||
total_count = 0
|
||||
for item, item_count in player_state.items():
|
||||
if item in stardew_world.excluded_from_total_progression_items:
|
||||
continue
|
||||
|
||||
total_count += item_count
|
||||
if total_count >= needed_count:
|
||||
return True
|
||||
|
|
|
@ -11,10 +11,10 @@ class TestCropsanityRules(SVTestBase):
|
|||
harvest_cactus = self.world.logic.region.can_reach_location("Harvest Cactus Fruit")
|
||||
self.assert_rule_false(harvest_cactus, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.world.create_item("Cactus Seeds"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.world.create_item("Shipping Bin"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.world.create_item("Desert Obelisk"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Cactus Seeds"))
|
||||
self.multiworld.state.collect(self.create_item("Shipping Bin"))
|
||||
self.multiworld.state.collect(self.create_item("Desert Obelisk"))
|
||||
self.assert_rule_false(harvest_cactus, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.world.create_item("Greenhouse"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Greenhouse"))
|
||||
self.assert_rule_true(harvest_cactus, self.multiworld.state)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import itertools
|
||||
|
||||
from Options import NamedRange
|
||||
from Options import NamedRange, Accessibility
|
||||
from . import SVTestCase, allsanity_no_mods_6_x_x, allsanity_mods_6_x_x, solo_multiworld
|
||||
from .assertion import WorldAssertMixin
|
||||
from .long.option_names import all_option_choices
|
||||
|
@ -54,6 +54,23 @@ class TestGoal(SVTestCase):
|
|||
victory = multi_world.find_item("Victory", 1)
|
||||
self.assertEqual(victory.name, location)
|
||||
|
||||
def test_given_perfection_goal_when_generate_then_accessibility_is_forced_to_full(self):
|
||||
"""There is a bug with the current victory condition of the perfection goal that can create unwinnable seeds if the accessibility is set to minimal and
|
||||
the world gets flooded with progression items through plando. This will increase the amount of collected progression items pass the total amount
|
||||
calculated for the world when creating the item pool. This will cause the victory condition to be met before all locations are collected, so some could
|
||||
be left inaccessible, which in practice will make the seed unwinnable.
|
||||
"""
|
||||
for accessibility in Accessibility.options.keys():
|
||||
world_options = {Goal.internal_name: Goal.option_perfection, "accessibility": accessibility}
|
||||
with self.solo_world_sub_test(f"Accessibility: {accessibility}", world_options) as (_, world):
|
||||
self.assertEqual(world.options.accessibility, Accessibility.option_full)
|
||||
|
||||
def test_given_allsanity_goal_when_generate_then_accessibility_is_forced_to_full(self):
|
||||
for accessibility in Accessibility.options.keys():
|
||||
world_options = {Goal.internal_name: Goal.option_allsanity, "accessibility": accessibility}
|
||||
with self.solo_world_sub_test(f"Accessibility: {accessibility}", world_options) as (_, world):
|
||||
self.assertEqual(world.options.accessibility, Accessibility.option_full)
|
||||
|
||||
|
||||
class TestSeasonRandomization(SVTestCase):
|
||||
def test_given_disabled_when_generate_then_all_seasons_are_precollected(self):
|
||||
|
|
|
@ -6,7 +6,7 @@ from argparse import Namespace
|
|||
from contextlib import contextmanager
|
||||
from typing import Dict, ClassVar, Iterable, Tuple, Optional, List, Union, Any
|
||||
|
||||
from BaseClasses import MultiWorld, CollectionState, PlandoOptions, get_seed, Location, Item, ItemClassification
|
||||
from BaseClasses import MultiWorld, CollectionState, PlandoOptions, get_seed, Location, Item
|
||||
from Options import VerifyKeys
|
||||
from test.bases import WorldTestBase
|
||||
from test.general import gen_steps, setup_solo_multiworld as setup_base_solo_multiworld
|
||||
|
@ -236,7 +236,6 @@ class SVTestBase(RuleAssertMixin, WorldTestBase, SVTestCase):
|
|||
|
||||
self.original_state = self.multiworld.state.copy()
|
||||
self.original_itempool = self.multiworld.itempool.copy()
|
||||
self.original_prog_item_count = world.total_progression_items
|
||||
self.unfilled_locations = self.multiworld.get_unfilled_locations(1)
|
||||
if self.constructed:
|
||||
self.world = world # noqa
|
||||
|
@ -246,7 +245,6 @@ class SVTestBase(RuleAssertMixin, WorldTestBase, SVTestCase):
|
|||
self.multiworld.itempool = self.original_itempool
|
||||
for location in self.unfilled_locations:
|
||||
location.item = None
|
||||
self.world.total_progression_items = self.original_prog_item_count
|
||||
|
||||
self.multiworld.lock.release()
|
||||
|
||||
|
@ -257,20 +255,13 @@ class SVTestBase(RuleAssertMixin, WorldTestBase, SVTestCase):
|
|||
return super().run_default_tests
|
||||
|
||||
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
|
||||
self.collect("Shipping Bin")
|
||||
real_total_prog_items = self.world.total_progression_items
|
||||
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
|
||||
self.collect("Stardrop", required_prog_items)
|
||||
|
||||
def collect_all_the_money(self):
|
||||
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.95))
|
||||
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
|
||||
self.collect_lots_of_money(0.95)
|
||||
|
||||
def collect_everything(self):
|
||||
non_event_items = [item for item in self.multiworld.get_items() if item.code]
|
||||
|
@ -278,7 +269,8 @@ class SVTestBase(RuleAssertMixin, WorldTestBase, SVTestCase):
|
|||
self.multiworld.state.collect(item)
|
||||
|
||||
def collect_all_except(self, item_to_not_collect: str):
|
||||
for item in self.multiworld.get_items():
|
||||
non_event_items = [item for item in self.multiworld.get_items() if item.code]
|
||||
for item in non_event_items:
|
||||
if item.name != item_to_not_collect:
|
||||
self.multiworld.state.collect(item)
|
||||
|
||||
|
@ -290,25 +282,26 @@ class SVTestBase(RuleAssertMixin, WorldTestBase, SVTestCase):
|
|||
|
||||
def collect(self, item: Union[str, Item, Iterable[Item]], count: int = 1) -> Union[None, Item, List[Item]]:
|
||||
assert count > 0
|
||||
|
||||
if not isinstance(item, str):
|
||||
super().collect(item)
|
||||
return
|
||||
|
||||
if count == 1:
|
||||
item = self.create_item(item)
|
||||
self.multiworld.state.collect(item)
|
||||
return item
|
||||
|
||||
items = []
|
||||
for i in range(count):
|
||||
item = self.create_item(item)
|
||||
self.multiworld.state.collect(item)
|
||||
items.append(item)
|
||||
|
||||
return items
|
||||
|
||||
def create_item(self, item: str) -> StardewItem:
|
||||
created_item = self.world.create_item(item)
|
||||
if created_item.classification & ItemClassification.progression:
|
||||
self.multiworld.worlds[self.player].total_progression_items -= 1
|
||||
return created_item
|
||||
return self.world.create_item(item)
|
||||
|
||||
def remove_one_by_name(self, item: str) -> None:
|
||||
self.remove(self.create_item(item))
|
||||
|
@ -336,7 +329,6 @@ def solo_multiworld(world_options: Optional[Dict[Union[str, StardewValleyOption]
|
|||
original_state = multiworld.state.copy()
|
||||
original_itempool = multiworld.itempool.copy()
|
||||
unfilled_locations = multiworld.get_unfilled_locations(1)
|
||||
original_prog_item_count = world.total_progression_items
|
||||
|
||||
yield multiworld, world
|
||||
|
||||
|
@ -344,7 +336,6 @@ def solo_multiworld(world_options: Optional[Dict[Union[str, StardewValleyOption]
|
|||
multiworld.itempool = original_itempool
|
||||
for location in unfilled_locations:
|
||||
location.item = None
|
||||
multiworld.total_progression_items = original_prog_item_count
|
||||
|
||||
multiworld.lock.release()
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ class TestArcadeMachinesLogic(SVTestBase):
|
|||
life = self.create_item("JotPK: Extra Life")
|
||||
drop = self.create_item("JotPK: Increased Drop Rate")
|
||||
|
||||
self.multiworld.state.collect(boots, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(boots)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 1")(self.multiworld.state))
|
||||
self.assertFalse(self.world.logic.region.can_reach("JotPK World 2")(self.multiworld.state))
|
||||
self.assertFalse(self.world.logic.region.can_reach("JotPK World 3")(self.multiworld.state))
|
||||
|
@ -28,8 +28,8 @@ class TestArcadeMachinesLogic(SVTestBase):
|
|||
self.remove(boots)
|
||||
self.remove(gun)
|
||||
|
||||
self.multiworld.state.collect(boots, prevent_sweep=True)
|
||||
self.multiworld.state.collect(boots, prevent_sweep=True)
|
||||
self.multiworld.state.collect(boots)
|
||||
self.multiworld.state.collect(boots)
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 1")(self.multiworld.state))
|
||||
self.assertFalse(self.world.logic.region.can_reach("JotPK World 2")(self.multiworld.state))
|
||||
self.assertFalse(self.world.logic.region.can_reach("JotPK World 3")(self.multiworld.state))
|
||||
|
@ -37,10 +37,10 @@ class TestArcadeMachinesLogic(SVTestBase):
|
|||
self.remove(boots)
|
||||
self.remove(boots)
|
||||
|
||||
self.multiworld.state.collect(boots, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(ammo, prevent_sweep=True)
|
||||
self.multiworld.state.collect(life, prevent_sweep=True)
|
||||
self.multiworld.state.collect(boots)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.multiworld.state.collect(ammo)
|
||||
self.multiworld.state.collect(life)
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 1")(self.multiworld.state))
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 2")(self.multiworld.state))
|
||||
self.assertFalse(self.world.logic.region.can_reach("JotPK World 3")(self.multiworld.state))
|
||||
|
@ -50,13 +50,13 @@ class TestArcadeMachinesLogic(SVTestBase):
|
|||
self.remove(ammo)
|
||||
self.remove(life)
|
||||
|
||||
self.multiworld.state.collect(boots, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(ammo, prevent_sweep=True)
|
||||
self.multiworld.state.collect(ammo, prevent_sweep=True)
|
||||
self.multiworld.state.collect(life, prevent_sweep=True)
|
||||
self.multiworld.state.collect(drop, prevent_sweep=True)
|
||||
self.multiworld.state.collect(boots)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.multiworld.state.collect(ammo)
|
||||
self.multiworld.state.collect(ammo)
|
||||
self.multiworld.state.collect(life)
|
||||
self.multiworld.state.collect(drop)
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 1")(self.multiworld.state))
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 2")(self.multiworld.state))
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 3")(self.multiworld.state))
|
||||
|
@ -69,17 +69,17 @@ class TestArcadeMachinesLogic(SVTestBase):
|
|||
self.remove(life)
|
||||
self.remove(drop)
|
||||
|
||||
self.multiworld.state.collect(boots, prevent_sweep=True)
|
||||
self.multiworld.state.collect(boots, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(gun, prevent_sweep=True)
|
||||
self.multiworld.state.collect(ammo, prevent_sweep=True)
|
||||
self.multiworld.state.collect(ammo, prevent_sweep=True)
|
||||
self.multiworld.state.collect(ammo, prevent_sweep=True)
|
||||
self.multiworld.state.collect(life, prevent_sweep=True)
|
||||
self.multiworld.state.collect(drop, prevent_sweep=True)
|
||||
self.multiworld.state.collect(boots)
|
||||
self.multiworld.state.collect(boots)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.multiworld.state.collect(gun)
|
||||
self.multiworld.state.collect(ammo)
|
||||
self.multiworld.state.collect(ammo)
|
||||
self.multiworld.state.collect(ammo)
|
||||
self.multiworld.state.collect(life)
|
||||
self.multiworld.state.collect(drop)
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 1")(self.multiworld.state))
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 2")(self.multiworld.state))
|
||||
self.assertTrue(self.world.logic.region.can_reach("JotPK World 3")(self.multiworld.state))
|
||||
|
|
|
@ -23,7 +23,7 @@ class TestBuildingLogic(SVTestBase):
|
|||
self.assertFalse(big_coop_blueprint_rule(self.multiworld.state),
|
||||
f"Rule is {repr(self.multiworld.get_location('Big Coop Blueprint', self.player).access_rule)}")
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Progressive Coop"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Coop"))
|
||||
self.assertTrue(big_coop_blueprint_rule(self.multiworld.state),
|
||||
f"Rule is {repr(self.multiworld.get_location('Big Coop Blueprint', self.player).access_rule)}")
|
||||
|
||||
|
@ -33,10 +33,10 @@ class TestBuildingLogic(SVTestBase):
|
|||
self.collect_lots_of_money()
|
||||
self.assertFalse(self.world.logic.region.can_reach_location("Deluxe Coop Blueprint")(self.multiworld.state))
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Progressive Coop"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Coop"))
|
||||
self.assertFalse(self.world.logic.region.can_reach_location("Deluxe Coop Blueprint")(self.multiworld.state))
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Progressive Coop"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Coop"))
|
||||
self.assertTrue(self.world.logic.region.can_reach_location("Deluxe Coop Blueprint")(self.multiworld.state))
|
||||
|
||||
def test_big_shed_blueprint(self):
|
||||
|
@ -48,6 +48,6 @@ class TestBuildingLogic(SVTestBase):
|
|||
self.assertFalse(big_shed_rule(self.multiworld.state),
|
||||
f"Rule is {repr(self.multiworld.get_location('Big Shed Blueprint', self.player).access_rule)}")
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Progressive Shed"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Shed"))
|
||||
self.assertTrue(big_shed_rule(self.multiworld.state),
|
||||
f"Rule is {repr(self.multiworld.get_location('Big Shed Blueprint', self.player).access_rule)}")
|
||||
|
|
|
@ -17,14 +17,14 @@ class TestRecipeLearnLogic(SVTestBase):
|
|||
rule = self.world.logic.region.can_reach_location(location)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Radish Seeds"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Spring"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Summer"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"))
|
||||
self.multiworld.state.collect(self.create_item("Radish Seeds"))
|
||||
self.multiworld.state.collect(self.create_item("Spring"))
|
||||
self.multiworld.state.collect(self.create_item("Summer"))
|
||||
self.collect_lots_of_money()
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("The Queen of Sauce"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("The Queen of Sauce"))
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
||||
|
||||
|
@ -42,21 +42,21 @@ class TestRecipeReceiveLogic(SVTestBase):
|
|||
rule = self.world.logic.region.can_reach_location(location)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Radish Seeds"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Summer"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"))
|
||||
self.multiworld.state.collect(self.create_item("Radish Seeds"))
|
||||
self.multiworld.state.collect(self.create_item("Summer"))
|
||||
self.collect_lots_of_money()
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
spring = self.create_item("Spring")
|
||||
qos = self.create_item("The Queen of Sauce")
|
||||
self.multiworld.state.collect(spring, prevent_sweep=False)
|
||||
self.multiworld.state.collect(qos, prevent_sweep=False)
|
||||
self.multiworld.state.collect(spring)
|
||||
self.multiworld.state.collect(qos)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
self.multiworld.state.remove(spring)
|
||||
self.multiworld.state.remove(qos)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Radish Salad Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Radish Salad Recipe"))
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
||||
def test_get_chefsanity_check_recipe(self):
|
||||
|
@ -64,20 +64,20 @@ class TestRecipeReceiveLogic(SVTestBase):
|
|||
rule = self.world.logic.region.can_reach_location(location)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Spring"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Spring"))
|
||||
self.collect_lots_of_money()
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
seeds = self.create_item("Radish Seeds")
|
||||
summer = self.create_item("Summer")
|
||||
house = self.create_item("Progressive House")
|
||||
self.multiworld.state.collect(seeds, prevent_sweep=False)
|
||||
self.multiworld.state.collect(summer, prevent_sweep=False)
|
||||
self.multiworld.state.collect(house, prevent_sweep=False)
|
||||
self.multiworld.state.collect(seeds)
|
||||
self.multiworld.state.collect(summer)
|
||||
self.multiworld.state.collect(house)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
self.multiworld.state.remove(seeds)
|
||||
self.multiworld.state.remove(summer)
|
||||
self.multiworld.state.remove(house)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("The Queen of Sauce"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("The Queen of Sauce"))
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
|
|
@ -25,7 +25,7 @@ class TestCraftsanityLogic(SVTestBase):
|
|||
self.collect_all_the_money()
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Marble Brazier Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Marble Brazier Recipe"))
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
||||
def test_can_learn_crafting_recipe(self):
|
||||
|
@ -38,16 +38,16 @@ class TestCraftsanityLogic(SVTestBase):
|
|||
|
||||
def test_can_craft_festival_recipe(self):
|
||||
recipe = all_crafting_recipes_by_name["Jack-O-Lantern"]
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Torch Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"))
|
||||
self.multiworld.state.collect(self.create_item("Torch Recipe"))
|
||||
self.collect_lots_of_money()
|
||||
rule = self.world.logic.crafting.can_craft(recipe)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Fall"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Fall"))
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Jack-O-Lantern Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Jack-O-Lantern Recipe"))
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
||||
def test_require_furnace_recipe_for_smelting_checks(self):
|
||||
|
@ -64,7 +64,7 @@ class TestCraftsanityLogic(SVTestBase):
|
|||
self.collect_all_the_money()
|
||||
self.assert_rules_false(rules, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Furnace Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Furnace Recipe"))
|
||||
self.assert_rules_true(rules, self.multiworld.state)
|
||||
|
||||
|
||||
|
@ -79,16 +79,16 @@ class TestCraftsanityWithFestivalsLogic(SVTestBase):
|
|||
|
||||
def test_can_craft_festival_recipe(self):
|
||||
recipe = all_crafting_recipes_by_name["Jack-O-Lantern"]
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Fall"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"))
|
||||
self.multiworld.state.collect(self.create_item("Fall"))
|
||||
self.collect_lots_of_money()
|
||||
rule = self.world.logic.crafting.can_craft(recipe)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Jack-O-Lantern Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Jack-O-Lantern Recipe"))
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Torch Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Torch Recipe"))
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
||||
|
||||
|
@ -109,7 +109,7 @@ class TestNoCraftsanityLogic(SVTestBase):
|
|||
|
||||
def test_can_craft_festival_recipe(self):
|
||||
recipe = all_crafting_recipes_by_name["Jack-O-Lantern"]
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"))
|
||||
self.collect_lots_of_money()
|
||||
rule = self.world.logic.crafting.can_craft(recipe)
|
||||
result = rule(self.multiworld.state)
|
||||
|
@ -126,7 +126,7 @@ class TestNoCraftsanityLogic(SVTestBase):
|
|||
self.collect([self.create_item("Progressive Sword")] * 4)
|
||||
self.collect([self.create_item("Progressive Mine Elevator")] * 24)
|
||||
self.collect([self.create_item("Progressive Trash Can")] * 2)
|
||||
self.multiworld.state.collect(self.create_item("Furnace Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Furnace Recipe"))
|
||||
self.collect([self.create_item("Combat Level")] * 10)
|
||||
self.collect([self.create_item("Fishing Level")] * 10)
|
||||
self.collect_all_the_money()
|
||||
|
@ -147,11 +147,11 @@ class TestNoCraftsanityWithFestivalsLogic(SVTestBase):
|
|||
|
||||
def test_can_craft_festival_recipe(self):
|
||||
recipe = all_crafting_recipes_by_name["Jack-O-Lantern"]
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Fall"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Pumpkin Seeds"))
|
||||
self.multiworld.state.collect(self.create_item("Fall"))
|
||||
self.collect_lots_of_money()
|
||||
rule = self.world.logic.crafting.can_craft(recipe)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Jack-O-Lantern Recipe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Jack-O-Lantern Recipe"))
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
|
|
@ -18,7 +18,7 @@ class TestDonationLogicAll(SVTestBase):
|
|||
for donation in locations_by_tag[LocationTags.MUSEUM_DONATIONS]:
|
||||
self.assertFalse(self.world.logic.region.can_reach_location(donation.name)(self.multiworld.state))
|
||||
|
||||
self.multiworld.state.collect(self.create_item(railroad_item), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(railroad_item))
|
||||
|
||||
for donation in locations_by_tag[LocationTags.MUSEUM_DONATIONS]:
|
||||
self.assertTrue(self.world.logic.region.can_reach_location(donation.name)(self.multiworld.state))
|
||||
|
@ -39,7 +39,7 @@ class TestDonationLogicRandomized(SVTestBase):
|
|||
for donation in donation_locations:
|
||||
self.assertFalse(self.world.logic.region.can_reach_location(donation.name)(self.multiworld.state))
|
||||
|
||||
self.multiworld.state.collect(self.create_item(railroad_item), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(railroad_item))
|
||||
|
||||
for donation in donation_locations:
|
||||
self.assertTrue(self.world.logic.region.can_reach_location(donation.name)(self.multiworld.state))
|
||||
|
@ -58,7 +58,7 @@ class TestDonationLogicMilestones(SVTestBase):
|
|||
for donation in locations_by_tag[LocationTags.MUSEUM_MILESTONES]:
|
||||
self.assertFalse(self.world.logic.region.can_reach_location(donation.name)(self.multiworld.state))
|
||||
|
||||
self.multiworld.state.collect(self.create_item(railroad_item), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(railroad_item))
|
||||
|
||||
for donation in locations_by_tag[LocationTags.MUSEUM_MILESTONES]:
|
||||
self.assertTrue(self.world.logic.region.can_reach_location(donation.name)(self.multiworld.state))
|
||||
|
|
|
@ -11,34 +11,34 @@ class TestFriendsanityDatingRules(SVTestBase):
|
|||
|
||||
def test_earning_dating_heart_requires_dating(self):
|
||||
self.collect_all_the_money()
|
||||
self.multiworld.state.collect(self.create_item("Fall"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Beach Bridge"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Fall"))
|
||||
self.multiworld.state.collect(self.create_item("Beach Bridge"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"))
|
||||
for i in range(3):
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Weapon"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Axe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Barn"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Weapon"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Axe"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Barn"))
|
||||
for i in range(10):
|
||||
self.multiworld.state.collect(self.create_item("Foraging Level"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Farming Level"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Mining Level"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Combat Level"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Mine Elevator"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Mine Elevator"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Foraging Level"))
|
||||
self.multiworld.state.collect(self.create_item("Farming Level"))
|
||||
self.multiworld.state.collect(self.create_item("Mining Level"))
|
||||
self.multiworld.state.collect(self.create_item("Combat Level"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Mine Elevator"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Mine Elevator"))
|
||||
|
||||
npc = "Abigail"
|
||||
heart_name = f"{npc} <3"
|
||||
step = 3
|
||||
|
||||
self.assert_can_reach_heart_up_to(npc, 3, step)
|
||||
self.multiworld.state.collect(self.create_item(heart_name), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(heart_name))
|
||||
self.assert_can_reach_heart_up_to(npc, 6, step)
|
||||
self.multiworld.state.collect(self.create_item(heart_name), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(heart_name))
|
||||
self.assert_can_reach_heart_up_to(npc, 8, step)
|
||||
self.multiworld.state.collect(self.create_item(heart_name), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(heart_name))
|
||||
self.assert_can_reach_heart_up_to(npc, 10, step)
|
||||
self.multiworld.state.collect(self.create_item(heart_name), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(heart_name))
|
||||
self.assert_can_reach_heart_up_to(npc, 14, step)
|
||||
|
||||
def assert_can_reach_heart_up_to(self, npc: str, max_reachable: int, step: int):
|
||||
|
|
|
@ -76,7 +76,7 @@ class TestShipsanityEverything(SVTestBase):
|
|||
with self.subTest(location.name):
|
||||
self.remove(bin_item)
|
||||
self.assertFalse(self.world.logic.region.can_reach_location(location.name)(self.multiworld.state))
|
||||
self.multiworld.state.collect(bin_item, prevent_sweep=False)
|
||||
self.multiworld.state.collect(bin_item)
|
||||
shipsanity_rule = self.world.logic.region.can_reach_location(location.name)
|
||||
self.assert_rule_true(shipsanity_rule, self.multiworld.state)
|
||||
self.remove(bin_item)
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
import unittest
|
||||
|
||||
from BaseClasses import ItemClassification
|
||||
from ...test import solo_multiworld
|
||||
from .. import SVTestBase, allsanity_mods_6_x_x
|
||||
from ...stardew_rule import HasProgressionPercent
|
||||
|
||||
|
||||
class TestHasProgressionPercent(unittest.TestCase):
|
||||
def test_max_item_amount_is_full_collection(self):
|
||||
# Not caching because it fails too often for some reason
|
||||
with solo_multiworld(world_caching=False) as (multiworld, world):
|
||||
progression_item_count = sum(1 for i in multiworld.get_items() if i.classification & ItemClassification.progression)
|
||||
self.assertEqual(world.total_progression_items, progression_item_count - 1) # -1 to skip Victory
|
||||
class TestHasProgressionPercentWithVictory(SVTestBase):
|
||||
options = allsanity_mods_6_x_x()
|
||||
|
||||
def test_has_100_progression_percent_is_false_while_items_are_missing(self):
|
||||
has_100_progression_percent = HasProgressionPercent(1, 100)
|
||||
|
||||
for i, item in enumerate([i for i in self.multiworld.get_items() if i.advancement and i.code][1:]):
|
||||
if item.name != "Victory":
|
||||
self.collect(item)
|
||||
self.assertFalse(has_100_progression_percent(self.multiworld.state),
|
||||
f"Rule became true after {i} items, total_progression_items is {self.world.total_progression_items}")
|
||||
|
||||
def test_has_100_progression_percent_account_for_victory_not_being_collected(self):
|
||||
has_100_progression_percent = HasProgressionPercent(1, 100)
|
||||
|
||||
self.collect_all_except("Victory")
|
||||
|
||||
self.assert_rule_true(has_100_progression_percent, self.multiworld.state)
|
||||
|
|
|
@ -21,30 +21,30 @@ class TestProgressiveToolsLogic(SVTestBase):
|
|||
self.assert_rule_false(sturgeon_rule, self.multiworld.state)
|
||||
|
||||
summer = self.create_item("Summer")
|
||||
self.multiworld.state.collect(summer, prevent_sweep=False)
|
||||
self.multiworld.state.collect(summer)
|
||||
self.assert_rule_false(sturgeon_rule, self.multiworld.state)
|
||||
|
||||
fishing_rod = self.create_item("Progressive Fishing Rod")
|
||||
self.multiworld.state.collect(fishing_rod, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_rod, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_rod)
|
||||
self.multiworld.state.collect(fishing_rod)
|
||||
self.assert_rule_false(sturgeon_rule, self.multiworld.state)
|
||||
|
||||
fishing_level = self.create_item("Fishing Level")
|
||||
self.multiworld.state.collect(fishing_level, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_level)
|
||||
self.assert_rule_false(sturgeon_rule, self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(fishing_level, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_level, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_level, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_level, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_level, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fishing_level)
|
||||
self.multiworld.state.collect(fishing_level)
|
||||
self.multiworld.state.collect(fishing_level)
|
||||
self.multiworld.state.collect(fishing_level)
|
||||
self.multiworld.state.collect(fishing_level)
|
||||
self.assert_rule_true(sturgeon_rule, self.multiworld.state)
|
||||
|
||||
self.remove(summer)
|
||||
self.assert_rule_false(sturgeon_rule, self.multiworld.state)
|
||||
|
||||
winter = self.create_item("Winter")
|
||||
self.multiworld.state.collect(winter, prevent_sweep=False)
|
||||
self.multiworld.state.collect(winter)
|
||||
self.assert_rule_true(sturgeon_rule, self.multiworld.state)
|
||||
|
||||
self.remove(fishing_rod)
|
||||
|
@ -53,24 +53,24 @@ class TestProgressiveToolsLogic(SVTestBase):
|
|||
def test_old_master_cannoli(self):
|
||||
self.multiworld.state.prog_items = {1: Counter()}
|
||||
|
||||
self.multiworld.state.collect(self.create_item("Progressive Axe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Axe"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Summer"), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Axe"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Axe"))
|
||||
self.multiworld.state.collect(self.create_item("Summer"))
|
||||
self.collect_lots_of_money()
|
||||
|
||||
rule = self.world.logic.region.can_reach_location("Old Master Cannoli")
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
fall = self.create_item("Fall")
|
||||
self.multiworld.state.collect(fall, prevent_sweep=False)
|
||||
self.multiworld.state.collect(fall)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
tuesday = self.create_item("Traveling Merchant: Tuesday")
|
||||
self.multiworld.state.collect(tuesday, prevent_sweep=False)
|
||||
self.multiworld.state.collect(tuesday)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
rare_seed = self.create_item("Rare Seed")
|
||||
self.multiworld.state.collect(rare_seed, prevent_sweep=False)
|
||||
self.multiworld.state.collect(rare_seed)
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
||||
self.remove(fall)
|
||||
|
@ -80,11 +80,11 @@ class TestProgressiveToolsLogic(SVTestBase):
|
|||
|
||||
green_house = self.create_item("Greenhouse")
|
||||
self.collect(self.create_item(Event.fall_farming))
|
||||
self.multiworld.state.collect(green_house, prevent_sweep=False)
|
||||
self.multiworld.state.collect(green_house)
|
||||
self.assert_rule_false(rule, self.multiworld.state)
|
||||
|
||||
friday = self.create_item("Traveling Merchant: Friday")
|
||||
self.multiworld.state.collect(friday, prevent_sweep=False)
|
||||
self.multiworld.state.collect(friday)
|
||||
self.assertTrue(self.multiworld.get_location("Old Master Cannoli", 1).access_rule(self.multiworld.state))
|
||||
|
||||
self.remove(green_house)
|
||||
|
@ -111,7 +111,7 @@ class TestToolVanillaRequiresBlacksmith(SVTestBase):
|
|||
for material in [ToolMaterial.copper, ToolMaterial.iron, ToolMaterial.gold, ToolMaterial.iridium]:
|
||||
self.assert_rule_false(self.world.logic.tool.has_tool(tool, material), self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item(railroad_item), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(railroad_item))
|
||||
|
||||
for tool in [Tool.pickaxe, Tool.axe, Tool.hoe, Tool.trash_can, Tool.watering_can]:
|
||||
for material in [ToolMaterial.copper, ToolMaterial.iron, ToolMaterial.gold, ToolMaterial.iridium]:
|
||||
|
@ -125,7 +125,7 @@ class TestToolVanillaRequiresBlacksmith(SVTestBase):
|
|||
for fishing_rod_level in [3, 4]:
|
||||
self.assert_rule_false(self.world.logic.tool.has_fishing_rod(fishing_rod_level), self.multiworld.state)
|
||||
|
||||
self.multiworld.state.collect(self.create_item(railroad_item), prevent_sweep=False)
|
||||
self.multiworld.state.collect(self.create_item(railroad_item))
|
||||
|
||||
for fishing_rod_level in [3, 4]:
|
||||
self.assert_rule_true(self.world.logic.tool.has_fishing_rod(fishing_rod_level), self.multiworld.state)
|
||||
|
|
|
@ -10,40 +10,40 @@ class TestWeaponsLogic(SVTestBase):
|
|||
}
|
||||
|
||||
def test_mine(self):
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive Pickaxe"))
|
||||
self.multiworld.state.collect(self.create_item("Progressive House"))
|
||||
self.collect([self.create_item("Combat Level")] * 10)
|
||||
self.collect([self.create_item("Mining Level")] * 10)
|
||||
self.collect([self.create_item("Progressive Mine Elevator")] * 24)
|
||||
self.multiworld.state.collect(self.create_item("Bus Repair"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Skull Key"), prevent_sweep=True)
|
||||
self.multiworld.state.collect(self.create_item("Bus Repair"))
|
||||
self.multiworld.state.collect(self.create_item("Skull Key"))
|
||||
|
||||
self.GiveItemAndCheckReachableMine("Progressive Sword", 1)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Dagger", 1)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Club", 1)
|
||||
self.give_item_and_check_reachable_mine("Progressive Sword", 1)
|
||||
self.give_item_and_check_reachable_mine("Progressive Dagger", 1)
|
||||
self.give_item_and_check_reachable_mine("Progressive Club", 1)
|
||||
|
||||
self.GiveItemAndCheckReachableMine("Progressive Sword", 2)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Dagger", 2)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Club", 2)
|
||||
self.give_item_and_check_reachable_mine("Progressive Sword", 2)
|
||||
self.give_item_and_check_reachable_mine("Progressive Dagger", 2)
|
||||
self.give_item_and_check_reachable_mine("Progressive Club", 2)
|
||||
|
||||
self.GiveItemAndCheckReachableMine("Progressive Sword", 3)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Dagger", 3)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Club", 3)
|
||||
self.give_item_and_check_reachable_mine("Progressive Sword", 3)
|
||||
self.give_item_and_check_reachable_mine("Progressive Dagger", 3)
|
||||
self.give_item_and_check_reachable_mine("Progressive Club", 3)
|
||||
|
||||
self.GiveItemAndCheckReachableMine("Progressive Sword", 4)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Dagger", 4)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Club", 4)
|
||||
self.give_item_and_check_reachable_mine("Progressive Sword", 4)
|
||||
self.give_item_and_check_reachable_mine("Progressive Dagger", 4)
|
||||
self.give_item_and_check_reachable_mine("Progressive Club", 4)
|
||||
|
||||
self.GiveItemAndCheckReachableMine("Progressive Sword", 5)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Dagger", 5)
|
||||
self.GiveItemAndCheckReachableMine("Progressive Club", 5)
|
||||
self.give_item_and_check_reachable_mine("Progressive Sword", 5)
|
||||
self.give_item_and_check_reachable_mine("Progressive Dagger", 5)
|
||||
self.give_item_and_check_reachable_mine("Progressive Club", 5)
|
||||
|
||||
def GiveItemAndCheckReachableMine(self, item_name: str, reachable_level: int):
|
||||
def give_item_and_check_reachable_mine(self, item_name: str, reachable_level: int):
|
||||
item = self.multiworld.create_item(item_name, self.player)
|
||||
self.multiworld.state.collect(item, prevent_sweep=True)
|
||||
self.multiworld.state.collect(item)
|
||||
rule = self.world.logic.mine.can_mine_in_the_mines_floor_1_40()
|
||||
if reachable_level > 0:
|
||||
self.assert_rule_true(rule, self.multiworld.state)
|
||||
|
|
|
@ -7,9 +7,6 @@ import unittest
|
|||
from BaseClasses import get_seed
|
||||
from .. import SVTestCase
|
||||
|
||||
# There seems to be 4 bytes that appear at random at the end of the output, breaking the json... I don't know where they came from.
|
||||
BYTES_TO_REMOVE = 4
|
||||
|
||||
# <function Location.<lambda> at 0x102ca98a0>
|
||||
lambda_regex = re.compile(r"^<function Location\.<lambda> at (.*)>$")
|
||||
|
||||
|
@ -27,8 +24,8 @@ class TestGenerationIsStable(SVTestCase):
|
|||
output_a = subprocess.check_output([sys.executable, '-m', 'worlds.stardew_valley.test.stability.StabilityOutputScript', '--seed', str(seed)])
|
||||
output_b = subprocess.check_output([sys.executable, '-m', 'worlds.stardew_valley.test.stability.StabilityOutputScript', '--seed', str(seed)])
|
||||
|
||||
result_a = json.loads(output_a[:-BYTES_TO_REMOVE])
|
||||
result_b = json.loads(output_b[:-BYTES_TO_REMOVE])
|
||||
result_a = json.loads(output_a)
|
||||
result_b = json.loads(output_b)
|
||||
|
||||
for i, ((room_a, bundles_a), (room_b, bundles_b)) in enumerate(zip(result_a["bundles"].items(), result_b["bundles"].items())):
|
||||
self.assertEqual(room_a, room_b, f"Bundle rooms at index {i} is different between both executions. Seed={seed}")
|
||||
|
|
Loading…
Reference in New Issue