示例#1
0
        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);
                        }
                    }
                }
            }
        }
示例#2
0
        /// <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);
        }