예제 #1
0
            private void          ExpandHex(IDirectedPath path, Hexside hexside)
            {
                var here  = path.PathStep.Hex;
                var there = Board[here.Coords.GetNeighbour(hexside)];

                if (there != null && !ClosedSet.Contains(there.Coords))
                {
                    var cost = StepCost(here, hexside, there);
                    if ((cost > 0) &&
                        (path.TotalCost + cost < BestSoFar || !OpenSet.ContainsKey(there.Coords))
                        )
                    {
                        var key     = path.TotalCost + cost + Heuristic(there.Coords);
                        var newPath = path.AddStep(there, HexsideDirection(hexside), cost);

                        TraceFindPathEnqueue(there.Coords, key, 0);

                        IDirectedPath oldPath;
                        if (!OpenSet.TryGetValue(there.Coords, out oldPath))
                        {
                            OpenSet.Add(there.Coords, newPath);
                            Queue.Enqueue(key, newPath);
                        }
                        else if (newPath.TotalCost < oldPath.TotalCost)
                        {
                            OpenSet.Remove(there.Coords);
                            OpenSet.Add(there.Coords, newPath);
                            Queue.Enqueue(key, newPath);
                        }

                        SetBestSoFar(newPath, GetPartnerPath(there.Coords));
                    }
                }
            }
예제 #2
0
        /// <summary>Paint the direction arrow for each hex of the current shortest path.</summary>
        /// <param name="g">Graphics object for the canvas being painted.</param>
        /// <param name="path"></param>
        protected virtual void PaintPathArrow(Graphics g, IDirectedPath path)
        {
            if (g == null)
            {
                throw new ArgumentNullException("g");
            }
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            g.TranslateTransform(GridSize.Width * 2 / 3, GridSize.Height / 2);
            var unit = GridSize.Height / 8.0F;

            if (path.PathSoFar == null)
            {
                g.DrawLine(Pens.Black, -unit * 2, -unit * 2, unit * 2, unit * 2);
                g.DrawLine(Pens.Black, -unit * 2, unit * 2, unit * 2, -unit * 2);
            }
            else
            {
                g.RotateTransform(60 * (int)path.PathStep.HexsideEntry);
                g.DrawLine(Pens.Black, 0, unit * 4, 0, -unit);
                g.DrawLine(Pens.Black, 0, unit * 4, -unit * 3 / 2, unit * 2);
                g.DrawLine(Pens.Black, 0, unit * 4, unit * 3 / 2, unit * 2);
            }
        }
        private void     ExpandHex(IDirectedPath path, Hexside hexside)
        {
            var here  = path.PathStep.Coords;
            var there = here.GetNeighbour(hexside);

            if (!ClosedSet.Contains(there))
            {
                TryStepCost(here, hexside).IfHasValueDo(cost => {
                    if (path.TotalCost + cost < BestSoFar || !OpenSet.ContainsKey(there))
                    {
                        Heuristic(there).IfHasValueDo(heuristic => {
                            var key     = path.TotalCost + cost + heuristic;
                            var newPath = path.AddStep(there, HexsideDirection(hexside), cost);

                            PathfinderExtensions.TraceFindPathEnqueue(there, key, 0);

                            if (!OpenSet.TryGetValue(there, out var oldPath))
                            {
                                OpenSet.Add(there, newPath);
                                Queue.Enqueue(key, newPath);
                            }
                            else if (newPath.TotalCost < oldPath.TotalCost)
                            {
                                OpenSet.Remove(there);
                                OpenSet.Add(there, newPath);
                                Queue.Enqueue(key, newPath);
                            }

                            SetBestSoFar(newPath, PartnerPath(there));
                        });
                    }
                });
            }
        }
예제 #4
0
 /// <summary>Returns a DirectedPath composed by extending this DirectedPath by one hex.</summary>
 public DirectedPathCollection(IDirectedPath pathSoFar, DirectedPathStepHex pathStep, int stepCost)
 {
     PathStep   = pathStep;
     PathSoFar  = pathSoFar;
     TotalCost  = (pathSoFar?.TotalCost ?? 0) + stepCost;
     TotalSteps = (pathSoFar?.TotalSteps ?? -1) + 1;
 }
        /// <inheritdoc/>
        public void SetBestSoFar(IDirectedPath pathRev, IDirectedPath pathFwd)
        {
            if (pathFwd.TotalCost + pathRev.TotalCost < BestSoFar)
            {
                _pathRev  = pathRev;
                _pathFwd  = pathFwd;
                BestSoFar = _pathRev.TotalCost + _pathFwd.TotalCost;

                PathfinderExtensions.TraceFindPathDetailBestSoFar(pathFwd, pathRev, BestSoFar);
            }
        }
예제 #6
0
 /// <summary>TODO</summary>
 private static IDirectedPath MergePaths(IDirectedPath targetPath, IDirectedPath sourcePath)
 {
     if (sourcePath != null)
     {
         while (sourcePath.PathSoFar != null)
         {
             var hexside = sourcePath.PathStep.HexsideExit;
             var cost    = sourcePath.TotalCost - (sourcePath = sourcePath.PathSoFar).TotalCost;
             targetPath = targetPath.AddStep(sourcePath.PathStep.Hex, hexside, cost);
         }
     }
     return(targetPath);
 }
예제 #7
0
 /// <summary>Returns the result of stacking <paramref name="mergePath"/> onto <paramref name="this"/></summary>
 public static Maybe <IDirectedPath> MergePaths(this IDirectedPath @this, IDirectedPath mergePath)
 {
     if (@this == null || mergePath == null)
     {
         return(null);
     }
     while (mergePath.PathSoFar != null)
     {
         var hexside = mergePath.PathStep.HexsideExit;
         var cost    = mergePath.TotalCost - (mergePath = mergePath.PathSoFar).TotalCost;
         @this = @this.AddStep(mergePath.PathStep.Coords, hexside, cost);
     }
     return(@this.ToMaybe());
 }
 /// <summary>Returns the result of stacking <paramref name="mergePath"/> onto <paramref name="targetPath"/></summary>
 public static Maybe <IDirectedPath> MergePaths <THex>(this IDirectedPath targetPath, IDirectedPath mergePath)
     where THex : class, IHex
 {
     if (mergePath != null)
     {
         while (mergePath.PathSoFar != null)
         {
             var hexside = mergePath.PathStep.HexsideExit;
             var cost    = mergePath.TotalCost - (mergePath = mergePath.PathSoFar).TotalCost;
             targetPath = targetPath.AddStep(mergePath.PathStep.Hex, hexside, cost);
         }
     }
     return(targetPath.ToMaybe());
 }
        /// <summary>Updates the record of the shortest path found so far.</summary>
        /// <param name="pathFwd">The half-path obtained by searching backward from the target (so stacked forwards).</param>
        /// <param name="pathRev">The half-path obtained by searching forward from the source (so stacked backwards).</param>
        public void    SetBestSoFar(IDirectedPath pathRev, IDirectedPath pathFwd)
        {
            if (pathFwd == null || pathRev == null)
            {
                return;
            }

            if (pathFwd.TotalCost + pathRev.TotalCost < BestSoFar)
            {
                _pathRev  = pathRev;
                _pathFwd  = pathFwd;
                BestSoFar = _pathRev.TotalCost + _pathFwd.TotalCost;

                pathFwd.TraceFindPathDetailBestSoFar(pathRev, BestSoFar);
            }
        }
예제 #10
0
        /// <summary>Updates the record of the shortest path found so far.</summary>
        /// <param name="pathFwd">The half-path obtained by searching backward from the target (so stacked forwards).</param>
        /// <param name="pathRev">The half-path obtained by searching forward from the source (so stacked backwards).</param>
        void IPathHalves.SetBestSoFar(IDirectedPath pathRev, IDirectedPath pathFwd)
        {
            if (pathFwd == null || pathRev == null)
            {
                return;
            }

            if (pathFwd.TotalCost + pathRev.TotalCost < _bestSoFar)
            {
                _pathRev   = pathRev;
                _pathFwd   = pathFwd;
                _bestSoFar = _pathRev.TotalCost + _pathFwd.TotalCost;

                Pathfinder.TraceFindPathDetailBestSoFar(pathFwd.PathStep.Hex.Coords, pathRev.PathStep.Hex.Coords, _bestSoFar);
            }
        }
        void ExpandNeighbour(IDirectedPath path, NeighbourHex neighbour)
        {
            if (!OpenSet.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, Source.Coords,
                                           neighbour.Hex.Coords, newPath.TotalCost);

                    TraceFindPathEnqueue(neighbour.Hex.Coords, key >> 16, (int)(key & 0xFFFFu));

                    Queue.Enqueue(key, newPath);
                }
            }
        }
        void PaintPathArrow(Graphics g, IDirectedPath path)
        {
            g.TranslateTransform(GridSize.Width * 2 / 3, GridSize.Height / 2);
            var unit = GridSize.Height / 8.0F;

            if (path.PathSoFar == null)
            {
                g.DrawLine(Pens.Black, -unit * 2, -unit * 2, unit * 2, unit * 2);
                g.DrawLine(Pens.Black, -unit * 2, unit * 2, unit * 2, -unit * 2);
            }
            else
            {
                g.RotateTransform(60 * (int)path.PathStep.HexsideEntry);
                g.DrawLine(Pens.Black, 0, unit * 4, 0, -unit);
                g.DrawLine(Pens.Black, 0, unit * 4, -unit * 3 / 2, unit * 2);
                g.DrawLine(Pens.Black, 0, unit * 4, unit * 3 / 2, unit * 2);
            }
        }
        void PaintPath(Graphics g, IDirectedPath Path)
        {
            var state = g.Save();

            using (var brush = new SolidBrush(Color.FromArgb(78, Color.PaleGoldenrod))) {
                var path = Path;
                while (path != null)
                {
                    g.Restore(state); state = g.Save();
                    var coords = path.PathStep.Hex.Coords;
                    g.TranslateTransform(
                        MapMargin.Width + coords.User.X * GridSize.Width,
                        MapMargin.Height + coords.User.Y * GridSize.Height + (coords.User.X + 1) % 2 * GridSize.Height / 2
                        );
                    g.FillPath(brush, HexgridPath);

                    PaintPathArrow(g, path);
                    path = path.PathSoFar;
                }
            }
        }
        /// <summary>Paint the direction and destination indicators for each hex of the current shortest path.</summary>
        /// <param name="g">Type: Graphics - Object representing the canvas being painted.</param>
        /// <param name="path">Type: <see cref="IDirectedPath"/> -
        /// A directed path (ie linked-list> of hexes to be highlighted with a direction arrow.</param>
        protected virtual void PaintPathArrow(Graphics g, IDirectedPath path)
        {
            if (g == null)
            {
                throw new ArgumentNullException("g");
            }
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            g.TranslateTransform(CentreOfHexOffset.Width, CentreOfHexOffset.Height);
            if (path.PathSoFar == null)
            {
                PaintPathDestination(g);
            }
            else
            {
                PaintPathArrow(g, path.PathStep.HexsideEntry);
            }
        }
예제 #15
0
        /// <summary>Paint the current shortese path.</summary>
        /// <param name="g">Graphics object for the canvas being painted.</param>
        /// <param name="path"></param>
        protected virtual void PaintPath(Graphics g, IDirectedPath path)
        {
            if (g == null)
            {
                throw new ArgumentNullException("g");
            }

            using (var brush = new SolidBrush(Color.FromArgb(78, Color.PaleGoldenrod))) {
                while (path != null)
                {
                    var coords = path.PathStep.Hex.Coords;
                    TranslateGraphicsToHex(g, coords);
                    g.FillPath(brush, HexgridPath);

                    if (ShowPathArrow)
                    {
                        PaintPathArrow(g, path);
                    }
                    path = path.PathSoFar;
                }
            }
        }
 public static void TraceFindPathDequeue(this HexCoords coords,
                                         string searchDirection, IDirectedPath path, int priority, int preference)
 => Tracing.FindPathDequeue.Trace(
     $"{searchDirection} Dequeue Path at {coords} w/ cost={path.TotalCost,4} at {path.HexsideExit,-9}; estimate={priority,4}:{preference,4}.");
 public static void TraceFindPathDequeue(this IHex hex,
                                         string searchDirection, IDirectedPath path, int priority, int preference)
 => Tracing.FindPathDequeue.Trace(
     "{0} Dequeue Path at {1} w/ cost={2,4} at {3,-9}; estimate={4,4}:{5,4}.",
     searchDirection, hex.Coords, path.TotalCost, path.HexsideExit, priority, preference);
 public static void TraceFindPathDetailBestSoFar(this IDirectedPath pathFwd, IDirectedPath pathRev,
                                                 int bestSoFar)
 => Tracing.FindPathDetail.Trace(
     $"   SetBestSoFar: pathFwd at {pathFwd.PathStep.Coords}; pathRev at {pathRev.PathStep.Coords}; Cost = {bestSoFar}");
예제 #19
0
 /// <summary>Returns a new instance composed by extending this DirectedPath by one hex.</summary>
 /// <param name="this"></param>
 /// <param name="stepHex"></param>
 /// <param name="stepCost"></param>
 public static IDirectedPath AddStep(this IDirectedPath @this, DirectedPathStepHex stepHex, int stepCost)
 => new DirectedPathCollection(@this, stepHex, stepCost);
예제 #20
0
 /// <summary>Returns a new instance composed by extending this DirectedPath by one hex.</summary>
 /// <param name="this"></param>
 /// <param name="hex"></param>
 /// <param name="hexsideExit"></param>
 /// <param name="stepCost"></param>
 public static IDirectedPath AddStep(this IDirectedPath @this, IHex hex, Hexside hexsideExit, int stepCost)
 => @this.AddStep(new DirectedPathStepHex(hex, hexsideExit), stepCost);
예제 #21
0
 protected override void    SetBestSoFar(IDirectedPath selfPath, IDirectedPath partnerPath)
 {
     PathHalves.SetBestSoFar(selfPath, partnerPath);
 }
예제 #22
0
 protected abstract void          SetBestSoFar(IDirectedPath fwdPath, IDirectedPath revPath);