Chocksmith
Chocksmith

Reputation: 1208

Function on left hand side of rule on Drools

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?

Upvotes: 0

Views: 1095

Answers (1)

laune
laune

Reputation: 31300

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.

Upvotes: 2

Related Questions