       (reset! timer-atom (System/currentTimeMillis))
       (swap! timing-map assoc step (+ current-time-for-step (- @timer-atom start-time))))))
 
+
+(defn process-generation
+  "Processes the generation, returning [new novelty archive, return val],
+   where new novelty archive will be nil if we are done."
+  [rand-gens pop-agents child-agents generation novelty-archive]
+  (r/new-generation! generation)
+  (println "Processing generation:" generation) (flush)
+  (population-translate-plush-to-push pop-agents @push-argmap)
+  (timer @push-argmap :reproduction)
+  (print "Computing errors... ") (flush)
+  (compute-errors pop-agents rand-gens @push-argmap)
+  (println "Done computing errors.") (flush)
+  (timer @push-argmap :fitness)
+  ;; calculate solution rates if necessary for historically-assessed hardness
+  (calculate-hah-solution-rates pop-agents @push-argmap)
+  ;; create global structure to support elite group lexicase selection
+  (when (= (:parent-selection @push-argmap) :elitegroup-lexicase)
+    (build-elitegroups pop-agents @push-argmap))
+  ;; calculate implicit fitness sharing fitness for population
+  (when (= (:total-error-method @push-argmap) :ifs)
+    (calculate-implicit-fitness-sharing pop-agents @push-argmap))
+  ;; calculate epsilons for epsilon lexicase selection
+  (when (= (:parent-selection @push-argmap) :epsilon-lexicase)
+    (calculate-epsilons-for-epsilon-lexicase pop-agents @push-argmap))
+  ;; calculate novelty when necessary
+  (when (or (= (:parent-selection @push-argmap) :novelty-search)
+            (some #{:novelty} (:meta-error-categories @push-argmap)))
+    (calculate-novelty pop-agents novelty-archive @push-argmap))
+  (timer @push-argmap :other)
+  ;; report and check for success
+  (let [[outcome best] (report-and-check-for-success (vec (doall (map deref pop-agents)))
+                                                     generation @push-argmap)]
+    (r/generation-data! [:outcome] outcome)
+    (r/end-generation!)
+    (cond (= outcome :failure) (do (printf "\nFAILURE\n")
+                                   (flush)
+                                   [nil
+                                    (when (:return-simplified-on-failure @push-argmap)
+                                      (auto-simplify best
+                                                     (:error-function @push-argmap)
+                                                     (:final-report-simplifications @push-argmap)
+                                                     true
+                                                     500))])
+          (= outcome :continue) (let [next-novelty-archive
+                                      (list-concat novelty-archive
+                                                   (select-individuals-for-novelty-archive
+                                                     (map deref pop-agents)
+                                                     @push-argmap))]
+                                  (timer @push-argmap :report)
+                                  (println "\nProducing offspring...") (flush)
+                                  (produce-new-offspring pop-agents
+                                                         child-agents
+                                                         rand-gens
+                                                         @push-argmap)
+                                  (println "Installing next generation...") (flush)
+                                  (install-next-generation pop-agents child-agents @push-argmap)
+                                  [next-novelty-archive nil])
+          :else [nil (final-report generation best @push-argmap)])))
+
+
+
 (defn pushgp
   "The top-level routine of pushgp."
   ([] (pushgp '()))
   ([args]
-    (reset! timer-atom (System/currentTimeMillis))
-    (load-push-argmap args)
-    (when (some? (:record-host @push-argmap))
-      (r/host! (str (:record-host @push-argmap))))
-    (random/with-rng (random/make-mersennetwister-rng (:random-seed @push-argmap))
-      ;; set globals from parameters
-      (reset-globals)
-      (initial-report @push-argmap) ;; Print the inital report
-      (r/uuid! (:run-uuid @push-argmap))
-      (print-params (r/config-data! [:argmap] (dissoc @push-argmap :run-uuid)))
-      (check-genetic-operator-probabilities-add-to-one @push-argmap)
-      (timer @push-argmap :initialization)
-      (when (:print-timings @push-argmap)
-        (r/config-data! [:initialization-ms] (:initialization @timer-atom)))
-      (println "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")
-      (println "\nGenerating initial population...") (flush)
-      (let [pop-agents (make-pop-agents @push-argmap)
-            child-agents (make-child-agents @push-argmap)
-            {:keys [rand-gens random-seeds]} (make-rng @push-argmap)]
-        ;(print "Random seeds: ")
-        ;(doseq [seed random-seeds] (print " " seed))
-        ;(println)
-        ;; Main loop
-        (loop [generation 0
-               novelty-archive '()]
-          (r/new-generation! generation)
-          (println "Processing generation:" generation) (flush)
-          (population-translate-plush-to-push pop-agents @push-argmap)
-          (timer @push-argmap :reproduction)
-          (print "Computing errors... ") (flush)
-          (compute-errors pop-agents rand-gens @push-argmap)
-          (println "Done computing errors.") (flush)
-          (timer @push-argmap :fitness)
-          ;; calculate solution rates if necessary for historically-assessed hardness
-          (calculate-hah-solution-rates pop-agents @push-argmap)
-          ;; create global structure to support elite group lexicase selection
-          (when (= (:parent-selection @push-argmap) :elitegroup-lexicase)
-            (build-elitegroups pop-agents @push-argmap))
-          ;; calculate implicit fitness sharing fitness for population
-          (when (= (:total-error-method @push-argmap) :ifs)
-            (calculate-implicit-fitness-sharing pop-agents @push-argmap))
-          ;; calculate epsilons for epsilon lexicase selection
-          (when (= (:parent-selection @push-argmap) :epsilon-lexicase)
-            (calculate-epsilons-for-epsilon-lexicase pop-agents @push-argmap))
-          ;; calculate novelty when necessary
-          (when (or (= (:parent-selection @push-argmap) :novelty-search)
-                    (some #{:novelty} (:meta-error-categories @push-argmap)))
-            (calculate-novelty pop-agents novelty-archive @push-argmap))
-          (timer @push-argmap :other)
-          ;; report and check for success
-          (let [[outcome best] (report-and-check-for-success (vec (doall (map deref pop-agents)))
-                                                             generation @push-argmap)]
-            (r/generation-data! [:outcome] outcome)
-            (r/end-generation!)
-            (cond (= outcome :failure) (do (printf "\nFAILURE\n")
-                                         (if (:return-simplified-on-failure @push-argmap)
-                                           (auto-simplify best 
-                                                          (:error-function @push-argmap) 
-                                                          (:final-report-simplifications @push-argmap) 
-                                                          true 
-                                                          500)
-                                           (flush)))
-                  (= outcome :continue) (let [next-novelty-archive 
-                                              (list-concat novelty-archive
-                                                           (select-individuals-for-novelty-archive
-                                                             (map deref pop-agents)
-                                                             @push-argmap))]
-                                          (timer @push-argmap :report)
-                                          (println "\nProducing offspring...") (flush)
-                                          (produce-new-offspring pop-agents 
-                                                                 child-agents 
-                                                                 rand-gens 
-                                                                 @push-argmap)
-                                          (println "Installing next generation...") (flush)
-                                          (install-next-generation pop-agents child-agents @push-argmap)
-                                          (recur (inc generation)
-                                                 next-novelty-archive))
-                  :else  (final-report generation best @push-argmap))))))))
-
+   (reset! timer-atom (System/currentTimeMillis))
+   (load-push-argmap args)
+   (when (some? (:record-host @push-argmap))
+     (r/host! (str (:record-host @push-argmap))))
+   (random/with-rng (random/make-mersennetwister-rng (:random-seed @push-argmap))
+     ;; set globals from parameters
+     (reset-globals)
+     (initial-report @push-argmap) ;; Print the inital report
+     (r/uuid! (:run-uuid @push-argmap))
+     (print-params (r/config-data! [:argmap] (dissoc @push-argmap :run-uuid)))
+     (check-genetic-operator-probabilities-add-to-one @push-argmap)
+     (timer @push-argmap :initialization)
+     (when (:print-timings @push-argmap)
+       (r/config-data! [:initialization-ms] (:initialization @timer-atom)))
+     (println "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")
+     (println "\nGenerating initial population...") (flush)
+     (let [pop-agents (make-pop-agents @push-argmap)
+           child-agents (make-child-agents @push-argmap)
+           {:keys [rand-gens]} (make-rng @push-argmap)]
+       (loop [generation 0
+              novelty-archive '()]
+         (let [[next-novelty-archive return-val]
+               (process-generation rand-gens pop-agents child-agents
+                                   generation novelty-archive)]
+           (if (nil? next-novelty-archive)
+             return-val
+             (recur (inc generation) next-novelty-archive))))))))

  (let [population-agents (vec (repeatedly population-size
                                           #(make-individual
                                              :genome (strip-random-insertion-flags
                                                        (random-plush-genome 
                                                          max-genome-size-in-initial-program
                                                          atom-generators
                                                          argmap))

    (reset! max-age (apply max ages))
    (dotimes [i population-size]
      ((if use-single-thread swap! send)
       (nth child-agents i)
       breed
       i (nth rand-gens i) pop @push-argmap)))
  (when-not use-single-thread (apply await child-agents))) ;; SYNCHRONIZE

(defn install-next-generation
  [pop-agents child-agents {:keys [population-size use-single-thread]}]
  (dotimes [i population-size]
    ((if use-single-thread swap! send)
     (nth pop-agents i) (fn [av] (deref (nth child-agents i)))))
  (when-not use-single-thread (apply await pop-agents))) ;; SYNCHRONIZE

(defn check-genetic-operator-probabilities-add-to-one
