protected override bool AllowResourceAt(string resourceType, CPos cell)
        {
            if (!Map.Contains(cell))
            {
                return(false);
            }

            // Resources are allowed on flat terrain and cardinal slopes
            if (Map.Ramp[cell] > 4)
            {
                return(false);
            }

            if (!info.ResourceTypes.TryGetValue(resourceType, out var resourceInfo))
            {
                return(false);
            }

            if (!resourceInfo.AllowedTerrainTypes.Contains(Map.GetTerrainInfo(cell).Type))
            {
                return(false);
            }

            // Ensure there is space for the vein border tiles (not needed on ramps)
            var check = resourceType == info.VeinType ? (Func <CPos, CPos, bool>)IsValidVeinNeighbour : IsValidResourceNeighbour;
            var blockedByNeighbours = Map.Ramp[cell] == 0 && !Common.Util.ExpandFootprint(cell, false).All(c => check(cell, c));

            return(!blockedByNeighbours && (resourceType == info.VeinType || !BuildingInfluence.AnyBuildingAt(cell)));
        }
Example #2
0
        CPos?ChooseBuildLocation(string actorType, bool distanceToBaseIsImportant, BuildingType type)
        {
            var actorInfo    = world.Map.Rules.Actors[actorType];
            var buildingInfo = actorInfo.TraitInfoOrDefault <BuildingInfo>();

            if (buildingInfo == null)
            {
                return(null);
            }

            // Find the buildable cell that is closest to pos and centered around center
            Func <CPos, CPos, int, int, CPos?> findPos = (center, target, minRange, maxRange) =>
            {
                var cells = world.Map.FindTilesInAnnulus(center, minRange, maxRange);

                // Sort by distance to target if we have one
                if (center != target)
                {
                    cells = cells.OrderBy(c => (c - target).LengthSquared);
                }
                else
                {
                    cells = cells.Shuffle(world.LocalRandom);
                }

                foreach (var cell in cells)
                {
                    if (!world.CanPlaceBuilding(cell, actorInfo, buildingInfo, null))
                    {
                        continue;
                    }

                    foreach (var adjacent in CVec.Directions)
                    {
                        var adjacentCell = cell + adjacent;

                        // Don't clutter the base
                        if (buildingInfluence.AnyBuildingAt(adjacentCell))
                        {
                            continue;
                        }

                        // Don't block of resources
                        if (resourceLayer.GetResource(adjacentCell).Density > 0)
                        {
                            continue;
                        }
                    }

                    if (distanceToBaseIsImportant && !buildingInfo.IsCloseEnoughToBase(world, player, actorInfo, cell))
                    {
                        continue;
                    }

                    return(cell);
                }

                return(null);
            };

            var baseCenter = baseBuilder.GetRandomBaseCenter();

            switch (type)
            {
            case BuildingType.Defense:

                // Build near the closest enemy structure
                var closestEnemy = world.ActorsHavingTrait <Building>().Where(a => !a.Disposed && player.RelationshipWith(a.Owner) == PlayerRelationship.Enemy)
                                   .ClosestTo(world.Map.CenterOfCell(baseBuilder.DefenseCenter));

                var targetCell = closestEnemy != null ? closestEnemy.Location : baseCenter;
                return(findPos(baseBuilder.DefenseCenter, targetCell, baseBuilder.Info.MinimumDefenseRadius, baseBuilder.Info.MaximumDefenseRadius));

            case BuildingType.Refinery:
            case BuildingType.Building:
                return(findPos(baseCenter, baseCenter, baseBuilder.Info.MinBaseRadius,
                               distanceToBaseIsImportant ? baseBuilder.Info.MaxBaseRadius : world.Map.Grid.MaximumTileSearchRange));
            }

            // Can't find a build location
            return(null);
        }