91 lines
2.7 KiB
C#
91 lines
2.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using Random = System.Random;
|
|
|
|
namespace Assets.Map
|
|
{
|
|
public class LocationGenerator
|
|
{
|
|
private Graph<LocationSite> _graph;
|
|
private readonly List<(int, Location)> _queue = new List<(int, Location)>();
|
|
private Random _random;
|
|
|
|
public bool Done => _queue.Count == 0;
|
|
public Graph<LocationSite> Result => _graph;
|
|
private Dictionary<Location, List<int>> _blacklist = new Dictionary<Location, List<int>>();
|
|
|
|
public LocationGenerator(Graph<LocationSite> 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<int>();
|
|
_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();
|
|
}
|
|
}
|
|
} |