(deffacts initial-phase
(phase choose-player))
(defrule player-select
(phase choose-player) ; control pattern
=>
(printout t "Who moves first (Computer: c "
"Human: h)? ")
(assert (player-select (read))))
(defrule good-player-choice
?phase <- (phase choose-player)
?choice <- (player-select ?player&c | h)
=>
(retract ?phase ?choice)
(assert (player-move ?player)))
(defrule bad-player-choice ; if bad, then back to previous page
?phase <- (phase choose-player)
?choice <- (player-select ?player&~c&~h)
=>
(retract ?phase ?choice)
(assert (phase choose-player))
(printout t "Choose c or h only." crlf)
)
(defrule get-human-move
(player-move h)
(pile-size ?size)
(test (> ?size 1))
=>
(printout t "How many sticks do you wish to take? ")
(assert (human-takes (read))))
(defrule good-human-move
?whose-turn <- (player-move h)
(pile-size ?size)
?number-taken <- (human-takes ?choice)
(test (and (integerp ?choice)
(>= ?choice 1)
(<= ?choice 3)
(< ?choice ?size)))
=>
(retract ?whose-turn ?number-taken)
(printout t "Human made a valid move." crlf)
(assert (player-move c)))
(defrule bad-human-move
?whose-turn <- (player-move h)
(pile-size ?size)
?number-taken <- (human-takes ?choice)
(test (or (not (integerp ?choice))
(< ?choice 1)
(> ?choice 3)
(>= ?choice ?size)))
=>
(printout t "Human made an invalid move." crlf)
(retract ?whose-turn ?number-taken)
(assert (player-move h)))
(pile-size ?size) (test (> ?size 1)) (pile-size ?size&:(> ?size 1)) (data ?item&:(stringp ?item)|(symbolp ?item))
(deftemplate take-sticks
(slot how-many) ; Number of sticks to take.
(slot for-remainder)) ; Remainder when stack is
; divided by 4.
(deffacts take-sticks-information
(take-sticks (how-many 1) (for-remainder 1))
(take-sticks (how-many 1) (for-remainder 2))
(take-sticks (how-many 2) (for-remainder 3))
(take-sticks (how-many 3) (for-remainder 0)))
(defrule computer-move
?whose-turn <- (player-move c)
?pile <- (pile-size ?size&:(> ?size 1))
(take-sticks (how-many ?number)
(for-remainder ?X&:(= ?X (mod ?size 4))))
=>
(retract ?whose-turn ?pile)
(assert (pile-size (- ?size ?number)))
(assert (player-move h)))
(defrule shut-off-electricity
(or (emergency (type flood))
(extinguisher-sysetem (type water-sprinkler)
(status on))
=>
(printout t "Shut off the electricity." crlf))
(defrule use-carbon-dioxide-extinguisher
?system <- (extingisher-system
(type carbon-dioxide)
(status off))
(or (emergency (type class-B-fire))
(and (emergency (type class-C-fire))
(electrical-power (status off))))
=>
(modify ?system (status on))
(printout t "Use carbon dioxide extinguisher" crlf))
(defrule largest-number
(number ?x)
(not (number ?y&:(> ?y ?x)))
=>
(printout t "Largest number is " ?x crlf))
Note: Variables bound within a not CE retain their value only within the scope of the not CE.
Example: Find the largest integer
(defrule operator-alert-for-emergency
(exist (emergency))
=>
(printout t "Emergency: Operator Alert" crlf)
(assert (operator-alert)))
Demo:
(deftemplate emergency
(slot type)
(slot location))
(deftemplate fire-squad
(slot name)
(slot location))
(deftemplate evacuated
(slot building))
(defrule all-fires-being-handled
(forall (emergency (type fire)
(location ?where))
(fire-squad (location ?where))
(evacuated (building ?where)))
=>
(printout t
"All buildings that are on fire " crlf
"have been evacuated and " crlf
"have firefighters on location." crlf))
Example:
(defrule noxious-fumes-present
(emergency (type fire))
(noxious-fumes-present)
=>
(assert (use-oxygen-mask)))
(defrule noxious-fumes-present
(logical (emergency (type fire))
(noxious-fumes-present))
=>
(assert (use-oxygen-mask)))
Example: logical CE
Previous Pattern Matching Up TOC Next Modular Design and Execution Control