Пример #1
0
        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);
            }
        }
Пример #3
0
 public RegionData(
     IRegionBiomeTemplate biome, IRegionTopologyTemplate topology,
     IEnumerable <IBalanceStrategy> availableBalanceStrategies
     )
 {
     Biome    = biome;
     Topology = topology;
     AvailableBalanceStrategies = availableBalanceStrategies;
 }
Пример #4
0
        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;
                }
            }
        }
Пример #5
0
        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);
        }
Пример #10
0
        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);
                }
            }
        }