Stardew Valley: simplify in-place (#2393)
this allows skipping multiple simplifications of the same object, e.g. item_rules also update the logic simplification tests to be a proper unittest.TestCase
This commit is contained in:
		
							parent
							
								
									ff65de1464
								
							
						
					
					
						commit
						d9b076a687
					
				| 
						 | 
				
			
			@ -88,6 +88,7 @@ assert true_ is True_()
 | 
			
		|||
 | 
			
		||||
class Or(StardewRule):
 | 
			
		||||
    rules: FrozenSet[StardewRule]
 | 
			
		||||
    _simplified: bool
 | 
			
		||||
 | 
			
		||||
    def __init__(self, rule: Union[StardewRule, Iterable[StardewRule]], *rules: StardewRule):
 | 
			
		||||
        rules_list: Set[StardewRule]
 | 
			
		||||
| 
						 | 
				
			
			@ -112,6 +113,7 @@ class Or(StardewRule):
 | 
			
		|||
            rules_list = new_rules
 | 
			
		||||
 | 
			
		||||
        self.rules = frozenset(rules_list)
 | 
			
		||||
        self._simplified = False
 | 
			
		||||
 | 
			
		||||
    def __call__(self, state: CollectionState) -> bool:
 | 
			
		||||
        return any(rule(state) for rule in self.rules)
 | 
			
		||||
| 
						 | 
				
			
			@ -139,6 +141,8 @@ class Or(StardewRule):
 | 
			
		|||
        return min(rule.get_difficulty() for rule in self.rules)
 | 
			
		||||
 | 
			
		||||
    def simplify(self) -> StardewRule:
 | 
			
		||||
        if self._simplified:
 | 
			
		||||
            return self
 | 
			
		||||
        if true_ in self.rules:
 | 
			
		||||
            return true_
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -151,11 +155,14 @@ class Or(StardewRule):
 | 
			
		|||
        if len(simplified_rules) == 1:
 | 
			
		||||
            return simplified_rules[0]
 | 
			
		||||
 | 
			
		||||
        return Or(simplified_rules)
 | 
			
		||||
        self.rules = frozenset(simplified_rules)
 | 
			
		||||
        self._simplified = True
 | 
			
		||||
        return self
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class And(StardewRule):
 | 
			
		||||
    rules: FrozenSet[StardewRule]
 | 
			
		||||
    _simplified: bool
 | 
			
		||||
 | 
			
		||||
    def __init__(self, rule: Union[StardewRule, Iterable[StardewRule]], *rules: StardewRule):
 | 
			
		||||
        rules_list: Set[StardewRule]
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +187,7 @@ class And(StardewRule):
 | 
			
		|||
            rules_list = new_rules
 | 
			
		||||
 | 
			
		||||
        self.rules = frozenset(rules_list)
 | 
			
		||||
        self._simplified = False
 | 
			
		||||
 | 
			
		||||
    def __call__(self, state: CollectionState) -> bool:
 | 
			
		||||
        return all(rule(state) for rule in self.rules)
 | 
			
		||||
| 
						 | 
				
			
			@ -207,6 +215,8 @@ class And(StardewRule):
 | 
			
		|||
        return max(rule.get_difficulty() for rule in self.rules)
 | 
			
		||||
 | 
			
		||||
    def simplify(self) -> StardewRule:
 | 
			
		||||
        if self._simplified:
 | 
			
		||||
            return self
 | 
			
		||||
        if false_ in self.rules:
 | 
			
		||||
            return false_
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +229,9 @@ class And(StardewRule):
 | 
			
		|||
        if len(simplified_rules) == 1:
 | 
			
		||||
            return simplified_rules[0]
 | 
			
		||||
 | 
			
		||||
        return And(simplified_rules)
 | 
			
		||||
        self.rules = frozenset(simplified_rules)
 | 
			
		||||
        self._simplified = True
 | 
			
		||||
        return self
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Count(StardewRule):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,56 +1,57 @@
 | 
			
		|||
import unittest
 | 
			
		||||
from .. import True_
 | 
			
		||||
from ..logic import Received, Has, False_, And, Or
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_simplify_true_in_and():
 | 
			
		||||
    rules = {
 | 
			
		||||
        "Wood": True_(),
 | 
			
		||||
        "Rock": True_(),
 | 
			
		||||
    }
 | 
			
		||||
    summer = Received("Summer", 0, 1)
 | 
			
		||||
    assert (Has("Wood", rules) & summer & Has("Rock", rules)).simplify() == summer
 | 
			
		||||
class TestSimplification(unittest.TestCase):
 | 
			
		||||
    def test_simplify_true_in_and(self):
 | 
			
		||||
        rules = {
 | 
			
		||||
            "Wood": True_(),
 | 
			
		||||
            "Rock": True_(),
 | 
			
		||||
        }
 | 
			
		||||
        summer = Received("Summer", 0, 1)
 | 
			
		||||
        self.assertEqual((Has("Wood", rules) & summer & Has("Rock", rules)).simplify(),
 | 
			
		||||
                         summer)
 | 
			
		||||
 | 
			
		||||
    def test_simplify_false_in_or(self):
 | 
			
		||||
        rules = {
 | 
			
		||||
            "Wood": False_(),
 | 
			
		||||
            "Rock": False_(),
 | 
			
		||||
        }
 | 
			
		||||
        summer = Received("Summer", 0, 1)
 | 
			
		||||
        self.assertEqual((Has("Wood", rules) | summer | Has("Rock", rules)).simplify(),
 | 
			
		||||
                         summer)
 | 
			
		||||
 | 
			
		||||
def test_simplify_false_in_or():
 | 
			
		||||
    rules = {
 | 
			
		||||
        "Wood": False_(),
 | 
			
		||||
        "Rock": False_(),
 | 
			
		||||
    }
 | 
			
		||||
    summer = Received("Summer", 0, 1)
 | 
			
		||||
    assert (Has("Wood", rules) | summer | Has("Rock", rules)).simplify() == summer
 | 
			
		||||
    def test_simplify_and_in_and(self):
 | 
			
		||||
        rule = And(And(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
                   And(Received('Winter', 0, 1), Received('Spring', 0, 1)))
 | 
			
		||||
        self.assertEqual(rule.simplify(),
 | 
			
		||||
                         And(Received('Summer', 0, 1), Received('Fall', 0, 1),
 | 
			
		||||
                             Received('Winter', 0, 1), Received('Spring', 0, 1)))
 | 
			
		||||
 | 
			
		||||
    def test_simplify_duplicated_and(self):
 | 
			
		||||
        rule = And(And(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
                   And(Received('Summer', 0, 1), Received('Fall', 0, 1)))
 | 
			
		||||
        self.assertEqual(rule.simplify(),
 | 
			
		||||
                         And(Received('Summer', 0, 1), Received('Fall', 0, 1)))
 | 
			
		||||
 | 
			
		||||
def test_simplify_and_in_and():
 | 
			
		||||
    rule = And(And(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
               And(Received('Winter', 0, 1), Received('Spring', 0, 1)))
 | 
			
		||||
    assert rule.simplify() == And(Received('Summer', 0, 1), Received('Fall', 0, 1), Received('Winter', 0, 1),
 | 
			
		||||
                                  Received('Spring', 0, 1))
 | 
			
		||||
    def test_simplify_or_in_or(self):
 | 
			
		||||
        rule = Or(Or(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
                  Or(Received('Winter', 0, 1), Received('Spring', 0, 1)))
 | 
			
		||||
        self.assertEqual(rule.simplify(),
 | 
			
		||||
                         Or(Received('Summer', 0, 1), Received('Fall', 0, 1), Received('Winter', 0, 1),
 | 
			
		||||
                            Received('Spring', 0, 1)))
 | 
			
		||||
 | 
			
		||||
    def test_simplify_duplicated_or(self):
 | 
			
		||||
        rule = And(Or(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
                   Or(Received('Summer', 0, 1), Received('Fall', 0, 1)))
 | 
			
		||||
        self.assertEqual(rule.simplify(),
 | 
			
		||||
                         Or(Received('Summer', 0, 1), Received('Fall', 0, 1)))
 | 
			
		||||
 | 
			
		||||
def test_simplify_duplicated_and():
 | 
			
		||||
    rule = And(And(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
               And(Received('Summer', 0, 1), Received('Fall', 0, 1)))
 | 
			
		||||
    assert rule.simplify() == And(Received('Summer', 0, 1), Received('Fall', 0, 1))
 | 
			
		||||
    def test_simplify_true_in_or(self):
 | 
			
		||||
        rule = Or(True_(), Received('Summer', 0, 1))
 | 
			
		||||
        self.assertEqual(rule.simplify(), True_())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_simplify_or_in_or():
 | 
			
		||||
    rule = Or(Or(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
              Or(Received('Winter', 0, 1), Received('Spring', 0, 1)))
 | 
			
		||||
    assert rule.simplify() == Or(Received('Summer', 0, 1), Received('Fall', 0, 1), Received('Winter', 0, 1),
 | 
			
		||||
                                 Received('Spring', 0, 1))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_simplify_duplicated_or():
 | 
			
		||||
    rule = And(Or(Received('Summer', 0, 1), Received('Fall', 0, 1)),
 | 
			
		||||
               Or(Received('Summer', 0, 1), Received('Fall', 0, 1)))
 | 
			
		||||
    assert rule.simplify() == Or(Received('Summer', 0, 1), Received('Fall', 0, 1))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_simplify_true_in_or():
 | 
			
		||||
    rule = Or(True_(), Received('Summer', 0, 1))
 | 
			
		||||
    assert rule.simplify() == True_()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_simplify_false_in_and():
 | 
			
		||||
    rule = And(False_(), Received('Summer', 0, 1))
 | 
			
		||||
    assert rule.simplify() == False_()
 | 
			
		||||
    def test_simplify_false_in_and(self):
 | 
			
		||||
        rule = And(False_(), Received('Summer', 0, 1))
 | 
			
		||||
        self.assertEqual(rule.simplify(), False_())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue