Stardew Valley: Make sure number of month in time logic is a int to improve performance by ~20% (#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
This commit is contained in:
parent
e33a9991ef
commit
34e7748f23
|
@ -27,8 +27,8 @@ class BundleLogicMixin(BaseLogicMixin):
|
||||||
self.bundle = BundleLogic(*args, **kwargs)
|
self.bundle = BundleLogic(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BundleLogic(BaseLogic[Union[ReceivedLogicMixin, HasLogicMixin, TimeLogicMixin, RegionLogicMixin, MoneyLogicMixin, QualityLogicMixin, FishingLogicMixin, SkillLogicMixin,
|
class BundleLogic(BaseLogic[Union[ReceivedLogicMixin, HasLogicMixin, TimeLogicMixin, RegionLogicMixin, MoneyLogicMixin, QualityLogicMixin, FishingLogicMixin,
|
||||||
QuestLogicMixin]]):
|
SkillLogicMixin, QuestLogicMixin]]):
|
||||||
# Should be cached
|
# Should be cached
|
||||||
def can_complete_bundle(self, bundle: Bundle) -> StardewRule:
|
def can_complete_bundle(self, bundle: Bundle) -> StardewRule:
|
||||||
item_rules = []
|
item_rules = []
|
||||||
|
@ -45,7 +45,7 @@ QuestLogicMixin]]):
|
||||||
qualities.append(bundle_item.quality)
|
qualities.append(bundle_item.quality)
|
||||||
quality_rules = self.get_quality_rules(qualities)
|
quality_rules = self.get_quality_rules(qualities)
|
||||||
item_rules = self.logic.has_n(*item_rules, count=bundle.number_required)
|
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
|
return can_speak_junimo & item_rules & quality_rules & time_rule
|
||||||
|
|
||||||
def get_quality_rules(self, qualities: List[str]) -> StardewRule:
|
def get_quality_rules(self, qualities: List[str]) -> StardewRule:
|
||||||
|
|
|
@ -41,7 +41,7 @@ class MuseumLogic(BaseLogic[Union[ReceivedLogicMixin, HasLogicMixin, TimeLogicMi
|
||||||
else:
|
else:
|
||||||
geodes_rule = False_()
|
geodes_rule = False_()
|
||||||
# monster_rule = self.can_farm_monster(item.monsters)
|
# 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)
|
time_rule = self.logic.time.has_lived_months(time_needed_to_grind)
|
||||||
pan_rule = False_()
|
pan_rule = False_()
|
||||||
if item.item_name == Mineral.earth_crystal or item.item_name == Mineral.fire_quartz or item.item_name == Mineral.frozen_tear:
|
if item.item_name == Mineral.earth_crystal or item.item_name == Mineral.fire_quartz or item.item_name == Mineral.frozen_tear:
|
||||||
|
|
|
@ -26,8 +26,10 @@ class TimeLogic(BaseLogic[Union[TimeLogicMixin, HasLogicMixin]]):
|
||||||
|
|
||||||
@cache_self1
|
@cache_self1
|
||||||
def has_lived_months(self, number: int) -> StardewRule:
|
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:
|
if number <= 0:
|
||||||
return self.logic.true_
|
return self.logic.true_
|
||||||
|
|
||||||
number = min(number, MAX_MONTHS)
|
number = min(number, MAX_MONTHS)
|
||||||
return HasProgressionPercent(self.player, number * MONTH_COEFFICIENT)
|
return HasProgressionPercent(self.player, number * MONTH_COEFFICIENT)
|
||||||
|
|
||||||
|
|
|
@ -431,7 +431,7 @@ class Count(BaseStardewRule):
|
||||||
return len(self.rules)
|
return len(self.rules)
|
||||||
|
|
||||||
def __repr__(self):
|
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)
|
@dataclass(frozen=True)
|
||||||
|
|
|
@ -34,7 +34,7 @@ class RuleExplanation:
|
||||||
if not self.sub_rules:
|
if not self.sub_rules:
|
||||||
return self.summary(depth)
|
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)
|
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))
|
for i in sorted(self.explained_sub_rules, key=lambda x: x.result))
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class RuleExplanation:
|
||||||
if not self.sub_rules:
|
if not self.sub_rules:
|
||||||
return self.summary(depth)
|
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))
|
for i in sorted(self.explained_sub_rules, key=lambda x: x.result))
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -61,6 +61,33 @@ class RuleExplanation:
|
||||||
return [_explain(i, self.state, self.expected, self.explored_rules_key) for i in self.sub_rules]
|
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:
|
def explain(rule: CollectionRule, state: CollectionState, expected: bool = True) -> RuleExplanation:
|
||||||
if isinstance(rule, StardewRule):
|
if isinstance(rule, StardewRule):
|
||||||
return _explain(rule, state, expected, explored_spots=set())
|
return _explain(rule, state, expected, explored_spots=set())
|
||||||
|
@ -80,7 +107,7 @@ def _(rule: AggregatingStardewRule, state: CollectionState, expected: bool, expl
|
||||||
|
|
||||||
@_explain.register
|
@_explain.register
|
||||||
def _(rule: Count, state: CollectionState, expected: bool, explored_spots: Set[Tuple[str, str]]) -> RuleExplanation:
|
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
|
@_explain.register
|
||||||
|
|
|
@ -122,4 +122,4 @@ class HasProgressionPercent(CombinableStardewRule):
|
||||||
return self, self(state)
|
return self, self(state)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"Received {self.percent}% progression items."
|
return f"Received {self.percent}% progression items"
|
||||||
|
|
Loading…
Reference in New Issue