internal void FillLandmark(IBoard <IHex> board) { if (board != null) { backingStore = new BoardStorage <short> .BlockedBoardStorage32x32(board.MapSizeHexes, c => - 1); var start = board[Coords]; var queue = DictionaryPriorityQueue <int, IHex> .NewQueue(); TraceFlags.FindPathDetail.Trace(true, "Find distances from {0}", start.Coords); queue.Enqueue(0, start); HexKeyValuePair <int, IHex> item; while (queue.TryDequeue(out item)) { var here = item.Value; var key = item.Key; if (backingStore[here.Coords] > 0) { continue; } TraceFlags.FindPathDetail.Trace("Dequeue Path at {0} w/ cost={1,4}.", here, key); backingStore[here.Coords] = (short)key; foreach (var there in here.GetAllNeighbours().Where(n => n != null && n.Hex.IsOnboard())) { var cost = board.DirectedStepCost(here, there.HexsideEntry); if (cost > 0 && backingStore[there.Hex.Coords] == -1) { TraceFlags.FindPathDetail.Trace(" Enqueue {0}: {1,4}", there.Hex.Coords, cost); queue.Enqueue(key + cost, there.Hex); } } } } }
/// <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 cost estimate from a range value.</param> /// <param name="isOnboard">Returns whether the coordinates specified are "on board".</param> public static IPath FindPath( HexCoords start, HexCoords goal, Func <HexCoords, Hexside, int> stepCost, Func <int, int> heuristic, Func <HexCoords, bool> isOnboard ) { if (stepCost == null) { throw new ArgumentNullException("stepCost"); } if (heuristic == null) { throw new ArgumentNullException("heuristic"); } if (isOnboard == null) { throw new ArgumentNullException("isOnboard"); } var vectorGoal = goal.Canon - start.Canon; var closed = new HashSet <HexCoords>(); var open = new HashSet <HexCoords>(); var queue = DictionaryPriorityQueue <int, Path> .NewQueue(); TraceFlags.FindPathDetail.Trace(true, "Find path from {0} to {1}; vectorGoal = {0}", start.Canon, goal.Canon, vectorGoal); queue.Enqueue(0, new Path(start)); HexKeyValuePair <int, Path> item; while (queue.TryDequeue(out item)) { var path = item.Value; if (closed.Contains(path.StepCoords)) { continue; } open.Add(item.Value.StepCoords); TraceFlags.FindPathDetail.Trace( "Dequeue Path at {0} w/ cost={1,4} at {2}; estimate={3,4}:{4,4}.", item.Value.StepCoords, item.Value.TotalCost, item.Value.HexsideExit, item.Key >> 16, item.Key & 0xFFFF); if (path.StepCoords.Equals(goal)) { return(path); } closed.Add(path.StepCoords); foreach (var neighbour in path.StepCoords.GetNeighbours() .Where(n => isOnboard(n.Coords)) ) { var cost = stepCost(path.StepCoords, neighbour.Hexside); if (cost > 0) { var newPath = path.AddStep(neighbour, (ushort)cost); var estimate = Estimate(heuristic, vectorGoal, goal, newPath.StepCoords, newPath.TotalCost); TraceFlags.FindPathDetail.Trace(" Enqueue {0}: {1,4}:{2,3}", neighbour.Coords, estimate >> 16, estimate & 0xFFFF); queue.Enqueue(estimate, newPath); } } } return(null); }