예제 #1
0
        public static IEnumerable <Loc> FindClosestConnectedTiles(Loc rectStart, Loc rectSize, LocTest checkFree, LocTest checkBlock, LocTest checkDiagBlock, Loc loc, int amount)
        {
            if (checkFree == null)
            {
                throw new ArgumentNullException(nameof(checkFree));
            }

            // create an array to cache which tiles were already traversed
            bool[][] fillArray = new bool[rectSize.X][];
            for (int ii = 0; ii < rectSize.X; ii++)
            {
                fillArray[ii] = new bool[rectSize.Y];
            }

            // use typical fill method
            StablePriorityQueue <int, Loc> locList = new StablePriorityQueue <int, Loc>();
            Loc offset_loc = loc - rectStart;

            locList.Enqueue(0, offset_loc);
            fillArray[offset_loc.X][offset_loc.Y] = true;
            int found = 0;

            while (locList.Count > 0)
            {
                Loc candidate = locList.Dequeue();

                if (checkFree(candidate + rectStart))
                {
                    yield return(candidate + rectStart);

                    found++;
                    if (found >= amount)
                    {
                        yield break;
                    }
                }

                foreach (Dir8 dir in DirExt.VALID_DIR8)
                {
                    Loc movedLoc = candidate + dir.GetLoc();
                    if (Collision.InBounds(rectSize.X, rectSize.Y, movedLoc) && !fillArray[movedLoc.X][movedLoc.Y] && !IsDirBlocked(candidate + rectStart, dir, checkBlock, checkDiagBlock))
                    {
                        Loc diff = movedLoc - offset_loc;
                        locList.Enqueue(diff.DistSquared(), movedLoc);
                        fillArray[movedLoc.X][movedLoc.Y] = true;
                    }
                }
            }
        }
예제 #2
0
        // an initial create-map method
        public T GenMap(ulong seed)
        {
            // may not need floor ID
            T map = (T)Activator.CreateInstance(typeof(T));

            map.InitSeed(seed);

            GenContextDebug.DebugInit(map);

            // postprocessing steps:
            StablePriorityQueue <Priority, IGenStep> queue = new StablePriorityQueue <Priority, IGenStep>();

            foreach (Priority priority in this.GenSteps.GetPriorities())
            {
                foreach (IGenStep genStep in this.GenSteps.GetItems(priority))
                {
                    queue.Enqueue(priority, genStep);
                }
            }

            ApplyGenSteps(map, queue);

            map.FinishGen();

            return(map);
        }
예제 #3
0
        /// <summary>
        /// Gets the N largest rectangles in the grid that are not a subset of a larger rectangle.  Modifies the grid in-place.
        /// </summary>
        /// <param name="grid">2D array of 0's and 1's</param>
        /// <param name="amount">Max number of rectangles to return.</param>
        /// <returns></returns>
        public static List <Rect> DetectNLargestRects(bool[][] grid, int amount)
        {
            StablePriorityQueue <int, Rect> queue = new StablePriorityQueue <int, Rect>();

            foreach (Rect rect in FindAllRects(grid))
            {
                queue.Enqueue(-rect.Width * rect.Height, rect);
            }

            List <Rect> results = new List <Rect>();

            while (results.Count < amount && queue.Count > 0)
            {
                results.Add(queue.Dequeue());
            }
            return(results);
        }
예제 #4
0
        public static List <Loc> FindAPath(Loc rectStart, Loc rectSize, Loc start, Loc[] ends, LocTest checkBlock, LocTest checkDiagBlock)
        {
            // searches for one specific path (ends[0]), but doesn't mind hitting the other ones
            PathTile[][] tiles = new PathTile[rectSize.X][];
            for (int ii = 0; ii < rectSize.X; ii++)
            {
                tiles[ii] = new PathTile[rectSize.Y];
                for (int jj = 0; jj < rectSize.Y; jj++)
                {
                    tiles[ii][jj] = new PathTile(new Loc(rectStart.X + ii, rectStart.Y + jj));
                }
            }

            Loc offset_start = start - rectStart;

            StablePriorityQueue <double, PathTile> candidates = new StablePriorityQueue <double, PathTile>();
            PathTile start_tile = tiles[offset_start.X][offset_start.Y];

            start_tile.Heuristic = Math.Sqrt((ends[0] - start).DistSquared());
            start_tile.Cost      = 0;
            candidates.Enqueue(start_tile.Heuristic + start_tile.Cost, start_tile);

            PathTile farthest_tile = start_tile;

            while (candidates.Count > 0)
            {
                PathTile currentTile = candidates.Dequeue();
                for (int ii = 0; ii < ends.Length; ii++)
                {
                    if (currentTile.Location == ends[ii])
                    {
                        return(GetBackreference(currentTile));
                    }
                }

                if (currentTile.Heuristic < farthest_tile.Heuristic)
                {
                    farthest_tile = currentTile;
                }

                currentTile.Traversed = true;

                foreach (Dir8 dir in DirExt.VALID_DIR8)
                {
                    if (!IsDirBlocked(currentTile.Location, dir, checkBlock, checkDiagBlock))
                    {
                        Loc newLoc = currentTile.Location - rectStart + dir.GetLoc();
                        if (Collision.InBounds(rectSize.X, rectSize.Y, newLoc))
                        {
                            PathTile tile = tiles[newLoc.X][newLoc.Y];

                            if (tile.Traversed)
                            {
                                continue;
                            }

                            int newCost = currentTile.Cost + 1;
                            if (tile.Cost == -1 || newCost < tile.Cost)
                            {
                                tile.Cost          = newCost;
                                tile.Heuristic     = Math.Sqrt((ends[0] - tile.Location).DistSquared());
                                tile.BackReference = currentTile;
                                candidates.AddOrSetPriority(tile.Heuristic + tile.Cost, tile);
                            }
                        }
                    }
                }
            }

            return(GetBackreference(farthest_tile));
        }
예제 #5
0
        private static List <Loc>[] FindMultiPaths(Loc rectStart, Loc rectSize, Loc start, Loc[] ends, LocTest checkBlock, LocTest checkDiagBlock, EvalPaths eval, EvalFallback fallback)
        {
            if (ends.Length == 0)
            {
                return(new List <Loc> [0]);
            }

            PathTile[][] tiles = new PathTile[rectSize.X][];
            for (int ii = 0; ii < rectSize.X; ii++)
            {
                tiles[ii] = new PathTile[rectSize.Y];
                for (int jj = 0; jj < rectSize.Y; jj++)
                {
                    tiles[ii][jj] = new PathTile(new Loc(rectStart.X + ii, rectStart.Y + jj));
                }
            }

            Loc offset_start = start - rectStart;

            StablePriorityQueue <double, PathTile> candidates = new StablePriorityQueue <double, PathTile>();
            PathTile start_tile = tiles[offset_start.X][offset_start.Y];

            start_tile.UpdateHeuristics(ends);
            start_tile.Cost = 0;
            candidates.Enqueue(start_tile.MinHeuristic + start_tile.Cost, start_tile);

            List <Loc>[] resultPaths = new List <Loc> [ends.Length];

            PathTile[] farthestTiles = new PathTile[ends.Length];
            for (int ii = 0; ii < farthestTiles.Length; ii++)
            {
                farthestTiles[ii] = start_tile;
            }

            while (candidates.Count > 0)
            {
                PathTile currentTile = candidates.Dequeue();

                if (eval(ends, resultPaths, farthestTiles, currentTile))
                {
                    return(resultPaths);
                }

                currentTile.Traversed = true;

                foreach (Dir8 dir in DirExt.VALID_DIR8)
                {
                    Loc newLoc = currentTile.Location - rectStart + dir.GetLoc();
                    if (Collision.InBounds(rectSize.X, rectSize.Y, newLoc))
                    {
                        if (!IsDirBlocked(currentTile.Location, dir, checkBlock, checkDiagBlock))
                        {
                            PathTile tile = tiles[newLoc.X][newLoc.Y];

                            if (tile.Traversed)
                            {
                                continue;
                            }

                            int newCost = currentTile.Cost + 1;
                            if (tile.Cost == -1 || newCost < tile.Cost)
                            {
                                tile.Cost = newCost;
                                tile.UpdateHeuristics(ends);
                                tile.BackReference = currentTile;
                                candidates.AddOrSetPriority(tile.MinHeuristic + tile.Cost, tile);
                            }
                        }
                    }
                }
            }

            fallback(resultPaths, farthestTiles);

            return(resultPaths);
        }