#+title: Open Heavens

Open Heavens is a semi-realistic and deterministic star system generator, based on [[https://github.com/BirDt/stardate-legacy][Stardate Legacy]]. Open Heavens provides the "controller" part of your average MVC, so it does not provide any visualisation or interaction logic with the system (except for whatever is needed for testing).

* Dependencies & Credits
- [[https://github.com/BirDt/markov-machine][Markov Machine]] is used for name generation.

* Generation Process
Open Heavens generates systems by their mass, age (which is sparingly used), and elemental abundance, both of which are configurable when passed to the system generator. This process outline assumes you leave all settings as random, and only provide a seed. Most rates are configurable.

We start by randomly generating the solar mass of the overall system. 80% of the time, we use a random distribution of a 1.1 solar mass mean with a 0.5 solar mass deviation, and we clamp this to 0.5 and 20 on the lower and upper end. 20% of the time, we just randomly generate anywhere from 0.5 to 20 solar masses. We also generate the age of the system, in gigayears - 80% of the time this is a normal distribution with a mean of 5 and deviation of 1, otherwise it's a random value between 1 and 13. The reason for these values is that they provide 80% (this is configurable) odds of generating an interesting system with a good number of exoplanets.

We next generate abundances. The [[https://en.wikipedia.org/wiki/Abundance_of_the_chemical_elements#Universe][top ten most common elements]] are normally distributed around their mass fraction with small (0.05 - 0.00005) deviations. For the remaining natural elements, they are completely random but always add up to 100%. This is not a particularly realistic way of generating the abundance, but it leads to some fun results like thorium worlds and the like.

We generate the star of the system by removing a random portion of the total system mass - between 20% and 99%. This mass makes up the star and is used to generate it.

** Star Generation
Aside from mass and age, we calculate or generate the following star values:
- Stellar Class
- Temperature
- Color (RGB)
- Luminosity (Visible Light, X-Ray, and Extreme UV)
- Radius
- Density
- Habitable Zone Range
- Composition (and Metallicity)
- Stellar Wind Quantity (yearly mass loss)
- Stellar Wind Velocity
- Magnetic Field Strength
- Average Solar Flare Energy & Average Flares per Day
- Stellar Variability

***  Stellar Class
We start by calculating the stellar class - since we only have main sequence stars this is fairly simple as we just look at the mass of the star and assign the class based on the range:
| Mass (Solar Masses) | Class |
|---------------------+-------|
| x < 0.45            | M     |
| 0.45 < x < 0.8      | K     |
| 0.8 < x < 1.04      | G     |
| 1.04 < x < 1.4      | F     |
| 1.4 < x < 2.1       | A     |
| 2.1 < x < 16        | B     |
| x > 16              | O     |

*** Temperature & Color
We use a curve to determine the temperature (in Kelvin) from the mass, and color (RGB) from the temperature. These curves used known stars as sample points.

*** Luminosity
For luminosity, the following DISGUSTING formula is used.
~14341850000 + ((78.43685-14341850000)/(1 + pow(temperature/145852.2,7.237745)))-78.46~
This gives the luminosity in solar luminosity, so 1 = 3.75×10^28 lumen.

*** Radius
To calculate the radius (in solar radii), we first calculate a best guess: ~pow((3.0 * mass)/4.0*PI, 1.0/3.0)~.
The output of this is ~0.62035~ for 1 solar mass, and so we normalise the value so that 1 solar mass = 1 solar radius: ~(best guess/0.62035) - 1.14503109452965~

*** Density
From the radius we calculate the density, which is used for habitable zone and Roche limit calculations. We do this by calculating the projected volume - ~(4.0/3.0) * PI * pow(solar_radii * SOLAR_RADIUS, 3)~ - and real mass (in Kg) - ~mass * 1.9885~ - which gives us a simple formula for the kg/m^3 density: ~(r_mass/projected_volume) * 1000 * 1000~.

*** Habitable Zone
We calculate the inner and outer radius of the star's habitable zone as the square root of the luminosity divided by 1.1, and the square root of the luminosity divided by 0.53 respectively. These values are in AU.

*** Composition
We also determine the composition of the star, however we assume it is only composed of hydrogen and helium. Hydrogen can be any percent between 65 and 85, while helium is the remainder to bring the composition to 100. This prevents too much hydrogen and helium from being used in planet generation, which prevents too many gas giants from being generated. However, though we don't calculate the fine-grained composition, we do calculate a metallicity based on age (in Solar Metallicities): for systems with an age between 1 and 8, this is a random value between 0.5 and 2.0. For older systems, it's between 0.001 and 0.1.

*** Stellar Wind
We also need to estimate the quantity of stellar wind, which helps us determine whether planets in proximity to the star should have atmospheres - as well as undestanding the general system's radiation. We calculate the mass loss rate differently depending on the class of star. For this we calculate the rotation period as ~25 * pow(mass, -1.7) * pow(age/4.6, 0.5)~ and convective turnover time as ~70 * pow(mass, -2.5)~. We can also then calculate the Rossby number as the period divided by the turnover time, divided by 2.
For stars less than 1.5 solar masses in size, mass loss is driven by magnetic activity and is calculated as ~pow(radius in km, 2) * pow(convective turnover time, -2.6) * pow(rotation period, -2.6)~, divided by the 1 Solar mass to get the mass lost per year.
For stars greater than 1.5 solar masses, the formula is instead:
~k * pow(luminosity, v) * pow(mass, q) * pow(metallicity, 0.69)~ divided 1 Solar mass. The values of ~k~, ~v~, and ~q~ change based on mass:
| Mass       | ~k~               |    ~v~ |     ~q~ |
|------------+-----------------+------+-------|
| 1.5 < x 3  | pow(10, -13.8)  | 1.24 | -0.16 |
| 3 < x < 10 | pow(10, -13.6)  | 1.69 | -0.84 |
| 10 < x     | pow(10, -12.95) | 1.58 | -0.67 |

We also need to calculate the terminal wind velocity of the stellar wind. This is ~617.7 * sqrt(mass / radius)~ km/s.

*** Magnetic Field Strength
We can calculate the magnetic field strength based on mass as well, with stars below 0.35 solar masses having a random strength between 1000 and 5000 Gauss. Stars between 0.35 and 1.5 solar masses calculate their strength from their rotation period at convective turnover: ~pow((period / convective turnover)/2, -1.2)~ kilo-Gauss. For stars greater than 1.5 solar masses, the value is random between 100 and 1000 Gauss.

*** X-ray and Extreme UV Luminosity
The X-ray luminosity is calculated as ~pow(10, -3.7) * pow(Rossby, -2)~, divided by the luminosity. The EUV luminosity is just 4 times the X-ray luminosity.

*** Solar Flare Frequency & Strength
For stars above 1.5 Solar masses, the flare frequency is a random on a normal distribution with a mean of 0.1 and a deviation of 0.005. For smaller stars, the flare frequency is ~10 * pow(age, -1.5)~.

We can calculate the average solar flare energy as ~x-ray luminosity * pow(Rossby, -2)~. 

*** Stellar Variability
Variability is important for modelling climate stability, and is calculated as ~0.001 * pow(Rossby, -1.5)~. The starspot cycle period is calculated as ~10 * pow(rotation period, 0.8)~ years.

** Planet Generation
We always generate a minimum of 1 planetoid, which can be forced to be habitable. We continue generating planets up until all the system mass is used up - that being when only 0.05 Earth masses are remaining, which is considered as the mass for non-planet system features such as asteroids or comets.

*** Mass
Each time we generate a planet, we generate a mass for it (in Earth masses) and subtract that from the remaining system mass. If the planet should be forced as habitable, the mass is always between 0.107 and 9.44 Earth masses, otherwise it is either between 0.05 and 1000, or 0.05 and 15, where we select the former a third of the time. This prevents too many gas giants from showing up.

*** Radius
To determine the radius of the planet (in Earth radii), for most planets we sample the planet mass to radius curve (which is constructed based on real known planet mass and radius values), adding some normally distributed deviation (mean of 0, deviation of 0.15). For planets with forced habitable generation, we start with a random radius between 0.5 and 2.49. We then incrementally subtract and add from this radius until we can get an estimated surface gravity between 0.4 and 1.7. We calculate the density after the radius, similarly to the star density calculation:
1. We get a projected volume: ~(4.0/3.0) * PI * pow(planet_radius * 6378 * 1000, 3)~
2. We get the real mass in kilograms: ~mass * 5.98 * pow(10, 24)~
3. We divide the latter by the former to get the density

Surface gravity is calculated from the kilogram mass (~mass * 5.98 * pow(10, 24)~) and meter radius (~planet_radius * 6378 * 1000~). This gives a gravity of ~G * (real_mass / pow(real_rad, 2))~ meters/second^2, and ~m/s^2 * 0.10197162129779~ g's.

*** Orbit
We calculate each planet's orbit. If the planet is forced habitable, we set the orbit distance to a random value within the star's habitable zone range. Otherwise, we calculate the roche limit based on the radius, mass, and density. If the parent body of this planet is a star (the system root) then we randomise the orbit between 0.05 AU + the roche limit and 50 AU + the outer habitable zone radius. If the parent body is a planet, we randomise it between the roche limit and 0.1 AU.

*** Orbit Speed
We calculate the orbit speed as ~sqrt((G * parent_mass)/distance_at_apoapsis_m) / 1000~, using real values, where the distance at apoapsis is ~(orbit_distance * 1.495979)*100000000~. The orbital period follows as ~(2 * PI * orbit_distance)/orbit_speed~, and we turn that into an "Earth days" measurement with ~abs(orbital_period / 0.211 * 365)~.

*** Rotation Period
We also calculate a rotation period - for forced habitable worlds, this value is a normal distribution with a mean of 1 day and a deviation of 0.2. For every other world, this is a normal distribution with a mean of 1 divided by the mass of the planet, and a deviation of 1. The rotation period has a 50% chance of being reversed. For forced habitable worlds, the axial tilt is random between 0 and 35 degrees, otherwise it's random between 0 and 90 degrees. If the rotation period and orbital period are approximately equal, we also keep track of the planet being tidally locked.

*** Moons and Rings
Each planetoid can also have moons, each of which being their own planetoid which is flagged as being unable to generate moons. The chance of generating a moon is based on the parent planetoid mass and is random - a moon is generated 20% of the time if the parent is less than 10 Earth masses, and 50% of the time otherwise. This chance is divided by the number of moons + 1, to progressively generate less and less moons.

Non-moon planetoids can also have rings. The chance of a ring generating is also based on the planetoid mass. We check if ~clampf(randf(), 0.0, 0.8)/mass~ is less than 0.0065, meaning that at a planet of Jupiter's mass we have a 65% chance of generating a ring.

Rings, or more accurately ring systems, can have multiple segments. This is a normal random distribution with a mean of 4 and a deviation of 3, with a minimum of 1. There are three types of rings - Icy, Dusty, and Rocky. Dusty has a 50% chance chosen as the ring type, while Icy and Rocky both have a 25% chance.

We assign a mass to the ring, which is a random number between 0.000001 and 0.05 Earth masses. We also determine the rings inner and outer radius - the inner radius is a random number between the Roche limit for the chosen mass and 0.05 AU, while the outer radius is a random number between the inner radius and 0.1 AU.

We calculate the ring's composition by using the starting system abundances. As with everything else, rings can only be composed of natural elements. We select up to 10 elements from the system abundance (sorted by most to least abundant) to make up the composition of the ring. The first element chosen accounts for anywhere between 0 and 100% of the composition, and each subsequent element makes up a random percent between 0 and 100 minus the current sum total of elements in the system.

*** Planet, Atmosphere, and Volcanism Classes
Planets are generated based on a classification system, with possible planet classes being Terrestrial, Metallic, Water, Gas, and Ice. By default, every planet can be metallic or terrestrial, and not ice, gas, or water. This is modified by mass and a few other factors:
- If a planet is greater than 10 Earth masses and is not a moon, it could be a gas planet.
- If the mass is less than 15, it could be an ice or water planet.
- If the mass is greater than 5, it can't be either a metallic or terrestrial planet.
- If the planet is not within the star's habitable zone, it cannot be a water planet.
- If the planet is closer than the other radius of the star's habitable zone, it cannot be an ice planet.
These rules provide some base sanity for planet generation and prevent things like small gas giants. We then roll a random float.
- If it could be ice and the number is between 0.7 and 0.9, the planet is an ice planet.
- If it could be water and the number is greater than 0.9, it is a water planet.
- If it could be metallic and the number is between 0.5 and 0.7, it's metallic.
- If it could be terrestrial, it's terrestrial.
- If it could be gas, it's gas.
- And finally as a fallback, if none of the previous conditions match, the planet is terrestrial.

The atmosphere is also based on a classification system, with atmospheres being either None, Light, Earth-like, or Heavy. The following rules govern which atmospheres are possible:
- If the planet is a gas giant, the atmosphere class must be None.
- If the planet is less than 0.5 Earth masses, the atmosphere class must be None.
- If the planet is within 0.1 AU of it's parent star, the atmosphere class must be None.
- Calculate the magnetic flux at the given point as the X-ray Luminosity divided by the orbit distance (in metres). If this value is more than ~100 * pow(mass in Earth masses, 2)~, the atmosphere class must be None. This estimates the impact of stellar wind against a likely magnetic core.
- If habitable generation is forced, and the above two rules are not applicable, the planet has an Earth-like atmosphere.
Otherwise, the atmosphere class is randomly determined: 50% of the time, it is None. 25% of the time, it is Light. 15% of the time it is Earth-like, and the remaining 10% of the time it is Heavy.

Finally, we also determine a classification for the volcanic activity. This can be either None, Low, Medium, High, and Extreme. This is, primarily, a representation of tidal forces - so planets with large moons will have more extreme volcanic activity.
Gas planets always have no volcanism.
Planets that have no moons, or aren't moons, always have no volcanism.
If the planet is not a moon, we calculate the mass, radius, and orbit distance of the closest moon in SI units - if the planet is a moon, we calculate these values for the parent planet instead. We calculate the tidal force exerted as ~G * real_mass * ((2*real_radius)/pow(real_distance, 3))~. From this result: if it's approximately 0, the volcanism is None. If the force is less than 1.2, the volcanism is Low. If it's less than 5, the volcanism is Medium. If the force is less than 20, the volcanism is High. Otherwise, the volcanism is Extreme.

*** Surface Temperature
We now generate the atmospheric pressure (in Atmospheres) based off the class:
- A class of None has 0 pressure.
- A class of Light has any pressure between 0 and 0.6.
- A class of Earth-like has any pressure between 0.6 and 1.4.
- A class of Heavy has any pressure between 1.4 and 100.

We also generate the planetary albedo based on planet class and atmosphere class, starting with a base random value from the planet class:
- Terrestrial planets have a value between 6 and 11.
- Metallic planets have a value between 0 and 6.
- Gas planets have a range between 30 and 100.
- Water planets have a range between 10 and 20.
- Ice planets have a range between 50 and 70.
We then add a random value based on the atmosphere class:
- For None atmospheres, we don't add anything.
- For Light atmospheres, we add a value between 0 and 2.
- For Earth-like atmospheres, we add a value between 2 and 12.
- For Heavy atmospheres we add a value between 12 and 100.
We then correct the albedo as a fraction by dividing it by 100. The result cannot be lower than 0 or higher than 1.

We also generate a greenhouse effect component based on the Atmosphere class:
- For None, it's 0.
- For Light, it's between 0 and 0.9.
- For Earth-like, it's between 0.9 and 1.5.
- For Heavy, it's between 1.5 and 500.

Now we can calculate the surface temperature. For this we need the SI values of the system's sun luminosity and the orbit distance of the planetary system. We also calculate the Stefan Boltzmann constant: ~5.67 * pow(10, -8)~.
This allows us to calculate the surface temperature like so: ~(pow((L/pow(d, 2)) * ((1-albedo)/(4*stefan_boltzmann)) * (1 + ((3.0/4.0)*greenhouse)), 1.0/4.0))/2~ Kelvin.

Based on the volcanism, we also add some additional variation:
- For no volcanism, we add nothing.
- For low volcanism, we add anywhere between 0 and 5 degrees.
- For medium volcanism, we add anywhere from 5 to 15.
- For high volcanism we add anywhere from 15 to 100.
- For extreme volcanism we add anywhere from 100 to 1000.

Finally, gas planets have their surface temperature multiplied by a random number between 100 and 500.

*** Elemental Composition
We also determine the planet's elemental composition - for the surface, we only look at the crust. We first filter to possible elements by looking at natural elements, and filtering based on the planet class.
- For Terrestrial planets, we only filter to elements which are solid given the surface temperature. We also remove heavy elements: any element with an atomic number greater than 34.
- For Metallic planets, we again filter to solids, and we also remove all non-metals, noble gasses, halogens, metalloids, alkali metals, and alkali earth metals.
- For Water planets, we filter to elements that can be either solid or liquid for the surface temperature.
- For Ice planets, we filter to solids only.
- For Gas planets, we filter to gasses only.
We then look in the system abundance, and copy all elements that pass the above filters, with their percentage abundance in the system. The only exception is Silicon - if the planet class is Terrestrial, we set the percent of Silicon in the planet to anywhere from 20% to 50%.
Now for the copied elements and percentages, sorted by their percentage, we randomly determined the composition. The first and most abundant element of Terrestrial planets is Silicon.
Otherwise, we pick the 10 most abundant elements, sort by ascending weight and take 3 from the result, shuffle, then take the first element, and push it to the crust composition with a random range between 0.4 and 0.8 (if this is the first element selected) or 0 and 1.0 - the sum total of all currently selected elements. We do this until we run out of elements or hit 100% composition.

If the atmosphere class is not None, we also need to determine the planet's atmospheric composition. For this we filter to natural elements, and only those that are gasses given the surface temperature.
Then we look in the system abundance, and copy all elements that pass the above filter. If the element is not a nonmetal and not a noble gas, we divide it's percent by it's atomic number * 10 - this makes it more unlikely for heavy elements to be part of the atmosphere.
Then, we pick a random element from the 5 most abundant elements and push it to the atmosphere composition composition with a random range between 0.5 and 0.9 (if this is the first element selected) or 0 and 1.0 - the sum total of all currently selected elements. We do this until we run out of elements to get the major atmospheric composition.

Terrestrial, Metallic, and Ice planets can have oceans or other, smaller liquid bodies. There is a 22% chance that a planet will attempt to generate liquid bodies. Instead of searching for individual elements, we have specific molecules that can form oceans each with their own feasible temperature range. These are:
- Water - 273.15 to 373.15 Kelvin
- Nitrogen - 63.15 to 77.5 Kelvin
- Carbon Dioxide - 217.15 to 273.15 Kelvin
If the surface temperature does not fit within any of these ranges, the ocean fails to generate. Otherwise, we set the composition of the ocean as the percentage of the chemicals that make up each molecule.

*** Magnetic Field
With the composition determined, we can estimate the magnetic field strength, in Gauss, of the planetoid. We do this by first estimating the electrical conductivity of the elemental composition. To do this, we multiply the electrical conductivity in S/m for each element in the composition by the percent composition of that element, then sum all the resulting values. We can then calculate the magnetic field as ~sqrt((density * rotation rate in ms)/conductivity)~.

** Planetary Surface Generation
#+begin_quote
Colloquially known as having a fun time.
#+end_quote

Based off the various planet metadata calculated, we can create a chunk-based surface for each planet and populate it. If you know anything about spheres, or maps, you may know that it is very difficult to tesselate a spherical surface equally with the shapes one may usually consider for chunks (for gameplay purposes). Even though spheres can't be tesselated equally by squares, we generate square chunks - our planets are actually cubes!

Currently, gas planets have no surface generation.

Each chunk is <YET UNDEFINED> kilometres across, and has a number of procedurally generated attributes.

*** Geo-biomes
Minerology and surface feature generation are both driven by the planetary geology, which abstracted to "geo-biomes". Each chunk on a planet pulls a random geo-biome from the list of possible biomes given the environment. Biomes are weighted based on how probably their generation is given the environment.
When looking at the list of possible geo-biomes, we first consider whether the planet is dead or not. Dead worlds have no volcanism, and no atmosphere. For dead worlds, every geo-biome except for impact and primordial is weighted as 0.2.

**** Impact
The Impact geo-biome is formed by extraterrestrial impacts. This is possible when the atmospheric pressure is less than 20 atmospheres. For dead worlds, this is the most common geo-biome, with a weighting of 0.9. For non-dead worlds, the weighting for impact planets is calculated as ~1 / atmospheric_pressure~.

**** Primordial
This geo-biome represents unaltered crust material and is only present on dead worlds, with a weighting of 0.5.

**** Supergene
The Supergene geo-biome represents fluid chemical weathering. It can only exist on planets with a surface temperature greater than 0.1. It is weighted by the ~atmospheric pressure / 100~.

**** Metamorphic
The Metamorphic geo-biome represents recrystallization of rock in response to heat or pressure. It can generate on any terrestrial, metallic, or ice planet, and is weighted by the ~surface temperature / 700~ with a maximum of 0.8.

**** Sedimentary
The Sedimentary geo-biome represents physical transport and deposition of particles by a fluid. It can exist on any planet, however is weighted by the presence of liquid bodies. If there are currently liquid bodies present, the weighting is ~2*(atmospheric pressure / 100)~, with a maximum of 0.8. If there are no liquid bodies present, it is ~(atmospheric pressure / 200)~.

**** Fumarolic
The Fumarolic geo-biome represents sublimation or condensation from a gas phase to the surface. It can generate on any planet with an atmospheric pressure greater than 0.001. The weighting is based on volcanism level - 0.1 for None, 0.2 for Low, 0.4 for Medium, 0.7 for High, 0.8 for Extreme.

**** Hydrothermal
The Hydrothermal geo-biome represents fluid circulation driven by a heat gradient. There are two types of Hydrothermal biome - high and low temperature. In both cases, liquid bodies are required.

High temperature hydrothermal can only exist in high or extreme volcanism. Low temperature hydrothermal can exist in any volcanism class. The weighting of this geo-biome is 0.6.

**** Pegmatitic
The Pegmatitic geo-biome presents crystallization caused by a volatile-rich melt. It can only generate on terrestrial planets with volcanism between low and high, and with a crust composition that contains volatile elements. The level of volcanism dictates the weighting: low is 0.5, medium is 0.8, high is 1.1 This weighting is multiplied by the percent (1/x) of volatiles in the crust.

Volatile elements are any elements with a boiling point below 1200 Kelvin. The presence of liquid bodies also indicates the presence of volatiles, with a 60% hardcoded value.

**** Magmatic
The Magmatic geo-biome represents partial melting of the crust. It can only generate on terrestrial or metallic planets with medium to extreme volcanism. The level of volcanism dictates the weighting: medium is 0.4, high is 0.7, and extreme is 0.9

*** Minerals
Based on the chemical composition of the crust, we can determine what minerals should be present on any given planet, and then place them based on the geo-biomes available. We do this by generating plausible minerals using simplified valence chemistry.
The number of minerals generated is based on the "activity" of world, as well as it's class.
For terrestrial worlds, start with 10 minerals.
For metallic worlds, start with 14 minerals.
For ice worlds, start with 2 minerals.
For water worlds, start with 5 minerals.
Then if we have a light atmosphere, add 3 minerals to the count. If we have an earth-like atmosphere, add 6 minerals to the count. If we have an extreme atmosphere, add 9 minerals.
For volcanism, if we have low volcanism add 2 minerals. If we have medium volcanism, add 5 minerals. If we have high volcanism, add 10 minerals. If we have extreme volcanism, add 20 minerals.

We then divide the number of minerals into "categories" of minerals to generate.
Currently, we pre-filter the mineral list to only abiotic minerals.
1 third of the total minerals, rounded down, are dedicated to the non-negotiable rock-forming minerals of the planet. These can be any rock-forming minerals from the master list that are made up of elements present in the crust. The specific modes permitted here are 5-6, 7-10, 19-21, 24-26, 31, 34, 38-43.
These minerals are weighted by the abundance of their constituent elements, and we randomly select the amount required using this weighting. If the planet is an ice planet, one of these minerals is automatically set to ice.

Next we subtract a random number from the total mineral count, anywhere from 0 to 3. If this subtraction leaves 0 remaining minerals, skip this step. Otherwise, this selected amount becomes randomly selected "rare" minerals that are capable of forming given the possible geo-biomes and composition.
Rare minerals are minerals that are either native elements, minerals that exist in only 1 mode, have a narrow formation window (modes 29, 30, 54-57, 18), or depend on elements that are scarce in the composition (sort abundance by percent reversed to find these).

And as for what minerals are capable of forming given each geo-biome, the remaining mineral count is divided by all possible geo-biomes on the planet and we determine a number of minerals that can occur per biome. These are based primarily off [[https://www.mindat.org/paragen.php][paragenetic modes]], and filtered to and weighted by the crust composition elements. 

**** Impact
Modes 1-4, 29-30, 51 can generate in the Impact biome.

Additionally, though not included in the generator but as a note, modes 5-6 may be found as deposits in this biome.

**** Primordial
Modes 1-6 can generate in the Primordial biome.

**** Supergene
Modes 22-23, 28, 47-48 can generate in the Supergene biome.

**** Metamorphic
Modes 6, 9, 13, 31-33, 38-41, 43, 51 can generate in the Metamorphic biome.

**** Sedimentary
17, 21, 24-46 can generate in the Sedimentary biome.

**** Fumarolic
Modes 11 and 45, 27 can generate in the Fumarolic biome.

**** Hydrothermal
Modes 6, 10, 13-14, 16, 22, 32, 42, 44, 46 can generate in low temperature Hydrothermal biomes.
Modes 12, 15, 32-33, 41 can generate in high temperature Hydrothermal biomes.

**** Pegmatitic
Mode 34 and 27 can generate in Pegmatitic biomes.

**** Magmatic
Modes 7-9, 19-20, 27, 35-38 can generate in Magmatic biomes.

*** Surface Biomes
Each chunk has a surface biome randomly chosen from a set derived from the geo-biome. Surface biomes are different for terrestrial, metallic, and ice worlds as opposed to water worlds.

These biomes also determine the sorts of surface features that can generate within the chunk. For water worlds, these are submarine.

**** Terrestrial, Metallic, Ice
***** Primordial
****** Ancient Highlands
The planet's original, battered crust. Heavy cratering, rugged landscape.
****** Impact Basin
A single vast circular depression from a massive impact, with concentric rings and a flat floor.
***** Magmatic
****** Shield Volcano
A broad, gently sloping mountain.
****** Stratovolcano
A classic volcano built from alternating layers of lava and ash.
****** Volcanic Plateau
An elevated plain formed by thick layers of lava that flooded from fissures, creating flat top mountains.
****** Lava Plain
A flat terrain covered by young lava flows.
***** Pegmatitic
****** Pegmatite DIke Swarm
A network of mineral veins cutting through old rock, marked by large protruding crystals.
****** Granitic Core Complex
The exposed, deep interior of a solidifed magma chamber, showing large crystals.
***** Fumarolic
****** Fumarole Field
A rugged area pockmarked by gas vents and brightly coloured mineral crusts.
****** Solfatara
A type of fumarole field creating extensive sulfar deposits.
***** Hydrothermal
Temperature is irrelevant for surface biome generation.
****** Geyser Basin
A volatile area of hot springs, geysers, and mineral terraces.
****** Epithermal Vein Field
A rocky landscape crisscrossed by prominent mineral veins.
***** Sedimentary
****** Alluvial Fan
A fan-shaped deposit of sediment where a steep stream slows upon entering a flat plain.
****** Fluvial Channel
The active or fossilized path of a river system.
****** Lacustrine Basin
A dry or wet lakebed with fine layered sediments.
****** Aeolian Dune Field
A desert of sand and other grains sculpted by wind into rolling dunes.
***** Metamorphic
****** Collisional Mountain Belt
A linear range of high, folded, and faulted mountains.
****** Metamorphic Dome
A large, rounded uplift.
***** Supergene
****** Gossan Cap
A hilltop marking the weathered top of a large ore deposit.
****** Lateritic Plateau
A tableland capped by a thick, hard layer of iron or aluminium oxides.
***** Impact
****** Complex Crater
A large crater with a central peak or peak ring.
****** Rayed Crater
A relatively fresh impact crater with bright, linear streaks of ejecta.
****** Palimpsest
A fait, ghost-like circular scar where an ancient crater's topography has been erased over time.
**** Water Worlds
***** Primordial
****** Abyssal Plain
Deep, dark sediment-covered ocean floor.
****** Seamount Province
Isolated, often conical underwater mountains. Remnants of ancient volcanic activity.
***** Magmatic
****** Submarine Volcano
An active volcano built on the ocean floor.
****** Oceanic Plateau
A vast, elevated region of the seafloor formed by massive outpourings of lava.
****** Pillow Lava Field
Expansive areas of the seafloor covered in characteristic bulbous pillow lava formations.
***** Pegmatitic
****** Subaqueous Pegmatite Still
A rare layer of crystals formed beneath the seabad, exposed by erosion.
***** Fumarolic
****** Submarine Fumarole Field
Gas vents on the seafloor.
****** Shallow Water Gas Vent Plume Zone
Areas where bouyant gas plumes rise through the water column, creating columns of bubbles and mineral sediment.
***** Hydrothermal
****** Deep-sea Vent Field
Cluster of black smoker or white smoke chimneys on the seafloor.
****** Hydrothermal Mound Complex
Large, layered deposits of minerals built up from long-lived venting.
****** Shallow Hydrothermal System
Venting mineral precipitation and unique chemistry in shelf-sea environments.
***** Sedimentary
****** Submarine Fan
A large, fan-shaped accumulation of sediment.
****** Pelagic Sediment Plain
Vast, flat areas of the deep ocean covered by slow, continuous rain of fine clay.
***** Metamorphic
****** Subduction Complex
A region of intensely deformed, mixed, and metamorphosed rocks on the seafloor.
****** Oceanic Core Complex
A dome-like exposure of deep mantle and crustal rocks.
***** Supergene
****** Seafloor Weathering Crust
A layer of enriched rock at shallow depths.
***** Impact
****** Submarine Impact Crater
A circular impact structure on the ocean floor.

** Limitations
- Elemental abundances are fully random beyond the top 10.
- Non-unary system generation is not implemented because I don't want to write the orbit math for it.
- Only main sequence stars are currently generated.
- Planetary orbits are circular, because I'm too lazy to do it otherwise.
- Volcanism is only based on tidal forces.
- Ocean composition possibilities are hardcoded.
- Ocean composition doesn't account for atmospheric pressure.

* FAQ
**  What does "semi-realistic" mean?
I am not an astrophysicist, geologist, or any other qualified position. I am just a computer programmer who wants to recreate Elite: Dangerous' galaxy generation logic. "Semi-realistic", in the context of this project, means "close enough" to realistic for simulation purposes or for the meta-setting this is inspired by (see the Stardate Legacy repo for more details). I am open to pull requests to correct any incorrect calculations or information, particularly from people with credentials in the field of whatever you are trying to correct.

