## Generating Terrestrial Planets Pt.1

This is related to Semi-Empirical Stellar Equations. I have had some questions easily answered, and others which are difficult or impossible to get the kind of accuracy I want.

I’m going to order what I’ve learned by the order I am planning to use these equations, marking equations loosely based on empirical data with an asterisk, and double asterisks for things I’ve completely made up to simplify calculation.

• Radius of Surface* (Rsurface):
5500km mean, 1550km standard deviation
• Density* [based on common rock types] (Dplanet):
4.7g/cm3 mean, 0.55g/cm3 standard deviation
• Volume [assumes a perfect sphere] (Vplanet):
4/3 * π * Rsurface3
• Mass (Mplanet):
Dplanet * Vplanet
• Surface Gravity (gsurface):
6.673×10-11Nm2kg-2 * Mplanet / Rsurface2
• Surface Area [assumes a perfect sphere]:
4 * π * Rsurface2
• Atmospheric Pressure Reduction Rate** (Pr):
Pr [unit: none] = -0.00011701572 [unit: s2 / m2] * gsurface
• Atmospheric Halving Height** (hd):
hd [unit: m-1] = ln(2) / Pr
• Atmospheric Volume at Constant Pressure** (Vsim):
(4/3 * π * (Rsurface + hd)3 – Vplanet) * 2
• Surface Atmospheric Pressure (Psurface):
Psurface [unit: kPa] = ???
• Lowest Safe Orbital Height** (h0):
h0 [unit: m] = ln(1.4×10-11 / Psurface) / Pr
• True Atmospheric Volume (Vatm):
4/3 * π * (Rsurface + h0)3 – Vplanet

Vsim exists to support a simulation of an entire planet’s atmospheric contents using my simple fluid simulation mechanic. The magic constant used to calculated Pr is based on Earth’s atmosphere, it can be changed to set an exact “atmospheric height” while maintaining other properties of this simulation.

• Atmospheric Pressure at Altitude** (Paltitude):
Paltitude [unit: kPa] = Psurface * exp(Pr * maltitude) [Pr may be -Pr, I don’t remember]

This post is obviously incomplete, but it’s been a while since I posted anything here, and I felt like I should go ahead and share what I’ve been up to.

## Semi-Empirical Stellar Equations

I’ve spent a lot of time trying to answer certain questions in astronomy, where I just want a rough approximation for the purpose of a simulation, and don’t need an exact answer. These are some of the equations I’ve come up with.

### Yerkes Classes’ T/Mv Relations

These equations are shown as functions where x is temperature in Kelvin, and f(x) is absolute magnitude (visual). Most are valid from 2400 K to a little bit past 30000 K, the exceptions are noted. For the hypergiants and white dwarfs, the range is within an elliptical region, of which these functions define the major axis; for all others, they are a trend line along a Yerkes classification.

• Hypergiants (0):
f(x) = -8.9
• Supergiants (Ia):
f(x) = -0.00135x3 + 0.0233x2 + 0.0187x – 7.349
• Supergiants (Ib):
f(x) = 0.00329x3 – 0.0962x2 + 0.829x – 7.209
• Bright Giants (II):
f(x) = 0.00557x3 – 0.166x2 + 1.505x – 6.816
• Giants (III):
f(x) = 0.0135x3 – 0.373x2 + 3.019x – 7.233
• Subgiants (IV):
f(x) = -0.151x2 + 2.216x – 5.128 (4450-100000 K only)
• Dwarfs (V):
f(x) = 0.00193x5 – 0.0615x4 + 0.742x3 – 4.257x2 + 12.439x – 12.996 (note: this one is the least accurate)
• Subdwarfs (VI):
f(x) = 0.131x3 – 3.275x2 + 27.576x – 71.7 (3050-6000 K only)
• White Dwarfs (VII):
f(x) = 0.489x + 10.01 (4450-30000 K only)

### Simple Conversions

• Absolute Magnitude (visual) → Luminosity (solar luminosities):
Lsun = 100 * exp(-0.944 * Mv)
Accurate between 0-10 Mv. Probably continues accuracy relatively well.
• Main Sequence Luminosity / Mass Relation:
Lstar / Lsun = (Mstar / Msun)3.5
Lstar = ( 3.68 * ln(Mstar) – 0.244 )e
(The second equation applies to all stars.)
• Mass / Lifetime Relation:
Tyears = ( 23.4 – 2.68 * ln(Mstar) )e
(This applies to all stars.)

Spectral filters are used to help classify stars. Ultraviolet, Blue, Visual, Red, and Infrared. Objects are listed in different indexes:

• UV for the hottest objects (stellar remnants, galaxies)
• BV (the majority of stars)
• RI for the coolest (LTY “stars” and below)

### Equations I no longer recommend

Provided for completeness, in case they are found to be useful.

• Temperature (K) → Absolute Magnitude (visual):
Mv = 35.463 * exp(-0.000353 * T)
Roughly accurate between 2000-50000 Kelvin. Probably doesn’t continue accuracy at hotter temperatures. Previously this was at the top of this post, now I am not sure why (perhaps the simplicity). The Yerkes’ classifications are a better system.
• B-V index (x) → Temperature (K):
T = -772.2x3 + 3152x2 – 6893x + 9500
Sorta accurate between 0-2. (This equation I am least comfortable with, and don’t plan to use.)

## cc-pkg: A ComputerCraft Package Manager

(The latest information and a quick reference is located here.)

ComputerCraft is a Minecraft mod that adds Lua-based computers. Over time, many programs have been created, and several package managers have come and gone. As I write this, all that I have seen are gone – their original authors have moved on, and shut down the servers hosting packages.

Now it’s my turn to sell you a package manager. Unlike the others, I expect this to remain viable – even if I’m gone from the picture. If you want to skip to trying it, here’s how it’s installed (and how to ask for help):

``````pastebin get 9Li3u4Rc /bin/pkg
/bin/pkg help``````

(I’d also recommend installing the `unix-like` package, which adds /bin to your path, along with a few other small tweaks.)

### Why is cc-pkg different?

1. It is built on ComputerCraft’s pastebin integration.
2. It does not require a maintainer.
3. It is extremely simple – and flexible.

cc-pkg has the same three sub-commands of the default `pastebin` program: get, run, and put*. They each do exactly what you’d expect them to do, except they can use names as well as pastebin IDs. Names consist of alphanumeric characters and dashes, and there are two file types cc-pkg can recognize and utilize:

Both are plaintext lists of the form `key=value`. The first is called a `package` and has file paths (all starting with a forward slash) as keys, with names or pastebin IDs as values. This is how cc-pkg knows which files to download and where to put them. The second type is called a `list`, and contains names as keys, with names or pastebin IDs as values. Lists are saved to a local file cc-pkg uses to resolve package names – overwriting any existing entries with the same package name, which is how updating is done.

With just those core features, I think the system is viable.

*The put command is not implemented as of version 1.4.2 1.5.10, the latest at the time of writing finishing updating this introduction.

### Command Extensions

On top of this, if a file is saved to `/lib/pkg-commands/<name>` and a user runs `pkg <name>`, that file will be run with the other arguments. This allows adding new functions, and overwriting the core functions to add additional features, if desired.

### Under the Hood

cc-pkg keeps metadata through the following files:

• `/etc/pkg/names.list`: The master names list. (How cc-pkg knows what to download.)
• `/etc/pkg/ids.list`: Download history of cc-pkg. (An ordered list of every pastebin ID successfully downloaded.)
• `/etc/pkg/<package-name>`: Each package is saved here by name, in addition to the files it specifies.

It uses global functions so that it can be loaded as an API to make a more advanced package management system on top of it – or just to make programs automatically download requirements using cc-pkg.

• `get(name_or_id, path)`: The core function that installs anything (package/list/file). (`path` is optional.)
• `down(id)`: Downloads from a pastebin ID, returning its content or throwing an error.
• `save(path, data)`: Write to file. (Note: This is not a binary write.)
• `append(path, data)`: Append to file. (Note: This is not a binary write.)
• `id(name_or_id)`: Recursively checks the master names list until a pastebin ID is returned. (Note: On failure, returns the last name resolved.)
• `type(data)`: Recognizes data as a `package`, `list`, or `unknown` type, and returns that type.
• `src(data)`: Combines this data with existing names (overwriting if duplicates exist). (If `get` is used, `src` will be called when needed automatically.)

An example of this is the `pkg-search` package, which adds a search command to look for specific package names within the master list.

### Example Packages & Lists

• A basic package looks like this:
`/startup=XsYUCf5b`
This is the `multi-startup` package, which makes the computer run all files in `/.startup` when started. It is required for several of my packages to function.
• A package with a dependency looks like this:
`/etc/pkg/multi-startup=multi-startup/.startup/unix-like.lua=iG9idFgk`
This is the `unix-like` package, which requires `multi-startup` to function, and makes the computer operate more like a UNIX computer. (Due to how cc-pkg works, specifying to download a package anywhere will install that package. By convention and for consistency, I use the location cc-pkg installs packages by default.)
• A “meta package” (a package that only lists dependencies) looks like this:
`/etc/pkg/ping=ping/etc/pkg/touch=touch/etc/pkg/which=which`
This is only part of the `unix-meta` package, which lists many packages that make a computer operate more like a UNIX computer. Packages are very flexible! They don’t even have to install anything themselves.
• A list looks like this:
`pocket-computer-chat=qtnShai4pocketgps=8SXT1hDN`
This is the current list of pocket packages at the time of writing. (These can be added by running `pkg get pocket-packages`.) Remember, lists can reference other names (e.g. `unix-stuff=unix-meta`), allowing one to create aliases for existing packages & lists.

## A Journey into λCalculus

I’m playing around in Minetest, and I have an idea. In order to execute this idea, I’m going to need a simple programming language. Asking Google… implementing a simple programming language

7 lines of code, 3 minutes: Implement a programming language from scratch
Sounds good! Ridiculously simple, fast, and gives us a fully usable language. (I would’ve understood brainfuck better..) Let’s see what this language looks like:

``````(λ v . e)   anonymous function with argument v and returning e
(f v)       call function f with argument v
(λ a . a)   example: identity function (returns its argument)

And the scary one:
(((λ f . (λ x . (f x))) (λ a . a)) (λ b . b))``````

Seems okay until I get to understanding that last example. If you’re curious about the steps I went through before I finally figured it out, here are my notes. I’m gonna skip to the good part:

``````(((λ f . (λ x . (f x))) (λ a . a)) (λ b . b))
two identity functions, let's name them I, & remove excess parenthesis
(λ f . (λ x . (f x))) I I
the syntax is still confusing me, let's make an "F" function
F(x) -> return (λ x . (f x))
F I I                          equivalent to ((F I) I)
substituting the function (identity) into our definition gives us
(λ x . (I x))                  which..is actually the same as the identity function
I(I)                           ..it all comes to returning the identity function

λ x . x``````

Now, at this point I’ve learned a few small tricks for my understanding, as well as how lambda calculus works in general.

### Reduction

Solving a lambda calculus program is made of three (or 2.5) steps called reductions:

• η-conversion (eta): Replace equivalent functions with simpler forms (λ x . f x) -> f
• β-reduction (beta): Substitution (λ a . a) x -> x (essentially, THIS is solving it)
• α-conversion (alpha): Rename conflicting names (λ a . a b) (λ a . a) -> (λ a . a b) (λ c . c)

### References

This is where my journey ends for now. I started studying lambda calculus because of a desire to implement a simple programming language, but this will likely not satisfy my needs..at least not in this form. Here are additional resources:

## Switches Suck

I don’t like switch statements, in any language. They seem unnecessarily verbose and error-prone, in fact I forgot the break statements in my example below on the first draft. Most of the time, you don’t want the fall-through feature, but you have to remember that extra word for each case to prevent that.

``````switch (n)
{
case 1:
// something useful
break;
case 2:
// another useful option
break;
default:
// nothing matched
}``````

I also really hate the indenting used in most examples (including my own), as it makes it more difficult to visually parse. I prefer to just create an object with keys based on the possible values, and access what you need directly.

``````-- we're gonna pretend these are useful functions dependent on a star's type..something to do with heat?
local default = {}           -- used for a unique key
local heat = {
A = function() end,        -- pretend these are full of useful code
B = function() end,
G = function() end,        -- and so on
[default] = function() end -- default which can't be accidentally chosen
}

-- make sure we don't error, and call default if needed
if heat[star.type] then
heat[star.type]()
else
heat[default]()
end``````