Skip to main content

Valenar - Location Generation Contract

This document is the authoritative design contract for generating Valenar Locations. It explains what information a Location must carry, how readable terrain classes are derived, how production world facts become Valenar gameplay facts, and how those facts feed exploration, settlement development, pressure, UI, and Feature placement.

Feature placement has its own authority in Feature Generation Contract. Feature sections in this document describe the Location-side handoff and examples.

Related docs:

  • World Generation Contract defines the top-level world-data-to-Valenar import boundary.
  • Feature Generation Contract defines Feature placement, discovery, activities, rewards, and validation.
  • Locations, Features, and Sites defines what a Location can contain.
  • Location Dossier defines how the player inspects revealed Location content.
  • World Pressure and Nexus defines shield, taint, gates, and starting Nexus rules.
  • Settlements and Outposts defines claim, designation, districts, outposts, and development. Taxonomy rule for this contract: Location is the strategic unit. Features are notable contents, signs, or facts inside it. Sites are first-class places inside it once discovered, enterable, exploitable, or developed. Threat is attached danger or hostile presence, not a parallel place model. Dungeons follow the same handoff: clue, sign, or Feature first, Site once discovered or enterable. Status: planned authoritative contract. The current executable Valenar map is a stepping-in prototype fixture with server-side Voronoi geometry, prototype-scale Location counts, mostly-zero geography channels, and random inert Feature sprinkling. Target behavior below applies to the production generator unless explicitly marked current prototype behavior. Later campaign/world maps may be much larger and may use larger or variable-sized Locations.

Scope

This contract covers strategic map generation for Valenar:

  • Location facts.
  • Derived terrain and pressure labels.
  • Location topology and route inputs.
  • Location knowledge defaults.
  • Location fields consumed by Feature generation.
  • Validation.
  • Runtime data responsibilities.

It does not define:

  • 3D rendering implementation.
  • Individual feature story scripts.
  • Final numeric balance.
  • MC combat internals.
  • Feature template catalogs, which live in Feature Generation Contract.
  • District development formulas beyond the Location inputs they consume.

Core Principle

The generated numeric facts are the truth. Labels are summaries.

A Location is not only:

terrain = Plains

A Location has continuous facts:

plainsCoverage = 52
forestCoverage = 36
wetlandCoverage = 3
waterCoverage = 4
fertility = 72
moisture = 47
slopeAvg = 8
routeImportance = 61

The player-facing label is derived:

derivedClass = Wooded Plains
tags = Fertile, ForestEdge, EasyTravel, GoodExpansionLand

Feature generation, activity availability, designation value, and threat calculation use the numeric facts and tags. The label is for readability, not simulation authority.

Generation Shape

The complete generation path is:

production WorldData layers
-> Location polygon and hierarchy ids
-> aggregated Location numeric facts
-> derived classes and tags
-> travel, pressure, and control facts
-> feature candidate scoring
-> regional feature budgets
-> selected Feature entities
-> discovery and knowledge state
-> generated activity availability
-> modifiers, channel effects, and UI readouts
-> validation

The current Valenar prototype uses an interim SECS MapGenerationSystem plus server-side Voronoi geometry. That prototype may populate the same fields before production world-data integration, but the final source of geographic truth is production WorldData.

Location Scale

Each Location is a strategic cell of roughly 250-500 km² (an irregular Voronoi polygon at this scale). A Province (Järvamaa-sized, ~2,600 km²) contains 5-10 Locations; the player's starting Shielded Zone is 3-6 Provinces, so 15-60 Locations at game start; the full world is 50-150 Provinces (250-1500 Locations) across multiple Shielded Zones. The player operates at strategic scale, not city-builder scale.

The full scale budget — Province size, Locations per Province, Shielded Zone size, world-Province count — is owned by World Generation Contract. This section is the per-Location consequence.

The design must not require hand-authored feature lists per Location or independent random tables per Location.

Most Locations should not have a dramatic explicit Feature. A Location with no Feature is still meaningful because it has terrain, topology, resources, pressure, ownership, and travel state — at 250-500 km² per cell, the "interesting thing" is the cell itself, not a single landmark inside it.

Expected explicit Feature density:

ordinary land location: 0 notable Features
mildly interesting location: 1 notable Feature
rich, dangerous, or strategic location: 2 Features
rare landmark or story location: 3-4 Features
special Nexus / gate / capital site: hand-constrained by story rules

Production World-Data Alignment

Valenar consumes production world data through an explicit adapter contract; it does not bypass that contract.

The production world-data provider owns:

  • heightmap-aligned scalar fields such as elevation, moisture, temperature, flow accumulation, and slope
  • classification fields such as biome and water mask
  • id textures for Location, Province, Area, and Region
  • locationHierarchy
  • topology graphs such as river, corridor, thalweg, and lake components
  • world dimensions, coordinates, seed, and content hash

Valenar aggregates those facts per Location and turns them into gameplay data. If a Valenar UI, system, or renderer needs a generated map fact, that fact must exist in the data contract. It must not reach into generator internals.

Land And Water Locations

Production generation makes land and water Locations disjoint. Every texel belongs to one Location, and a Location has one high-level kind:

land-inland
land-coastal
water-narrow
water-coast
water-open
water-inland-lake

Valenar must respect this. A large lake, sea, or ocean area is a water Location, not a half-land Location. Coastal gameplay comes from adjacency between land-coastal and water-* Locations.

Within a land Location, Valenar can still have continuous land composition:

plainsCoverage
forestCoverage
hillCoverage
rockyCoverage
wetlandCoverage
barrenCoverage
ruinCoverage
corruptedCoverage

Tiny ponds, streams, springs, marsh patches, or drainage channels can contribute to waterCoverage and generate water Features inside a land Location when they are below the configured threshold for separate water Locations.

Location Data Contract

Every Location should have these generated or derived fields. Not every field must be visible to the player immediately.

Identity

locationId
seed
name
kind
parentProvinceId
parentAreaId
parentRegionId

kind is the high-level production Location kind, such as land-inland or water-coast.

Geometry And Topology

polygon
centroid
areaSquareMetres
neighbourLocationIds
borderLengthsByNeighbour
routeDistanceByNeighbour
edgeSlopeByNeighbour
edgeCrossingTypeByNeighbour

Topology is gameplay data. Travel, claiming, patrol, road, route safety, outpost connection, district grouping, and scouting all depend on it.

Terrain Composition

Terrain composition is normalized coverage across the Location. For land Locations:

plainsCoverage
forestCoverage
hillCoverage
mountainCoverage
wetlandCoverage
rockyCoverage
barrenCoverage
ruinCoverage
corruptedCoverage
tinyWaterCoverage

For water Locations:

openWaterCoverage
shallowWaterCoverage
shoreAdjacency
reefOrRockCoverage
riverMouthInfluence
lakeCoverage
coastExposure

Do not force one exclusive terrain type where composition matters. A Location can be Wooded Plains because it is 52 percent open ground and 36 percent forest edge.

Physical Values

elevationMin
elevationAvg
elevationMax
slopeAvg
roughness
moisture
temperature
windExposure
floodRisk
soilQuality
fertility
visibility
cover
defensibility

These are generated from map layers and topology. They are host-owned facts.

Resource Values

foodPotential
foragePotential
gamePotential
timberPotential
herbPotential
clayPotential
stonePotential
orePotential
rareMineralPotential
salvagePotential
ancientRelicPotential
waterReliability

Resources are not all visible at first. The Location may know foodPotential internally while the UI only shows unknown, signs of forage, or surveyed: high.

Travel Values

travelDifficulty
roadSuitability
routeImportance
riverCrossingDifficulty
chokepointScore
caravanViability
patrolViability
campSuitability

routeImportance is derived from graph position, such as how often a Location lies on good paths between useful regions, resources, settlement anchors, gates, or coastline access.

Pressure Values

baseThreat
predatorPressure
banditPressure
demonPressure
corruption
taintGrowth
nightDanger
weatherDanger
gateInfluence
shieldSuppression

Pressure fields can produce Features, activities, blockers, warnings, and modifiers. For example, high demon pressure may generate DemonTracks, while a true gate source becomes a stronger Feature with its own state and escalation.

Control Values

ownerId
controlState
claimability
designationType
settlementSuitability
outpostSuitability
districtSuitability
nexusCoverage
shieldCoverage
controlRouteState

Control is not binary. It is affected by knowledge, adjacency, route safety, Nexus or ward coverage, threat blockers, and act unlocks.

Knowledge Values

The Location knowledge ladder is the second of the three named state axes documented in ../systems/gd-state-axes-and-thresholds.md under "Location Knowledge Axis". The committed prototype is binary (int Explored on LocationData); the full ladder below is target, not yet implemented.

knowledgeState
surveyProgress
lastVisitedTick
knownThreat
knownResources
hiddenFeatureCountEstimate
visibleFeatureIds
hintedFeatureIds

Recommended Location knowledge ladder:

Unknown
Sighted
Scouted
Surveyed
Secured
Claimed
Cleansed
Developed

Binary Explored is only prototype scaffolding. Long-term Valenar needs gradual knowledge because Features, risks, resource quality, and route safety are revealed at different depths.

Derived Classes And Tags

The terrain-derived tag list below is planned — these labels are description-only language until they are committed to Content/common/tags.secs. The tag layer (namespace rules, modifier vs structural-predicate split, Feature category vs tag distinction) is documented in ../systems/gd-tags-and-classification.md, and the catalog of committed and planned tags lives in ../catalogs/gd-tag-catalog.md. Do not reference the planned tags below as Tags.<Name> constants in code until they are committed.

Derived classes summarize numeric facts.

Example rules:

Open Plains:
plainsCoverage >= 70
forestCoverage < 15
wetlandCoverage < 15

Wooded Plains:
plainsCoverage >= 30
forestCoverage >= 25
slopeAvg < 35

River Meadow:
plainsCoverage >= 25
moisture >= 55
fertility >= 55
tinyWaterCoverage >= 5 or adjacent river/water route

Deep Forest:
forestCoverage >= 70

Rocky Upland:
hillCoverage + rockyCoverage >= 45
slopeAvg >= 20

Marsh:
wetlandCoverage >= 35
moisture >= 65

Blighted Field:
corruptedCoverage >= 25 or corruption >= 60

Tags are smaller derived facts:

Fertile
ForestEdge
OpenGround
EasyTravel
GoodRoadLand
Sheltered
Exposed
HighCover
LowCover
OreBearing
AncientTrace
Tainted
Shielded
GateShadow
Chokepoint
CoastalAccess
RiverAccess
GoodSettlementLand
PoorSettlementLand

Classes and tags can change when knowledge improves. The underlying generated facts do not change unless the world simulation changes them.

SECS Responsibility Split

Generated host fields are facts:

forestCoverage
fertility
orePotential
corruption
routeImportance
knowledgeState
featureState

SECS channels are resolved effective values:

FoodOutput
WoodOutput
MetalOutput
RouteSafety
RestSafety
SurveyDifficulty
ThreatLevel
SettlementSuitability

Actual economy readouts such as connected stockpiles, consumption, or throughput sit one layer above these. They are downstream settlement or outpost values, not generated Location facts and not a replacement for resolved SECS outputs.

Templates define static identity and channel sources. Modifiers express persistent effects from Features, sites, designations, events, or control state.

The host should not write gameplay channel values directly. If a value needs tooltip breakdowns, modifiers, formulas, or effects, it belongs in SECS channels. If a value is generated map truth or entity state, it belongs in host fields.

Feature Model

A Feature is a notable thing inside a Location:

spring
ore vein
forest stand
ancient road segment
ruined mill
demon tracks
bandit camp
gate fissure
standing stones
dormant Nexus

Features are not terrain labels. They are discoverable, inspectable, and often actionable. A ForestEdge tag can make a Location wooded; a Forest Stand Feature exists only when that wooded area is notable enough to expose activities, risks, resources, or development hooks.

A Feature can stay a Feature for its whole life, or it can convert into a Site once the content becomes discovered, enterable, exploitable, or developed. Threat remains attached pressure or hostile presence on the Location, Feature, or resulting Site rather than a second place ontology.

Feature Categories

These categories classify Feature records. They do not create a competing player-facing place model.

NaturalResource
Water
Food
Forest
Mineral
Travel
Shelter
Ruin
Threat
Corruption
Landmark
Nexus
SettlementOpportunity
Story

Feature Template Contract

Each Feature template needs:

id
category
rarity
minSpacing
maxPerLocation
maxPerProvince
maxPerArea
maxPerRegion
hardRequirements
suitabilityWeights
conflictTags
synergyTags
discoveryDifficulty
surveyDifficulty
interactionDifficulty
possibleStates
available interactions
effects
modifiers
rewards

Template data answers:

  • where the Feature can exist
  • how rare it is
  • what it conflicts with
  • what it synergizes with
  • how it is discovered
  • what activities it creates
  • what it does to the Location, routes, settlement, or world pressure

Feature Generation Formula

Do not roll every Location independently. Independent per-Location random chance creates noisy nonsense even at the 250-1500 Location world scale, because budgets, spacing, conflicts, and story rules all need cross-Location coherence the per-Location roll cannot give.

Use score-and-budget placement:

score(location, featureTemplate) =
hardGate(location, featureTemplate)
* suitability(location, featureTemplate)
* rarityModifier(featureTemplate)
* seededNoise(worldSeed, locationId, featureTemplateId)
* spacingPenalty(location, featureTemplate)
* storyBias(location, featureTemplate)

Where:

hardGate:
0 or 1. Required conditions must pass.

suitability:
weighted match between Location facts and template preferences.

rarityModifier:
global, regional, and category budget pressure.

seededNoise:
deterministic variation. Same seed and content gives same result.

spacingPenalty:
prevents bad clustering and respects min spacing.

storyBias:
forces or encourages required narrative geography, such as Nexus starts,
demon fronts, ancient roads, leyline anchors, or gate pressure arcs.

Candidate selection:

for each region:
for each feature template:
collect eligible candidates
score candidates
sort by score descending
select until regional/province budget is filled
enforce min spacing
enforce max features per Location
enforce conflict rules

This gives authored-feeling distribution without hand-authored placement.

Feature Capacity

Feature capacity prevents every Location from becoming cluttered.

capacityScore =
max(resourceRichness, threat, ancientness, routeImportance, settlementSuitability)
+ landmarkBias
+ seededNoise

Suggested capacity:

score < 35: 0 explicit Features
35-60: 1 explicit Feature
60-80: 2 explicit Features
80-95: 3 explicit Features
story or landmark override: 4 Features

Capacity can reserve slots by category. For example, a starting Nexus Location may reserve one story slot for the Nexus and still allow one natural survival Feature.

Feature Conflict And Synergy

Conflict rules prevent nonsense:

DormantNexus conflicts with duplicate Nexus/Wardheart anchor placement
OpenMarketCrossroads conflicts with DeepWildernessOnly
PristineSpring conflicts with SevereTaintSource unless explicitly corrupted
DenseForestFeature requires enough forestCoverage
LargeMineSite requires enough orePotential and terrain support

Synergy rules create meaningful clusters:

AncientRoadSegment increases chance of RuinedWatchtower nearby.
RiverMeadow increases chance of GoodFarmland and OldMill.
DemonGate increases chance of DemonTracks, BlightedField, and RefugeeCamp nearby.
OreBearingUpland increases chance of OreVein and CollapsedMine.
ForestEdge increases chance of GameTrail, HiddenCopse, and AmbushGrass.

Synergy should be deterministic and budgeted. It should not create unbounded chains.

Feature State

Feature state is more than discovered or cleared.

Recommended ladder:

Hidden
Hinted
Discovered
Surveyed
Interacting
Handled
Secured
Developed
Depleted
Destroyed

Not every Feature uses every state. The state model must support mystery, partial knowledge, local activities, long-term development, and cleanup.

Site-facing wording, once a Feature converts, should use explicit place states: wild, discovered, secured, active, owned, developed, depleted, sealed, destroyed.

Example:

Hidden Spring

Hidden:
not shown

Hinted:
damp reeds, insect noise, or greener grass

Discovered:
shown as Hidden Spring

Surveyed:
water reliability and taint safety revealed

Secured:
improves rest safety and camp suitability

Developed:
supports farm, pasture, settlement water, or outpost

Activity Generation

Activities come from Location facts, Feature state, MC location, site ownership, threat blockers, tools, resources, act unlocks, and Nexus/founding state.

availableActivity(feature, actor, location) =
feature exists
required state passes
actor is present or has valid remote access
required tools/resources/act pass
threat blockers pass or the activity handles the threat
route/control requirements pass

Common activity families:

Look Around
Scout
Survey
Forage
Hunt
Gather
Investigate
Clear
Secure
Harvest
Excavate
Consecrate
Cleanse
Build Outpost
Develop Site
Study
Patrol
Seal
Exploit
Establish the Core

Feature activities must be causal. Investigate Ruined Mill can unlock tools, blueprints, local restoration, or production-site knowledge. It should not grant a random global production bonus unrelated to the ruin.

Effects And Modifiers

Feature effects should attach to the entity they actually affect.

Examples:

WildGrainPatch discovered:
reveals food potential and forage activity

WildGrainPatch secured:
adds local FoodOutput or FarmingSuitability modifier

OreVein surveyed:
reveals ore quality and mine-site activity

OreVein developed:
adds MetalOutput to the owning Location, outpost, district, or settlement
through the proper scope

DemonNest active:
increases ThreatLevel
lowers RouteSafety and RestSafety
blocks safe survey, mining, or settlement work

DemonNest handled:
removes active threat modifier
may reveal salvage, shard, route safety, or taint source information

Use Location-scoped modifiers first. Promote to settlement or region effects only when ownership, route connection, designation, site development, or story state justifies it.

Plains Example

Plains are not empty. They are about food, grazing, visibility, roads, exposure, soft ground, old travel routes, and pressure.

Possible plains Features:

Food/resource:
WildGrainPatch
GrazingHerd
GoodFarmland
ForagingGround
HerbMeadow

Water:
SeasonalStream
ShallowPond
ReedPool
HiddenSpring

Travel:
RoadTrace
CaravanCamp
MarketCrossroads
OldBoundaryStones

Shelter/defense:
LoneHill
WindbreakCopse
EarthenRise
ExposedApproach

Threat:
AmbushGrass
PredatorTrail
BanditCamp
DemonTracks
BlightedField

History:
StandingStones
BattlefieldRemnant
BuriedRuins
AncientRoadSegment
FallenWatchtower
SealedBarrow

Example WildGrainPatch:

eligible if:
plainsCoverage >= 35
fertility >= 55
corruption <= 50

score =
plainsCoverage * 0.30
+ fertility * 0.45
+ moisture * 0.15
- forestCoverage * 0.10
- corruption * 0.25
+ noise * 0.10

Example RoadTrace:

eligible if:
slopeAvg <= 35
tinyWaterCoverage <= 35
routeImportance >= 40

score =
routeImportance * 0.45
+ plainsCoverage * 0.20
+ roadSuitability * 0.25
- wetlandCoverage * 0.20
- roughness * 0.15
+ noise * 0.10

Example DemonTracks:

eligible if:
demonPressure >= 35
knowledgeState >= Sighted

score =
demonPressure * 0.45
+ corruption * 0.25
+ visibility * 0.10
+ routeImportance * 0.10
+ noise * 0.10

Mixed Terrain Example

Generated facts:

plainsCoverage = 52
forestCoverage = 36
wetlandCoverage = 3
tinyWaterCoverage = 4
fertility = 72
moisture = 47
threat = 18
routeImportance = 61

Derived class:

Wooded Plains

Tags:

Fertile
ForestEdge
EasyTravel
GoodExpansionLand

Likely selected Features:

WildGrainPatch:
high fertility plus open ground

ForestEdgeGameTrail:
mixed forest and plains with low threat

RoadTrace:
good route importance plus low slope

Other Terrain Examples

Deep Forest:

high forestCoverage
medium cover
lower visibility
possible Features:
ForestStand
GameTrail
HiddenCopse
OldShrine
AmbushSigns
WitchPath

Rocky Upland:

high slope and rockyCoverage
lower fertility
higher defensibility
possible Features:
OreVein
QuarryFace
CollapsedMine
WatchHill
CaveMouth
FallenTower

Wet Meadow:

high moisture and fertility
moderate tinyWaterCoverage or water adjacency
possible Features:
SeasonalStream
ReedPool
GoodFarmland
OldMillRace
SoftGround
TaintedRunoff

Blighted Field:

high corruption or corruptedCoverage
lower rest safety
possible Features:
BlackAshPatch
DemonTracks
BlightedCrop
MinorFissure
DeadGrove
CleansingSite

Land-Coastal:

land location adjacent to water location
possible Features:
FishingCamp
LandingBeach
CliffPath
OldPier
SmugglerCove
StormWreck

Water-Coast or Water-Inland-Lake:

water location, not settlement land by default
possible Features:
FishingGround
ShallowReef
FerryRoute
LakeIsland
SunkenRuin
DangerousCurrent

Starting Location Rules

The starting Location is procedural but constrained. It must pass the Nexus/Wardheart rules:

inside Ancient Shield coverage
low taint
weak or no demons in immediate reach
water within 1-2 hops
food in the start or within 1 hop
shelter and fire materials in the start
at least 2 viable expansion directions
at least 1 visible mystery hint
no immediate lethal gate
contains a dormant or damaged Nexus Feature

The Nexus is a story-constrained Feature placement. It is not the result of ordinary ruin rarity. Not every ruin can become a Nexus.

Founding is unlocked by the starting Nexus chain:

find ruin clue
investigate ruin
identify dormant Nexus / Wardheart
stabilize Nexus
unlock Establish the Core
found once
remove founding activity forever

Generic settlement suitability must not unlock founding by itself.

Validation

Generation is incomplete without validation.

Location invariants:

every Location has a polygon, centroid, parent ids, and kind
every non-isolated Location has at least one neighbour
parent province/area/region membership is spatially contiguous
coverage values are normalized and bounded
physical and resource values are bounded
water and land Location kind rules match production world data
large water bodies are water Locations, not land coverage
tiny water features inside land Locations are below the configured threshold

Feature invariants:

every Feature has a valid Location
every selected Feature still passes hard requirements
Feature count does not exceed Location capacity
rare Features respect spacing
incompatible Features do not coexist
story Features required by start rules exist
no visible Feature is in Hidden state
no activity references a missing Feature, Site, or Location

Pressure and start invariants:

starting Location passes Nexus/Wardheart constraints
starting Nexus Feature exists and is hidden/dormant until discovered
no immediate lethal gate threatens the starting Location
taint and shield values produce survivable Act 0 pressure
gate pressure sources produce coherent nearby clues and threats

Route and control invariants:

travel graph is connected within intended landmasses
blocked routes explain their blockers
claimable Locations have valid control paths
district grouping can be derived from claimed adjacency
route safety uses topology plus pressure, not UI-only labels

Determinism invariants:

same seed, config, production WorldData, and content definitions produce the same
Location facts and Feature placements
feature placement order is stable
tie-breaks use deterministic ids or seeded noise

Runtime Migration Direction

The current prototype has the containers but not the full semantic generator.

Existing useful substrate:

  • LocationData already stores parent id, owner, designation, explored flag, five geography ints, feature ids, building substrate, geometry, neighbours, and area.
  • FeatureData already stores location id, template id, name, discovered, cleared, and hostile.
  • Location and Feature scopes already exist in .secs.
  • Feature lifecycle contracts already exist.
  • The client already has a Location panel and expanded dossier shell.

Required direction:

1. Extend LocationData for the generated fields in this contract.
2. Extend FeatureData beyond binary discovered/cleared/hostile state.
3. Populate semantic Location facts after interim Voronoi generation now, and
from production WorldData later.
4. Replace random Feature sprinkling with score-and-budget placement.
5. Replace hard-coded Act 0 dossier facts with snapshot-backed facts,
Features, activities, and knowledge state.
6. Fire Feature lifecycle hooks on discovery, interaction, handling, clearing,
securing, and development transitions.
7. Enforce Nexus-gated founding in runtime, not only UI text.

The field names can evolve during implementation, but the architecture must preserve the contract:

numeric generated facts first
derived classes second
Features selected from facts
activities derived from Features and state
effects applied through channels and modifiers
UI reads real state
validation proves the world is coherent