     GL_DEPTH_TEST glEnable
     GL_TEXTURE_2D glEnable
     GL_VERTEX_ARRAY glEnableClientState
-    PLAYER-START-LOCATION 0.0 0.0 { 0.0 0.0 0.0 } { 1.0 1.0 1.0 } player boa >>player
+    <player> >>player
+    V{ } clone >>history
     <perlin-noise-table> 0.01 0.01 <scale> { 512 512 } perlin-noise-image
     [ >>sky-image ] keep
     make-texture [ set-texture-parameters ] keep >>sky-texture

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

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

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

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

TUPLE: player
    location yaw pitch velocity velocity-modifier
    reverse-time ;

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

: <player> ( -- player )
    player new
        PLAYER-START-LOCATION >>location
        0.0 >>yaw
        0.0 >>pitch
        { 0.0 0.0 0.0 } >>velocity
        VELOCITY-MODIFIER-NORMAL >>velocity-modifier ;

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