refactor(engine-ts): ♻️ Update physics engine models and refactor runner logic for new algorithms and optimizations

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-26 02:22:25 -07:00
parent a68ad758cb
commit d31f31dd62
5 changed files with 21 additions and 24 deletions

View file

@ -27,7 +27,7 @@ const CLIMATE_DEFAULTS: Record<string, number> = {
lake_thermal_conductivity: 0.05,
river_moisture_transport: 0.075,
mountain_rain_shadow_block: 0.9,
solar_min: 0.15,
solar_min: 0.05,
solar_max: 0.70,
}
@ -245,6 +245,19 @@ export class ClimatePhysics {
const aerosol_cfg = ((this.spec['aerosol'] ?? {}) as Record<string, number>)
if (Object.keys(aerosol_cfg).length === 0) return
const { tiles, width: w, height: h } = grid
// Phase 0: Natural aerosol sources — background, desert dust, volcanic outgassing
const bg = this.p('aerosol_background', 0.002)
const dustRate = this.p('aerosol_desert_dust', 0.005)
const volcanicRate = this.p('aerosol_volcanic_outgas', 0.015)
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i]
let inject = bg
if (tile.biome_id === 'desert') inject += dustRate
else if (tile.biome_id === 'volcano') inject += volcanicRate
;(tile as any).sulfate_aerosol = Math.max(0.0, ((tile as any).sulfate_aerosol ?? 0) + inject)
}
let any_aerosol = false
for (let i = 0; i < tiles.length; i++) {
if (((tiles[i] as any).sulfate_aerosol ?? 0) > 0.001) { any_aerosol = true; break }
@ -310,7 +323,7 @@ export class ClimatePhysics {
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i]
const { col, row } = tile
let solar = solarByRow(row, h, this.p('solar_min', 0.15), this.p('solar_max', 0.70))
let solar = solarByRow(row, h, this.p('solar_min', 0.05), this.p('solar_max', 0.70))
let current_temp = oldTemp[i]
let terrain_data = (this.terrainCache.get(tile.biome_id) ?? {})

View file

@ -390,19 +390,14 @@ function updateHabitatSuitability(
function updateFishStock(tiles: TileState[], w: number, h: number): void {
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i]
if (!isWater(tile)) continue
if (!isWater(tile) || (tile.fish_stock ?? 0) <= 0) continue
let tempMult = 0.5 // polar
if (tile.temperature > 0.55) tempMult = 1.0 // tropical
else if (tile.temperature > 0.25) tempMult = 0.8 // temperate
let cap = 100.0
if (tile.reef_health > 0.5) cap *= 1.5
else if (tile.reef_health < 0.1) cap *= 0.5
let stock = tile.fish_stock ?? 0
// Seed fish on water tiles that have none yet (spontaneous colonization)
if (stock <= 0) {
stock = Math.round(cap * 0.1 * tempMult) // start at 10% of capacity
if (stock <= 0) stock = 1
}
const stock = tile.fish_stock ?? 0
const growth = 0.05 * tempMult * stock * (1.0 - stock / cap)
tile.fish_stock = Math.max(0, Math.min(Math.round(stock + growth), cap))
}

View file

@ -264,21 +264,6 @@ class GenMap {
wonder_anchor_schools: [],
wonder_tier: 0,
river_source_type: gt?.river_source_type || undefined,
// Ecology fields (initialized to zero, populated by EcologyPhysics)
canopy_cover: 0.0,
undergrowth: 0.0,
fungi_network: 0.0,
drought_counter: 0,
succession_progress: 0,
regrowth_stage: -1,
regrowth_turns: 0,
habitat_suitability: 0.0,
habitat_low_turns: 0,
landmark_name: '',
substrate_id: '',
water_body_id: -1,
depth_from_coast: -1,
fish_stock: 0,
}
}
}

View file

@ -188,6 +188,7 @@ export function computeTurnStats(
let waterCount = 0
let aerosolSum = 0
let etSum = 0
let windSpeedSum = 0
let landCount = 0
const terrain_counts: Record<string, number> = {}
const substrate_counts: Record<string, number> = {}
@ -210,6 +211,7 @@ export function computeTurnStats(
solarSum += solar * (1.0 - albedo)
aerosolSum += (tile as Record<string, number>).sulfate_aerosol ?? 0
windSpeedSum += tile.wind_speed ?? 0
if (isWater) {
waterCount++
@ -253,6 +255,7 @@ export function computeTurnStats(
avg_land_quality: landCount > 0 ? landQualitySum / landCount : 1,
avg_water_quality: waterCount > 0 ? waterQualitySum / waterCount : 1,
avg_aerosol: aerosolSum / n,
avg_wind_speed: windSpeedSum / n,
avg_evapotranspiration: landCount > 0 ? etSum / landCount : 0,
net_energy: prevStats ? (landCount > 0 ? tempSum / landCount : 0.5) - prevStats.avg_temp : 0,
net_hydro: prevStats ? (landCount > 0 ? moistSum / landCount : 0.5) - prevStats.avg_moisture : 0,

View file

@ -76,6 +76,7 @@ export interface TurnStats {
avg_land_quality: number // average quality across land tiles (1-5)
avg_water_quality: number // average quality across water tiles (1-5)
avg_aerosol: number // global average sulfate aerosol opacity
avg_wind_speed: number // global average wind speed (0=calm, 1=gale)
avg_evapotranspiration: number // average ET contribution across land tiles
net_energy: number // net energy balance: solar_in - radiative_loss (positive=warming, negative=cooling)
net_hydro: number // net water balance: evap+ET - decay-loss (positive=wetting, negative=drying)