Thursday, December 21, 2017

WinForms TextBox Get as Double or Integer

I always end up returning to Windows Forms when I want to code some tool or prototype an idea. This time I just want to share two extension methods for retrieving the contents of a TextBox as an Integer or a Double.

public static double AsDouble(this TextBox textBox)
{
 var s = textBox.Text.Replace(",", ".").Trim();
 return double.TryParse(s, out var d) ? d : double.NaN;
}
public static int AsInt(this TextBox textBox)
{
 var s = textBox.Text.Trim();
 return int.TryParse(s, out var i) ? i : 0;
}

The colon to period replacement is to ensure that Swedish formatting works with the default parser. No guarantee that it will work with all cultures.


All code provided as-is. This is copied from my own code-base, May need some additional programming to work. Use for whatever you want, how you want! If you find this helpful, please leave a comment, not required but appreciated! :)

Hope this helps someone out there!

Thursday, December 7, 2017

Asserting floating point values in unit tests


Just a few methods to help out with unit testing, mainly for asserting floating point values (float, double) to be within a tolerance of the expected value

public static class Dessert
{
    public static void AreEqual(double expected, double actual, double tolerance)
    {
        Assert.IsTrue(expected.IsEqual(actual, tolerance),
            $"{Environment.NewLine}Dessert.AreEqual(double, double) failed. Expected:<{expected}>. Actual<{actual}>. Tolerance<{tolerance}>");
    }
        
    public static void AreEqual(float expected, float actual, float tolerance)
    {
        Assert.IsTrue(expected.IsEqual(actual, tolerance),
            $"{Environment.NewLine}Dessert.AreEqual(float, float) failed. Expected:<{expected}>. Actual<{actual}>. Tolerance<{tolerance}>");
    }
}

How to use:

Dessert.AreEqual(2700, weight, 0.000000000000001);

All code provided as-is. This is copied from my own code-base, May need some additional programming to work. Use for whatever you want, how you want! If you find this helpful, please leave a comment, not required but appreciated! :)

Hope this helps someone out there!

Wednesday, November 15, 2017

Distances to human readable text in C#


Needed a function that converts a double to a human readable distance in my latest project, ended up writing the following function.
Input argument is in meters.
For values less than 1 meter, the result is given as centimeters.
For values up to 10 km, the values are given with one decimal.
Values up to one tenth of an Astronomical Unit are given as kilometers.
Values between one tenth of an Astronomical Unit and one tenth of a Parsec are given in Astronimical Units.
Values larger then one tenth of a Parsec are given in Parsecs.

Example output
Input
Output
0.533
53 cm
-1 -1 m
1 1 m
3,08568E+16 1.0 pc
3,08568E+17 10.0 pc
1,49598E+12 10.0 AU
1000 1.0 km
10000 10 km


The code for you to use as you please:
public const double AstronomicalUnit = 149597870700;
// https://en.wikipedia.org/wiki/Parsec
public static double Parsec { get; } = (648000 / Math.PI) * AstronomicalUnit;
public static string ToReadableDistanceFavorParsec(double meters, CultureInfo cultureInfo = null)
{
    if (cultureInfo == null)
        cultureInfo = CultureInfo.InvariantCulture;
    var sign = meters.Sign() > 0 ? string.Empty : "-";
    meters = meters.Abs();
    if (meters > (Parsec / 10))
    {
        return $"{sign}{(meters / Parsec).ToString("0.0", cultureInfo)} pc";
    }

    if (meters > (AstronomicalUnit / 10))
    {
        return $"{sign}{(meters / AstronomicalUnit).ToString("0.0", cultureInfo)} AU";
    }

    if (meters > (997))
    {

        if (meters >= (10000))
        {
            return $"{sign}{(meters / 1000).ToString("0", cultureInfo)} km";
        }
        return $"{sign}{(meters / 1000).ToString("0.0", cultureInfo)} km";
    }

    if (meters < 1)
    {
        return $"{sign}{meters * 100:0} cm";
    }
    return sign + meters.ToString("0") + " m";
}


All code provided as-is. This is copied from my own code-base, May need some additional programming to work. Use for whatever you want, how you want! If you find this helpful, please leave a comment, not required but appreciated! :)

Hope this helps someone out there!

Friday, October 13, 2017

System.Math extension methods

Why

Because I've lately started to think a little more functional, this also allows for nice chaining of calls to the Math class.

How to use

Say you want to calculate the angle between 2 vectors by taking arc cosine of our dot product to give us the angle:
With normal Math usage..
var dot = vector1.X* vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
double radians = Math.Acos(dot);
Same example with our extensions
var dot = vector1.X* vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
double radians = dot.Acos();

The above example but with a method to calculate the dot product.
double radians = vector1.Dot(vector2).Acos();


Code for your pleasure

public static class MathExtensions
{
    public static decimal Abs(this decimal d)
    {
        return Math.Abs(d);
    }
    public static float Abs(this float d)
    {
        return Math.Abs(d);
    }
    public static double Abs(this double d)
    {
        return Math.Abs(d);
    }
    public static int Abs(this int d)
    {
        return Math.Abs(d);
    }
    public static long Abs(this long d)
    {
        return Math.Abs(d);
    }
    public static short Abs(this short d)
    {
        return Math.Abs(d);
    }
    public static short Abs(this byte d)
    {
        return Math.Abs(d);
    }
    public static decimal Max(this decimal d, decimal x)
    {
        return Math.Max(d, x);
    }
    public static float Max(this float d, float x)
    {
        return Math.Max(d, x);
    }
    public static double Max(this double d, double x)
    {
        return Math.Max(d, x);
    }
    public static int Max(this int d, int x)
    {
        return Math.Max(d, x);
    }
    public static long Max(this long d, long x)
    {
        return Math.Max(d, x);
    }
    public static short Max(this short d, short x)
    {
        return Math.Max(d, x);
    }
    public static short Max(this byte d, byte x)
    {
        return Math.Max(d, x);
    }
    public static decimal Min(this decimal d, decimal x)
    {
        return Math.Min(d, x);
    }
    public static float Min(this float d, float x)
    {
        return Math.Min(d, x);
    }
    public static double Min(this double d, double x)
    {
        return Math.Min(d, x);
    }
    public static int Min(this int d, int x)
    {
        return Math.Min(d, x);
    }
    public static long Min(this long d, long x)
    {
        return Math.Min(d, x);
    }
    public static short Min(this short d, short x)
    {
        return Math.Min(d, x);
    }
    public static short Min(this byte d, byte x)
    {
        return Math.Min(d, x);
    }

    public static int Sign(this decimal d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this float d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this double d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this int d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this long d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this short d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this byte d)
    {
        return Math.Sign(d);
    }
    public static decimal Floor(this decimal d)
    {
        return Math.Floor(d);
    }
    public static double Floor(this float d)
    {
        return Math.Floor(d);
    }
    public static double Floor(this double d)
    {
        return Math.Floor(d);
    }
    public static decimal Round(this decimal d)
    {
        return Math.Round(d);
    }
    public static decimal Round(this decimal d, int x)
    {
        return Math.Round(d, x);
    }
    public static decimal Round(this decimal d, int x, MidpointRounding mr)
    {
        return Math.Round(d, x, mr);
    }
    public static decimal Round(this decimal d, MidpointRounding mr)
    {
        return Math.Round(d, mr);
    }
    public static double Round(this float d)
    {
        return Math.Round(d);
    }
    public static double Round(this double d)
    {
        return Math.Round(d);
    }
    public static double Round(this double d, int x)
    {
        return Math.Round(d, x);
    }
    public static double Round(this double d, int x, MidpointRounding mr)
    {
        return Math.Round(d, x, mr);
    }
    public static double Round(this double d, MidpointRounding mr)
    {
        return Math.Round(d, mr);
    }
    public static decimal Ceiling(this decimal d)
    {
        return Math.Ceiling(d);
    }
    public static double Ceiling(this float d)
    {
        return Math.Ceiling(d);
    }
    public static double Ceiling(this double d)
    {
        return Math.Ceiling(d);
    }
    public static double Acos(this double d)
    {
        return Math.Acos(d);
    }
    public static double Asin(this double d)
    {
        return Math.Asin(d);
    }
    public static double Atan(this double d)
    {
        return Math.Atan(d);
    }
    public static double Atan2(this double d, double x)
    {
        return Math.Atan2(d, x);
    }
    public static double Cos(this double d)
    {
        return Math.Cos(d);
    }
    public static double Cosh(this double d)
    {
        return Math.Cosh(d);
    }
    public static double Exp(this double d)
    {
        return Math.Exp(d);
    }
    public static double Sin(this double d)
    {
        return Math.Sin(d);
    }
    public static double Sinh(this double d)
    {
        return Math.Sinh(d);
    }
    public static double Tan(this double d)
    {
        return Math.Tan(d);
    }
    public static double Tanh(this double d)
    {
        return Math.Tanh(d);
    }
    public static long BigMul(this int a, int b)
    {
        return Math.BigMul(a, b);
    }
    public static double IEEERemainder(this double d, double y)
    {
        return Math.IEEERemainder(d, y);
    }
    public static double Log(this double d)
    {
        return Math.Log(d);
    }
    public static double Log(this double d, double x)
    {
        return Math.Log(d, x);
    }
    public static double Log10(this double d)
    {
        return Math.Log10(d);
    }
    public static double Sqrt(this double d)
    {
        return Math.Sqrt(d);
    }
    public static decimal Truncate(this decimal d)
    {
        return Math.Truncate(d);
    }
    public static double Truncate(this double d)
    {
        return Math.Truncate(d);
    }
    public static double Pow(this double d, double power)
    {
        return Math.Pow(d, power);
    }
}

Quite a lot of overloads, I think I got them all but if you find that I've missed one, please comment on this post and I will add it!

All code provided as-is. This is copied from my own code-base, May need some additional programming to work. Use for whatever you want, how you want! If you find this helpful, please leave a comment, not required but appreciated! :)

Hope this helps someone out there!


Sunday, October 1, 2017

Functional adventures in .NET C# - Part 2, Application State


This part we will look at how to store and manipulate application/game state in an ordered fashion. This is heavily inspired by the React/Redux web development (javascript) patterns. My thoughts were, why not use the same in my game code as the end results are pretty clean and structured?

This is part 2 of this series. Here are links to all the other posts:
Functional adventures in .NET C# - Part 1, Immutable Objects
Functional adventures in .NET C# - Part 2, Application State

Update 2018-03-15: I only wrote 2 posts on C# functional constructs. And after embarking on a large game project with it I started looking at F#. To read the F# source code of this post, head over to Functional Adventures in F# - Application State

General Idea

At any given point in time, the whole application state is stored in a class named Application State, it consists of different Stores and they in turn consist of the object model for each store. I.e. Fleet Store might contain Fleets that consists of Ships. All updates to the model are routed to the store in the form of Actions. The application state is immutable, meaning that any object that you get a reference to will never mutate into something else (see previous post in this series on Immutable objects)

Add object to a store
Say that you would like to create a new object in Store Y, this would yield in a new instance of Store Y that also contains the new object. And as Store Y belongs to Application State, it would need a new instance of that as well. That still point to the old instances of Store X & Z but a new instance of Y.

Update object in a store
If you in turn would like to update a object that is deeper in the structure inside Store Z, you would create a copy (call the Modify method) on that object. But as it returns a new object, you would have to propagate the change to the parent object (SetItem if it is in the System.Collections.Immutable namespace, or Modify if it is our own) and then propagate it to a new version of the application state object as well.

Remove object from a store
And it is pretty much the same for when you want to remove objects, you remove the object reference from the parent object by calling Remove or Modify depending on if it is a collection or our own object. And then you propagate the change up all the way to a new Application State object.


Code

So, now that we know the general idea lets look at some code. At the moment I decided to only propagate the change to the store and let the ApplicationState class be the entry point to the different stores. So not 100% immutable, only where it counts.. I.e. the model.

Application State

The ApplicationState (or GameState in this case) contains references to all the different stores.
public static class GameState
{
    private static FleetStore _fleetStore;

    public static FleetStore FleetStore
    {
        get
        {
            if(_fleetStore == null)
                _fleetStore = new FleetStore();
            return _fleetStore;
        }
        set
        {
            _fleetStore = value;
        }
    }
}
I decided to have this globally accessible so that the whole game can read the current application state  and dispatch actions from this static context.

Actions

Actions are pretty much POCOs (plain old class objects)
public class CreateFleet
{
    public string Name { get; }
    public CreateFleet(string name)
    {
        Name = name;
    }
}
These are safe objects, if any part of the application wants to change state they are not allowed to call the modify method by themselves. Even if they did they would not be able to propagate the change properly so that it becomes visible. Instead they create an Action object describing the change that they want to be done and send it to the Store.

Stores and Action Handlers

The store holds the immutable state of its model and handles all actions.
First of, lets look at the abstract base class for all of the stores.
public abstract class AStore<TItem>
{
 public ImmutableList<TItem> State { get; protected set; }
 private ImmutableDictionary<Type, Action<object>> _actionHandlers;
 private readonly object _lock = new object();
 public AStore()
 {
  State = ImmutableList<TItem>.Empty;
  _actionHandlers = ImmutableDictionary<Type, Action<object>>.Empty;
 }

 public void HandleAction(object action)
 {
  lock (_lock)
  {
   var actionType = action.GetType();
   var handlers = _actionHandlers;
   if (handlers.TryGetValue(actionType, out var actionHandler))
   {
    actionHandler(action);
   }
  }
 }

 public void HandleActionAsync(object action)
 {
  ThreadPool.QueueUserWorkItem(HandleAction, action);
 }

 protected void AddActionHandler(Type actionType, Action<object> actionHandler)
 {
  _actionHandlers = _actionHandlers.Add(actionType, actionHandler);
 }
}

First of, we have the State stored as a ImmutableList<T>, all changes to objects managed by this store will propagate to this State object and replace it with a new reference. The State is public and is read by the rest of the application.

Secondly we have a dictionary of Action Handlers. Here we can lookup the correct action handler with the help of the Type of the action.

There is only 2 public methods, HandleActionAsync. All it does is to dispatch the action to the threadpool.
The HandleAction is pretty basic, it tries to get an action handler for the object type it received and either dispatches the action to the correct handler or does nothing. All this is done inside a lock to ensure that only 1 thread is writing at a time.
I am not 100% satisfied with this solution to serialize the writes, if you have a better solution please do not hesitate to share in the comments!

There is also only 1 protected method, AddActionHandler. This is used by all sub-classes that inherit from this abstract class to register action handlers that are defined in their code.

Example of concrete store. In this case taken from my space game.
public class FleetStore : AStore<Fleet>
{
 private uint _currentFleetId;
 private uint _currentShipId;
 public FleetStore()
 {
  AddActionHandler(typeof(CreateFleet), CreateFleet);
  AddActionHandler(typeof(RemoveFleet), RemoveFleet);
  AddActionHandler(typeof(CreateShip), CreateShip);
  AddActionHandler(typeof(MoveShipToFleet), MoveShipToFleet);
  AddActionHandler(typeof(SetShipTargetVector), SetShipTargetVector);
 }
Here we see that in the constructor the class registers all action handlers with the help of the AddActionHandler method.

Example of Add action handler
private void CreateFleet(object action)
{
 var a = (CreateFleet) action;
 var fleet = Fleet.Default.Modify(_currentFleetId++, a.Name);
 State = State.Add(fleet);
}
Here we use the Fleet.Default reference (instead of calling new) to create a new immutable fleet and then call Add on the State list. And finally replace the State with the new State so that it sticks.

Example of Remove action handler
private void RemoveFleet(object action)
{
 var a = (RemoveFleet)action;
 var item = State.FirstOrDefault(x => x.Id == a.Id);
 State = State.Remove(item);
}
Here we find the item to remove with a query and then call Remove on the state list and replace the old state with the new state.

And finally an example of Update action handler
private void SetShipTargetVector(object action)
{
 var a = (SetShipTargetVector)action;
 var originalFleet = State.FirstOrDefault(x => x.Id == a.FleetId);
 var originalShip = originalFleet.Ships.FirstOrDefault(x => x.Id == a.ShipId);
 
 var ship = originalShip.Modify(targetCoordinates: a.Target);
 var ships = originalFleet.Ships.SetItem(originalFleet.Ships.IndexOf(originalShip), ship);
 var fleet = originalFleet.Modify(ships: ships);
 State = State.SetItem(State.IndexOf(originalFleet), fleet);
}
This is an update of a field a little bit deeper in the object structure.
First we need to find the Fleet from the state list.
After that we find the ship from the fleets list of ships.
Then we modify the ship and store the new state in a new variable.
Then we use the old ship to find the index in the list that we want to replace with the new ship. We store the new immutable list in a new variable.
After that we modify the fleet and set the new list of ships with the Modify command and store the new fleet.
Lastly we update the State with SetItem and replace the old State with the new one.


Hope this helps someone out there getting started with immutable application state in C#, or at least getting some new ideas. Thank you for reading, here's a video of one of our cats

Saturday, September 30, 2017

Functional adventures in .NET C# - Part 1, immutable objects


Lately I've been converted to the immutable data train, working with web technologies like React/Redux. I've started to wonder why I don't build all applications with immutable data, as it removes a big headache, if you get a reference to a data structure it will _always_ be the same data in it. Not like when you are working with ordinary data structures, where other threads or sub-functions can modify the in data when you aren't looking.

This is part 1 of this series. Here are links to all the other posts:
Functional adventures in .NET C# - Part 1, Immutable Objects
Functional adventures in .NET C# - Part 2, Application State

So, my native platform is .NET and C#, is there a way to work with immutable data out of the box or do we have to write something ourselves? It turns out that Microsoft has released an immutable library System.Collections.Immutable outside of the ordinary .NET versions as a NuGet package.
It has all the collections like
  • System.Collections.Immutable.ImmutableArray
  • System.Collections.Immutable.ImmutableArray<T>
  • System.Collections.Immutable.ImmutableDictionary
  • System.Collections.Immutable.ImmutableDictionary<TKey,TValue>
  • System.Collections.Immutable.ImmutableHashSet
  • System.Collections.Immutable.ImmutableHashSet<T>
  • System.Collections.Immutable.ImmutableList
  • System.Collections.Immutable.ImmutableList<T>
  • System.Collections.Immutable.ImmutableQueue
  • System.Collections.Immutable.ImmutableQueue<T>
  • System.Collections.Immutable.ImmutableSortedDictionary
  • System.Collections.Immutable.ImmutableSortedDictionary<TKey,TValue>
  • System.Collections.Immutable.ImmutableSortedSet
  • System.Collections.Immutable.ImmutableSortedSet<T>
  • System.Collections.Immutable.ImmutableStack
  • System.Collections.Immutable.ImmutableStack<T>
All well and good! But what of the all the POCO (plain old class object) and domain objects in your code? These need to be converted to immutables as well if you are to build something that can be relied upon.

So, how to do this in a simple way? After searching a bit on how other people are doing this I found this article by @davepermen and decided to take some of the ideas from there.

So here is the pattern that I'm currently using in a space game that I'm writing on my spare time.
public class Fleet
{
    public static Fleet Default { get; } = new Fleet();

    public uint Id { get; }
    public string Name { get; }
    public ImmutableDictionary<ShipType, ImmutableList<Ship>> Ships { get; }
        
    private Fleet()
    {
        Ships = ImmutableDictionary<ShipType, ImmutableList<Ship>>.Empty;
    }
    private Fleet(uint id, string name, ImmutableDictionary<ShipType, ImmutableList<Ship>> ships)
    {
        Id = id;
        Name = name;
        Ships = ships;
    }

    public Fleet Modify(uint? id = null,
        string name = null, 
        ImmutableDictionary<ShipType, ImmutableList<Ship>> ships = null)
    {
        return new Fleet
        (
            id ?? Id,
            name ?? Name,
            ships ?? Ships
        );
    }
}

Some key points.
Private constructor
The constructors are private, as the class is immutable, there is no real reason to have multiple 'new' fleet objects, just get the reference to the Default object.
So to create a new fleet we would do something like:
var fleet = Fleet.Default.Modify(_currentFleetId++, a.Name);
I.e. we get the reference to the default object and call Modify on it with the stuff that we want to have in our new fleet object.

All public fields are getters only
So that you can read the values from outside, but not set them other then from the constructor.

The Modify(T name = null) method
The only way to 'modify' state is to create use this method, and it does not really modify the state but it creates a new state based on the input. All attributes are nullable and with default values so that you only need to specify the values that change. The non-provided values will be copied from this object.
I.e. setting only the name would be like this:
fleet = fleet.Modify(name: "Battlestar!");

Explicit set to null methods
If you need to be able to set a value specifically to null, you would have to create a specific Modify method for that value, as if you send in null to the one provided it would copy the value from this instead of setting it to null.

public Ship RemoveTargetCoordinates()
{
    return new Ship
    (
        Id,
        Coordinates,
        ShipType,
        Health,
        MaxSpeed,
        Acceleration,
        Deceleration,
        null
    );
}
In this example we provide a copy from the current instance of all values but the one we want to set to null. Not the prettiest solution but works for now.

Update 20171003
There is no need to set to null, set the value to Default instead and instead of doing a null check check against the Default value. This solved all my 'set to null' issues in my code base so far. And this way there will not be a null reference exception in the middle of a chained function call.

Hope this helps someone out there getting started with functional programming in C#



Sunday, September 10, 2017

Typescript Array.Map


TypeScript made me go back to web development again, bringing in the compile time type checks really makes it easier to write correct code faster.
But sometimes it is a little tricky to figure out the syntax. For example last night when I tried to store the result from an array.map call in a variable. Most of the examples I found used the var keyword and pretty much ignoring the type check making me wonder why even bother with TypeScript if you don't use the types?

So, I wanted to try the array.map in the render method of a React JSX file to render a list of items. The end result was something like this:
public render() {
 const itemNames: string[] = ["Item One", "Item Two"];
 let itemNamesRender: JSX.Element[] = equipmentNames.map((name: string) => <li>{name}</li>);
 return <div>
  <h1>My Items</h1>

  <ul>{equipmentNamesRender}</ul>
 </div>;
}

Where the
let result: JSX.Element[] = array.map()
is the key. So pretty much just like all other variable declarations. The issue I had turned out to be that I didn't know that the type was JSX.Element, instead I was trying to force it to a string type.

Hope this helps someone out there. : )

Friday, July 21, 2017

Expression evaluation over time - Was?


A closer look at the Was query to determine if something has been, builds heavily on the previous articles in this series.

Other articles in the AI Knowledge Based Reasoning series on this site:
Knowledge based reasoning in .net c#
Reasoning in Open or Closed models
Logic Expression evaluation with open-world assumption
Expression evaluation on object based models
Expression evaluation over time
Expression evaluation over time - Was?

Definition of Was

So lets start with defining what we mean when we say Was.
Was Mikaela angry?
Is there a previous frame where the logical expression Feeling(Angry) results in true?
There is also a meaning of this to not be the case at some point after it was true.

Lets look at this in a table form to get our bearings straight.
FrameNameOccupationEye-colorHair-color
1MikaelaStudentBlueBrown
2MikaelaPearlescent
3MikaelaPink
4MikaelaJunior Software DeveloperBlue
5MikaelaSoftware DeveloperBlonde
6MikaelaSenior Software DeveloperPearlescent
7MikaelaSoftware ArchitectBrown

At this point was could ask,

WAS Occupation(Student)
Would be true, as there is a frame where Mikaela was a student. and after that something else.

WAS Name(Mikaela)
Would not be true, as she is Mikaela and has never had any other name

WAS Occupation(Software Architect)
Would not be true, as she currently is and there is no previous frame where she was

WAS HairColor(Brown)
Would be true, she still is in the current frame, but there was other hair colors for at least one frame and all the way back there was Brown again.

Unit tests

Lets look at this in unit test form

[TestClass]
public class RelativeWasTest
{
    [TestMethod]
    public void RelativeWasTest_True()
    {
        Context target;
        var obj = CreateTarget(out target);
            
        var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Student", Relation = "Occupation of", Target = obj.ToString() });
        var relative = new RelativeWas(expr2);
        var actual = target.Evaluate(relative);
        Assert.AreEqual(EvaluationResult.True, actual);
    }
    [TestMethod]
    public void RelativeWasTest_False()
    {
        Context target;
        var obj = CreateTarget(out target);

        var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Lawyer", Relation = "Occupation of", Target = obj.ToString() });
        var relative = new RelativeWas(expr2);
        var actual = target.Evaluate(relative);
        Assert.AreEqual(EvaluationResult.False, actual);
    }
    [TestMethod]
    public void RelativeWasTest_True_PeriodOfWasNot()
    {
        Context target;
        var obj = CreateTarget(out target);

        var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Black", Relation = "HairColor of", Target = obj.ToString() });
        var relative = new RelativeWas(expr2);
        var actual = target.Evaluate(relative);
        Assert.AreEqual(EvaluationResult.True, actual);
    }
    [TestMethod]
    public void RelativeWasTest_NotSure()
    {
        Context target;
        var obj = CreateTarget(out target);

        var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Student", Relation = "Lunch of", Target = obj.ToString() });
        var relative = new RelativeWas(expr2);
        var actual = target.Evaluate(relative);
        Assert.AreEqual(EvaluationResult.NotSure, actual);
    }

    private static Person CreateTarget(out Context target)
    {
        var obj = new Person("Alice")
        {
            Occupation = "Student",
            HairColor = "Black"
        };
        target = new Context(obj.ToString());
        target.AddFrame(FrameFactory.Create(obj));

        obj.Occupation = string.Empty;
        obj.HairColor = "Pearlescent";
        target.AddFrame(FrameFactory.Create(obj));

        obj.Occupation = string.Empty;
        obj.HairColor = "Pink";
        target.AddFrame(FrameFactory.Create(obj));

        obj.Occupation = "Lawyer";
        obj.HairColor = "Black";
        target.AddFrame(FrameFactory.Create(obj));
        return obj;
    }
}

And just to make things interesting its not the exact example as in this post. Just noticed it now, but anyway. The idea is the same.

How to implement this based on the IRelative interface and Context class from the previous post.

public class RelativeWas : IRelative
{
 private readonly AExpression _expression;

 public RelativeWas(AExpression expression)
 {
  _expression = expression;
 }

 public EvaluationResult Evaluate(Context context)
 {
  var wasNot = false;
  for (int frameIndex = context.Frames.Count - 1; frameIndex >= 0; frameIndex--)
  {
   var result = context.Evaluate(_expression, frameIndex);

   if (result == EvaluationResult.NotSure)
    return EvaluationResult.NotSure;
   if (wasNot)
   {
    if (result == EvaluationResult.True)
     return EvaluationResult.True;
   }
   else
   {
    if (result == EvaluationResult.False)
     wasNot = true;
   }
  }
  return EvaluationResult.False;
 }
}


Thank you for reading! Here comes a video of our cat Prime trying fresh catnip for the first time!
All code provided as-is. This is copied from my own code-base, May need some additional programming to work.

Monday, July 3, 2017

Expression evaluation over time

We have looked at different aspects of knowledge representation during this series and this time its time to look at time itself. How to model logical expressions that incorporate time? I.e. how to store knowledge and query it with time based queries?

Other articles in the AI Knowledge Based Reasoning series on this site:
Knowledge based reasoning in .net c#
Reasoning in Open or Closed models
Logic Expression evaluation with open-world assumption
Expression evaluation on object based models
Expression evaluation over time
Expression evaluation over time - Was?

Introduction

To be able to model logic expressions that incorporate time we first have to ask ourselves, what do we mean by time? Is it abstract ideas like before, after, now and then? Or is it exact number of ticks since we began to measure? Or is it a combination of both?

This part will be quite heavy on ideas rather then code..
Turns out that I provided code for the examples as well. Enjoy : )

Discrete Time

Lets first look at some definitions of discrete time.
Discrete time views values of variables as occurring at distinct, separate "points in time", or equivalently as being unchanged throughout each non-zero region of time ("time period")—that is, time is viewed as a discrete variable -wikipedia
So basically what we say is that even though time is continuous, we will look at it in a discrete way just to simplify our models.

Events

Lets say that we receive knowledge in the form of events, all data recorded in the event will be added to our Context as one frame. For example:
Time Frame Name Occupation Eye-color Hair-color
1 Kate Student Blue Brown
2 Kate Pearlescent
3 Kate Pink
4 Kate Student Blue
5 Kate Intern Blonde
6 Kate
Pearlescent
7 Kate Lawyer Brown
Time frame can be incremental number if we don't care about actual time passed or a time stamp of when the even occurred.
So lets store all our data in this form.

Full frame from incomplete frames

How to query something like the above example?
One idea is to see each event as its own frame of context. I.e. all expressions written in previous posts would now be transferred to refer only to one frame at a time. But that would be kind of incomplete as all events do not record data on all possible parameters. One way to work around this would be to always start from the latest frame and search backwards in the frame-stack until that parameter gets hit. For example in the example above, a full 'latest' frame of information would be the blue highlighted information as seen in the following table:
Time Frame Name Occupation Eye-color Hair-color
4 Kate Student Blue
5 Kate Intern Blonde
6 Kate
Pearlescent
7 Kate Lawyer Brown

Occupation(Lawyer) AND Eye-color(Blue) AND Hair-color(Brown)
Would return True

Occupation(Intern) AND Eye-color(Blue) AND Hair-color(Brown)
Would evaluate to False, as it is not the last full aggregate frame. See Occupation column has newer entries then Intern.

Occupation(Lawyer) AND Eye-color(Blue) AND Drives(Volvo XC90)
Would evaluate to Not Sure as there is no event recording any knowledge about what car Kate drives.

Lets look at some C# code to do just that. Lets convert our Evaluate method in the Context class to the following instead:
public EvaluationResult Evaluate(AExpression expression, int frameStart = -1)
{
    if (frameStart == -1)
        frameStart = _frames.Count - 1;
    var facts = new Dictionary<ExpressionLeaf, EvaluationResult>();
    var leafNodes = expression.GetLeafNodes();
    foreach (var node in leafNodes)
    {
        var leaf = node.Leaf;
        var attr = leaf as KnowledgeAttribute;
        var rel = leaf as KnowledgeRelation;
        if (!(attr != null | rel != null))
            continue;
        for (int i = frameStart; i >= 0; i--)
        {
            var frame = _frames[i];
            var result = attr != null ? frame.Evaluate(attr) : frame.Evaluate(rel);

            if (result == EvaluationResult.NotSure)
                continue;
            facts.Add(node, result);
            break;
        }
    }
    if (!facts.Any())
        return EvaluationResult.NotSure;
    if (facts.Values.Any(x => x == EvaluationResult.NotSure))
        return EvaluationResult.NotSure;
    return expression.TransformEvaluation(facts);
}
And the frame/event store looks something like this (still in the Context class):
private readonly List<KnowledgeStore> _frames;
public IReadOnlyCollection<KnowledgeStore> Frames => new ReadOnlyCollection<KnowledgeStore>(_frames);
public KnowledgeStore CurrentFrame => _frames.Last();
public void AddFrame(KnowledgeStore frame)
{
    _frames.Add(frame);
}

Relative queries

So now we have covered how to determine the current state from this event based knowledge store. Next step is to start determining how knowledge relates to each other based on relative time queries.

For this we will need to add an Evaluate method in the Context class for just relative queries:
public EvaluationResult Evaluate(IRelative expression)
{
    return expression.Evaluate(this);
}

All keyword

Time Frame Name Occupation Eye-color Hair-color
1 Kate Student Blue Brown
2 Kate Pearlescent
3 Kate Pink
4 Kate Student Blue
5 Kate Intern Blonde
6 Kate
Pearlescent
7 Kate Lawyer Brown
This one is pretty simple, it just states that All knowledge frames in the store should evaluate the expression to true.
I.e. ALL Name(Kate) AND Eye-color(Blue)
would be True.
But ALL Occupation(Lawyer) would evaluate to False as there exists frames where this statement is false.
And as before, including a fact from a column that has no recorded data in the query would result in Not Sure.

public class RelativeAll : IRelative
{
    private readonly AExpression _expression;

    public RelativeAll(AExpression expression)
    {
        _expression = expression;
    }

    public EvaluationResult Evaluate(Context context)
    {
        var result = EvaluationResult.NotSure;
        for (int frameIndex = context.Frames.Count - 1; frameIndex >= 0; frameIndex--)
        {
            result = context.Evaluate(_expression, frameIndex);
            if(result == EvaluationResult.False)
                return EvaluationResult.False;
        }
        return result;
    }
}

Some unit tests to see how it behaves:
[TestMethod]
public void RelativeAllTest_AddFrame_CurrentUpdated()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr = new ExpressionIs(new KnowledgeRelation { Subject = "Lawyer", Relation = "Occupation of", Target = obj.ToString() });
    var actual = target.Evaluate(expr);
    Assert.AreEqual(EvaluationResult.True, actual);
}

[TestMethod]
public void RelativeAllTest_All_True()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr = new ExpressionIs(new KnowledgeRelation
    {
        Subject = "Alice",
        Relation = "Name of",
        Target = obj.ToString()
    });
    var rel = new RelativeAll(expr);
    var actual = target.Evaluate(rel);
    Assert.AreEqual(EvaluationResult.True, actual);
}

[TestMethod]
public void RelativeAllTest_All_False()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr = new ExpressionIs(new KnowledgeRelation
    {
        Subject = "Lawyer",
        Relation = "Occupation of",
        Target = obj.ToString()
    });
    var rel = new RelativeAll(expr);
    var actual = target.Evaluate(rel);
    Assert.AreEqual(EvaluationResult.False, actual);
}

[TestMethod]
public void RelativeAllTest_All_NotSure()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr = new ExpressionIs(new KnowledgeRelation
    {
        Subject = "Undercut",
        Relation = "Hair style of",
        Target = obj.ToString()
    });
    var rel = new RelativeAll(expr);
    var actual = target.Evaluate(rel);
    Assert.AreEqual(EvaluationResult.NotSure, actual);
}

private static Person CreateTarget(out Context target)
{
    var obj = new Person("Alice");
    obj.Occupation = "Student";
    target = new Context(obj.ToString());
    target.AddFrame(FrameFactory.Create(obj));
    obj.Occupation = "Lawyer";
    target.AddFrame(FrameFactory.Create(obj));
    return obj;
}

Before keyword

Time Frame Name Occupation Eye-color Hair-color
4 Kate Student Blue
5 Kate Intern Blonde
6 Kate
Pearlescent
7 Kate Lawyer Brown

Syntax: Expression1 Before Expression2
A little harder, trying to determine if Expression1 evaluates true in a full frame before Expression2 evaluates true.
For example:
(Name(Kate) AND Occupation(Intern) AND Hair-color(Blonde)) Before (Name(Kate) AND Occupation(Intern) AND Hair-color(Pearlescent))
Would evaluate to True.

(Name(Kate) AND Occupation(Intern) AND Hair-color(Pearlescent)) Before (Name(Kate) AND Occupation(Intern) AND Hair-color(Blonde))
Would evaluate to False.

And as before, including a fact from a column that has no recorded data in the query would result in Not Sure.

Tricky one is if only one of the expressions evaluate but the other comes back Not Sure, I think for sake of consistency we should evaluate that as Not Sure also.
public class RelativeBefore : IRelative
{
    private readonly AExpression _left;
    private readonly AExpression _right;

    public RelativeBefore(AExpression left, AExpression right)
    {
        _left = left;
        _right = right;
    }

    public EvaluationResult Evaluate(Context context)
    {
        int rightFrameIndex;
        var rightResult = EvaluateExpression(context, _right, out rightFrameIndex);
        int leftFrameIndex;
        var leftResult = EvaluateExpression(context, _left, out leftFrameIndex);

        if (leftResult == EvaluationResult.NotSure || rightResult == EvaluationResult.NotSure)
            return EvaluationResult.NotSure;

        if (leftResult == EvaluationResult.True && rightResult == EvaluationResult.True)
        {
            return leftFrameIndex < rightFrameIndex ? EvaluationResult.True : EvaluationResult.False;
        }
        return EvaluationResult.False;
    }

    private EvaluationResult EvaluateExpression(Context context, AExpression expression, out int frameIndex)
    {
        var result = EvaluationResult.NotSure;
        for (frameIndex = context.Frames.Count - 1; frameIndex >= 0; frameIndex--)
        {
            result = context.Evaluate(expression, frameIndex);
            if (result == EvaluationResult.True)
            {
                return EvaluationResult.True;
            }
        }
        return result;
    }
}

Some tests to clarify things:
[TestMethod]
public void RelativeBeforeTest_True()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr1 = new ExpressionIs(new KnowledgeRelation { Subject = "Student", Relation = "Occupation of", Target = obj.ToString() });
    var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Lawyer", Relation = "Occupation of", Target = obj.ToString() });
    var relative = new RelativeBefore(expr1, expr2);
    var actual = target.Evaluate(relative);
    Assert.AreEqual(EvaluationResult.True, actual);
}
[TestMethod]
public void RelativeBeforeTest_False()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr1 = new ExpressionIs(new KnowledgeRelation { Subject = "Student", Relation = "Occupation of", Target = obj.ToString() });
    var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Lawyer", Relation = "Occupation of", Target = obj.ToString() });
    var relative = new RelativeBefore(expr2, expr1);
    var actual = target.Evaluate(relative);
    Assert.AreEqual(EvaluationResult.False, actual);
}
[TestMethod]
public void RelativeBeforeTest_LeftNotSure_NotSure()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr1 = new ExpressionIs(new KnowledgeRelation { Subject = "Undercut", Relation = "Hair style of", Target = obj.ToString() });
    var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Lawyer", Relation = "Occupation of", Target = obj.ToString() });
    var relative = new RelativeBefore(expr1, expr2);
    var actual = target.Evaluate(relative);
    Assert.AreEqual(EvaluationResult.NotSure, actual);
}
[TestMethod]
public void RelativeBeforeTest_RightNotSure_NotSure()
{
    Context target;
    var obj = CreateTarget(out target);

    var expr1 = new ExpressionIs(new KnowledgeRelation { Subject = "Undercut", Relation = "Hair style of", Target = obj.ToString() });
    var expr2 = new ExpressionIs(new KnowledgeRelation { Subject = "Lawyer", Relation = "Occupation of", Target = obj.ToString() });
    var relative = new RelativeBefore(expr2, expr1);
    var actual = target.Evaluate(relative);
    Assert.AreEqual(EvaluationResult.NotSure, actual);
}
private static Person CreateTarget(out Context target)
{
    var obj = new Person("Alice");
    obj.Occupation = "Student";
    target = new Context(obj.ToString());
    target.AddFrame(FrameFactory.Create(obj));
    obj.Occupation = "Lawyer";
    target.AddFrame(FrameFactory.Create(obj));
    return obj;
}


Conclusions and future work

The method to determine a 'full' frame by aggregating each column backwards gives room for uncertainty as we don't really consider the time between two events that are aggregated together into one frame, if we only have a few records of knowledge and the time between those events is years, then maybe we should be a little bit more uncertain.. a little bit more fuzzy in our determination. Or perhaps return a probability value together with the result. I.e.
True: 0.95
False: 0.1
NotSure: 0.4
And that way be able to build a little more smooth evaluations. But for now this suites my needs.
Another improvement could be to add variance per knowledge column. I.e. if the name is always Kate, then variance should be 0, but for the hair color in the example above it should be way higher as it changes for each event..
Addition of more types of relative expressions could be useful. Exists, Followed by, X years ago etc. But here I think the requirements for each type of project needs to guide the way.

For example source code, head over to my github repository and play around for yourself:


All code provided as-is. This is copied from my own code-base, May need some additional programming to work.

Saturday, May 13, 2017

Expression evaluation on object based models


Let's look at how to mix object based models with logical expression evaluation.

Other articles in the AI Knowledge Based Reasoning series on this site:
Knowledge based reasoning in .net c#
Reasoning in Open or Closed models
Logic Expression evaluation with open-world assumption
Expression evaluation on object based models
Expression evaluation over time
Expression evaluation over time - Was?

Many systems work on an object model of some kind, to be able to integrate logical expression evaluation to an existing system you need some way to translate from that object model to a knowledge model. This is one way to do it, there are probably better ways out there. But this works for me : )

To be able to evaluate logical expressions on an object model, you first have to translate the object model into a Knowledge model. The idea here is to scope the amount of knowledge to a certain object (or objects), lets call that scope a Context, in the case of objects lets call it an ObjectContext.
public class Context
{
 public Guid Id { get; }
 public string Name { get; }
   
 public KnowledgeStore KnowledgeStore { get; }

 public Context(string name)
 {
  Id = Guid.NewGuid();
  Name = name;
  KnowledgeStore = new KnowledgeStore(this);
 }

 public EvaluationResult Evaluate(AExpression expression)
 {
  var facts = new Dictionary<ExpressionLeaf, EvaluationResult>();
  var leafNodes = expression.GetLeafNodes();
  foreach (var node in leafNodes)
  {
   var leaf = node.Leaf;
   if(leaf is KnowledgeNon)
    continue;
   var attr = leaf as KnowledgeAttribute;
   if (attr != null)
   {
    facts.Add(node, KnowledgeStore.Evaluate(attr));
   }
   var rel = leaf as KnowledgeRelation;
   if (rel != null)
   {
    facts.Add(node, KnowledgeStore.Evaluate(rel));
   }
  }
  if (facts.Values.Any(x => x == EvaluationResult.NotSure))
   return EvaluationResult.NotSure;
  return expression.TransformEvaluation(facts);
 }
}
So, the base Context object lets us Evaluate an Expression, as we assume an open world we also allow for the response NotSure.

And for the ObjectContext, we will use reflection to create the Knowledge from the objects that we throw at it.In my case, my model inherits from a BaseObject class, but it could be any object.
public class ObjectContext : Context
{
 public BaseObject Root { get; set; }
 public ObjectContext(BaseObject root) : base(root.ToString())
 {
  Root = root;
  KnowledgeStore.AddAttribute(new KnowledgeAttribute
  {
   Attribute = root.GetType().Name,
   Subject = Name
  }, Name);
  var fields = GetAllProperties(root);
  foreach (var field in fields)
  {
   KnowledgeStore.AddRelation(new KnowledgeRelation
   {
    Subject = field.Value,
    Relation = $"{field.Key}Of",
    Target = Name
   }, Name);
  }
 }

 private Dictionary<string, string> GetAllProperties(object obj)
 {
  var d = new Dictionary<string, string>();
  var properties = obj.GetType().GetProperties();
  foreach (var prop in properties)
  {
   var val = prop.GetValue(obj);
   if (val == null)
    val = string.Empty;
   d.Add(prop.Name, val.ToString());
  }
  return d;
 }
}

So basically we will take a snapshot of the model and allow for expression evaluation on that snapshot. If the underlying model changes, the context object would need to be recreated.
As you can see we add a suffix to each attribute name, so if the object has a field called Name, the knowledge attribute would be NameOf.

Lets look at some unit tests to see how this works.
[TestClass]
public class ObjectContextTest
{
 [TestMethod]
 public void ContextTest_Evaluate_Not_False()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionNot(new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() });
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.False, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_Not_True()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionNot(new KnowledgeRelation { Relation = "NameOf", Subject = "T", Target = obj.ToString() });
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.True, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_And_BothTrue()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionAnd(
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() },
   new KnowledgeRelation { Relation = "NameOf", Subject = "Charlize", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.True, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_And_RightFalse()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionAnd(
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() },
   new KnowledgeRelation { Relation = "NameOf", Subject = "T", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.False, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_And_LeftFalse()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionAnd(
   new KnowledgeRelation { Relation = "NameOf", Subject = "T", Target = obj.ToString() },
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.False, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_And_BothFalse()
 {
  var obj = new Person("Charlize") { Gender = Person.GenderType.Female };
  var target = new ObjectContext(obj);
  var expr = new ExpressionAnd(
   new KnowledgeRelation { Relation = "NameOf", Subject = "T", Target = obj.ToString() },
   new KnowledgeRelation { Relation = "GenderOf", Subject = "male", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.False, actual);
 }
 [TestMethod]
 public void ContextTest_Evaluate_Or_BothTrue()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionOr(
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() },
   new KnowledgeRelation { Relation = "NameOf", Subject = "Kate", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.True, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_Or_RightFalse()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionOr(
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() },
   new KnowledgeRelation { Relation = "NameOf", Subject = "Kate", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.True, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_Or_LeftFalse()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionOr(
   new KnowledgeRelation { Relation = "NameOf", Subject = "Kate", Target = obj.ToString() },
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.True, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_Or_BothFalse()
 {
  var obj = new Person("Charlize") { Gender = Person.GenderType.Female };
  var target = new ObjectContext(obj);
  var expr = new ExpressionOr(
   new KnowledgeRelation { Relation = "NameOf", Subject = "Kate", Target = obj.ToString() },
   new KnowledgeRelation { Relation = "GenderOf", Subject = "Male", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.False, actual);
 }


 [TestMethod]
 public void ContextTest_Evaluate_Xor_BothTrue()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionXor(
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() },
   new KnowledgeRelation { Relation = "NameOf", Subject = "Charlize", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.False, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_Xor_RightFalse()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionXor(
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() },
   new KnowledgeRelation { Relation = "NameOf", Subject = "Kate", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.True, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_Xor_LeftFalse()
 {
  var obj = new Person("Charlize");
  var target = new ObjectContext(obj);
  var expr = new ExpressionXor(
   new KnowledgeRelation { Relation = "NameOf", Subject = "Kate", Target = obj.ToString() },
   new KnowledgeAttribute { Attribute = "Person", Subject = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.True, actual);
 }

 [TestMethod]
 public void ContextTest_Evaluate_Xor_BothFalse()
 {
  var obj = new Person("Charlize") { Gender = Person.GenderType.Female };
  var target = new ObjectContext(obj);
  var expr = new ExpressionXor(
   new KnowledgeRelation { Relation = "NameOf", Subject = "T", Target = obj.ToString() },
   new KnowledgeRelation { Relation = "GenderOf", Subject = "female", Target = obj.ToString() }
   );
  var actual = target.Evaluate(expr);
  Assert.AreEqual(EvaluationResult.False, actual);
 }
}

So, just some thoughts on how to do this. This is far from completed and is still a work in progress used by one of my home projects. Any comments are appreciated.
If you wonder why this is not on my github repository, I feel that it doesn't really have that kind of quality yet. But with time it will get there.

All code provided as-is. This is copied from my own code-base, May need some additional programming to work.



Sunday, April 9, 2017

DIY Game Financial System Part 2: Trade Algorithm


This is part of my series on DIY Game Financial System
For other posts in this series check out the following links:
DIY Game Financial System Part 1: Intro and Accounts
DIY Game Financial System Part 2: Trade Algorithm

For the full source code for the financial system discussed in this series, look in the repository.
This post we will look at the actual trade algorithm used. It is a quite naive implementation but works for me. Feel free to extend it for your own needs.

In the Marketplace class, we have an Update method that iterates through all the buy and sell orders available and tries to match them with each other. This simple implementation tries to find an exact match but there is potential to extend it to match multiple sell to one buy, or one sell to multiple sell.
In the demo application this is triggered by a timer.

public void Update()
{
 bool updated = false;
 lock(_sellOrders)
 {
  lock (_buyOrders)
  {
   foreach (var buyName in _buyOrders)
   {
    List<SellOrder> sellOrders;
    if (!_sellOrders.TryGetValue(buyName.Key, out sellOrders))
     continue;
    // naive
    foreach (var buyOrder in buyName.Value)
    {
     foreach (var sellOrder in sellOrders)
     {
      if (buyOrder.Quantity == sellOrder.Quantity
       && buyOrder.PricePerItem == sellOrder.PricePerItem)
      {
       updated = true;
       buyOrder.Execute(sellOrder);
      }
     }
    }
   }
   foreach (var order in _sellOrdersToBeRemoved)
   {
    _sellOrders[order.SecurityName].Remove(order);
   }
   foreach (var order in _buyOrdersToBeRemoved)
   {
    _buyOrders[order.SecurityName].Remove(order);
   }

  }
 }
 if (updated)
 {
  Updated?.Invoke(this, this);
 }
}

The key lines above are the
if (buyOrder.Quantity == sellOrder.Quantity
 && buyOrder.PricePerItem == sellOrder.PricePerItem)
{
 updated = true;
 buyOrder.Execute(sellOrder);
}
This tries to exactly match each buy with a sell and then trigger the Execute method:
public void Execute(SellOrder sellOrder)
{
    OrderAccount.DepositInto(sellOrder.OrderAccount, sellOrder.Quantity * sellOrder.PricePerItem);
    Security = sellOrder.ForSale;
    foreach (var action in _executeActions)
    {
        action(this);
    }
    sellOrder.Execute();
}
This is where the money is transferred between the two orders, all actions connected to this BuyOrder are triggered and then finally the sellOrder is executed as well.

When the buy order was added to the Marketplace, it associated a Cancel and Execute action with it to be triggered when the order was successful or canceled.
public void Buy(BuyOrder order)
{
 lock (_buyOrders)
 {
  if (_buyOrders.ContainsKey(order.SecurityName))
   _buyOrders[order.SecurityName].Add(order);
  else
   _buyOrders.Add(order.SecurityName, new List<BuyOrder> { order });
  order.AddCancelAction(RemoveBuy);
  order.AddExecuteAction(RemoveBuy);
 }
}
For both cases, we are just interested in removing the order from the list of available orders. The same goes for the Sell method.
private void RemoveBuy(BuyOrder order)
{
 _buyOrdersToBeRemoved.Add(order);
}
As this is triggered from an iteration of the _buyOrders collection, we need to deffer the removal to after the iteration has completed, hence the addition to a secondary removal list.
Just writing this I spotted a bug in the code where the order needs to be flagged as executed so that the same order isn't executed multiple times. I will not fix this in the demo application for now. 


Last in the Update method, a call to the Updated event handlers associated with this marketplace object.
if (updated)
{
 Updated?.Invoke(this, this);
}
This way a GUI can update itself if there was an update. The Updated event is also fired each time an order is added to the marketplace.

So there, thank you for reading. Hope this helps someone out there : )


Friday, March 10, 2017

DIY Game Financial System Part 1: Intro and Accounts

picture of commerce on river banks in the evening

I'm quite interested in finance as can be seen on my other blog dreamstateliving, and thus I decided to start working on a small but powerful in game financial system that can be used in my future games.
The goal for this system is to allow for
  • trading at a marketplace, much like the stock market
  • buying and selling stuff from vendors
Note that the code provided with this post is intended to be used in games, a lot of shortcuts have been taken. This is not a fool-proof system, more like a base to start building your own in game financial system on.

In this part we will introduce the scenario and go through the Account and TradeAccount classes.

This is part of my series on DIY Game Financial System
For other posts in this series check out the following links:
DIY Game Financial System Part 1: Intro and Accounts
DIY Game Financial System Part 2: Trade Algorithm

Introduction, a textual description

Every player, vendor etc. has their private TradeAccount consisting of a BalanceAccount and a list of Securities (items, shares whatever) owned at his current state.
Each TradeAccount is able to generate a BuyOrder based on a name of the Security to buy, the Quantity of Securities we are shopping for and the PricePerItem we are willing to pay. The BuyOrder  also contains a BalanceAccount with the amount of money needed to make the purchase. It is not possible to generate a BuyOrder if the TradeAccounts' BalanceAccount does not hold the amount of money needed to close the transaction.
In a similar fashion, each TradeAccount is able to generate a SellOrder for Securities currently held by that TradeAccount. The SellOrder also consists of the PricePerItem, Quantity and the Security for sale.

Both the SellOrder and the BuyOrder are sent to the Marketplace where the trade should be made. The Marketplace should be possible to instance as many times as needed. For example each vendor would have their own with things for sale, but the global Marketplace would allow for players to trade.

If there is an exact match on Security, Quantity and PricePerItem we will Execute the BuyOrder and transfer the money to the sellers TradeAccount and the securities to the buyers TradeAccount.
This will be our first naive algorithm to match orders.

Lets look at some code.


BalanceAccount

This is just a holder of money. Lets look at the interface.
public interface IAccount
{
    Guid Id { get; }
    ulong Balance { get; }
    bool CanAfford(ulong x);
    bool DepositInto(IAccount dest, ulong amount);
    void AddBalance(ulong amount);
}
So first we have an identifier, Id, just so that we can identify this account uniquely. Then we will store the actual current Balance of the account. I chose an unsigned long to store because of three reasons:

  • I don't really want to handle negative numbers, i.e. if you cannot afford it you can't buy it.
  • to be able to handle very large sums, I don't really know the applications for this yet, but don't want to limit someone for buying something for a ridiculous amount of money (18,446,744,073,709,551,615 to be exact)
  • I don't want to handle decimal numbers. Keep it simple, its a game :)
After that we have some functions, CanAfford checks if the account could afford to buy something costing x. 
public bool CanAfford(ulong x)
{
    return Balance >= x;
}
DepositInto withdraws money from this account and inserts it into the destination account.
public bool DepositInto(IAccount dest, ulong amount)
{
    lock (this)
    {
        if (!CanAfford(amount))
            return false;
        SubtractBalance(amount);
    }
    lock (dest)
    {
        dest.AddBalance(amount);
    }
    return true;
}
And lastly AddBalance creates money out of the blue (or you handle it somewhere else) and inserts into this account.
public void AddBalance(ulong amount)
{
    lock (this)
    {
        Balance += amount;
    }
}
private void SubtractBalance(ulong amount)
{
    Balance -= amount;
}
As you can see we add an extra lock in the AddBalance function as it is a public one and could be called from outside the DepositInto lock. For the private SubtractBalance method, we have full control and don't need the additional lock overhead.
There is a number of unit tests to verify this implementation in the source code in the repository. It gets quite long and thus not included in the post.

TradeAccount

public interface ITradeAccount
{
    event EventHandler<TradeAccount> Updated;
    IAccount BalanceAccount { get; }
    ulong ValueOfActiveBuyOrders { get; }
    Dictionary<string, Security> Securities { get; }
    List<BuyOrder> BuyOrders { get; }
    List<SellOrder> SellOrders { get; }

    SellOrder CreateSellOrder(string name, ulong quantity, ulong pricePerItem);
    BuyOrder CreateBuyOrder(string name, ulong quantity, ulong pricePerItem);
}

First off, we will expose an event, Updated, that will be triggered whenever the contents of this Trade Account change. This to be able to create event based updates of GUI elements at a later stage.
After that we have the BalanceAccount associated with this TradeAccount, for storage of money that can be used to buy stuff.
ValueOfActiveBuyOrders will return the amount of money bound in buy orders created by this TradeAccount.
public ulong ValueOfActiveBuyOrders
{
    get
    {
        ulong sum = 0;
        foreach (var item in BuyOrders)
        {
            sum += item.OrderAccount.Balance;
        }
        return sum;
    }
}
Securities is a dictionary of securities held by this account followed bu the currently active BuyOrders and SellOrders.

Lastly we expose functions to create both Sell and Buy orders.

CreateSellOrder

public SellOrder CreateSellOrder(string name, ulong quantity, ulong pricePerItem)
{
    Security security; 
    if (!Securities.TryGetValue(name, out security))
        return null;
    var split = security.Split(quantity);
    if (split == null)
        return null;
    var order = new SellOrder(split, pricePerItem);
    order.AddCancelAction(CancelSellOrder);
    order.AddExecuteAction(ExecuteSellOrder);
    lock (SellOrders)
    {
        SellOrders.Add(order);
    }
    Updated?.Invoke(this, this);
    return order;
}
To createa a SellOrder we first need to check if we actually own any securities with the name provided, if we don't we will stop directly. After that we split our owned security into a new one with the quantity we want to sell. We expect the Split method to return null if the split is invalid (tries to sell more then owned) and we stop there as well. If all is well, we setup the SellOrder, connect both Cancel and Execute handlers to this TradeAccount so that it will know its way home when the mission is accomplished or canceled. Lastly, we add it to the list of active SellOrders and invoke the Updated event.
private void ExecuteSellOrder(SellOrder order)
{
    order.OrderAccount.DepositInto(BalanceAccount, order.OrderAccount.Balance);
    lock (SellOrders)
    {
        SellOrders.Remove(order);
    }
    Updated?.Invoke(this, this);
}
The ExecuteSellOrder is responsible to transfer money to the selling TradeAccount when a trade is completing. As seen, the SellOrder has already received the money from the buying account so this is just a final put the money where it belongs and cleanup things handler.
private void CancelSellOrder(SellOrder order)
{
    Security security;
    if (!Securities.TryGetValue(order.SecurityName, out security))
    {
        Securities.Add(order.SecurityName, order.ForSale);
    }
    else
    {
        Securities[order.SecurityName].Merge(order.ForSale);
    }
    lock (SellOrders)
    {
        SellOrders.Remove(order);
    }
    Updated?.Invoke(this, this);
}
The CancelSellOrder is a little more complicated. We are not receiving any money here but we need to put the Securities back where they belong. So find the security we were trying to sell and either merge with the existing one or create a new entry (if it has been cleaned up for any reason). After that some cleanup and update event invoking.

CreateBuyOrder

The CreateBuyOrder basically follows the same pattern as the sell order creator but here we check that we have enough money to make the purchase that we want to.
We do this by creating a new account and trying to deposit the needed amount of money into it. If it fails, we stop there. If all is good, we create the BuyOrder and supply it the just created account and what to look for in the marketplace. Just as for the SellOrder, we connect handlers for both the Execute and Cancel outcomes and add it to the list of active buy orders.
public BuyOrder CreateBuyOrder(string name, ulong quantity, ulong pricePerItem)
{
    var orderAccount = new Account(0);
    if (!BalanceAccount.DepositInto(orderAccount, quantity*pricePerItem))
        return null;
    var order = new BuyOrder(name, pricePerItem, quantity, orderAccount);
    order.AddCancelAction(CancelBuyOrder);
    order.AddExecuteAction(ExecuteBuyOrder);
    lock (BuyOrders)
    {
        BuyOrders.Add(order);
    }
    Updated?.Invoke(this, this);
    return order;
}
The ExecuteBuyOrder looks very similar to the CancelSellOrder above, instead of putting back a canceled sell order, we will put in a newly purchased Security. It needs to find the already owned security and merge with it if it exists or create a new entry in the owned Securites dictionary. After that a cleanup is done.
private void ExecuteBuyOrder(BuyOrder order)
{
    Security security;
    if (!Securities.TryGetValue(order.SecurityName, out security))
    {
        Securities.Add(order.SecurityName, order.Security);
    }
    else
    {
        Securities[order.SecurityName].Merge(order.Security);
    }
    lock (BuyOrders)
    {
        BuyOrders.Remove(order);
    }
    Updated?.Invoke(this, this);
}
And surprise, surprise the CancelBuyOrder is similar to the ExecuteSellOrder. Here we put back the pocket-money we received when going to the market and then cleaning up.
private void CancelBuyOrder(BuyOrder order)
{
    order.OrderAccount.DepositInto(BalanceAccount, order.OrderAccount.Balance);
    lock (BuyOrders)
    {
        BuyOrders.Remove(order);
    }
    Updated?.Invoke(this, this);
}

So just like with the Account, there are a number of unit tests in the repository  that I will not cover here. Actually the repository contains the code for the first working version with a test GUI. We will cover the rest of the code in future posts in this series, but if you are interested you can look at the code already now :)

So there, thank you for reading. Hope this helps someone out there : )


Monday, February 27, 2017

OpenGL 4 with OpenTK in C# Part 14: Basic Text


In this post we will look at how to get basic text on screen so that we can display the score of the game to the player.

This is part 14 of my series on OpenGL4 with OpenTK.
For other posts in this series:
OpenGL 4 with OpenTK in C# Part 1: Initialize the GameWindow
OpenGL 4 with OpenTK in C# Part 2: Compiling shaders and linking them
OpenGL 4 with OpenTK in C# Part 3: Passing data to shaders
OpenGL 4 with OpenTK in C# Part 4: Refactoring and adding error handling
OpenGL 4 with OpenTK in C# Part 5: Buffers and Triangle
OpenGL 4 with OpenTK in C# Part 6: Rotations and Movement of objects
OpenGL 4 with OpenTK in C# Part 7: Vectors and Matrices
OpenGL 4 with OpenTK in C# Part 8: Drawing multiple objects
OpenGL 4 with OpenTK in C# Part 9: Texturing
OpenGL 4 with OpenTK in C# Part 10: Asteroid Invaders
Basic bullet movement patterns in Asteroid Invaders
OpenGL 4 with OpenTK in C# Part 11: Mipmap
OpenGL 4 with OpenTK in C# Part 12: Basic Moveable Camera
OpenGL 4 with OpenTK in C# Part 13: IcoSphere
OpenGL 4 with OpenTK in C# Part 14: Basic Text
OpenGL 4 with OpenTK in C# Part 15: Object picking by mouse

As stated in the previous post, I am in no way an expert in OpenGL. I write these posts as a way to learn and if someone else finds these posts useful then all the better :)
If you think that the progress is slow, then know that I am a slow learner :P
This part will build upon the game window and shaders from part 13.

Generate font texture

First off, we need to generate a texture for the font that we want to use. For simplicity, all letters that we will need are put on a single line and each letter will get a fixed size rectangle in the texture.
private const string Characters = @"qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789µ§½!""#¤%&/()=?^*@£€${[]}\~¨'-_.:,;<>|°©®±¥";
public Bitmap GenerateCharacters(int fontSize, string fontName, out Size charSize)
{
    var characters = new List<Bitmap>();
    using (var font = new Font(fontName, fontSize))
    {
        for (int i = 0; i < Characters.Length; i++)
        {
            var charBmp = GenerateCharacter(font, Characters[i]);
            characters.Add(charBmp);
        }
        charSize = new Size(characters.Max(x => x.Width), characters.Max(x => x.Height));
        var charMap = new Bitmap(charSize.Width * characters.Count, charSize.Height);
        using (var gfx = Graphics.FromImage(charMap))
        {
            gfx.FillRectangle(Brushes.Black, 0, 0, charMap.Width, charMap.Height);
            for (int i = 0; i < characters.Count; i++)
            {
                var c = characters[i];
                gfx.DrawImageUnscaled(c, i * charSize.Width, 0);

                c.Dispose();
            }
        }
        return charMap;
    }
}

private Bitmap GenerateCharacter(Font font, char c)
{
    var size = GetSize(font, c);
    var bmp = new Bitmap((int)size.Width, (int)size.Height);
    using (var gfx = Graphics.FromImage(bmp))
    {
        gfx.FillRectangle(Brushes.Black, 0, 0, bmp.Width, bmp.Height);
        gfx.DrawString(c.ToString(), font, Brushes.White, 0, 0);
    }
    return bmp;
} 
private SizeF GetSize(Font font, char c)
{
    using (var bmp = new Bitmap(512, 512))
    {
        using (var gfx = Graphics.FromImage(bmp))
        {
            return  gfx.MeasureString(c.ToString(), font);
        }
    }
}


The GenerateCharacters method takes the name of the font that we want to use, the size of the font and outputs the size of a single character in the returned texture. So white on black.
output from font texture generator
Example output from above algorithm. Original texture was 3432x48 pixels
This texture will be used to calculate the alpha channel of the color that we want to render on screen. I.e. whatever is white on the texture will be rendered as the chose color and the black will be rendered as transparent.

Render Objects

Basically we want to render each character in a quad, so we need to generate a model with 2 triangles that can be reused. So into our RenderObjectFactory we add the following:
public static TexturedVertex[] CreateTexturedCharacter()
{
    float h = 1;
    float w = RenderText.CharacterWidthNormalized;
    float side = 1f / 2f; // half side - and other half

    TexturedVertex[] vertices =
    {
        new TexturedVertex(new Vector4(-side, -side, side, 1.0f),    new Vector2(0, h)),
        new TexturedVertex(new Vector4(side, -side, side, 1.0f),     new Vector2(w, h)),
        new TexturedVertex(new Vector4(-side, side, side, 1.0f),     new Vector2(0, 0)),
        new TexturedVertex(new Vector4(-side, side, side, 1.0f),     new Vector2(0, 0)),
        new TexturedVertex(new Vector4(side, -side, side, 1.0f),     new Vector2(w, h)),
        new TexturedVertex(new Vector4(side, side, side, 1.0f),      new Vector2(w, 0)),
    };
    return vertices;
}
It is the front facing quad from the generate cube method already there.
The RenderText.CharacterWidthNormalized is returning the 1/number of characters to get the correct alignment of the x-axis.

We will be needing 2 new render objects to accomplish putting text on the screen. RenderText that handles the whole string to be rendered, and RenderCharacter that handles each individual character in the string.
public class RenderText : AGameObject
{
    private readonly Vector4 _color;
    public const string Characters = @"qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789µ§½!""#¤%&/()=?^*@£€${[]}\~¨'-_.:,;<>|°©®±¥";
    private static readonly Dictionary<char, int> Lookup;
    public static readonly float CharacterWidthNormalized;
    // 21x48 per char, 
    public readonly List<RenderCharacter> Text;
    static RenderText()
    {
        Lookup = new Dictionary<char, int>();
        for (int i = 0; i < Characters.Length; i++)
        {
            if (!Lookup.ContainsKey(Characters[i]))
                Lookup.Add(Characters[i], i);
        }
        CharacterWidthNormalized = 1f / Characters.Length;
    }
    public RenderText(ARenderable model, Vector4 position, Color4 color, string value)
        : base(model, position, Vector4.Zero, Vector4.Zero, 0)
    {
        _color = new Vector4(color.R, color.G, color.B, color.A);
        Text = new List<RenderCharacter>(value.Length);
        _scale = new Vector3(0.02f);
        SetText(value);
    }
    public void SetText(string value)
    {
        Text.Clear();
        for (int i = 0; i < value.Length; i++)
        {
            int offset;
            if (Lookup.TryGetValue(value[i], out offset))
            {
                var c = new RenderCharacter(Model,
                    new Vector4(_position.X + (i * 0.015f),
                        _position.Y,
                        _position.Z,
                        _position.W),
                    (offset*CharacterWidthNormalized));
                c.SetScale(_scale);
                Text.Add(c);
            }
        }
    }
    public override void Render(ICamera camera)
    {
        _model.Bind();
        GL.VertexAttrib4(3, _color);
        for (int i = 0; i < Text.Count; i++)
        {
            var c = Text[i];
            c.Render(camera);
        }
    }
}
From the top.
Characters string containing all the characters in our font texture in the correct order.
Static constructor that initializes the lookup table, mapping each character to its index. Dictionary for faster lookup then doing the index of operation during for each string we want to show.
Instance constructor, just decomposes the Color struct to a Vector4, I still don't know why the GL.VertexAttrib4 doesn't support the Color struct out of the box.
SetText, allows for changing the contents of this RenderText object. This is a naive implementation that empties all content and then adds new. Optimization could be to try re-use whatever objects that already are in the collection. But for now, this works for me.
Render, just sets the color attribute and calls render for all RenderCharacters.

Next, all characters in the string
public class RenderCharacter : AGameObject
{
    private float _offset;

    public RenderCharacter(ARenderable model, Vector4 position, float charOffset)
        : base(model, position, Vector4.Zero, Vector4.Zero, 0)
    {
        _offset = charOffset;
        _scale = new Vector3(0.2f);
    }

    public void SetChar(float charOffset)
    {
        _offset = charOffset;
    }

    public override void Render(ICamera camera)
    {
        GL.VertexAttrib2(2, new Vector2(_offset, 0));
        var t2 = Matrix4.CreateTranslation(
            _position.X,
            _position.Y,
            _position.Z);
        var s = Matrix4.CreateScale(_scale);
        _modelView = s * t2 * camera.LookAtMatrix;
        GL.UniformMatrix4(21, false, ref _modelView);
        _model.Render();
    }
}
The key component for a character is the x-axis offset in the texture. The Render method just binds the offset attribute to the shader and renders the quad holding the character. At the moment the character is transformed with a Model-View matrix.


Shaders

Vertex Shader
#version 450 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 textureCoordinate;
layout(location = 2) in vec2 textureOffset;
layout(location = 3) in vec4 color;

out vec2 vs_textureOffset;
out vec4 vs_color;
layout(location = 20) uniform  mat4 projection;
layout (location = 21) uniform  mat4 modelView;

void main(void)
{
 vs_textureOffset = textureCoordinate + textureOffset;
 gl_Position = projection * modelView * position;
 vs_color = color;
}
The first 2 inputs to our vertex shader are bound from buffers, and we introduce 2 new inputs that we set from the render methods. The texture offset and color.
We also need to send the color forward to the fragment shader so we need an out parameter for that.
The vs_textureOffset is the original texture coordinate plus the new offset to find a character. The original texture coordinate the X-axis was of the width of 1 character and that's why this works.

Fragment Shader
#version 450 core
in vec2 vs_textureOffset;
in vec4 vs_color;
uniform sampler2D textureObject;
out vec4 color;

void main(void)
{
 vec4 alpha = texture(textureObject, vs_textureOffset);
 color = vs_color;
 color.a = alpha.r;
}
The vertex shader reads the texture, as it is black and white the red, green and blue channels should have the same values, hence we can look at just one of them and set the alpha channel of our color to get transparency. i.e. the color just sticks to the characters and we cut out everything else.

Game Window

OnLoad
We need to setup some stuff in the OnLoad method of our game window. First out is to setup the new shaders needed to render our text objects.
_textProgram = new ShaderProgram();
_textProgram.AddShader(ShaderType.VertexShader, @"Components\Shaders\1Vert\textVert.c");
_textProgram.AddShader(ShaderType.FragmentShader, @"Components\Shaders\5Frag\textFrag.c");
_textProgram.Link();

Nothing fancy there, next to load our texture and add it to the list of models (for correct disposal)
var textModel = new TexturedRenderObject(RenderObjectFactory.CreateTexturedCharacter(), _textProgram.Id, @"Components\Textures\font singleline.bmp");
models.Add("Quad", textModel);

As we do this in our Asteroid Invaders game, we will be displaying the score. So we need a variable to store this in.
_text = new RenderText(models["Quad"], new Vector4(-0.2f, 0.1f, -0.4f, 1),  Color4.Red, "Score");

And lastly, we need to enable transparency. Otherwise the alpha blending wouldn't bite and we would have a black background instead.
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

OnRenderFrame
The major changes to our OnRenderFrame method consists of updating our score and adding a second render step after all normal game objects for rendering of our transparent objects. This because we need to have whatever we want to show in the transparent areas to be drawn before our text. Otherwise we would get the dark blue background color as a box for all characters.
protected override void OnRenderFrame(FrameEventArgs e)
{
 Title = $"{_title}: FPS:{1f / e.Time:0000.0}, obj:{_gameObjects.Count}, score:{_score}";
 _text.SetText($"Score: {_score}");
 GL.ClearColor(_backColor);
 GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

 int lastProgram = -1;
 foreach (var obj in _gameObjects)
 {
  lastProgram = RenderOneElement(obj, lastProgram);
 }
 // render after all opaque objects to get transparency right
 RenderOneElement(_text, lastProgram);
 SwapBuffers();
}

private int RenderOneElement(AGameObject obj, int lastProgram)
{
 var program = obj.Model.Program;
 if (lastProgram != program)
  GL.UniformMatrix4(20, false, ref _projectionMatrix);
 lastProgram = obj.Model.Program;
 obj.Render(_camera);
 return lastProgram;
}

Further work

This is not a fully featured way to render text, but enough to get a score on the screen. There's a lot of things that could be done to improve it and here comes a few:

As the solution is based on a bitmap, it scales kind of bad. There exists a lot of material on how to make that smooth and something that I will look at some time in the future. Distance fields is an area that seems promising and that takes advantage of the GPU. More information in the following links if you want to give it a try:

Positioning on the screen. Today the solution uses world coordinates, works for this static camera scene but not so well with a moving camera if you still want to have the text visible to the user.

Text wrapping, multi row text. Better scaling.
The list goes on and I'll probably end up coding some of the stuff on the list whenever I feel a need for it.

End results

For the complete source code for the tutorial at the end of this part, go to: https://github.com/eowind/dreamstatecoding

So there, thank you for reading. Hope this helps someone out there : )