Phillip Trelford's Array

POKE 36879,255

Silverlife

Back in February Jon Harrop published an implementation of John Conway’s Game of Life in 32 lines of F# using WPF. I’ve managed to increase Jon’s example to a massive 50 lines but at the same time get it running in Silverlight. If you have Silverlight 4 installed you can click in the box below to kick start life.


Jon’s original code for calculating life:

module Game =
    let count (a: _ [,]) x y =
        let m, n = a.GetLength 0, a.GetLength 1
        let mutable c = 0
        for x in x-1..x+1 do
            for y in y-1..y+1 do
                if x>=0 && x<m && y>=0 && y<n && a.[x, y] then
                    c <- c + 1
        if a.[x, y] then c-1 else c
    let rule (a: _ [,]) x y =
        match a.[x, y], count a x y with
        | true, (2 | 3) | false, 3 -> true
        | _ -> false

The Silverlight Control, containing a WriteableBitmap updated from an F# Async Workflow:

type GameControl(n) as control =
    inherit System.Windows.Controls.UserControl()
    let game =
        let rand = System.Random()
        Array2D.init n n (fun _ _ -> rand.Next 2 = 0) |> ref
    let update _ = Game.rule !game |> Array2D.init n n
    let bitmap = System.Windows.Media.Imaging.WriteableBitmap(n,n)
    do  control.Content <- System.Windows.Controls.Image(Source=bitmap)
    let render () =
        let pixels = bitmap.Pixels
        let black, white = 0xff000000, 0xffffffff
        for x in 0..n-1 do
            for y in 0..n-1 do
                pixels.[x+y*n] <- 
                    if (!game).[x, y] then white else black
    do  for i = 1 to 3 do game:= update() done; render ()
    do  async {
        use handle = new System.Threading.AutoResetEvent(false)
        do! control.MouseLeftButtonUp |> Async.AwaitEvent |> Async.Ignore
        do! Async.SwitchToThreadPool ()
        while true do
            game := update ()
            bitmap.Dispatcher.BeginInvoke(fun _ -> 
                render()
                bitmap.Invalidate()
                handle.Set() |> ignore
            ) |> ignore
            do! Async.AwaitWaitHandle handle |> Async.Ignore
            handle.Reset() |> ignore
        } |> Async.StartImmediate

Application startup:

type App() as app =
    inherit System.Windows.Application()
    do  app.Startup.Add(fun _ -> app.RootVisual <- GameControl(256))

Resources:


Source code: GameOfLife.zip (2.38 kb)

Comments (1) -

  • Art Scott

    4/17/2013 8:23:16 PM |

    Hi Phil. Hope all's well.
    Playing with RayTrace; reviewed Jon's F#J article, circa 2011 -- Real-time ray tracing in Silverlight.
    It uses asynchronous workflows and a MailboxProcessor.
    FWIW
    My issues is  
    let bitmap = System.Windows.Media.Imaging.WriteableBitmap(n,n)
    seems to not be working ... with your Life version, or Jon's RT. Maybe I'm not keeping up with framework changes? Or cockpit error?
    Thanks. PHL OOE Art

Pingbacks and trackbacks (2)+

Comments are closed