Для этого можно использовать следующий шаблон:
(deftemplate range-test
(field check (type SYMBOL) (default no))
(field fired (type SYMBOL) (default no)) )
Первое правило будет устанавливать в рабочую память программы задачу range-test.
(defrule start
(initial-fact) =>
(assert (range-test)) )
При активизации этого правила в рабочую память будет добавлено (range-test (check no) (fired no))
Следующие три правила будут проверять, правильно ли снаряжен пистолет.
(defrule check
(object (name [PPK]) (safety on) (magazine out)
?T <- (range-test (check no)) =>
(send [PPK] clear)
(modify ?T (check yes) )
Правило check заключается в том, что если пистолет стоит на предохранителе (safety on), обойма вынута (magazine out) и пистолет не был проверен, то нужно очистить патронник и проверить, нет ли в нем патрона. Обработчик сообщения clear для класса pistol будет выглядеть следующим образом:
(defmessage-handler pistol clear ( )
(dynamic-put chamber 0)
(ppinstance) )
В первой строке объявляется, что clear является обработчиком сообщения для класса pistol, причем этот обработчик не требует передачи аргументов. Оператор во второй строке "очищает" патронник. Присвоение выполняется независимо от того, какое текущее значение имеет слот chamber, — 0 или 1 . Оператор в третьей строке требует, чтобы экземпляр распечатал информацию о текущем состоянии своих слотов.
В следующих двух правилах обрабатываются ситуации, когда пистолет снаряжен неправильно, — не установлен на предохранитель или в него вставлена обойма. Правило correctl устанавливает пистолет на предохранитель, а правило correct2 извлекает из него обойму.
(defrule correctl
(object (name [PPK]) (safety off) )
(range-test (check no)) =>
(send [PPK] safety on)
)
(defrule correct2
(object (name [PPK]) (safety on) (magazine in))
(range-test (check no)) =>
(send [PPK] drop) )
Как и при разработке предыдущего правила, нам понадобятся обработчики сообщений safety и drop.
(defmessage-handler pistol safety (?on-off)