code wiki / _hdl_build / nx_wardrobe_state.nx
nx_wardrobe_state.nx source
↩ module page · 137 lines · 5600 B
1// nx_wardrobe_state.nx -- THE WARDROBE / EXPOSURE / TRANSFORMATION STATE MACHINE (certified composable PART).
2// nx_gamebench ranked its capabilities: adult-gating-by-construction (blocks all 10 adult reference titles)
3// and wardrobe-state-coherence (blocks 3) top the gap_queue. This part eats both.
4//
5// It is the game-side twin of the companion keystone F975 (a character dresses herself + STAYS coherent):
6// a body is a set of ZONES each with a coverage LEVEL; the state can never self-contradict, round-trips
7// through the certified save part bit-exact, and -- the point -- FAILS CLOSED on age<18 BY CONSTRUCTION,
8// the nx_card_compile refusal pattern generalized to a reusable game part.
9//
10// Built as a LIB (no main) per knowledge/registry/game_parts.tsv doctrine so every emitted adult title
11// inherits these properties for free. Composes nx_gamesave (the certified persistence part).
12// license_tier: ORIGINAL expect_exit: 0
13import "nx_syscalls.nx"
14import "nx_gamesave.nx"
15
16// ---- model constants (data-driven thresholds, rule 11: named, not magic) ----
17const WS_NZ: i64 = 8 // zones: 0 head 1 torso 2 chest 3 waist 4 hips 5 legs 6 feet 7 hands
18const WS_MAXCOV: i64 = 4 // 0 nude, 1 underwear, 2 modest, 3 dressed, 4 outerwear
19const WS_MODEST: i64 = 2 // coverage >= WS_MODEST = NOT sexually exposed
20const WS_ADULT_AGE: i64 = 18 // fail-closed threshold (matches nx_card_compile)
21const WS_NMORPH: i64 = 8 // transformation forms 0..WS_NMORPH-1 (species/morph, humanoid-only)
22const WS_LEN: i64 = 10 // i64 state vector: [0]=age [1]=morph [2..9]=coverage per zone
23const WS_SCHEMA: i64 = 975 // save schema id (F975 lineage)
24const WS_CK_SEED: i64 = 2166136261
25const WS_CK_MUL: i64 = 16777619
26
27// error codes (all negative, all distinct)
28const WS_E_MINOR: i64 = 0-1 // adult gate: would expose a gated zone on a minor -> REFUSED
29const WS_E_ZONE: i64 = 0-2
30const WS_E_COV: i64 = 0-3
31const WS_E_INCOHERENT: i64 = 0-4 // load refused: persisted state violates an invariant
32const WS_E_MORPH: i64 = 0-5
33
34func ws_len() -> i64 { return WS_LEN }
35
36// the two zones whose exposure is sexual and therefore adult-gated (chest, hips)
37func ws_is_gated_zone(z: i64) -> i64 {
38 if z==2 { return 1 }
39 if z==4 { return 1 }
40 return 0
41}
42
43// initialize a body: fully DRESSED (WS_MAXCOV) by default. age may be any value >=0 -- a minor may EXIST,
44// they simply can never be placed in an exposed wardrobe state (that is the fail-closed rule below).
45func ws_init(w: *i64, age: i64, morph: i64) -> i64 {
46 w[0] = age
47 var mm: i64 = morph
48 if mm < 0 { mm = 0 }
49 if mm >= WS_NMORPH { mm = 0 }
50 w[1] = mm
51 var z: i64 = 0
52 while z < WS_NZ { w[2+z] = WS_MAXCOV; z = z+1 }
53 return 0
54}
55
56// set a single zone's coverage. ADULT GATE BY CONSTRUCTION: on a minor, any attempt to drop a gated
57// zone below WS_MODEST is REFUSED and the state is left BIT-IDENTICAL (never a partial mutation).
58func ws_set(w: *i64, zone: i64, cov: i64) -> i64 {
59 if zone < 0 { return WS_E_ZONE }
60 if zone >= WS_NZ { return WS_E_ZONE }
61 if cov < 0 { return WS_E_COV }
62 if cov > WS_MAXCOV { return WS_E_COV }
63 var minor: i64 = 0
64 if w[0] < WS_ADULT_AGE { minor = 1 }
65 if minor == 1 {
66 if ws_is_gated_zone(zone) == 1 {
67 if cov < WS_MODEST { return WS_E_MINOR }
68 }
69 }
70 w[2+zone] = cov
71 return 0
72}
73
74// transformation-morph: change species/form. Coherence-preserving (range-checked); state otherwise intact.
75func ws_morph(w: *i64, new_morph: i64) -> i64 {
76 if new_morph < 0 { return WS_E_MORPH }
77 if new_morph >= WS_NMORPH { return WS_E_MORPH }
78 w[1] = new_morph
79 return 0
80}
81
82// derived scene-intent scalar: higher = more exposed. Pure function of state.
83func ws_exposure(w: *i64) -> i64 {
84 var s: i64 = 0
85 var z: i64 = 0
86 while z < WS_NZ { s = s + (WS_MAXCOV - w[2+z]); z = z+1 }
87 return s
88}
89
90// THE COHERENCE CHECK. Returns 1 iff every invariant holds -- range validity AND the adult invariant.
91// A game calls this after load / after any external mutation; a violating state is detectably invalid.
92func ws_coherent(w: *i64) -> i64 {
93 if w[0] < 0 { return 0 }
94 if w[1] < 0 { return 0 }
95 if w[1] >= WS_NMORPH { return 0 }
96 var minor: i64 = 0
97 if w[0] < WS_ADULT_AGE { minor = 1 }
98 var z: i64 = 0
99 while z < WS_NZ {
100 let c: i64 = w[2+z]
101 if c < 0 { return 0 }
102 if c > WS_MAXCOV { return 0 }
103 if minor == 1 {
104 if ws_is_gated_zone(z) == 1 {
105 if c < WS_MODEST { return 0 }
106 }
107 }
108 z = z+1
109 }
110 return 1
111}
112
113// order-sensitive rolling checksum over the state vector (a swapped pair changes it). Determinism witness.
114func ws_ck(w: *i64) -> i64 {
115 var h: i64 = WS_CK_SEED
116 var i: i64 = 0
117 while i < WS_LEN {
118 h = h ^ (w[i] & 0x7FFFFFFFFFFFFFFF)
119 h = (h * WS_CK_MUL) & 0x7FFFFFFFFFFFFFFF
120 i = i+1
121 }
122 return h
123}
124
125// PERSISTENCE via the certified save part -- inherits atomic + bit-exact + corruption-refused + additive.
126func ws_save(w: *i64, path: *u8, saved_at: i64) -> i64 {
127 return gs_save(path, WS_SCHEMA, w, WS_LEN, saved_at)
128}
129
130// load then RE-VALIDATE coherence: a persisted wardrobe that violates an invariant is REFUSED, never
131// loaded (the coherence guarantee holds across persistence, not just in memory).
132func ws_load(w: *i64, path: *u8) -> i64 {
133 let r: i64 = gs_load(path, w, WS_LEN, 0 as *i64)
134 if r < 0 { return r }
135 if ws_coherent(w) == 0 { return WS_E_INCOHERENT }
136 return r
137}