Ejemplo n.º 1
0
 /// <param name="coords">The <see cref="HexCoords"/> for this landmark.</param>
 /// <param name="board">IBoard{IHex} on which the landmark is to be created.</param>
 /// <param name="queueFactory">TODO</param>
 private static IList <DirectedLandmark> BackingStore(HexCoords coords, INavigableBoard board, Func <IPriorityQueue <int, HexCoords> > queueFactory)
 {
     return(new List <DirectedLandmark> {
         DirectedLandmark.New(coords, board.MapSizeHexes, queueFactory, board.TryEntryCost),
         DirectedLandmark.New(coords, board.MapSizeHexes, queueFactory, board.TryExitCost)
     }.AsReadOnly());
 }
Ejemplo n.º 2
0
 // Common settings for both directions
 /// <param name="board">Board on which this path search is taking place.</param>
 /// <param name="start">Start hex for this half of the bidirectional path search.</param>
 /// <param name="goal">Goal hex for this this half of the bidirectional path search.</param>
 /// <param name="pathHalves"></param>
 protected DirectionalPathfinder(INavigableBoard <IHex> board, IHex start, IHex goal, IPathHalves pathHalves)
     : base(board, start, goal, pathHalves.ClosedSet)
 {
     PathHalves = pathHalves;
     OpenSet    = new Dictionary <HexCoords, IDirectedPath>();
     Queue      = new HotPriorityQueue <IDirectedPath>(0, 256);
 }
        /// <summary>TODO</summary>
        /// <param name="board">Board on which this shortest-path search is taking place.</param>
        /// <param name="source">Source hex for this shortest-path search.</param>
        /// <param name="target">Target hex for this shortest-path search.</param>
        /// <param name="closedSet">Injected implementation of <see cref="ISet{HexCoords}"/>.</param>
        protected internal Pathfinder(INavigableBoard board, IHex source, IHex target, ISet <HexCoords> closedSet)
        {
            if (board == null)
            {
                throw new ArgumentNullException("board");
            }
            if (board.Landmarks == null)
            {
                throw new ArgumentNullException("board", "Member Landmarks must not be null");
            }
            if (closedSet == null)
            {
                throw new ArgumentNullException("closedSet");
            }
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            Board     = board;
            ClosedSet = closedSet;
            Source    = source;
            Target    = target;
        }
        }                                       // TODO: Set this to FOVRange perhaps?

        public static IPath2 FindPath(
            ICoordsUser start,
            ICoordsUser goal,
            INavigableBoard board
            )
        {
            return(FindPath(start, goal, board.StepCost, board.Heuristic, board.IsOnBoard));
        }
Ejemplo n.º 5
0
 /// <summary>Returns the requested neighbours for this hex.</summary>
 /// <param name="this">TODO</param>
 /// <param name="here">TODO</param>
 /// <returns></returns>
 public static IEnumerable <NeighbourHex> GetNeighbourHexes(
     this INavigableBoard <IHex> @this, IHex here
     )
 {
     if (@this == null)
     {
         throw new ArgumentNullException("this");
     }
     return(@this.GetAllNeighbours(here).Where(n => n.Hex != null));
 }
Ejemplo n.º 6
0
 /// <summary>All neighbours of this hex, as an <see cref="IEnumerable {NeighbourHex}"/></summary>
 public static IEnumerable <NeighbourHex> GetAllNeighbours(
     this INavigableBoard <IHex> @this, IHex here
     )
 {
     if (@this == null)
     {
         throw new ArgumentNullException("this");
     }
     return(HexsideExtensions.HexsideList.Select(hexside =>
                                                 new NeighbourHex(@this[here.Coords.GetNeighbour(hexside)], hexside.Reversed())));
 }
Ejemplo n.º 7
0
 /// <summary>TODO</summary>
 /// <param name="start"></param>
 /// <param name="goal"></param>
 /// <param name="board"></param>
 /// <returns></returns>
 public static IPath FindPath(
     HexCoords start,
     HexCoords goal,
     INavigableBoard board
     )
 {
     if (board == null)
     {
         throw new ArgumentNullException("board");
     }
     return(FindPath(start, goal, board.StepCost,
                     board.Heuristic, board.IsOnboard));
 }
        /// <summary>Creates a new <see cref="Pathfinder"/> instance implementing a unidirectional A* from
        /// <paramref name="source"/> to <paramref name="target"/>.</summary>
        /// <param name="board">An object satisfying the interface <c>INavigableBoardFwd</c>.</param>
        /// <param name="source">Coordinates for the <c>first</c> step on the desired path.</param>
        /// <param name="target">Coordinates for the <c>last</c> step on the desired path.</param>
        public UnidirectionalPathfinder(INavigableBoard <IHex> board, IHex source, IHex target)
            : base(board, source, target, new HashSet <HexCoords>()
                   )
        {
            if (board == null)
            {
                throw new ArgumentNullException("board");
            }

            StepCost  = (hex, hexside) => board.GetDirectedCostToExit(hex, hexside);
            Heuristic = board.Heuristic;
            Path      = GetPath();

            TraceFindPathDone(ClosedSet.Count);
        }
        /// <summary>Returns an <see cref="IPath{THex}"/> for the optimal path using a standard A* algorithm.</summary>
        /// <param name="board">An object satisfying the interface <see cref="INavigableBoard{THex}"/>.</param>
        /// <param name="source">Coordinates for the <c>first</c> step on the desired path.</param>
        /// <param name="target">Coordinates for the <c>last</c> step on the desired path.</param>
        /// <param name="queue"></param>
        /// <param name="closedSet"></param>
        /// <returns>A <see cref="IPath{THex}"/> for the shortest path found, or null if no path was found.</returns>
        /// <remarks>
        /// <para>Note that the Heuristic provided by <paramref name="board"/> <b>must</b> be monotonic in order for the algorithm to perform properly.</para>
        /// </remarks>
        public static IPath <THex> GetPath <THex>(this INavigableBoard <THex> board, THex source, THex target,
                                                  IPriorityQueue <int, IDirectedPath> queue, ISet <HexCoords> closedSet)
            where THex : IHex
        {
            source.TraceFindPathDetailInit(target);

            var vectorGoal = target.Coords.Canon - source.Coords.Canon;

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

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

                if (closedSet.Contains(step.Coords))
                {
                    continue;
                }

                step.Hex.TraceFindPathDequeue("A* Rev", path, item.Key >> 16, (int)(item.Key & 0xFFFFu) - 0x7FFF);

                if (step.Hex == (IHex)source)
                {
                    return(new Path <THex>(path.ToMaybe(), source, target, closedSet, null));
                }

                closedSet.Add(step.Coords);

                Hexside.HexsideList.ForEach(hexside => {
                    board[step.Coords.GetNeighbour(hexside)].IfHasValueDo(neighbour => {
                        var cost = step.Hex.TryDirectedCost(hexside);
                        if (cost > 0)
                        {
                            var newPath = path.AddStep(neighbour, hexside.Reversed, cost);
                            board.Estimate(vectorGoal, source, neighbour, newPath.TotalCost)
                            .IfHasValueDo(key => {
                                neighbour.Coords.TraceFindPathEnqueue(key >> 16, (int)(key & 0xFFFFu));

                                queue.Enqueue(key, newPath);
                            });
                        }
                    });
                });
            }

            return(null);
        }
Ejemplo n.º 10
0
        /// <summary>Creates a populated <see cref="Collection{T}"/> of <see cref="Landmark"/>
        /// instances.</summary>
        /// <param name="board">The board on which the collection of landmarks is to be instantiated.</param>
        /// <param name="landmarkCoords">Board coordinates of the desired landmarks</param>
        public static ILandmarkCollection New(
            INavigableBoard board,
            IFastList <HexCoords> landmarkCoords
            )
        {
            int degreeOfParallelism = Math.Max(1, Environment.ProcessorCount - 1);
            var query = from coords in landmarkCoords.AsParallel()
                        .WithDegreeOfParallelism(degreeOfParallelism)
                        .WithMergeOptions(ParallelMergeOptions.NotBuffered)
#if UseSortedDictionary
                        select Landmark.DictionaryPriorityQueueLandmark(coords, board);
#else
                        select Landmark.HotPriorityQueueLandmark(coords, board);
#endif

            return(Extensions.InitializeDisposable(() => new LandmarkCollection(query)));
        }
Ejemplo n.º 11
0
        /// <summary>Calculates an <c>IPath</c> for the optimal path from coordinates .</summary>
        /// <param name="board">An object satisfying the interface <c>INavigableBoardFwd</c>.</param>
        /// <param name="source">Coordinates for the <c>first</c> step on the desired path.</param>
        /// <param name="target">Coordinates for the <c>last</c> step on the desired path.</param>
        public BidirectionalPathfinder(INavigableBoard <IHex> board, IHex source, IHex target)
            : base(board, source, target, new HashSet <HexCoords>())
        {
            Pathfinder.TraceFindPathDetailInit(Source.Coords, Target.Coords);

            _bestSoFar = int.MaxValue;
            var pathfinderFwd = new BidirectionalPathfinder.DirectionalPathfinder.PathfinderRev(board, source, target, this);
            var pathfinderRev = new BidirectionalPathfinder.DirectionalPathfinder.PathfinderFwd(board, source, target, this);

            // Alternate searching from each direction and calling the other direction
            pathfinderFwd.Partner = pathfinderRev;
            var pathfinder = pathfinderRev.Partner
                                 = pathfinderFwd;

            while (!pathfinder.IsFinished())
            {
                pathfinder = pathfinder.Partner;
            }

            TraceFindPathDone(ClosedSet.Count);
        }
Ejemplo n.º 12
0
        /// <summary>TODO</summary>
        public static ILandmark HotPriorityQueueLandmark(HexCoords coords, INavigableBoard board)
        {
            var backingStore = BackingStore(coords, board, () => PriorityQueueFactory.NewHotPriorityQueue <HexCoords>(1024));

            return(Extensions.InitializeDisposable(() => new Landmark(coords, backingStore)));
        }
Ejemplo n.º 13
0
 /// <summary>Returns an <see cref="UnidirectionalPathfinder"/>.</summary>
 /// <param name="this"></param>
 /// <param name="source"></param>
 /// <param name="target"></param>
 /// <returns>Returns an <see cref="IPathfinder{IHex}"/> with a shortest path from <paramref name="source"/> to <paramref name="target"/>
 /// as well as statistice on the Unidirectional path determination.</returns>
 public static IPathfinder <IHex> GetUnidirectionalPathfinder(this INavigableBoard <IHex> @this, IHex source, IHex target)
 {
     return(new UnidirectionalPathfinder(@this, source, target));
 }
 static int?Estimate <THex>(this INavigableBoard <THex> board, IntVector2D vectorGoal,
                            IHex start, IHex hex, int totalCost)
     where THex : IHex
 => from heuristic in board.Heuristic(start, hex) as int?select((heuristic + totalCost) << 16)
 + Preference(vectorGoal, start.Coords.Canon - hex.Coords.Canon);
 /// <summary>Returns an <see cref="IPath{THex}"/> for the optimal path using a standard A* algorithm.</summary>
 /// <param name="board">An object satisfying the interface <c>INavigableBoardFwd</c>.</param>
 /// <param name="source">Coordinates for the <c>first</c> step on the desired path.</param>
 /// <param name="target">Coordinates for the <c>last</c> step on the desired path.</param>
 /// <returns>A <see cref="IPath{THex}"/> for the shortest path found, or null if no path was found.</returns>
 /// <remarks>
 /// <para>Note that the Heuristic provided by <paramref name="board"/> <b>must</b> be monotonic in order for the algorithm to perform properly.</para>
 /// </remarks>
 public static IPath <THex> GetPathStandardAStar <THex>(this INavigableBoard <THex> board,
                                                        THex source, THex target)
     where THex : IHex
 => board.GetPath(source, target, new DictionaryPriorityQueue <int, IDirectedPath>(), new HashSet <HexCoords>());
Ejemplo n.º 16
0
 /// <summary>Create a new instance of <see cref="PathfinderRev"/>, a backward-searching <see cref="DirectionalPathfinder"/>.</summary>
 /// <param name="board">Board on which this path search is taking place.</param>
 /// <param name="source">Source hex for this path search, the goal for the directional path search.</param>
 /// <param name="target">Target hex for this path search, the start for the directional path search.</param>
 /// <param name="pathHalves"></param>
 internal PathfinderRev(INavigableBoard <IHex> board, IHex source, IHex target, IPathHalves pathHalves)
     : base(board, source, target, pathHalves)
 {
     TraceFindPathDetailDirection("Fwd", Goal.Coords - Start.Coords);
     StartPath(Start);
 }
     /// <summary>TODO</summary>
     /// <param name="start"></param>
     /// <param name="goal"></param>
     /// <param name="board"></param>
     /// <returns></returns>
     public static IPath FindPath(
   HexCoords     start,
   HexCoords     goal,
   INavigableBoard board
 )
     {
         if (board==null) throw new ArgumentNullException("board");
           return FindPath(start, goal, board.StepCost,
                                board.Heuristic, board.IsOnboard);
     }
 /// <summary>Creates a new <see cref="IPathfinder"/> instance implementing a unidirectional A*.</summary>
 /// <param name="board">An object satisfying the interface <c>INavigableBoardFwd</c>.</param>
 /// <remarks>
 /// <para>Note that the Heuristic provided by <paramref name="board"/> <b>must</b> be monotonic
 /// in order for the algorithm to perform properly.</para>
 /// </remarks>
 public StandardPathfinder(INavigableBoard board) => Board = board;
 /// <summary>Returns an <c>IDirectedPath</c> for the optimal path from coordinates <c>start</c> to <c>goal</c>.</summary>
 /// <param name="board">An object satisfying the interface <c>INavigableBoardFwd</c>.</param>
 /// <param name="source">Coordinates for the <c>first</c> step on the desired path.</param>
 /// <param name="target">Coordinates for the <c>last</c> step on the desired path.</param>
 /// <returns>A <c>IDirectedPathCollection</c>  for the shortest path found, or null if no path was found.</returns>
 /// <remarks>
 /// <para>Note that the Heuristic provided by <paramref name="board"/> <b>must</b> be monotonic in order for the algorithm to perform properly.</para>
 /// <seealso cref="PGNapoleonics.HexUtilities.Pathfinding.UnidirectionalPathfinder"/>
 /// </remarks>
 public static IDirectedPath FindDirectedPathFwd(INavigableBoard <IHex> board, IHex source, IHex target)
 {
     return((new UnidirectionalPathfinder(board, source, target)).Path);
 }