Simplifying code with finite state machines

Yes, it's been a while. We've been busy. The good news (for you) is that we've been making fun new things (i.e. code libraries) that we'll be sharing soon!

Now, on to the actual topic of this post - finite state machines. What is a finite state machine you ask? Well it's just a construct that lets you track the states within a piece of code and ensure that you only do what you're allowed to do when you're allowed to do it.

A while back I wrote a generic finite state machine (I called it PastaMachine - since every time I wrote FSM I thought of the Flying Spaghetti Monster). It is exceptionally generic - you just define states, define the allowed transitions between those states (state A can go to state B, but B can't go back to A, etc) and the actions that each state may take (an action may trigger a transition, but it doesn't have to). The states themselves can have attached to them an arbitrary amount of metadata and in less than 340 lines of code you have a simple finite state machine.

What can you do with it? Well, originally it was written to handle a branching logic game where depending on the users success at a simple game they went down multiple paths and were shown various different videos (yeah... it was a PG-13 strip poker game). But recently Keenan has been using PastaMachine to track the logic of an application to assist doctors in treating patients with HPV. If that's not a nice range of usefulness, I don't know what is!

One nice extra trick PastaMachine has up it's sleeve is that once you've defined a state machine with it you can export the information about that state machine to data in DOT format. That DOT data can be loaded into the ever-so-awesome GraphViz and BAM! you have a directed graph diagram of your state machine! It's actually really useful in debugging the state machine's connections, but beyond that it adds a very nice "WOW!" factor when you present it to your client.

Over the next few weeks we'll be cleaning up PastaMachine and sharing it with everyone. Then, if everything goes smoothly, there will be a number of other Automata code libraries following along behind it.

Does Your Tween Stop In The Middle?

Branden and I were working in the office today when Branden came over and asked me if I've ever run into the following problem:

You are creating tweens using the Tween class in AS3. These tweens are inside of a method (or a loop). The tweens appear to work fine, except, they stop in the middle without explanation. As it turns out, I had run into this problem before. While working on a previous project, I had a series of tweens moving around a Rectangle object inside a class method. Halfway through the tween, it stopped for no apparent reason. After using everyone's favorite inter-web fast-food chain, Google, I determined that the issue must be due to garbage collection. I typed in "AS3 tween garbage collection", and found that my problem had been solved and discussed by Scott Morgan. Here's his blog post about it.

The solution, as described by Scott is to create class properties for your tweens instead of local variables. As I described this to Branden, he noted a potential problem with this solution. When you use class properties, the Flash player will allocate space for those properties, even when you are not using them. Why is this a problem? Well, imagine you can potentially have hundreds of instances of a class, where each instance contains private properties for 5 tweens. This could significantly hurt the performance of your application since you will have allocated space for all of those tweens, even though the tweens are not running. Needless to say, while this is a good solution, and great in a pinch, ultimately, you will have problems for large numbers of tweens.

So, how do you solve the secondary problem of allocating space for tweens that are not running? Is there a way to use a class property to store the tween (so it is not killed by the garbage collector), without actually allocating space until the tween is needed?

The answer: DICTIONARY!

Instead of creating a property for each tween you use, instead, create a single property of type flash.utils.Dictionary. The Dictionary class allows you to create a set of dynamic properties, without allocating the space for them until the property is actually created. Additionally, you can also use an object reference as a key in a dictionary, which can be a very powerful tool. Once you have your dictionary, inside the method (or loop) that creates the tweens, store the tween object reference as the key in the dictionary. Once your tween is complete, delete the key and your tween will be collected by the garbage collector.

Here's an example:

Chaining Events

Lately I've been dinking around with a wonderful library for Python called Twisted. Twisted is a networking library that makes creating custom clients and servers insanely easy.

Like a lot of good libraries Twisted starts off with a philosophy (think Ruby on Rails, etc) - in Twisted's case it's "You don't call Twisted, Twisted calls you". If that immediately makes you think "hey they must be doing some neat things with events!" then you're right.

When you're using Twisted and you call a function that needs to do some sort of work where it will takes some time for the result to be available you don't have to wait for that result to come. Instead the function immediately returns an instance of the Deferred class. What is the Deferred class you ask? Well, I think the Twisted manual explains it best:

Twisted uses the Deferred object to manage the callback sequence. The client application attaches a series of functions to the deferred to be called in order when the results of the asychronous request are available (this series of functions is known as a series of callbacks, or a callback chain), together with a series of functions to be called if there is an error in the asychronous request (known as a series of errbacks or an errback chain). The asychronous library code calls the first callback when the result is available, or the first errback when an error occurs, and the Deferred object then hands the results of each callback or errback function to the next function in the chain.

I happen to think that's a pretty neat take on chaining events and am seriously debating creating a similar system for a new little project I'm working on that will involve a lot of async programming.

In general finding this concept reminds me about why it's so important to go outside of your usual mental playground and find other places where developers are playing. Almost every time I do this and go look at something like Python or Objective C or Haskell I end up finding a concept I want to port over to one of my usual tools.

How do I do “onReleaseOutside” in ActionScript 3?

Back in the days of ActionScript 1 and 2 you sometimes wanted to find out when a button or movieclip was clicked, but then the mouse was released outside of that object. This was particularly handy when doing drag and drop since it was (and still is) possible that the user could whip their mouse around and let go of the mouse when the mouse pointer wasn't actually on top of the clip. If you didn't listen for the the "onReleaseOutside" event the clip being dragged would now be permanantly stuck a few pixels away from your mouse pointer following it around like a stray dog.

In ActionScript 3 the core mouse related events are CLICK, MOUSE_DOWN, and MOUSE_UP. The overall concept of releasing the mouse but not on top of the display object that received the original MOUSE_DOWN event is intrinsically handled by how the new event system works. Essentially events go through phases - for example when the mouse is pressed the Flash player creates an event and passes that event down from the stage through the display tree to the display object that was actually clicked on. If that display object doesn't catch the event it then bubbles back up the tree to see if any of those display objects want to handle it. If the event bubbles all the way up the stage and it isn't handled it is just destroyed.

Thus, you can find out when the mouse was released, no matter what display object it was over, by listening for a MOUSE_UP event coming from the stage. Just as always you should only listen for this event when you need it - which in this case is easy to do because you can start listening when the the MOUSE_DOWN event is handled and stop listening when the MOUSE_UP event is handled.

import flash.events.MouseEvent;

function dragPin(evt:MouseEvent):void {

pin.startDrag();

stage.addEventListener(MouseEvent.MOUSE_UP, dropPin);

}

function dropPin(evt:MouseEvent):void {

pin.stopDrag();

stage.removeEventListener(MouseEvent.MOUSE_UP, dropPin);

}

pin.addEventListener(MouseEvent.MOUSE_DOWN, dragPin);

How to Start - Part 2

First off if you want to follow along, it would be a good idea to download the current Abalone source code and read the first article in the series..

I ended the first entry of this series talking about nodes - how each space on the board of Abalone is a node. After deciding on the concept of nodes my next step was to think about what kind of data each node needed to contain. Each node need to know about it's immediate neighbors and what it's current state is (empty, has a black marble or has a white marble). By the looks of it both of these types of data were well suited for something known as an enumerated type. Unfortunately ActionScript 3 doesn't explicitly support enumerated types, but they can be sufficiently faked.

Thus, we have the AbaloneDirection class and the AbaloneState class. Both of these classes should never be instatiated - instead they just hold our special sets of data. So what's the benefit of storing our states in the special strings? Why not just use strings in the first place? Well, that comes down to working smarter and having your tools work for you. If you use this faked-up enumerated type and always refer to AbaloneState.EMPTY then you don't have to worry about funny misspellings and other nasty errors that the compiler won't catch for you. Sure, it's a little more work up front, but your code ends up being much more clean and easier to debug - which is a pretty fair trade off in my book.

The only funny thing in those two classes is that the AbaloneDirection class also has a static method named getInverse - this method helps in making connections between two nodes go both ways. That is NodeA connects to NodeB through it's AbaloneDirection.RIGHT edge. That means that NodeB needs to connect back to NodeA using it's AbaloneDirection.LEFT edge.

Now that our data is sorted out, let's get back to the nodes themselves. After thinking about it a bit I realized that there were in actuality two types of nodes - the regular nodes that we've already discussed and the gutter that surrounds the playing board. These two different types of nodes are similar in that marbles can be pushed into them, but what they actually do when marbles are pushed into them is different. It would be nice if they were essentially interchangable - something that can be pulled off through the use of an interface. I defined a simple interface called IAbaloneNode that enforces two methods, setNeighbor and push. Then I defined two classes, AbaloneNode and AbaloneGutter that implemented that interface.

AbaloneNode defines it's setNeighbor method so that it both makes references to the neighbor and makes sure the neighbor has a reference back to it. The push method of AbaloneNode "pushes" the state of the node onto the appropriate neighbor and handles the logic of dealing with empty nodes along the way. It turns out that AbaloneGutter can't push marbles back into the playing board, so it's setNeighbor method can be blank (it has to have a setNeighbor method though, to conform to the interface). The push method of AbaloneGutter accepts whatever state was pushed into it and then broadcasts out an event of the type AbaloneEvent.EJECT that contains the state (type of marble) that was ejected.

Notice that with all of this that there is no enforcement of the rules of Abalone - and for good reason. By keeping the classes as simple as possible and having them handle one concept (how nodes connect) we end up with more flexible and easier to understand code. In the next part of this series we'll be looking at the code that defines and enforces the rules of Abalone.