public RichArea(Patch patch) : base(patch) { }
public PoorArea(Patch patch) : base(patch) { }
public OutsideWallArea(Patch patch) : base(patch) { }
public EmptyArea(Patch patch) : base(patch) { }
public CastleArea(Patch patch) : base(patch) { }
public TownArea(Patch patch) : base(patch) { _town = patch.Town; }
public FarmArea(Patch patch) : base(patch) { }
protected Area(Patch patch) { Patch = patch; random = patch.Town.Random; }
public Polygon FindCircumference(Patch patch) { return(FindCircumference(new List <Patch> { patch })); }
private void BuildPatches() { var points = GetVoronoiPoints(NumPatches, Center).ToList(); var v = Voronoi.Build(points); for (var i = 0; i < 3; i++) { var toRelax = v.Points.Take(3).ToList(); toRelax.Add(v.Points[NumPatches]); v = Voronoi.Relax(v, toRelax); } v = Voronoi.Relax(v); var comparer = new Vector2LengthComparer(); v.Points.Sort(comparer); var regions = v.Partitioning(); Patches.Clear(); foreach (var region in regions) { Patches.Add(Patch.FromRegion(this, region)); } var patchesInTown = Patches.OrderBy(p => (Center - p.Center).Length).Take(NumPatches).ToList(); // Find random patch at the outside of town to place water if (Options.Water) { var firstWaterPatch = patchesInTown.Where(p => p.GetAllNeighbours().Any(n => !n.WithinCity)) .OrderBy(p => Rnd.NextDouble()).First(); firstWaterPatch.Water = true; var waterDirection = Vector2.Normalize(firstWaterPatch.Center - Center); var toCheck = new List <Patch> { firstWaterPatch }; while (toCheck.Any()) { var checking = toCheck[0]; toCheck.RemoveAt(0); var waterPatches = checking.GetAllNeighbours().Except(patchesInTown) .Where(n => Math.Abs((Center - n.Center).AngleComparedTo(waterDirection)) < Math.PI / 4) .Where(n => !n.Water).ToList(); foreach (var waterPatch in waterPatches) { waterPatch.Water = true; toCheck.Add(waterPatch); } } } patchesInTown = Patches.Where(p => !p.Water).OrderBy(p => (Center - p.Center).Length).Take(NumPatches) .ToList(); foreach (var patch in patchesInTown) { patch.WithinCity = true; patch.WithinWalls = true; } Castle = new Castle(patchesInTown.Last()); Market = patchesInTown.First(); var circumference = FindCircumference(patchesInTown); var smoothAmount = Math.Min(1f, 40f / circumference.Vertices.Count); if (Options.Walls) { SmoothPatches(circumference, smoothAmount); } if (Options.Water) { var waterCircumference = FindCircumference(Patches.Where(p => p.Water)); SmoothPatches(waterCircumference, 0.2f); WaterBorder.Clear(); WaterBorder.AddRange(waterCircumference.Vertices); } }
protected Area(Patch patch) { Patch = patch; }
private void PlaceGatesAndTowers(IEnumerable <Vector2> allowedTowerPositions, int minNumberOfGates, int maxNumberOfGates, List <Vector2> illegalGatePositions) { var cityPatches = _town.Patches.Where(p => p.WithinCity).ToList(); var outsidePatches = _town.Patches.Except(cityPatches).ToList(); var possibleGates = allowedTowerPositions .Where(v => cityPatches.Count(cp => cp.Shape.Vertices.Contains(v)) > 1) .Except(illegalGatePositions) .OrderByDescending(v => (_town.Castle.Patch.Center - v).Length) .ToList(); var towers = Circumference.ToList(); var gates = new List <Vector2> (); var attempts = 0; while ((gates.Count < minNumberOfGates || attempts < 4) && possibleGates.Any() && gates.Count < maxNumberOfGates) { attempts++; var newGate = possibleGates.First(); try { possibleGates.Remove(newGate); possibleGates.RemoveFirstIfPossible(); possibleGates.RemoveFirstIfPossible(); var outerNeighbours = outsidePatches .Where(p => p.Shape.Vertices.Any(v => v.Equals(newGate))) .ToList(); if (outerNeighbours.Count == 1) { var neighbour = outerNeighbours.Single(); var wallPoint = neighbour.Shape.GetNextVertex(newGate) - neighbour.Shape.GetPreviousVertex(newGate); var outPoint = new Vector2(wallPoint.y, -wallPoint.x); var possibleSplitPoints = neighbour.Shape.Vertices.Except(Circumference).ToList(); var farthest = possibleSplitPoints.OrderByDescending(p => { var dir = p - newGate; return(Vector2.Dot(dir, outPoint) / dir.Length); }).First(); var newPatches = neighbour.Shape.Split(newGate, farthest).Select(p => Patch.FromPolygon(_town, p)).ToList(); if (newPatches.Any(p => p.Shape.Vertices.Count < 3)) { farthest = neighbour.Shape.GetNextVertex(farthest); newPatches = neighbour.Shape.Split(newGate, farthest).Select(p => Patch.FromPolygon(_town, p)).ToList(); if (newPatches.Any(p => p.Shape.Vertices.Count < 3)) { throw new InvalidOperationException( "Splitting patch resulted in polygon with only two points"); } } _town.Patches.Remove(neighbour); _town.Patches.AddRange(newPatches); } gates.Add(newGate); towers.Remove(newGate); } catch (InvalidOperationException) { } } _town.Gates.AddRange(gates); Gates.AddRange(gates); Towers.AddRange(towers); }