 :: handle-input ( world -- )
     world player>> :> player
     read-keyboard keys>> :> keys
-    key-left-shift keys nth [
-        { 2.0 1.0 2.0 } player (>>velocity-modifier)
-    ] when
-    key-left-shift keys nth [
-        { 1.0 1.0 1.0 } player (>>velocity-modifier)
-    ] unless
+
+    key-left-shift keys nth
+    VELOCITY-MODIFIER-FAST VELOCITY-MODIFIER-NORMAL ? player (>>velocity-modifier)
+
+    {
+        [ key-1 keys nth 1  f ? ]
+        [ key-2 keys nth 2  f ? ]
+        [ key-3 keys nth 3  f ? ]
+        [ key-4 keys nth 4  f ? ]
+        [ key-5 keys nth 10000 f ? ]
+    } 0|| player (>>reverse-time)
 
     key-w keys nth [ player walk-forward ] when 
     key-s keys nth [ player walk-backward ] when 

CONSTANT: terrain-vertex-row-length $[ 512 1 + 2 * ]

TUPLE: player
    location yaw pitch velocity velocity-modifier ;

TUPLE: terrain-world < game-world
    player
    sky-image sky-texture sky-program
    terrain terrain-segment terrain-texture terrain-program
    terrain-vertex-buffer ;

M: terrain-world tick-length
    drop 1000 30 /i ;

: scaled-velocity ( player -- velocity )
    [ velocity>> ] [ velocity-modifier>> ] bi v* ;

: save-history ( world player -- )
    clone swap history>> push ;

:: tick-player-reverse ( world player -- )
    player reverse-time>> :> reverse-time
    world history>> :> history
    history length 0 > [
        history length reverse-time 1 - - 1 max history set-length
        history pop world (>>player)
    ] when ;

: tick-player-forward ( world player -- )
    2dup save-history
    [ apply-friction apply-gravity ] change-velocity
    dup scaled-velocity [ v+ [ terrain-segment>> ] dip collide ] curry with change-location
    drop ;

: tick-player ( world player -- )
    dup reverse-time>> [
        tick-player-reverse
    ] [
        tick-player-forward
    ] if ;

M: terrain-world tick*
    [ dup focused?>> [ handle-input ] [ drop ] if ]
