private void AssignLandOrphans( MapRegion region, IRegionBiomeTemplate template, HashSet <IHexCell> unassignedLandCells ) { foreach (var orphan in unassignedLandCells.ToArray()) { var adjacentLandTerrains = Grid.GetCellsInRadius(orphan, 3) .Except(unassignedLandCells) .Intersect(region.LandCells) .Select(neighbor => neighbor.Terrain) .Where(terrain => !terrain.IsWater() && ModLogic.CanChangeTerrainOfCell(orphan, terrain)); if (adjacentLandTerrains.Any()) { var newTerrain = adjacentLandTerrains.Random(); ModLogic.ChangeTerrainOfCell(orphan, newTerrain); unassignedLandCells.Remove(orphan); } else { Debug.LogWarning("Could not find a valid terrain for an orphaned cell"); } } }
public void PaintVegetation(MapRegion region, IRegionBiomeTemplate template) { var treeType = template.AreTreesJungle ? CellVegetation.Jungle : CellVegetation.Forest; var openCells = new List <IHexCell>(); foreach (var cell in region.LandCells) { if (ShouldBeMarsh(cell, template)) { ModLogic.ChangeVegetationOfCell(cell, CellVegetation.Marsh); } else if (ModLogic.CanChangeVegetationOfCell(cell, treeType)) { openCells.Add(cell); } } int treeCount = Mathf.RoundToInt(template.TreePercentage * openCells.Count * 0.01f); var treeSeeds = CellRandomSampler.SampleElementsFromSet( openCells, UnityEngine.Random.Range(template.MinTreeClumps, template.MaxTreeClumps), GetTreeSeedWeightFunction(treeType, template) ); var treeCells = new List <IHexCell>(); var treeCrawlers = treeSeeds.Select( seed => GridTraversalLogic.GetCrawlingEnumerator( seed, openCells, treeCells, GetTreeCrawlingCostFunction(treeType, template) ) ).ToList(); for (int i = 0; i < treeCount; i++) { if (treeCrawlers.Count == 0) { Debug.LogWarning("Failed to paint correct number of trees into region"); break; } var crawler = treeCrawlers.Random(); if (crawler.MoveNext()) { treeCells.Add(crawler.Current); openCells.Remove(crawler.Current); } else { treeCrawlers.Remove(crawler); i--; } } foreach (var treeCell in treeCells) { ModLogic.ChangeVegetationOfCell(treeCell, treeType); } }
public RegionData( IRegionBiomeTemplate biome, IRegionTopologyTemplate topology, IEnumerable <IBalanceStrategy> availableBalanceStrategies ) { Biome = biome; Topology = topology; AvailableBalanceStrategies = availableBalanceStrategies; }
private void PaintArcticTerrain( MapRegion region, IRegionBiomeTemplate template, HashSet <IHexCell> unassignedLandCells ) { var unassignedByPolarDistance = new List <IHexCell>(unassignedLandCells); unassignedByPolarDistance.Sort(PolarDistanceComparer); int snowCellCount = Mathf.RoundToInt(template.SnowPercentage * region.LandCells.Count * 0.01f); int tundraCellCount = Mathf.RoundToInt(template.TundraPercentage * region.LandCells.Count * 0.01f); for (int i = 0; i < snowCellCount; i++) { if (unassignedByPolarDistance.Any()) { var candidate = unassignedByPolarDistance.Last(); if (ModLogic.CanChangeTerrainOfCell(candidate, CellTerrain.Snow)) { ModLogic.ChangeTerrainOfCell(candidate, CellTerrain.Snow); unassignedLandCells.Remove(candidate); } unassignedLandCells.Remove(candidate); unassignedByPolarDistance.RemoveAt(unassignedByPolarDistance.Count - 1); } else { break; } } for (int i = 0; i < tundraCellCount; i++) { if (unassignedByPolarDistance.Any()) { var candidate = unassignedByPolarDistance.Last(); if (ModLogic.CanChangeTerrainOfCell(candidate, CellTerrain.Tundra)) { ModLogic.ChangeTerrainOfCell(candidate, CellTerrain.Tundra); unassignedLandCells.Remove(candidate); } unassignedByPolarDistance.RemoveAt(unassignedByPolarDistance.Count - 1); } else { break; } } }
public void PaintTerrain(MapRegion region, IRegionBiomeTemplate template) { var unassignedLandCells = new HashSet <IHexCell>(region.LandCells); PaintArcticTerrain(region, template, unassignedLandCells); PaintOtherTerrains(region, template, unassignedLandCells); AssignLandOrphans(region, template, unassignedLandCells); foreach (var cell in region.WaterCells) { ModLogic.ChangeTerrainOfCell(cell, CellTerrain.ShallowWater); } }
private float GetBiomePriority(IRegionBiomeTemplate biome, float temperature, float precipitation) { float distanceFromTemperatureAverage = Math.Abs(temperature - (biome.MinTemperature + biome.MaxTemperature) / 2f); float distanceFromPrecipitationAverage = Math.Abs(precipitation - (biome.MinPrecipitation + biome.MaxPrecipitation) / 2f); if (temperature < biome.MinTemperature || temperature > biome.MaxTemperature) { distanceFromTemperatureAverage *= 2; } if (precipitation < biome.MinPrecipitation || precipitation > biome.MaxPrecipitation) { distanceFromPrecipitationAverage *= 2; } return(distanceFromTemperatureAverage + distanceFromPrecipitationAverage); }
private Func <IHexCell, int> GetTreeSeedWeightFunction( CellVegetation treeType, IRegionBiomeTemplate template ) { return(delegate(IHexCell cell) { if (cell.Vegetation == CellVegetation.Marsh || cell.Feature != CellFeature.None || !ModLogic.CanChangeVegetationOfCell(cell, treeType) ) { return 0; } else { int terrainCost = template.GetTreePlacementCostForTerrain(cell.Terrain); int shapeCost = template.GetTreePlacementCostForShape(cell.Shape); return 1000 - 200 * (terrainCost + shapeCost); } }); }
private CrawlingWeightFunction GetTreeCrawlingCostFunction( CellVegetation treeType, IRegionBiomeTemplate template ) { return(delegate(IHexCell cell, IHexCell seed, IEnumerable <IHexCell> acceptedCells) { if (cell.Vegetation == CellVegetation.Marsh || cell.Feature != CellFeature.None || !ModLogic.CanChangeVegetationOfCell(cell, treeType) ) { return -1; } else { int terrainCost = template.GetTreePlacementCostForTerrain(cell.Terrain); int shapeCost = template.GetTreePlacementCostForShape(cell.Shape); int distanceCost = Grid.GetDistance(seed, cell); return terrainCost + shapeCost + distanceCost; } }); }
private bool ShouldBeMarsh(IHexCell cell, IRegionBiomeTemplate template) { if (cell.Terrain != CellTerrain.Grassland || cell.Shape != CellShape.Flatlands) { return(false); } int adjacentWater = Grid.GetNeighbors(cell).Where( neighbor => neighbor.Terrain.IsWater() ).Count(); int adjacentRivers = EnumUtil.GetValues <HexDirection>().Where( direction => RiverCanon.HasRiverAlongEdge(cell, direction) ).Count(); float chanceOfMarsh = template.MarshChanceBase + adjacentWater * template.MarshChancePerAdjacentWater + adjacentRivers * template.MarshChancePerAdjacentRiver; return(UnityEngine.Random.value < chanceOfMarsh); }
private void PaintOtherTerrains( MapRegion region, IRegionBiomeTemplate template, HashSet <IHexCell> unassignedLandCells ) { var terrainsToPaint = new List <CellTerrain>() { CellTerrain.Grassland, CellTerrain.Plains, CellTerrain.Desert }; var percentageOfTerrains = new Dictionary <CellTerrain, int>() { { CellTerrain.Grassland, template.GrasslandPercentage }, { CellTerrain.Plains, template.PlainsPercentage }, { CellTerrain.Desert, template.DesertPercentage }, }; int landToPaintCount = unassignedLandCells.Count; foreach (var terrain in terrainsToPaint) { var weightFunction = GetWeightFunction(terrain); int terrainCount = Mathf.RoundToInt(percentageOfTerrains[terrain] * 0.01f * landToPaintCount); terrainCount = Math.Min(terrainCount, unassignedLandCells.Count); var changeCandidatesDescending = new List <IHexCell>(unassignedLandCells); changeCandidatesDescending.Sort((first, second) => weightFunction(second).CompareTo(weightFunction(first))); for (int i = 0; i < terrainCount; i++) { var cellToChange = changeCandidatesDescending[i]; ModLogic.ChangeTerrainOfCell(cellToChange, terrain); unassignedLandCells.Remove(cellToChange); } } }