⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sticks.clp

📁 一套美国国家宇航局人工智能中心NASA的专家系统工具源代码
💻 CLP
字号:

;;;======================================================
;;;   Sticks Program
;;;
;;;     This program was introduced in Chapter 9.
;;;
;;;     CLIPS Version 6.0 Example
;;;
;;;     To execute, merely load, reset and run.
;;;======================================================

; **************
; FACT TEMPLATES
; **************

; The phase fact indicates the current action to be
; undertaken before the game can begin

; (phase 
;    <action>)      ; Either choose-player or 
                    ; select-pile-size

; The player-select fact contains the human's response to 
; the "Who moves first?" question.

; (player-select
;    <choice>)      ; Valid responses are c (for computer)
                    ; and h (for human).
    
; The pile-select fact contains the human's response to 
; the "How many sticks in the pile?" question.

; (pile-select
;    <choice>)      ; Valid responses are integers 
                    ; greater than zero.

; The pile-size fact contains the current number 
; of sticks in the stack.

; (pile-size
;    <sticks>)      ; An integer greater than zero.

; The player-move fact indicates whose turn it is.

; (player-move
;    <player)       ; Either c (for computer) 
                    ; or h (for human).

; The human-takes fact contains the human's response to 
; the "How many sticks do you wish to take?" question.


; (human-takes
;    <choice>)      ; Valid responses are 1, 2, and 3.

; The take-sticks facts indicate how many sticks the 
; computer should take based on the remainder when the 
; stack size is divided by 4.

(deftemplate take-sticks
   (slot how-many)         ; Number of sticks to take.
   (slot for-remainder))   ; Remainder when stack is
                           ; divided by 4.

; ********
; DEFFACTS 
; ********

(deffacts initial-phase
   (phase choose-player))

(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)))

; *****
; RULES 
; *****

; RULE player-select
; IF
;   The phase is to choose the first player
; THEN
;   Ask who should move first, and
;   Get the human's response

(defrule player-select
   (phase choose-player)
   =>
   (printout t "Who moves first (Computer: c "
               "Human: h)? ")
   (assert (player-select (read))))

; RULE good-player-choice
; IF
;   The phase is to choose the first player, and
;   The human has given a valid response
; THEN
;   Remove unneeded information, and 
;   Indicate whose turn it is, and
;   Indicate that the pile size should be chosen

(defrule good-player-choice
   ?phase <- (phase choose-player)
   ?choice <- (player-select ?player&c | h)
   =>
   (retract ?phase ?choice)
   (assert (player-move ?player))
   (assert (phase select-pile-size)))

; RULE bad-player-choice
; IF
;   The phase is to choose the first player, and
;   The human has given a invalid response
; THEN
;   Remove unneeded information, and 
;   Indicate that the first player should be chosen again, 
;   and Print the valid choices

(defrule bad-player-choice 
   ?phase <- (phase choose-player)
   ?choice <- (player-select ?player&~c&~h)
   =>
   (retract ?phase ?choice)
   (assert (phase choose-player))
   (printout t "Choose c or h." crlf))

; RULE pile-select
; IF
;   The phase is to choose the pile size
; THEN
;   Ask what the pile size should be, and
;   Get the human's response


(defrule pile-select 
   (phase select-pile-size)
   =>
   (printout t "How many sticks in the pile? ")
   (assert (pile-select (read))))

; RULE good-pile-choice
; IF
;   The phase is to choose the pile size, and
;   The human has given a valid response
; THEN
;   Remove unneeded information, and 
;   Store the pile size

(defrule good-pile-choice
   ?phase <- (phase select-pile-size)
   ?choice <- (pile-select ?size&:(integerp ?size)
                                &:(> ?size 0))
   =>
   (retract ?phase ?choice)
   (assert (pile-size ?size)))

; RULE bad-pile-choice
; IF
;   The phase is to choose the pile size, and
;   The human has given a invalid response
; THEN
;   Remove unneeded information, and 
;   Indicate that the pile size should be chosen again, 
;   and Print the valid choices

(defrule bad-pile-choice
   ?phase <- (phase select-pile-size)
   ?choice <- (pile-select ?size&~:(integerp ?size)
                                 |:(<= ?size 0))
   =>
   (retract ?phase ?choice)
   (assert (phase select-pile-size))
   (printout t "Choose an integer greater than zero."
               crlf))




; RULE computer-loses
; IF
;   The pile size is 1, and
;   It is the computer's move
; THEN
;   Print that the computer has lost the game

(defrule computer-loses
   (pile-size 1)
   (player-move c)
   =>
   (printout t "Computer must take the last stick!" crlf)
   (printout t "I lose!" crlf))

; RULE human-loses
; IF
;   The pile size is 1, and
;   It is the human's move
; THEN
;   Print that the human has lost the game

(defrule human-loses
   (pile-size 1)
   (player-move h)
   =>
   (printout t "You must take the last stick!" crlf)
   (printout t "You lose!" crlf))

; RULE get-human-move
; IF
;   The pile size is greater than 1, and
;   It is the human's move
; THEN
;   Ask how many sticks to take, and
;   Get the human's response

(defrule get-human-move
   (pile-size ?size&:(> ?size 1))
   (player-move h)
   =>
   (printout t "How many sticks do you wish to take? ")
   (assert (human-takes =(read))))


; RULE good-human-move
; IF
;   There is a pile of sticks, and
;   The human has chosen how many sticks to take, and
;   It is the human's move, and
;   The human's choice is valid
; THEN
;   Remove unneeded information, and 
;   Compute the new pile size, and
;   Update the pile size, and
;   Print the number of sticks left in the stack, and
;   Trigger the computer player's turn

(defrule good-human-move
   ?pile <- (pile-size ?size)
   ?move <- (human-takes ?choice)
   ?whose-turn <- (player-move h)
   (test (and (integerp ?choice)
              (>= ?choice 1) 
              (<= ?choice 3)
              (< ?choice ?size)))
   =>
   (retract ?pile ?move ?whose-turn)
   (bind ?new-size (- ?size ?choice))
   (assert (pile-size ?new-size))
   (printout t ?new-size " stick(s) left in the pile."
               crlf)
   (assert (player-move c)))

; RULE bad-human-move
; IF
;   There is a pile of sticks, and
;   The human has chosen how many sticks to take, and
;   It is the human's move, and
;   The human's choice is invalid
; THEN
;   Print the valid choices, and
;   Remove unneeded information, and
;   Retrigger the human player's move





(defrule bad-human-move
   (pile-size ?size)
   ?move <- (human-takes ?choice)
   ?whose-turn <- (player-move h)
   (test (or (not (integerp ?choice)) 
             (< ?choice 1) 
             (> ?choice 3)
             (>= ?choice ?size)))
   =>
   (printout t "Number of sticks must be between 1 and 3,"
               crlf
               "and you must be forced to take the last "
               "stick." crlf)
   (retract ?move ?whose-turn)
   (assert (player-move h)))

; RULE computer-move
; IF
;   It is the computers's move, and
;   The pile size is greater than 1, and
;   The computer's response is available
; THEN
;   Remove unneeded information, and
;   Compute the new pile size, and
;   Print the number of sticks left in the stack, and
;   Update the pile size, and
;   Trigger the human players move

(defrule computer-move
   ?whose-turn <- (player-move c)
   ?pile <- (pile-size ?size&:(> ?size 1))
   (take-sticks (how-many ?number)
                (for-remainder =(mod ?size 4)))
   =>
   (retract ?whose-turn ?pile)
   (bind ?new-size (- ?size ?number))
   (printout t "Computer takes " ?number " stick(s)."
               crlf)
   (printout t ?new-size " stick(s) left in the pile."
               crlf)
   (assert (pile-size ?new-size))
   (assert (player-move h)))


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -