;;;;;;;;;;;;;;;;;;;;;;;;

;;;
;; We recommend that you run this model in raw ACT-R, rather than in the environment

;; To run the model, call the function named demo

;; This function takes two lists.
;; The first list is the values of A, B, and C
;; These values are restricted to integers in the range 0-9, inclusive.

;; The second list is T1, OPERATOR, T2, and T3, which specify
;; an equation of the form T1X OPERATOR T2 = T3

;; T1, T2, and T3 can appear as numbers (no substitution)
;; or as A, B, or C (require substitution)

;; The value of X (the solution) must be an integer in the range 0-9, inclusive.

;; Example:
;; (demo '(3 4 5) '(A - C 16)) creates the equation AX-C=16,
;; which solves to X=7


(defparameter *visual* nil)
(defparameter *retrieved* nil)
(defparameter *productions* nil)
(defparameter *exp* 3.67)
(defparameter *scale* 1.383)
(defvar *v* nil)

(defun gammafn (x)
  (* (expt x x) (exp (- x)) (sqrt (* 2 pi x)) (1+ (/ 1 (* 12 x)))))

(defparameter *ret-mag* .074)  ; (/ 1.097 (gammafn *exp*)))
(defparameter *man-mag* .330)  ; (/ 4.878 (gammafn *exp*)))
(defparameter *imag-mag* .219) ; (/ 3.241 (gammafn *exp*)))


(setf *actr-enabled-p* t)

(defparameter equation-set 
  '(((58 1 7) (1 + 0 5))
    ((58 1 7) (5 + 0 15))
    ((58 1 7) (1 + 3 8))
    ((58 1 7) (5 + 3 18))
    ((1 3 5) (a + 0 c))
    ((5 3 15) (a + 0 c))
    ((1 3 8) (a + 3 c))
    ((5 3 18) (a + 3 c))))

(defvar *experiment-window* nil)
(defvar *response* nil)
(defvar *hold-time* nil)
(defparameter *graphic* nil)

(defvar *a*)
(defvar *b*)
(defvar *c*)
(defvar *t1*)
(defvar *t2*)
(defvar *op*)
(defvar *t3*)

(defvar *WWW-interface*)

(setf  *WWW-interface* 
      '((:heading "fMRI Experiment 1" 2)
        (:heading "Parameters" 3)
        (:table)
        (:table)
        "latency scale, s:"         (:string :sy *scale*  1.383)  (:new-row)
        "exponent, a:"              (:string :sy *exp* 3.67)      (:new-row)
        "magnitude, M (retrieval):" (:string :sy *ret-mag* .074)  (:new-row)
        "magnitude, M (imaginal):"  (:string :sy *imag-mag* .219) (:new-row)
        "magnitude, M (manual):"    (:string :sy *man-mag* .330)         
        
        (:table-end)
        
        (:table)
        (:checkbox "Trace" :sy *v*  nil)                (:new-row)
        (:checkbox "Graphic output" :sy *graphic*  nil) (:new-row)
        (:table-end)
        (:table-end)
        
        (:new-para)
        
        (:heading "Equation" 3)
        (:table)
        (:table)
        "A: " (:string :sy *a* 3) (:new-row)
        "B: " (:string :sy *b* 4) (:new-row)
        "C: " (:string :sy *c* 5)  
        (:table-end)
        (:table)
        "first term:"  (:string :sy *t1* "a") (:new-row)
        "operator:"    (:string :sy *op* "-") (:new-row)
        "second term:" (:string :sy *t2* "c") (:new-row)
        "third term:"  (:string :sy *t3* 16)  
        (:table-end)
        (:table-end)
        (:new-para)
        "The values for the equation parameters allow you to specify the conditions of the trial presented to the model (see the paper for more details).  The terms specify the terms of the equation and can be either numbers or the symbols a, b or, c. The operator is the operator of the equation which can be either + or -, and the values for a, b, and c are the values the participant was to substitute for those symbols in the equation.  The default values above specify the equation \"aX - c = 16\".  Which is solved to X=7 when the a and c vaules are substituted in.  For the model to solve the equation the value of X found must be an integer in the range of 0-9, inclusive."
        (:new-para)
        (:button "Run model" "(if (and (numberp *scale*) (numberp *exp*)
                                       (numberp *ret-mag*) (numberp *man-mag*) 
                                       (numberp *imag-mag*))
                                  (progn
                                    (demo (list *a* *b* *c*) (list *t1* *op* *t2* *t3*)) 
                                    )
                                  (format *standard-output* \"~%~%All parameters must be numbers.~%\"))")
        (:reset "Default values")
        (:button "Production Rules" "(let ((prods (no-output (pp))))
                                       (dolist (x prods)
                                         (pp-fct (list x))
                                         (spp-fct (list x))
                                         (format *standard-output* \"~%\")))")
        (:button "Chunk types" "(chunk-type)")
        (:button "Chunks" "(dm)")
        (:new-para)
         "TIME and SIZE:"
        (:new-para)
        "- It usually takes less than 1 minute to run the model"
        (:new-line)
        "- The trace of 1 run is approximatly 3k (2 pages) in size"
        (:use-actr5)))



(defun demo (constants coefficients)
  (cond ((not (legaltest constants coefficients)) (format t "Invalid equation.  The solution for X must be an integer 0-9."))
        (t 
         (princ "The constant set was A = ") 
         (princ (first constants)) 
         (princ ", B = ")
         (princ (second constants)) 
         (princ ", C = ") 
         (princ (third constants)) 
         (terpri)
         (reset)
         (encode-it constants coefficients)
         (test-equation (format nil "~d ~d ~d" (first constants)
                          (second constants) (third constants))
                        (format nil "~d X ~a ~d = ~d" (first coefficients)
                          (second coefficients) 
                          (third coefficients)(fourth coefficients))))))


(defun legaltest (constants coefficients)
  (and (equal (length constants) 3)
       (equal (length coefficients) 4)
       (numberp (first constants))
       (numberp (second constants))
       (numberp (third constants))
       (or (numberp (first coefficients)) (member (first coefficients) '(a b c)))
       (member (second coefficients) '(+ -))
       (or (numberp (third coefficients)) (member (third coefficients) '(a b c)))
       (or (numberp (fourth coefficients)) (member (fourth coefficients) '(a b c)))
       (equal (type-of (solve-equation constants coefficients)) 'fixnum)
       (< (solve-equation constants coefficients) 10)
       (>= (solve-equation constants coefficients) 0)))

(defun solve-equation (constants coefficients)
  (setf coefficients (subst (first constants) 'a coefficients))
  (setf coefficients (subst (second constants) 'b coefficients))
  (setf coefficients (subst (third constants) 'c coefficients))
  (/ (funcall (if (equal (second coefficients) '+) #'- #'+) (fourth coefficients) (third coefficients)) (first coefficients))
)

(defun count-productions (x) (push *time* *productions*))

(defun assign-retrieval (arguments)
  "Assigns to the variable *retrieval-scheduler* the result and latency of the retrieval.
   The variable *retrieval* is also reset to nil waiting for the result."
  (let ((retrieval (if (first arguments)
                       (instantiation-variable *instantiation* (pop arguments))
                     *retrieval-scheduler*)))
    (signal-output *latency-trace* "Latency ~6,3F: ~A Retrieval" *latency* retrieval)
    (setf *retrieved* (push (list *time* *latency*) *retrieved*))
    (setf *retrieval* nil)
    (setf *retrieval-scheduler* (cons (+ *time* *latency*) retrieval))))

(defun transform (start val)
  (push *time* *visual*))


(defun test-equation (set equation)
  (let (result start-time)
    (princ "The equation was ") (princ equation) (terpri)
  (setf *retrieved* nil *productions* nil *visual* nil)
  
  (when (open-rpm-window? *experiment-window*)
    (close-rpm-window *experiment-window*))
  
  (setf *experiment-window* (make-rpm-window :visible nil ;; model probably doesn't work with t but a person can do it then
                                             :title "Equation Experiment"
                                             :width 300 :height 300))
  
  (add-visual-items-to-rpm-window *experiment-window* 
                                  (make-static-text-for-rpm-window *experiment-window* 
                                                                   :x 25
                                                                   :y 150
                                                                   :width 275
                                                                   :text set))
  (if *actr-enabled-p*
      (let ((goal (new-name "GOAL")))
        (pm-install-device *experiment-window*)
        (add-dm-fct (list (cons goal `(isa do-set constant a))))
        (goal-focus-fct  (list goal))
        (pm-proc-display ) 
        
        (pm-run 3 :full-time t)
        (lose-focus)
        (mod-focus term nil)
        (remove-all-items-from-rpm-window *experiment-window*)
        (add-visual-items-to-rpm-window *experiment-window* 
                                  (make-static-text-for-rpm-window *experiment-window* 
                                                                   :x 25
                                                                   :y 150
                                                                   :width 275
                                                                   :text equation))
        
        (pm-proc-display)
        
        (setf start-time (pm-get-time))
        (pm-run 30)
        (generate *response* (/ (- *hold-time* start-time) 1000.0) (reverse *retrieved*)
                  (reverse *visual*)))
    
    (progn ;;; person
      (sleep 3)
      (remove-all-items-from-rpm-window *experiment-window*)
        (add-visual-items-to-rpm-window *experiment-window* 
                                  (make-static-text-for-rpm-window *experiment-window* 
                                                                   :x 25
                                                                   :y 150
                                                                   :width 275
                                                                   :text equation))
       (setf start-time (pm-get-time))
      (setf *hold-time* nil)
      (while (null *hold-time*)
        (allow-event-manager *experiment-window*))
      (setf result (list *response* (/ (- *hold-time* start-time) 1000.0))))
      )

  (close-rpm-window *experiment-window*)
    result))

#+:(or :mcl :allegro-ide) (defmethod rpm-window-key-event-handler ((win rpm-window) key)
      (setf *response* (string key))
      (setf *hold-time* (pm-get-time))
      )


(defmethod rpm-window-key-event-handler ((win virtual-window) key)
  (setf *response* (string key))
  (setf *hold-time* (pm-get-time)))



(defun generate (answer time retrieval imag)
  (let ((imaginal (mapcar #'(lambda (x) (list x .2)) imag))
        (res (list nil nil nil)))
    (format t "~%The model's answer is ~S and it was generated in ~6,3f seconds~%~%" answer time) 
    (format t " Scan  Time(sec) Imaginal  Retrieval   Motor~%")
    
    (dotimes (scan 14)
      (let* ((mean (+ .75 (* scan 1.5)))
             (i (* *imag-mag* (bold-fn mean imaginal)))
             (r (* *ret-mag* (bold-fn mean retrieval)))
             (m (* *man-mag* (bold-fn mean (list (list (+ 2.6 time) .4))))))
        (format t "~4d~10,3f~10,3f~10,3f~10,3f~%" (1+ scan) mean i r m) 
        (push i (first res))
        (push r (second res))
        (push m (third res))))
    (draw-graphs res)))



(defun integrate (t1 t2 exp scale)
  (let* ((nt1 (/ t1 scale))
         (nt2 (/ t2 scale))
         (nt12 (/ (+ nt1 nt2) 2))
         (start (* (expt nt1 exp) (exp (- nt1))))
         (mid (* (expt nt12 exp) (exp (- nt12))))
         (end (* (expt nt2 exp) (exp (- nt2)))))
    (* (- nt2 nt1) .25 (+ start mid mid end))))

(defun sqr (x) (* x x))

(defun bold-fn (time lis)
  (do ((temp lis (cdr temp))
       (signal 0 (+ signal (calculate-bold time (caar temp) (cadar temp)))))
      ((or (null temp) (< time (caar temp))) (return signal))))


(defun calculate-bold (current past length)
  (integrate (- current past) (+ length (- current past))
             *exp* *scale*))

(defun encode-digits (n)
  (do ((count 0 (1+ count))
       (result nil (cons (list count 'isa 'symbol 
                               'string (prin1-to-string count)
                               'type 'integer) result)))
      ((equal count n) (eval `(add-dm ,@result)))))

(defun encode-it (constants equation)
  (let* ((subbed (subst (first constants) 'a
                        (subst (second constants) 'b
                               (subst (third constants) 'c equation))))
         (op (case (second equation) (+ '-) (- '+)))
         (part (apply op
                      (list (fourth subbed) (third subbed))))
         (end (/ part (first subbed))))
    (eval `(add-dm
            (fact1 isa arithmetic-fact arg1 ,(fourth subbed) arg2 ,(third subbed)
                   operator ,op result ,part)
            (fact2 isa arithmetic-fact arg1 ,part arg2 ,(first subbed)
                   operator / result ,end)))))

(defun lose-focus ()
  (setf (current-marker (vis-m *mp*)) nil)
  (setf (currently-attended (vis-m *mp*)) nil)
  )

(defun draw-graphs (data)
  (unless *graphic* (format *standard-output* 
                        "~%</pre>If your browser supports JAVA, you 
                               can display the data in a graph by checking 
                               the Graphic output box on the interface page.<pre>~%~%"))
  (when *graphic*
    (format *standard-output* " 
        <applet 
        code = \"DansGraphs.class\" 
        width = 500 
        height = 400> 
        <PARAM name=\"title\" value=\"Model BOLD Response Predictions\">
        <PARAM name=\"xmin\" value=\"0\">
        <PARAM name=\"xmax\" value=\"22\">
        <PARAM name=\"ymax\" value=\"1.0\">
        <PARAM name=\"ymin\" value=\"0.0\">
        <PARAM name=\"longestline\" value=\"14\">
        <PARAM name=\"numlines\" value=\"3\">
        <PARAM name=\"xdiv\" value=\"1\">
        <PARAM name=\"xspacing\" value=\"5\">
        <PARAM name=\"ydiv\" value=\"0.1\">
        <PARAM name=\"yspacing\" value=\"0.2\">
        <PARAM name=\"xname\" value=\"Time (sec.)\">
        <PARAM name=\"yname\" value=\"Percent change\">
        <PARAM name=\"name0\" value=\"Imaginal\">
        <PARAM name=\"lcolor0\" value=\"0\">
        <PARAM name=\"lstyle0\" value=\"2\">
        <PARAM name=\"xval0\" value=\"0.75;2.25;3.75;5.25;6.75;8.25;9.75;11.25;12.75;14.25;15.75;17.25;18.75;20.25;\">
        <PARAM name=\"name1\" value=\"Retrieval\">
        <PARAM name=\"lcolor1\" value=\"1\">
        <PARAM name=\"lstyle1\" value=\"2\">
        <PARAM name=\"xval1\" value=\"0.75;2.25;3.75;5.25;6.75;8.25;9.75;11.25;12.75;14.25;15.75;17.25;18.75;20.25;\">
        <PARAM name=\"name2\" value=\"Manual\">
        <PARAM name=\"lcolor2\" value=\"2\">
        <PARAM name=\"lstyle2\" value=\"2\">
        <PARAM name=\"xval2\" value=\"0.75;2.25;3.75;5.25;6.75;8.25;9.75;11.25;12.75;14.25;15.75;17.25;18.75;20.25;\"> ")

      (dotimes (i 3) 
        (format *standard-output* "<PARAM name=\"yval~s\" value=\"" i)
        (dotimes (j 14)
          (format *standard-output* "~6,3f;" (nth (- 13 j) (nth i data))))
      
      (format *standard-output* "\">"))

    (format *standard-output* "
             <HR> Either your browser does not support JAVA or this graph has scrolled off the top of the display.~%
             </HR></applet>")))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; This section contains the ACT-R productions
;;; and memory definitions for the simulation

(clear-all)
(pm-reset)

(sgp-fct (list :v *v* :esc t :lf .6 :ga 0.00))

(pm-set-params :show-focus t :visual-attention-latency .05)

(chunk-type do-set constant term)
(chunk-type solve-equation term value operator operand state)
(chunk-type symbol string type inverted-by)
(chunk-type arithmetic-fact arg1 arg2 operator result)

(setf *firing-hook-fn* #'count-productions)
(encode-digits 100)

(add-dm (a isa symbol string "a" type letter)
        (b isa symbol string "b" type letter)
        (c isa symbol string "c" type letter))

(sdp :base-level 2)

(add-dm 
 (+ isa symbol string "+" type operator inverted-by -)
 (* isa symbol string "*" type operator inverted-by /)
 (- isa symbol string "-" type operator inverted-by +)
 (/ isa symbol string "/" type operator inverted-by *)
 (f38 isa arithmetic-fact arg1 8 arg2 3 operator - result 5)
 (f318 isa arithmetic-fact arg1 18 arg2 3 operator - result 15)
 (f315 isa arithmetic-fact arg1 15 arg2 5 operator / result 3))


(P find-next-term-set
   =goal>
     ISA         do-set
     term        nil
   ==>
   +visual-location>
     ISA         visual-location
     screen-x    lowest
     attended    nil
   =goal>
     term        looking
   )

(P attend-next-term-set
   =goal>
     ISA         do-set
     term        looking
   =visual-state>
     ISA         module-state
     modality    free
   =visual-location>
     ISA         visual-location
   ==>
   =goal>
     term        attending
   +visual>
     ISA         visual-object
     screen-pos  =visual-location
   )

(P encode-term
   =goal>
     ISA         do-set
     term        attending
   =visual>
     ISA         text
     value       =term
     status      nil
   ==>
   +retrieval>
     isa SYMBOL
     string =term
   =goal>
     term        retrieving)

(P encode-a-term
   =goal>
     ISA         do-set
     term        retrieving
     constant        a
   =retrieval>
     isa SYMBOL
   ==>
   =goal>
     term =retrieval
   +goal>
     isa         do-set
     constant        b
   )

(P encode-b-term
   =goal>
     ISA         do-set
     term        retrieving
     constant        b
   =retrieval>
     isa SYMBOL
   ==>
   =goal>
     term =retrieval
   +goal>
     isa         do-set
     constant        c
   )

(P encode-c-term
   =goal>
     ISA         do-set
     term        retrieving
     constant        c
   =retrieval>
     isa SYMBOL
   ==>
   =goal>
     term =retrieval
   +goal>
     isa         solve-equation
     term        waiting
     state       right
   
   )

(P find-right-term
   =goal>
     ISA         solve-equation
     term        nil
     state       right
   ==>
   +visual-location>
     ISA         visual-location
     screen-x    highest
     attended    nil
   =goal>
     term        looking
   )

(P translate
   =goal>
     ISA         solve-equation
     term        retrieving
   =retrieval>
     isa symbol
     type letter     
   ==>
   =goal>
     term        translating
   +retrieval>
     isa do-set
     constant =retrieval
   )

(P process-value-letter
   =goal>
     ISA         solve-equation
     term        translating
     state       right
   =retrieval>
     isa do-set
     term =val 
     constant =con
   =visual-location>
     ISA         visual-location
     screen-x =x   
   ==>
   !eval! (transform =con =val)
   !bind! =x1 (- =x 18)
   !bind! =x2 (- =x 36)
   +visual-location>
     ISA         visual-location
     screen-x    (within =x2 =x1)
     attended    nil
   =goal>
     value =retrieval
     state Op1
     term Looking
     value =val
   )

(P process-value-integer
   =goal>
     ISA         solve-equation
     term        retrieving
     state       right
   =retrieval>
     isa symbol
     type Integer  
   =visual-location>
     ISA         visual-location
     screen-x =x   
   ==>
   !bind! =x1 (- =x 18)
   !bind! =x2 (- =x 36)
   +visual-location>
     ISA         visual-location
     screen-x    (within =x2 =x1)
     attended    nil
   =goal>
     value =retrieval
     state Op1
     term Looking
   )


(P process-0-integer
   =goal>
     ISA         solve-equation
     term        retrieving
     state       op1
   =retrieval>
     isa symbol
     string "0"
     type Integer     
   =visual-location>
     ISA         visual-location
     screen-x =x
   ==>
   !bind! =x2 (- =x 36)
   +visual-location>
     ISA         visual-location
   <  screen-x   =x2
     attended    nil
   =goal>
     state       op2
     term        looking
   )

(P process-0-letter
   =goal>
     ISA         solve-equation
     term        retrieving
     state       op1
   =retrieval>
     isa DO-SET
     term 0   
     constant =con
   =visual-location>
     ISA         visual-location
     screen-x =x
   ==>
   !bind! =x1 (1- =x)
   !bind! =x2 (- =x 18)
   !eval! (transform =con 0)
   +visual-location>
     ISA         visual-location
     screen-x    (within =x2 =x1)
     attended    nil
   =goal>
     state       op2
     term        looking
   )

(P process-op1-letter
   =goal>
     ISA         solve-equation
     term        translating
     state       op1
   =retrieval>
     isa DO-SET
     term =val 
     constant =con
   - term 0
   =visual-location>
     ISA         visual-location
     screen-x =x
   ==>
   !bind! =x1 (1- =x)
   !bind! =x2 (- =x 18)
   !eval! (transform =con =val)
   +visual-location>
     ISA         visual-location
     screen-x    (within =x2 =x1)
     attended    nil
   =goal>
     operand     =val
     state       operator
     term        looking
   )

(P process-op1-integer
   =goal>
     ISA         solve-equation
     term        retrieving
     state       op1
   =retrieval>
     isa symbol
   -  string "0"
     type Integer     
   =visual-location>
     ISA         visual-location
     screen-x =x
   ==>
   !bind! =x1 (1- =x)
   !bind! =x2 (- =x 18)
   +visual-location>
     ISA         visual-location
     screen-x    (within =x2 =x1)
     attended    nil
   =goal>
     operand     =retrieval
     state       operator
     term        looking
   )

(P process-operator
   =goal>
     ISA         solve-equation
     term        retrieving
     state       operator
     value       =val1
     operand     =val2
   =retrieval>
     isa symbol
     type operator
     inverted-by    =opposite
   ==>
   +retrieval>
     isa arithmetic-fact
     arg1 =val1
     arg2 =val2
     operator =opposite
   =goal>
     operator     =retrieval
     term        retrieving-fact
   )

(p finish-operation1
   =goal>
     ISA         solve-equation
     state   operator
     term    retrieving-fact
   =retrieval>
     isa arithmetic-fact
     result    =val
   =visual-location>
     ISA         visual-location
     screen-x =x
   ==>
   !bind! =x1 (- =x 18)
   !bind! =x2 (- =x 28)
   !eval! (transform 'answer =val)
   +visual-location>
     ISA         visual-location
     screen-x    (within =x2 =x1)
     attended    nil
   =goal>
     state       op2
     term        looking
     value =val)

(P process-1-integer
   =goal>
     ISA         solve-equation
     term        retrieving
     state       op2
   =retrieval>
     isa symbol
     string "1"
     type Integer     
   ==>
   =goal>
     state       respond
     term        nil
   )

(P process-1-letter
   =goal>
     ISA         solve-equation
     term        translating
     state       op2
   =retrieval>
     isa DO-SET
     term 1
     constant =con
   ==>
   !eval! (transform =con 1)
   =goal>
     state       respond
     term        nil
   )


(P process-op2-integer
   =goal>
     ISA         solve-equation
     term        retrieving
     state       op2
     value       =val1
   =retrieval>
     isa symbol
   - string "1"
     type Integer     
   ==>
   =goal>
     term       retrieving-fact
   +retrieval>
     isa arithmetic-fact
     arg1 =val1
     arg2 =retrieval
     operator /)

(P process-op2-letter
   =goal>
     ISA         solve-equation
     term        translating
     state       op2
     value       =val1
   =retrieval>
     isa DO-SET
     term =val2
     constant =con
   - term 1
   ==>
   !eval! (transform =con =val2)
   =goal>
     term       retrieving-fact
   +retrieval>
     isa arithmetic-fact
     arg1 =val1
     arg2 =val2
     operator /)

(p finish-operation2
   =goal>
     ISA         solve-equation
     state   op2
     term    retrieving-fact
   =retrieval>
     isa arithmetic-fact
     result    =val
   ==>
   !eval! (transform 'answer =val)
   =goal>
     state respond
     operator nil
     operand nil
     term nil
     value =val)

(p attend-next-term-equation
   =goal>
     ISA         solve-equation
     term        looking
   =visual-state>
     ISA         module-state
     modality    free
   =visual-location>
     ISA         visual-location
   ==>
   =goal>
     term        attending
   +visual>
     ISA         visual-object
     screen-pos  =visual-location
   )



(P encode
   =goal>
     ISA         solve-equation
     term        attending
   =visual>
     ISA         text
     value       =term
     status      nil
   =visual-location>
     isa visual-location
   ==>
   !eval! (transform 'encode =term)
   =goal>
     term         retrieving
   +retrieval>
     isa          symbol
     string       =term
   )

(p retrieve-key
   =goal>
     isa SOLVE-EQUATION
     value =val
     state respond
   ==>
   +retrieval> =val
   =goal>
     state answer)

(p generate-answer
   =goal>
     isa SOLVE-EQUATION
     state answer
   =retrieval>
     isa SYMBOL
     string =ans
   =manual-state>
     ISA         module-state
     modality    free
   ==>
   =goal>
     state finished
   +manual>
     ISA         press-key
     key         =ans)