Files
settled-reach/tooling/planet-gen/biome_config.py
T
jpmschweitzerandClaude Opus 4.6 f84275edf3 feat(assets): planet generator pipeline — heightmap + globe from wiki data
Full terrain-to-render pipeline at tooling/planet-gen/:
- body_definition_parser: reads system index.md → body definitions
- planet_simulation: FBM + Voronoi ridges, Whittaker biome classification,
  D8 river routing, physics-driven craters (atmo × tectonics scaling)
- render_heightmap: 4096×2048 cartographic maps with hillshade
- planet_renderer: 512×512 globe with terrain UV mapping, clouds, rings
- biomes.toml: externalized color/classification tables (single source)
- scaffold_bodies: creates per-body index.md with YAML frontmatter
- batch: unattended processing with error handling, resume, determinism check

Supports all body types: temperate, arid, frozen, volcanic, barren,
oceanic, gas giant (banded + ringed), and moons (half-size, grey, cratered).

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

100 lines
4.1 KiB
Python

"""
biome_config.py — loads biomes.toml and provides lookup structures.
Single source of truth for biome classification, colors, and rendering
parameters. All three pipeline modules import from here instead of
maintaining their own hardcoded tables.
Usage:
from biome_config import (
WHITTAKER_TABLE, CLASS_T_BAND, BIOME_PALETTE,
STAR_TINTS, ATMO_COLORS, GAS_PALETTES,
EXOTIC_CLASSES, CRATER_SCALING, RIVER_RGB, COAST_RGB,
)
"""
import os
from pathlib import Path
try:
import tomllib
except ModuleNotFoundError:
import tomli as tomllib # Python < 3.11 fallback
_CONFIG_PATH = Path(__file__).resolve().parent / "biomes.toml"
def _load():
with open(_CONFIG_PATH, "rb") as f:
return tomllib.load(f)
_CFG = _load()
# ── Whittaker table ──────────────────────────────────────────────────
# List of (temp_lo, temp_hi, moist_lo, moist_hi, class_id) tuples.
WHITTAKER_TABLE = [
(w["temp_lo"], w["temp_hi"], w["moist_lo"], w["moist_hi"], w["id"])
for w in _CFG["whittaker"]
]
# ── Temperature bands per planet class ───────────────────────────────
CLASS_T_BAND = {
k: tuple(v) for k, v in _CFG["temperature_bands"].items()
}
# ── Biome color palette ──────────────────────────────────────────────
# {class_id: {"cartographic": (R,G,B), "photographic": (R,G,B), "name": str}}
BIOME_PALETTE = {}
for key, val in _CFG["biome_colors"].items():
cid = int(key)
BIOME_PALETTE[cid] = {
"cartographic": tuple(val["cartographic"]),
"photographic": tuple(val["photographic"]),
"name": val.get("name", f"class_{cid}"),
}
# Max class ID for array sizing
MAX_BIOME_ID = max(BIOME_PALETTE.keys())
def build_biome_rgb(mode: str = "cartographic") -> dict:
"""Returns {class_id: (R, G, B)} for the given render mode."""
return {k: v[mode] for k, v in BIOME_PALETTE.items()}
# ── Render colors ────────────────────────────────────────────────────
RIVER_RGB = tuple(_CFG["render_colors"]["river"])
COAST_RGB = tuple(_CFG["render_colors"]["coastline"])
# ── Star tints ───────────────────────────────────────────────────────
STAR_TINTS = {k: tuple(v) for k, v in _CFG["star_tints"].items()}
# ── Atmosphere colors ────────────────────────────────────────────────
ATMO_COLORS = {k: tuple(v) for k, v in _CFG["atmosphere_colors"].items()}
# Planet classes without atmosphere glow
for _no_atmo in ("barren", "moon", "gas_giant", "gas_giant_ringed"):
ATMO_COLORS.setdefault(_no_atmo, None)
# ── Gas giant palettes ───────────────────────────────────────────────
GAS_PALETTES = {
k: [tuple(band) for band in v]
for k, v in _CFG["gas_palettes"].items()
if k != "selection_order"
}
# Locked selection list — order determines which body gets which palette.
# Only append, never reorder or remove.
GAS_PALETTE_SELECTION = list(_CFG["gas_palettes"]["selection_order"])
# ── Exotic biome class IDs ───────────────────────────────────────────
EXOTIC_CLASSES = dict(_CFG["exotic_classes"])
# ── Crater scaling ───────────────────────────────────────────────────
CRATER_SCALING = {
"base_count": _CFG["crater_scaling"]["base_count"],
"atmosphere": dict(_CFG["crater_scaling"]["atmosphere"]),
"tectonics": dict(_CFG["crater_scaling"]["tectonics"]),
}