6 Commits

Author SHA1 Message Date
8cd487a5dc Civ Step 6: diplomacy, alliances & coalitions (save v22)
Wars stop being isolated 1-v-1 grudges. Each pair of nearby realms carries an
attitude that drifts over time, crystallising into alliances / non-aggression
pacts / rivalries. Allies don't fight and join each other's wars (coalitions),
and wars end in real peace treaties. Extends the Step-5 conflict subsystem
in place (same stepConflict tick, same war RNG), saved v22 + snapshotted.

- PlanetTypes.hpp: DiploKind + DiploTie {a,b capital indices, attitude, truceUntil,
  kind}; diplo* config knobs; WeatherSnapshot carries diplomacy.
- PlanetConflict.cpp: a diplomacy pass in stepConflict (revolts -> prosecute ->
  diplomacy -> declare). Attitude drifts from culture/faith affinity + a war
  penalty + truce recovery + per-pair noise; reclassified by threshold with
  hysteresis (kind-6 events on change). War-declare skips allied/non-aggression/
  truced pairs; hostility now rises as attitude falls (rivals fight); a defender's
  allies join by declaring their own war on the aggressor; a war end sets a truce
  + grudge. diploBetween/realmsAllied helpers.
- Save v22 + step-back: allegiance/wars block joined by a diplomacy block (new
  hasDiplo readState param + per-frame history block); captureWeather/restoreWeather
  carry the ties.
- Render: green alliance / dark-red rivalry great-circle arcs over the Territory
  view (P), per-realm ally/rival counts + active-wars list in the Realms tab, a
  cell-info allies/rivals line, kind-6 events (= icon).
- test_diplomacy.cpp: alliances/rivalries form, allies never war, coalitions form,
  truces after peace, determinism, RNG isolation, save-v22 + snapshot round-trip.
  All 14 suites green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 13:07:10 +02:00
4a1f3377ba Civ Step 5: conflict, war & shifting borders (save v21)
Realms stop coexisting peacefully and go to war. Unlike the derived Steps 3-4,
war is stateful & path-dependent, so it adds saved state (allegiance + wars +
a war RNG), extends the step-back snapshot, and bumps the save to v21.

- PlanetConflict.{hpp,cpp}: stepConflict(year) runs once per sim year. Neighbouring
  realms (adjacency by settlement proximity) grow hostile from ambition (size gap)
  + ideology (culture/faith difference) + contested frontier + a yearly streak, and
  declare wars (cap warMaxConcurrent). Each war-year runs a battle (strength =
  totalPop x Warlike bonus x defender home advantage), inflicts casualties on
  frontier cities, and the winner conquers a loser frontier city (allegiance flips
  to the victor) or sacks it (ruins). Conquered foreign/distant cities revolt over
  time; a realm that loses its capital collapses -> empires rise and fall. Separate
  sWarRng keeps tectonics deterministic.
- computeTerritory() honours sSettleAllegiance (overriding the mono-cultural rule)
  with a chain-resolving capital lookup, so borders move as cities change hands.
- Save v21: allegiance + wars + war RNG (new hasConflict readState param + a
  per-frame block in the step-back history); WeatherSnapshot + capture/restoreWeather
  extended, so ,/. rewind conquests + revolts.
- Render: red war-front lines + a red at-war marker & active-wars list in the Realms
  tab over the Territory view (P), a cell-info AT WAR flag, a HUD war count, and
  kind=5 events (declare / capture / sack / revolt / peace).
- war* config knobs; test_conflict.cpp covers wars erupting, conquest moving the
  border, revolts, determinism, RNG isolation, save-v21 + snapshot round-trip.
  All 13 suites green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 08:33:38 +02:00
91f1b90a93 Civ Step 4: culture, beliefs & governments
Give the world peoples and faiths on top of Step 3's realms. All derived
deterministically from the (saved) settlement set + geography (pure hashes,
no RNG, recomputed each sim year -> no save-version bump, step-back free).

- PlanetCulture.{hpp,cpp}: computeCultures() groups living settlements into one
  culture per inhabited continent, each with a generated people name, a dominant
  ethos picked from its cells' environment (Seafaring/Highland/Nomadic/Agrarian,
  else a hashed Mercantile/Warlike), and a religion (a Faith focus biased by the
  dominant biome + a generated faith name). Runs after computeTerritory().
- Governments: each realm (Nation) gets a GovType from its tier + a deterministic
  pick, folded into its name ("Republic of X", "Duchy of X", "X Theocracy", "X
  Confederation", "X Dominion", ...) -- culture-driven renaming.
- Culture-driven grouping: realm vassalage is now restricted to the same
  continent, so every kingdom/empire is mono-cultural.
- Render: a Culture colour mode (cultureColor, cultural blocs) + pale
  buildCultureBorders lines + a Cultures tab + a cell-info culture/faith line +
  government-aware realm labels, all under key X. Cultures recompute with
  territory in rebuildTerritory().
- test_culture.cpp: one culture per continent, valid ethos/faith, governments per
  tier reflected in names, mono-cultural realms, determinism, RNG isolation,
  save->load->recompute parity. All 12 suites green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 07:58:58 +02:00
ee2ef3655b Civ Step 3: territory, nations & political borders
Group settlements into realms (city-states / kingdoms / empires) and give them
territory + political borders, all derived deterministically from the saved
settlement set (no save-version bump, step-back free).

- PlanetNation.{hpp,cpp}: computeTerritory() — size-scaled influence range per
  settlement, realm grouping (a town joins the nearest larger capital within its
  annexation reach, else founds its own nation), tier by member count / total pop,
  and per-cell ownership maximising range - angular-distance (wilderness frontiers
  where no settlement reaches). No RNG → tectonic stream untouched.
- Territory colour mode + nationColor, buildNationBorders (plate dual-contour
  reused), realm labels at capitals, a Realms info tab, cell-info realm line, and
  kind=4 WorldEvents (realm founded / rises to empire / collapsed). Key P toggles
  the view + borders; territory recomputed once per sim year, on placement, load
  and step-back.
- civTerritory*/civVassalRange/civEmpire* config knobs (self-describing → no save
  break); test_nation.cpp covers ownership/wilderness, empires vs city-states,
  realm grouping, tiers, determinism, RNG isolation, save/load parity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 14:00:32 +02:00
aa32e38dad Live World stage: clock, day/night, seasons, moons, tides & ocean currents
Adds the slow real-time "Live World" mode (key W on a settled world) that runs the
finished planet on an hours->weeks/months clock (liveTime/liveRate, [ / ] ramp the rate)
with geology frozen. Everything new is a derived per-cell field flowed over the fixed grid.

Day/night & seasons (PlanetLive.cpp): a raylib-free per-cell insolation field
(computeInsolation) drives a moving day/night terminator (N) from time-of-day rotation +
seasonal declination (axialTilt); a live seasonal temperature cycles the static summer/winter
fields over the year (computeLiveSeason); a moving snow/sea-ice line tracks it. Day/night +
snow are render overlays over any colour mode (3D + 2D). Save v8 stores the live clock.

Sky & tides (PlanetOcean.cpp): 1-3 random moons (separate RNG, saved v9) orbit on the
clock and, with the now small/distant sun, raise an equilibrium tide (computeTides -> sTide),
shown as a tide-coloured coastline (T, buildCoastline + tideColor). Moons render with sun-lit
phases, orbit rings and eclipses (solar shadow spot in the day/night overlay, lunar dimming).
The 2D map is left-aligned; the freed space holds a Live-World "Sky & tides" panel (per-moon
phase + a selected coastal tile's tidal phase).

Ocean currents + climate feedback (PlanetOcean.cpp): computeOceanCurrents builds a
per-ocean-cell tangent velocity from wind stress + Coriolis deflection + coast-following
(gyres); computeClimate feeds warm (poleward) / cold (equatorward) currents back into sTemp as
a bounded coastal anomaly (climateCurrentFactor) before seasons, so biomes shift. Rendered as
warm/cold current arrows (O).

Config: dayLengthHours/yearLengthDays/snowTemp/seaIceTemp/tideAmplitude/tideSunFactor/
climateCurrentFactor. Save header v7->v9 (version-gated; older saves load fine). Headless
test_live.cpp + test_ocean.cpp; test_logic/test_biota still pass; GUI build clean. Docs updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 10:04:45 +02:00
acc0e5eec9 Initial commit: fanworgen planet sim
C++/raylib semi-realistic fantasy/sci-fi planet generator on a fixed icosphere
grid (Eulerian: properties flow over fixed cells). World-creation stages:
tectonics, continental drift & erosion, hydrology (rivers/lakes), climate
(temperature + orographic precipitation), and biome classification. Engine in
src/sim (raylib-free, headless-testable), viewer in src/render. See CLAUDE.md
and docs/ (design-notes.md, fauna-flora-plan.md = next step).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 15:08:25 +02:00