예제 #1
0
        private int RiverStartWeightFunction(IHexCell cell)
        {
            int nearbyDesert = Grid.GetCellsInRadius(cell, 1).Count(nearby => nearby.Terrain == CellTerrain.Desert);
            int nearbyArctic = Grid.GetCellsInRadius(cell, 1).Count(nearby => nearby.Terrain.IsArctic());

            return(1 + nearbyDesert * Config.RiverEndpointOnDesertWeight + nearbyArctic * Config.RiverEndpointOnArcticWeight);
        }
        public float GetUtilityForUnit(IUnit unit, InfluenceMaps maps)
        {
            if (!unit.CanAttack)
            {
                return(0f);
            }

            IEnumerable <IHexCell> attackCandidates = null;

            if (unit.RangedAttackStrength > 0)
            {
                var unitLocation = UnitPositionCanon.GetOwnerOfPossession(unit);

                attackCandidates = Grid.GetCellsInRadius(unitLocation, unit.AttackRange)
                                   .Where(FilterLogic.GetRangedAttackFilter(unit));
            }
            else
            {
                attackCandidates = UnitVisibilityLogic.GetCellsVisibleToUnit(unit)
                                   .Where(FilterLogic.GetMeleeAttackFilter(unit));
            }

            if (attackCandidates.Any())
            {
                return(attackCandidates.Max(UtilityLogic.GetAttackUtilityFunction(unit, maps)));
            }
            else
            {
                return(0f);
            }
        }
예제 #3
0
        public float GetUtilityForUnit(IUnit unit, InfluenceMaps maps)
        {
            var unitLocation = UnitPositionCanon.GetOwnerOfPossession(unit);

            return(Grid.GetCellsInRadius(unitLocation, Mathf.RoundToInt(unit.MaxMovement)).Max(
                       UtilityLogic.GetPillageUtilityFunction(unit, maps)
                       ));
        }
예제 #4
0
        private void OnCityPossessionChanged(Tuple <ICivilization, ICity> data)
        {
            var affectedChunks = CellPossessionCanon.GetPossessionsOfOwner(data.Item2)
                                 .SelectMany(cell => Grid.GetCellsInRadius(cell, 1))
                                 .SelectMany(cell => cell.OverlappingChunks)
                                 .Distinct();

            foreach (var chunk in affectedChunks)
            {
                chunk.Refresh(TerrainRefreshType.Culture);
            }
        }
예제 #5
0
 private void EditCells(IHexCell center)
 {
     foreach (var cell in Grid.GetCellsInRadius(center, BrushSize))
     {
         EditCell(cell);
     }
 }
예제 #6
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 UnitSpawnInfo TryGetValidSpawn(
            IEncampment encampment, Func <IHexCell, IEnumerable <IUnitTemplate> > unitSelector
            )
        {
            var encampmentLocation = EncampmentLocationCanon.GetOwnerOfPossession(encampment);

            foreach (var cell in Grid.GetCellsInRadius(encampmentLocation, 1, true))
            {
                var availableUnits = unitSelector(cell);

                if (availableUnits.Any())
                {
                    return(new UnitSpawnInfo()
                    {
                        IsValidSpawn = true, LocationOfUnit = cell,
                        TemplateToBuild = Randomizer.TakeRandom(availableUnits)
                    });
                }
            }

            return(new UnitSpawnInfo()
            {
                IsValidSpawn = false, LocationOfUnit = null, TemplateToBuild = null
            });
        }
예제 #8
0
        public void PerformDamageOnUnitFromImprovements(IUnit unit)
        {
            var unitOwner    = UnitPossessionCanon.GetOwnerOfPossession(unit);
            var unitLocation = UnitPositionCanon.GetOwnerOfPossession(unit);

            float highestDamage = 0f;

            foreach (var nearbyCell in Grid.GetCellsInRadius(unitLocation, 1))
            {
                var ownerOfCell = CivTerritoryLogic.GetCivClaimingCell(nearbyCell);

                if (ownerOfCell == null || !WarCanon.AreAtWar(unitOwner, ownerOfCell))
                {
                    continue;
                }

                foreach (var improvement in ImprovementLocationCanon.GetPossessionsOfOwner(nearbyCell))
                {
                    highestDamage = Mathf.Max(highestDamage, improvement.Template.AdjacentEnemyDamagePercentage);
                }
            }

            if (highestDamage > 0f)
            {
                unit.CurrentHitpoints -= Mathf.RoundToInt(unit.MaxHitpoints * highestDamage);
            }
        }
        public float GetUtilityForUnit(IUnit unit, InfluenceMaps maps)
        {
            var unitPosition = UnitPositionCanon.GetOwnerOfPossession(unit);

            if (EncampmentLocationCanon.GetPossessionsOfOwner(unitPosition).Any())
            {
                return(BarbarianConfig.StayInEncampmentUtility);
            }
            else if (Grid.GetCellsInRadius(unitPosition, BarbarianConfig.DefendEncampmentRadius).Any(HasUndefendedEncampment))
            {
                return(BarbarianConfig.HeadTowardsEncampmentUtility);
            }
            else
            {
                return(0f);
            }
        }
예제 #10
0
        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);
                }
            }
        }
예제 #11
0
        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);
            }
        }
        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 bool HasRangedAttackTarget()
        {
            var cityLocation = CityLocationCanon.GetOwnerOfPossession(ObjectToDisplay);

            foreach (var cell in Grid.GetCellsInRadius(cityLocation, Config.CityAttackRange))
            {
                foreach (var unit in UnitPositionCanon.GetPossessionsOfOwner(cell))
                {
                    if (CombatExecuter.CanPerformRangedAttack(ObjectToDisplay.CombatFacade, unit))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #14
0
        private IEnumerable <IUnit> GetNearbyAllies(IUnit unit, int maxRange)
        {
            var unitLocation = UnitPositionCanon.GetOwnerOfPossession(unit);
            var unitOwner    = UnitPossessionCanon.GetOwnerOfPossession(unit);

            var retval = new List <IUnit>();

            if (unitLocation != null && unitOwner != null)
            {
                var cellsInRange = Grid.GetCellsInRadius(unitLocation, maxRange);

                foreach (var nearbyUnit in cellsInRange.SelectMany(cell => UnitPositionCanon.GetPossessionsOfOwner(cell)))
                {
                    if (UnitPossessionCanon.GetOwnerOfPossession(nearbyUnit) == unitOwner)
                    {
                        retval.Add(nearbyUnit);
                    }
                }
            }

            return(retval);
        }
        public void HandleCommandOnUnit(AbilityCommandRequest command, IUnit unit)
        {
            if (CanHandleCommandOnUnit(command, unit))
            {
                var unitPosition = UnitPositionCanon.GetOwnerOfPossession(unit);
                var unitOwner    = UnitPossessionCanon.GetOwnerOfPossession(unit);

                var nearbyCells = Grid.GetCellsInRadius(unitPosition, 1);

                foreach (var nearbyUnit in nearbyCells.SelectMany(cell => UnitPositionCanon.GetPossessionsOfOwner(cell)))
                {
                    var nearbyOwner = UnitPossessionCanon.GetOwnerOfPossession(nearbyUnit);

                    if (nearbyUnit.Type.IsWaterMilitary() && nearbyOwner == unitOwner)
                    {
                        nearbyUnit.CurrentHitpoints = nearbyUnit.MaxHitpoints;
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Cannot handle command");
            }
        }
예제 #16
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);
        }
예제 #17
0
        public IEnumerable <IHexCell> GetCellsVisibleToUnit(IUnit unit)
        {
            var retval = new List <IHexCell>();

            var unitLocation = UnitPositionCanon.GetOwnerOfPossession(unit);

            foreach (var cell in Grid.GetCellsInRadius(unitLocation, unit.VisionRange))
            {
                if (!HasObstructionsBetween(unitLocation, cell))
                {
                    retval.Add(cell);
                }
            }

            foreach (var cell in Grid.GetCellsInRing(unitLocation, unit.VisionRange + 1))
            {
                if (!HasObstructionsBetween(unitLocation, cell) && cell.Terrain.IsWater())
                {
                    retval.Add(cell);
                }
            }

            return(retval);
        }
예제 #18
0
        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 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);
        }