public bool     IsFinished()
        {
            if (Queue.TryDequeue(out var item))
            {
                var path   = item.Value;
                var coords = path.PathStep.Coords;

                OpenSet.Remove(coords);
                if (!ClosedSet.Contains(coords))
                {
                    PathfinderExtensions.TraceFindPathDequeue(GetType().Name, coords, path, item.Key, 0);

                    if (item.Key < BestSoFar)
                    {
                        Partner.Heuristic(coords).IfHasValueDo(heuristic => {
                            if (path.TotalCost + Partner.FrontierMinimum() - heuristic < BestSoFar)
                            {
                                Hexside.ForEach(hexside => ExpandHex(path, hexside));
                            }
                        });
                    }
                    ClosedSet.Add(coords);
                }
                return(!Queue.Any());
            }
            return(true);
        }
        static IBoardStorage <int> PopulateLandmark(this IBoard <IHex> board,
                                                    StepCost directedStepCost, Func <Queue> queueGenerator, IHex landmark
                                                    )
        {
            TraceNewLine($"Find distances from {landmark.Coords}");

            var costs = new BlockedBoardStorage32x32 <int>(board.MapSizeHexes, c => - 1);
            var queue = queueGenerator();

            queue.Enqueue(0, landmark);

            while (queue.TryDequeue(out var item))
            {
                var here = item.Value;
                var key  = item.Key;
                if (costs[here.Coords] > 0)
                {
                    continue;
                }

                Trace($"Dequeue Path at {here} w/ cost={key,4}.");

                costs.SetItem(here.Coords, key);

                void SetHexside(Hexside hexside)
                => board.ExpandNode(directedStepCost, costs, queue, here, key, hexside);

                Hexside.ForEach(SetHexside);
            }

            return(costs);
        }
        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
            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));
                    }
                }
            }
 private Path(Path previousSteps, HexCoords step, Hexside direction, int totalCost)
 {
     HexsideExit = direction;
     StepCoords  = step;
     PathSoFar   = previousSteps;
     TotalCost   = totalCost;
     TotalSteps  = previousSteps == null ? 0 : previousSteps.TotalSteps + 1;
 }
 private Path(Path <TNode> previousSteps, TNode thisStep, Hexside direction, uint totalCost, int count)
 {
     _previousSteps = previousSteps;
     LastDirection  = direction;
     LastStep       = thisStep;
     Count          = count;
     TotalCost      = totalCost;
     TotalSteps     = previousSteps == null ? 0 : previousSteps.TotalSteps + 1;
 }
 private Path2(Path2 previousSteps, ICoordsUser thisStep, Hexside direction, uint totalCost, int count)
 {
     _previousSteps = previousSteps;
     LastDirection  = direction;
     LastStep       = thisStep;
     Count          = count;
     TotalCost      = totalCost;
     TotalSteps     = previousSteps == null ? 0 : previousSteps.TotalSteps + 1;
 }
        protected override IEnumerable <NeighbourCoords> GetNeighbours(Hexside hexsides)
        {
            ICoordsCanon coords = this;

            foreach (Hexside hexside in Enum.GetValues(typeof(Hexside)))
            {
                if (hexside != Hexside.None && hexsides.HasFlag(hexside))
                {
                    yield return(new NeighbourCoords(hexside, coords.StepOut(hexside)));
                }
            }
        }
        private void Action(
            IPriorityQueue <int, HexCoords> queue,
            BoardStorage <short?> store,
            TryDirectedCost tryDirectedStepCost,
            HexCoords here, int key, Hexside hexside
            )
        {
            var neighbour = here.GetNeighbour(hexside);

            tryDirectedStepCost(here, hexside).IfHasValueDo(stepCost => {
                store[neighbour].ElseDo(() => Enqueue((short)(key + stepCost), neighbour, store));
            });
        }
        /// <summary>Paint the direction arrow for each hex of the current shortest path.</summary>
        /// <param name="g">Type: Graphics - Object representing the canvas being painted.</param>
        /// <param name="hexside">Type: <see cref="Hexside"/> -
        /// Direction from this hex in which the next step is made.</param>
        /// <remarks>The current graphics origin must be the centre of the current hex.</remarks>
        protected virtual void PaintPathArrow(Graphics g, Hexside hexside)
        {
            if (g == null)
            {
                throw new ArgumentNullException("g");
            }

            var unit = GridSize.Height / 8.0F;

            g.RotateTransform(60 * (int)hexside);
            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);
        }
示例#11
0
        /// <summary>Paint the direction arrow for each hex of the current shortest path.</summary>
        /// <param name="dc">Type: Graphics - Object representing the canvas being painted.</param>
        /// <param name="hexside">Type: <see cref="Hexside"/> -
        /// Direction from this hex in which the next step is made.</param>
        /// <remarks>The current graphics origin must be the centre of the current hex.</remarks>
        protected virtual void PaintPathArrow(DrawingContext graphics, Hexside hexside)
        {
            if (graphics == null)
            {
                throw new ArgumentNullException("graphics");
            }

            var penBlack = new Pen(Brushes.Black, 1.0F);
            var unit     = GridSize.Height / 8.0F;

            graphics.PushTransform(new RotateTransform(60 * (int)hexside));
            graphics.DrawLine(penBlack, new Point(0, unit * 4), new Point(0, -unit));
            graphics.DrawLine(penBlack, new Point(0, unit * 4), new Point(-unit * 3 / 2, unit * 2));
            graphics.DrawLine(penBlack, new Point(0, unit * 4), new Point(unit * 3 / 2, unit * 2));
            graphics.Pop();
        }
            public void Invoke(DirectedPath path, Hexside hexside)
            {
                var here  = path.PathStep.Hex;
                var there = here.Board[here.Coords.GetNeighbour(hexside)];

                if (there != null && !_open.ContainsKey(there.Coords))
                {
                    var cost = _stepCost(there, hexside.Reversed());
                    if (cost > 0)
                    {
                        var newPath  = path.AddStep(there, hexside, cost);
                        var estimate = Estimate(_heuristic, _vectorGoal, _start.Coords, newPath.PathStep.Hex.Coords, newPath.TotalCost);
                        TraceFlags.FindPathEnqueue.Trace("   Enqueue {0}: estimate={1,4}:{2,3}",
                                                         there.Coords, estimate >> 16, estimate & 0xFFFF);
                        _queue.Enqueue(estimate, newPath);
                    }
                }
            }
        public override BoardStorage <short?> Fill()
        {
            // Reduce field references by keeping all these on stack.
            var queue = _queue;
            var store = _store;
            var tryDirectedStepCost = _tryDirectedStepCost;

            HexKeyValuePair <int, HexCoords> item;

            while (queue.TryDequeue(out item))
            {
                var here = item.Value;
                var key  = item.Key;
                Tracing.FindPathDetail.Trace("Dequeue Path at {0} w/ cost={1,4}.", here, key);

                Hexside.ForEach(hexside => Action(queue, store, tryDirectedStepCost, here, key, hexside));
            }
            return(store);
        }
        ICoordsCanon ICoordsCanon.StepOut(Hexside hexside)
        {
            switch (hexside)
            {
            case Hexside.NorthWest:   return(StepOut(new IntVector2D(-1, -1)));

            case Hexside.North:       return(StepOut(new IntVector2D(0, -1)));

            case Hexside.NorthEast:   return(StepOut(new IntVector2D(1, 0)));

            case Hexside.SouthEast:   return(StepOut(new IntVector2D(1, 1)));

            case Hexside.South:       return(StepOut(new IntVector2D(0, 1)));

            case Hexside.SouthWest:   return(StepOut(new IntVector2D(-1, 0)));

            default:                  throw new ArgumentOutOfRangeException();
            }
        }
        void ExpandHex(DirectedPath path, Hexside hexside)
        {
            var here  = path.PathStep.Hex;
            var there = here.Neighbour(hexside);

            if (there != null && !_closed.Contains(there.Coords))
            {
                var cost = _stepCost(here, hexside, there);
                if ((cost > 0)
                    )
                {
                    if ((path.TotalCost + cost < _getBestSoFar() || !_open.ContainsKey(there.Coords))
                        )
                    {
                        var totalCost = cost + path.TotalCost;
                        var key       = Estimate(here, there, totalCost);
                        var newPath   = _addStep(path, there, hexside, cost);

                        TraceFlags.FindPathEnqueue.Trace("   Enqueue {0}: estimate={1,4}:{2,4}",
                                                         there.Coords, key >> 16, key & 0xFFFF);

                        DirectedPath oldPath;
                        if (!_open.TryGetValue(there.Coords, out oldPath))
                        {
                            _open.Add(there.Coords, newPath);
                            _queue.Enqueue(key, newPath);
                        }
                        else if (newPath.TotalCost < oldPath.TotalCost)
                        {
                            _open.Remove(there.Coords);
                            _open.Add(there.Coords, newPath);
                            _queue.Enqueue(key, newPath);
                        }

                        _setBestSoFar(newPath, Partner.GetPartnerPath(there.Coords));
                    }
                }
            }
        }
 /// <inheritdoc/>
 public IDirectedPathCollection AddStep(IHex hex, Hexside hexsideExit, int stepCost)
 {
     return(AddStep(new NeighbourHex(hex, hexsideExit), stepCost));
 }
示例#17
0
 IEnumerable <NeighbourCoords> ICoordsUser.GetNeighbours(Hexside hexsides)
 {
     return(GetNeighbours(hexsides));
 }
 /// <inheritdoc/>
 public override int  StepCost(Hexside direction)
 {
     return(-1);
 }
        void ExpandHex(DirectedPath path, Hexside hexside)
        {
            var here = path.PathStep.Hex;
            var there = here.Neighbour(hexside);
            if (there != null && !_closed.Contains(there.Coords))
            {
                var cost = _stepCost(here, hexside, there);
                if ((cost > 0)
                )
                {
                    if ((path.TotalCost + cost < _getBestSoFar() || !_open.ContainsKey(there.Coords))
                    )
                    {
                        var totalCost = cost + path.TotalCost;
                        var key = Estimate(here, there, totalCost);
                        var newPath = _addStep(path, there, hexside, cost);

                        DirectedPath oldPath;
                        if (!_open.TryGetValue(there.Coords, out oldPath))
                        {
                            _open.Add(there.Coords, newPath);
                            _queue.Enqueue(key, newPath);
                        }
                        else if (newPath.TotalCost < oldPath.TotalCost)
                        {
                            _open.Remove(there.Coords);
                            _open.Add(there.Coords, newPath);
                            _queue.Enqueue(key, newPath);
                        }

                        _setBestSoFar(newPath, Partner.GetPartnerPath(there.Coords));
                    }
                }
            }
        }
 /// <summary>Elevation of the hexside Above Sea Level</summary>
 /// <param name="this">The {IFovBoard} to be analyzed.</param>
 /// <param name="coords">The coordinates of the hex being tested.</param>
 /// <param name="hexside"></param>
 public static int ElevationHexsideASL(this IFovBoard @this, HexCoords coords, Hexside hexside)
 => @this[coords].Match(hex => @this.ElevationASL(hex) + hex.HeightHexside(hexside), MaxValue32);
 private Path2(Path2 previousSteps, ICoordsUser thisStep, Hexside direction, uint totalCost)
     : this(previousSteps, thisStep, direction, totalCost, 0)
 {
 }
        public override double StepCost(Hexside direction)
        {
            if (SelectedArmy != null)
            {
                switch (SelectedArmy.ArmyType)
                {
                    case "Standard":
                    case "Mounstrous":
                    case "Mounted":
                        return SpecialType == "Road" ? _stepCost / 2 : _stepCost;
                    case "Scouting":
                        if (_stepCost == 1) return SpecialType == "Road" ? _stepCost / 2 : _stepCost;
                        else return SpecialType == "Road" ? (_stepCost - 1) / 2 : (_stepCost - 1);
                    case "Flying":
                        return 1;
                    default:
                        return SpecialType == "Road" ? _stepCost / 2 : _stepCost;
                }
            }

            return SpecialType == "Road" ? _stepCost / 2 : _stepCost;
        }
示例#23
0
 /// <summary>Creates a new <see cref="DirectedPathStepHex"/> instance at <paramref name="hex"/> exiting through <paramref name="hexsideExit"/>.</summary>
 /// <param name="hex"></param>
 /// <param name="hexsideExit"></param>
 /// <remarks>
 /// This is usually only used as the initial step for a new <see cref="DirectedPathCollection"/>.
 /// </remarks>
 public DirectedPathStepHex(IHex hex, Hexside hexsideExit) : this()
 {
     Hex         = hex;
     HexsideExit = hexsideExit;
 }
示例#24
0
 /// <summary>TODO</summary>
 /// <param name="hex"></param>
 /// <param name="hexside"></param>
 /// <param name="stepCost"></param>
 /// <param name="key"></param>
 /// <returns></returns>
 public DirectedPath AddStep(IHex hex, Hexside hexside, int stepCost, int key)
 {
     return(AddStep(new NeighbourHex(hex, hexside), stepCost, key));
 }
 /// <summary>TODO</summary>
 public override int           StepCost(Hexside hexsideExit)
 {
     return(-1);
 }
示例#26
0
 /// <summary>TODO</summary>
 public int TryEntryCost(HexCoords hexCoords, Hexside hexside) =>
 (from x in _entryCosts[hexCoords] select x[hexside]).ElseDefault() ?? -1;
        private void ExpandNode(BoardStorage <short> store, Func <IHex, Hexside, IHex, int> directedStepCost,
                                IPriorityQueue <int, IHex> queue, IHex here, int key, Hexside hexside
                                )
        {
            var neighbourCoords = here.Coords.GetNeighbour(hexside);
            var neighbourHex    = Board[neighbourCoords];

            if (neighbourHex != null)
            {
                var cost = directedStepCost(here, hexside, neighbourHex);
                if (cost > 0 && store[neighbourCoords] == -1)
                {
                    FindPathDetailTrace("   Enqueue {0}: {1,4}", neighbourCoords, cost);

                    queue.Enqueue(key + cost, neighbourHex);
                }
            }
        }
示例#28
0
 /// <inheritdoc/>
 public Maybe <THex> Neighbour(HexCoords coords, Hexside hexside)
 => BoardHexes.Neighbour(coords, hexside);
示例#29
0
 /// <summary>TODO</summary>
 public NeighbourHex(IHex hex, Hexside?hexsideIndex) : this()
 {
     Hex          = hex;
     HexsideIndex = hexsideIndex ?? 0;
 }
 public Path2 AddStep(ICoordsUser step, uint stepCost, Hexside direction)
 {
     return(new Path2(this, step, direction, TotalCost + stepCost));
 }
 ///  <inheritdoc/>
 public override short?TryStepCost(Hexside direction) => _stepCost; readonly short?_stepCost;
示例#32
0
 /// <summary>TODO</summary>
 public short?TryEntryCost(HexCoords hexCoords, Hexside hexside)
 => (from x in EntryCosts[hexCoords] from c in x[hexside].ToMaybe() select c).ToNullable();