planetsim/src/render/Overlays.hpp
Jonas Reith 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

74 lines
4.4 KiB
C++

#pragma once
#include "raylib.h"
#include "Planet.hpp"
#include <vector>
#include <memory>
// World overlays drawn over the globe (3D) and/or the Equal Earth map (2D):
// plate borders, per-plate drift arrows + labels, Phase-3 rivers, lat/lon
// graticule, projected line segments, and the selected-cell subgrid patch.
// ---- Plate borders (dual contour through boundary triangles) ----------------
// Segments separating two real plates go to `real` (drawn yellow); any segment
// touching a baby (young spreading-ridge) plate goes to `ridge` (drawn red).
void buildBorders(const Planet& p, float radius,
std::vector<Vector3>& real, std::vector<Vector3>& ridge);
// ---- Nation borders (civ Step 3) -------------------------------------------
// Same dual-contour, but separating cells of different `cellNation()` (a realm's outline:
// inter-realm borders + its coast + wilderness frontier). One segment list.
void buildNationBorders(const Planet& p, float radius, std::vector<Vector3>& segs);
// Like buildNationBorders but on the per-cell culture split (civ Step 4): cultural-region outlines.
void buildCultureBorders(const Planet& p, float radius, std::vector<Vector3>& segs);
// Frontier segments between two cells whose realms are in an active war (civ Step 5): the war front.
void buildWarFrontier(const Planet& p, float radius, std::vector<Vector3>& segs);
// Great-circle arcs between allied (-> ally) and rival (-> rival) realm capitals (civ Step 6).
void buildDiploLinks(const Planet& p, float radius, std::vector<Vector3>& ally, std::vector<Vector3>& rival);
// ---- Per-plate drift arrows -------------------------------------------------
struct PlateLabel { int id; Vector3 pos; };
void buildDriftArrows(const Planet& p, float radius,
std::vector<Vector3>& out, std::vector<PlateLabel>& labels);
// ---- Phase-3 rivers: drainage-network segments (cell -> its downstream cell) -
// Split into normal and "big" rivers by discharge so they can be drawn at two
// line widths. Needs Planet::computeHydrology() to have been called.
void buildRivers(const Planet& p, float radius,
std::vector<Vector3>& rivers, std::vector<Vector3>& bigRivers);
// ---- Coastline (land/ocean boundary, dual contour through triangles) --------
// Like buildBorders but on the elevation-vs-seaLevel split. For each emitted segment
// (pairs in `segs`) records a representative adjacent OCEAN cell in `oceanCell` (one
// entry per segment, i.e. per 2 points) so the viewer can colour it by that cell's tide.
void buildCoastline(const Planet& p, float radius,
std::vector<Vector3>& segs, std::vector<int>& oceanCell);
// ---- Ocean currents (subsampled arrows, warm/cold) --------------------------
// Short arrows along Planet::current() over a subsample of ocean cells. `cols` has one
// colour per segment (warm = poleward/red, cold = equatorward/blue). Needs computeClimate
// (which computes the current field) to have run.
void buildCurrents(const Planet& p, float radius,
std::vector<Vector3>& segs, std::vector<Color>& cols);
// ---- Lat/lon graticule ------------------------------------------------------
// Polylines of (lon,lat) radians (Vector2.x=lon, .y=lat).
std::vector<std::vector<Vector2>> buildGraticule();
void drawGraticule3D(const std::vector<std::vector<Vector2>>& g, float radius);
void drawGraticule2D(const std::vector<std::vector<Vector2>>& g, Rectangle r, double lonOffset);
// Degree numbers along the 2D map edges (latitudes at the left, longitudes at the
// bottom). lonOffset is the map's east/west pan. Draw inside the map scissor.
void drawGraticuleLabels2D(Rectangle r, double lonOffset);
// Project 3D sphere line segments (pairs of points) onto the 2D map.
void drawSegments2D(const std::vector<Vector3>& segs, Color col, float width,
Rectangle r, double lonOffset);
// As drawSegments2D but with a per-segment colour (cols has one entry per segment,
// i.e. per 2 points). Used for the tide-shaded coastline.
void drawColoredSegments2D(const std::vector<Vector3>& segs, const std::vector<Color>& cols,
float width, Rectangle r, double lonOffset);
// ---- Subgrid overlay (high-res patch over a selected cell) ------------------
void drawSubgrids(const std::vector<std::shared_ptr<SubGrid>>& sgs,
float visBase, float elevExagg, double seaLevel, float eps);