Stardew Valley: speed up rules creation by 4% (#2371)
* Stardew Valley: speed up rules creation by 4% No class should ever inherit from And, Or, False_ or True_ and isinstance is not free. Sadly there is no cheap way to forbid inheritance, but it was tested using metaclass. * Stardew Valley: save calls to type() Local variable is a bit faster than fetching type again * Stardew Valley: save calls to True_() and False_(), also use 'in' operator * Stardew Valley: optimize And and Or simplification * Stardew Valley: optimize logic constructors
This commit is contained in:
parent
6a2407468a
commit
fc2855ca6d
|
@ -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
|
||||
|
@ -14,13 +14,13 @@ class StardewRule:
|
|||
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)
|
||||
|
@ -80,28 +80,36 @@ class False_(StardewRule): # noqa
|
|||
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)
|
||||
|
||||
|
@ -112,11 +120,11 @@ class Or(StardewRule):
|
|||
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}))
|
||||
|
@ -131,17 +139,17 @@ class Or(StardewRule):
|
|||
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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -179,11 +188,11 @@ class And(StardewRule):
|
|||
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}))
|
||||
|
@ -198,17 +207,17 @@ class And(StardewRule):
|
|||
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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue