Example #1
0
 private void ScanInternal()
 {
     while (frontier.Count > 0)
     {
         Point current = frontier.Dequeue();
         foreach (Dir8 dir in EightDirections.Enumerate(true, false, false))
         {
             Point neighbor = current.PointInDir(dir);
             if (!neighbor.ExistsOnMap())
             {
                 continue;
             }
             int neighborCost = GetCellCost(neighbor);
             if (neighborCost < 0)
             {
                 if (this[neighbor] == Unexplored)
                 {
                     this[neighbor] = Blocked;
                 }
             }
             else
             {
                 int totalCost = this[current] + neighborCost;
                 if (this[neighbor] > totalCost)
                 {
                     this[neighbor] = totalCost;
                     frontier.Enqueue(neighbor, totalCost);
                 }
             }
         }
     }
 }
Example #2
0
 public static IEnumerable <Point> GetNeighbors(this Point source)
 {
     foreach (Dir8 dir in EightDirections.Enumerate(true, false, false))
     {
         yield return(source.PointInDir(dir));
     }
 }
        public static IEnumerable <Point> Scan(Point source, Func <Point, bool> condition, SourceOption sourceOption = SourceOption.AlwaysIncludeSource)
        {
            List <Point>    frontier = new List <Point>();
            HashSet <Point> visited  = new HashSet <Point> {
                source
            };

            switch (sourceOption)
            {
            case SourceOption.AlwaysIncludeSource:
                yield return(source);

                break;

            case SourceOption.ConditionallyIncludeSource:
            case SourceOption.StopScanOnSourceFailure:
                if (condition.Invoke(source))
                {
                    yield return(source);
                }
                else if (sourceOption == SourceOption.StopScanOnSourceFailure)
                {
                    yield break;
                }
                break;
            }
            frontier.Add(source);
            while (frontier.Count > 0)
            {
                Point current = frontier[frontier.Count - 1];
                frontier.RemoveAt(frontier.Count - 1);
                foreach (Dir8 dir in EightDirections.Enumerate(true, false, false))
                {
                    Point neighbor = current.PointInDir(dir);
                    if (!neighbor.ExistsBetweenMapEdges())
                    {
                        continue;
                    }
                    if (visited.Contains(neighbor))
                    {
                        continue;
                    }
                    if (condition.Invoke(neighbor))
                    {
                        yield return(neighbor);

                        frontier.Add(neighbor);
                        visited.Add(neighbor);
                    }
                }
            }
        }
Example #4
0
        /* Might add these at some point -- these are the ones that would allow partial rescans by resetting values starting at the changed cell(s).
         * 1) Search outward from the given changed cell(s) as long as you can keep jumping to a cell with HIGHER total cost. This set of cells represents
         *      all the cells which might have been influenced by the changed cell(s).
         * 2) Note where this search stopped:  Each of the cells adjacent to this set (but not part of it) will be the frontier for the rescan.
         * 3) Reset the value of each cell in this set to Unexplored.
         * 3) Rescan the map from the frontier.
         * (If any of the changed cells could be sources, that needs to be handled too.)
         * public void Rescan(Point changedCell){ }
         * public void Rescan(IEnumerable<Point> changedCells){ }*/

        private void RescanInternal()          // Differs from ScanInternal in how it uses the frontier
        {
            while (frontier.Count > 0)
            {
                Point current = frontier.Dequeue();
                foreach (Dir8 dir in EightDirections.Enumerate(true, false, false))
                {
                    Point neighbor = current.PointInDir(dir);
                    if (!neighbor.ExistsOnMap())
                    {
                        continue;
                    }
                    if (this[neighbor] == Blocked)
                    {
                        continue;
                    }
                    int neighborCost = GetCellCost(neighbor);
                    if (neighborCost < 0)
                    {
                        if (this[neighbor] == Unexplored)
                        {
                            frontier.TryRemove(neighbor);                             // (Not sure this can happen on a rescan if done correctly)
                            this[neighbor] = Blocked;
                        }
                    }
                    else
                    {
                        int totalCost = this[current] + neighborCost;
                        if (this[neighbor] > totalCost)
                        {
                            // Remove them before changing sort values, so the sort doesn't break:
                            if (this[neighbor] != Unexplored)
                            {
                                frontier.TryRemove(neighbor);
                            }
                            this[neighbor] = totalCost;
                            frontier.Enqueue(neighbor, totalCost);
                        }
                    }
                }
            }
        }