;; bottles2.clp

;; Solution employing non-deterministic rule firing
;;
(deffunction bottles ( ?X )
  (reset)
  (if (> ?X 0)
    then
    (assert (bottle ?X)))
  (run))

(defrule take_one "Take one bottle down"
  (declare (salience 10))
  ?f <- (take)
  =>
  (printout t "Take one down, and pass it around." crlf)
  (retract ?f)
  )

(defrule generate "Generate bottles"
  (bottle ?x)
  (not
    (and (bottle ?y)
	 (test (> ?x ?y))))
  (test (> ?x 1))
  =>
  (bind ?new (- ?x 1))
  (assert (bottle ?new))
  )

(defrule more_bottles "Decrease the number of bottles by one"
  ?f <- (bottle ?x)
  (not
    (not (bottle ~?x)))
  (not
    (and (bottle ?y)
	 (test (< ?x ?y))))
   =>
  (printout t ?x " bottles of beer on the wall. ")
  (retract ?f)
  (assert (take))
  )

(defrule last_bottle "Take the last bottle"
  ?f <- (bottle 1)
  (not
    (bottle ~1))
  =>
  (retract ?f)
  (printout t "1 bottle of beer on the wall. ")
  (assert (take))
  )

(defrule empty_stock "All bottles have been removed"
  (not
    (bottle ?))
  =>
  (printout t "Now, they are all gone." crlf)
  )

