Skip to content

Terraforming

Shipped — five-level project ladder, flat-column persistence, habitability-points model.

Long-term improvements to existing colonies' habitability. Distinct from Genesis Devices (which create planets — see galaxy/genesis-devices.md).

The model is habitability points, not growth percentages: each level adds a fixed integer to Planet.habitability_score (0–100), and habitability drives population cap, growth multiplier, and morale through a single shared formula in planetary_service.get_habitability_effects. See ADR-0002 for the design rationale.

Five-level project ladder

Authoritative source: services/gameserver/src/services/terraforming_service.py:TERRAFORMING_LEVELS.

Level Name Cost (cr) Duration (h) Habitability boost Organics Equipment
1 Basic Atmospheric 100,000 72 +10 500 200
2 Climate Stabilization 250,000 120 +15 1,500 500
3 Ecosystem Seeding 500,000 168 +20 3,000 1,000
4 Biome Engineering 1,000,000 240 +25 5,000 2,000
5 Full Terraformation 2,000,000 336 +30 10,000 5,000

Boost is applied as a single integer addition to habitability_score, capped at TERRAFORMING_MAX_HABITABILITY = 100.

Resource sourcing: organics and equipment are drawn from the planet's own stockpile (Planet.organics, Planet.equipment) — not from the player's ship cargo. The level cannot start if either stock is below the requirement. Credits are deducted from the player.

Levels are independent, not sequential. The code does not enforce "Level 2 requires Level 1 complete" or any citadel-level prerequisite. Any owned planet below the skip threshold can start any level if resources are available.

Mechanics

services/terraforming_service.py:start_terraforming:

  1. Verify planet is owned by the player.
  2. Verify habitability_score < TERRAFORMING_MIN_TARGET (90).
  3. Verify no terraforming already active on the planet.
  4. Verify player credits and planet stockpile cover the level's recipe.
  5. Deduct credits from player; deduct organics + equipment from planet stockpile.
  6. Set Planet.terraforming_active = True, terraforming_target, terraforming_start_time, terraforming_progress = 0.0, status = TERRAFORMING.
  7. Push a metadata entry into the planet's active_events JSONB list with shape {type: "terraforming", level, level_name, credit_cost, organics_cost, equipment_cost, habitability_boost, duration_hours, started_at, start_habitability, last_tick_at}. The two trailing fields support lazy tick advancement: start_habitability records the score at project start (used by cancellation to revert), and last_tick_at is the timestamp the lazy reader divides against TICK_PERIOD to compute due ticks.

Tick-based progression

Shipped — lazy advance-on-read. process_terraforming_tick(planet_id) advances habitability by 1–3 points, scaled by population:

  • Base increment: TERRAFORMING_BASE_INCREMENT = 1.
  • Population bonus: +1 per TERRAFORMING_POPULATION_SCALE = 1000 colonists/population.
  • Cap: TERRAFORMING_MAX_INCREMENT = 3.

So a planet with ≥ 2,000 population terraforms at the maximum 3 points/tick; a planet with < 1,000 progresses at the minimum 1 point/tick.

Rather than a background scheduler, ticks are applied lazily when terraforming status is read: the wall time elapsed since the last tick is divided by the tick period, and the resulting number of due ticks is applied in one pass before the status is returned. The tick period derives from the level's documented duration so that a minimum-speed (< 1,000 pop) planet finishes in exactly the level's duration_hours, while a populous planet (up to the 3-points/tick cap) finishes up to 3× faster: TICK_PERIOD = duration_hours / total_points, where total_points is the level's habitability boost. This derivation is canon (blessed by Max 2026-06-14).

Completion

_complete_terraforming runs when habitability_score reaches terraforming_target:

  • Apply the level's habitability_boost (capped at 100).
  • Recompute max_population = habitability_score × 1,000 (canonical formula, see ./colonization.md#population-capacity). The recompute is a fresh evaluation of the formula, not a multiplicative shrink of the current value — terraforming raises habitability and therefore raises the cap. max_colonists is not touched here; it is citadel-bound, not habitability-bound.
  • Floor population_growth at:
  • 2.0 if habitability ≥ 80,
  • 1.5 if habitability ≥ 60,
  • 1.0 if habitability ≥ 40.
  • Clear terraforming_active, terraforming_target, terraforming_start_time; set terraforming_progress = 100.0.
  • Remove the terraforming entry from active_events.
  • Set status = COLONIZED (if populated) or HABITABLE (if empty).

Cancellation

TERRAFORMING_CANCEL_REFUND = 0.50 — cancelling a project refunds 50% of the credit cost. Organics and equipment are not refunded (treated as consumed in-process). Cancellation also reverts habitability_score to start_habitability (the value recorded at project start), so any habitability gained from lazy ticks before the cancel is rolled back. This is an anti-arbitrage measure: without the revert, a player could repeatedly start, let a few ticks bank habitability, then cancel for the 50% refund and keep the gains.

Skip threshold

Planets with habitability_score ≥ 90 (TERRAFORMING_MIN_TARGET) cannot start a new project — start_terraforming raises.

Habitability effects

planetary_service.get_habitability_effects:

  • effective_max_colonists = base_max_colonists * (habitability / 100).
  • growth_multiplier = habitability / 100 (applied to base growth).
  • morale_bonus = +1 per 10 habitability above 50.

Population growth in _calculate_production: colonist_rate = colonists * 0.01 * (habitability / 100) per day.

This is how habitability points translate to the growth-rate intuition. A Level 1 terraform on a starting-habitability-50 planet (+10 → 60) raises the growth multiplier from 0.50 to 0.60, a 20% relative increase. A Level 5 from 50 to 80 takes it from 0.50 to 0.80, a 60% relative increase.

Planet model state

The terraforming columns on planets (added in migration b2c3d4e5f6a7_add_terraforming_columns_to_planets):

Column Type Purpose
terraforming_active Boolean Project is in progress.
terraforming_target Integer (nullable) Target habitability score for the active project.
terraforming_start_time DateTime (nullable) When the active project began.
terraforming_progress Float 0.0–100.0, percentage of target reached.

Per-level metadata (cost, boost, duration, level name) lives in the planet's active_events JSONB column under a {type: "terraforming"} entry, along with the two tick-support fields start_habitability and last_tick_at. There is no separate terraforming_projects table — see ADR-0002. Multiple concurrent projects on a single planet are not representable.

Planet types

The full enum is in DATA_MODELS/planets.md (12 values: TERRA, MOUNTAINOUS, OCEANIC, DESERT, VOLCANIC, BARREN, ICE, JUNGLE, ARCTIC, TROPICAL, GAS_GIANT, ARTIFICIAL). The seven types in active gameplay use, with their per-type production multipliers, storage caps, base growth rates, and habitability ranges, are catalogued in colonization.md.

JUNGLE, ARCTIC, TROPICAL, GAS_GIANT, and ARTIFICIAL are present in the enum but have no production-multiplier definitions in colonization.md. Treat them as design-only until those biomes are specified.

📐 Design-only — planet-type reclassification. The legacy design specified that completing Level 5 may upgrade a hostile planet's type (BARREN → VOLCANIC, ICE → DESERT). The implemented _complete_terraforming does not modify planet.type; only habitability_score changes. If reclassification becomes desired again, the rule belongs in _complete_terraforming and would need a deliberate ADR amendment.

🚧 Partial — cost scaling at high habitability. The level's credit cost scales by the planet's current habitability: ×1.25 above 40, ×1.5 above 70 (TERRAFORMING_COST_SCALE_LOW / TERRAFORMING_COST_SCALE_HIGH in terraforming_service.py, bands inclusive-exclusive — "above N" is strictly greater than N). The ×2.0-above-90 band is moot because the skip threshold at 90 (TERRAFORMING_MIN_TARGET) blocks new projects there. Organics and equipment costs are not scaled.

📐 Design-only — Terraform Engineers profession. The legacy PLANETARY_COLONIZATION.md design includes a Terraform Engineers profession (training queue, monthly progress driven by engineer count, scaling resource costs). No profession system exists in code today. The current model derives tick speed from total population, not specialised engineers.

Strategic considerations

  • Early game: prefer Genesis Devices for new planets — much cheaper than full terraforming an existing hostile world.
  • Mid game: Level 1–2 terraform on M/L/O-Class planets to lift habitability into the 60–80 band where the growth multiplier and morale bonus compound.
  • Late game: Level 5 to push strategically-located worlds (e.g. a Barren planet on a critical trade route) toward 100 habitability, unlocking maximum population cap and growth.

ROI sketch:

  • Advanced Genesis (250,000 cr per ADR-0012, plus the sacrificed Colony Ship hull at ~500,000 cr per ADR-0013) → ~30 days to break-even on Settlement-phase production.
  • Full sequence Level 1 → 5 (3,850,000 cr + 20,000 organics + 8,700 equipment) → ~180 days to break-even on a rescued Barren world (capped at 100 habitability, but the climb from 0 takes the full ladder).

The terraform path makes sense only when the planet's location justifies the long payoff.

Player-facing affordances

  • Terraforming panel per planet showing current habitability, active project, time remaining, expected boost.
  • Cost preview before starting (credits + planet-stockpile organics + planet-stockpile equipment).
  • Cancel button surfacing the 50%-credits refund warning and that resources are not refunded.
  • Empire view showing terraforming progress across all owned planets.

Source map

Topic Path
Terraforming service services/gameserver/src/services/terraforming_service.py
Habitability effects on capacity / growth / morale services/gameserver/src/services/planetary_service.py:get_habitability_effects
Per-day colonist growth services/gameserver/src/services/planetary_service.py:_calculate_production
Planet model services/gameserver/src/models/planet.py
Terraforming columns migration services/gameserver/alembic/versions/b2c3d4e5f6a7_add_terraforming_columns_to_planets.py
Genesis (related) services/gameserver/src/services/genesis_service.py
Planet API services/gameserver/src/api/routes/planets.py
Admin terraforming view services/gameserver/src/api/routes/admin_colonization.py
Design rationale ADR/0002-terraforming-formula-model.md