Monads, a rethink

Stepping back from coding for a short while has allowed me to mull over the monad implementations in Woz.Functional and I have realised it is time for a rethink…

I have been through various implementations up to this point and all have followed a similar pattern. An interface, such as IMaybe<T>, and the concrete classes that back them. In the case of Maybe those are Some<T> : IMaybe<T> and None<T> : IMaybe<T>. This is all fine, the concrete classes are streamlined as they know the state which makes the implementation cleaner for each path.

The one thing though that this type of implementation has never addressed if the whole reason for Maybe and the other Monads in the first place, that is to make the types explicit. What is the point of something like Maybe if it is a reference type and hence can actually be null. The thing is is protecting us against is still possible.

The other issue I have always had is that Monads tend to have a short lifetime when you have a compositional workflow, being reference types means lots of heap churn and more load on the Garbage Collection.

The logical move here is to use value types via structs which removes both problems in one go. The Monads can’t be null and they are only on the heap when a member of a class so reduced object churn.

The downsides in this move are:

  • All operations need to determine state to select the path for an operation as structs are sealed.
  • For Monads such as Either<TR, TL> we have more data to pass around on the stack as we have the Left and Right values along with a bool as C# does not support discriminated unions… yet.

I believe this is the correct move though as it actually brings the Monad library closer to the goal, that being explicit types and side effects.

It will be a few days before I get into this refactor but the end results should be worth the .effort 🙂

Woz.Functional, Slow but sure

I have decided to rework the Monad code from Woz.BadlyDrawnRogue as I move it over to Woz.Functional for a few reasons:

  • I have C# 6 which allows a new level of terseness.
  • Some of the property/method names were not quiet right before.
  • The tests were not always testing all paths.
  • I am adding /// comments to the public interface.

This is slowing down progress from being a direct copy and paste of the original code but the results are worth it in the long run, it will result in a better library that includes better help within the IDE when using it.

Woz.Functional

With the two easy class libraries extracted and published to Nuget (Woz.SimpleIOC and Woz.Linq) it is time to move on to Woz.Functional. This will be a more iterative piece of work as I would like this library to have no dependencies and optional sub libraries/packages that carry the code with dependencies such as Woz.Functional.Immutable which will pull in the MS immutable collections and integrate them with Woz.Functional code.

My though here was go back to Haskell and CategoryTheory first principles and see if I could implement Functors, Monoids, Aplicative and the like for C# in a generic way. This would allow me to build every thing on top of these building blocks.

The sad truth is that C# is not capable of re-creating a Haskell like type system. Searching the web you will find many different attempts but in all cases they break down as the .NET/C# generic system is not capable of the Haskell type system subtlety. All the examples you will find are a compromised approximation that look fine in the various contrived examples but then all fall apart when pushed in the real world. For example, the simple definition of:

fmap :: (a -> b) -> Ma -> Mb

C# is just not capable of this definition in a generic means, you have no way to ensure the M in Ma is the same M in Mb, the generic type system treats each one as a separate type. This really forces you to declare a separate fmap declarations for each M to ensure the output boxing type us the same as the input one, such as:

IEnumerable FMap<T, TResult>(IEnumerable source, Func<T, TResult> selector);
IMaybe FMap<T, TResult>(IMaybe source, Func<T, TResult> selector);

This makes trying to build from first principles a bit pointless. I knew this was coming as the Monad library I built in BadlyDrawRogue went through this same fight. In that code I accepted the limitations in C# and instead decided that Linq integration was the better path. In C# Linq is really a monad and computational engine with IEnumerable being the only supplied monad. This means instead of the more normal naming of bind, return, map, fmap etc you instead use Linq naming such as Select, SelectMany etc.

Embracing Nuget

I have finally bit the bullet and upgraded my Surface Pro to Win 10 with VS2015 and got my dev tools installed. With this move I have finally decided to embrace Nuget fully and start to push my common library code as Nuget packages.

After a few teething problems figuring out Nuget packages I have two projects pushed.

Woz.SimpleIOC and Woz.Linq, more will follow over the next month.

Woz.SimpleIOC is a rewrite of my IOC (Inversion Of Control) library from the ground up using C# 6 goodness and a more functional approach to provide more robust and concise version of the library that makes it easier for me to pull in to other projects

Woz.Linq is a merge of various different Linq based entension functions that I have felt are missing from the base implementation. This will grow over time as and when I find other functions that simplify Linq queries or solve issues that require hoop jumps to work around

Both libraries are Portable Class Libraries that support the following target platforms:

  • .NET Framework 4.5
  • .NET Framework 4.5.1
  • .NET Framework 4.6
  • ASP.NET Core 5
  • Windows Universal 10
  • Windows 8
  • Windows Phone 8.1
  • Windows Phone Silverlight 8

There is a whole raft of other library code that I want to extract but this requires more careful thought over how it is split and what dependencies they have. This includes my Monads, Lenses and a group of more general purpose library code.

You can get the current packages using

PM> Install-Package Woz.SimpleIOC
PM> Install-Package Woz.Linq

Bit of a break

I have been a little distracted recently due to the Steam summer sales and playing through some of my game backlog. Once the dust has settled on the Windows 10 and VS2015 release I will be back into Badly Drawn Rogue 🙂

Line of sight

I have been fighting with line of sight over the past couple of days. I picked up my old algorithm and reworked it but it proved too heavy an inefficient for my needs. It attempts to calculate how much of the view was blocked by walls and give a % of the target square that was visible. While it gives a good approximation it always carried some strange artefacts that gave strange FOV results when rendered.

So I went back to basics. I wanted an algorithm that would be efficient. accurate and work on integers only for speed. I first considered the Bresenham’s line algorithm but this has issues in how it steps along the line, shown below in the first image. As you can see it actually misses a few squares along the projection, the ones highlighted in the second image in green.

Bresenham.svgModifiedBresenham

The Bresenham algorithm also uses real numbers which means using float, double or decimals in C#, all of which have issues. Float and doubles are limited precision so you end up requiring tolerance checking when you want to compare values and decimals are just too costly in time.

I found an algorithm that would walk the line matching the second image all in integers but this was flawed when projecting the line diagonally, say (0, 0) -> (4, 4) in that it would step strangely and give an asymmetric line of sight depending on if you were tracing (0, 0) -> (4, 4) or (4, 4) -> (0, 0). This was quickly fixed up such that a trace of (0, 0) -> (4, 4) would yield (0, 0) (1, 1) (2, 2) (3, 3) (4, 4). This leaves the dilemma, does (0, 1) block line of sight or not as the line really touches the corner but does not enter the square, I decided not to include off the line in these situations.

The result is the following, a function that produces an enumerable list of the squares you must check between two points. It is a lazy generator so will only produce the trace while you consume it.

public static IEnumerable CastRay(
    this Vector start, Vector end, bool includeStart, bool includeEnd)
{
    var delta = (start - end).Abs();

    var current = start;

    var xIncrement = (end.X > start.X) ? 1 : -1;
    var yIncrement = (end.Y > start.Y) ? 1 : -1;

    var error = delta.X - delta.Y;
    var errorCorrect = delta * 2;

    while (true)
    {
        if ((current == start && includeStart) ||
            (current == end && includeEnd) ||
            (current != start && current != end))
        {
            yield return current;
        }

        if (current == end)
        {
            yield break;
        }

        if (error > 0)
        {
            current = Vector.Create(current.X + xIncrement, current.Y);
            error -= errorCorrect.Y;
        }
        else if (error < 0)
        {
            current = Vector.Create(current.X, current.Y + yIncrement);
            error += errorCorrect.X;
        }
        else
        {
            current = Vector.Create(
            current.X + xIncrement,
            current.Y + yIncrement);
        }
    }
}

This is the building block that all my line of sight code is based on from determining if actor 1 can see actor 2 through to building a field of view projection for the player so the render engine knows what is visible to the player. It would have been nice to remove the need for the loop but limitation in tail recursion in C# means that a recursive solution is not really viable.

Determining if a target is visible to the player become trivial as shown below.

public static bool CanSee(
    this Vector location, Vector target, 
    Func<Vector, bool> blocksLineOfSight)
{
    return CastRay(location, target, false, false)
        .All(x => !blocksLineOfSight(x));
}

All we need to do is walk the line and ensure that none of the squares block the line of sight. The Func<Vector, bool> is used to test if a square blocks the line of sight making the code map agnostic so it is easy to use in any 2D grid based world no matter how it is stored.

Calculation of the map area visible to the player is also based off the same ray casting building block. It simply calculates all the locations around the edge of the area you want to test, cast a ray to each and then walks the ray until a blocking square is located. While this is not quite as efficient as techniques like shadow casting it provides a far better representation with no strange artefacts.

The final code is all available Here.

A* pathfinding

The task of the past week has been to port my old A* PathFinding from my previous Roguelike engine into this engine. The primary changes I wanted to make were:

  • The code had to be map agnostic so I could reuse it elsewhere.
  • Moved from imperative code to a more functional implementation.

The first of these was the easiest to get done. The code now knows nothing above the map it will traverse, instead it takes a function with the signature Func<Vector, bool>. This is used to check the location on a map to see if the move is valid or not.

The refactor into the functional space took longer and many rewrites to get into a good shape. In the end I scrapped the original code and went back to basics to rebuild from the ground up.

If you are new to A* then  A* Pathfinding for Beginners is a good starting point to understand how path finding works.

My starting point was the data structures for the Open and Closed lists. It is common to see some form of Priority Queue for the Open List and a List for the Closed List. The Priority Queue is typically used for the Open List so that the next cheapest open entry is first in the list.

I avoided these options because the reality is that you need to locate nodes in the open and closed list but location, this means a worst case of an O(n) operation to locate the entry. As I am in the functional space I used ImmutableDictionary<Vector, LocationCandidate> for each. This gives me O(log n) lookup by location which is a good improvement.

The downside of this choice is the Open List is not sorted. The standard Linq solution to this would be:

var nextCandidate = openList.OrderBy(x => x.OverallCost).First()

This is far from ideal as it requires sorting the Open List each parse which is too costly on long paths, I believe it is an O(n log n) operation. This was solved by creating a new Linq style extension:

T MinBy<T, TKey>(this IEnumerable self, Func<T, TKey> selector)

With this the location of the next node becomes a simple scan which is an O(n) operation so far cheaper.

The rest of the code fell into place well after these sticking points were solved as it became a mechanical implementation of the algorithm. The only sticking point was being forced into using a while loop to pick the next candidate each parse due to C# not implementing Tail Call optimisation 😦

The results of this can be seen on GitHub at Woz.PathFinding. The unit tests at Woz.PathFinding.Tests show how easy it is to use with any map structure.

Soooo, the Asus T200TA

I have spent the last few days with the Asus T200TA 2 in 1, currently it is back in the box and waiting for the shops to open on Tuesday for a full refund.

I love the form factor, the machine appears good enough to run Visual Studio 2013 with full ReSharper stack, its light enough and small enough for to make truly portable. So what it wrong with it?

To put bluntly it appears that either Asus can’t make drivers or the hardware is just a crock of shit!

After hours of initial install of windows updates and my development stack I find the Wi-Fi is failing to connect to my network. Reading through various forums I find this is stupidly common in the T100 and T200 models. I tried the new drivers to no avail. A complete re-install of Windows later and initially it works again initially but windows updates installed and the problem comes back again. I did this cycle a few more times but am just not willing to figure out which of the 120 updates is causing the issue. Even if I find the problem update it still means I have a security hole left open and run the risk of the next windows update bricks the Wi-Fi again.

Given the length of time Asus have had this model out I cant believe they have been so inept that forums remain awash with the issue. It will be a long time before I buy Asus again!!!!!

New Tablet and also JetBrains License

The next couple of days will be busy. I have just bought an Asus T200TA as a travel PC for dev on the go, saves lugging around my main Dev/Gaming trusty HP laptop. So first port of call is to install my tool chain on the new device. VS2013, Git etc

Also with perfect perfect timing, BadlyDrawRogue has been running long enough that I qualify for the JetBrains open source license which means I have just got my hands on ReSharper Ultimate which will go onto my main dev laptop and tablet, many thanks to JetBrains on this. Can’t wait to try out the tools this includes, I will write up more on these as I get used to what is included 🙂

So now I have hours of watching progress bars ahead of me as I install everything…

System.Drawing.Point….. WTF

I had been using System.Drawing.Point as my means of storage for game coordinates until now. During my time catching up with unit tests I had a horrific realisation. Against all best practice information on structs in C# I found that Point is in fact a mutable struct.

I think I need to write that one more time so it can sink in…. Point is a MUTABLE struct.

Having a value type that is mutable is an oxymoron so all I can figure is that Point has been around since .NET V1 days when the advice was different and changing it now would break loads of existing code.

Given that I am aiming for fully immutable state this is catastrophic. I am just glad that I have caught this at this stage in development and not later down the line when a refactor to a different type would have been far more ugly and time consuming in nature. Even at this state without my friend ReSharper this could have been far worse than it needed to be.

So now I have a new Coordinate struct that is nice and safe and immutable. Shame that I was forced into this extra work because of the mess Microsoft had caused in their own core library but that is life at the code face 🙂