feat(simulation): NpcBlueprint struct design, RON schema, and validator CLI (#611)
Define ZoneSpec, CultureProfile, and NpcBlueprint structs with serde/RON deserialization. Ship example RON files as schema contract for the copy team (#609, #610). Add validate-ron CLI for copy team to lint their files without compiling the server. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
// Krenn Culture Profile — example file
|
||||
//
|
||||
// Schema: server/src/npc/blueprint.rs :: CultureProfile
|
||||
// Real content: ticket #610 (copy team fills this)
|
||||
// Validate: tooling/validate-ron content/global/culture-krenn.example.ron culture
|
||||
//
|
||||
// One file per culture. The generator reads this to give NPCs culturally
|
||||
// appropriate names, speech patterns, and personality bias.
|
||||
//
|
||||
// Source: D-036 (Krenn System canonical setting), D-128 (culture implicit in location),
|
||||
// D-121 (voice culture-driven), D-123 (AI content templating via culture vectors).
|
||||
|
||||
(
|
||||
id: "krenn",
|
||||
name: "Krenn System Culture",
|
||||
description: "Working-class pragmatic culture. ~180 years settled, mid-Reach G3V system. Community-oriented, suspicious of distant authority, values competence and reliability over credentials. First-name-primary in social contexts.",
|
||||
|
||||
naming: (
|
||||
style: "compact, consonant-heavy, first-name-primary in social contexts",
|
||||
given_names: [
|
||||
"Kael", "Voss", "Lera", "Torek", "Drin",
|
||||
"Maret", "Naia", "Sera", "Nils", "Pael",
|
||||
"Tev", "Ren", "Sess", "Renn", "Olin",
|
||||
"Tav", "Resha", "Harek", "Sabel", "Pell",
|
||||
],
|
||||
family_names: [
|
||||
"Davan", "Sessik", "Korr", "Tamm", "Venn",
|
||||
"Lintar", "Darvo", "Kosse",
|
||||
],
|
||||
// Krenn culture is first-name-primary. Family names exist but are
|
||||
// used mainly in formal/institutional contexts.
|
||||
family_name_used_socially: false,
|
||||
),
|
||||
|
||||
speech: (
|
||||
register: "direct, minimal pleasantries, gets to the point",
|
||||
filler_words: [
|
||||
"look",
|
||||
"right",
|
||||
"yeah",
|
||||
"so",
|
||||
],
|
||||
greetings: [
|
||||
"hey",
|
||||
"morning",
|
||||
"shift treating you alright?",
|
||||
],
|
||||
farewells: [
|
||||
"shift's calling",
|
||||
"gotta move",
|
||||
"catch you later",
|
||||
],
|
||||
exclamations: [
|
||||
"void take it",
|
||||
"stars",
|
||||
"unbelievable",
|
||||
],
|
||||
),
|
||||
|
||||
values: (
|
||||
description: "Pragmatic, community-oriented, suspicious of authority. Competence earns respect. Showing up and doing the work matters more than rank or credentials. Outsiders are tolerated but watched.",
|
||||
// Traits more common in Krenn culture — generator biases toward these.
|
||||
favored_traits: [Bold, Honest, Curious],
|
||||
// Traits less common — generator biases away from these.
|
||||
disfavored_traits: [Reclusive, Deceptive],
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,97 @@
|
||||
// Zone Identity Spec — example file
|
||||
//
|
||||
// Schema: server/src/npc/blueprint.rs :: ZoneSpec
|
||||
// Real content: ticket #609 (copy team fills this)
|
||||
// Validate: tooling/validate-ron content/global/zone-identity-spec.example.ron zone
|
||||
//
|
||||
// One file per zone type. The generator reads this to decide NPC count,
|
||||
// role distribution, and social site placement.
|
||||
//
|
||||
// Format: RON (Rusty Object Notation) — the Rust structs ARE the schema.
|
||||
// Comments are allowed. Trailing commas are allowed.
|
||||
|
||||
(
|
||||
zone_type: "rural",
|
||||
label: "Rural Settlement",
|
||||
description: "Scattered homesteads, small workshops, and communal gathering spots. Low population density, strong community bonds, subsistence-plus economy.",
|
||||
|
||||
// 1-10 scale. Rural = low economic activity, mostly self-sufficient.
|
||||
economic_level: 3,
|
||||
// 1-10 scale. Rural = sparse, everyone knows everyone.
|
||||
population_density: 2,
|
||||
|
||||
roles: [
|
||||
(
|
||||
id: "farmer",
|
||||
label: "Farmer",
|
||||
weight: 5,
|
||||
skill_focus: ["technical"],
|
||||
combat_eligible: false,
|
||||
typical_behaviors: [
|
||||
"tends crops in the field",
|
||||
"hauls produce to the market stall",
|
||||
"repairs equipment by hand",
|
||||
],
|
||||
),
|
||||
(
|
||||
id: "mechanic",
|
||||
label: "Settlement Mechanic",
|
||||
weight: 3,
|
||||
skill_focus: ["technical"],
|
||||
combat_eligible: false,
|
||||
typical_behaviors: [
|
||||
"works on machinery with focused intensity",
|
||||
"wipes grease on coveralls between tasks",
|
||||
"explains repairs in terse technical shorthand",
|
||||
],
|
||||
),
|
||||
(
|
||||
id: "trader",
|
||||
label: "Itinerant Trader",
|
||||
weight: 2,
|
||||
skill_focus: ["persuasion", "observation"],
|
||||
combat_eligible: false,
|
||||
typical_behaviors: [
|
||||
"arranges goods on a portable display",
|
||||
"haggles with quiet persistence",
|
||||
"watches foot traffic from market stall",
|
||||
],
|
||||
),
|
||||
(
|
||||
id: "militia",
|
||||
label: "Settlement Militia",
|
||||
weight: 1,
|
||||
skill_focus: ["combat", "observation"],
|
||||
combat_eligible: true,
|
||||
typical_behaviors: [
|
||||
"patrols the settlement perimeter",
|
||||
"checks credentials at the gate",
|
||||
"leans on rifle while scanning the horizon",
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
social_sites: [
|
||||
(
|
||||
site_type: "tavern",
|
||||
label: "Local Tavern",
|
||||
roles: ["farmer", "mechanic", "trader", "militia"],
|
||||
min_npcs: 3,
|
||||
max_npcs: 6,
|
||||
),
|
||||
(
|
||||
site_type: "workshop",
|
||||
label: "Community Workshop",
|
||||
roles: ["mechanic", "farmer"],
|
||||
min_npcs: 2,
|
||||
max_npcs: 4,
|
||||
),
|
||||
(
|
||||
site_type: "market_stall",
|
||||
label: "Market Stall",
|
||||
roles: ["trader", "farmer"],
|
||||
min_npcs: 1,
|
||||
max_npcs: 3,
|
||||
),
|
||||
],
|
||||
)
|
||||
Reference in New Issue
Block a user