feat(world): Add new biome types (tundra, savanna) with temperature/humidity rules and enhance classification logic

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-28 21:31:37 -07:00
parent e1070b6467
commit 3d1cf9fefe
2 changed files with 29 additions and 11 deletions

View file

@ -16,6 +16,7 @@ var flora_climax: Dictionary = {
} # target values at peak quality
var fauna_capacity: int = 10 # max creatures per tile
var food_web_tier: String = ""
var tags: Array[String] = [] # semantic tags (is_water, is_elevated, etc.)
static func from_dict(data: Dictionary) -> BiomeModel:
@ -43,6 +44,9 @@ static func from_dict(data: Dictionary) -> BiomeModel:
b.flora_climax = data.get("flora_climax", {"canopy": 0.0, "undergrowth": 0.0, "fungi": 0.0})
b.fauna_capacity = data.get("fauna_capacity", 10)
b.food_web_tier = data.get("food_web_tier", "")
b.tags = []
for t: Variant in data.get("tags", []):
b.tags.append(String(t))
return b
@ -57,4 +61,5 @@ func to_dict() -> Dictionary:
"flora_climax": flora_climax,
"fauna_capacity": fauna_capacity,
"food_web_tier": food_web_tier,
"tags": tags,
}

View file

@ -29,6 +29,12 @@ static func classify(tile: Variant) -> String:
## Aquatic classification: water body type + temperature + depth.
## Falls back to biome_id when water_body_type is not set (TS guide tiles).
static func _classify_aquatic(tile: Variant) -> String:
# Boil threshold: water-substrate tile too hot for liquid water → volcanic basin.
# Normalized temperature 0.82 ≈ 800°C surface temp — pre-ocean Hadean conditions.
const WATER_BOIL_TEMP: float = 0.82
if _get_temperature(tile) >= WATER_BOIL_TEMP:
return "volcanic"
var wb_type: String = _get_water_body_type(tile)
var biome: String = _get_biome_id(tile)
@ -70,7 +76,7 @@ static func _classify_land(tile: Variant) -> String:
# Wetland override: saturated moisture on lowland
# (mangrove already handled in classify() before water/land split)
if moisture > 0.7 and elevation < 0.4:
if moisture > 0.7 and elevation < 0.4 and canopy > 0:
if temp > 0.4:
return "swamp"
return "bog"
@ -78,36 +84,41 @@ static func _classify_land(tile: Variant) -> String:
# Elevation-driven
if elevation > 0.85:
if temp < 0.1:
return "permanent_ice"
return "glacial"
return "alpine_tundra"
if elevation > 0.70:
if moisture > 0.3:
if canopy > 0 and moisture > 0.3:
return "alpine_meadow"
return "alpine_tundra"
if elevation > 0.55:
if canopy > 0.4:
return "montane_forest"
if moisture > 0.7 and temp > 0.3:
if canopy > 0 and moisture > 0.7 and temp > 0.3:
return "cloud_forest"
return "alpine_meadow"
if canopy > 0 and moisture > 0.3:
return "alpine_meadow"
return "alpine_tundra"
# Temperature-driven (lowland/midland)
if temp > 0.55:
if moisture > 0.7 and canopy > 0.6:
return "tropical_rainforest"
if moisture > 0.4:
return "tropical_dry_forest"
if moisture > 0.2:
return "savanna"
# Without biology, warm moist land is bare rock — not savanna or dry forest
if canopy > 0:
if moisture > 0.4:
return "tropical_dry_forest"
if moisture > 0.2:
return "savanna"
return "desert"
# Temperate
if temp > 0.25:
if canopy > 0.5:
return "temperate_forest"
if moisture > 0.3:
# Without biology, temperate moist land is bare rock — not grassland
if moisture > 0.3 and canopy > 0:
return "temperate_grassland"
return "chaparral"
@ -115,7 +126,9 @@ static func _classify_land(tile: Variant) -> String:
if temp > 0.1:
if canopy > 0.3:
return "boreal_forest"
return "tundra"
if canopy > 0:
return "tundra"
return "polar_desert"
return "polar_desert"