code wiki / (root) / nx_scene_contract.nx

nx_scene_contract.nx source

↩ module page · 186 lines · 7206 B

1// nx_scene_contract.nx -- THE style-spanning scene contract (exceed-ladder 2// R0; spec 2026-06-10-beat-top10-procgen-exceed-ladder.md). 3// 4// None of the top-10 procedural tools can take ONE character and insert it 5// into a realistic survival world, an anime world, a cartoon world and a 6// visual-novel backdrop without re-authoring assets. This contract makes 7// that a LAW of the substrate: 8// 9// identity = f(identity_seed) ONLY -- palette, build, face params. 10// style transforms PROPORTIONS and SHADING via the named tables below; 11// it must NEVER touch identity fields. 12// every style renderer consumes the SAME (*SceneWorld, *SceneEntity). 13// the entity anchors to terrain: feet on the ground in every style. 14// 15// Tiers (progressive disclosure, same as nx_procgen_preset): 16// Tier 0 nx_scene_quickstart(world_seed, human_seed, style, path) in 17// nx_scene_render.nx -- one call -> a PPM scene on disk. 18// Tier 1 nx_entity_human(seed) + nx_scene_world(seed, preset, style) 19// Tier 2 the proportion/palette tables below -- add a style = add rows. 20// license_tier: ORIGINAL 21 22import "nx_syscalls.nx" 23import "nx_tier.nx" 24import "nx_procgen_preset.nx" 25const NX_MAGIC_1103515245: i64 = 1103515245 26const NX_MAGIC_12345: i64 = 12345 27const NX_MAGIC_65536: i64 = 65536 28const NX_MAGIC_32768: i64 = 32768 29 30// ===== Sealed-enum: render styles ===================================== 31const NX_STYLE_REALISTIC: nx_int = 0 32const NX_STYLE_ANIME: nx_int = 1 33const NX_STYLE_CARTOON: nx_int = 2 34const NX_STYLE_VN: nx_int = 3 35const NX_STYLE_COUNT: nx_int = 4 36 37func nx_style_is_valid(s: nx_int) -> nx_int { 38 if s < 0 { return 0 } 39 if s >= NX_STYLE_COUNT { return 0 } 40 return 1 41} 42 43// ===== SceneEntity: the synthetic human ============================== 44// 16-slot i64 record (mmap-allocated; never a stack struct). 45const NX_ENT_IDENTITY: nx_int = 0 // identity seed (provenance) 46const NX_ENT_KIND: nx_int = 1 // 0 = human (sealed for later kinds) 47const NX_ENT_HEIGHT_Q10: nx_int = 2 // canonical body height (Q10 of world relief) 48const NX_ENT_BUILD_Q10: nx_int = 3 // 768 slim .. 1280 broad (shoulder factor) 49const NX_ENT_SKIN_RGB: nx_int = 4 // 0xRRGGBB 50const NX_ENT_HAIR_RGB: nx_int = 5 51const NX_ENT_OUTFIT_RGB: nx_int = 6 52const NX_ENT_EYE_RGB: nx_int = 7 53const NX_ENT_ANCHOR_X: nx_int = 8 // world cell the feet stand on 54const NX_ENT_ANCHOR_Y: nx_int = 9 55const NX_ENT_POSE: nx_int = 10 // 0 standing (sealed for later poses) 56const NX_ENT_SLOTS: nx_int = 16 57 58// deterministic LCG over the identity seed -- same seed, same human, forever 59func _ent_lcg(state: *i64) -> nx_int { 60 state[0] = state[0] * NX_MAGIC_1103515245 + NX_MAGIC_12345 61 var v: nx_int = (state[0] / NX_MAGIC_65536) % NX_MAGIC_32768 62 if v < 0 { v = 0 - v } 63 return v 64} 65 66// identity palettes: small curated tables, indexed by seed draws. Adding 67// a row widens the population; rows are data, not logic. 68func _ent_skin(i: nx_int) -> nx_int { 69 let k: nx_int = i % 5 70 if k == 0 { return 0xF5D5B8 } 71 if k == 1 { return 0xE0B089 } 72 if k == 2 { return 0xC68642 } 73 if k == 3 { return 0x8D5524 } 74 return 0x5C3A1E 75} 76func _ent_hair(i: nx_int) -> nx_int { 77 let k: nx_int = i % 6 78 if k == 0 { return 0x101010 } 79 if k == 1 { return 0x4A2F1B } 80 if k == 2 { return 0x8B5A2B } 81 if k == 3 { return 0xD8B863 } 82 if k == 4 { return 0xB22222 } 83 return 0x7A7A7A 84} 85func _ent_outfit(i: nx_int) -> nx_int { 86 let k: nx_int = i % 6 87 if k == 0 { return 0x2E5D34 } 88 if k == 1 { return 0x27408B } 89 if k == 2 { return 0x8B2E2E } 90 if k == 3 { return 0x6A4C93 } 91 if k == 4 { return 0x3B3B3B } 92 return 0xB8860B 93} 94func _ent_eye(i: nx_int) -> nx_int { 95 let k: nx_int = i % 4 96 if k == 0 { return 0x3B2716 } 97 if k == 1 { return 0x2F5D8A } 98 if k == 2 { return 0x3E6B3E } 99 return 0x555555 100} 101 102// Tier-1: mint a synthetic human from an identity seed. EVERY field here 103// is identity -- style renderers read, never write. 104func nx_entity_human(identity_seed: nx_int) -> *i64 { 105 let e: *i64 = sys_mmap(NX_ENT_SLOTS * 8) as *i64 106 let st: *i64 = sys_mmap(16) as *i64 107 st[0] = identity_seed 108 e[NX_ENT_IDENTITY] = identity_seed 109 e[NX_ENT_KIND] = 0 110 // height: 900..1100 Q10 around the canonical 1.0 111 e[NX_ENT_HEIGHT_Q10] = 900 + (_ent_lcg(st) % 201) 112 // build: 768..1280 113 e[NX_ENT_BUILD_Q10] = 768 + (_ent_lcg(st) % 513) 114 e[NX_ENT_SKIN_RGB] = _ent_skin(_ent_lcg(st)) 115 e[NX_ENT_HAIR_RGB] = _ent_hair(_ent_lcg(st)) 116 e[NX_ENT_OUTFIT_RGB] = _ent_outfit(_ent_lcg(st)) 117 e[NX_ENT_EYE_RGB] = _ent_eye(_ent_lcg(st)) 118 e[NX_ENT_ANCHOR_X] = 0 119 e[NX_ENT_ANCHOR_Y] = 0 120 e[NX_ENT_POSE] = 0 121 return e 122} 123 124// ===== Style proportion tables (Tier-2 data) ========================== 125// head height as Q10 fraction of body height -- THE style signature. 126// realistic ~1/7.5; anime ~1/5; cartoon ~1/3; VN portrait ~1/4.5. 127func nx_style_head_ratio_q10(style: nx_int) -> nx_int { 128 if style == NX_STYLE_REALISTIC { return 137 } 129 if style == NX_STYLE_ANIME { return 205 } 130 if style == NX_STYLE_CARTOON { return 341 } 131 if style == NX_STYLE_VN { return 228 } 132 return 137 133} 134// on-screen body height in pixels (VN sprites render large) 135func nx_style_px_height(style: nx_int) -> nx_int { 136 if style == NX_STYLE_VN { return 96 } 137 if style == NX_STYLE_CARTOON { return 56 } 138 return 48 139} 140// 1 = draw a dark outline around the figure (cartoon law) 141func nx_style_outline(style: nx_int) -> nx_int { 142 if style == NX_STYLE_CARTOON { return 1 } 143 return 0 144} 145// 1 = draw eye dots (anime/VN faces read through the eyes) 146func nx_style_eyes(style: nx_int) -> nx_int { 147 if style == NX_STYLE_ANIME { return 1 } 148 if style == NX_STYLE_VN { return 1 } 149 return 0 150} 151// terrain elevation bands for cel shading (0 = continuous gradient) 152func nx_style_terrain_bands(style: nx_int) -> nx_int { 153 if style == NX_STYLE_ANIME { return 5 } 154 if style == NX_STYLE_CARTOON { return 3 } 155 return 0 156} 157 158// ===== SceneWorld ===================================================== 159// 8-slot record: the landscape + the style it will be rendered under. 160const NX_SW_LAND: nx_int = 0 // *Landscape 161const NX_SW_STYLE: nx_int = 1 162const NX_SW_SEED: nx_int = 2 163const NX_SW_PRESET: nx_int = 3 164const NX_SW_SLOTS: nx_int = 8 165 166func nx_scene_world(world_seed: nx_int, preset: nx_int, style: nx_int) -> *i64 { 167 let sw: *i64 = sys_mmap(NX_SW_SLOTS * 8) as *i64 168 var st: nx_int = style 169 if nx_style_is_valid(st) == 0 { st = NX_STYLE_REALISTIC } 170 let land: *Landscape = nx_procgen_landscape(world_seed, preset, 171 NX_PROCGEN_DEFAULT_WIDTH, 172 NX_PROCGEN_DEFAULT_HEIGHT, 173 NX_PROCGEN_DEFAULT_DENSITY_Q10) 174 sw[NX_SW_LAND] = land as i64 175 sw[NX_SW_STYLE] = st 176 sw[NX_SW_SEED] = world_seed 177 sw[NX_SW_PRESET] = preset 178 return sw 179} 180 181// place the entity's feet on a world cell (the insertion point) 182func nx_scene_place(e: *i64, x: nx_int, y: nx_int) -> nx_int { 183 e[NX_ENT_ANCHOR_X] = x 184 e[NX_ENT_ANCHOR_Y] = y 185 return 0 186}