From e79d96708f2a555759b7f106c3bb9f613efe14d0 Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 2 May 2026 23:21:58 +0100 Subject: [PATCH] fix: align LOD biome selection with registry scoring --- modules/world-worldgen/src/biome_selector.zig | 49 +++---------------- .../src/biome_selector_tests.zig | 46 +++++++++++++++++ src/worldgen_tests.zig | 4 +- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/modules/world-worldgen/src/biome_selector.zig b/modules/world-worldgen/src/biome_selector.zig index fdf0fdc9..db770e3f 100644 --- a/modules/world-worldgen/src/biome_selector.zig +++ b/modules/world-worldgen/src/biome_selector.zig @@ -258,49 +258,12 @@ pub fn selectBiomeWithConstraintsAndRiver(climate: ClimateParams, structural: St // LOD-optimized Biome Functions (Issue #114) // ============================================================================ -/// Simplified biome selection for LOD2+ (no structural constraints). +/// Simplified biome selection for LOD2+ paths that only have climate params. /// -/// Intentionally excludes transition micro-biomes (foothills, marsh, dry_plains, -/// coastal_plains), special biomes (mushroom_fields, mangrove_swamp), beach, -/// and mountain variants. These are either rare, narrow-band, or structurally -/// dependent biomes that don't significantly affect distant terrain silhouette. -/// The full Voronoi selection handles them when chunks enter LOD0/LOD1 range. +/// Keep this aligned with the full registry scoring path so distant biome color +/// and material choices use the same climate, elevation, continentalness, +/// ruggedness, and ridge signals as LOD0 where structural height/slope filters +/// are not available. pub fn selectBiomeSimple(climate: ClimateParams) BiomeId { - const heat = climate.temperature * 100.0; - const humidity = climate.humidity * 100.0; - const continental = climate.continentalness; - - // Ocean check - if (continental < 0.35) { - if (heat <= 15) return .frozen_ocean; - if (heat <= 30) return .cold_ocean; - if (continental < 0.20) return .deep_ocean; - if (heat > 75 and humidity > 55) return .warm_ocean; - return .ocean; - } - - if (continental < 0.48 and heat > 85 and humidity > 70) return .tropical; - - // Simple land biome selection based on heat/humidity - if (heat < 20) { - return if (humidity > 50) .taiga else .snow_tundra; - } else if (heat < 40) { - return if (humidity > 60) .taiga else .plains; - } else if (heat < 60) { - return if (humidity > 70) .forest else .plains; - } else if (heat < 80) { - if (humidity > 70) { - return if (humidity > 85) .bamboo_jungle else .jungle; - } - if (humidity > 30) return if (climate.elevation > 0.55) .savanna_plateau else .savanna; - return .desert; - } else { - if (humidity > 85) return .bamboo_jungle; - if (humidity > 70) return .jungle; - if (humidity > 50) return .sparse_jungle; - if (humidity > 15 and humidity <= 30 and climate.elevation > 0.55) return .windswept_savanna; - if (humidity > 25) return .wooded_badlands; - if (humidity > 10) return .badlands; - return .desert; - } + return selectBiome(climate); } diff --git a/modules/world-worldgen/src/biome_selector_tests.zig b/modules/world-worldgen/src/biome_selector_tests.zig index 55547b23..70a24485 100644 --- a/modules/world-worldgen/src/biome_selector_tests.zig +++ b/modules/world-worldgen/src/biome_selector_tests.zig @@ -591,6 +591,52 @@ test "selectBiomeSimple hot humid returns non-desert" { try testing.expect(biome != .ocean); } +test "selectBiomeSimple matches constrained selector for LOD-compatible samples" { + const Case = struct { + name: []const u8, + climate: ClimateParams, + structural: StructuralParams, + }; + + const cases = [_]Case{ + .{ + .name = "deep ocean", + .climate = .{ .temperature = 0.5, .humidity = 0.5, .elevation = 0.2, .continentalness = 0.10, .ruggedness = 0.1 }, + .structural = .{ .height = 48, .slope = 1, .continentalness = 0.10, .ridge_mask = 0.0 }, + }, + .{ + .name = "plains", + .climate = .{ .temperature = 0.5, .humidity = 0.45, .elevation = 0.35, .continentalness = 0.60, .ruggedness = 0.1 }, + .structural = .{ .height = 70, .slope = 2, .continentalness = 0.60, .ridge_mask = 0.1 }, + }, + .{ + .name = "jagged peaks", + .climate = .{ .temperature = 0.32, .humidity = 0.45, .elevation = 0.85, .continentalness = 0.85, .ruggedness = 0.85, .ridge_mask = 0.7 }, + .structural = .{ .height = 150, .slope = 18, .continentalness = 0.85, .ridge_mask = 0.7 }, + }, + }; + + for (cases) |case| { + errdefer std.debug.print("failed LOD selector consistency case: {s}\n", .{case.name}); + try testing.expectEqual(selectBiomeWithConstraints(case.climate, case.structural), selectBiomeSimple(case.climate)); + } +} + +test "selectBiomeSimple uses terrain signals beyond heat and humidity" { + const warm_dry = ClimateParams{ + .temperature = 0.82, + .humidity = 0.25, + .elevation = 0.40, + .continentalness = 0.80, + .ruggedness = 0.10, + }; + var rugged = warm_dry; + rugged.ruggedness = 0.75; + + try testing.expectEqual(BiomeId.savanna, selectBiomeSimple(warm_dry)); + try testing.expectEqual(BiomeId.badlands, selectBiomeSimple(rugged)); +} + // ============================================================================ // BiomeSelection Structure Tests // ============================================================================ diff --git a/src/worldgen_tests.zig b/src/worldgen_tests.zig index a37c4ae7..7bf1ba43 100644 --- a/src/worldgen_tests.zig +++ b/src/worldgen_tests.zig @@ -986,13 +986,13 @@ test "BiomeSource selectBiomeSimplified returns valid biome" { const climate2 = biome_mod.ClimateParams{ .temperature = 0.5, .humidity = 0.5, - .elevation = 0.4, + .elevation = 0.2, .continentalness = 0.1, .ruggedness = 0.2, }; const result2 = source.selectBiomeSimplified(climate2); - try testing.expectEqual(result2, BiomeId.deep_ocean); + try testing.expectEqual(BiomeId.deep_ocean, result2); } test "BiomeSource getColor returns valid packed RGB" {