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; } } } }
// 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); }
/// <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); }
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)); }
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); }