I'm exploring Apple's GameplayKit APIs and I am currently very confused by the way that GKRuleSystem evaluates its rules. The documentation says that the salience property determines the order of evaluation, with higher-salience rules being evaluated first (https://developer.apple.com/library/ios/documentation/GameplayKit/Reference/GKRule_Class/index.html#//apple_ref/occ/instp/GKRule/salience). But in practice, this does not appear to happen:
let twoRuleSystem = GKRuleSystem()
let stateConditionA = "A"
let stateConditionB = "B"
let fact = "A"
let stronglyAssert = NSPredicate(format: "state.\(stateConditionA) = true")
let weaklyRetract = NSPredicate(format: "state.\(stateConditionB) = true")
let strongRule = GKRule(predicate: stronglyAssert, assertingFact: fact, grade: 1.0)
let weakRule = GKRule(predicate: weaklyRetract, retractingFact: fact, grade: 0.25)
strongRule.salience = 10
weakRule.salience = 1
twoRuleSystem.addRulesFromArray([strongRule, weakRule])
twoRuleSystem.state[stateConditionA] = true
twoRuleSystem.state[stateConditionB] = true
twoRuleSystem.reset()
twoRuleSystem.evaluate()
print("The fact \(fact) evaluates to \(twoRuleSystem.gradeForFact(fact))")
// prints "The fact A evaluates to 1.0"
If I reverse the salience of the two facts, then the result is "The fact A evaluates to 0.75".
I would expect that when my strongRule has salience of 10, it will be evaluated first, and the fact A will be asserted with a value of 1.0. Then the weakRule will be evaluated, and fact A will be retracted with a value of 0.25, resulting in a fact grade of 0.75. But this only works if the weakRule has a higher salience.
This confuses me even more, because if the weakRule is being evaluated first, I would expect the value of fact A to be 0; the fact's grade can only be a value from 0 to 1.0. Then I would expect the strongRule to be evaluated and assert fact A with a grade of 1.0. But that is not what's happening.