Files
settled-reach/tooling/planet-gen/biomes.toml
T
jpmschweitzerandClaude Opus 4.6 db241b88bd refactor(schema): rename biome_summary to planet_class (D-188)
"Biome" describes per-zone vegetation classification (Whittaker table).
"Planet class" describes overall planetary character. The conflation
caused the planet generator to misclassify ~270 bodies as barren.

Scope: systems.db column, schema SQL, Rust atlas code, wiki table
headers (Biome → Class), atlas proposal JSONs, all docs/decisions,
tooling scripts. Also normalizes atmosphere vocabulary (breathable →
standard) and expands planet class mapping to all 26 wiki values.
Unknown classes default to temperate for modder safety.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 17:10:35 +02:00

334 lines
13 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Planet Generator — Biome & Color Configuration
#
# Single source of truth for biome classification, color palettes,
# and rendering parameters. Loaded by planet_simulation.py,
# render_heightmap.py, and planet_renderer.py.
#
# Edit this file to adjust colors without touching Python code.
# ─────────────────────────────────────────────────────────────────────
# Whittaker biome classification table
#
# Temperature axis is ABSOLUTE KELVIN — not normalized per-world.
# Moisture axis is [0, 1].
# Order matters: first match wins.
# ─────────────────────────────────────────────────────────────────────
[[whittaker]]
id = 5
name = "tropical_rainforest"
temp_lo = 303
temp_hi = 999
moist_lo = 0.65
moist_hi = 1.00
[[whittaker]]
id = 6
name = "tropical_seasonal"
temp_lo = 303
temp_hi = 999
moist_lo = 0.35
moist_hi = 0.65
[[whittaker]]
id = 7
name = "savanna"
temp_lo = 293
temp_hi = 999
moist_lo = 0.18
moist_hi = 0.35
[[whittaker]]
id = 15
name = "hot_desert"
temp_lo = 303
temp_hi = 999
moist_lo = 0.00
moist_hi = 0.18
[[whittaker]]
id = 9
name = "temperate_deciduous"
temp_lo = 283
temp_hi = 308
moist_lo = 0.55
moist_hi = 1.00
[[whittaker]]
id = 8
name = "temperate_grassland"
temp_lo = 278
temp_hi = 303
moist_lo = 0.30
moist_hi = 0.55
[[whittaker]]
id = 10
name = "temperate_rainforest"
temp_lo = 278
temp_hi = 303
moist_lo = 0.60
moist_hi = 1.00
[[whittaker]]
id = 9
name = "temperate_deciduous_cool"
temp_lo = 273
temp_hi = 293
moist_lo = 0.30
moist_hi = 0.60
[[whittaker]]
id = 12
name = "shrubland"
temp_lo = 278
temp_hi = 303
moist_lo = 0.10
moist_hi = 0.30
[[whittaker]]
id = 14
name = "subtropical_desert"
temp_lo = 283
temp_hi = 308
moist_lo = 0.00
moist_hi = 0.18
[[whittaker]]
id = 13
name = "temperate_desert"
temp_lo = 273
temp_hi = 293
moist_lo = 0.00
moist_hi = 0.30
[[whittaker]]
id = 11
name = "boreal_taiga"
temp_lo = 253
temp_hi = 278
moist_lo = 0.40
moist_hi = 1.00
[[whittaker]]
id = 11
name = "boreal_dry"
temp_lo = 253
temp_hi = 278
moist_lo = 0.15
moist_hi = 0.40
[[whittaker]]
id = 16
name = "tundra"
temp_lo = 243
temp_hi = 263
moist_lo = 0.00
moist_hi = 1.00
[[whittaker]]
id = 16
name = "cold_tundra"
temp_lo = 233
temp_hi = 253
moist_lo = 0.20
moist_hi = 1.00
[[whittaker]]
id = 17
name = "ice_snow"
temp_lo = 200
temp_hi = 243
moist_lo = 0.00
moist_hi = 1.00
[[whittaker]]
id = 17
name = "ice_cold_dry"
temp_lo = 243
temp_hi = 273
moist_lo = 0.00
moist_hi = 0.15
# ─────────────────────────────────────────────────────────────────────
# Temperature bands per planet class (Kelvin)
# Fiction wins over physics — temperature is clamped to these bands.
# ─────────────────────────────────────────────────────────────────────
[temperature_bands]
# Core classes
temperate = [275, 305]
oceanic = [278, 300]
forest = [275, 308]
arid = [295, 340]
frozen = [210, 265]
volcanic = [290, 380]
barren = [180, 380]
# Extended classes
temperate_terminator = [260, 310] # sharp day/night gradient, wide band
cold_arid = [240, 290] # cold desert (Mars-analog)
hot_arid = [310, 360] # scorching desert
tropical = [295, 315] # hot and wet
boreal = [245, 278] # cold forest / taiga
# ─────────────────────────────────────────────────────────────────────
# Biome color palette
#
# Each biome class has two color modes:
# cartographic — map colors (National Geographic style, readable)
# photographic — orbital appearance (dark, muted, realistic)
#
# RGB values 0-255.
# ─────────────────────────────────────────────────────────────────────
[biome_colors]
# Ocean
0 = { name = "ocean_deep", cartographic = [ 80, 155, 190], photographic = [ 18, 45, 80] }
1 = { name = "ocean_mid", cartographic = [110, 185, 215], photographic = [ 28, 72, 115] }
2 = { name = "ocean_shallow", cartographic = [150, 210, 230], photographic = [ 42, 105, 145] }
# Coast / lowland
3 = { name = "coast", cartographic = [155, 185, 130], photographic = [ 90, 108, 75] }
4 = { name = "lowland", cartographic = [120, 165, 100], photographic = [ 72, 98, 58] }
# Tropical
5 = { name = "tropical_rainforest", cartographic = [ 50, 140, 65], photographic = [ 12, 38, 18] }
6 = { name = "tropical_seasonal", cartographic = [ 90, 170, 75], photographic = [ 28, 65, 28] }
7 = { name = "savanna", cartographic = [175, 210, 105], photographic = [108, 118, 55] }
# Temperate
8 = { name = "temperate_grassland", cartographic = [190, 210, 110], photographic = [118, 128, 62] }
9 = { name = "temperate_deciduous", cartographic = [ 70, 148, 70], photographic = [ 22, 55, 28] }
10 = { name = "temperate_rainforest", cartographic = [ 45, 125, 65], photographic = [ 15, 45, 22] }
11 = { name = "boreal_taiga", cartographic = [ 28, 88, 55], photographic = [ 8, 30, 18] }
12 = { name = "shrubland", cartographic = [168, 168, 95], photographic = [ 98, 88, 55] }
# Desert
13 = { name = "temperate_desert", cartographic = [215, 200, 155], photographic = [155, 138, 98] }
14 = { name = "subtropical_desert", cartographic = [210, 165, 85], photographic = [148, 108, 62] }
15 = { name = "hot_desert", cartographic = [215, 138, 55], photographic = [162, 98, 42] }
# Cold
16 = { name = "tundra", cartographic = [198, 185, 145], photographic = [ 95, 88, 72] }
17 = { name = "ice_snow", cartographic = [235, 238, 242], photographic = [218, 228, 238] }
18 = { name = "mountain_rock", cartographic = [148, 135, 120], photographic = [ 88, 80, 72] }
# Volcanic
19 = { name = "lava_field", cartographic = [ 55, 32, 22], photographic = [ 38, 22, 15] }
# Exotic / extremophile
20 = { name = "chemosynthetic_mat", cartographic = [ 45, 88, 52], photographic = [ 18, 38, 22] }
21 = { name = "thermophilic_field", cartographic = [118, 72, 40], photographic = [ 78, 45, 22] }
22 = { name = "sulfuric_scrub", cartographic = [148, 130, 58], photographic = [ 98, 85, 35] }
23 = { name = "cryptobiotic_crust", cartographic = [130, 118, 100], photographic = [ 78, 70, 58] }
24 = { name = "lithic_pioneer", cartographic = [138, 125, 110], photographic = [ 82, 75, 65] }
25 = { name = "ash_field", cartographic = [ 68, 58, 52], photographic = [ 42, 35, 30] }
26 = { name = "ice_shelf", cartographic = [245, 246, 248], photographic = [235, 238, 242] }
# Dry terrain (atmosphere gate — non-vegetated)
27 = { name = "dust_plain", cartographic = [195, 165, 115], photographic = [175, 142, 95] }
28 = { name = "rocky_highland", cartographic = [175, 145, 105], photographic = [152, 122, 85] }
29 = { name = "warm_dust", cartographic = [210, 175, 120], photographic = [188, 155, 105] }
30 = { name = "cold_rock", cartographic = [160, 140, 115], photographic = [135, 118, 95] }
# Lunar terrain (grey rock)
31 = { name = "lunar_highland", cartographic = [165, 165, 162], photographic = [138, 138, 135] }
32 = { name = "lunar_mare", cartographic = [120, 120, 118], photographic = [100, 100, 98] }
33 = { name = "lunar_midland", cartographic = [145, 145, 142], photographic = [118, 118, 115] }
# ─────────────────────────────────────────────────────────────────────
# Rendering colors (not biome-specific)
# ─────────────────────────────────────────────────────────────────────
[render_colors]
river = [ 80, 140, 200]
coastline = [ 30, 45, 35]
# ─────────────────────────────────────────────────────────────────────
# Star tints — subtle color shift from stellar type
# Applied multiplicatively to surface lighting.
# ─────────────────────────────────────────────────────────────────────
[star_tints]
O = [0.90, 0.92, 1.00]
B = [0.94, 0.96, 1.00]
A = [0.97, 0.98, 1.00]
F = [1.00, 0.99, 0.97]
G = [1.00, 0.97, 0.93]
K = [1.00, 0.93, 0.85]
M = [1.00, 0.88, 0.78]
# ─────────────────────────────────────────────────────────────────────
# Atmosphere rim colors per planet class (globe renderer)
# null = no atmosphere glow
# ─────────────────────────────────────────────────────────────────────
[atmosphere_colors]
temperate = [0.45, 0.65, 1.00]
oceanic = [0.40, 0.60, 1.00]
forest = [0.42, 0.68, 0.80]
arid = [0.90, 0.72, 0.50]
martian = [0.82, 0.58, 0.40]
frozen = [0.75, 0.88, 1.00]
volcanic = [0.55, 0.40, 0.30]
# ─────────────────────────────────────────────────────────────────────
# Gas giant band palettes (globe renderer)
# Each palette is a list of RGB band colors.
# ─────────────────────────────────────────────────────────────────────
[gas_palettes]
jovian = [[0.78, 0.62, 0.44], [0.60, 0.44, 0.30], [0.88, 0.76, 0.60],
[0.72, 0.55, 0.38], [0.92, 0.84, 0.70], [0.55, 0.40, 0.28]]
neptunian = [[0.25, 0.45, 0.75], [0.35, 0.58, 0.85], [0.18, 0.35, 0.65],
[0.42, 0.65, 0.90], [0.20, 0.40, 0.70], [0.50, 0.70, 0.92]]
saturnian = [[0.82, 0.74, 0.55], [0.75, 0.66, 0.48], [0.88, 0.80, 0.62],
[0.70, 0.62, 0.44], [0.92, 0.86, 0.68], [0.65, 0.58, 0.42]]
icy = [[0.78, 0.85, 0.92], [0.70, 0.80, 0.90], [0.85, 0.90, 0.95],
[0.65, 0.75, 0.88], [0.90, 0.93, 0.97], [0.60, 0.70, 0.85]]
sulfuric = [[0.88, 0.80, 0.22], [0.80, 0.65, 0.18], [0.92, 0.86, 0.35],
[0.75, 0.60, 0.15], [0.85, 0.75, 0.28], [0.70, 0.55, 0.12]]
infernal = [[0.65, 0.18, 0.12], [0.45, 0.12, 0.08], [0.80, 0.25, 0.15],
[0.55, 0.15, 0.10], [0.72, 0.20, 0.12], [0.38, 0.10, 0.06]]
# Locked selection list for deterministic random palette assignment.
# Order matters — changing this changes which body gets which palette.
# Only add to the end. Never reorder or remove.
selection_order = ["jovian", "neptunian", "saturnian", "icy", "sulfuric", "infernal"]
# ─────────────────────────────────────────────────────────────────────
# Crater scaling factors
# atmosphere: fraction of impactors that survive entry
# tectonics: fraction of craters preserved (not resurfaced)
# Final crater count = base_count × atmo_factor × tect_factor
# ─────────────────────────────────────────────────────────────────────
[crater_scaling]
base_count = 300
[crater_scaling.atmosphere]
none = 1.0
thin = 0.6
standard = 0.25
thick = 0.08
[crater_scaling.tectonics]
none = 1.0
low = 0.7
active = 0.3
extreme = 0.1
# ─────────────────────────────────────────────────────────────────────
# Exotic biome class IDs (modifier stack in compute_biome)
# ─────────────────────────────────────────────────────────────────────
[exotic_classes]
chemosynthetic_mat = 20
thermophilic_field = 21
sulfuric_scrub = 22
cryptobiotic_crust = 23
ash_field = 25
lava_field = 19
ice_shelf = 26