using System; using System.Collections.Generic; using System.Linq; using UnityEngine.UIElements; using Random = System.Random; namespace DungeonGenerator { public class EvenDisperser { private List _samples = new List(){new Room( RoomType.Normal, 1, 1, new Point(1000, 1000))}; private HashSet _availablePoints; public EvenDisperser(int xLength, int yLength, HashSet availablePoints) { _availablePoints = availablePoints; } private HashSet GenerateAvailablePoints(int xLength, int yLength, List excludedPoints) { HashSet availablePoints = new HashSet(); 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; } public Room GenerateAndPlaceRoom(int xLength, int yLength, RoomType roomType) { int numCandidates = 100; // Increasing improves results but greatly effects performance. Random rnd = new Random(); Room bestCandidate = new Room(roomType, xLength, yLength, new Point(Int32.MaxValue, Int32.MaxValue)); int bestDistance = 0; for (var i = 0; i < numCandidates; i++) { var candidate = new Room( roomType, xLength, yLength, _availablePoints.ToList()[rnd.Next(0, _availablePoints.Count)]); var distance = candidate.GetDistanceToRoom(FindClosestRoom(_samples, candidate)); if (distance > bestDistance && candidate.GetPointsInRoom().All(room => _availablePoints.Contains(room))) { _availablePoints.ExceptWith(candidate.GetPointsInRoom()); bestCandidate = candidate; bestDistance = distance; } } _samples.Add(bestCandidate); return bestCandidate; } private Room FindClosestRoom(List options, Room reference) { Room closest = options[0]; foreach (var option in options) { if (reference.GetDistanceToRoom(option) < reference.GetDistanceToRoom(closest)) { closest = option; } } return closest; } } }