Skip to content

Stardew Valley: speed up rules creation by 4% #2371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 61 additions & 50 deletions worlds/stardew_valley/stardew_rule.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import Iterable, Dict, List, Union, FrozenSet
from typing import Iterable, Dict, List, Union, FrozenSet, Set

from BaseClasses import CollectionState, ItemClassification
from .items import item_table
Expand All @@ -14,13 +14,13 @@ def __call__(self, state: CollectionState) -> bool:
raise NotImplementedError

def __or__(self, other) -> StardewRule:
if isinstance(other, Or):
if type(other) is Or:
return Or(self, *other.rules)

return Or(self, other)

def __and__(self, other) -> StardewRule:
if isinstance(other, And):
if type(other) is And:
return And(other.rules.union({self}))

return And(self, other)
Expand Down Expand Up @@ -80,28 +80,36 @@ def get_difficulty(self):
return 999999999


false_ = False_()
true_ = True_()
assert false_ is False_()
assert true_ is True_()


class Or(StardewRule):
rules: FrozenSet[StardewRule]

def __init__(self, rule: Union[StardewRule, Iterable[StardewRule]], *rules: StardewRule):
rules_list = set()
rules_list: Set[StardewRule]

if isinstance(rule, Iterable):
rules_list.update(rule)
rules_list = {*rule}
else:
rules_list.add(rule)
rules_list = {rule}

if rules is not None:
rules_list.update(rules)

assert rules_list, "Can't create a Or conditions without rules"

new_rules = set()
for rule in rules_list:
if isinstance(rule, Or):
new_rules.update(rule.rules)
else:
new_rules.add(rule)
rules_list = new_rules
if any(type(rule) is Or for rule in rules_list):
new_rules: Set[StardewRule] = set()
for rule in rules_list:
if type(rule) is Or:
new_rules.update(rule.rules)
else:
new_rules.add(rule)
rules_list = new_rules

self.rules = frozenset(rules_list)

Expand All @@ -112,11 +120,11 @@ def __repr__(self):
return f"({' | '.join(repr(rule) for rule in self.rules)})"

def __or__(self, other):
if isinstance(other, True_):
if other is true_:
return other
if isinstance(other, False_):
if other is false_:
return self
if isinstance(other, Or):
if type(other) is Or:
return Or(self.rules.union(other.rules))

return Or(self.rules.union({other}))
Expand All @@ -131,17 +139,17 @@ def get_difficulty(self):
return min(rule.get_difficulty() for rule in self.rules)

def simplify(self) -> StardewRule:
if any(isinstance(rule, True_) for rule in self.rules):
return True_()
if true_ in self.rules:
return true_

simplified_rules = {rule.simplify() for rule in self.rules}
simplified_rules = {rule for rule in simplified_rules if rule is not False_()}
simplified_rules = [simplified for simplified in {rule.simplify() for rule in self.rules}
if simplified is not false_]

if not simplified_rules:
return False_()
return false_

if len(simplified_rules) == 1:
return next(iter(simplified_rules))
return simplified_rules[0]

return Or(simplified_rules)

Expand All @@ -150,25 +158,26 @@ class And(StardewRule):
rules: FrozenSet[StardewRule]

def __init__(self, rule: Union[StardewRule, Iterable[StardewRule]], *rules: StardewRule):
rules_list = set()
rules_list: Set[StardewRule]

if isinstance(rule, Iterable):
rules_list.update(rule)
rules_list = {*rule}
else:
rules_list.add(rule)
rules_list = {rule}

if rules is not None:
rules_list.update(rules)

if len(rules_list) < 1:
rules_list.add(True_())

new_rules = set()
for rule in rules_list:
if isinstance(rule, And):
new_rules.update(rule.rules)
else:
new_rules.add(rule)
rules_list = new_rules
if not rules_list:
rules_list.add(true_)
elif any(type(rule) is And for rule in rules_list):
new_rules: Set[StardewRule] = set()
for rule in rules_list:
if type(rule) is And:
new_rules.update(rule.rules)
else:
new_rules.add(rule)
rules_list = new_rules

self.rules = frozenset(rules_list)

Expand All @@ -179,11 +188,11 @@ def __repr__(self):
return f"({' & '.join(repr(rule) for rule in self.rules)})"

def __and__(self, other):
if isinstance(other, True_):
if other is true_:
return self
if isinstance(other, False_):
if other is false_:
return other
if isinstance(other, And):
if type(other) is And:
return And(self.rules.union(other.rules))

return And(self.rules.union({other}))
Expand All @@ -198,17 +207,17 @@ def get_difficulty(self):
return max(rule.get_difficulty() for rule in self.rules)

def simplify(self) -> StardewRule:
if any(isinstance(rule, False_) for rule in self.rules):
return False_()
if false_ in self.rules:
return false_

simplified_rules = {rule.simplify() for rule in self.rules}
simplified_rules = {rule for rule in simplified_rules if rule is not True_()}
simplified_rules = [simplified for simplified in {rule.simplify() for rule in self.rules}
if simplified is not true_]

if not simplified_rules:
return True_()
return true_

if len(simplified_rules) == 1:
return next(iter(simplified_rules))
return simplified_rules[0]

return And(simplified_rules)

Expand All @@ -218,11 +227,12 @@ class Count(StardewRule):
rules: List[StardewRule]

def __init__(self, count: int, rule: Union[StardewRule, Iterable[StardewRule]], *rules: StardewRule):
rules_list = []
rules_list: List[StardewRule]

if isinstance(rule, Iterable):
rules_list.extend(rule)
rules_list = [*rule]
else:
rules_list.append(rule)
rules_list = [rule]

if rules is not None:
rules_list.extend(rules)
Expand Down Expand Up @@ -260,11 +270,12 @@ class TotalReceived(StardewRule):
player: int

def __init__(self, count: int, items: Union[str, Iterable[str]], player: int):
items_list = []
items_list: List[str]

if isinstance(items, Iterable):
items_list.extend(items)
items_list = [*items]
else:
items_list.append(items)
items_list = [items]

assert items_list, "Can't create a Total Received conditions without items"
for item in items_list:
Expand Down