 
   (go
     (loop []
-      (let [cs [(timeout (get-level-speed (:level @state))) 
-                pause-grav]                 ; channels to listen to (timeout, pause)
+      (let [soft-speed 25
+            level-speed (get-level-speed (:level @state))
+            speed (if (:soft-drop @state)
+                    (min soft-speed level-speed)
+                    level-speed)
+
+            cs [(timeout speed) pause-grav] ; channels to listen to (timeout, pause)
             [_ c] (alts! cs)]               ; get the first channel to receive a value
         (if (= pause-grav c)                ; if "pause" received, wait for "resume"
           (<! resume-grav)
-          (try-gravity!))
+          (apply-gravity!))
         (recur)))))
 
 ;;------------------------------------------------------------
 ;; Input-driven STATE CHANGES
 ;;------------------------------------------------------------
-
-(def key-codes {:left 37
-                :up 38
-                :right 39
-                :down 40
-                :space 32
-                :shift 16})
 
 (defn try-move!
   "Try moving the current piece to the given offset."

                  :score 0
                  :level 0
                  :level-lines 0
                  :total-lines 0}))

; required for pausing/resuming the gravity routine
(def pause-grav (chan))

        (try-spawn-piece!))
      (try-spawn-piece!))))

(defn apply-gravity!
  "Move current piece down 1 if possible, else lock the piece."
  []
  (let [piece (:piece @state)
