anchor.diff:  
       [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
       module GameState = 
  -        let mapCursor f { cursor = cursor } = { cursor = f cursor }
  +        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
  
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:     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, "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 (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
  
      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
  
      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 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.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
                  DefaultSurfaces.simpleLighting |> toEffect
                  ]
              |> Sg.andAlso cursor 
              |> Sg.viewTrafo (viewTrafo   () |> Mod.map CameraView.viewTrafo )
              |> Sg.projTrafo (perspective () |> Mod.map Frustum.projTrafo    )
  
  