Consider the following rule for "locations" r and s:
∀r,s[(danger(r)∧adjacent(r,s))→danger(s)]
I tried to implement as follows:
function boolean adjacent(Location l1, Location l2) {
if (l1.x == l2.x)
return Math.abs(l1.y - l2.y) == 1;
if (l1.y == l2.y)
return Math.abs(l1.x - l2.x) == 1;
return false;
}
rule danger
when
$s : Location(danger == true)
$r : Location()
adjacent($s,$r)
then
modify($r) { setDanger(true) }
end;
But it does not compile saying that adjacent cannot be resolved. I tried eval(adjacent($s,$r)) but it does not work because rete keeps visiting the same combinations of $s and $r forever.
I tried implementing adjacent() method on Location, but it does not compile either:
$r : Location(adjacent($s) == true)
I thought on some alternatives like: making each Location has a list of adjacent locations; etc. But none of them sounded right for me.
How would be the right way to implement this?
rule danger
when
$s : Location( danger )
$r : Location(! danger, adjacent($s,$r) )
then
modify($r) { setDanger(true) }
end
You can write a boolean expression as a constraint, or inside an eval CE (but never as a pattern all by itself, as you tried).
To avoid the loop, add a constraint that fails after the modify.