コード例 #1
0
ファイル: Generator.cs プロジェクト: spacerush/Spaceplanets
        private static Planet GeneratePlanet(PlanetSeed seed, int planetNo, ref Star sun, bool useRandomTilt, string planetID, bool isMoon, SystemGenerationOptions genOptions)
        {
            var planet = new Planet(seed, sun, planetNo);

            planet.OrbitZone         = Environment.OrbitalZone(sun.Luminosity, planet.SemiMajorAxisAU);
            planet.OrbitalPeriodDays = Environment.Period(planet.SemiMajorAxisAU, planet.MassSM, sun.Mass);
            if (useRandomTilt)
            {
                planet.AxialTiltDegrees = Environment.Inclination(planet.SemiMajorAxisAU);
            }
            planet.ExosphereTempKelvin = GlobalConstants.EARTH_EXOSPHERE_TEMP / Utilities.Pow2(planet.SemiMajorAxisAU / sun.EcosphereRadiusAU);
            planet.RMSVelocityCMSec    = Environment.RMSVelocity(GlobalConstants.MOL_NITROGEN, planet.ExosphereTempKelvin);
            planet.CoreRadiusKM        = Environment.KothariRadius(planet.DustMassSM, false, planet.OrbitZone);

            // Calculate the radius as a gas giant, to verify it will retain gas.
            // Then if mass > Earth, it's at least 5% gas and retains He, it's
            // some flavor of gas giant.

            planet.DensityGCC = Environment.EmpiricalDensity(planet.MassSM, planet.SemiMajorAxisAU, sun.EcosphereRadiusAU, true);
            planet.RadiusKM   = Environment.VolumeRadius(planet.MassSM, planet.DensityGCC);

            planet.SurfaceAccelerationCMSec2 = Environment.Acceleration(planet.MassSM, planet.RadiusKM);
            planet.SurfaceGravityG           = Environment.Gravity(planet.SurfaceAccelerationCMSec2);

            planet.MolecularWeightRetained = Environment.MinMolecularWeight(planet);

            // Is the planet a gas giant?
            if (((planet.MassSM * GlobalConstants.SUN_MASS_IN_EARTH_MASSES) > 1.0) && ((planet.GasMassSM / planet.MassSM) > 0.05) && (planet.MolecularWeightRetained <= 4.0))
            {
                if ((planet.GasMassSM / planet.MassSM) < 0.20)
                {
                    planet.Type = PlanetType.SubSubGasGiant;
                }
                else if ((planet.MassSM * GlobalConstants.SUN_MASS_IN_EARTH_MASSES) < 20.0)
                {
                    planet.Type = PlanetType.SubGasGiant;
                }
                else
                {
                    planet.Type = PlanetType.GasGiant;
                }
            }
            else // If not, it's rocky.
            {
                planet.RadiusKM   = Environment.KothariRadius(planet.MassSM, false, planet.OrbitZone);
                planet.DensityGCC = Environment.VolumeDensity(planet.MassSM, planet.RadiusKM);

                planet.SurfaceAccelerationCMSec2 = Environment.Acceleration(planet.MassSM, planet.RadiusKM);
                planet.SurfaceGravityG           = Environment.Gravity(planet.SurfaceAccelerationCMSec2);

                if ((planet.GasMassSM / planet.MassSM) > 0.000001)
                {
                    var h2Mass = planet.GasMassSM * 0.85;
                    var heMass = (planet.GasMassSM - h2Mass) * 0.999;

                    var h2Life = Environment.GasLife(GlobalConstants.MOL_HYDROGEN, planet.ExosphereTempKelvin,
                                                     planet.SurfaceGravityG, planet.RadiusKM);
                    var heLife = Environment.GasLife(GlobalConstants.HELIUM, planet.ExosphereTempKelvin,
                                                     planet.SurfaceGravityG, planet.RadiusKM);

                    if (h2Life < sun.AgeYears)
                    {
                        var h2Loss = ((1.0 - (1.0 / Math.Exp(sun.AgeYears / h2Life))) * h2Mass);

                        planet.GasMassSM -= h2Loss;
                        planet.MassSM    -= h2Loss;

                        planet.SurfaceAccelerationCMSec2 = Environment.Acceleration(planet.MassSM, planet.RadiusKM);
                        planet.SurfaceGravityG           = Environment.Gravity(planet.SurfaceAccelerationCMSec2);
                    }

                    if (heLife < sun.AgeYears)
                    {
                        var heLoss = ((1.0 - (1.0 / Math.Exp(sun.AgeYears / heLife))) * heMass);

                        planet.GasMassSM -= heLoss;
                        planet.MassSM    -= heLoss;

                        planet.SurfaceAccelerationCMSec2 = Environment.Acceleration(planet.MassSM, planet.RadiusKM);
                        planet.SurfaceGravityG           = Environment.Gravity(planet.SurfaceAccelerationCMSec2);
                    }
                }
            }

            planet.AngularVelocityRadSec = Environment.AngularVelocity(planet);
            planet.DayLengthHours        = Environment.DayLength(planet.AngularVelocityRadSec, planet.OrbitalPeriodDays,
                                                                 planet.Eccentricity);
            planet.HasResonantPeriod = Environment.HasResonantPeriod(planet.AngularVelocityRadSec,
                                                                     planet.DayLengthHours, planet.OrbitalPeriodDays, planet.Eccentricity);
            planet.EscapeVelocityCMSec = Environment.EscapeVelocity(planet.MassSM, planet.RadiusKM);
            planet.HillSphereKM        = Environment.SimplifiedHillSphereKM(sun.Mass, planet.MassSM, planet.SemiMajorAxisAU);

            if (planet.IsGasGiant)
            {
                planet.HasGreenhouseEffect        = false;
                planet.VolatileGasInventory       = GlobalConstants.INCREDIBLY_LARGE_NUMBER;
                planet.Atmosphere.SurfacePressure = GlobalConstants.INCREDIBLY_LARGE_NUMBER;

                planet.BoilingPointWaterKelvin = GlobalConstants.INCREDIBLY_LARGE_NUMBER;

                planet.SurfaceTempKelvin    = GlobalConstants.INCREDIBLY_LARGE_NUMBER;
                planet.GreenhouseRiseKelvin = 0;
                planet.Albedo                  = Utilities.About(GlobalConstants.GAS_GIANT_ALBEDO, 0.1);
                planet.WaterCoverFraction      = 1.0;
                planet.CloudCoverFraction      = 1.0;
                planet.IceCoverFraction        = 0.0;
                planet.SurfaceGravityG         = Environment.Gravity(planet.SurfaceAccelerationCMSec2);
                planet.MolecularWeightRetained = Environment.MinMolecularWeight(planet);
                planet.SurfaceGravityG         = GlobalConstants.INCREDIBLY_LARGE_NUMBER;
            }
            else
            {
                planet.SurfaceGravityG         = Environment.Gravity(planet.SurfaceAccelerationCMSec2);
                planet.MolecularWeightRetained = Environment.MinMolecularWeight(planet);

                planet.HasGreenhouseEffect  = Environment.Greenhouse(sun.EcosphereRadiusAU, planet.SemiMajorAxisAU);
                planet.VolatileGasInventory = Environment.VolatileInventory(
                    planet.MassSM, planet.EscapeVelocityCMSec, planet.RMSVelocityCMSec, sun.Mass,
                    planet.OrbitZone, planet.HasGreenhouseEffect, (planet.GasMassSM / planet.MassSM) > 0.000001);
                planet.Atmosphere.SurfacePressure = Environment.Pressure(
                    planet.VolatileGasInventory, planet.RadiusKM, planet.SurfaceGravityG);

                planet.BoilingPointWaterKelvin = Math.Abs(planet.Atmosphere.SurfacePressure) < 0.001
                    ? 0.0
                    : Environment.BoilingPoint(planet.Atmosphere.SurfacePressure);

                // Sets: planet.surf_temp, planet.greenhs_rise, planet.albedo, planet.hydrosphere,
                // planet.cloud_cover, planet.ice_cover
                Environment.IterateSurfaceTemp(ref planet);

                CalculateGases(planet, genOptions.GasTable);

                planet.IsTidallyLocked = Environment.IsTidallyLocked(planet);

                // Assign planet type
                if (planet.Atmosphere.SurfacePressure < 1.0)
                {
                    if (!isMoon && ((planet.MassSM * GlobalConstants.SUN_MASS_IN_EARTH_MASSES) < GlobalConstants.ASTEROID_MASS_LIMIT))
                    {
                        planet.Type = PlanetType.Asteroids;
                    }
                    else
                    {
                        planet.Type = PlanetType.Barren;
                    }
                }
                else if ((planet.Atmosphere.SurfacePressure > 6000.0) && (planet.MolecularWeightRetained <= 2.0)) // Retains Hydrogen
                {
                    planet.Type = PlanetType.SubSubGasGiant;
                    planet.Atmosphere.Composition = new List <Gas>();
                }
                else
                {
                    // Atmospheres:
                    // TODO remove PlanetType enum entirely and replace it with a more flexible classification systme
                    if (planet.WaterCoverFraction >= 0.95) // >95% water
                    {
                        planet.Type = PlanetType.Water;
                    }
                    else if (planet.IceCoverFraction >= 0.95) // >95% ice
                    {
                        planet.Type = PlanetType.Ice;
                    }
                    else if (planet.WaterCoverFraction > 0.05) // Terrestrial
                    {
                        planet.Type = PlanetType.Terrestrial;
                    }
                    else if (planet.MaxTempKelvin > planet.BoilingPointWaterKelvin) // Hot = Venusian
                    {
                        planet.Type = PlanetType.Venusian;
                    }
                    else if ((planet.GasMassSM / planet.MassSM) > 0.0001) // Accreted gas, but no greenhouse or liquid water make it an ice world
                    {
                        planet.Type             = PlanetType.Ice;
                        planet.IceCoverFraction = 1.0;
                    }
                    else if (planet.Atmosphere.SurfacePressure <= 250.0) // Thin air = Martian
                    {
                        planet.Type = PlanetType.Martian;
                    }
                    else if (planet.SurfaceTempKelvin < GlobalConstants.FREEZING_POINT_OF_WATER)
                    {
                        planet.Type = PlanetType.Ice;
                    }
                    else
                    {
                        planet.Type = PlanetType.Unknown;
                    }
                }
            }

            // Generate moons
            planet.Moons = new List <Planet>();
            if (!isMoon)
            {
                var curMoon = seed.FirstMoon;
                var n       = 0;
                while (curMoon != null)
                {
                    if (curMoon.Mass * GlobalConstants.SUN_MASS_IN_EARTH_MASSES > .000001)
                    {
                        curMoon.SemiMajorAxisAU = planet.SemiMajorAxisAU;
                        curMoon.Eccentricity    = planet.Eccentricity;

                        n++;

                        string moon_id = String.Format("{0}.{1}", planetID, n);

                        var generatedMoon = GeneratePlanet(curMoon, n, ref sun, useRandomTilt, moon_id, true, genOptions);

                        double roche_limit = 2.44 * planet.RadiusKM * Math.Pow((planet.DensityGCC / generatedMoon.DensityGCC), (1.0 / 3.0));
                        double hill_sphere = planet.SemiMajorAxisAU * GlobalConstants.KM_PER_AU * Math.Pow((planet.MassSM / (3.0 * sun.Mass)), (1.0 / 3.0));

                        if ((roche_limit * 3.0) < hill_sphere)
                        {
                            generatedMoon.MoonSemiMajorAxisAU = Utilities.RandomNumber(roche_limit * 1.5, hill_sphere / 2.0) / GlobalConstants.KM_PER_AU;
                            generatedMoon.MoonEccentricity    = Utilities.RandomEccentricity();
                        }
                        else
                        {
                            generatedMoon.MoonSemiMajorAxisAU = 0;
                            generatedMoon.MoonEccentricity    = 0;
                        }
                        planet.Moons.Add(generatedMoon);
                    }
                    curMoon = curMoon.NextPlanet;
                }
            }

            return(planet);
        }