(setf *load-print* T)

(defstruct terminal contents)
(defstruct node test yes no)

(defun next-node (test-result node)
  (cond (test-result (node-yes node))
        (T (node-no node))))


(defun traverse (node)
  (cond ((terminal-p node) (terminal-contents node))
        ((node-p node)
           (traverse (next-node (funcall (node-test node)) node)))
        (T nil)
  )
)

(let ((subtree (make-node 
	       :test #'(lambda () (y-or-n-p "Heavy Exercise?"))
	       :yes (make-terminal :contents "Run down")
	       :no (make-terminal :contents "May be hyperactive")
	       )
	      ))

  (setq *hypochondriac*
	(make-node
	 :test #'(lambda () (y-or-n-p "Feel Well?"))
	 :yes (make-node
	       :test #'(lambda () (y-or-n-p "Hungry?"))
	       :no (make-node
		    :test #'(lambda () (y-or-n-p "Thirsty?"))
		    :yes (make-terminal :contents "Potential dehydration")
		    :no (make-terminal :contents "Possible Eating Disorder")
		    )
	       :yes (make-node
		     :test #'(lambda () (y-or-n-p "Very Hungry?"))
		     :yes (make-node
			   :test #'(lambda () (y-or-n-p "Recent Meal?"))
			   :yes subtree
			   :no (make-terminal :contents "Starving")
			   )
		     :no (make-terminal :contents "Time for a health snack")
		     )
	       )
	 :no (make-node
	      :test #'(lambda () (y-or-n-p "Weak?"))
	      :yes (make-node
		    :test #'(lambda () (y-or-n-p "Hungry?"))
		    :yes subtree
		    :no (make-node
			 :test #'(lambda () (y-or-n-p "Headache?"))
			 :yes (make-node
			       :test #'(lambda () (y-or-n-p "Runny Nose"))
			       :yes (make-terminal :contents "Probably Flu")
			       :no (make-terminal :contents "Probably Mad Cow Disease")
			       )
			 :no (make-terminal :contents "Try an aspirin")
			 )
		    )
	      :no (make-node
		   :test #'(lambda () (y-or-n-p "Upset stomach?"))
		   :yes (make-terminal :contents "Probably food poisoning")
		   :no (make-terminal :contents "Probably Lyme disease")
		   )
	      )
	 )
	)
  
  )
(traverse *hypochondriac*)