Phillip Trelford's Array

POKE 36879,255

Pacman Tiles

Back in January I built a sample Pacman maze script in F# to use at a Pacman Kata evening with the F#unctional Londoners group. Coincidentally there’s another Coding Kata this Thursday 26th July at Skills Matter. Anyway a couple of weeks ago I started playing with the sample again on the train to and from work, filling in some of the gameplay.

You can play the latest version with your cursor keys and 9 lives below:

(Right click to install game to desktop)

 
Windows 8

As the sample runs in Silverlight I thought I’d also try it out on it’s cousin WinRT. WinRT lets you build Metro apps on Windows 8. The transition code wise has been pretty straight forward and I now have a tile for the game appearing on my Windows 8 start page:

One click: From Metro tile to video game

 

WinRT is yet another XAML based framework, and is very similar to Silverlight and WPF. One of the few differences I have encountered has been the namespaces the classes are in. For example in Silverlight the Canvas class is in the System.Windows.Controls namespace and in WinRT it is in Windows.UI.Xaml.Controls namespace. It is possible to target both WinRT and Silverlight from the same source code using conditional directives:

#if NETFX_CORE
using Windows.UI.Xaml.Controls;
#else
using System.Windows.Controls;
#endif

 

Multi-targeting

Multi-targeting Silverlight and WinRT is the route I decided to go down which allowed me to develop the game on my laptop running Windows 7 with Visual Studio 2010. Then I periodically tested it out on a desktop box running the Windows 8 Preview Release using Visual Studio 2012. Visual Studio 2012 does run on Windows 7, however WinRT does not.

The WinRT version of the app is implemented in F# and C#. The game part is written in F# as a portable library and the plumbing in C#. There’s a great walkthrough on Creating a Portable F# Library over on MSDN which describes this direction in some detail.

Code Fragment

When the ghosts are eaten they need to return to the enclosure. I used a flood fill algorithm to mark the shortest route from anywhere in the maze back to the enclosure. The flood fill is started inside the enclosure, the fill number is incremented with each iteration of the fill, so that the shortest route is to follow the lowest number adjacent to the ghost’s current square:

module Algorithm =
    let flood canFill fill (x,y) =
        let rec f n = function
            | [] -> ()
            | ps ->
                let ps = ps |> List.filter canFill
                ps |> List.iter (fill n)
                ps |> List.collect (fun (x,y) -> 
                    [(x-1,y);(x+1,y);(x,y-1);(x,y+1)]
                )
                |> f (n+1)
        f 0 [(x,y)]
 
Full Source

The full source code to the game is publicly available on BitBucket:

A single file playable script version is also available on F# Snippets:

Developer Democracy

You decide what happens in the developer community. You can vote with your feet by choosing which conferences and user group meetings you can turn up at. You can also vote with your mouse and decide which talks you’d like to hear all the way through to the new features you’d like to see in developer products.

If you’re a .Net developer there are a lot of ways you can get involved with the community by voting with your feet and choosing which user group meetings you attend. These days you can vote for the talks you’d like to see at a conference through to new features for your IDE in the new version of Visual Studio,

Developer Developer Developer 10 (DDD10)

The DDD10 conference will be held at the Microsoft Campus in Reading (UK) on Saturday September 1st, you can vote for the talks you’d like to see (voting closes next week).

Here’s a few of my picks:

Note: this conference is free however you need to be quick when registration opens, the places are usually all taken in the first hour.

F#unctional Londoners Meetup Group

Like most user groups the the F#unctional Londoners let you suggest what meetings you’d like to see next, just let us know. The next meetup is a Coding Kata on Thursday 26th July at Skills Matter, hope to see you there!

User Voice

Over 1,000 votes have been cast for Full Support for F within MonoDevelop.

MonoDevelop is a .Net development environment that runs on Windows, Mac and Linux. The F# add-in for MonoDevelop (thanks Tomas Petricek) bring full support for F# with colour coding, intelllisense and tooltips.

Visual Studio

Again using User Voice, you can suggest and vote for features in Visual Studio

Here’s my suggestion for C# (the idea is taken from Java’s import keyword):

Support using for static classes, e.g. using static System.Math;

Allow the static keyword to be applied in a using namespace directive, e.g. using static System.Math; allowing static classes to be treated as namespaces and avoid having to fully qualify every method call, i.e. Math.Max becomes just Max

The most voted for suggestion for F# is Provide refactoring support for F# code.

Everyone gets 10 votes, why not have your say.

Resharper

For many .Net developers Resharper is the first add-in they install for Visual Studio (for me it’s VisualHG). ReSharper 7 promises an SDK that enables developing support for new languages.

Again you can vote: ReSharper support for F#

Thanks to everyone who has voted for this issue, we’re up to 59 votes now!

There are already a few Visual Studio add-ins for F# that support code indentation and  refactoring:

Here’s some more excellent suggestions for refactoring support in F# (via Twitter):

Phillip Trelford@ptrelford

@brandewinder compiling a list of key features for an F# R# plugin probably makes sense now. Rename, code navigation & test runner?

Mathias Brandewinder@brandewinder

.@ptrelford good list. Nonstandard R#, but I think an indentation guideline would be nice, too (exists separately already)

Mathias Brandewinder@brandewinder

.@7sharp9 good one on that list: remove/highlight dead code. cc@ptrelford @1tgr

Ben Taylor@bentayloruk

@ptrelford I like that list too. Rename is far and away the main one for me. Optimise "open"s & "add open" would be nice (like ns in C#).

Tim Robinson@1tgr

@ptrelford @brandewinder convert closure to object

Tim Robinson@1tgr

@ptrelford @brandewinder function call to pipeline, and vice versa

Tim Robinson@1tgr

@ptrelford @brandewinder curry/uncurry

Dave Thomas@7sharp9

@1tgr @ptrelford @brandewinder Maybe 'borrow' some of these:http://www.cs.kent.ac.uk/projects/refactor-fp/catalogue/

Make a difference

Get involved and have your say about what happens in your future, your opinions matter.

GOTO Copenhagen 2012 Conference

This week I had the please of attending GOTO Copenhagen - a 3 day developer conference covering a diverse range of topics.

Day 1

I started the day on the excellent Beyond the Microsoft Echo Chamber track taking in:

kmm-74127_green_prince_of_wales_front_largeMark demonstrated his open source project AutoFixture aimed at writing maintainable unit tests faster. Tobias described how Credit Suisse have been using F# to migrate large computations over from Excel, and created a minimal implementation live on stage. Glenn, a trilby hat fan, gave a flavour of Node.js, showing pre-built code running on Windows, Azure and Cloud9; socket.io looked particularly interesting.

Then I switched over to the Lean and Kanban case studies track for Jesper Boeg’s talk about Launching Kanban teams, and received a free Kanban book a the end, thanks!

Monday’s keynote was from Kasper Lund on the Dart programming language which I’d sum up as a programming language that runs in Chrome with “an unsurprising and familiar syntax” for Java and JavaScript programmers.

Day 2

The day started with a functional orientated keynote from Rich Hickey, author of Clojure, on The Value of Values.

CH20-BLK, 12/9/99, 12:48 PM,  8C, 1018x648 (1124+1536),  25%, better push6,  1/15, R705, G520, B595,

I managed to catch the first 30 minutes of Simon Brown’s very interesting presentation Master-builder; the original generalising specialist? But had to nip out to do a video interview with fellow bowler hat wearer Werner Schuster on F# and FP which should be available on InfoQ in around a month or so.

 

After lunch I caught a great talk on dandelions Master-builders have rich conceptual models of software design from George Fairbanks.

Then it was my chance to talk about Functional Architecture:

Code samples:

Day 3

Another day, another Rich Hickey talk, this time on Writing Datomic in Clojure.

However most of my day was spent on the Programming with the Stars track which involved solving a minimal Minesweeper Kata in Java, functional Java, F# and C. Interestingly only the F# and C pairs were able to complete the task in the allotted hour.

I paired with Mark Seeman on the F# session. We were able to complete the computational version of the task with 15 minutes to spare, so even had time to start building a UI.

 1: let compute (board : string) =
 2:     let options = System.StringSplitOptions.RemoveEmptyEntries
 3:     let board = board.Split([| "\n" |], options)
 4:     let count (x, y) =      
 5:         [-1, -1; 0, -1;  1, -1;
 6:          -1,  0;         1,  0;
 7:          -1,  1; 0,  1;  1,  1]
 8:          |> List.map (fun (x', y') -> x + x', y + y')
 9:          |> List.filter (fun (x, y) -> 
10:             x >= 0 && x < board.[y].Length && 
11:             y >= 0 && y < board.Length
12:          )
13:          |> List.sumBy (fun (x, y) ->
14:             if board.[y].[x] = '*'
15:             then 1 else 0
16:          )
17:     board |> Array.mapi (fun y line ->
18:         line.ToCharArray() |> Array.mapi (fun x c ->
19:             match c with
20:             | '*' -> '*'
21:             | '.' -> '0' + char (count(x, y))
22:             | _ -> invalidArg "c" "Boo hiss!"
23:         )
24:     )
25:     |> Array.map (fun chars -> System.String(chars))
26:     |> Array.reduce (+)
27: 
28: let input = "*...
29: ....
30: .*..
31: ...."
val compute : string -> System.String

Full name: Snippet.compute
val board : string

  type: string
  implements: System.IComparable
  implements: System.ICloneable
  implements: System.IConvertible
  implements: System.IComparable<string>
  implements: seq<char>
  implements: System.Collections.IEnumerable
  implements: System.IEquatable<string>
Multiple items
val string : 'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------

type string = System.String

Full name: Microsoft.FSharp.Core.string

  type: string
  implements: System.IComparable
  implements: System.ICloneable
  implements: System.IConvertible
  implements: System.IComparable<string>
  implements: seq<char>
  implements: System.Collections.IEnumerable
  implements: System.IEquatable<string>
val options : System.StringSplitOptions

  type: System.StringSplitOptions
  inherits: System.Enum
  inherits: System.ValueType
namespace System
type StringSplitOptions =
  | None = 0
  | RemoveEmptyEntries = 1

Full name: System.StringSplitOptions

  type: System.StringSplitOptions
  inherits: System.Enum
  inherits: System.ValueType
field System.StringSplitOptions.RemoveEmptyEntries = 1
val board : string []

  type: string []
  implements: System.ICloneable
  implements: System.Collections.IList
  implements: System.Collections.ICollection
  implements: System.Collections.IStructuralComparable
  implements: System.Collections.IStructuralEquatable
  implements: System.Collections.Generic.IList<string>
  implements: System.Collections.Generic.ICollection<string>
  implements: seq<string>
  implements: System.Collections.IEnumerable
  inherits: System.Array
val count : (int * int -> int)
val x : int

  type: int
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<int>
  implements: System.IEquatable<int>
  inherits: System.ValueType
val y : int

  type: int
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<int>
  implements: System.IEquatable<int>
  inherits: System.ValueType
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------

type List<'T> =
  | ( [] )
  | ( :: ) of 'T * 'T list
  with
    interface System.Collections.IEnumerable
    interface System.Collections.Generic.IEnumerable<'T>
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    member Tail : 'T list
    static member Cons : head:'T * tail:'T list -> 'T list
    static member Empty : 'T list
  end

Full name: Microsoft.FSharp.Collections.List<_>

  type: List<'T>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<List<'T>>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
  implements: System.Collections.Generic.IEnumerable<'T>
  implements: System.Collections.IEnumerable
val map : ('T -> 'U) -> 'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val x' : int

  type: int
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<int>
  implements: System.IEquatable<int>
  inherits: System.ValueType
val y' : int

  type: int
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<int>
  implements: System.IEquatable<int>
  inherits: System.ValueType
val filter : ('T -> bool) -> 'T list -> 'T list

Full name: Microsoft.FSharp.Collections.List.filter
property System.Array.Length: int
val sumBy : ('T -> 'U) -> 'T list -> 'U (requires member ( + ) and member get_Zero)

Full name: Microsoft.FSharp.Collections.List.sumBy
module Array

from Microsoft.FSharp.Collections
val mapi : (int -> 'T -> 'U) -> 'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.mapi
val line : string

  type: string
  implements: System.IComparable
  implements: System.ICloneable
  implements: System.IConvertible
  implements: System.IComparable<string>
  implements: seq<char>
  implements: System.Collections.IEnumerable
  implements: System.IEquatable<string>
Multiple overloads
System.String.ToCharArray() : char []
System.String.ToCharArray(startIndex: int, length: int) : char []
val c : char

  type: char
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IComparable<char>
  implements: System.IEquatable<char>
  inherits: System.ValueType
Multiple items
val char : 'T -> char (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.char

--------------------

type char = System.Char

Full name: Microsoft.FSharp.Core.char

  type: char
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IComparable<char>
  implements: System.IEquatable<char>
  inherits: System.ValueType
val invalidArg : string -> string -> 'T

Full name: Microsoft.FSharp.Core.Operators.invalidArg
val map : ('T -> 'U) -> 'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val chars : char []

  type: char []
  implements: System.ICloneable
  implements: System.Collections.IList
  implements: System.Collections.ICollection
  implements: System.Collections.IStructuralComparable
  implements: System.Collections.IStructuralEquatable
  implements: System.Collections.Generic.IList<char>
  implements: System.Collections.Generic.ICollection<char>
  implements: seq<char>
  implements: System.Collections.IEnumerable
  inherits: System.Array
type String =
  class
    new : char -> string
    new : char * int * int -> string
    new : System.SByte -> string
    new : System.SByte * int * int -> string
    new : System.SByte * int * int * System.Text.Encoding -> string
    new : char [] * int * int -> string
    new : char [] -> string
    new : char * int -> string
    member Chars : int -> char
    member Clone : unit -> obj
    member CompareTo : obj -> int
    member CompareTo : string -> int
    member Contains : string -> bool
    member CopyTo : int * char [] * int * int -> unit
    member EndsWith : string -> bool
    member EndsWith : string * System.StringComparison -> bool
    member EndsWith : string * bool * System.Globalization.CultureInfo -> bool
    member Equals : obj -> bool
    member Equals : string -> bool
    member Equals : string * System.StringComparison -> bool
    member GetEnumerator : unit -> System.CharEnumerator
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> System.TypeCode
    member IndexOf : char -> int
    member IndexOf : string -> int
    member IndexOf : char * int -> int
    member IndexOf : string * int -> int
    member IndexOf : string * System.StringComparison -> int
    member IndexOf : char * int * int -> int
    member IndexOf : string * int * int -> int
    member IndexOf : string * int * System.StringComparison -> int
    member IndexOf : string * int * int * System.StringComparison -> int
    member IndexOfAny : char [] -> int
    member IndexOfAny : char [] * int -> int
    member IndexOfAny : char [] * int * int -> int
    member Insert : int * string -> string
    member IsNormalized : unit -> bool
    member IsNormalized : System.Text.NormalizationForm -> bool
    member LastIndexOf : char -> int
    member LastIndexOf : string -> int
    member LastIndexOf : char * int -> int
    member LastIndexOf : string * int -> int
    member LastIndexOf : string * System.StringComparison -> int
    member LastIndexOf : char * int * int -> int
    member LastIndexOf : string * int * int -> int
    member LastIndexOf : string * int * System.StringComparison -> int
    member LastIndexOf : string * int * int * System.StringComparison -> int
    member LastIndexOfAny : char [] -> int
    member LastIndexOfAny : char [] * int -> int
    member LastIndexOfAny : char [] * int * int -> int
    member Length : int
    member Normalize : unit -> string
    member Normalize : System.Text.NormalizationForm -> string
    member PadLeft : int -> string
    member PadLeft : int * char -> string
    member PadRight : int -> string
    member PadRight : int * char -> string
    member Remove : int -> string
    member Remove : int * int -> string
    member Replace : char * char -> string
    member Replace : string * string -> string
    member Split : char [] -> string []
    member Split : char [] * int -> string []
    member Split : char [] * System.StringSplitOptions -> string []
    member Split : string [] * System.StringSplitOptions -> string []
    member Split : char [] * int * System.StringSplitOptions -> string []
    member Split : string [] * int * System.StringSplitOptions -> string []
    member StartsWith : string -> bool
    member StartsWith : string * System.StringComparison -> bool
    member StartsWith : string * bool * System.Globalization.CultureInfo -> bool
    member Substring : int -> string
    member Substring : int * int -> string
    member ToCharArray : unit -> char []
    member ToCharArray : int * int -> char []
    member ToLower : unit -> string
    member ToLower : System.Globalization.CultureInfo -> string
    member ToLowerInvariant : unit -> string
    member ToString : unit -> string
    member ToString : System.IFormatProvider -> string
    member ToUpper : unit -> string
    member ToUpper : System.Globalization.CultureInfo -> string
    member ToUpperInvariant : unit -> string
    member Trim : unit -> string
    member Trim : char [] -> string
    member TrimEnd : char [] -> string
    member TrimStart : char [] -> string
    static val Empty : string
    static member Compare : string * string -> int
    static member Compare : string * string * bool -> int
    static member Compare : string * string * System.StringComparison -> int
    static member Compare : string * string * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
    static member Compare : string * string * bool * System.Globalization.CultureInfo -> int
    static member Compare : string * int * string * int * int -> int
    static member Compare : string * int * string * int * int * bool -> int
    static member Compare : string * int * string * int * int * System.StringComparison -> int
    static member Compare : string * int * string * int * int * bool * System.Globalization.CultureInfo -> int
    static member Compare : string * int * string * int * int * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
    static member CompareOrdinal : string * string -> int
    static member CompareOrdinal : string * int * string * int * int -> int
    static member Concat : obj -> string
    static member Concat : obj [] -> string
    static member Concat<'T> : System.Collections.Generic.IEnumerable<'T> -> string
    static member Concat : System.Collections.Generic.IEnumerable<string> -> string
    static member Concat : string [] -> string
    static member Concat : obj * obj -> string
    static member Concat : string * string -> string
    static member Concat : obj * obj * obj -> string
    static member Concat : string * string * string -> string
    static member Concat : obj * obj * obj * obj -> string
    static member Concat : string * string * string * string -> string
    static member Copy : string -> string
    static member Equals : string * string -> bool
    static member Equals : string * string * System.StringComparison -> bool
    static member Format : string * obj -> string
    static member Format : string * obj [] -> string
    static member Format : string * obj * obj -> string
    static member Format : System.IFormatProvider * string * obj [] -> string
    static member Format : string * obj * obj * obj -> string
    static member Intern : string -> string
    static member IsInterned : string -> string
    static member IsNullOrEmpty : string -> bool
    static member IsNullOrWhiteSpace : string -> bool
    static member Join : string * string [] -> string
    static member Join : string * obj [] -> string
    static member Join<'T> : string * System.Collections.Generic.IEnumerable<'T> -> string
    static member Join : string * System.Collections.Generic.IEnumerable<string> -> string
    static member Join : string * string [] * int * int -> string
  end

Full name: System.String

  type: System.String
  implements: System.IComparable
  implements: System.ICloneable
  implements: System.IConvertible
  implements: System.IComparable<string>
  implements: seq<char>
  implements: System.Collections.IEnumerable
  implements: System.IEquatable<string>
val reduce : ('T -> 'T -> 'T) -> 'T [] -> 'T

Full name: Microsoft.FSharp.Collections.Array.reduce
val input : string

Full name: Snippet.input

  type: string
  implements: System.IComparable
  implements: System.ICloneable
  implements: System.IConvertible
  implements: System.IComparable<string>
  implements: seq<char>
  implements: System.Collections.IEnumerable
  implements: System.IEquatable<string>

No surprises then that according to the ICFP:

F# is the programming language of choice for discriminating hackers

untitled

For the C session I paired with John Nolan. Again we were able to complete the computational task, this time with only 30 seconds to spare, and it certainly wasn’t pretty, but still a lot of fun!

Since the conference I’ve knocked up an Erlang version: http://pastebin.com/s9mChuPp

 

Plus another F# version that fits nicely in a Tweet (140 characters): http://fssnip.net/ce

s|>Array2D.mapi(fun x y->function '*'->'*'|_->'0'+char([for i in 0..8->i%3-1,i/3-1].Count(fun(x,y)->x>=0&&x=0&&y<m&&s.[x,y]='*')))

MinesweeperInTryFSharp

End of day 3

The last talk of the day for me was Nat Pryce’s excellent Stop Refactoring! talk on the Iconoclasts track:

An iconoclast is someone who performs iconoclasm — destruction of religious symbols, or, by extension, established dogma or conventions.

Nat retold his observations of refactoring ping-pong:

Refactor one way, then another. then back again

The main message was that “code doesn’t need to be perfect only habitable” and::

The imperfection of our code is really motion blur, as the state of the code is simply a snapshot as it evolves

Day after

I really enjoyed the conference, saw some inspiring talks, and met some really interesting people, and would recommend Goto Copenhagen to anyone interested in software development. Read more about the conference and more specifically Concurrent Programming using the Disruptor over on Trisha’s blog.

Finally it appears to me that people are not wearing enough hats.