using System; using System.Collections.Generic; using UnityEngine.UIElements; using Random = System.Random; namespace DungeonGenerator { public class EvenDisperser { private List _samples = new List(){new Point(1,1)}; private List _availablePoints; public EvenDisperser(int xLength, int yLength, List excludedPoints = null) { _availablePoints = GenerateAvailablePoints(xLength, yLength, excludedPoints ?? new List()); } private List GenerateAvailablePoints(int xLength, int yLength, List excludedPoints) { List availablePoints = new List(); for (var x = 0; x < xLength; x++) { for (var y = 0; y < yLength; y++) { if (!excludedPoints.Contains(new Point(x, y))) { availablePoints.Add(new Point(x, y)); } } } return availablePoints; } // Can place point so that the x lengt hand y length go out of bounds to the right and down. public Point GetPoint(int xLength, int yLength) { int numCandidates = 50; // Increasing improves results but greatly effects performance. Random rnd = new Random(); int randomIndex = rnd.Next(0, _availablePoints.Count); Point bestCandidate = new Point(Int32.MaxValue, Int32.MaxValue); int bestDistance = 0; for (var i = 0; i < numCandidates; i++) { var candidate = _availablePoints[randomIndex]; var distance = candidate.ManhattanDistance(FindClosest(_samples, candidate)); if (distance > bestDistance) { RemoveArea(candidate, xLength, yLength, _availablePoints); bestCandidate = candidate; bestDistance = distance; } } _samples.Add(bestCandidate); return bestCandidate; } private Point FindClosest(List options, Point reference) { Point closest = options[0]; foreach (var option in options) { if (reference.ManhattanDistance(option) < reference.ManhattanDistance(closest)) { closest = option; } } return closest; } private void RemoveArea(Point topLeft, int xLength, int yLength, List availablePoints) { for (var x = topLeft.X; x < topLeft.X + xLength; x++) { for (var y = topLeft.Y; y < topLeft.Y + yLength; y++) { availablePoints.Remove(new Point(x, y)); } } } } }