Problems with deffunction usage

35 views
Skip to first unread message

Jose Antonio Escribano Ayllon

unread,
Apr 24, 2024, 6:11:17 AMApr 24
to CLIPSESG
Hi,

I am trying to create a deffunction to use it to decide whether I need to adopt a new plan in for my NPCs.

But I am having some troubles to make it work, and I am not sure why.
So, my function looks like this: I would expect, that if there is no current_npc_action at all, it would just return true, and if there is a fact with score that is higher than inp_new_score it would return false.

But for some reason, this doesn't really do what I would expect. Maybe the problem is in the caller defrule?

This is the code

(deffunction can_adopt_new_plan (?inp_id  ?inp_new_score)
    if  (do-for-fact   ((?f current_npc_action))
                       (eq ?f:npc_id ?inp_id)
                       (> ?f:score ?inp_new_score)
            (return false)
        )
    (return true)
)



(defrule MAIN::adopt-new-plan
(new_plan_information ?npc_id ?score)
    (test (can_adopt_new_plan ?npc_id ?score))
    =>
    (assert (current_npc_action (npc_id ?npc_id) (score ?score)))
)




Could you help me to figure out what I am doing wrong?
Cheers,
Jose

Ryan Johnston

unread,
Apr 24, 2024, 7:22:09 AMApr 24
to CLIPSESG
With your approach, can_adopt_new_plan will only run when a new_plan_information fact is asserted or retracted from working memory.

I think you'd be better off here avoiding the deffunction and instead doing the pattern-matching as part of the rule antecedent:

CLIPS>  (deftemplate current_npc_action (slot npc_id) (slot score))
CLIPS> (defrule adopt-new-plan
    (new_plan_information ?npc_id ?score)
    (not (current_npc_action (npc_id ?npc_id) (score ?somethingHigher&:(> ?somethingHigher ?score))))

    =>
    (assert (current_npc_action (npc_id ?npc_id) (score ?score))))
CLIPS> (assert (new_plan_information 1 1))
==> f-1     (new_plan_information 1 1)
==> Activation 0      adopt-new-plan: f-1,*
<Fact-1>
CLIPS> (run)
FIRE    1 adopt-new-plan: f-1,*
==> f-2     (current_npc_action (npc_id 1) (score 1))
<== Focus MAIN
1 rules fired        Run time is 0.00668001174926758 seconds.
149.700335498608 rules per second.
2 mean number of facts (2 maximum).
0 mean number of instances (0 maximum).
1 mean number of activations (1 maximum).
CLIPS> (assert (new_plan_information 2 0))
==> f-3     (new_plan_information 2 0)
==> Activation 0      adopt-new-plan: f-3,*
<Fact-3>
CLIPS> (run)
==> Focus MAIN
FIRE    1 adopt-new-plan: f-3,*
==> f-4     (current_npc_action (npc_id 2) (score 0))
<== Focus MAIN
1 rules fired        Run time is 0.00562286376953125 seconds.
177.845318860244 rules per second.
4 mean number of facts (4 maximum).
0 mean number of instances (0 maximum).
1 mean number of activations (1 maximum).
CLIPS> (assert (new_plan_information 1 0))
==> f-5     (new_plan_information 1 0)
<Fact-5>
CLIPS> (agenda)
CLIPS> (assert (new_plan_information 1 3))
==> f-6     (new_plan_information 1 3)
==> Activation 0      adopt-new-plan: f-6,*
<Fact-6>
CLIPS> (run)
==> Focus MAIN
FIRE    1 adopt-new-plan: f-6,*
==> f-7     (current_npc_action (npc_id 1) (score 3))
<== Focus MAIN
1 rules fired        Run time is 0.00562310218811035 seconds.
177.837778248887 rules per second.
7 mean number of facts (7 maximum).
0 mean number of instances (0 maximum).
1 mean number of activations (1 maximum).
CLIPS> (facts)
f-1     (new_plan_information 1 1)
f-2     (current_npc_action (npc_id 1) (score 1))
f-3     (new_plan_information 2 0)
f-4     (current_npc_action (npc_id 2) (score 0))
f-5     (new_plan_information 1 0)
f-6     (new_plan_information 1 3)
f-7     (current_npc_action (npc_id 1) (score 3))
For a total of 7 facts.

Anecdotally, I've noticed if I do `do-for-fact` in a `deffunction` like your original code, it makes the execution of my rules engines slower. YMMV
Reply all
Reply to author
Forward
0 new messages