コード例 #1
0
        public void GenerateTopology(MapRegion region, IRegionTopologyTemplate template)
        {
            var landCells = region.LandCells;

            int desiredMountainCount = Mathf.RoundToInt(template.MountainsPercentage * landCells.Count() * 0.01f);
            int desiredHillsCount    = Mathf.RoundToInt(template.HillsPercentage * landCells.Count() * 0.01f);

            var elevatedCells = CellRandomSampler.SampleElementsFromSet(
                landCells, desiredHillsCount + desiredMountainCount,
                HillsStartingWeightFunction, HillsDynamicWeightFunction, cell => Grid.GetNeighbors(cell)
                );

            foreach (var cell in elevatedCells)
            {
                ModLogic.ChangeShapeOfCell(cell, CellShape.Hills);
            }

            var mountainousCells = CellRandomSampler.SampleElementsFromSet(
                elevatedCells, desiredMountainCount, MountainWeightFunction
                );

            foreach (var cell in mountainousCells)
            {
                ModLogic.ChangeShapeOfCell(cell, CellShape.Mountains);
            }
        }
コード例 #2
0
        private void DistributeLuxuryAcrossSingleRegion(
            MapRegion region, int nodeCount, List <IResourceDefinition> validLuxuries,
            Dictionary <IResourceDefinition, int> weightForResources,
            HashSet <IResourceDefinition> luxuriesAlreadyChosen
            )
        {
            while (validLuxuries.Any())
            {
                var candidate = ResourceRandomSampler.SampleElementsFromSet(
                    validLuxuries, 1, luxury => weightForResources[luxury]
                    ).FirstOrDefault();
                validLuxuries.Remove(candidate);

                if (luxuriesAlreadyChosen.Contains(candidate))
                {
                    continue;
                }

                var validCells = region.Cells.Where(
                    cell => ResourceRestrictionCanon.IsResourceValidOnCell(candidate, cell)
                    );

                if (validCells.Count() >= nodeCount)
                {
                    DistributeResource(candidate, validCells, nodeCount);
                    luxuriesAlreadyChosen.Add(candidate);
                    return;
                }
            }

            Debug.LogWarning("Failed to perform luxury distribution on region");
        }
コード例 #3
0
        private void DistributeResource(
            IResourceDefinition resource, IEnumerable <IHexCell> validLocations,
            int count
            )
        {
            var nodeLocations = CellRandomSampler.SampleElementsFromSet(
                validLocations, count, GetResourceWeightFunction(resource)
                );

            if (nodeLocations.Count < count)
            {
                Debug.LogWarningFormat(
                    "Could not find enough valid locations to place {0} {1} after weighting. Only found {2}",
                    count, resource.name, nodeLocations.Count
                    );
            }

            foreach (var location in nodeLocations)
            {
                int copies = resource.Type == ResourceType.Strategic
                           ? UnityEngine.Random.Range(Config.MinStrategicCopies, Config.MaxStrategicCopies) : 1;

                NodeFactory.BuildNode(location, resource, copies);
            }
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        public void DistributeStrategicsAcrossHomeland(HomelandData homelandData)
        {
            int nodesLeft  = Mathf.CeilToInt(homelandData.YieldAndResources.StrategicNodesPerCell * homelandData.Cells.Count());
            int copiesLeft = Mathf.CeilToInt(homelandData.YieldAndResources.StrategicCopiesPerCell * homelandData.Cells.Count());

            var validStrategics = new List <IResourceDefinition>(StrategicResources);

            var resourceWeightsByRegion = new Dictionary <MapRegion, Dictionary <IResourceDefinition, int> >();

            foreach (var region in homelandData.AllRegions)
            {
                resourceWeightsByRegion[region] = homelandData.GetDataOfRegion(region).GetResourceWeights();
            }

            var regions    = homelandData.AllRegions.ToList();
            int iterations = regions.Count * 10;

            while (nodesLeft > 0 && copiesLeft > 0 && iterations-- > 0)
            {
                if (regions.Count == 0)
                {
                    regions.AddRange(homelandData.AllRegions);
                }

                var region = regions.Random();
                regions.Remove(region);

                var resourceWeights = resourceWeightsByRegion[region];

                var strategic = ResourceRandomSampler.SampleElementsFromSet(
                    validStrategics, 1,
                    resource => resourceWeights.ContainsKey(resource) ? resourceWeights[resource] : 0
                    ).FirstOrDefault();

                if (strategic == null)
                {
                    continue;
                }

                var location = CellRandomSampler.SampleElementsFromSet(
                    region.Cells, 1, cell => ResourceRestrictionCanon.GetPlacementWeightOnCell(strategic, cell)
                    ).FirstOrDefault();

                if (location != null && NodeFactory.CanBuildNode(location, strategic))
                {
                    int copies = StrategicCopiesLogic.GetWeightedRandomCopies();

                    copies = Math.Min(copies, copiesLeft);

                    NodeFactory.BuildNode(location, strategic, copies);

                    nodesLeft--;
                    copiesLeft -= copies;
                }
            }
        }
コード例 #6
0
        public bool TryIncreaseYield(
            MapRegion region, RegionData regionData, YieldType type, out YieldSummary yieldAdded
            )
        {
            var availableResources = BonusResourcesWithYield[type].ToList();

            while (availableResources.Count > 0)
            {
                var chosenResource = ResourceRandomSampler.SampleElementsFromSet(
                    availableResources, 1, GetResourceSelectionWeightFunction(region, regionData)
                    ).FirstOrDefault();

                if (chosenResource == null)
                {
                    break;
                }

                var cell = CellRandomSampler.SampleElementsFromSet(
                    region.Cells, 1, GetCellPlacementWeightFunction(chosenResource)
                    ).FirstOrDefault();

                if (cell != null)
                {
                    var oldYield = YieldEstimator.GetYieldEstimateForCell(cell, TechCanon.AvailableTechs);

                    int copies = chosenResource.Type == ResourceType.Strategic
                               ? StrategicCopiesLogic.GetWeightedRandomCopies()
                               : 0;

                    ResourceNodeFactory.BuildNode(cell, chosenResource, copies);

                    yieldAdded = YieldEstimator.GetYieldEstimateForCell(cell, TechCanon.AvailableTechs) - oldYield;
                    return(true);
                }
                else
                {
                    availableResources.Remove(chosenResource);
                }
            }

            yieldAdded = YieldSummary.Empty;
            return(false);
        }
コード例 #7
0
        public void CreateRivers(
            IEnumerable <IHexCell> landCells, IEnumerable <IHexCell> waterCells,
            int desiredRiveredCells
            )
        {
            var riveredCells = new HashSet <IHexCell>();

            var riverStartCandidates = landCells.Where(GetRiverStartFilter(waterCells)).ToList();

            HashSet <IHexCell> cellsAdjacentToNewRiver = new HashSet <IHexCell>();

            int iterations = landCells.Count() * 10;

            while (riveredCells.Count < desiredRiveredCells && riverStartCandidates.Count > 0 && iterations-- > 0)
            {
                var start = CellRandomSampler.SampleElementsFromSet(
                    riverStartCandidates, 1, RiverStartWeightFunction
                    ).FirstOrDefault();

                riverStartCandidates.Remove(start);

                if (TryBuildNewRiver(
                        landCells, waterCells, start, desiredRiveredCells - riveredCells.Count,
                        ref cellsAdjacentToNewRiver
                        ))
                {
                    foreach (var cell in cellsAdjacentToNewRiver)
                    {
                        riveredCells.Add(cell);
                        riverStartCandidates.Remove(cell);

                        foreach (var startingNeighbor in Grid.GetNeighbors(start))
                        {
                            riverStartCandidates.Remove(startingNeighbor);
                        }
                    }
                }
            }
        }
コード例 #8
0
        public void TrySpawnEncampment(InfluenceMaps maps)
        {
            var validCells = Grid.Cells.Where(SpawningTools.EncampmentValidityFilter).ToList();

            if (validCells.Any())
            {
                var candidate = CellSampler.SampleElementsFromSet(
                    validCells, 1, SpawningTools.BuildEncampmentWeightFunction(maps)
                    ).FirstOrDefault();

                if (candidate != null)
                {
                    var newEncampment = EncampmentFactory.CreateEncampment(candidate);

                    UnitSpawner.TrySpawnUnit(newEncampment);
                }
            }
        }
コード例 #9
0
        private void CarveArchipelagoesFromOcean(
            IEnumerable <MapSection> shallowOceanSections, List <MapSection> midOceanSections,
            IEnumerable <MapSection> deepOceanSections, IOceanTemplate oceanTemplate, GridPartition partition,
            IMapTemplate mapTemplate, out List <MapRegion> emptyOceanRegions,
            out List <MapRegion> archipelagoRegions, out List <RegionData> archipelagoRegionData
            )
        {
            int landSectionCount = Mathf.RoundToInt(oceanTemplate.DeepOceanLandPercentage * 0.01f * deepOceanSections.Count());

            var deepOceanLand = MapSectionRandomSampler.SampleElementsFromSet(
                deepOceanSections, landSectionCount, GetArchipelagoWeightFunction(mapTemplate)
                ).ToList();

            var deepOceanWater = deepOceanSections.Except(deepOceanLand).ToList();

            List <MapSection> emptyDeepOcean;

            GetArchipelagoesFromLandAndWater(
                deepOceanLand, deepOceanWater, midOceanSections, oceanTemplate,
                partition, out archipelagoRegions, out emptyDeepOcean
                );

            var emptyOceanCells = shallowOceanSections.Concat(midOceanSections).Concat(emptyDeepOcean);

            var emptyOcean = new MapRegion(
                new List <IHexCell>(),
                emptyOceanCells.SelectMany(section => section.Cells).ToList()
                );

            emptyOceanRegions = new List <MapRegion>()
            {
                emptyOcean
            };

            archipelagoRegionData = archipelagoRegions.Select(region => new RegionData(
                                                                  TemplateSelectionLogic.GetBiomeForLandRegion(region, mapTemplate),
                                                                  TemplateSelectionLogic.GetTopologyForLandRegion(region, mapTemplate),
                                                                  AvailableBalanceStrategies
                                                                  )).ToList();
        }
コード例 #10
0
        public bool TryIncreaseYield(
            MapRegion region, RegionData regionData, YieldType type, out YieldSummary yieldAdded
            )
        {
            yieldAdded = YieldSummary.Empty;
            if (type != YieldType.Food && type != YieldType.Gold)
            {
                return(false);
            }

            var newOasis = CellRandomSampler.SampleElementsFromSet(
                region.LandCells, 1, GetOasisCandidateWeightFunction(region)
                ).FirstOrDefault();

            if (newOasis == null)
            {
                return(false);
            }

            var oldYields = new Dictionary <IHexCell, YieldSummary>();

            foreach (var cell in Grid.GetCellsInRadius(newOasis, 1))
            {
                oldYields[cell] = YieldEstimator.GetYieldEstimateForCell(cell, TechCanon.AvailableTechs);
            }

            ModLogic.ChangeFeatureOfCell(newOasis, CellFeature.Oasis);

            yieldAdded = YieldSummary.Empty;
            foreach (var cell in oldYields.Keys)
            {
                yieldAdded += YieldEstimator.GetYieldEstimateForCell(cell, TechCanon.AvailableTechs) - oldYields[cell];
            }

            return(true);
        }
コード例 #11
0
        public List <IUnitCommand> GetCommandsForUnit(IUnit unit, InfluenceMaps maps)
        {
            var retval = new List <IUnitCommand>();

            var unitLocation = UnitPositionCanon.GetOwnerOfPossession(unit);

            var nearbyCells = Grid.GetCellsInRadius(unitLocation, Mathf.RoundToInt(unit.MaxMovement));

            var bestCandidate = CellRandomSampler.SampleElementsFromSet(
                nearbyCells, 1, BrainTools.GetWanderWeightFunction(unit, maps)
                ).FirstOrDefault();

            if (bestCandidate != null)
            {
                var moveCommand = Container.Instantiate <MoveUnitCommand>();

                moveCommand.UnitToMove      = unit;
                moveCommand.DesiredLocation = bestCandidate;

                retval.Add(moveCommand);
            }

            return(retval);
        }
コード例 #12
0
        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);
        }
コード例 #13
0
 private IBalanceStrategy GetStrategy(Dictionary <IBalanceStrategy, int> strategyWeights)
 {
     return(BalanceStrategySampler.SampleElementsFromSet(
                strategyWeights.Keys, 1, strategy => strategyWeights[strategy]
                ).FirstOrDefault());
 }