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)); }); } }); } }
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); }
/// <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)); }
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; }
/// <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; }
/// <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); }
/// <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); } } }
/// <inheritdoc/> public Maybe <THex> Neighbour(HexCoords coords, Hexside hexside) => BoardHexes.Neighbour(coords, hexside);
/// <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;
/// <summary>TODO</summary> public short?TryEntryCost(HexCoords hexCoords, Hexside hexside) => (from x in EntryCosts[hexCoords] from c in x[hexside].ToMaybe() select c).ToNullable();