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:
parent
a68ad758cb
commit
d31f31dd62
5 changed files with 21 additions and 24 deletions
|
|
@ -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) ?? {})
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue