                   (<! (timeout 100))
                   (when-not (ended? board)
                     (recur board :wait)))
-      :wait (if-let [board' (handle-move board (<! keys))]
+      :wait (if-let [board' (handle-move board (build-rand-tile) (<! keys))]
               (recur board' :render)
               (recur board :wait)))))

  "Performs a new move on board in the given direction after removing transient
   data from the tiles (:new and :src keys). Returns the new board, or nil when
   no change occurs."
  [board direction]
  (move build-tile (map #(dissoc % :new :src) board) direction))

;; The player will make moves by pressing the arrow keys. Instead of registering
;; callbacks to handle keyup events, we’ll convert them to a core.async’s


(defn move
  "Returns a new board that results from sliding and synthesizing the tiles of
   board in the given direction and adding a tile. However, nil is returned if
   sliding and synthesizing the tiles doesn't change the original board."
  [tile board direction]
  (let [board' (slide-synth board direction)]
    (when (not= board board') (add-tile tile board'))))

;; Sadly, moves can’t be made indefinitely. As stated in the 'Tile synthesis'
;; section, the player wins the game when a tile that is not able to be merged
