open System
open System.Windows
open System.Windows.Media.Imaging
let rec skipPrevious p c i =
match p,i with
| ']'::t, i -> skipPrevious t (']'::c) (i + 1)
| '['::t, 0 -> t, '['::c
| '['::t, i -> skipPrevious t ('['::c) (i - 1)
| h::t, i -> skipPrevious t (h::c) i
let rec skipNext p c i =
match c,i with
| '['::t, i -> skipNext ('['::p) t (i + 1)
| ']'::t, 0 -> ']'::p, t
| ']'::t, i -> skipNext (']'::p) t (i - 1)
| h::t, i -> skipNext (h::p) t i
[<STAThread>]
[<EntryPoint>]
let main argv =
let code = "*
[[s*en]
sw[w]enn
[[e]w*ssss*nnnnw[w]ess[e]*[w]enn]
ssss[*nnnn*essss]
nnnnw[w]e
ss]"
let width = 1000
let height = 500
let image = Controls.Image(Stretch=Media.Stretch.Uniform)
let format = Media.PixelFormats.Gray2
let pixel = Array.create (width*height) 0uy
let data:bool[,] = Array2D.zeroCreate height width
let mutable x_ = 0
let mutable y_ = 0
let mutable pn_ = [], code.ToCharArray() |> Array.toList
let rec fxx x y = function
| (_, []) -> ()
| (p, h::t) when h = 'n' -> fxx ((x + height - 1) % height) y (h::p, t)
| (p, h::t) when h = 'e' -> fxx x ((y + 1) % width) (h::p, t)
| (p, h::t) when h = 's' -> fxx ((x + 1) % height) y (h::p, t)
| (p, h::t) when h = 'w' -> fxx x ((y + width - 1) % width) (h::p, t)
| (p, h::t) when h = '*' ->
data.[x,y] <- not data.[x,y]
data |> Seq.cast<bool> |> Seq.iteri (fun i x -> pixel.[i] <- if x then 255uy else 0uy)
image.Source <- BitmapSource.Create(width, height, 1.0, 1.0, format, null, pixel, width)
x_ <- x
y_ <- y
pn_ <- h::p, t
| (p, h::t) when h = '[' && data.[x,y] -> fxx x y (h::p, t)
| (p, h::t) when h = '[' -> fxx x y (skipNext (h::p) t 0)
| (p, h::t) when h = ']' -> fxx x y (skipPrevious p (h::t) 0)
| (p, h::t) -> fxx x y (h::p, t)
Media.CompositionTarget.Rendering.Add (fun _ -> fxx x_ y_ pn_)
Window(Content=image, Title="Paintfuck") |> (Application()).Run |> ignore
0