anchor.diff:      type Input = Move of Dir | Set
       
       let directions = Map.ofList [ Left, (fun v -> v - V3i.IOO); Right, (fun v -> v + V3i.IOO); Forward, (fun v -> v + V3i.OIO); Backward, (fun v -> v - V3i.OIO); Up, (fun v -> v + V3i.OOI); Down, (fun v -> v - V3i.OOI) ]
  +
  +    let flipPlayer (g : GameState) =
  +        match g.player with
  +         | A -> { g with player = B }
  +         | B -> { g with player = A }
  +
  +    let visualizeHistory = GitVis.visualizeHistory "history.dgml"
  +
       let processInput (g : GameState) (i : Input) =
           let c = [
               match i with
                | Move d -> 
                   let dir = Map.find d directions
                   match g.player with 
  -                 | A -> yield PMod.modify (GameState.mapCursor dir) g.stateA 
  -                 | B -> yield PMod.modify (GameState.mapCursor dir) g.stateB
  -             | _ -> ()
  +                 | A -> yield PMod.modify (GameState.mapCursor dir) g.stateA, "a moved"
  +                 | B -> yield PMod.modify (GameState.mapCursor dir) g.stateB, "b moved"
  +             | Set ->
  +                let (x,y,z),msg = 
  +                    match g.player with
  +                      | A -> g.stateA.Value.cursor |> V3i.toTup, sprintf "A set on %A" g.stateA.Value.cursor
  +                      | B -> g.stateB.Value.cursor |> V3i.toTup, sprintf "B set on %A" g.stateA.Value.cursor
  +                yield PMod.change (Array3D.get g.arr x y z) (X g.player),msg
           ]
  -        for c in c do git.apply c
  -        git.commit "blubber"
  -        g
  +        for (a,msg) in c do git.apply a
  +        let msg = c |> Seq.toArray |> Array.map snd |> String.Concat
  +        git.commit (sprintf "game: %s" msg)
  +        match i with 
  +            | Set -> visualizeHistory git.History  |> ignore 
  +            | _ -> ()
  +        if i = Set then flipPlayer g else g
   
       let mutable s = GameState.empty
   
  -    win.Keyboard.KeyDown(Keys.Up).Values.Subscribe(fun () -> 
  -        s <- processInput s (Move Up)
  +    let keyBindings =
  +        [ Keys.Up,    Move Up
  +          Keys.Down,  Move Down 
  +          Keys.Right, Move Right 
  +          Keys.Left,  Move Left 
  +          Keys.F,     Move Backward 
  +          Keys.R,     Move Forward 
  +          Keys.Space, Set
  +        ] 
  +
  +    for (k,a) in keyBindings do
  +        win.Keyboard.KeyDown(k).Values.Subscribe(fun () -> 
  +            s <- processInput s a
  +        ) |> ignore
  +
  +    win.Keyboard.KeyDown(Keys.Z).Values.Subscribe(fun () -> 
  +        printfn "undo"
       ) |> ignore
  -    win.Keyboard.KeyDown(Keys.Down).Values.Subscribe(fun () -> 
  -        s <- processInput s (Move Down)
  -    ) |> ignore
  -    win.Keyboard.KeyDown(Keys.Right).Values.Subscribe(fun () -> 
  -        s <- processInput s (Move Right)
  -    ) |> ignore
  -    win.Keyboard.KeyDown(Keys.Left).Values.Subscribe(fun () -> 
  -        s <- processInput s (Move Left)
  -    ) |> ignore
  -
   
       let cubeSg = Helpers.wireBox C4b.White Box3d.Unit |> Sg.ofIndexedGeometry
       let cube c = Helpers.box c Box3d.Unit |> Sg.ofIndexedGeometry
  +    let markA = 
  +        Sphere.solidSphere C4b.Green 5 |> Sg.trafo (Mod.constant <| Trafo3d.Translation(0.5,0.5,0.5) * Trafo3d.Scale 0.5)
  +    let markB = cube C4b.Red
   
       let boxes = 
  -        [| for x in 0 .. 3 do
  -            for y in 0 .. 3 do
  -              for z in 0 .. 3 do
  -                let t = Trafo3d.Translation(float x ,float y ,float z) |> Mod.constant
  -                yield Sg.trafo t cubeSg |] |> Sg.group
  +        [|
  +            for x in 0 .. 3 do
  +                for y in 0 .. 3 do
  +                    for z in 0 .. 3 do
  +                        let t = Trafo3d.Translation(float x ,float y ,float z) |> Mod.constant
  +                        yield Array3D.get s.arr x y z
  +                                |> Mod.map (fun n ->
  +                                        match n with 
  +                                         | X p -> match p with
  +                                                    | A -> Sg.trafo t markA
  +                                                    | b -> Sg.trafo t markB
  +                                         | O -> Sg.trafo t cubeSg
  +                                    ) 
  +                                |> Sg.dynamic
  +        |] |> Sg.group
   
       let cursor = 
           let toTrafo c = c.cursor |> V3d.op_Explicit |> Trafo3d.Translation
           Sg.group [ Sg.trafo (s.stateA |> Mod.map toTrafo) (cube C4b.Red)
  -                   Sg.trafo (s.stateA |> Mod.map toTrafo) (cube C4b.Red) ]
  +                   Sg.trafo (s.stateB |> Mod.map toTrafo) (cube C4b.Red) ]
   
       let sg =
           boxes |> Sg.effect [
                   DefaultSurfaces.trafo |> toEffect                   // compose shaders by using FShade composition.
                   DefaultSurfaces.constantColor C4f.Red |> toEffect   // use standard trafo + map a constant color to each fragment
  -                Shaders.simpleLighting |> toEffect
  +                DefaultSurfaces.simpleLighting |> toEffect
                   ]
               |> Sg.andAlso cursor 
  -            |> Sg.andAlso (Sphere.solidSphere C4b.Gray 5 |> Sg.effect [ DefaultSurfaces.trafo |> toEffect; Shaders.simpleLighting |> toEffect ])
               |> Sg.viewTrafo (viewTrafo   () |> Mod.map CameraView.viewTrafo )
               |> Sg.projTrafo (perspective () |> Mod.map Frustum.projTrafo    )
   
  
positive.code: 
  module TicTacToe = 
  
      module Shaders = 
          open FShade
          open DefaultSurfaces
  
          let simpleLighting (v : Vertex) =
              fragment {
                  let n = v.n |> Vec.normalize
                  let c = uniform.CameraLocation - v.wp.XYZ |> Vec.normalize
  
                  let ambient = 0.2
                  let diffuse = Vec.dot c n |> abs
  
                  let l = ambient + (1.0 - ambient) * diffuse
  
                  return V4d(v.c.XYZ * diffuse, v.c.W)
              }
  
      Aardvark.Rendering.Interactive.FsiSetup.init (Path.combine [__SOURCE_DIRECTORY__; ".."; ".."; ".."; "bin";"Debug"])
  
  
      open Aardvark.Base.Incremental.Git
  
      let git = Aardvark.Base.Incremental.Git.init ()
  
      module PMod =
          let value (p : pmod<_>) = p.Value
          let modify f p =
              PMod.change p (f (value p))
  
      type Tick = X | O
      type Player = A | B
      type PlayerState = { cursor : V3i }
      type GameState = 
          { 
  
negative.code: 
      [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
      module GameState = 
          let mapCursor f { cursor = cursor } = 
              let c : V3i = f cursor
              printfn "map to: %A" c
              { cursor = V3i(clamp 0 3 c.X, clamp 0 3 c.Y, clamp 0 3 c.Z) }
          let empty = { 
              arr = Array3D.init 4 4 4 (fun x y z -> git.pmod (sprintf "%A" (x,y,z)) O)
              player = A
  