From b17a8990b0aa09ee43d9196077527480e4f9351d Mon Sep 17 00:00:00 2001 From: George Date: Sun, 7 Jun 2026 22:07:48 +0100 Subject: [PATCH] Speed up ecosystem decay and fix succession cap being silently reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VegetationModule: - All living tiers now die under bad conditions, not just grass. Rates: grass 1.0, flowers 0.5, shrubs 0.25, trees 0.10 per sim cycle (trees only die under severe pollution >60 or near-zero soil <10). - Dead accumulation raised 0.20 → 0.50 per bad cycle. - Previously only grass died, keeping vegetation pressure artificially high and preventing regression even when soil/pollution were terrible. RecoveryModule: - DAMAGE_PER_BAD_TICK raised 3.0 → 5.0 so regression fires in ~14 bad cycles (~35s) once conditions trip the threshold, down from ~23 cycles. - DAMAGE_DECAY_RATE lowered 0.05 → 0.03 so damage sticks around during oscillating conditions instead of washing away on good ticks. - Fixed bug: 3-arg RecoveryRegionData constructor (used during damage decay) defaulted maxSuccessionStage to MATURE_FOREST, silently overwriting any biome or dynamic cap set by setRegionBiomeCap() / applyDynamicCapUpdate(). Now uses 4-arg constructor to preserve cap. Net result: a heavily polluted forest regresses a stage in ~2 minutes of sustained bad conditions instead of 10-15+ minutes. Co-Authored-By: Claude Sonnet 4.6 --- .../modules/recovery/RecoveryModule.java | 11 +++++++---- .../modules/vegetation/VegetationModule.java | 18 ++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/livingworld/modules/recovery/RecoveryModule.java b/src/main/java/com/livingworld/modules/recovery/RecoveryModule.java index cd59566..fadf0ea 100644 --- a/src/main/java/com/livingworld/modules/recovery/RecoveryModule.java +++ b/src/main/java/com/livingworld/modules/recovery/RecoveryModule.java @@ -46,9 +46,10 @@ public final class RecoveryModule implements SimulationModule { /** Extra recovery progress per point of ecosystemHealth above 50. */ private static final double HEALTH_PROGRESS_BONUS = 0.02; /** Damage accumulated per tick when conditions are badly violated. */ - private static final double DAMAGE_PER_BAD_TICK = 3.0; - /** Damage decays this fraction per tick when conditions are OK. */ - private static final double DAMAGE_DECAY_RATE = 0.05; + private static final double DAMAGE_PER_BAD_TICK = 5.0; + /** Damage decays this fraction per tick when conditions are OK. + * Kept low so damage sticks around during oscillating conditions. */ + private static final double DAMAGE_DECAY_RATE = 0.03; private static final double CHANGE_THRESHOLD = 0.01; private static final ModuleMetadata METADATA = new ModuleMetadata( @@ -112,10 +113,12 @@ public final class RecoveryModule implements SimulationModule { // Damage decays passively when conditions are good (bypass accumulateDamage // to avoid triggering regression with a zero-damage call that might fire at 70+). + // Use 4-arg constructor to preserve the dynamic succession cap. data = new RecoveryRegionData( data.getSuccessionStage(), data.getRecoveryProgress(), - Math.max(0.0, data.getDamageAccumulation() * (1.0 - DAMAGE_DECAY_RATE))); + Math.max(0.0, data.getDamageAccumulation() * (1.0 - DAMAGE_DECAY_RATE)), + data.getMaxSuccessionStage()); } else if (data.getSuccessionStage().conditionsMissedForRegression(soil, poll, veg)) { // Conditions are bad: accumulate damage toward regression. diff --git a/src/main/java/com/livingworld/modules/vegetation/VegetationModule.java b/src/main/java/com/livingworld/modules/vegetation/VegetationModule.java index c978aea..d28e24d 100644 --- a/src/main/java/com/livingworld/modules/vegetation/VegetationModule.java +++ b/src/main/java/com/livingworld/modules/vegetation/VegetationModule.java @@ -53,8 +53,15 @@ public final class VegetationModule implements SimulationModule { // --- die-off thresholds --- private static final double DIEOFF_SOIL_THRESHOLD = 20.0; private static final double DIEOFF_POLLUTION_THRESHOLD = 30.0; - private static final double GRASS_DIEOFF_RATE = 0.30; - private static final double DEAD_ACCUMULATION_RATE = 0.20; + // All living tiers die in bad conditions; trees die slowest. + private static final double GRASS_DIEOFF_RATE = 1.00; + private static final double FLOWER_DIEOFF_RATE = 0.50; + private static final double SHRUB_DIEOFF_RATE = 0.25; + private static final double TREE_DIEOFF_RATE = 0.10; + private static final double DEAD_ACCUMULATION_RATE = 0.50; + // Trees also die-off when conditions are severe (heavy pollution or near-zero soil). + private static final double TREE_SEVERE_POLLUTION = 60.0; + private static final double TREE_SEVERE_SOIL = 10.0; // --- decomposition --- private static final double DEAD_DECOMPOSITION_RATE = 0.01; @@ -131,6 +138,13 @@ public final class VegetationModule implements SimulationModule { if (badConditions) { data.setGrassPressure(data.getGrassPressure() - GRASS_DIEOFF_RATE); + data.setFlowerPressure(data.getFlowerPressure() - FLOWER_DIEOFF_RATE); + data.setShrubPressure(data.getShrubPressure() - SHRUB_DIEOFF_RATE); + // Trees die only under severe stress to reflect their resilience. + if (metrics.getPollutionScore() > TREE_SEVERE_POLLUTION + || metrics.getSoilQuality() < TREE_SEVERE_SOIL) { + data.setTreePressure(data.getTreePressure() - TREE_DIEOFF_RATE); + } data.setDeadVegetation(data.getDeadVegetation() + DEAD_ACCUMULATION_RATE); }