Reported after a long run left the world under one dominant culture -- the
existing schism only fires for a geographically distant cluster (overseas
colonies), so a single unbroken landmass had nothing to check one culture
quietly absorbing the whole world via border conversion.
Two new independent triggers, both refactored to share the existing schism
machinery via a doSchism() helper:
- Dominance schism: past cultDominanceShare (80%) of the world's living
population, a per-year chance rising from cultDominanceProbMin (1%) to
cultDominanceProbMax (99%) at 100% share that the culture fractures on
its own -- a coin flip splits off half or a fifth of its own members,
the ones farthest from its own population-weighted core.
- War schism: a war between two realms sharing a culture has
cultWarSchismChance (50%) odds, rolled once at declaration, that one
whole side renounces the shared identity and becomes a new people.
Both are pure hashes of (stable id, year, seed), so step-back replays them
exactly, matching the rest of Step 8. Config is the self-describing text
block, so no save-version bump.
Dropped an initial validateConfig() cross-rule requiring
cultDominanceProbMin <= cultDominanceProbMax after finding it would reject
a very natural "disable via Max=0" edit (e.g. from the Main Menu) whenever
Min was left at its default -- silently reverting a player's entire config
to defaults on New World. The interpolation tolerates the reverse fine
since the mechanic is already gated on Max > 0.
test_cultevo.cpp gains two new scenarios (dominance split, war split)
alongside the existing distant-cluster one; quietCulture() now also zeros
the two new rates.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TMfyZv91tonDnPJqbaTVJE
A continent used to always seed exactly one culture at the dawn
(seedCultures(), grouped by regionId), which -- combined with the existing
border-conversion/backfill dynamics -- tended to erode into one
super-dominant culture covering the entire world over a long simulated run.
seedCultures() now splits each continent into 1..cultDawnMaxPerContinent
initial peoples via deterministic farthest-point seeding (a settlement is
assigned to its nearest seed point, giving geographically coherent,
Voronoi-like cultural regions instead of a checkerboard). The target count
scales with the continent's settlement population via the new
cultDawnSettlementsPerCulture config knob, capped by cultDawnMaxPerContinent.
Per-culture ethos/faith/name hashes now fold in Culture.id so multiple
cultures sharing a continent (and therefore the same regionId/bank) get
distinct identities instead of colliding.
This surfaced a real, previously-latent ordering bug: computeTerritory()
(realm/vassalage grouping, which prefers matching by actual culture and only
falls back to same-continent when culture data doesn't exist yet) ran BEFORE
computeCultures() populated per-settlement culture, so on every fresh
recompute realms formed by continent for one full pass before the next
recompute split them correctly. Harmless before this change (one culture per
continent made the two equivalent), but would have left temporarily
multi-cultural realms now. Fixed at the root: split computeCultures() into
refreshSettlementCultures() (the settlement-level seed/backfill/tally slice,
no dependency on `nations`) and had computeTerritory() call it internally
before grouping -- every caller (production and the dozens of existing test
call sites) gets correct behaviour automatically, no call-site changes needed
beyond the two tests whose assertions encoded the old exact one-per-continent
invariant.
test_culture.cpp and test_cultevo.cpp updated to assert the new bounded
(1..cultDawnMaxPerContinent) invariant instead of exact equality, plus that a
single culture never itself spans two continents (still enforced).
Verified live: a single continent now shows six distinct peoples ("the
Thisur", "the Bomebro", "the Draordaes", etc.) instead of one dominant
culture, while realms remain correctly mono-cultural.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TMfyZv91tonDnPJqbaTVJE
Cultures stop being static one-per-continent blocs. Culture identities are
now stateful: the list is append-only (seeded once at the dawn, schism
children appended later, records frozen after creation) and the
per-settlement culture is mutable state.
- stepCulture(year) in the yearly tick (pure hashes, no RNG):
assimilation (a conquered settlement adopts its ruler's culture, which
drops the Step-5 revolt cultBonus -> assimilation pacifies provinces),
border conversion (population x trade-prestige pressure; realm capitals
exempt), schism (a far-flung coherent cluster -- typically overseas
colonies -- breaks away as a new people with a local-bank NameGen name
and ethos/faith re-derived from its own lands).
- computeCultures() became a pure derived refresh (seeds only when the
list is empty); seedCultures() reproduces the old per-continent peoples
byte-identically for the dawn and pre-v23 loads.
- Colonies inherit the founder's culture at founding; the Step-3
mono-cultural vassalage rule is culture-matched (regionId fallback) so
schism clusters found their own realms -> colonial independence wars.
- Per-cell culture view colours by the owning settlement's culture, so a
conquered city keeps its colour until it assimilates.
- Save v23: culture identities + sSettleCulture + next-id counter, also in
the step-back frames; snapshots rewind via truncate-and-replay. Pre-v23
saves re-seed on the next refresh.
- Kind-7 world events; Cultures tab hides extinct peoples and shows a
schism child's founding year. Knobs cult* in planet.cfg.
- New test_cultevo.cpp (30 checks); all 15 existing suites still pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>