Beispiel #1
0
        // PERF: If this ends up being slow, we can mark with a dirty bit

        /**
         * Returns a path from start to end, exclusive - that is, the start and end nodes are *not* listed in the path. Does a full
         * naive search every time.
         */
        public static List <EncounterPosition> AStarWithNewGrid(
            EncounterPosition start,
            EncounterPosition end,
            EncounterState state,
            int maxAreaToExplore = 950
            )
        {
            SimplePriorityQueue <EncounterPosition> frontier = new SimplePriorityQueue <EncounterPosition>();

            frontier.Enqueue(start, 0f);

            var cameFrom = new Dictionary <EncounterPosition, EncounterPosition>();

            var costSoFar = new Dictionary <EncounterPosition, float>();

            costSoFar[start] = 0f;

            while (frontier.Count > 0 && cameFrom.Count < maxAreaToExplore)
            {
                var currentPosition   = frontier.Dequeue();
                var adjacentPositions = state.AdjacentPositions(currentPosition);

                if (adjacentPositions.Contains(end))
                {
                    var path = new List <EncounterPosition>()
                    {
                        currentPosition
                    };

                    EncounterPosition cameFromPos;
                    while (cameFrom.TryGetValue(path[path.Count - 1], out cameFromPos) && (cameFromPos != start))
                    {
                        path.Add(cameFromPos);
                    }
                    path.Reverse();

                    return(path);
                }

                var adjacentUnblocked = adjacentPositions.Where(adjacent => !state.IsPositionBlocked(adjacent)).ToList();
                adjacentUnblocked.ForEach(adjacent => {
                    var newNextPositionCost = costSoFar[currentPosition] + 1f;
                    if (!costSoFar.ContainsKey(adjacent) || newNextPositionCost < costSoFar[adjacent])
                    {
                        costSoFar[adjacent] = newNextPositionCost;
                        // Uses straight-line distance as heuristic
                        float priority = newNextPositionCost + adjacent.DistanceTo(end);
                        frontier.Enqueue(adjacent, priority);
                        cameFrom[adjacent] = currentPosition;
                    }
                });
            }
            return(null);
        }
        public static EncounterPath BuildReverseLinePath(EncounterPosition start, EncounterPosition target, int overshoot)
        {
            var distance = (int)Math.Ceiling(start.DistanceTo(target));

            var outwardPath = StraightLine(start, target, numSteps: distance + overshoot, endsAtTarget: false);
            var reversePath = StraightLine(outwardPath[outwardPath.Count - 2], start, numSteps: distance + overshoot, endsAtTarget: false);

            reversePath.RemoveAt(reversePath.Count - 1);
            outwardPath.AddRange(reversePath);
            return(new EncounterPath(outwardPath));
        }
        private static List <EncounterPosition> StraightLine(EncounterPosition start, EncounterPosition end, int numSteps, bool endsAtTarget)
        {
            List <EncounterPosition> acc = new List <EncounterPosition>();

            acc.Add(start);

            bool  isVertical = start.X == end.X;
            float dError     = isVertical ? float.MaxValue : Math.Abs(((float)end.Y - (float)start.Y) / ((float)end.X - (float)start.X));

            int yErr  = end.Y - start.Y > 0 ? 1 : -1;
            int xDiff = end.X - start.X > 0 ? 1 : -1;

            float error = 0.0f;
            int   cX    = start.X;
            int   cY    = start.Y;
            int   steps = 0;

            while (steps < numSteps)
            {
                EncounterPosition newPosition;
                if (isVertical)
                {
                    cY         += yErr;
                    newPosition = new EncounterPosition(cX, cY);
                }
                else if (error >= 0.5f)
                {
                    cY         += yErr;
                    error      -= 1f;
                    newPosition = new EncounterPosition(cX, cY);
                }
                else
                {
                    cX         += xDiff;
                    error      += dError;
                    newPosition = new EncounterPosition(cX, cY);
                }

                acc.Add(newPosition);
                if (endsAtTarget && newPosition == end)
                {
                    break;
                }

                steps += 1;
            }

            return(acc);
        }
Beispiel #4
0
 public List <EncounterPosition> AStar(EncounterPosition start, EncounterPosition end, EncounterState state)
 {
     return(AStarWithNewGrid(start, end, state));
 }
 public static EncounterPath BuildStraightLinePath(EncounterPosition start, EncounterPosition target, int maxSteps = 100, bool endsAtTarget = false)
 {
     return(new EncounterPath(StraightLine(start, target, maxSteps, endsAtTarget)));
 }