public OceanData GetOceanData( IEnumerable <MapSection> oceanSections, IOceanTemplate oceanTemplate, IMapTemplate mapTemplate, GridPartition partition ) { var shallowOceanSections = oceanSections.Where( section => partition.GetNeighbors(section).Any(neighbor => !oceanSections.Contains(neighbor)) ).ToList(); var midOceanSections = oceanSections.Except(shallowOceanSections).Where( section => partition.GetNeighbors(section).Any(neighbor => shallowOceanSections.Contains(neighbor)) ).ToList(); var deepOceanSections = oceanSections.Except(shallowOceanSections).Except(midOceanSections); List <MapRegion> emptyOceanRegions; List <MapRegion> archipelagoRegions; List <RegionData> archipelagoRegionData; CarveArchipelagoesFromOcean( shallowOceanSections, midOceanSections, deepOceanSections, oceanTemplate, partition, mapTemplate, out emptyOceanRegions, out archipelagoRegions, out archipelagoRegionData ); return(new OceanData(emptyOceanRegions, archipelagoRegions, archipelagoRegionData)); }
private IEnumerable <MapSection> GetContiguousLand( MapSection seed, List <MapSection> landSections, GridPartition partition ) { var uncheckedSections = new List <MapSection>() { seed }; var contiguousSection = new List <MapSection>(); while (uncheckedSections.Any()) { var uncheckedSection = uncheckedSections.Last(); uncheckedSections.Remove(uncheckedSection); contiguousSection.Add(uncheckedSection); foreach (var neighbor in partition.GetNeighbors(uncheckedSection).Intersect(landSections).Except(contiguousSection)) { uncheckedSections.Add(neighbor); } } return(contiguousSection); }
private void GetArchipelagoesFromLandAndWater( List <MapSection> landSections, List <MapSection> deepWaterSections, List <MapSection> midOceanSections, IOceanTemplate template, GridPartition partition, out List <MapRegion> archipelagoRegions, out List <MapSection> emptyDeepOcean ) { archipelagoRegions = new List <MapRegion>(); while (landSections.Any()) { var contiguousLand = GetContiguousLand(landSections.Last(), landSections, partition); foreach (var land in contiguousLand) { landSections.Remove(land); } var coastSections = contiguousLand.SelectMany(section => partition.GetNeighbors(section)) .Where(neighbor => deepWaterSections.Contains(neighbor) || midOceanSections.Contains(neighbor)) .Distinct().ToList(); foreach (var coast in coastSections) { deepWaterSections.Remove(coast); midOceanSections.Remove(coast); } archipelagoRegions.Add(new MapRegion( contiguousLand.SelectMany(section => section.Cells).ToList(), coastSections.SelectMany(section => section.Cells).ToList() )); } emptyDeepOcean = deepWaterSections; }
private void DrawForbiddenLine( HashSet <MapSection> unassignedSections, HashSet <MapSection> forbiddenSections, GridPartition partition, IMapTemplate mapTemplate ) { int lineXCoord = Mathf.RoundToInt(Grid.CellCountX * UnityEngine.Random.Range( mapTemplate.ContinentSeparationLineXMin, mapTemplate.ContinentSeparationLineXMax )); IHexCell startCell = Grid.GetCellAtCoordinates(HexCoordinates.FromOffsetCoordinates(lineXCoord, 0)); IHexCell endCell = Grid.GetCellAtCoordinates(HexCoordinates.FromOffsetCoordinates(lineXCoord, Grid.CellCountZ - 1)); var cellLine = Grid.GetCellsInLine(startCell, endCell); var sectionsOnLine = cellLine.Select(cell => partition.GetSectionOfCell(cell)).Distinct(); var sectionsToForbid = sectionsOnLine.SelectMany(section => partition.GetNeighbors(section)) .Concat(sectionsOnLine).Distinct(); foreach (var section in sectionsToForbid) { unassignedSections.Remove(section); forbiddenSections.Add(section); } }
private ExpansionWeightFunction GetExpansionWeightFunction( GridPartition partition, IMapTemplate template ) { var middleCell = Grid.GetCellAtOffset(Grid.CellCountX / 2, Grid.CellCountZ / 2); return(delegate(MapSection section, List <MapSection> chunk) { if (IsWithinHardBorder(section.CentroidCell, template)) { return 0; } int borderAvoidanceWeight = GetBorderAvoidanceWeight(section.CentroidCell, template); int neighborsInContinent = partition.GetNeighbors(section).Intersect(chunk).Count(); int neighborsInContinentWeight = neighborsInContinent * template.NeighborsInContinentWeight; int distanceFromSeedCentroid = Grid.GetDistance(chunk[0].CentroidCell, section.CentroidCell); int distanceFromSeedCentroidWeight = distanceFromSeedCentroid * template.DistanceFromSeedCentroidWeight; int distanceFromMapCenter = Grid.GetDistance(section.CentroidCell, middleCell) * template.DistanceFromMapCenterWeight; int weight = 1 + Math.Max( 0, neighborsInContinentWeight + distanceFromSeedCentroidWeight + borderAvoidanceWeight + distanceFromMapCenter ); return weight; }); }
private List <MapSection> GetCoastForLandSection( List <MapSection> landSections, HashSet <MapSection> unassignedSections, GridPartition partition ) { var unassignedAdjacentToLand = landSections.SelectMany(section => partition.GetNeighbors(section)) .Intersect(unassignedSections) .Distinct() .ToList(); foreach (var adjacentSection in unassignedAdjacentToLand) { unassignedSections.Remove(adjacentSection); } return(unassignedAdjacentToLand); }
private bool TryExpandChunk( List <MapSection> chunk, HashSet <MapSection> unassignedSections, GridPartition partition, IMapTemplate mapTemplate, ExpansionWeightFunction weightFunction, bool mustBeContiguous ) { expansionCandidates.Clear(); foreach (MapSection section in chunk) { nearbySections.Clear(); sectionsWithinDistance.Clear(); if (mustBeContiguous) { foreach (var adjacentSection in partition.GetNeighbors(section)) { if (unassignedSections.Contains(adjacentSection)) { nearbySections.Add(adjacentSection); } } } else { foreach (IHexCell nearbyCell in Grid.GetCellsInRadius(section.CentroidCell, mapTemplate.HomelandExpansionMaxCentroidSeparation)) { MapSection sectionOfCell = partition.GetSectionOfCell(nearbyCell); if (unassignedSections.Contains(sectionOfCell)) { sectionsWithinDistance.Add(sectionOfCell); } } var sectionsSurroundedByUnassigned = sectionsWithinDistance.Where( nearby => partition.GetNeighbors(nearby).Count(neighbor => !unassignedSections.Contains(neighbor)) <= 0 ); if (sectionsSurroundedByUnassigned.Any()) { foreach (var surroundedSection in sectionsSurroundedByUnassigned) { nearbySections.Add(surroundedSection); } } else { foreach (var sectionWithin in sectionsWithinDistance) { nearbySections.Add(sectionWithin); } } } foreach (var nearby in nearbySections) { expansionCandidates.Add(nearby); } } if (expansionCandidates.Count > 0) { var newSection = MapSectionRandomSampler.SampleElementsFromSet( expansionCandidates, 1, section => weightFunction(section, chunk) ).FirstOrDefault(); if (newSection != null) { unassignedSections.Remove(newSection); chunk.Add(newSection); return(true); } } return(false); }