Skip to content

Iloggable

State-aware programming in C#, part I

This is going to be a multi-parter, simply to allow for some organizing and avoid the giant scrolling page.

State as language syntax

One thing I've always liked about UnrealScript was its inclusion of states as a first class citizen in the language. It's something that just made sense for the problem that UnrealScript tries to solve. After doing some Unreal modding, I thought about building a game scripting language of my own and contacted Tim Sweeney for his advice. I don't know if he just didn't get as much mail as he does now, or if he is just one of the incredibly helpful guys in the industry, but he got back to me in a day and gave me some good advice on language design and generally told me to bone up on the Java Virtual Machine design docs -- which is where he got a lot of his ideas for UnrealScript.

While fun, that project didn't get very far, but I still keep coming back to first-class stateful programming from time to time. Now that XNA is out seems like the perfect time to revisit this, because writing your game logic in .NET would almost certainly benefit from the approach of UnrealScript.

There are three paths of approach to this problem that I think are all viable:

Implement an UnrealScript compiler for .NET

This would be a cool project and could be something to try to get Epic to pick up and have them embedd .NET/mono into Unreal. It would provides their clients with more programatic flexibility (i.e. more languages), a richer framework and might even add a good bit of performance (not sure how optimized the UnrealScript VM is by now). It's basically what SecondLife is up to.. Of course LSL was always a scripting language, and UnrealScript has been a bytecode compiled language from the start, so the comparison might be flawed.

Create a C# derivative that implements new state keywords

This is my fav, just because I prefer to have the C# as my foundation. While UnrealScript is probably one of the nicest game scripting languages for gaming, its syntax is still a bit strange to me at times -- like state() vs. state keywords and the lack of static methods. But it would be a major undertaking, so it's likely to be the ultimate, not initial, approach.

See what can be done in C# to create a stateful object framework

This is the path I've chosen for now, because it let me prototype the whole thing in a day, which is always nice. If that turns out to be useful, the prior approach can always be adopted from this work.

Design of a stateful C# framework

So what are my design goals for this stateful C# framework?

Different logic paths per state on state aware methods

Really the definition of state aware objects. If the state of my Bot is Idle a different code path for Hit() should be called than if the Bot was in state Attacking.

State specific methods should be inherited

Extend regular inheritance to per state logic path inheritance. I.e. a subclass should be able to override the existing default and state specific methods, as well as create state specific methods, where the base class was just using the default.

Default and state specific methods

A method that is declared as state aware should always have a default implementation, so that identical behaviors don't all create duplicate code or simple stubs that just point to common implementations.

Type-safe states

I always prefer strongly-type definitions, so enum's seem like the ideal way to express states. The biggest drawback is lack of inheritance in enums. If we used one enum for all states of all objects the state names would quickly become meaningless. So the design must allow for per class enumeration of states and the framework should not have a preconceived idea of the possible states.

Serializable state-aware objects

If our objects store state, we should be able to fully serialize them, including their state, so we can take a snapshot of our action at any point in time.

See State-aware programming in C#, part II for the syntax that implements this design.

State-aware programming in C#, part II

Having defined the approach for the stateful framework, let's tackle the design goals:

  • Serializable state-aware objects
  • Different logic paths per state on state aware methods
  • State specific methods should be inherited
  • Default and state specific methods
  • Type-safe states

Ideally we would like our code so look something like this:

public class Bot : AStateObject
{
  public virtual void Touch()
  {
    //default implementation
  }

  virtual state(BotStates.Idle)
  {
    public virtual void Touch()
    {
      // Idle specific implementation
    }
  }
}

public class GuardBot : Bot
{
  public override void Touch()
  {
    // override of default implementation
  }

  virtual state(BotStates.Guarding)
  {
    public virtual void Touch()
    {
      // Guarding specific implementation
    }
  }
}

Since that's not possible without altering the language, let's see what we can do to approximate that behavior.

Serializable state-aware objects

I'm just going to get this out of the way first. For the initial version, i'm handling the serializable portion by simple making the abstract base class ISerializable and putting the burden on the subclass to be serializable. .NET already has great facilities for serializing and it won't be hard to retrofit the base class with the methods for automating the saving of state later, as long as we just insist on ISerializable.

Different logic paths per state on state aware methods

Since we can't just create new keywords in the language, what can we do? Well, to start, a large part of the motivation behind stateful programming in UnrealScript can be alleviated by using events. I.e. a common example is a Touch() function. I.e. the object responds to an external event. Well, instead of creating Touch() in different parts of the code, you could just have a Touched event in the class and subscribe and unsubscribe different handlers depending on the state.

While events will play a large part of any complex game logic, the approach for this framework doesn't use events. Instead we use the language feature that makes events possible, i.e. Delegates. Sure we could have a case statement in each stateful Method that branches on the state, but that makes for error-prone and hard to maintain code. Instead each stateful method could simply call a state handler, which is initialized with the appropriate delegate on state change. Now we have a single set of plumbing for setting up all code paths for each state.

But that still leaves a lot of code at state change to attach the right delegates to each method per state change. Instead of doing this manually, we can use Attributes to identify the appropriate handlers and Reflection to discover state methods and the matching state specific handlers.

The resulting code looks like this:

public class Bot : AStateObject
{
  // Start: Definition of the Stateful method
  protected delegate void TouchDelegate();
  protected TouchDelegate touchDelegate;
  [StateMethod("touchDelegate")]
  public void Touch()
  {
    touchDelegate();
  }
  // End: Definition of the Stateful method

  // Tagged as default handler
  [StateMethodHandler("Touch")]
  protected virtual void Default_Touch()
  {
    //default implementation
  }

  // Tagged as Idle state handler
  [StateMethodHandler("Touch", (byte)BotStates.Idle)]
  protected virtual void Idle_Touch()
  {
    // Idle specific implementation
  }
}

public class GuardBot : Bot
{
  // normal override mechanism works in our state code as well
  protected override void Default_Touch()
  {
    // override of default implementation
  }

  // Tagged as Idle state handler
  [StateMethodHandler("Touch", (byte)BotStates.Guarding)]
  protected virtual void Guarding_Touch()
  {
    // Guarding specific implementation
  }
}

This covers pretty much all the bases, but let me just point out the ones specific to state handling.

First we have to separate the state method from its implemenation and then tag it as such. That's how we get:

protected delegate void TouchDelegate();
protected TouchDelegate touchDelegate;
[StateMethod("touchDelegate")]
public void Touch()
{
  touchDelegate();
}

Clearly a lot of busy work for a simple method. But it's busy work a code generator could easily move to a partial class. The StateMethod attribute both tags the method and provides information to our framework which delegate needs to be wired up.

Now we're free to define our state specific implemenation:

[StateMethodHandler("Touch", (byte)BotStates.Idle)] protected virtual void Idle_Touch() { // Idle specific implementation }

The name Idle_Touch is convention and does not affect execution. Its purpose serves both to make sure we get a unique method name and that its easily recognizable by someone trying to subclass the class. It's the StateMethodHandler attribute that tells the framework that the method is the Idle handler for Touch(). Why are we casting our state enum to byte? I'll cover that when I talk about type-safe states.

State specific methods should be inherited

Since our state specific methods are really just normal methods that have been tagged as handlers, inheritance proceeds in the regular fashion. Marked as virtual, any subclass can override any state handler. Since Intellisense won't tell you which method is tagged to what state, the naming convention of _ once again becomes useful.

Default and state specific methods

In addition to the StateMethodHandler(string methodName, byte state) constructor, there also exists StateMethodHandler(string methodName). Methods tagged as such are the default handlers:

[StateMethodHandler("Touch")]
protected virtual void Default_Touch()
{
  //default implementation
}

Type-safe states

This last goal is a bit tricky and the solution is only somewhat satisfying. My desire is to have states that are type-safe and discoverable enumerations of states. Naturally enums come to mind. But there are a number of disadvantages to enums:

  1. If we define the enum as part of the framework, all classes that implement the framework have to share a fixed set of states. This is clearly not useful.
  2. If we let a subclass define the enumeration and the framework just stores it as an Id, it solves the first problem. However any further subclassing can only add states by changing the original enum, which is only possible if you are the author of the assembly containing that enumeration.
  3. Even if a subclass decides to throw out the parent's state enum and just create its own, any State property will not permit this, since we can't change the property's signature in the override.

The first we address by hiding state in the bowels of the framework simply as a byte and requiring the subclasses to define their own state enum and casting them. Hence the byte cast in the StateMethodHandler attribute. (If you have more than 256 states, you probably have something a bit more complex than should be handled on simple single valued state changes).`` ```

The second is a trade-off for being a compile-time checked framework. I'd rather have my enums to be machine-discoverable and fixed than some dynamic value that only becomes meaningful at runtime. I'll go out on a limb and say that if you are subclassing an existing member of your game's simulation, it should only contain the existing states because the simulation is unlikely to ever set your new states. If you do need more states, maybe your class isn't a subclass at all. You probably have two game objects that share common code, but different states, so they instead have a common ancestor (which doesn't define states). Then your two classes become siblings, each defining their own states.

If you really must extend the states of your base class, you can still handle the last case by simply marking your override of the State accessor as new and taking on the responsibility of doing all the casting.

So that covers the syntax of the implementation for a simple stateful framework. Next I'll cover the guts that implements that syntax in State-aware programming in C#, part III.

Not your iPhone's Multi-touch

There is an article over at Fast Company about Jeff Han, the guy responsible for the Multitouch demo that spread via YouTube a couple of months ago. When I saw that video I was mesmerized. Everything looked so natural. There was no need for explanation, every gesture once seen seemed like the obvious thing to do. It's one of those brilliant inventions that once seen seems like it should always have been around. Well, the video attached to the Fast Company article is even more hypnotizing. Just beautiful.

And I guess the best thing is that this tech is going to hit the market, considering that half the interactions of the iPhone appear to be based on this research. Curious whether Han helped Apple or Apple engineers were inspired at TED. The article mentions PIXAR as an interested party, but not Apple. I do have to give Apple the nod for idea of taking multitouch to the phone. Seeing the multitouch video, I never even considered going to a smaller screen (and neither has Han if the new video is any indication). But it's perfect for the small screen, since that input device of all is the one that needs to be more flexible to what people want to do, and anticipate their input, since there isn't all that much room to get interaction from.

Any way you look at it, I wish Han's company Perceptive Pixel all the luch and funding to make multitouch the way we interact with computers in the future.

Visible != You can see it

The Visible property on Controls is a bit misleading. Aside from the fact that setting it to true, is really only an advisory setting, since it's truth is also dependent on all its parents, there is the issue that is has nothing to do with whether it's actually visible when the form is painted.

Simple example: You have a Control A in a panel and that panel is half off-screen (or at least half across the edge of its container. And A is in the part of the panel that's obscured. A is going to be Visible, even though its not visible.

The interesting thing is that the paint cycle knows this, and OnPaint won't be called on the Control. Now wouldn't it be nice if there was a property that told you that your Visible control won't be drawn? If there is a simple way to determine this, I haven't found it (especially not on .NETCF 1.0).

The way I do it now is that i use RectangleToScreen on the Control and then recursively walk up the parents, get their screen rectangle and call IntersectsWith on the control's Rectangle and each Parent. As soon as i find one that doesn't intersect, I know the Control is not going to be drawn.

It's always the Invoke

If you are working on the .NET Compact Framework 1.0 and you get an ArgumentException trying to manipulate your UI (such as adding a Control to a form), you are likely doing this operation from a thread other than you UI thread and should be using Invoke. Thanks to jonfroelich's post "Controls.Add ArgumentException" for putting me on the right path. With all my frustrating debugging and unexplained freezes, i'd completely forgot that the particular code branch I was looking at was initiated by a callback from a WorkerThread.

Of course the Invoke facilities of .NETCF 1.0 are pitiful, lacking the things that make this whole single-threaded UI business bearable in regular Windows.Forms. There is not InvokeRequired for one thing, nor is there BeginInvoke. And even Invoke just provides the Invoke(Delegate) signature, not the much more useful Invoke(Delegate, Object[]).

Add to that that the only valid Delegate is an EventHandler, which takes two arguments, the exclusion of Invoke(Delegate, Object[]) really is painful.

Of System.Diagnostics.Debug, ActiveSync & Sockets

Today started simple enough. I needed more debug info from my Smartphone app than just using the debugger could give me in a reasonable fashion. My usual solution is log4net for getting a debug spew, but trying to stay as simple as possible on the .NETCF 1.0, I decided to hit up System.Diagnostics instead. More to the point, System.Diagnostics.Debug.WriteLine() and its brethren.

Except, nothing showed up in the output window. Checking whether there was a config setting, then making sure that .NETCF 1.0 supported it, I was stumped. Finally I find out that the default TraceListener is only supported by VS.NET 2k5 if you use .NETCF 2.0. Now I don't know if you've looked at deploying 2.0 apps in a world where even the most modern phones still ship with 1.0, but I certainly couldn't find a clean and simple solution. Especially not one that didn't require being tethered and downloading 40MB from MS, just so they can run a couple hundred kilobytes of App. And it's a pity, because I run into something every day to which the answer is "Use .NETCF 2.0". I want to, really, I do, but deployment convenience trumps developer convenience.

Next up was writing a custom TraceListener and wanting to be as unobtrusive to my Apps operation, I built it on UDP, i.e. a UdpTraceListener. Console based prototype code was up in about 20 minutes for the UdpTraceListener and the console app for listening to the spew. Then followed a couple of hours of testing and stepping through debug and not being able to get anything to be sent from my Emulator cradled via ActiveSync.

I even thought it might be because the phone Emulator couldn't talk to the hosting computer and moved the console app to Mono on my server. That part worked flawlessly--copy the binary call mono UdpTraceConsole.exe and it was up and running. But it also received no data.

Then finally I find a chat log with the .NETCF team that reveals that UDP is not supported over ActiveSync. Nice.

Another 20 minutes of coding and i had a TcpTraceListener up in running in my console test harness. Woot. Time to put test on the phone, so i can finally get back to real coding....

Right. That would have been nice. The same game as before. Tried all sorts of permutations and received no data. Sometimes the debugger would throw a Socket Exception, usually it wouldn't. It made no sense. I knew that TCP worked because I use HttpWebRequest extensively. So I tried putting my console listener on port 80. Nothing. Finally, I decided to open up a port on my firewall and forward it back to my dev machine so that I could try to contact my console listener via a network address from the outside world. And that finally worked. Only theory I have right now is that the DHCP setup via ActiveSync is screwy and it just can't see any of my local net. I'll investigate that later, for now I'm just happy to have a working debug spew.

And here is the exceedingly simple TcpTraceListener. Note: I use '\0' to denote the end of any message so my debug messages can include linefeeds.

using System;
using System.Diagnostics;
using System.Net.Sockets;
using System.Net;
using System.Text;

namespace Droog.Diagnostics
{
  public class TcpTraceListener : TraceListener
  {
    IPEndPoint endPoint;
    Socket console;

    public TcpTraceListener(IPEndPoint consoleEndPoint)
    {
      this.endPoint = consoleEndPoint;
    }

    private Socket ConsoleSocket
    {
      get
      {
        if (console == null || !console.Connected)
        {
          console = new Socket(
            AddressFamily.InterNetwork,
            SocketType.Stream,
            ProtocolType.Tcp);
          console.Connect(endPoint);
        }
        return console;
      }
    }

    public override void Write(string message)
    {
      try
      {
        ConsoleSocket.Send(Encoding.ASCII.GetBytes(message));
      }
      catch
      {
        // this is for a debug spew. I'd rather swallow the exceptions
        // than have my debug code mess with my App.
      }
    }

    public override void WriteLine(string message)
    {
      Write(message + "\\r\\n\\0");
    }

    public override void Close()
    {
      if (console != null)
      {
        if (console.Connected)
        {
          console.Close();
        }
        console = null;
      }
      base.Close();
    }
  }
}

UserControl need to be able to run with no arguments for Designer

When you create a Custom Control or User Control in Visual Studio 2k5, it needs to be able to render its running state with no additional information. I.e. it needs to have a no argument constructor and cannot need extra data passed in at initialization, otherwise Visual Studio 2k5 Designer will die when you add the Control to another form or control, even if it comes up fine in the Designer by itself.

Ok, this one is a big Duh! but i'm sure i'll forget again some day in the future and bitch and moan about Visual Studio hating me and constantly crashing. Basically it comes down to the designer embedding the control and running it. So OnPaint will get called and any timer you have that's not disabled will run. Now if you build controls that require extra initialization data, and the running portions of the control try to use them, you'll get a NullException. Makes perfect sense really, hence the Duh. But of course, you may forget that part, because, after all, the control by itself runs fine and only crashes if the control is added to another control/form. My bet is that the designer is basically a control container and will just discard the exception, but if you add the control to another, the control being added to doesn't handle the exception and complaints.

A cool little side-effect here is that that you can put an animation in a control and that animaton will run in the Designer. :)

Put it in the Dropboks

A friend of mine created a simple web app that falls in the "yeah, i was going to do that... some time.. when i have time.. right, any day now" category. But you know how it goes, you just wish someone did it and you never get around to it.

It's a web page for uploading all those files that you need to lug around various computers you use in different locations. As a geek, i generally end up scp'ing things to my server. But that only works if the machine has scp, etc. I tried iFolder for a while, but it just never worked reliably for me and ask me for my password every time i reboot, even though i tell it to remember me each time.

And sure, there are a ton of file upload but most of them are rich on features, and with that need for configuration, and I just never bother setting up an account. If I had built my own, i'd have started down that road as well, with a nice API, advanced user and group system, ways to mount the file system on the desktop, and would have just got bogged down in the complexity.

Dropboks does just one thing, but it does it immediately and it does it extremely well. It's brilliant in its simplicty and it's gonna be immensely useful to me.

A matter of timing

You know how everything time related in .NET uses milliseconds? Kind of gives you the impression you can deal with things at a millisecond resolution. Generally not so. The internal clock seems to have a resolution just a bit above 10ms, so no matter what value you use for Thread.Sleep() or as your interval for any of the three built-in timers, you achieve about 65Hz. Now, I say "generally" because while my tests on timers have returned 65Hz regardless of which machine I tried them on, Thread.Sleep(1) seemed to give me about 500Hz (still half as fast as it should be) on one machine.

For gathering timing statistics, you could always wrap the Kernel32 counters and get amazing time resolution and with .NET 2.0 you get System.Diagnostics.Stopwatch which has that high resolution as well, if Stopwatch.IsHighResolution is true. It seems to be true on every machine i've tried. But still doesn't give me a timer with the right resolution.

Thread.Sleep(0) seems to just yield execution, so a tight loop on it gives us high resolution and should let other threads work uninterrupted. But it does drive load up regardless. I guess it's a phantom load, but i can't be sure. Using System.Diagnostics.Stopwatch and Thread.Sleep(0), I whipped up a quick-and-dirty High Resolution Timer class as follows:

public class HiResTimer
{
  static Stopwatch ticktock = new Stopwatch();
  static int counter;
  static public void Test()
  {
    HiResTimer hiTee = new HiResTimer(new TimerCallback(DoSomething), 10);
    Thread.Sleep(500);
    for (int i = 0; i < 1000; i++)
    {
      Thread.Sleep(100);
      Console.Clear();
      double hz = counter \* 1000 / ticktock.ElapsedMilliseconds;
      Console.WriteLine("hz: {0:f}", hz);
    }
    hiTee.Stop();
  }

  static void DoSomething(object nullobject)
  {
    if (!ticktock.IsRunning)
    {
      ticktock.Start();
    }
    counter++;
  }

  Thread timerLoop;
  Stopwatch watch = new Stopwatch();
  bool keepTiming = true;
  TimerCallback cycleDelegate;
  int interval;

  public HiResTimer(TimerCallback timerCycle, int interval)
  {
    this.cycleDelegate = timerCycle;
    this.interval = interval;
    timerLoop = new Thread(new ThreadStart(DoLoop));
    timerLoop.Start();
  }

  public void Stop()
  {
    keepTiming = false;
    timerLoop.Join();
  }

  private void DoLoop()
  {
    while (keepTiming)
    {
      watch.Reset();
      watch.Start();
      cycleDelegate(null);
      while (watch.ElapsedMilliseconds < interval)
      {
        Thread.Sleep(0);
      }
    }
  }
}

Seems to work and the built-in static Test() method reliably runs at 100Hz, but as i mentioned, my CPU is constantly at 50%. In theory, as the cycleDelegate increases in complexity and other threads consume processing power, the idle loop of the timer should yield it's processing hunger, but I have not given this a proper test.

The real question is, is there another sleep/yield mechanism that gives me a resoltution somewhere between Thread.Sleep(0) and Thread.Sleep(1) (where 1 really ends up being more like 12 in most cases).

Staying in sync

As I mentioned a couple of days ago, I'm trying to keep my PDA/phone and web in sync. The calendar portion is reasonably well taken care of. That leaves contacts and tasks.

I got one of my domains switched to Zimbra (fodder for another post) and looked at their address book. It seems to be just a folder with .vcf files. Using IMAP, I should be able to manipulate those fairly easily. I'll have to look whether i can access the contacts format on the xv6700 directly, because then I could just sync zimbra and my phone over the net. Alternatively, I hook into activesync on my PC and sync contacts only when I dock the phone.

And then there's Tasks. Zimbra doesn't seem to have an option for that. I know apple now stores tasks in iCal, but I guess nobody else has picked up on that yet. I looked around on the net and decided to use Voo2Do for my task keeping. It's got a nice simple REST api, that I was able to wrap in short time. Last night I moved that API to to .NET CF dll and got a little demo app running on my phone that fetches the contacts from Voo2Do. Yay! While not the most straight forward experience, I am nonetheless impressed how simple programming Pocket PC is, if you are already doing .NET stuff.

That means, tasks are well on their way to being taken care of and Contacts shouldn't be impossible to do as well.

So what were the less than straigh forward pieces in developing for the phone? Most likely it comes down to not having found any good resources for doing this and everything I've done for far has been cobbled together from various web searches and forum posts. So here's what I came across:

  • Visual Studio Windows CE 5.0 projects are always targeting 2.0, even though 2.0 doesn't appear to be standard on the platform yet
  • Initial deployment failed getting the debugging cab installed, but it does put it on the phone. Running it on the phone will fix that and then deploy works fine.
  • Need to figure out signing, so I don't get complaints every time i deploy a new build
  • I currently have two copies of a source identical lib, one for .NET and one for .NET CF. Be nice to have a single source tree with multiple targets via Visual Studio. Dunno if that's possible.
  • Debug deployment works and any exception thrown on the phone is caught in Visual Studio. Breakpoints do not, however. Everytime i set one, Visual Studio complaints that the connection to the device closed (even though debug keeps running).
  • Haven't been able to figure out how to get network connectivity on the Pocket PC 2003 SE up and running, so i can't use it for testing.
  • Can't find an emulator for Windows CE 5.0 Pocket PC, just the full CE 5.0. Dunno if one exists.

Gonna have to dig around a bit and find some better sources of documentation for doing this stuff.