       grid
       (g/link-cells grid cell (rand-nth neighbors)))))
 
-(s/defn maze-binary-tree [grid :- g/Grid result-chan]
-  (go-loop [grid (assoc grid :algorithm-name "binary-tree")
-            [coord & coords] (g/grid-coords grid)]
-    (if-not coord
-      (do
-        (when result-chan (async/close! result-chan))
-        grid)
-      (do
-        (when (and result-chan (g/changed? grid))
-          (async/>! result-chan grid))
-        (recur (binary-tree-step (g/begin-step grid) coord) coords)))))
+(s/defn maze-binary-tree
+  ([grid :- g/Grid] (maze-binary-tree grid nil))
+  ([grid :- g/Grid result-chan]
+    (go-loop [grid (assoc grid :algorithm-name "binary-tree")
+              [coord & coords] (g/grid-coords grid)]
+             (if-not coord
+               (do
+                 (when result-chan (async/close! result-chan))
+                 grid)
+               (do
+                 (when (and result-chan (g/changed? grid))
+                   (async/>! result-chan grid))
+                 (recur (binary-tree-step (g/begin-step grid) coord) coords))))))
 
 (defn sidewinder-end-run? [cell]
   (let [on-east-side? (not (:east cell))

        [(g/link-cells grid current-cell neighbor)
         neighbor]))))

(s/defn maze-hunt-and-kill [grid :- g/Grid result-chan]
  (go-loop [grid (assoc grid :algorithm-name "hunt-and-kill")
            current-coord (g/random-coord grid)]
      (when (and result-chan (g/changed? grid))
        (async/>! result-chan grid))
    (let [[new-grid next-coord] (hunt-and-kill-step (g/begin-step grid) current-coord)]
      (if-not next-coord
        (do
          (when result-chan (async/close! result-chan))
          new-grid)
        (recur new-grid next-coord)))))

(s/defn find-distances :- g/Distances
  [grid :- g/Grid
   start :- g/CellPosition
   result-chan]
  (go-loop [distances {start 0 :origin start}
            current start
            frontier #?(:clj PersistentQueue/EMPTY
                        :cljs #queue [])]
    (when result-chan
      (async/>! result-chan distances))
    (let [cell (g/grid-cell grid current)
          current-distance (distances current)
          links (remove #(contains? distances %) (:links cell))
          next-frontier (apply conj frontier links)]
      (if (empty? next-frontier)
        (do
          (when result-chan (async/close! result-chan))
          (assoc distances :max current-distance :max-coord current))
        (recur (if (empty? links)
                 distances
                 (apply assoc distances
                        (mapcat #(vector % (inc current-distance)) links)))
               (peek next-frontier)
               (pop next-frontier))))))

(s/defn find-path :- g/Distances
  [grid :- g/Grid

                   (g/link-cells grid cell (:east cell)))]
    [new-grid (if end-run? [] run)]))

(s/defn maze-sidewinder
  ([grid :- g/Grid] (maze-sidewinder grid nil))
  ([grid :- g/Grid result-chan]
    (go-loop [grid (assoc grid :algorithm-name "sidewinder")
              [coord & coords] (g/grid-coords grid)
              current-run [coord]]
             (when (and result-chan (g/changed? grid))
               (async/>! result-chan grid))
      (let [[new-grid processed-run] (sidewinder-step (g/begin-step grid) coord current-run)]
        (if (empty? coords)
          (do
            (when result-chan (async/close! result-chan))
            new-grid)
          (recur new-grid
                 coords
                 (conj processed-run (first coords))))))))

(s/defn maze-aldous-broder
  ([grid :- g/Grid] (maze-aldous-broder grid nil))
  ([grid :- g/Grid result-chan]
    (go-loop [grid (assoc grid :algorithm-name "aldous-broder")
              current (g/random-coord grid)
              unvisited (dec (g/grid-size grid))]
             (when (and result-chan (g/changed? grid))
               (async/>! result-chan grid))
      (let [cell (g/grid-cell grid current)
            neighbor (rand-nth (g/cell-neighbors cell))
            neighbor-new? (empty? (:links (g/grid-cell grid neighbor)))]
        (if (= unvisited 0)
          (do
            (when result-chan (async/close! result-chan))
            grid)
          (recur (if neighbor-new?
                   (g/link-cells (g/begin-step grid) cell neighbor)
                   (g/begin-step grid))
                 neighbor
                 (if neighbor-new? (dec unvisited) unvisited)))))))

(defn wilsons-loop-erased-walk [grid start-coord unvisited]
  (let [unvisited-set (into #{} unvisited)]
