diff --git a/content/campaigns/main/campaign.yaml b/server/content/campaigns/main/campaign.yaml similarity index 100% rename from content/campaigns/main/campaign.yaml rename to server/content/campaigns/main/campaign.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/district.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/district.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/district.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/district.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/maintenance-corridors.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/maintenance-corridors.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/maintenance-corridors.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/maintenance-corridors.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-last-shift.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-last-shift.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-last-shift.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-last-shift.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-terminal.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-terminal.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-terminal.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/environmental/the-terminal.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-gallery.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-gallery.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-gallery.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-gallery.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-ground.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-ground.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-ground.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/gate-ground.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/maintenance-corridors.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/maintenance-corridors.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/maintenance-corridors.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/maintenance-corridors.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-last-shift.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-last-shift.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-last-shift.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-last-shift.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-terminal.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-terminal.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-terminal.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/locations/the-terminal.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/routines/schedules.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/routines/schedules.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/routines/schedules.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/routines/schedules.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/.gitkeep b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/.gitkeep similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/.gitkeep rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/.gitkeep diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/bar.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/bar.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/bar.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/bar.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/logistics-hub.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/logistics-hub.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/logistics-hub.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/logistics-hub.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/smuggling-ring.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/smuggling-ring.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/smuggling-ring.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/templates/smuggling-ring.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/ticker/the-last-shift.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/ticker/the-last-shift.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/ticker/the-last-shift.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/ticker/the-last-shift.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/bar-tensions.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/bar-tensions.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/bar-tensions.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/bar-tensions.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/hub-power.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/hub-power.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/hub-power.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/hub-power.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/worried-partner.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/worried-partner.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/worried-partner.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/districts/transit/triangles/worried-partner.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/stations/sova/station.yaml b/server/content/campaigns/main/systems/van-maanens-star/stations/sova/station.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/stations/sova/station.yaml rename to server/content/campaigns/main/systems/van-maanens-star/stations/sova/station.yaml diff --git a/content/campaigns/main/systems/van-maanens-star/system.yaml b/server/content/campaigns/main/systems/van-maanens-star/system.yaml similarity index 100% rename from content/campaigns/main/systems/van-maanens-star/system.yaml rename to server/content/campaigns/main/systems/van-maanens-star/system.yaml diff --git a/content/content.yaml b/server/content/content.yaml similarity index 100% rename from content/content.yaml rename to server/content/content.yaml diff --git a/content/gauntlet/cross_room_checks.yaml b/server/content/gauntlet/cross_room_checks.yaml similarity index 100% rename from content/gauntlet/cross_room_checks.yaml rename to server/content/gauntlet/cross_room_checks.yaml diff --git a/content/gauntlet/rooms/inventory_warehouse/checklist.yaml b/server/content/gauntlet/rooms/inventory_warehouse/checklist.yaml similarity index 100% rename from content/gauntlet/rooms/inventory_warehouse/checklist.yaml rename to server/content/gauntlet/rooms/inventory_warehouse/checklist.yaml diff --git a/content/gauntlet/rooms/occlusion_corridor/checklist.yaml b/server/content/gauntlet/rooms/occlusion_corridor/checklist.yaml similarity index 100% rename from content/gauntlet/rooms/occlusion_corridor/checklist.yaml rename to server/content/gauntlet/rooms/occlusion_corridor/checklist.yaml diff --git a/content/gauntlet/rooms/pause_chamber/checklist.yaml b/server/content/gauntlet/rooms/pause_chamber/checklist.yaml similarity index 100% rename from content/gauntlet/rooms/pause_chamber/checklist.yaml rename to server/content/gauntlet/rooms/pause_chamber/checklist.yaml diff --git a/content/global/contraband/.gitkeep b/server/content/global/contraband/.gitkeep similarity index 100% rename from content/global/contraband/.gitkeep rename to server/content/global/contraband/.gitkeep diff --git a/content/global/culture-osse.ron b/server/content/global/culture-osse.ron similarity index 100% rename from content/global/culture-osse.ron rename to server/content/global/culture-osse.ron diff --git a/content/global/culture-vael.ron b/server/content/global/culture-vael.ron similarity index 100% rename from content/global/culture-vael.ron rename to server/content/global/culture-vael.ron diff --git a/content/global/culture-van-maanens-star.example.ron b/server/content/global/culture-van-maanens-star.example.ron similarity index 100% rename from content/global/culture-van-maanens-star.example.ron rename to server/content/global/culture-van-maanens-star.example.ron diff --git a/content/global/culture-van-maanens-star.ron b/server/content/global/culture-van-maanens-star.ron similarity index 100% rename from content/global/culture-van-maanens-star.ron rename to server/content/global/culture-van-maanens-star.ron diff --git a/content/global/enums/access-tiers.yaml b/server/content/global/enums/access-tiers.yaml similarity index 100% rename from content/global/enums/access-tiers.yaml rename to server/content/global/enums/access-tiers.yaml diff --git a/content/global/enums/activities.yaml b/server/content/global/enums/activities.yaml similarity index 100% rename from content/global/enums/activities.yaml rename to server/content/global/enums/activities.yaml diff --git a/content/global/enums/moods.yaml b/server/content/global/enums/moods.yaml similarity index 100% rename from content/global/enums/moods.yaml rename to server/content/global/enums/moods.yaml diff --git a/content/global/enums/motivations.yaml b/server/content/global/enums/motivations.yaml similarity index 100% rename from content/global/enums/motivations.yaml rename to server/content/global/enums/motivations.yaml diff --git a/content/global/enums/patterns.yaml b/server/content/global/enums/patterns.yaml similarity index 100% rename from content/global/enums/patterns.yaml rename to server/content/global/enums/patterns.yaml diff --git a/content/global/enums/situations.yaml b/server/content/global/enums/situations.yaml similarity index 100% rename from content/global/enums/situations.yaml rename to server/content/global/enums/situations.yaml diff --git a/content/global/enums/topics.yaml b/server/content/global/enums/topics.yaml similarity index 100% rename from content/global/enums/topics.yaml rename to server/content/global/enums/topics.yaml diff --git a/content/global/enums/triggers.yaml b/server/content/global/enums/triggers.yaml similarity index 100% rename from content/global/enums/triggers.yaml rename to server/content/global/enums/triggers.yaml diff --git a/content/global/enums/trust-tiers.yaml b/server/content/global/enums/trust-tiers.yaml similarity index 100% rename from content/global/enums/trust-tiers.yaml rename to server/content/global/enums/trust-tiers.yaml diff --git a/content/global/factions/concord-assembly.yaml b/server/content/global/factions/concord-assembly.yaml similarity index 100% rename from content/global/factions/concord-assembly.yaml rename to server/content/global/factions/concord-assembly.yaml diff --git a/content/global/factions/guardians-of-autonomy.yaml b/server/content/global/factions/guardians-of-autonomy.yaml similarity index 100% rename from content/global/factions/guardians-of-autonomy.yaml rename to server/content/global/factions/guardians-of-autonomy.yaml diff --git a/content/global/factions/syndics.yaml b/server/content/global/factions/syndics.yaml similarity index 100% rename from content/global/factions/syndics.yaml rename to server/content/global/factions/syndics.yaml diff --git a/content/global/factions/the-ring.yaml b/server/content/global/factions/the-ring.yaml similarity index 100% rename from content/global/factions/the-ring.yaml rename to server/content/global/factions/the-ring.yaml diff --git a/content/global/factions/the-unbound.yaml b/server/content/global/factions/the-unbound.yaml similarity index 100% rename from content/global/factions/the-unbound.yaml rename to server/content/global/factions/the-unbound.yaml diff --git a/content/global/factions/veil-institute.yaml b/server/content/global/factions/veil-institute.yaml similarity index 100% rename from content/global/factions/veil-institute.yaml rename to server/content/global/factions/veil-institute.yaml diff --git a/content/global/knowledge/awareness.yaml b/server/content/global/knowledge/awareness.yaml similarity index 100% rename from content/global/knowledge/awareness.yaml rename to server/content/global/knowledge/awareness.yaml diff --git a/content/global/knowledge/behavioral.yaml b/server/content/global/knowledge/behavioral.yaml similarity index 100% rename from content/global/knowledge/behavioral.yaml rename to server/content/global/knowledge/behavioral.yaml diff --git a/content/global/knowledge/contraband.yaml b/server/content/global/knowledge/contraband.yaml similarity index 100% rename from content/global/knowledge/contraband.yaml rename to server/content/global/knowledge/contraband.yaml diff --git a/content/global/knowledge/entity-attributes.yaml b/server/content/global/knowledge/entity-attributes.yaml similarity index 100% rename from content/global/knowledge/entity-attributes.yaml rename to server/content/global/knowledge/entity-attributes.yaml diff --git a/content/global/knowledge/knowledge.yaml b/server/content/global/knowledge/knowledge.yaml similarity index 100% rename from content/global/knowledge/knowledge.yaml rename to server/content/global/knowledge/knowledge.yaml diff --git a/content/global/knowledge/location.yaml b/server/content/global/knowledge/location.yaml similarity index 100% rename from content/global/knowledge/location.yaml rename to server/content/global/knowledge/location.yaml diff --git a/content/global/knowledge/progress.yaml b/server/content/global/knowledge/progress.yaml similarity index 100% rename from content/global/knowledge/progress.yaml rename to server/content/global/knowledge/progress.yaml diff --git a/content/global/knowledge/relationship.yaml b/server/content/global/knowledge/relationship.yaml similarity index 100% rename from content/global/knowledge/relationship.yaml rename to server/content/global/knowledge/relationship.yaml diff --git a/content/global/knowledge/ring.yaml b/server/content/global/knowledge/ring.yaml similarity index 100% rename from content/global/knowledge/ring.yaml rename to server/content/global/knowledge/ring.yaml diff --git a/content/global/knowledge/social.yaml b/server/content/global/knowledge/social.yaml similarity index 100% rename from content/global/knowledge/social.yaml rename to server/content/global/knowledge/social.yaml diff --git a/content/global/knowledge/world.yaml b/server/content/global/knowledge/world.yaml similarity index 100% rename from content/global/knowledge/world.yaml rename to server/content/global/knowledge/world.yaml diff --git a/content/global/technology/.gitkeep b/server/content/global/technology/.gitkeep similarity index 100% rename from content/global/technology/.gitkeep rename to server/content/global/technology/.gitkeep diff --git a/content/global/trait-modifiers.ron b/server/content/global/trait-modifiers.ron similarity index 100% rename from content/global/trait-modifiers.ron rename to server/content/global/trait-modifiers.ron diff --git a/content/global/van-maanens-star-industrial-zone.ron b/server/content/global/van-maanens-star-industrial-zone.ron similarity index 100% rename from content/global/van-maanens-star-industrial-zone.ron rename to server/content/global/van-maanens-star-industrial-zone.ron diff --git a/content/global/van-maanens-star-rural-zone.ron b/server/content/global/van-maanens-star-rural-zone.ron similarity index 100% rename from content/global/van-maanens-star-rural-zone.ron rename to server/content/global/van-maanens-star-rural-zone.ron diff --git a/content/global/zone-identity-spec.example.ron b/server/content/global/zone-identity-spec.example.ron similarity index 100% rename from content/global/zone-identity-spec.example.ron rename to server/content/global/zone-identity-spec.example.ron diff --git a/content/global/zone-types/industrial_freight.ron b/server/content/global/zone-types/industrial_freight.ron similarity index 99% rename from content/global/zone-types/industrial_freight.ron rename to server/content/global/zone-types/industrial_freight.ron index 177a182b5..1d8b201b4 100644 --- a/content/global/zone-types/industrial_freight.ron +++ b/server/content/global/zone-types/industrial_freight.ron @@ -2,7 +2,7 @@ // // Schema: server/src/npc/blueprint.rs :: ZoneTypeTemplate // Ticket: #661 (copy team) -// Validate: tooling/validate-ron content/global/zone-types/industrial_freight.ron zone_type +// Validate: tooling/validate-ron server/content/global/zone-types/industrial_freight.ron zone_type // // Sources: D-142 (zone-type template architecture). // diff --git a/content/global/zone-types/rural_agricultural.ron b/server/content/global/zone-types/rural_agricultural.ron similarity index 99% rename from content/global/zone-types/rural_agricultural.ron rename to server/content/global/zone-types/rural_agricultural.ron index 3fdf77e5f..b7cdaca3a 100644 --- a/content/global/zone-types/rural_agricultural.ron +++ b/server/content/global/zone-types/rural_agricultural.ron @@ -2,7 +2,7 @@ // // Schema: server/src/npc/blueprint.rs :: ZoneTypeTemplate // Ticket: #661 (copy team) -// Validate: tooling/validate-ron content/global/zone-types/rural_agricultural.ron zone_type +// Validate: tooling/validate-ron server/content/global/zone-types/rural_agricultural.ron zone_type // // Sources: D-142 (zone-type template architecture). // diff --git a/content/modules/tier1/smuggling_ring_v0_1.yaml b/server/content/modules/tier1/smuggling_ring_v0_1.yaml similarity index 100% rename from content/modules/tier1/smuggling_ring_v0_1.yaml rename to server/content/modules/tier1/smuggling_ring_v0_1.yaml diff --git a/content/npc-conversations/overheard.yaml b/server/content/npc-conversations/overheard.yaml similarity index 100% rename from content/npc-conversations/overheard.yaml rename to server/content/npc-conversations/overheard.yaml diff --git a/content/schemas/drama_module.schema.yaml b/server/content/schemas/drama_module.schema.yaml similarity index 99% rename from content/schemas/drama_module.schema.yaml rename to server/content/schemas/drama_module.schema.yaml index 02fb039d5..93c2df1e5 100644 --- a/content/schemas/drama_module.schema.yaml +++ b/server/content/schemas/drama_module.schema.yaml @@ -1,6 +1,6 @@ # Drama Module Schema — Tier 1 Content (D-023) # YAML expression of JSON Schema 2020-12 -# Validated against this schema: content/modules/tier1/*.yaml +# Validated against this schema: server/content/modules/tier1/*.yaml # # Ownership: # Dramatic structure (this file): Paula diff --git a/server/src/bin/generator_spike.rs b/server/src/bin/generator_spike.rs index ae4500394..400525472 100644 --- a/server/src/bin/generator_spike.rs +++ b/server/src/bin/generator_spike.rs @@ -8,8 +8,8 @@ //! //! Run twice, compare side-by-side: //! ```sh -//! cargo run --bin generator_spike -- --zone rural --seed 42 -//! cargo run --bin generator_spike -- --zone industrial --seed 42 +//! cargo run --bin generator_spike -- --zone-type rural --seed 42 +//! cargo run --bin generator_spike -- --zone-type industrial --seed 42 //! ``` //! //! The test: can you tell which is which from the output alone? @@ -22,7 +22,7 @@ //! functions that work without ECS. Full ECS integration is deferred. use std::collections::{BTreeMap, VecDeque}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process; use clap::Parser; @@ -31,9 +31,9 @@ use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use settled_reach_server::npc::blueprint::{ - assemble_behaviors, BlueprintRelationship, CultureProfile, CulturalMarkers, CulturalValues, + assemble_behaviors, BlueprintRelationship, CulturalMarkers, CulturalValues, CultureProfile, NamingConventions, NpcBlueprint, NpcWant, RoleSpec, SocialSiteSpec, SpeechPatterns, - SpikeOutput, ZoneSpec, + SpikeOutput, ZoneSpec, ZoneTypeTemplate, }; use settled_reach_server::npc::PersonalityTrait; use settled_reach_server::simulation::rng::SimRng; @@ -48,9 +48,11 @@ use settled_reach_server::simulation::rng::SimRng; about = "NPC generator proof-of-life — Sprint 25 (#612)" )] struct Args { - /// Zone type to generate ("rural" or "industrial"). + /// Zone type to generate. + /// Phase 1 (hardcoded): "rural" or "industrial". + /// Phase 2 (--from-files): a zone-type ID like "rural_agricultural" or "industrial_freight". #[arg(long)] - zone: String, + zone_type: String, /// Deterministic seed — same seed produces identical output. #[arg(long)] @@ -60,8 +62,8 @@ struct Args { #[arg(long, default_value = "van-maanens-star")] culture: String, - /// Phase 2: load zone spec and culture from RON files on disk. - /// Requires content/global/-zone-spec.ron and content/global/culture-.ron. + /// Phase 2: load zone-type template and culture from RON files on disk. + /// Requires server/content/global/zone-types/.ron and server/content/global/culture-.ron. #[arg(long)] from_files: bool, @@ -268,21 +270,60 @@ fn hardcoded_van_maanens_star_culture() -> CultureProfile { // Phase 2: file loading // --------------------------------------------------------------------------- -fn load_zone_from_file(content_root: &PathBuf, zone_type: &str) -> ZoneSpec { - let path = content_root.join("global").join(format!("{}-zone-spec.ron", zone_type)); +fn load_zone_from_file(content_root: &Path, zone_type: &str) -> ZoneSpec { + let path = content_root + .join("global") + .join("zone-types") + .join(format!("{}.ron", zone_type)); let content = std::fs::read_to_string(&path).unwrap_or_else(|e| { - eprintln!("Error loading zone spec from {:?}: {}", path, e); - eprintln!("Tip: copy team fills this file (ticket #609)."); + eprintln!("Error loading zone-type template from {:?}: {}", path, e); + eprintln!("Tip: zone-type RON files live in content/global/zone-types/."); process::exit(1); }); - ron::from_str(&content).unwrap_or_else(|e| { - eprintln!("Invalid ZoneSpec in {:?}: {}", path, e); + let template: ZoneTypeTemplate = ron::from_str(&content).unwrap_or_else(|e| { + eprintln!("Invalid ZoneTypeTemplate in {:?}: {}", path, e); process::exit(1); - }) + }); + zone_type_template_to_zone_spec(template) } -fn load_culture_from_file(content_root: &PathBuf, culture_id: &str) -> CultureProfile { - let path = content_root.join("global").join(format!("culture-{}.ron", culture_id)); +/// Convert a `ZoneTypeTemplate` to a `ZoneSpec` compatible with the spike generation pipeline. +/// +/// `ZoneTypeTemplate` roles have no weight (weights live on `LocationSpec`). +/// The spike assigns weight=1 uniformly — all roles equally likely. +fn zone_type_template_to_zone_spec(template: ZoneTypeTemplate) -> ZoneSpec { + ZoneSpec { + zone_type: template.id, + label: template.label, + description: template.description, + economic_level: template.economic_level, + population_density: template.population_density, + roles: template + .roles + .into_iter() + .map(|mut r| { + r.weight = 1; // uniform weight — location specs provide real weights + r + }) + .collect(), + social_sites: template + .social_site_types + .into_iter() + .map(|s| SocialSiteSpec { + site_type: s.site_type, + label: String::new(), + roles: s.eligible_roles, + min_npcs: 1, + max_npcs: 6, + }) + .collect(), + } +} + +fn load_culture_from_file(content_root: &Path, culture_id: &str) -> CultureProfile { + let path = content_root + .join("global") + .join(format!("culture-{}.ron", culture_id)); let content = std::fs::read_to_string(&path).unwrap_or_else(|e| { eprintln!("Error loading culture from {:?}: {}", path, e); eprintln!("Tip: copy team fills this file (ticket #610)."); @@ -386,7 +427,11 @@ fn gen_traits(rng: &mut SimRng, culture: &CultureProfile) -> Vec u64 { let mut h: u64 = seed ^ 0xcbf29ce484222325; // FNV-1a offset basis, XOR'd with seed - for b in zone_type.bytes().chain(std::iter::once(b':')).chain(culture_id.bytes()) { + for b in zone_type + .bytes() + .chain(std::iter::once(b':')) + .chain(culture_id.bytes()) + { h ^= b as u64; h = h.wrapping_mul(0x100000001b3); // FNV-1a prime } @@ -549,7 +594,8 @@ const MAX_FILLER_WORDS: usize = 2; fn gen_cultural_markers(rng: &mut SimRng, culture: &CultureProfile) -> CulturalMarkers { let filler_count = if culture.speech.filler_words.len() > 1 { - rng.rng.random_range(1_usize..=MAX_FILLER_WORDS.min(culture.speech.filler_words.len())) + rng.rng + .random_range(1_usize..=MAX_FILLER_WORDS.min(culture.speech.filler_words.len())) } else { culture.speech.filler_words.len() }; @@ -595,7 +641,10 @@ fn gen_relationships( ) -> Vec { use settled_reach_server::npc::blueprint::RelationshipValence; - let other_names: Vec<&String> = all_names.iter().filter(|n| n.as_str() != this_name).collect(); + let other_names: Vec<&String> = all_names + .iter() + .filter(|n| n.as_str() != this_name) + .collect(); if other_names.is_empty() { return vec![]; } @@ -649,9 +698,7 @@ fn generate_npc_blueprint( let role = pick_role(rng, zone); let traits = gen_traits(rng, culture); let want = gen_want(rng, &traits, role); - let pool = behavior_pools - .entry(role.id.clone()) - .or_insert_with(VecDeque::new); + let pool = behavior_pools.entry(role.id.clone()).or_default(); let observable_behaviors = gen_behaviors(rng, role, pool); let cultural_markers = gen_cultural_markers(rng, culture); // Relationships and Want tells assigned in later passes. @@ -807,9 +854,15 @@ fn gen_want_tell(rng: &mut SimRng, npc: &NpcBlueprint) -> Option { AvoidingSomeone => match avoid_target { Some(name) => { let options = [ - format!("routes around {}'s usual area without looking toward it", name), + format!( + "routes around {}'s usual area without looking toward it", + name + ), format!("takes the long way past {}'s position", name), - format!("keeps a surface or cluster of people between them and {}", name), + format!( + "keeps a surface or cluster of people between them and {}", + name + ), ]; options[rng.rng.random_range(0..options.len())].clone() } @@ -870,7 +923,10 @@ fn apply_relationship_behaviors(rng: &mut SimRng, npc: &mut NpcBlueprint) { } ("friend", _) => format!("drifts toward {} between tasks", target), ("subordinate", RelationshipValence::Negative) => { - format!("complies when {} speaks, but doesn't volunteer anything", target) + format!( + "complies when {} speaks, but doesn't volunteer anything", + target + ) } ("subordinate", _) => format!("defers to {} before moving on", target), ("superior", RelationshipValence::Negative) => { @@ -992,17 +1048,20 @@ fn main() { // Load zone spec and culture profile let (zone, culture) = if args.from_files { eprintln!("Phase 2: loading from files..."); - let zone = load_zone_from_file(&args.content_root, &args.zone); + let zone = load_zone_from_file(&args.content_root, &args.zone_type); let culture = load_culture_from_file(&args.content_root, &args.culture); (zone, culture) } else { // Phase 1: hardcoded stubs - let zone = match args.zone.as_str() { + let zone = match args.zone_type.as_str() { "rural" => hardcoded_rural_zone(), "industrial" => hardcoded_industrial_zone(), other => { - eprintln!("Unknown zone type: '{}'. Use 'rural' or 'industrial'.", other); - eprintln!("(Phase 2 with --from-files supports additional zone types from disk)"); + eprintln!( + "Unknown zone type: '{}'. Use 'rural' or 'industrial'.", + other + ); + eprintln!("(Phase 2 with --from-files supports zone-type IDs like 'rural_agricultural')"); process::exit(1); } }; @@ -1046,7 +1105,7 @@ fn main() { // Pre-generate unique names using a derived RNG (#628 fix: first-pick bias). // Name ordering is a pure function of (seed, zone_type, culture) — independent // of how many words the main RNG has consumed for NPC count or other purposes. - let name_pool = build_name_pool(args.seed, &args.zone, &culture, npc_count); + let name_pool = build_name_pool(args.seed, &args.zone_type, &culture, npc_count); // Pre-shuffle behavior pools per role (#629 fix: dedup within a zone run). // D-139: uses assemble_behaviors() when behavior_primitives are present. @@ -1055,9 +1114,7 @@ fn main() { // First pass: generate all NPCs (no relationships yet) let mut npcs: Vec = name_pool .into_iter() - .map(|name| { - generate_npc_blueprint(&mut rng, &zone, &culture, name, &mut behavior_pools) - }) + .map(|name| generate_npc_blueprint(&mut rng, &zone, &culture, name, &mut behavior_pools)) .collect(); // Collect all names for relationship pass. diff --git a/server/src/bin/validate_ron.rs b/server/src/bin/validate_ron.rs index a21b7dd26..22bcb27be 100644 --- a/server/src/bin/validate_ron.rs +++ b/server/src/bin/validate_ron.rs @@ -8,8 +8,8 @@ //! //! ```sh //! # Via wrapper script (recommended): -//! tooling/validate-ron content/global/zone-identity-spec.example.ron zone -//! tooling/validate-ron content/global/culture-van-maanens-star.example.ron culture +//! tooling/validate-ron server/content/global/zone-identity-spec.example.ron zone +//! tooling/validate-ron server/content/global/culture-van-maanens-star.example.ron culture //! //! # Direct: //! cargo run --bin validate_ron -- @@ -19,7 +19,7 @@ use std::process; use clap::Parser; -use settled_reach_server::npc::blueprint::{CultureProfile, ZoneSpec}; +use settled_reach_server::npc::blueprint::{CultureProfile, ZoneSpec, ZoneTypeTemplate}; #[derive(Parser)] #[command( @@ -29,7 +29,7 @@ use settled_reach_server::npc::blueprint::{CultureProfile, ZoneSpec}; struct Args { /// Path to the RON file to validate. file: String, - /// Schema type: "zone" (ZoneSpec) or "culture" (CultureProfile). + /// Schema type: "zone" (ZoneSpec), "zone_type" (ZoneTypeTemplate), or "culture" (CultureProfile). schema: String, } @@ -48,7 +48,11 @@ fn main() { "zone" => match ron::from_str::(&content) { Ok(spec) => { println!("Valid ZoneSpec: {} ({})", spec.label, spec.zone_type); - println!(" {} roles, {} social sites", spec.roles.len(), spec.social_sites.len()); + println!( + " {} roles, {} social sites", + spec.roles.len(), + spec.social_sites.len() + ); let mut warnings = 0; if spec.roles.is_empty() { eprintln!(" WARNING: no roles defined — generator will reject this"); @@ -105,8 +109,43 @@ fn main() { process::exit(1); } }, + "zone_type" => match ron::from_str::(&content) { + Ok(template) => { + println!("Valid ZoneTypeTemplate: {} ({})", template.label, template.id); + println!( + " {} roles, {} social site types", + template.roles.len(), + template.social_site_types.len() + ); + let mut warnings = 0; + if template.roles.is_empty() { + eprintln!(" WARNING: no roles defined — generator will reject this"); + warnings += 1; + } + for role in &template.roles { + if role.behavior_primitives.is_empty() { + eprintln!( + " WARNING: role '{}' has no behavior_primitives", + role.id + ); + warnings += 1; + } + } + if warnings > 0 { + process::exit(1); + } + } + Err(e) => { + eprintln!("Invalid ZoneTypeTemplate in {}:", args.file); + eprintln!(" {}", e); + process::exit(1); + } + }, other => { - eprintln!("Unknown schema type: '{}'. Use 'zone' or 'culture'.", other); + eprintln!( + "Unknown schema type: '{}'. Use 'zone', 'zone_type', or 'culture'.", + other + ); process::exit(1); } } diff --git a/tooling/check-fact-ids b/tooling/check-fact-ids index 8472b1450..8c5320208 100755 --- a/tooling/check-fact-ids +++ b/tooling/check-fact-ids @@ -10,8 +10,8 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_ROOT="$(dirname "$SCRIPT_DIR")" -KNOWLEDGE_DIR="$REPO_ROOT/content/global/knowledge" -CONTENT_DIR="$REPO_ROOT/content/campaigns" +KNOWLEDGE_DIR="$REPO_ROOT/server/content/global/knowledge" +CONTENT_DIR="$REPO_ROOT/server/content/campaigns" # --- Extract canonical fact_ids from knowledge catalogs --- # Matches YAML lines like: fact_id: some_value or fact_id: "some_value" diff --git a/tooling/validate-checklist b/tooling/validate-checklist index 727985087..c7b30579b 100755 --- a/tooling/validate-checklist +++ b/tooling/validate-checklist @@ -16,8 +16,8 @@ import jsonschema import yaml ROOT = Path(__file__).resolve().parent.parent -SCHEMA_PATH = ROOT / "content" / "_schema" / "checklist.schema.json" -GAUNTLET_DIR = ROOT / "content" / "gauntlet" +SCHEMA_PATH = ROOT / "server" / "content" / "_schema" / "checklist.schema.json" +GAUNTLET_DIR = ROOT / "server" / "content" / "gauntlet" def load_schema(): diff --git a/tooling/validate-content b/tooling/validate-content index c8ffab01b..cf853a6f3 100755 --- a/tooling/validate-content +++ b/tooling/validate-content @@ -29,7 +29,7 @@ from pathlib import Path import jsonschema import yaml -CONTENT_DIR = Path(__file__).resolve().parent.parent / "content" +CONTENT_DIR = Path(__file__).resolve().parent.parent / "server" / "content" SCHEMA_DIR = CONTENT_DIR / "_schema" # Map directory parent name (or filename) to schema file diff --git a/tooling/validate-ron b/tooling/validate-ron index 74bbb2d95..0f309f3d2 100755 --- a/tooling/validate-ron +++ b/tooling/validate-ron @@ -2,21 +2,23 @@ # RON content validator — wrapper for the Rust validate_ron binary (#611). # # Usage: -# tooling/validate-ron +# tooling/validate-ron # # Examples: -# tooling/validate-ron content/global/zone-identity-spec.example.ron zone -# tooling/validate-ron content/global/culture-van-maanens-star.example.ron culture +# tooling/validate-ron server/content/global/zone-types/rural_agricultural.ron zone_type +# tooling/validate-ron server/content/global/culture-van-maanens-star.example.ron culture +# tooling/validate-ron server/content/global/zone-identity-spec.example.ron zone set -euo pipefail if [ $# -lt 2 ]; then - echo "Usage: tooling/validate-ron " + echo "Usage: tooling/validate-ron " echo "" echo "Validates a RON file against the Rust struct schema." echo "Schema types:" - echo " zone — ZoneSpec (zone identity spec)" - echo " culture — CultureProfile (culture profile)" + echo " zone_type — ZoneTypeTemplate (D-142 zone-type template)" + echo " zone — ZoneSpec (legacy zone identity spec)" + echo " culture — CultureProfile (culture profile)" exit 1 fi