コード例 #1
0
ファイル: CarnCellFinder.cs プロジェクト: Pyr3z/Carnivale
        public static IntVec3 PreCalculateBannerCell()
        {
            if (!Info.Active)
            {
                Log.Error("[Carnivale] Tried to perform a cell calculation while current carnival is inactive.");
                return(IntVec3.Invalid);
            }

            var map         = Info.map;
            var setupCentre = Info.setupCentre;
            var baseRadius  = Info.baseRadius;

            var minDistToCentre = baseRadius / 2;
            var maxDistToCentre = baseRadius + 3f;

            var minDistSqrdToCentre = (int)(minDistToCentre * minDistToCentre * 2);
            var maxDistSqrdToCentre = (int)(maxDistToCentre * maxDistToCentre * 2);

            IntVec3 colonistPos;

            if (!(colonistPos = CellsUtil.ApproxClosestColonistBuilding(map, setupCentre, ThingDefOf.Door)).IsValid)
            {
                colonistPos = CellsUtil.AverageColonistPosition(map);
            }
            else
            {
                colonistPos = colonistPos.AverageWith(CellsUtil.AverageColonistPosition(map));
            }

            // Initial pass
            var closestCell = CellRect.CenteredOn(setupCentre, (int)maxDistToCentre).EdgeCells.ClosestCellTo(colonistPos, map);

            if (Prefs.DevMode)
            {
                Log.Message("[Carnivale] bannerCell initial pass: "******"Road"))
                    {
                        adjustedCell += IntVec3.East * 2;
                    }
                    else if ((adjustedCell + IntVec3.West * 2).GetTerrain(map).HasTag("Road"))
                    {
                        adjustedCell += IntVec3.West * 2;
                    }
                    else
                    {
                        adjustedCell += IntVec3.North;
                    }

                    closestCell = adjustedCell;

                    if (Prefs.DevMode)
                    {
                        Log.Message("\t[Carnivale] bannerCell road pass: "******". distSqrdToCentre=" + dist + ", minDistSqrdToCentre=" + minDistSqrdToCentre + ", maxDistSqrdToCentre=" + maxDistSqrdToCentre);
                    }

                    break;
                }
                else
                {
                    if (Prefs.DevMode)
                    {
                        Log.Warning("\t[Carnivale] bannerCell road pass failure: " + rcell + ". distSqrdToCentre=" + dist + ", minDistSqrdToCentre=" + minDistSqrdToCentre + ", maxDistSqrdToCentre=" + maxDistSqrdToCentre);
                    }
                }
            }

            // line of sight pass

            if (!GenSight.LineOfSight(setupCentre, closestCell, map))
            {
                Func <IntVec3, float> weightLoSSetupCentre = c => 2f / (setupCentre.CountObstructingCellsTo(c, map) + 1f);
                Func <IntVec3, float> weightLoSColony      = c => 1f / (c.CountObstructingCellsTo(colonistPos, map) + 1f);
                Func <IntVec3, float> weightBest           = c => (weightLoSSetupCentre(c) == 2f ? 2f : 0f) + (weightLoSColony(c) == 1f ? 1f : 0f);

                var candidateCells = CellTriangle
                                     .FromTarget(setupCentre, closestCell, 45f, maxDistToCentre)
                                     .Where(c => c.InBounds(map) && c.DistanceToSquared(setupCentre) >= minDistSqrdToCentre);

                try
                {
                    closestCell = candidateCells.MaxBy(weightBest);

                    if (Prefs.DevMode)
                    {
                        Log.Message("\t[Carnivale] bannerCell optimal LoS pass: "******"\t[Carnivale] bannerCell sub-optimal LoS pass: "******"\t[Carnivale] bannerCell failed LoS passes. Is candidateCells empty? Leaving it at: " + closestCell);
                    }
                }
            }

            // Mountain proximity pass

            var     attempts = 0;
            IntVec3 nearestMineable;

            while (attempts < 10 &&
                   closestCell.DistanceSquaredToNearestMineable(map, 12, out nearestMineable) <= 36)
            {
                closestCell = CellRect.CenteredOn(closestCell, 5).FurthestCellFrom(nearestMineable);
                attempts++;

                if (Prefs.DevMode)
                {
                    Log.Message("\t[Carnivale] bannerCell mountain proximity pass #" + attempts + ": " + closestCell);
                }
            }

            if (attempts == 10 && Prefs.DevMode)
            {
                Log.Warning("\t[Carnivale] bannerCell mountain proximity passes took too many tries. Leaving it at: " + closestCell);
            }

            // End passes

            if (Prefs.DevMode)
            {
                Log.Message("[Carnivale] bannerCell pre-buildability pass: " + closestCell);
            }

            return(closestCell);
        }
コード例 #2
0
ファイル: CarnCellFinder.cs プロジェクト: Pyr3z/Carnivale
        private static bool TryCarnivalSetupPosition_Triangular(IntVec3 initPos, IntVec3 colPos, int distSqrToColony, Map map, out IntVec3 result)
        {
            var minDistSqrToColony = MinDistToColony * MinDistToColony * 2;

            var halfAngle = Mathf.Lerp(30f, 10f, distSqrToColony / map.Size.LengthHorizontalSquared);

            IntVec3 roadPos;

            if (!map.AnyRoads() ||
                !initPos
                .TranslateToward(colPos, c => !c.InNoBuildEdgeArea(map))
                .TryFindNearestRoadCell(map, 15f, out roadPos, c => !c.InNoBuildEdgeArea(map)))
            {
                roadPos = initPos;
            }

            var mapRect = CellRect.WholeMap(map).ContractedBy(MinDistToMapEdge);

            var candidateTri = CellTriangle
                               .FromTarget(colPos, roadPos, halfAngle, map.Size.x / 2)
                               .ClipInside(mapRect);

            if (Prefs.DevMode)
            {
                Log.Message("\t[Carnivale] triangular setupSpot: MinDistToMapEdge=" + MinDistToMapEdge + ", minDistSqrToColony=" + minDistSqrToColony + ", halfAngle=" + halfAngle + ", roadPos=" + roadPos);

                candidateTri.DebugFlashDraw();
            }

            Func <IntVec3, bool>  reachable       = c => map.reachability.CanReachColony(c);
            Func <IntVec3, bool>  validDist       = c => c.DistanceToSquared(colPos) >= minDistSqrToColony;
            Func <IntVec3, bool>  validRoad       = c => !map.AnyRoads() || c.DistanceSquaredToNearestRoad(map, Info.baseRadius * 1.5f) < int.MaxValue;
            Func <IntVec3, float> weightBuildable = c => 1f / (c.CountBadTerrainInRadius(map, 14) + 1f);
            Func <IntVec3, float> weightDist      = c => Rand.Range(0, 20) + distSqrToColony / (c.DistanceToSquared(colPos) + 1f);

            var maxWeight = 0f;

            foreach (var cell in candidateTri.InRandomOrder().Where(c => validDist(c) && reachable(c) && validRoad(c)))
            {
                if (Prefs.DevMode)
                {
                    map.debugDrawer.FlashCell(cell);
                }

                var weight = weightBuildable(cell) + weightDist(cell);
                var thresh = Rand.Range(19, 24);

                if (weight > maxWeight)
                {
                    maxWeight = weight;
                }

                if (weight >= thresh)
                {
                    result = cell;

                    if (Prefs.DevMode)
                    {
                        Log.Message("\t[Carnivale] triangular setupSpot: successfully found cell. result=" + result + ", weight=" + weight);
                    }
                    return(true);
                }
            }

            if (Prefs.DevMode)
            {
                Log.Warning("\t[Carnivale] triangular setupSpot: unable to find cell in candidates. maxWeight=" + maxWeight);
            }

            result = IntVec3.Invalid;
            return(false);
        }