private IDirectedPath GetPath()
        {
            VectorGoal = Target.Coords.Canon - Source.Coords.Canon;
            OpenSet    = new HashSet <HexCoords>();
            Queue      = new DictionaryPriorityQueue <int, IDirectedPath>();

            TraceFindPathDetailInit(Source.Coords, Target.Coords);

            Queue.Enqueue(0, new DirectedPath(Target));

            HexKeyValuePair <int, IDirectedPath> item;

            while (Queue.TryDequeue(out item))
            {
                var path = item.Value;
                var step = path.PathStep.Hex;

                OpenSet.Add(step.Coords);
                if (ClosedSet.Contains(step.Coords))
                {
                    continue;
                }

                TraceFindPathDequeue("Rev", step.Coords, path.TotalCost, path.HexsideExit, item.Key >> 16,
                                     (int)((int)(item.Key & 0xFFFFu) - 0x7FFF));

                if (step.Equals(Source))
                {
                    return(path);
                }

                ClosedSet.Add(step.Coords);

                foreach (var neighbour in Board.GetNeighbourHexes(step))
                {
                    ExpandNeighbour(path, neighbour);
                }
            }

            return(null);
        }
        /// <summary>Returns an <c>IPath</c> for the optimal path from coordinates <c>start</c> to <c>goal</c>.</summary>
        /// <param name="start">Coordinates for the <c>last</c> step on the desired path.</param>
        /// <param name="goal">Coordinates for the <c>first</c> step on the desired path.</param>
        /// <param name="stepCost">Cost to extend path by hex at <c>coords</c> from hex at direction <c>hexside</c>.</param>
        /// <param name="heuristic">Returns a monotonic (ie locally admissible) cost estimate from a range value.</param>
        /// <returns></returns>
        /// ///<remarks>Note that <c>heuristic</c> <b>must</b> be monotonic in order for the algorithm to perform properly.</remarks>
    #pragma warning disable 1658, 1584
        /// <seealso cref="http://www.cs.trincoll.edu/~ram/cpsc352/notes/astar.html"/>
    #pragma warning restore 1658, 1584
        public static IDirectedPath FindDirectedPathFwd(
            IHex start,
            IHex goal,
            Func <IHex, Hexside, int> stepCost,
            Func <int, int> heuristic
            )
        {
            if (start == null)
            {
                throw new ArgumentNullException("start");
            }
            if (goal == null)
            {
                throw new ArgumentNullException("goal");
            }
            if (stepCost == null)
            {
                throw new ArgumentNullException("stepCost");
            }

            var vectorGoal = goal.Coords.Canon - start.Coords.Canon;
            var closed     = new HashSet <HexCoords>();
            var open       = new HashSet <HexCoords>();
            var queue      = new DictionaryPriorityQueue <int, DirectedPath>();

            TraceFlags.FindPathDetail.Trace(true, "Find path from {0} to {1}; vectorGoal = {2}",
                                            start.Coords, goal.Coords, vectorGoal);

            queue.Enqueue(0, new DirectedPath(goal));

            HexKeyValuePair <int, DirectedPath> item;

            while (queue.TryDequeue(out item))
            {
                var path = item.Value;
                open.Add(path.PathStep.Hex.Coords);
                if (closed.Contains(path.PathStep.Hex.Coords))
                {
                    continue;
                }

                TraceFlags.FindPathDequeue.Trace(
                    "Dequeue Path at {0} w/ cost={1,4} at {2}; estimate={3,4}:{4,4}.",
                    path.PathStep.Hex.Coords, path.TotalCost, path.HexsideExit, item.Key >> 16,
                    (int)((int)(item.Key & 0xFFFFu) - 0x7FFF));

                if (path.PathStep.Hex.Equals(start))
                {
                    TraceFlags.FindPathDequeue.Trace("Closed: {0,7}", closed.Count);
                    return(path);
                }

                closed.Add(path.PathStep.Hex.Coords);

                foreach (var neighbour in path.PathStep.Hex.GetNeighbourHexes()
                         )
                {
                    if (!open.Contains(neighbour.Hex.Coords))
                    {
                        var cost = stepCost(neighbour.Hex, neighbour.HexsideExit);
                        if (cost > 0)
                        {
                            var newPath = path.AddStep(neighbour, cost);
                            var key     = Estimate(heuristic, vectorGoal, start.Coords, neighbour.Hex.Coords,
                                                   newPath.TotalCost);
                            TraceFlags.FindPathEnqueue.Trace("   Enqueue {0}: estimate={1,4}:{2,3}",
                                                             neighbour.Hex.Coords, key >> 16, key & 0xFFFFu);
                            queue.Enqueue(key, newPath);
                        }
                    }
                }
            }
            return(null);
        }