Con­sid­er­ing a very sim­ple finite state machine (FSM) such as a code lock which requires you to enter a 4-digit numeric code and upon which will open the lock for a brief few seconds.

imageSuch a FSM have two states: Locked and Open.

Every time a key is entered it checks the sequence of dig­its inputted so far and if the sequence does not match the secret code then it stays in the Locked state.

If the input sequence matches the length of the secret code then the user is judged to have entered an incor­rect sequence and the input sequence is reset.

If, on the other hand, the user has entered the cor­rect code then the FSM will change to the Open state for a num­ber of sec­onds before revert­ing back to the Locked state.

This post is intended to show you how you can imple­ment this FSM eas­ily using F#’s agent and Erlang OTP’s gen_fsm behaviour.

 

 

 

F#

First, let’s define the dif­fer­ent states that our FSM can be in:

image

and then the mes­sages that our agent can receive:

image

The actual FSM imple­men­ta­tion looks like this:

This imple­men­ta­tion is pretty straight for­ward, I’ve used a sim­i­lar tech­nique to the one Tomas Pet­ricek used in his Block­ingQueueAgent imple­men­ta­tion and rep­re­sented the dif­fer­ent states using recur­sive functions.

One caveat with this FSM is the need to revert back to the Locked state after being in the Open state for a cer­tain amount of time. For sim­plic­ity sake, I’ve sim­ply spec­i­fied a time­out (3 sec­onds) when wait­ing for mes­sages in the Open state and use the Time­ou­tEx­cep­tion as cue to go back to the Locked state. The obvi­ous down­side to my imple­men­ta­tion here is that if a Get­State mes­sage is received it will reset the timer!

You can fix this eas­ily enough in a num­ber of ways, includ­ing using a muta­ble instance vari­able to keep track of the cur­rent state and let the async lamb­das mod­ify it dur­ing state changes and tran­si­tions, then the Get­State() method would no longer need to trou­ble the agent to find out what the cur­rent state is.

 

Erlang

Erlang’s OTP frame­work pro­vide a gen_fsm behav­iour which you can use to imple­ment a FSM, which will take care of most of the plumb­ing and orches­tra­tion for you leav­ing you free to focus on the impor­tant things – han­dling the dif­fer­ent ‘events’ that can be trig­gered dur­ing dif­fer­ent states.

This Erlang imple­men­ta­tion might look much big­ger than its F# coun­ter­part but keep in mind that I’ve included plenty of com­ments here and not been as con­ser­v­a­tive with write spaces as I was with the F# code. All and all, both ver­sions require roughly the same num­ber of LOC, the main dif­fer­ence being the lack of plumb­ing in the Erlang ver­sion, which if I have to be hon­est, can be con­fus­ing if you don’t have a decent under­stand­ing of how the gen_fsm behav­iour works!

You can down­load and play around with the full source code (with cor­re­spond­ing tests for each imple­men­ta­tion) from Github here. Enjoy!

Share

Another week, another Thurs­day, another release and another new slot to add to our pla­toon of F#-backed slots game, Plants vs Zom­bies Sum­mer Brains is now live on Lucky Gem Casino!

image

Plants vs Zom­bies Sum­mer Brainz

As you can see from the sports sta­dium in the back­ground, this brand new 25-line slot is clearly themed around an upcom­ing global sport­ing event that’ll be hap­pen­ing very close to our office (hint hint!) Winking smile

Besides fea­tur­ing some of your favourite char­ac­ters from the Plants vs Zom­bies game there is also a fun pick bonus game with an excel­lent soundtrack:

image image

image image

image

Go on, try it out, and enjoy some SUMMER BRAAAIIINNZZZ!!!!

Share

Related Posts

 

Here I will look at how some com­monly used func­tions in F#’s List mod­ule might be trans­lated to Erlang using Erlang’s equiv­a­lent – the lists module.

 

List.append

F#:         let newList = List.append [ 1..5 ] [ 6..10 ]

Erlang:   NewList = lists:append([ 1, 2, 3, 4, 5 ], [ 6, 7, 8, 9, 10 ]).

List.average

F#:         let avg = List.average [ 1.0..10.0 ]

Erlang:   List = lists: seq(1, 10).

             Avg = lists: sum(List) / length(List).

List.collect

F#:         let duped = [ ‘a’; ‘b’; ‘c’ ] |> List.collect (fun x -> [ x; x ])

Erlang:   Duped = lists:flatmap(fun(X) –> [ X, X ] end, [ a, b, c ]).

List.concat

F#:         let newList = List.concat [ [ 1; 2 ]; [ 3; 4; 5 ]; [ 6; 7; 8; 9 ] ]

Erlang:   NewList = lists:append([ [ 1, 2 ], [ 3, 4, 5 ], [ 6, 7, 8, 9 ] ]).

 

List.exists

F#:         let hasEven = [ 1..2..9 ] |> List.exists (fun x -> x % 2 = 0)

Erlang:   HasEven = lists:any(fun(X) -> X rem 2 =:= 0 end, lists: seq(1, 9, 2)).

 

List.filter

F#:         let evens = [ 1.. 6 ] |> List.filter (fun x -> x % 2 = 0)

Erlang:   Evens = lists:filter(fun(X) -> X rem 2 =:= 0 end, lists:seq(1, 6)).

 

List.find

F#:         let fst­Match = [ “cui”; “xue”; “yan” ] |> List.find ((=) “yan”)

Erlang:   Fst­Match = lists:keyfind(yan, 1, [ { cui }, { xue }, { yan } ]).

 

List.fold

F#:         let data = [ (“Cats”, 4); (“Dogs”, 5); (“Mice”, 3); (“Ele­phants”, 2) ]

              let count = data |> List.fold (fun acc (_, x) -> acc + x) 0

Erlang:   Data = [ { cats, 4 }, { dogs, 5 }, { mice, 3 }, { ele­phants, 2 } ].

             Count = lists:foldl(fun({ _, N }, Acc) -> Acc + N end, 0, Data).

 

List.foldBack

F#:         let copy = List.foldBack (fun elem acc -> elem::acc) [ 1..10 ] []

Erlang:   Copy = lists:foldr(fun(X, Acc) -> [X|Acc] end, [], lists:seq(1, 10)).

 

List.forall

F#:         let allEven = [2; 4; 6; 8] |> List.forall (fun n -> n % 2 = 0)

Erlang:   AllEven = lists:all(fun(X) -> X rem 2 =:= 0 end, [ 2, 4, 6, 8 ]).

 

List.iter

F#:         [1..10] |> List.iter (printfn “%d”)

Erlang:   lists:foreach(fun(X) -> io:format(“~p~n”, [ X ]) end, lists:seq(1, 10)).

 

List.length

F#:         let lst = [ 1..10 ]

              // you can call the Length prop­erty on a list

              let len1 = lst.Length

              // or use List.length

              let len2 = List.length lst

Erlang:   Lst = lists: seq(1, 10).

             % you can use the length built-in function

             Len1 = length(Lst).

             % or you can use lists:flatlength

             Len2 = lists:flatlength(Lst).

 

List.map

F#:         let dou­bles = [ 1..10 ] |> List.map (fun x -> x * 2)

Erlang:   Dou­bles = lists:map(fun(X) -> X * 2 end, lists:seq(1, 10)).

 

List.max

F#:         let max = [ 1..10 ] |> List.max

Erlang:   Max = lists:max(lists: seq(1, 10)).

 

List.min

F#:         let min = [ 1..10 ] |> List.min

Erlang:   Min = lists:min(lists: seq(1, 10)).

 

List.nth

F#:         let fourth = List.nth [ 1..10 ] 3

Erlang:   Fourth = lists:nth(4, lists: seq(1, 10)). % node that n is not zero-indexed here!

 

List.partition

F#:         let evens, odds = [ 1..10 ] |> List.partition (fun n -> n % 2 = 0)

Erlang:   { Evens, Odds } = lists:partition(fun(X) -> X rem 2 =:= 0 end, lists:seq(1, 10)).

 

List.rev

F#:         let rev = [ 1..10 ] |> List.rev

Erlang:   Rev = lists:reverse(lists: seq(1, 10)).

 

List.sort

F#:         let sorted = List.sort [ 1; 4; 7; –1; 5 ]

Erlang:   Sorted = lists:sort([ 1, 4, 7, –1, 5 ]).

 

List.sum

F#:         let sum = List.sum [ 1..10 ]

Erlang:   Sum = lists:sum(lists:seq(1, 10)).

 

List.unzip

F#:         let lstA, lstB = List.unzip [ (1, 2); (3, 4) ]

Erlang:   { LstA, LstB } = lists:unzip([ {1, 2}, {3, 4} ]).

 

List.zip

F#:         let lst = List.zip [ 1; 2 ] [ 3; 4 ]

Erlang:   Lst = lists:zip([ 1, 2 ], [ 3, 4 ]).

Share

Today we released another new slot that runs on our F# slots engine onto Jack­potJoy Slots. This time it’s a Japan­ese themed game with a rather cool bonus game feature Winking smile

image

Samu­rai vs Ninja

Samu­rai vs Ninja is a 25-line slot, when you land a Samu­rai sym­bol on the first and a Ninja sym­bol on the last reel, or a Ninja sym­bol on the first and a Samu­rai sym­bol on the last reel it’ll trig­ger the bonus game feature!

image

A samu­rai and a ninja will fight in the bonus game and the player is asked to ‘back’ one of the fight­ers. If the player’s cho­sen fighter wins the sub­se­quent fight then the player will receive a bonus in their cho­sen bonus game.

image image

If the player had cho­sen the ninja then the player will go into a pick bonus game after the fight:

image

On the other hand, if the player had cho­sen the samu­rai then the player will go into the free spins mode instead. Dur­ing the free spins fea­ture the samu­rai will ran­domly slash through the reels and the slashed reels will turn into a col­umn of wild symbols.

image image 

So the only ques­tion remains, who would you back in a fight!?!?

image  image

Share

Related Posts

 

Throw­ing Exceptions

In F#, you can define a cus­tom excep­tion type by cre­at­ing a type that inherit from System.Exception or using the light­weight excep­tion syn­tax to define them with the same syn­tax as dis­crim­i­nated unions.

You can throw excep­tions in F# using the raise key­word or using fail­with or fail­withf:

excep­tion MyExceptionA

excep­tion MyEx­cep­tionB of string

let exThrower (isA : bool option) =

    match isA with

    | Some(true) -> raise MyExceptionA

    | Some(false) -> raise <| MyExceptionB(“Blah Blah”)

    | _ -> raise <| new System.Exception()

    | _ -> fail­with “Not a valid input”

Erlang also has a num­ber of dif­fer­ent excep­tion types, the most com­mon ways to raise an excep­tion in Erlang is via:

  • error(Reason) – ter­mi­nates the cur­rent process and includes a stack trace.
  • exit(Reason) – sim­i­lar to errors, but does not return the stack trace.
  • throw(Reason) – throws excep­tions that the caller can be expected to han­dle, also used as a way to return from deep recursion.

1> throw(“Blah Blah”).

** excep­tion throw: “Blah Blah”

2> error(boo).

** excep­tion error: boo

3> exit(foo).

** excep­tion exit: foo

 

Catch­ing Exceptions

In F#, you can imple­ment a try-catch block using the try-with key­words, and it’s really easy to use pat­tern match­ing to make han­dling mul­ti­ple types of excep­tions really easy.

Bor­row­ing from the won­der­fully humor­ous exam­ple from Learn you some Erlang for great good! here’s how it’ll look in F#:

 

In Erlang, the syn­tax is sur­pris­ingly similar:

 

Another thing to keep in mind is that whilst F# has try-with and try-finally blocks there is no equiv­a­lent of C#’s try-catch–finally block. In Erlang the try-catch-finally block looks like this:

black_knight(Attack) when is_function(Attack, 0) –>

    try Attack() of

        _ -> “None shall pass.”

    catch

        throw:slice   -> “It is but a scratch.”;

        error:cut_arm -> “I’ve had worse.”;

        exit: cut_leg -> “Come on you pansy!”;

        _:_             -> “Just a flesh wound.”

    after

        io:format(“Attack finished…~n”, [])

    end.

Share