using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using Random = System.Random; namespace Assets.Map { public class LocationGenerator { private Graph _graph; private readonly List<(int, Location)> _queue = new List<(int, Location)>(); private Random _random; public bool Done => _queue.Count == 0; public Graph Result => _graph; private Dictionary> _blacklist = new Dictionary>(); public LocationGenerator(Graph graph, Random random = null) { _graph = graph; _random = random ?? new Random(); } public void Init(params (int, Location)[] start) { foreach (var (vertex, location) in start) SetLocation(vertex, location); } private (int, Location) Dequeue() { while (_queue.Count > 0) { var index = _random.Next(_queue.Count); var pair = _queue[index]; _queue.RemoveAt(index); if (_graph.Vertices[pair.Item1].Location == null) return pair; } throw new Exception("No more elements."); } public void Step() { try { var (vertex, location) = Dequeue(); SetLocation(vertex, location); } catch (Exception ex) { } } private void SetLocation(int vertex, Location location) { _graph.Vertices[vertex].Location = location; location.Sites.Add(_graph.Vertices[vertex]); FixBoundaryPoints(vertex, location); FixBoundaryEdges(vertex, location); foreach (var neighbour in _graph.Neighbours(vertex)) if (_graph.Vertices[neighbour].Location == null) _queue.Add((neighbour, location)); } private void FixBoundaryPoints(int vertex, Location location) { var a = location.BoundaryPoints; var b = _graph.Vertices[vertex].Site.Vertices; if (!_blacklist.ContainsKey(location)) _blacklist[location] = new List(); _blacklist[location].AddRange(a.Intersect(b)); location.BoundaryPoints = a.Union(b).Except(_blacklist[location]).ToList(); } private void FixBoundaryEdges(int vertex, Location location) { var a = location.BoundaryEdges; var b = _graph.Vertices[vertex].Site.Edges; location.BoundaryEdges = a.Union(b).Except(a.Intersect(b)).ToList(); } } }