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