inz-00/Assets/Map/LocationGenerator.cs
2019-08-16 16:48:49 +02:00

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