private bool GeneratePlanet(Planet planet) { planet.SurfaceTemperature = 0; planet.HighTemperature = 0; planet.LowTemperature = 0; planet.MaxTemperature = 0; planet.MinTemperature = 0; planet.RiseInTemperatureDueToGreenhouse = 0; planet.IsInResonantRotation = false; planet.OrbitZone = EnviroUtilities.OrbitalZone(planet.Primary.Luminosity, planet.SolarSemiMajorAxis); planet.AxialTilt = Inclination(planet.SolarSemiMajorAxis); initOrbitPosition(planet); planet.ExoSphericTemperature = Constants.Sol.Earth.EXOSPHERE_TEMP / Math.Pow(planet.SolarSemiMajorAxis / planet.Primary.EcoSphereRadius, 2.0); planet.RootMeanSquaredVelocity = EnviroUtilities.RootMeanSquareVelocity(Constants.Gases.MolecularWeights.MOL_NITROGEN, planet.ExoSphericTemperature); planet.RadiusOfCore = EnviroUtilities.KothariRadius(planet.MassOfDust, 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.Density = EnviroUtilities.EmpiricalDensity(planet.Mass, planet.SolarSemiMajorAxis, planet.Primary.EcoSphereRadius, true); planet.Radius = EnviroUtilities.VolumeRadius(planet.Mass, planet.Density); planet.SurfaceAcceleration = EnviroUtilities.Acceleration(planet.Mass, planet.Radius); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); planet.MolecularWeightRetained = EnviroUtilities.MinMolecWeight(planet); if (((planet.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES) > 1.0) && ((planet.MassOfGas / planet.Mass) > 0.05) && (EnviroUtilities.MinMolecWeight(planet) <= 4.0)) { if ((planet.MassOfGas / planet.Mass) < 0.20) { planet.PlanetType = PlanetTypes.GasDwarf; } else if ((planet.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES) < 20.0) { planet.PlanetType = PlanetTypes.IceGiant; } else { planet.PlanetType = PlanetTypes.GasGiant; } } else // If not, it's rocky. { planet.Radius = EnviroUtilities.KothariRadius(planet.Mass, true, planet.OrbitZone); planet.Density = EnviroUtilities.VolumeDensity(planet.Mass, planet.Radius); if ((planet.MassOfGas / planet.Mass) > 0.000001) { double h2Mass = planet.MassOfGas * 0.85; double heMass = (planet.MassOfGas - h2Mass) * 0.999; double h2Life = EnviroUtilities.GasLife(Constants.Gases.MolecularWeights.MOL_HYDROGEN, planet); double heLife = EnviroUtilities.GasLife(Constants.Gases.MolecularWeights.HELIUM, planet); if (h2Life < planet.Primary.Age) { var h2Loss = ((1.0 - (1.0 / Math.Exp(planet.Primary.Age / h2Life))) * h2Mass); planet.MassOfGas -= h2Loss; //planet.Mass -= h2Loss; //Mass of planet changed so recalculate planet.SurfaceAcceleration = EnviroUtilities.Acceleration(planet.Mass, planet.Radius); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); } if (heLife < planet.Primary.Age) { var heLoss = ((1.0 - (1.0 / Math.Exp(planet.Primary.Age / heLife))) * heMass); planet.MassOfGas -= heLoss; //planet.Mass -= heLoss; //Mass of planet changed so recalculate planet.SurfaceAcceleration = EnviroUtilities.Acceleration(planet.Mass, planet.Radius); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); } } } planet.LengthOfDay = EnviroUtilities.DayLength(planet); /* Modifies planet->resonant_period */ planet.EscapeVelocity = EnviroUtilities.EscapeVel(planet.Mass, planet.Radius); planet.MolecularWeightRetained = EnviroUtilities.MinMolecWeight(planet); if ((planet.PlanetType == PlanetTypes.GasGiant) || (planet.PlanetType == PlanetTypes.IceGiant) || (planet.PlanetType == PlanetTypes.GasDwarf)) { planet.HasGreenhouseEffect = false; planet.VolatileGasInventory = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.SurfacePressure = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.BoilingPoint = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.SurfaceTemperature = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.RiseInTemperatureDueToGreenhouse = 0; planet.Albedo = rnd.About(Constants.Units.GAS_GIANT_ALBEDO, 0.1); planet.HydrosphereCover = 1.0; planet.CloudCover = 1.0; planet.IceCover = 0.0; planet.SurfaceGravity = Constants.Units.INCREDIBLY_LARGE_NUMBER; planet.EstimatedTemperature = EnviroUtilities.EstTemp(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis, planet.Albedo); planet.EstimatedTerrestrialTemperature = EnviroUtilities.EstTemp(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis, Constants.Sol.Earth.ALBEDO); } else { planet.EstimatedTemperature = EnviroUtilities.EstTemp(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis, Constants.Sol.Earth.ALBEDO); planet.SurfaceGravity = EnviroUtilities.Gravity(planet.SurfaceAcceleration); planet.HasGreenhouseEffect = EnviroUtilities.Greenhouse(planet.Primary.EcoSphereRadius, planet.SolarSemiMajorAxis); planet.VolatileGasInventory = EnviroUtilities.VolInventory(planet.Mass, planet.EscapeVelocity, planet.RootMeanSquaredVelocity, planet.Primary.Mass, planet.OrbitZone, planet.HasGreenhouseEffect, (planet.MassOfGas / planet.Mass) > 0.000001); planet.SurfacePressure = EnviroUtilities.Pressure(planet.VolatileGasInventory, planet.Radius, planet.SurfaceGravity); if (planet.SurfacePressure == 0.0D) { planet.BoilingPoint = 0.0; } else { planet.BoilingPoint = EnviroUtilities.BoilingPoint(planet.SurfacePressure); } EnviroUtilities.IterateSurfaceTemp(planet); if ((planet.MaxTemperature >= Constants.Sol.Earth.FREEZING_POINT_OF_WATER) && (planet.MinTemperature <= planet.BoilingPoint)) { CalculateGases(planet); } /* * Next we assign a type to the planet. */ if (planet.SurfacePressure < 1.0) { if (!planet.IsMoon && ((planet.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES) < Constants.Stargen.ASTEROID_MASS_LIMIT)) { planet.PlanetType = PlanetTypes.Asteroid; } else { planet.PlanetType = PlanetTypes.Rock; } } else if ((planet.SurfacePressure > 6000.0) && (planet.MolecularWeightRetained <= 2.0)) // Retains Hydrogen { planet.PlanetType = PlanetTypes.GasDwarf; planet.Gases.Clear(); //TODO: Do we really want to clear the atmosphere just because it is a gas dwarf? } else { // Atmospheres: //if (((int)planet.Day == (int)(planet.OrbitalPeriod * 24.0) || (planet.IsInResonantRotation))) // planet.PlanetType = PlanetTypes.Face; //else if (planet.HydrosphereCover >= 0.95) { planet.PlanetType = PlanetTypes.Water; // >95% water } else if (planet.IceCover >= 0.95) { planet.PlanetType = PlanetTypes.Ice; // >95% ice } else if (planet.HydrosphereCover > 0.05) { planet.PlanetType = PlanetTypes.Terrestrial; // Terrestrial // else <5% water } else if (planet.MaxTemperature > planet.BoilingPoint) { planet.PlanetType = PlanetTypes.Venusian; // Hot = Venusian } else if ((planet.MassOfGas / planet.Mass) > 0.0001) { // Accreted gas, But no Greenhouse, or liquid water, Make it an Ice World planet.PlanetType = PlanetTypes.Ice; planet.IceCover = 1.0; } else if (planet.SurfacePressure <= 250.0) { // Thin air = Martian planet.PlanetType = PlanetTypes.Martian; } else if (planet.SurfaceTemperature < Constants.Sol.Earth.FREEZING_POINT_OF_WATER) { planet.PlanetType = PlanetTypes.Ice; } else { planet.PlanetType = PlanetTypes.Unknown; } } } if (_generateMoons && !planet.IsMoon) { if (planet.Moons != null) { // Sort moons planet.Moons = new BindingList <Planet>(planet.Moons.OrderBy(x => x.SemiMajorAxis).ToList()); // Create a copy of the moons list var moonList = planet.Moons.ToList(); var count = 0; var hillSphere = planet.SemiMajorAxis * (1.0 - planet.Eccentricity) * Constants.Units.KM_PER_AU * Math.Pow((planet.Mass / (3.0 * planet.Primary.Mass)), (1.0 / 3.0)) / Constants.Units.KM_PER_AU; for (int n = 0; n < moonList.Count; n++) { bool pass = true; var moon = moonList[n]; if (moon.Mass * Constants.Sol.Sun.MASS_IN_EARTH_MASSES > .000001) { //moon.SemiMajorAxis = planet.SemiMajorAxis; //moon.Eccentricity = planet.Eccentricity; moon.Id = Guid.NewGuid(); moon.Name = string.Format("{0}.{1}", planet.Name, count + 1); moon.Primary = planet.Primary; GeneratePlanet(moon); //TODO: Look at adding atmosphere call to this var rocheLimit = 2.44 * planet.Radius * Math.Pow((planet.Density / moon.Density), (1.0 / 3.0)) / Constants.Units.KM_PER_AU; //if ((rocheLimit * 3.0) < hillSphere) if (moon.SemiMajorAxis < rocheLimit) { // Moon too close. // TODO: Turn moon into rings planet.Moons.Remove(moon); pass = false; //return false; //#if LOG4NET_ENABLED //logger.Debug(string.Format("Moon of planet {0} inside Roche limit", planet.Name)); //#endif } if (moon.SemiMajorAxis > hillSphere) { // Moon too far planet.Moons.Remove(moon); pass = false; //return false; //#if LOG4NET_ENABLED //logger.Debug(string.Format("Moon of planet {0} outside hill radius", planet.Name)); //#endif } } else { // Moon too small planet.Moons.Remove(moon); pass = false; //return false; //#if LOG4NET_ENABLED //logger.Debug(string.Format("Moon of planet {0} too small", planet.Name)); //#endif } if (pass) { count++; } } } } return(true); }