Skip to content

Commit 400f81f

Browse files
committed
Rebalance biome climate bands to the measured noise distribution
ClimateNoise (OpenSimplex2 FBm) concentrates temperature/humidity near 0 (measured p5..p95 = -0.54..+0.54; see mod/tools/ClimateProbe), but the biome table's temperature bands assumed a uniform [-1.5,1.5] spread. The HOT cutoff at 0.5 captured only 7% of the map, split four ways and gated to low altitude, so desert/swamp/volcanic each covered under 0.5% — effectively never seen — while COOL hogged 45%. Recalibrated the four temperature bands to measured quantiles (~16/33/26/25%). Every biome is now >=1% of the map: desert 0.40% -> 1.72% savanna 1.73% -> 6.50% volcanic 0.26% -> 1.05% swamp 0.32% -> 1.04% tundra 10.8% -> 8.6% Adds mod/tools/ClimateProbe for measuring the distribution; keeps TerrainPreview's biome classifier in sync.
1 parent 8278e14 commit 400f81f

3 files changed

Lines changed: 73 additions & 19 deletions

File tree

‎mod/src/main/java/com/grandterrain/worldgen/biome/GrandterrainBiomeSource.java‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,16 @@ private float blockYToParam(int blockY) {
146146
private Climate.ParameterList<Holder<Biome>> buildBiomeParameters(
147147
float cTemperate, float cAlpine, float cMountain, float cRocky) {
148148

149-
Climate.Parameter T_FROZEN = Climate.Parameter.span(-1.5f, -0.3f);
150-
Climate.Parameter T_COOL = Climate.Parameter.span(-0.3f, 0.15f);
151-
Climate.Parameter T_WARM = Climate.Parameter.span(0.15f, 0.5f);
152-
Climate.Parameter T_HOT = Climate.Parameter.span(0.5f, 1.5f);
153-
Climate.Parameter T_NOT_FROZEN = Climate.Parameter.span(-0.3f, 1.5f);
149+
// Bands calibrated to the MEASURED ClimateNoise distribution (FBm
150+
// concentrates near 0; see mod/tools/ClimateProbe), not a uniform
151+
// [-1.5,1.5]. Quantile splits ~16/33/26/25% keep every temperature
152+
// tier populated — the old 0.5 HOT cutoff caught only 7% of the map
153+
// and starved deserts/savannas to under 0.5% each.
154+
Climate.Parameter T_FROZEN = Climate.Parameter.span(-1.5f, -0.35f);
155+
Climate.Parameter T_COOL = Climate.Parameter.span(-0.35f, -0.02f);
156+
Climate.Parameter T_WARM = Climate.Parameter.span(-0.02f, 0.25f);
157+
Climate.Parameter T_HOT = Climate.Parameter.span(0.25f, 1.5f);
158+
Climate.Parameter T_NOT_FROZEN = Climate.Parameter.span(-0.35f, 1.5f);
154159

155160
Climate.Parameter C_LOW = Climate.Parameter.span(-1.5f, cTemperate);
156161
Climate.Parameter C_TEMPERATE = Climate.Parameter.span(cTemperate, cAlpine);

‎mod/tools/ClimateProbe.java‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import com.grandterrain.worldgen.noise.ClimateNoise;
2+
3+
import java.util.Arrays;
4+
5+
/**
6+
* Measures the ClimateNoise temperature/humidity distribution and the share
7+
* of the map that falls into each biome-table band. The bands were written
8+
* assuming uniform [-1.5,1.5] noise, but FBm concentrates near 0 — this shows
9+
* how lopsided the resulting biome shares really are.
10+
*/
11+
public final class ClimateProbe {
12+
public static void main(String[] args) {
13+
long seed = args.length > 0 ? Long.parseLong(args[0]) : 20260712L;
14+
ClimateNoise cn = new ClimateNoise(seed);
15+
16+
int N = 1200, step = 24, off = 50000;
17+
float[] temp = new float[N * N];
18+
float[] humid = new float[N * N];
19+
int i = 0;
20+
for (int x = 0; x < N; x++)
21+
for (int z = 0; z < N; z++) {
22+
temp[i] = (float) cn.temperature(off + x * step, off + z * step);
23+
humid[i] = (float) cn.humidity(off + x * step, off + z * step);
24+
i++;
25+
}
26+
report("temperature", temp);
27+
report("humidity", humid);
28+
29+
System.out.println("\ncurrent temperature bands (share of map):");
30+
band("FROZEN (-1.5..-0.3)", temp, -1.5f, -0.3f);
31+
band("COOL (-0.3..0.15)", temp, -0.3f, 0.15f);
32+
band("WARM (0.15..0.5) ", temp, 0.15f, 0.5f);
33+
band("HOT (0.5..1.5) ", temp, 0.5f, 1.5f);
34+
}
35+
36+
static void report(String label, float[] v) {
37+
float[] s = v.clone();
38+
Arrays.sort(s);
39+
int n = s.length;
40+
System.out.printf("%-12s min=%+.3f p5=%+.3f p10=%+.3f p25=%+.3f p50=%+.3f p75=%+.3f p90=%+.3f p95=%+.3f max=%+.3f%n",
41+
label, s[0], s[n / 20], s[n / 10], s[n / 4], s[n / 2], s[3 * n / 4], s[9 * n / 10], s[19 * n / 20], s[n - 1]);
42+
}
43+
44+
static void band(String label, float[] v, float lo, float hi) {
45+
long c = 0;
46+
for (float x : v) if (x >= lo && x < hi) c++;
47+
System.out.printf(" %-22s %6.2f%%%n", label, 100.0 * c / v.length);
48+
}
49+
}

‎mod/tools/TerrainPreview.java‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,20 @@ public static void main(String[] args) throws Exception {
8585
List<Entry> entries = new ArrayList<>();
8686
// order matches buildBiomeParameters; ids index BIOME_NAMES
8787
entries.add(new Entry(-1.5f, 1.5f, -1.5f, 1.5f, cR, 1.5f, 7)); // snow_peaks
88-
entries.add(new Entry(-1.5f, -0.3f, -1.5f, 1.5f, -1.5f, cR, 13)); // tundra
89-
entries.add(new Entry(-0.3f, 1.5f, -1.5f, 1.5f, cM, cR, 6)); // rocky_highlands
90-
entries.add(new Entry(-0.3f, 1.5f, -1.5f, 1.5f, cA, cM, 5)); // mountain_pine_forest
91-
entries.add(new Entry(-0.3f, 1.5f, -1.5f, 0.3f, cT, cA, 4)); // alpine_meadow
92-
entries.add(new Entry(-0.3f, 1.5f, 0.3f, 1.5f, cT, cA, 8)); // deep_valley
93-
entries.add(new Entry(0.5f, 1.5f, -1.5f, -0.4f, -1.5f, cT, 9)); // volcanic
94-
entries.add(new Entry(0.5f, 1.5f, -0.4f, -0.2f, -1.5f, cT, 10)); // desert
95-
entries.add(new Entry(0.5f, 1.5f, -0.2f, 0.4f, -1.5f, cT, 11)); // savanna
96-
entries.add(new Entry(0.5f, 1.5f, 0.4f, 1.5f, -1.5f, cT, 12)); // swamp
97-
entries.add(new Entry(0.15f, 0.5f, 0.4f, 1.5f, -1.5f, cT, 15)); // dark_forest
98-
entries.add(new Entry(0.15f, 0.5f, 0.0f, 0.4f, -1.5f, cT, 3)); // temperate_forest
99-
entries.add(new Entry(0.15f, 0.5f, -1.5f, 0.0f, -1.5f, cT, 2)); // lowland_plains
100-
entries.add(new Entry(-0.3f, 0.15f, 0.2f, 1.5f, -1.5f, cT, 14)); // birch_forest
101-
entries.add(new Entry(-0.3f, 0.15f, -1.5f, 0.2f, -1.5f, cT, 2)); // lowland_plains
88+
entries.add(new Entry(-1.5f, -0.35f, -1.5f, 1.5f, -1.5f, cR, 13)); // tundra
89+
entries.add(new Entry(-0.35f, 1.5f, -1.5f, 1.5f, cM, cR, 6)); // rocky_highlands
90+
entries.add(new Entry(-0.35f, 1.5f, -1.5f, 1.5f, cA, cM, 5)); // mountain_pine_forest
91+
entries.add(new Entry(-0.35f, 1.5f, -1.5f, 0.3f, cT, cA, 4)); // alpine_meadow
92+
entries.add(new Entry(-0.35f, 1.5f, 0.3f, 1.5f, cT, cA, 8)); // deep_valley
93+
entries.add(new Entry(0.25f, 1.5f, -1.5f, -0.4f, -1.5f, cT, 9)); // volcanic
94+
entries.add(new Entry(0.25f, 1.5f, -0.4f, -0.2f, -1.5f, cT, 10)); // desert
95+
entries.add(new Entry(0.25f, 1.5f, -0.2f, 0.4f, -1.5f, cT, 11)); // savanna
96+
entries.add(new Entry(0.25f, 1.5f, 0.4f, 1.5f, -1.5f, cT, 12)); // swamp
97+
entries.add(new Entry(-0.02f, 0.25f, 0.4f, 1.5f, -1.5f, cT, 15)); // dark_forest
98+
entries.add(new Entry(-0.02f, 0.25f, 0.0f, 0.4f, -1.5f, cT, 3)); // temperate_forest
99+
entries.add(new Entry(-0.02f, 0.25f, -1.5f, 0.0f, -1.5f, cT, 2)); // lowland_plains
100+
entries.add(new Entry(-0.35f, -0.02f, 0.2f, 1.5f, -1.5f, cT, 14)); // birch_forest
101+
entries.add(new Entry(-0.35f, -0.02f, -1.5f, 0.2f, -1.5f, cT, 2)); // lowland_plains
102102

103103
double[][] height = new double[n][n];
104104
int[][] biome = new int[n][n];

0 commit comments

Comments
 (0)