code wiki / (root) / nx_decl_townscape.nx

nx_decl_townscape.nx source

↩ module page · 168 lines · 6361 B

1// nx_decl_townscape.nx -- fifth declarative #tag-style primitive. 2// 3// license_tier: ORIGINAL 4// 5// Composes a populated outdoor settlement: an environment with a 6// settlement guaranteed + building counts + road density + market 7// presence. Distinct from simple_scene: emphasis on inhabited 8// structure, not landscape. Equivalent of `#townscape <modifier>`. 9// 10// Per S-class roadmap §A3 -- fifth slice. 11 12// nx_safety_envelope: 13// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 14// sil_target: SIL1 15// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 16// verdict: NOT_YET_EVALUATED 17 18import "nx_syscalls.nx" 19import "nx_types.nx" 20import "nx_tier.nx" 21import "nx_biome_classifier.nx" 22import "nx_decl_random_environment.nx" 23import "nx_decl_simple_scene.nx" 24const NX_MAGIC_1200: i64 = 1200 25const NX_MAGIC_8000: i64 = 8000 26 27// ---- Sealed enum: settlement kind -------------------------------- 28const NX_TOWN_KIND_HAMLET: nx_int = 0 // < 50 people 29const NX_TOWN_KIND_VILLAGE: nx_int = 1 // 50..500 30const NX_TOWN_KIND_TOWN: nx_int = 2 // 500..5000 31const NX_TOWN_KIND_CITY: nx_int = 3 // 5000+ 32const NX_TOWN_KIND_OUTPOST: nx_int = 4 // small frontier (sci-fi or fantasy) 33const NX_TOWN_KIND_METROPOLIS: nx_int = 5 // 100k+ (sci-fi) 34const NX_TOWN_KIND_N: nx_int = 6 35 36func nx_town_kind_is_valid(k: nx_int) -> nx_int { 37 if k < 0 { return 0 } 38 if k >= NX_TOWN_KIND_N { return 0 } 39 return 1 40} 41 42func nx_town_kind_name(k: nx_int) -> *u8 { 43 if k == NX_TOWN_KIND_HAMLET { return "HAMLET" as *u8 } 44 if k == NX_TOWN_KIND_VILLAGE { return "VILLAGE" as *u8 } 45 if k == NX_TOWN_KIND_TOWN { return "TOWN" as *u8 } 46 if k == NX_TOWN_KIND_CITY { return "CITY" as *u8 } 47 if k == NX_TOWN_KIND_OUTPOST { return "OUTPOST" as *u8 } 48 if k == NX_TOWN_KIND_METROPOLIS { return "METROPOLIS" as *u8 } 49 return "<invalid town>" as *u8 50} 51 52// ---- Output struct ----------------------------------------------- 53struct NxTownscape { 54 seed: nx_int, 55 modifier: nx_int, 56 scene: *NxSimpleScene, 57 kind: nx_int, // sealed enum NX_TOWN_KIND_* 58 building_count: nx_int, 59 road_count: nx_int, 60 market_present: nx_int, // 0 / 1 61 temple_present: nx_int, // 0 / 1 (or sci-fi: ritual-comp center) 62 population_log10: nx_int, // log10 of population estimate * 10 (Q1) 63 is_valid: nx_int, 64} 65 66// ---- Kind selection per modifier + seed -------------------------- 67func _ts_default_kind(modifier: nx_int, seed: nx_int) -> nx_int { 68 if modifier == NX_RE_MODIFIER_SCI_FI { 69 let r: nx_int = _re_hash_mod(seed, 31, 3) 70 if r == 0 { return NX_TOWN_KIND_OUTPOST } 71 if r == 1 { return NX_TOWN_KIND_CITY } 72 return NX_TOWN_KIND_METROPOLIS 73 } 74 if modifier == NX_RE_MODIFIER_FANTASY { 75 let r: nx_int = _re_hash_mod(seed, 31, 4) 76 if r == 0 { return NX_TOWN_KIND_HAMLET } 77 if r == 1 { return NX_TOWN_KIND_VILLAGE } 78 if r == 2 { return NX_TOWN_KIND_TOWN } 79 return NX_TOWN_KIND_CITY 80 } 81 // REAL: more weight on village/town (common in real worlds) 82 let r: nx_int = _re_hash_mod(seed, 31, 5) 83 if r == 0 { return NX_TOWN_KIND_HAMLET } 84 if r == 1 { return NX_TOWN_KIND_VILLAGE } 85 if r == 2 { return NX_TOWN_KIND_VILLAGE } 86 if r == 3 { return NX_TOWN_KIND_TOWN } 87 return NX_TOWN_KIND_CITY 88} 89 90func _ts_building_count(kind: nx_int) -> nx_int { 91 if kind == NX_TOWN_KIND_HAMLET { return 8 } 92 if kind == NX_TOWN_KIND_VILLAGE { return 40 } 93 if kind == NX_TOWN_KIND_TOWN { return 200 } 94 if kind == NX_TOWN_KIND_CITY { return NX_MAGIC_1200 } 95 if kind == NX_TOWN_KIND_OUTPOST { return 6 } 96 if kind == NX_TOWN_KIND_METROPOLIS { return NX_MAGIC_8000 } 97 return 0 98} 99 100func _ts_road_count(kind: nx_int) -> nx_int { 101 if kind == NX_TOWN_KIND_HAMLET { return 2 } 102 if kind == NX_TOWN_KIND_VILLAGE { return 4 } 103 if kind == NX_TOWN_KIND_TOWN { return 12 } 104 if kind == NX_TOWN_KIND_CITY { return 40 } 105 if kind == NX_TOWN_KIND_OUTPOST { return 1 } 106 if kind == NX_TOWN_KIND_METROPOLIS { return 200 } 107 return 0 108} 109 110// population_log10 returns log10 of approximate population * 10 (Q1). 111// HAMLET 25 (1.4 in log10 * 10 = 14), VILLAGE 200 -> 23, TOWN 2000 -> 33, 112// CITY 20000 -> 43, METROPOLIS 200000 -> 53, OUTPOST 20 -> 13. 113func _ts_population_log10(kind: nx_int) -> nx_int { 114 if kind == NX_TOWN_KIND_HAMLET { return 14 } 115 if kind == NX_TOWN_KIND_VILLAGE { return 23 } 116 if kind == NX_TOWN_KIND_TOWN { return 33 } 117 if kind == NX_TOWN_KIND_CITY { return 43 } 118 if kind == NX_TOWN_KIND_OUTPOST { return 13 } 119 if kind == NX_TOWN_KIND_METROPOLIS { return 53 } 120 return 0 121} 122 123// ---- Main declarator --------------------------------------------- 124func nx_decl_townscape(out: *NxTownscape, modifier: nx_int, seed: nx_int) -> nx_int { 125 if nx_re_modifier_is_valid(modifier) == 0 { 126 out.is_valid = 0 127 return 0 128 } 129 out.seed = seed 130 out.modifier = modifier 131 132 // Phase 1: scene composition. 133 let scene: *NxSimpleScene = nx_ss_alloc() 134 nx_decl_simple_scene(scene, modifier, seed) 135 if scene.is_valid == 0 { 136 out.is_valid = 0 137 return 0 138 } 139 out.scene = scene 140 141 // Phase 2: settlement kind + counts. 142 out.kind = _ts_default_kind(modifier, seed) 143 out.building_count = _ts_building_count(out.kind) 144 out.road_count = _ts_road_count(out.kind) 145 out.population_log10 = _ts_population_log10(out.kind) 146 147 // Phase 3: amenities. Market present iff kind >= VILLAGE. 148 var market: nx_int = 0 149 if out.kind != NX_TOWN_KIND_HAMLET { 150 if out.kind != NX_TOWN_KIND_OUTPOST { market = 1 } 151 } 152 out.market_present = market 153 // Temple/ritual-center present iff kind >= TOWN. 154 var temple: nx_int = 0 155 if out.kind == NX_TOWN_KIND_TOWN { temple = 1 } 156 if out.kind == NX_TOWN_KIND_CITY { temple = 1 } 157 if out.kind == NX_TOWN_KIND_METROPOLIS { temple = 1 } 158 out.temple_present = temple 159 160 out.is_valid = 1 161 return 1 162} 163 164func nx_ts_alloc() -> *NxTownscape { 165 let raw: *u8 = sys_mmap(256) 166 let t: *NxTownscape = raw as *NxTownscape 167 return t 168}