Skip to content

Commit

Permalink
Stardew Valley: Make sure number of month in time logic is a int to i…
Browse files Browse the repository at this point in the history
…mprove performance by ~20% (ArchipelagoMW#3665)

* make sure number of month is actually a int

* improve rule explain like in pr

* remove redundant if in can_complete_bundle

* assert number is int so cache is not bloated
  • Loading branch information
Jouramie authored Jul 20, 2024
1 parent e33a999 commit 34e7748
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 9 deletions.
6 changes: 3 additions & 3 deletions worlds/stardew_valley/logic/bundle_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ def __init__(self, *args, **kwargs):
self.bundle = BundleLogic(*args, **kwargs)


class BundleLogic(BaseLogic[Union[ReceivedLogicMixin, HasLogicMixin, TimeLogicMixin, RegionLogicMixin, MoneyLogicMixin, QualityLogicMixin, FishingLogicMixin, SkillLogicMixin,
QuestLogicMixin]]):
class BundleLogic(BaseLogic[Union[ReceivedLogicMixin, HasLogicMixin, TimeLogicMixin, RegionLogicMixin, MoneyLogicMixin, QualityLogicMixin, FishingLogicMixin,
SkillLogicMixin, QuestLogicMixin]]):
# Should be cached
def can_complete_bundle(self, bundle: Bundle) -> StardewRule:
item_rules = []
Expand All @@ -45,7 +45,7 @@ def can_complete_bundle(self, bundle: Bundle) -> StardewRule:
qualities.append(bundle_item.quality)
quality_rules = self.get_quality_rules(qualities)
item_rules = self.logic.has_n(*item_rules, count=bundle.number_required)
time_rule = True_() if time_to_grind <= 0 else self.logic.time.has_lived_months(time_to_grind)
time_rule = self.logic.time.has_lived_months(time_to_grind)
return can_speak_junimo & item_rules & quality_rules & time_rule

def get_quality_rules(self, qualities: List[str]) -> StardewRule:
Expand Down
2 changes: 1 addition & 1 deletion worlds/stardew_valley/logic/museum_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def can_find_museum_item(self, item: MuseumItem) -> StardewRule:
else:
geodes_rule = False_()
# monster_rule = self.can_farm_monster(item.monsters)
time_needed_to_grind = (20 - item.difficulty) / 2
time_needed_to_grind = int((20 - item.difficulty) // 2)
time_rule = self.logic.time.has_lived_months(time_needed_to_grind)
pan_rule = False_()
if item.item_name == Mineral.earth_crystal or item.item_name == Mineral.fire_quartz or item.item_name == Mineral.frozen_tear:
Expand Down
2 changes: 2 additions & 0 deletions worlds/stardew_valley/logic/time_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ class TimeLogic(BaseLogic[Union[TimeLogicMixin, HasLogicMixin]]):

@cache_self1
def has_lived_months(self, number: int) -> StardewRule:
assert isinstance(number, int), "Can't have lived a fraction of a month. Use // instead of / when dividing."
if number <= 0:
return self.logic.true_

number = min(number, MAX_MONTHS)
return HasProgressionPercent(self.player, number * MONTH_COEFFICIENT)

Expand Down
2 changes: 1 addition & 1 deletion worlds/stardew_valley/stardew_rule/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ def rules_count(self):
return len(self.rules)

def __repr__(self):
return f"Received {self.count} {repr(self.rules)}"
return f"Received {self.count} [{', '.join(f'{value}x {repr(rule)}' for rule, value in self.counter.items())}]"


@dataclass(frozen=True)
Expand Down
33 changes: 30 additions & 3 deletions worlds/stardew_valley/stardew_rule/rule_explain.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ def __str__(self, depth=0):
if not self.sub_rules:
return self.summary(depth)

return self.summary(depth) + "\n" + "\n".join(RuleExplanation.__str__(i, depth + 1)
return self.summary(depth) + "\n" + "\n".join(i.__str__(depth + 1)
if i.result is not self.expected else i.summary(depth + 1)
for i in sorted(self.explained_sub_rules, key=lambda x: x.result))

def __repr__(self, depth=0):
if not self.sub_rules:
return self.summary(depth)

return self.summary(depth) + "\n" + "\n".join(RuleExplanation.__repr__(i, depth + 1)
return self.summary(depth) + "\n" + "\n".join(i.__repr__(depth + 1)
for i in sorted(self.explained_sub_rules, key=lambda x: x.result))

@cached_property
Expand All @@ -61,6 +61,33 @@ def explained_sub_rules(self) -> List[RuleExplanation]:
return [_explain(i, self.state, self.expected, self.explored_rules_key) for i in self.sub_rules]


@dataclass
class CountSubRuleExplanation(RuleExplanation):
count: int = 1

@staticmethod
def from_explanation(expl: RuleExplanation, count: int) -> CountSubRuleExplanation:
return CountSubRuleExplanation(expl.rule, expl.state, expl.expected, expl.sub_rules, expl.explored_rules_key, expl.current_rule_explored, count)

def summary(self, depth=0) -> str:
summary = " " * depth + f"{self.count}x {str(self.rule)} -> {self.result}"
if self.current_rule_explored:
summary += " [Already explained]"
return summary


@dataclass
class CountExplanation(RuleExplanation):
rule: Count

@cached_property
def explained_sub_rules(self) -> List[RuleExplanation]:
return [
CountSubRuleExplanation.from_explanation(_explain(rule, self.state, self.expected, self.explored_rules_key), count)
for rule, count in self.rule.counter.items()
]


def explain(rule: CollectionRule, state: CollectionState, expected: bool = True) -> RuleExplanation:
if isinstance(rule, StardewRule):
return _explain(rule, state, expected, explored_spots=set())
Expand All @@ -80,7 +107,7 @@ def _(rule: AggregatingStardewRule, state: CollectionState, expected: bool, expl

@_explain.register
def _(rule: Count, state: CollectionState, expected: bool, explored_spots: Set[Tuple[str, str]]) -> RuleExplanation:
return RuleExplanation(rule, state, expected, rule.rules, explored_rules_key=explored_spots)
return CountExplanation(rule, state, expected, rule.rules, explored_rules_key=explored_spots)


@_explain.register
Expand Down
2 changes: 1 addition & 1 deletion worlds/stardew_valley/stardew_rule/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ def evaluate_while_simplifying(self, state: CollectionState) -> Tuple[StardewRul
return self, self(state)

def __repr__(self):
return f"Received {self.percent}% progression items."
return f"Received {self.percent}% progression items"

0 comments on commit 34e7748

Please sign in to comment.