public RegionData GetRegionData(MapRegion archipelagoRegion) { int regionIndex = ArchipelagoRegions.IndexOf(archipelagoRegion); if (regionIndex < 0) { throw new InvalidOperationException("The given region is not an archipelago region in this ocean"); } return(ArchipelagoRegionData[regionIndex]); }
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); } }
public bool TryIncreaseScore(MapRegion region, RegionData regionData, out float scoreAdded) { YieldSummary yieldAdded; if (TryIncreaseYield(region, regionData, YieldType.Food, out yieldAdded)) { scoreAdded = MapScorer.GetScoreOfYield(yieldAdded); return(true); } else { scoreAdded = 0f; return(false); } }
private Func <IResourceDefinition, int> GetResourceSelectionWeightFunction( MapRegion region, RegionData regionData ) { return(delegate(IResourceDefinition resource) { if (region.Cells.Any(cell => ResourceRestrictionCanon.IsResourceValidOnCell(resource, cell))) { return regionData.GetWeightOfResource(resource); } else { return 0; } }); }
public HomelandData( MapRegion startingRegion, RegionData startingData, List <MapRegion> otherRegions, List <RegionData> otherRegionData, IEnumerable <LuxuryResourceData> luxuryResources, IYieldAndResourcesTemplate yieldData ) { StartingRegion = startingRegion; StartingData = startingData; _otherRegions = otherRegions; _otherRegionData = otherRegionData; LuxuryResources = luxuryResources; YieldAndResources = yieldData; }
private Func <IHexCell, int> GetOasisCandidateWeightFunction(MapRegion region) { return(delegate(IHexCell cell) { if (OasisCandidateFilter(cell, region)) { int nearbyOases = Grid.GetCellsInRadius(cell, 2).Where(nearby => nearby.Feature == CellFeature.Oasis).Count(); int nearbyNonDesert = Grid.GetCellsInRadius(cell, 2).Where(nearby => nearby.Terrain != CellTerrain.Desert).Count(); return Math.Max(1, 1000 - nearbyOases * NearbyOasisAvoidance - nearbyNonDesert * NearbyNonDesertAvoidance); } else { return 0; } }); }
private bool OasisCandidateFilter(IHexCell cell, MapRegion region) { if (cell.Terrain == CellTerrain.Desert && ModLogic.CanChangeFeatureOfCell(cell, CellFeature.Oasis)) { bool surroundedByLand = Grid.GetNeighbors(cell).All( neighbor => !neighbor.Terrain.IsWater() ); bool hasResourceNode = NodePositionCanon.GetPossessionsOfOwner(cell).Any(); return(surroundedByLand && !hasResourceNode); } else { return(false); } }
public IRegionBiomeTemplate GetBiomeForLandRegion(MapRegion landRegion, IMapTemplate mapTemplate) { float regionTemperature = GetRegionTemperature(landRegion); float regionPrecipitation = GetRegionPrecipitation(landRegion); var templatesByPriority = new List <IRegionBiomeTemplate>(mapTemplate.RegionBiomes); var templatePriority = new Dictionary <IRegionBiomeTemplate, float>(); foreach (var regionTemplate in templatesByPriority) { templatePriority[regionTemplate] = GetBiomePriority(regionTemplate, regionTemperature, regionPrecipitation); } templatesByPriority.Sort((a, b) => templatePriority[a].CompareTo(templatePriority[b])); return(templatesByPriority.First()); }
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); }
public bool TryIncreaseScore( MapRegion region, RegionData regionData, out float scoreAdded ) { var candidateResources = new List <IResourceDefinition>(ScoreIncreasingCandidates); while (candidateResources.Any()) { var chosenResource = ResourceRandomSampler.SampleElementsFromSet( candidateResources, 1, GetResourceSelectionWeightFunction(region, regionData) ).FirstOrDefault(); if (chosenResource == null) { break; } var cell = CellRandomSampler.SampleElementsFromSet( region.Cells, 1, GetCellPlacementWeightFunction(chosenResource) ).FirstOrDefault(); if (cell != null) { float oldScore = CellScorer.GetScoreOfCell(cell); int copies = chosenResource.Type == ResourceType.Strategic ? StrategicCopiesLogic.GetWeightedRandomCopies() : 0; ResourceNodeFactory.BuildNode(cell, chosenResource, copies); scoreAdded = CellScorer.GetScoreOfCell(cell) - oldScore; return(true); } else { candidateResources.Remove(chosenResource); } } scoreAdded = 0f; return(false); }
public RegionData GetDataOfRegion(MapRegion region) { if (region == StartingRegion) { return(StartingData); } else { int index = OtherRegions.IndexOf(region); if (index >= 0) { return(OtherRegionData[index]); } else { throw new InvalidOperationException("No data exists for the argued region"); } } }
public bool TryDecreaseScore(MapRegion region, RegionData regionData, out float scoreRemoved) { var removeJungleCandidates = region.Cells.Where(DecreaseScoreFilter); if (removeJungleCandidates.Any()) { var oldJungle = removeJungleCandidates.Random(); var oldScore = CellScorer.GetScoreOfCell(oldJungle); ModLogic.ChangeVegetationOfCell(oldJungle, CellVegetation.None); scoreRemoved = oldScore - CellScorer.GetScoreOfCell(oldJungle); return(true); } else { scoreRemoved = 0f; return(false); } }
public bool TryIncreaseScore(MapRegion region, RegionData regionData, out float scoreAdded) { var addJungleCandidates = region.Cells.Where(IncreaseScoreFilter); if (addJungleCandidates.Any()) { var newJungle = addJungleCandidates.Random(); var oldScore = CellScorer.GetScoreOfCell(newJungle); ModLogic.ChangeVegetationOfCell(newJungle, CellVegetation.Jungle); scoreAdded = CellScorer.GetScoreOfCell(newJungle) - oldScore; return(true); } else { scoreAdded = 0f; return(false); } }
public void PlaceStartingUnitsInRegion( MapRegion region, ICivilization owner, IMapTemplate mapTemplate ) { if (owner.Template.IsBarbaric) { return; } var centralLocation = GetBestStartingCell(region); if (centralLocation == null) { throw new InvalidOperationException("Failed to find an appropriate central location"); } UnitFactory.BuildUnit(centralLocation, mapTemplate.StartingUnits[0], owner); for (int i = 1; i < mapTemplate.StartingUnits.Count; i++) { var unitTemplate = mapTemplate.StartingUnits[i]; var location = Grid.GetCellsInRadius(centralLocation, 2).Where( cell => !UnitPositionCanon.GetPossessionsOfOwner(cell).Any() && UnitFactory.CanBuildUnit(cell, unitTemplate, owner) && cell != null ).FirstOrDefault(); if (location == null) { throw new InvalidOperationException( string.Format("Failed to place starting unit {0} for civ {1}", unitTemplate, owner) ); } else { UnitFactory.BuildUnit(location, unitTemplate, owner); } } }
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(); }
public bool TryIncreaseYield( MapRegion region, RegionData regionData, YieldType type, out YieldSummary yieldAdded ) { if (type != YieldType.Food) { yieldAdded = YieldSummary.Empty; return(false); } var candidates = region.Cells.Where(GetLakeCandidateFilter(region)); if (candidates.Any()) { var newLake = candidates.Random(); var oldYields = new Dictionary <IHexCell, YieldSummary>(); foreach (var cell in Grid.GetCellsInRadius(newLake, 1)) { oldYields[cell] = YieldEstimator.GetYieldEstimateForCell(cell, TechCanon.AvailableTechs); } ModLogic.ChangeTerrainOfCell(newLake, CellTerrain.FreshWater); yieldAdded = YieldSummary.Empty; foreach (var cell in oldYields.Keys) { yieldAdded += YieldEstimator.GetYieldEstimateForCell(cell, TechCanon.AvailableTechs) - oldYields[cell]; } return(true); } else { yieldAdded = YieldSummary.Empty; return(false); } }
private bool TryDistributeLuxuryAcrossSingleAndMultipleRegions( MapRegion singleRegion, IEnumerable <MapRegion> multipleRegions, int singleNodeCount, int multipleNodeCount, 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 validSingleCells = singleRegion.Cells.Where( cell => ResourceRestrictionCanon.IsResourceValidOnCell(candidate, cell) ); var validMultipleCells = multipleRegions.SelectMany(region => region.Cells).Where( cell => ResourceRestrictionCanon.IsResourceValidOnCell(candidate, cell) ); if (validSingleCells.Count() >= singleNodeCount && validMultipleCells.Count() >= multipleNodeCount) { DistributeResource(candidate, validSingleCells, singleNodeCount); DistributeResource(candidate, validMultipleCells, multipleNodeCount); luxuriesAlreadyChosen.Add(candidate); return(true); } } return(false); }
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); } } }
public bool TryDecreaseScore(MapRegion region, RegionData regionData, out float scoreRemoved) { var allCandidates = region.LandCells.Where(CandidateFilter).ToList(); allCandidates.Sort(CandidateComparer); var bestCandidate = allCandidates.FirstOrDefault(); if (bestCandidate != null) { var oldScore = CellScorer.GetScoreOfCell(bestCandidate); ModLogic.ChangeShapeOfCell(bestCandidate, CellShape.Mountains); scoreRemoved = oldScore - CellScorer.GetScoreOfCell(bestCandidate); return(true); } else { scoreRemoved = 0f; return(false); } }
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); }
private Comparison <IHexCell> GetScoreComparisonFunction(MapRegion region) { var cellScores = new Dictionary <IHexCell, float>(); var cellsInRange = new Dictionary <IHexCell, IHexCell[]>(); foreach (var cell in region.Cells) { cellScores[cell] = CellScorer.GetScoreOfCell(cell); cellsInRange[cell] = Grid.GetCellsInRadius(cell, CityConfig.MaxBorderRange) .Where(nearby => region.Cells.Contains(nearby)) .ToArray(); } var cityPlacementScore = new Dictionary <IHexCell, float>(); return(delegate(IHexCell cellOne, IHexCell cellTwo) { float cellOneScore, cellTwoScore; if (!cityPlacementScore.TryGetValue(cellOne, out cellOneScore)) { cellOneScore = cellsInRange[cellOne].Select(neighbor => cellScores[neighbor]).Sum(); cityPlacementScore[cellOne] = cellOneScore; } if (!cityPlacementScore.TryGetValue(cellTwo, out cellTwoScore)) { cellTwoScore = cellsInRange[cellTwo].Select(neighbor => cellScores[neighbor]).Sum(); cityPlacementScore[cellTwo] = cellTwoScore; } return cellTwoScore.CompareTo(cellOneScore); }); }
public bool TryIncreaseScore(MapRegion region, RegionData regionData, out float scoreAdded) { scoreAdded = 0f; return(false); }
public bool TryIncreaseYield(MapRegion region, RegionData regionData, YieldType type, out YieldSummary yieldAdded) { yieldAdded = YieldSummary.Empty; return(false); }
private float GetRegionTemperature(MapRegion region) { return(region.LandCells.Sum(cell => CellClimateLogic.GetTemperatureOfCell(cell)) / region.LandCells.Count); }
private float GetRegionPrecipitation(MapRegion region) { return(region.LandCells.Sum(cell => CellClimateLogic.GetPrecipitationOfCell(cell)) / region.LandCells.Count); }
public bool TryDecreaseScore(MapRegion region, RegionData regionData, out float scoreRemoved) { scoreRemoved = 0; return(false); }
public HomelandData GetHomelandData( ICivilization civ, List <MapSection> landSections, List <MapSection> waterSections, GridPartition partition, IHomelandTemplate homelandTemplate, IMapTemplate mapTemplate ) { var landChunks = new List <List <MapSection> >(); var waterChunks = new List <List <MapSection> >(); IHexCell seedCentroid = landSections[0].CentroidCell; var startingLandSections = Grid.GetCellsInRadius(seedCentroid, homelandTemplate.StartingRegionRadius) .Select(cell => partition.GetSectionOfCell(cell)) .Distinct() .Intersect(landSections); var startingWaterSections = Grid.GetCellsInRadius(seedCentroid, homelandTemplate.StartingRegionRadius) .Select(cell => partition.GetSectionOfCell(cell)) .Distinct() .Intersect(waterSections); var startingRegion = new MapRegion( startingLandSections.SelectMany(section => section.Cells).ToList(), startingWaterSections.SelectMany(section => section.Cells).ToList() ); foreach (var cell in startingRegion.Cells) { cell.SetMapData(1f); } var unassignedLand = landSections.Except(startingLandSections); var unassignedWater = waterSections.Except(startingWaterSections); DivideSectionsIntoRectangularChunks( unassignedLand, unassignedWater, homelandTemplate.RegionCount, out landChunks, out waterChunks ); var regions = new List <MapRegion>(); regions.Add(startingRegion); for (int i = 0; i < landChunks.Count; i++) { var region = new MapRegion( landChunks [i].SelectMany(section => section.Cells).ToList(), waterChunks[i].SelectMany(section => section.Cells).ToList() ); regions.Add(region); } var startingData = new RegionData( TemplateSelectionLogic.GetBiomeForLandRegion(startingRegion, mapTemplate), TemplateSelectionLogic.GetTopologyForLandRegion(startingRegion, mapTemplate), AvailableBalanceStrategies ); var otherRegions = regions.Where(region => region != startingRegion).ToList(); var otherData = otherRegions.Select(region => new RegionData( TemplateSelectionLogic.GetBiomeForLandRegion(region, mapTemplate), TemplateSelectionLogic.GetTopologyForLandRegion(region, mapTemplate), AvailableBalanceStrategies )).ToList(); return(new HomelandData( startingRegion, startingData, otherRegions, otherData, homelandTemplate.LuxuryResourceData, homelandTemplate.YieldAndResources )); }
private float GetScorePerCell(MapRegion region) { var cellsByScore = region.Cells.Select(cell => CellScorer.GetScoreOfCell(cell)); return(cellsByScore.Aggregate((current, next) => current + next) / region.Cells.Count); }
public IRegionTopologyTemplate GetTopologyForLandRegion(MapRegion region, IMapTemplate mapTemplate) { return(mapTemplate.RegionTopologies.Random()); }