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

;;;
;;; This file contains the ACT-R model of the
;;; Roberts free recall experiment
;;; presented in Chapter 7
;;;
;;; ACT-R version 4 required
;;; 
;;; A WWW interface and a command line interface
;;; are provided.  
;;; To run the command line version, call
;;; (do-roberts n)
;;; replacing n with the number of runs to
;;; simulate.

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; This section contains the LISP functions to simulate
;;; the experiment, implement the interface, collect the
;;; data, and display the results
;;;
;;; The ACT-R Model starts further down
;;;

;;; Global variables

(defvar *stop-it*)
(defvar *history*)
(defvar *items*)
(defvar *data*)
(defvar *index*)
(defvar *counter*)
(defvar *predictions*)
(defvar *inc*)
(defvar *results*)


(defparameter *respond* .5)
(defparameter *encode* .2)
(defparameter *factor* 2)
(defparameter *thresh* 2.9)
(defparameter *noise* .85)
(defparameter *rehearsal* 0.5)
(defparameter *v* nil)
(defparameter *text* t)
(defparameter *graphic* nil)
(defparameter *overlay* nil)
(defparameter *runs* 1)

(defparameter *roberts-contexts* '(l1 l2 l3 l4 l5 l6 l7 l8 l9 l10
                     l11 l12 l13 l14 l15 l16 l17 l18 l19 l20))

(defparameter *roberts-results* (make-array '(20) :initial-contents 
                                           '(6.25	7.50	8.50	9.00
                                             7.25	9.75	11.00	12.50
                                             8.00	12.50	15.00	16.00
                                             8.50	14.00	17.50	21.00
                                             9.00	15.75	20.00	24.00)))

(defparameter *roberts-headers* '(".5" " 1" " 2" " 4" " 8"))


    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; This section contains the interface for the WWW using the
;;; ACT-R on the Web application by Elmar Schwarz

(defvar *WWW-interface*)

(setf  *WWW-interface* 
      '((:heading "Roberts Experiment model" 2)
        (:table)
        
        (:table)
        "Noise (s): "             (:string :sy *noise*   .85)  (:new-row)
        "Threshold: "             (:string :sy *thresh*  2.9)  (:new-row)
        "Factor (F):"             (:string :sy *factor*  2)  (:new-row)
        "Response time (sec.): " (:string :sy *respond* .5)        (:new-row)
        "Encoding time (sec.): " (:string :sy *encode* .2)         (:new-row)
        "Rehearsal time (sec.): " (:string :sy *rehearsal* .5) (:new-row)
        "Number of runs (1-20): " (:string :sy *runs*    1)
        (:table-end)
        
        (:table)
        (:checkbox "Trace" :sy *v*  nil)  (:new-row)
        (:checkbox "Text output" :sy *text*  t) (:new-row)
        (:checkbox "Graphic output" :sy *graphic*  nil) (:new-row)
        (:checkbox "Show simulation and experiment data on one graph" :sy *overlay*  nil) 
        (:table-end)
       (:table-end)
        
        (:new-para)
        (:button "Show Experiment Results" "(display-roberts-data *roberts-results* nil)")
       
        (:new-para)
        
        
        (:button "Run model" "(if (and (numberp *thresh*) (numberp *noise*)
                                       (numberp *noise*) (numberp *runs*)
                                       (numberp *encode*) (numberp *rehearsal*) (numberp *respond*))
                                  (do-roberts (min 20 (max 1 *runs*)))
                                  (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 for 1 run of the model"
        (:new-line)
        "- The trace of 1 run is approximatly 400k (250 pages) in size"
        (:new-para)))



;;; reset-wme-number-roberts takes one parameter
;;; which is ignored, and sets the number of
;;; chunks to be 100 
;;; this function is hooked to the actr 
;;; cycle-hook-fn, so that the number
;;; of chunks is always 100
;;; to prevent problems with ia's 
;;; changing for the different size lists

(defun reset-wme-number-roberts (instantiation)
  (declare (ignore instantiation))
  (setf *wme-number* 100))

;;; display-roberts-data takes 1 parameter
;;; an array containg data for a simulation
;;; of the roberts experiment, and it displays
;;; a table showing the data from the array

(defun display-roberts-data (data simulation)
  (when simulation 
    (format *standard-output* "~%~%Parameters for run (~S ~S ~S ~S ~S ~S ~S)~%" 
            *noise* *thresh* *factor*  *respond* *encode* *rehearsal* *runs*))
  
  (when *text*
    (format *standard-output* "~%~a data (number of items recalled):~%~%" (if simulation "Simulation" "Experimental"))
    
    (format *standard-output* "                     List Length~%")
    (format *standard-output* "               10      20      30      40~%")
    (format *standard-output* "delay (sec)~%")
    (dotimes (i 5)
      (format *standard-output* "~A           " (nth i *roberts-headers*))
      (dotimes (j 4)
        (format *standard-output* "~5,2F   " (aref data (+ j (* i 4)))))
      (format *standard-output* "~%"))
    
    (when (and simulation *overlay*)
      (format *standard-output* "~%Experimental data (number of items recalled):~%~%")
      
      (format *standard-output* "                     List Length~%")
      (format *standard-output* "               10      20      30      40~%")
      (format *standard-output* "delay (sec)~%")
      (dotimes (i 5)
        (format *standard-output* "~A           " (nth i *roberts-headers*))
        (dotimes (j 4)
          (format *standard-output* "~5,2F   " (aref *roberts-results* (+ j (* i 4)))))
        (format *standard-output* "~%")))

    (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 = 400 
        height = 600> 

        <PARAM name=\"title\" value=\"Data for Roberts Experiemnt\">
        <PARAM name=\"longestline\" value=\"4\">
        <PARAM name=\"numlines\" value=\"~S\">
        <PARAM name=\"xmin\" value=\"0\">
        <PARAM name=\"xmax\" value=\"40\">
        <PARAM name=\"ymax\" value=\"30\">
        <PARAM name=\"ymin\" value=\"0\">
        <PARAM name=\"xspacing\" value=\"10\">
        <PARAM name=\"ydiv\" value=\"5\">
        <PARAM name=\"yspacing\" value=\"10\">
        <PARAM name=\"lcolor0\" value=\"0\">
        <PARAM name=\"lcolor1\" value=\"1\">
        <PARAM name=\"lcolor2\" value=\"2\">
        <PARAM name=\"lcolor3\" value=\"3\">
        <PARAM name=\"lcolor4\" value=\"4\">
        <PARAM name=\"lstyle0\" value=\"~s\">
        <PARAM name=\"lstyle1\" value=\"~s\">
        <PARAM name=\"lstyle2\" value=\"~s\">
        <PARAM name=\"lstyle3\" value=\"~s\">
        <PARAM name=\"lstyle4\" value=\"~s\">
        <PARAM name=\"xval0\" value=\"10;20;30;40;\">
        <PARAM name=\"xval1\" value=\"10;20;30;40;\">
        <PARAM name=\"xval2\" value=\"10;20;30;40;\">
        <PARAM name=\"xval3\" value=\"10;20;30;40;\">
        <PARAM name=\"xval4\" value=\"10;20;30;40;\">
        <PARAM name=\"xname\" value=\"List Length\">
        <PARAM name=\"yname\" value=\"Recalled\">"
            (if (and simulation *overlay*) 10 5)
            (if simulation 2 6553)
            (if simulation 2 6553)
            (if simulation 2 6553)
            (if simulation 2 6553)
            (if simulation 2 6553))

    (dotimes (i 5)
      (format *standard-output* "<PARAM name=\"name~s\" value=\"~a delay = ~a\">"
              i (if simulation "Simulation Data" "Experiment Data") (nth i *roberts-headers*))
    
      (format *standard-output* "<PARAM name=\"yval~s\" value=\"" i)
      (dotimes (j 4)
        (format *standard-output* "~4,2f;"  (aref data (+ j (* i 4)))))
      (format *standard-output* "\">"))

    (when (and simulation *overlay*)
      (format *standard-output* "
        <PARAM name=\"lcolor5\" value=\"0\">
        <PARAM name=\"lcolor6\" value=\"1\">
        <PARAM name=\"lcolor7\" value=\"2\">
        <PARAM name=\"lcolor8\" value=\"3\">
        <PARAM name=\"lcolor9\" value=\"4\">
        <PARAM name=\"lstyle5\" value=\"6553\">
        <PARAM name=\"lstyle6\" value=\"6553\">
        <PARAM name=\"lstyle7\" value=\"6553\">
        <PARAM name=\"lstyle8\" value=\"6553\">
        <PARAM name=\"lstyle9\" value=\"6553\">
        <PARAM name=\"xval5\" value=\"10;20;30;40;\">
        <PARAM name=\"xval6\" value=\"10;20;30;40;\">
        <PARAM name=\"xval7\" value=\"10;20;30;40;\">
        <PARAM name=\"xval8\" value=\"10;20;30;40;\">
        <PARAM name=\"xval9\" value=\"10;20;30;40;\">")
      (dotimes (i 5)
        (format *standard-output* "<PARAM name=\"name~s\" value=\"Experimental Data delay = ~a\">"
                (+ 5 i)  (nth i *roberts-headers*))
        
        (format *standard-output* "<PARAM name=\"yval~s\" value=\"" (+ 5 i))
        (dotimes (j 4)
          (format *standard-output* "~4,2f;"  (aref *roberts-results* (+ j (* i 4)))))
        (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>")))



;;; set-roberts-parameters is used to set
;;; the parameters of the model before each run
;;; it is needed for the WWW interface

(defun set-roberts-parameters ()
  (setf *cycle-hook-fn* #'reset-wme-number-roberts)
  
  (sgp-fct (list :bll 0.5 :ans *noise* :rt *thresh* :er t :lf *factor* :v *v*))

  (parameters-fct 'create-token (list :effort *encode*))
  (parameters-fct 'rehearse-it (list :effort *rehearsal*))
  (parameters-fct 'dump-it (list :a *rehearsal*))
  (parameters-fct 'recall-a-word  (list :effort *respond*)))


;;; setup-roberts takes 2 parameters
;;; a name for a word chunk, and
;;; the number of previous contexts that word occured
;;; in, and returns the list of chunk definitions
;;; for the previous contexts

(defun setup-roberts (word n)
  (addwm-fct (list (list word 'isa 'word)))
  (do ((count 0 (1+ count))
       (result nil (cons   `(,(gentemp "C") isa memory-token 
                             context ,(nth count *roberts-contexts*)
                             name ,word) result)))
      ((= count n) result)))


;;; setup-roberts-materials takes one parameter
;;; the number of words to create, and
;;; generates the word chunks, and the 
;;; previous context chunks for the words,
;;; and then sets the base levels for the items,
;;; and returns the list of word chunk
;;; names

(defun setup-roberts-materials (n)
   (do ((count 0 (1+ count))
        (items nil (append (setup-roberts (gentemp "I") 1) items)))
       ((= count n) 
        (eval `(addwm ,@items))
        (setallbaselevels 10 -400)
        (remove-duplicates (mapcar 'seventh items)))))



;;; do-roberts takes one parameter
;;; the number of runs to simulate,
;;; and runs the experiment
;;; that many times, displaying a table
;;; of the results when finished

(defun do-roberts (n)
  (let ((final (make-array '(20) :initial-element 0)))
    (do ((count 0 (1+ count)))
        ((equal count n) (setf *predictions* final) )
      (let ((temp (conditions-roberts)))
        (do ((j 0 (1+ j)))
            ((equal j 20) nil)
          (do ((k 0 (1+ k)))
              ((equal k 40) nil)
            (cond ((not (zerop (aref temp  j k)))
                   (setf (aref final j) (1+ (aref final j)))))))))
    (dotimes (i 20)
      (setf (aref *predictions* i) (/ (aref *predictions* i) n)))
    (display-roberts-data *predictions* t)))

;;; conditions-roberts takes no parameters
;;; and runs one simulation of each condition 
;;; of the roberts experiment 
;;; and returns the data array of the results

(defun conditions-roberts ()
  (setf *data* (make-array '(20 40) :initial-element 0))
    (reset) (run-roberts-experiment 10 .5 0)
    (reset) (run-roberts-experiment 20 .5 1)
    (reset) (run-roberts-experiment 30 .5 2)
    (reset) (run-roberts-experiment 40 .5 3)
    (reset) (run-roberts-experiment 10 1 4)
    (reset) (run-roberts-experiment 20 1 5)
    (reset) (run-roberts-experiment 30 1 6)
    (reset) (run-roberts-experiment 40 1 7)
    (reset) (run-roberts-experiment 10 2 8)
    (reset) (run-roberts-experiment 20 2 9)
    (reset) (run-roberts-experiment 30 2 10)
    (reset) (run-roberts-experiment 40 2 11)
    (reset) (run-roberts-experiment 10 4 12)
    (reset) (run-roberts-experiment 20 4 13)
    (reset) (run-roberts-experiment 30 4 14)
    (reset) (run-roberts-experiment 40 4 15)
    (reset) (run-roberts-experiment 10 8 16)
    (reset) (run-roberts-experiment 20 8 17)
    (reset) (run-roberts-experiment 30 8 18)
    (reset) (run-roberts-experiment 40 8 19)
    *data*)


;;; run-roberts-experiment takes 3 parameters,
;;; the number of words for the run, the amount
;;; of time for study (in seconds), and the index
;;; of this condition in the data array *data*
;;; it then runs one simulation of the experiment
;;; using the given number of words and study time

(defun run-roberts-experiment (n time index)  
  (set-roberts-parameters)
  (setf *index* index) 
  (setf *inc* time)
  (let* ((materials (setup-roberts-materials n)))
    (setallbaselevels 500 -1000)
    (reset-wme-number-roberts nil)
    (reset-ia)
    (setf *stop-it* 0) 
    (setf *items* (no-output (wm-fct materials)))
    (setf *history* *items*)

    (addwm (goal isa study-words context L0))
    (wmfocus goal) 
    (run) 

    (setf *counter* 1)
    (modwme goal position transfer) 
    (resetia)
    (wmfocus goal)
    (run)))


;;; analyze-roberts takes one parameter
;;; a word chunk, and updates the results
;;; array for the position of the word in
;;; the study list

(defun analyze-roberts (word)
  (setf (aref *data* *index* (position word *history*)) *counter*)
  (setf *counter* (1+ *counter*)))


;;; get-word-roberts takes no parameters
;;; and sets the time when the next
;;; study word will be presented
;;; and returns the current word 

(defun get-word-roberts ()
  (setf *stop-it* (+ *inc* *stop-it*))
   (pop *items*))



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

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; ACT-R Model of the task
;;;
;;;


(clearall)

(chunk-type study-words first second third fourth position context)
(chunk-type memory-token name status context)
(chunk-type context)
(chunk-type word)
(chunk-type rehearse target)
(chunk-type output target)
(chunk-type recall-words context)
(chunk-type type-word position word)
(chunk-type dump-words first second third fourth position context)


; adds the contexts to working memory

(add-dm (l0 isa context)
        (l1 isa context))

(sgp-fct (list :bll 0.5 :ans *noise* :rt *thresh* :er t :lf *factor* :v *v*))

(setallbaselevels 500 -1000)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Productions
;;;

(p high-first
"
  IF the goal is to study words
     and there is no word in the first position
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context
      first nil

   !eval! *items*
 
   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj

   =goal>
       first =newgoal
       position first

   !push! =newgoal
)

(parameters high-first :r .95)


(p high-second
"
  IF the goal is to study words
     and there is no word in the second position
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context
      second nil

   !eval! *items*

   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj

   =goal>
       second =newgoal
       position first

   !push! =newgoal
)

(parameters high-second :r .95)


(p high-third
"
  IF the goal is to study words
     and there is no word in the third position
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context
      third nil

   !eval! *items*

   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj

   =goal>
       third =newgoal
       position first

   !push! =newgoal
)

(parameters high-third :r .95)


(p high-fourth
"
  IF the goal is to study words
     and there is no word in the fourth position
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context
      fourth nil

   !eval! *items*

   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj

   =goal>
      fourth =newgoal
      position first

   !push! =newgoal
)

(parameters high-fourth :r .95)


(p attend-first
"
  IF the goal is to study words
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context
 
   !eval! *items*

   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj

   =goal>
      first =newgoal
      position first

   !push! =newgoal
)

(parameters attend-first :r .9)


(p attend-second
"
  IF the goal is to study words
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context

   !eval! *items*

   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj

   =goal>
      second =newgoal
      position first

   !push! =newgoal
)

(parameters attend-second :r .9)


(p attend-third
"
  IF the goal is to study words
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context

   !eval! *items*

   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj
      context =context

   =goal>
      third =newgoal
      position first

   !push! =newgoal
)

(parameters attend-third :r .9)

(p attend-fourth
"
  IF the goal is to study words
     and there are items to study
     and a new word has been presented
  THEN create a memory token chunk
     mark the current goal with that
     chunk 
     mark the current goal to start rehearsal 
     with the first item
     and push the new chunk on the goal stack
"
   =goal>
      isa study-words
      context =context

   !eval! *items*

   !eval! (>= (actr-time) *stop-it*)
==>
   =newgoal>
      isa memory-token
      context =context
      name =obj

   =goal>
      fourth =newgoal
      position first

   !push! =newgoal
)

(parameters attend-fourth :r .9)


(p create-token
"
  IF the goal is a memory token
  THEN store the word in the goal
     and pop the goal
"
   =goal>
      isa memory-token
==>
   !bind! =name  (get-word-roberts)

   =goal>
      name =name

   !pop!
)

(parameters-fct 'create-token (list :effort *encode*))


(p rehearse-it 
"
  IF the goal is to rehearse an item
     and the item is a memory token
  THEN pop the goal
"
   =goal>
      isa rehearse
      target =token

   =token>
      isa memory-token
      name =name
==>
   !pop!
)

(parameters-fct 'rehearse-it (list :effort *rehearsal*))

(p skip-rehearsal
   =goal>
     isa rehearse
     target =token
==>
!pop!
)

(parameters skip-rehearsal :r .5)

(p rehearse-first
"
  IF the goal is to study words 
     and rehearse the first word
     and there is an item in the first position
     and the next word has not been presented
     yet
  THEN create a new goal to rehearse the 
     first item
     and mark the current goal to process the
     second item next
     and push the new goal
"
   =goal>
      isa study-words
      position first
      first =token

   !eval! (< (actr-time) *stop-it*)
==>
   =subgoal>
      isa rehearse
      target =token

   =goal>
      position second

   !push! =subgoal
)

(parameters rehearse-first :r .6)


(p rehearse-second
"
  IF the goal is to study words
     and rehearse the second word
     and there is an item in the second position
     and the next word has not been presented
     yet
  THEN create a new goal to rehearse the 
     second item
     and mark the current goal to process the
     third item next
     and push the new goal
"
   =goal>
      isa study-words
      position second
      second =token

   !eval! (< (actr-time) *stop-it*)
==>
   =subgoal>
      isa rehearse
      target =token

   =goal>
      position third

   !push! =subgoal
)

(parameters rehearse-second :r .6)


(p rehearse-third
"
  IF the goal is to study words
     and rehearse the third word
     and there is an item in the third position
     and the next word has not been presented
     yet
  THEN create a new goal to rehearse the 
     third item
     and mark the current goal to process the
     fourth item next
     and push the new goal
"
   =goal>
      isa study-words
      position third
      third =token

   !eval! (< (actr-time) *stop-it*)
==>
   =subgoal>
      isa rehearse
      target =token

   =goal>
      position fourth

   !push! =subgoal
)

(parameters rehearse-third :r .6)


(p rehearse-fourth
"
  IF the goal is to study words
     and rehearse the fourth word
     and there is an item in the fourth position
     and the next word has not been presented
     yet
  THEN create a new goal to rehearse the 
     fourth item
     and mark the current goal to next process the
     first item next
     and push the new goal
"
   =goal>
      isa study-words
      position fourth
      fourth =token

   !eval! (< (actr-time) *stop-it*)
==>
   =subgoal>
      isa rehearse
      target =token

   =goal>
      position first

   !push! =subgoal
)

(parameters rehearse-fourth :r .6)


(p skip-first
"
  IF the goal is to study words
     and rehearse the first word
     and the next word has not been presented yet
  THEN mark the goal to rehearse the second position next
"
   =goal>
      isa study-words
      position first

   !eval! (< (actr-time) *stop-it*)
==>
   =goal>
      position second
)

(parameters skip-first :r .3)


(p skip-second
"
  IF the goal is to study words
     and rehearse the second word
     and the next word has not been presented yet
  THEN mark the goal to rehearse the third position next
"
   =goal>
      isa study-words
      position second

   !eval! (< (actr-time) *stop-it*)
==>
   =goal>
      position third
)

(parameters skip-second :r .3)


(p skip-third
"
  IF the goal is to study words
     and rehearse the third word
     and the next word has not been presented yet
  THEN mark the goal to rehearse the fourth position next
"
   =goal>
      isa study-words
      position third

   !eval! (< (actr-time) *stop-it*)
==>
   =goal>
      position fourth
)

(parameters skip-third :r .3)


(p skip-fourth
"
  IF the goal is to study words
     and rehearse the fourth word
     and the next word has not been presented yet
  THEN mark the goal to rehearse the first position next
"
   =goal>
      isa study-words
      position fourth

   !eval! (< (actr-time) *stop-it*)
==>
   =goal>
      position first
)

(parameters skip-fourth :r .3)


(p wait
"
  IF the goal is to study words
     and no position is marked for rehearsal
     and the next word has not been presented yet
  THEN mark the goal to rehearse none of the positions
"
   =goal>
      isa study-words
      position nil

   !eval! (< (actr-time) *stop-it*)
==>
   =goal>
      position nil
)

(parameters wait :r .3 :effort .2)


(p start-recall
"
  IF the goal is to study words
     and it is time to start recalling
  THEN create a new goal to dump the
     words from the current goal
     and create a new goal to recall words
     focus on the recall words goal
     and then push the dump words goal
"
   =goal>
      isa study-words
      context =context
      first =first
      second =second
      third =third
      fourth =fourth
      position transfer
==>
   =newgoal1>
      isa dump-words
      first =first
      second =second
      third =third
      fourth =fourth
      position first
      context =context

   =newgoal2>
      isa recall-words
      context =context

   !focus-on! =newgoal2

   !push! =newgoal1
)


(p dump-it
"
  IF the goal is to output an item
     and that item is a memory token
  THEN mark the item as recalled
     and respond with the item
     and pop the goal
"
   =goal>
      isa output
      target =token

   =token>
      isa memory-token
      name =name
==>
   =token>
      status recalled

   !eval! (analyze-roberts =name)

   !pop!
)

(parameters-fct 'dump-it (list :a *rehearsal*))

(p skip-dump
   =goal>
     isa output
==>
!pop!
)

(parameters skip-dump :r .5)

(p dump-first
"
  IF the goal is to dump the word
     in the first position
     and there is an item in the first position
  THEN mark the goal to dump the second position next
     and create a new goal to output the first item
     and push the new goal
"
   =goal>
      isa dump-words
      position first 
      first =token
==>
   =goal>
      position second

   =subgoal>
      isa output
      target =token

   !push! =subgoal
)


(p dump-first-default
"
  IF the goal is to dump the word
     in the first position
  THEN mark the goal to dump the item in the 
     second position
"
   =goal>
      isa dump-words
      position first
==>
   =goal>
      position second
)

(parameters dump-first-default :r .5 )


(p dump-second
"
  IF the goal is to dump the word
     in the second position
     and there is an item in the second position
  THEN mark the goal to dump the third position next
     and create a new goal to output the second item
     and push the new goal
"
   =goal>
      isa dump-words
      position second 
      second =token
==>
   =goal>
      position third

   =subgoal>
      isa output
      target =token

   !push! =subgoal
)


(p dump-second-default
"
  IF the goal is to dump the word
     in the second position
  THEN mark the goal to dump the item in the 
     third position
"
   =goal>
      isa dump-words
      position second
==>
   =goal>
      position third
)

(parameters dump-second-default :r .5)


(p dump-third
"
  IF the goal is to dump the word
     in the third position
     and there is an item in the third position
  THEN mark the goal to dump the fourth position next
     and create a new goal to output the third item
     and push the new goal
"
   =goal>
      isa dump-words
      position third
      third =token
==>
   =goal>
      position fourth

   =subgoal>
      isa output
      target =token

   !push! =subgoal
)


(p dump-third-default
"
  IF the goal is to dump the word
     in the third position
  THEN mark the goal to dump the item in the 
     fourth position
"
   =goal>
      isa dump-words
      position third
==>
   =goal>
      position fourth
)

(parameters dump-third-default :r .5)


(p dump-fourth
"
  IF the goal is to dump the word
     in the fourth position
     and there is an item in the fourth position
  THEN  create a new goal to output the fourth item
     and focus on the new goal
"
   =goal>
      isa dump-words
      position fourth 
      fourth =token
==>
   =subgoal>
      isa output
      target =token

   !focus-on! =subgoal
)


(p dump-fourth-default
"
  IF the goal is to dump the word
     in the fourth position
  THEN pop the goal
"
   =goal>
      isa dump-words
      position fourth
      context =context
==>
   !pop!
)

(parameters dump-fourth-default :r .5)


(p recall-a-word
"
  IF the goal is to recall words
     and a memory token can be recalled
     that has not been recalled previously,
     and was in the current context
  THEN mark the item as recalled
     and respond with the word
"
   =goal>
      isa recall-words
      context =context

   =token>
      isa memory-token
      status nil
      name =name
      context =context
==>
   =token>
      status recalled

   !eval! (analyze-roberts =name)
)

(parameters-fct 'recall-a-word  (list :effort *respond*))


(p stop-recall
"
  IF the goal is to recall words
  THEN pop the goal
"
   =goal>
      isa recall-words
==>
   !pop!
)

(parameters stop-recall :r .25)