           new-list)))
     ))
 
-
-;; -----------------------------------------
-;; GAME LOOP
-;; -----------------------------------------
-
-(defn- handle-ai! []
-  (let [ai-algo (get @ai-players @current-player)
-        move (ai-algo @game @current-player)]
-    (update-game! play-move move)))
+(defn- handle-game-event!
+  [msg]
+  (case msg
+    :new-game (swap! app-state assoc-in [:games] (list (new-game)))
+    :restart (swap! app-state update-in [:games] #(take-last 1 %))
+    :undo (cancel-last-move!)
+    ))
 
 (defn start-game-loop
   "Manage transitions between player moves, ai moves, and generic game events"

(def ai-players (reaction (get-in @game [:ai-players])))
(def end-of-game (reaction (nil? @current-player)))

(defn update-game! [f & args]
  (swap! app-state update-in [:games] conj (apply f @game args)))

(defn new-game! []
  (swap! app-state assoc-in [:games] (list (new-game))))

(defn is-ai? [player]
  (contains? @ai-players player))

(defn restart-game! []
  (swap! app-state update-in [:games] #(take-last 1 %)))

(defn cancel-last-move! []
  (swap! app-state update-in [:games]

        is-human-xf (fn [_] (not (is-ai? @current-player)))
        is-ai-xf (fn [_] (is-ai? @current-player))
        ai-events (chan 1 (comp (filter game-on-xf) (filter is-ai-xf)))
        player-events (chan 1 (comp (filter game-on-xf) (filter is-human-xf)))
        game-events (chan 1)]
    
    (go
      (while true
        (alt!
          game-events ([msg] (handle-game-event! msg))
          player-events ([coord] (update-game! play-move coord))
          ai-events ([msg] (when (= msg :ai-play) (handle-ai!)))
          (async/timeout ai-move-delay) ([_] (put! ai-events :ai-play))
          )))
    
    {:player-events player-events
     :game-events game-events}))

(defonce game-loop (start-game-loop))

(def send-player-event!
  #(put! (game-loop :player-events) %))

(def send-game-event!
  #(put! (game-loop :game-events) %))


;; -----------------------------------------
