code wiki / _hdl_build / nx_coc_engine.nx
nx_coc_engine.nx source
↩ module page · 231 lines · 11276 B
1// nx_coc_engine.nx -- M1 MILESTONE: a Corruption-of-Champions-class TEXT-RPG ENGINE emitted by COMPOSING
2// certified parts. This is the recombinator claim made concrete for the adult-emitter program: a playable
3// branching text RPG with stats, transformation, adult-gated wardrobe, and persistence -- ZERO new game
4// logic, only composition of parts each certified-to-exceed ONCE (game_parts.tsv doctrine).
5//
6// PLOT nx_plotgen (pg_gen) -- generates a SOLVABLE branching narrative graph
7// EXECUTION nx_story_vm (sv_choose) -- runs the graph as a data-driven state machine
8// STATS nx_rpgstats (rs_*) -- XP curve, level, saturating HP, skill
9// BODY nx_wardrobe_state (ws_*) -- clothing/exposure/TRANSFORMATION, ADULT-GATED by construction
10// SAVE nx_gamesave (gs_save) -- atomic bit-exact persistence
11//
12// SELF-PROVING (self-gating like nx_frontier_engine): P1 winnable, P2 LOSABLE (a CoC-class game MUST be
13// losable or it is hollow), P3 deterministic, P4 save/load transparent, P5 ADULT-GATE HOLDS THROUGH THE
14// WHOLE LOOP (a minor can never reach an exposed wardrobe state, and an ADULT on the same seed DOES -- the
15// gate is real AND targeted), P6 solvable (the generated plot has a reachable ending).
16//
17// HONEST SCOPE: this is the ENGINE (state machine + stats + transformation + adult-gating + persistence).
18// Narrative PROSE slots into the story-graph nodes as a later LLM-authored rung (nx_story_vm's design).
19// Emits a JSON proof line so agents/workflows can emit-and-prove an M1 game on demand (MCP tool).
20// license_tier: ORIGINAL expect_exit: 0
21import "nx_syscalls.nx"
22import "nx_gamesave.nx"
23import "nx_rpgstats.nx"
24import "nx_story_vm.nx"
25import "nx_plotgen.nx"
26import "nx_wardrobe_state.nx"
27const CE_MAGIC_20260724: i64 = 20260724
28const CE_MAGIC_424242: i64 = 424242
29const CE_MAGIC_4096: i64 = 4096
30
31const CE_NODES: i64 = 12
32const CE_LEN: i64 = 16 // save vector: [0]node [1]flags [2]hp [3]xp [4]level [5]cycle [6..15]wardrobe(10)
33const CE_MAXHP: i64 = 100
34const CE_TARGET: i64 = 3 // win requires level >= this
35const CE_HAZ_PCT: i64 = 45 // chance a node is a hazard
36const CE_HEAL: i64 = 8 // cautious recovers between nodes
37const CE_TOLL: i64 = 22 // reckless pays a detour toll in HP
38const CE_XPBASE: i64 = 100
39const CE_XPQUAD: i64 = 20
40const CE_M63: i64 = 0x7FFFFFFFFFFFFFFF
41const CE_FNV: i64 = 1099511628211
42const CE_MIXA: i64 = 2654435761
43const CE_MIXB: i64 = 1274126177
44
45func ce_hash(node: i64, seed: i64) -> i64 {
46 var h: i64 = seed ^ (node * CE_MIXA)
47 h = (h ^ (h >> 13)) * CE_MIXB
48 h = h ^ (h >> 7)
49 return h & CE_M63
50}
51
52// run one playthrough. policy 0=cautious(spine,heal) 1=reckless(detour,toll). fills V; res[0]=outcome(1 win/
53// 0 lose) res[1]=frame_chain res[2]=final_level res[3]=cycles res[4]=exposure_attempts.
54func ce_run(V: *i64, res: *i64, seed: i64, policy: i64, age: i64) -> i64 {
55 let N: i64 = CE_NODES
56 let ct: *i64 = sys_mmap(N*SV_NCH*8) as *i64
57 let cq: *i64 = sys_mmap(N*SV_NCH*8) as *i64
58 let cs: *i64 = sys_mmap(N*SV_NCH*8) as *i64
59 let ie: *i64 = sys_mmap(N*8) as *i64
60 pg_gen(ct, cq, cs, ie, N, seed)
61
62 var z: i64 = 0
63 while z < CE_LEN { V[z] = 0; z = z+1 }
64 V[0] = 0 // node
65 V[2] = CE_MAXHP // hp
66 V[4] = 1 // level
67 let w: *i64 = (V as i64 + 48) as *i64 // wardrobe sub-vector at V[6]
68 ws_init(w, age, 0)
69
70 var fck: i64 = seed & CE_M63
71 var expo: i64 = 0
72 var running: i64 = 1
73 var steps: i64 = 0
74 let maxsteps: i64 = N * 3
75 while running == 1 {
76 let node: i64 = V[0]
77 if steps >= maxsteps { running = 0 }
78 if running == 1 { if sv_is_end(ie, node) == 1 { running = 0 } }
79 if running == 1 { if V[2] <= 0 { running = 0 } }
80 if running == 1 {
81 let h: i64 = ce_hash(node, seed)
82 // encounter reward
83 let xpgain: i64 = 20 + (h % 30)
84 V[3] = rs_sadd(V[3], xpgain)
85 V[4] = rs_level_for_xp(V[3], CE_XPBASE, CE_XPQUAD)
86 // hazard toll
87 let hz: i64 = (h / 100) % 100
88 if hz < CE_HAZ_PCT { V[2] = V[2] - (15 + (h % 20)) }
89 // transformation on some nodes (form change; coherence-preserving)
90 if (h % 7) == 0 { ws_morph(w, (h / 7) % WS_NMORPH) }
91 // wardrobe exposure ATTEMPT on some nodes -> ADULT-GATED (refused for a minor, state intact)
92 if (h % 5) == 0 { expo = expo + 1; ws_set(w, 2, 0) }
93 // choose next by policy
94 var nxt: i64 = 0-1
95 if policy == 0 {
96 V[2] = rs_clamp(V[2] + CE_HEAL, 0, CE_MAXHP)
97 nxt = sv_choose(ct, cq, cs, node, 0, (V as i64 + 8) as *i64)
98 }
99 if policy == 1 {
100 // RUSH: never rest, pay a toll at every node, push the spine through every hazard.
101 // Genre-honest stakes: without resting the HP/hazard system genuinely kills you.
102 V[2] = V[2] - CE_TOLL
103 nxt = sv_choose(ct, cq, cs, node, 0, (V as i64 + 8) as *i64)
104 }
105 if nxt < 0 { nxt = sv_choose(ct, cq, cs, node, 0, (V as i64 + 8) as *i64) }
106 if nxt < 0 { running = 0 }
107 if nxt >= 0 {
108 V[0] = nxt
109 V[5] = V[5] + 1
110 fck = (fck * CE_FNV) ^ (V[0] + V[2]*7 + V[4]*13 + ws_exposure(w)*17)
111 fck = fck & CE_M63
112 }
113 steps = steps + 1
114 }
115 }
116 var outcome: i64 = 0
117 if sv_is_end(ie, V[0]) == 1 { if V[2] > 0 { if V[4] >= CE_TARGET { outcome = 1 } } }
118 res[0] = outcome
119 res[1] = fck
120 res[2] = V[4]
121 res[3] = V[5]
122 res[4] = expo
123 return outcome
124}
125
126func jc(o: *u8, at: i64, s: *u8) -> i64 { var i: i64=0; var a: i64=at; while s[i]!=(0 as u8){o[a]=s[i]; a=a+1; i=i+1} return a }
127func jn(o: *u8, at: i64, v: i64) -> i64 {
128 var a: i64=at; var m: i64=v
129 if m==0 { o[a]=48 as u8; return a+1 }
130 if m<0 { o[a]=45 as u8; a=a+1; m=0-m }
131 let t: *u8=sys_mmap(32); var k: i64=0
132 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
133 var q: i64=k-1
134 while q>=0 { o[a]=t[q]; a=a+1; q=q-1 }
135 return a
136}
137
138func main() -> i64 {
139 let ADULT_SEED: i64 = CE_MAGIC_20260724
140 let LOSE_SEED: i64 = 777
141
142 let Vw: *i64 = sys_mmap(CE_LEN*8) as *i64 // adult cautious (winner)
143 let rW: *i64 = sys_mmap(8*8) as *i64
144 ce_run(Vw, rW, ADULT_SEED, 0, 25)
145
146 // P2: reckless on a hazard seed dies
147 let Vl: *i64 = sys_mmap(CE_LEN*8) as *i64
148 let rL: *i64 = sys_mmap(8*8) as *i64
149 ce_run(Vl, rL, LOSE_SEED, 1, 25)
150
151 // P3: determinism -- same seed+policy twice -> identical frame chain
152 let Vd: *i64 = sys_mmap(CE_LEN*8) as *i64
153 let rD: *i64 = sys_mmap(8*8) as *i64
154 ce_run(Vd, rD, ADULT_SEED, 0, 25)
155
156 // P4: save/load transparent -- save the winner, load into a ZEROED vector, compare
157 let wrote: i64 = gs_save("knowledge/nx_coc_save.sav" as *u8, 900, Vw, CE_LEN, CE_MAGIC_424242)
158 let Vp: *i64 = sys_mmap(CE_LEN*8) as *i64
159 var zz: i64 = 0
160 while zz < CE_LEN { Vp[zz] = 0; zz = zz+1 }
161 let got: i64 = gs_load("knowledge/nx_coc_save.sav" as *u8, Vp, CE_LEN, 0 as *i64)
162 var loadok: i64 = 1
163 if got != CE_LEN { loadok = 0 }
164 zz = 0
165 while zz < CE_LEN { if Vp[zz] != Vw[zz] { loadok = 0 } zz = zz+1 }
166
167 // P5: adult gate holds through the WHOLE loop. Minor run vs adult run on the SAME seed.
168 let Vm: *i64 = sys_mmap(CE_LEN*8) as *i64
169 let rM: *i64 = sys_mmap(8*8) as *i64
170 ce_run(Vm, rM, ADULT_SEED, 0, 16) // a 16-year-old
171 let wm: *i64 = (Vm as i64 + 48) as *i64
172 let wa: *i64 = (Vw as i64 + 48) as *i64
173 // chest is zone 2 -> wardrobe slot w[2+2]=w[4]
174 let minor_chest: i64 = wm[4]
175 let adult_chest: i64 = wa[4]
176 var gate_held: i64 = 0
177 // minor's chest NEVER dropped below modest (exposure refused), AND coherent, AND at least one attempt happened
178 if minor_chest >= WS_MODEST { if ws_coherent(wm) == 1 { if rM[4] > 0 { gate_held = 1 } } }
179 // targeted: an ADULT on the same seed with attempts DID expose (gate is not a blanket disable)
180 var gate_targeted: i64 = 0
181 if adult_chest < WS_MODEST { if rW[4] > 0 { gate_targeted = 1 } }
182
183 // P6: solvability -- the generated plot has a reachable ending via pg_walk
184 let ct: *i64 = sys_mmap(CE_NODES*SV_NCH*8) as *i64
185 let cq: *i64 = sys_mmap(CE_NODES*SV_NCH*8) as *i64
186 let cs: *i64 = sys_mmap(CE_NODES*SV_NCH*8) as *i64
187 let ie: *i64 = sys_mmap(CE_NODES*8) as *i64
188 pg_gen(ct, cq, cs, ie, CE_NODES, ADULT_SEED)
189 let endnode: i64 = pg_walk(ct, cq, cs, ie, CE_NODES, CE_NODES*3)
190
191 // ---- verdicts ----
192 var p1: i64 = 0
193 if rW[0] == 1 { p1 = 1 } // adult cautious WON
194 var p2: i64 = 0
195 if rL[0] == 0 { if Vl[2] <= 0 { p2 = 1 } } // reckless LOST by dying
196 var p3: i64 = 0
197 if rD[1] == rW[1] { p3 = 1 } // determinism: identical frame chain
198 var p4: i64 = loadok
199 if wrote <= 0 { p4 = 0 }
200 var p5: i64 = 0
201 if gate_held == 1 { if gate_targeted == 1 { p5 = 1 } }
202 var p6: i64 = 0
203 if endnode >= 0 { if sv_is_end(ie, endnode) == 1 { p6 = 1 } }
204 let pass: i64 = p1 + p2 + p3 + p4 + p5 + p6
205
206 let jb: *u8 = sys_mmap(CE_MAGIC_4096)
207 var j: i64 = 0
208 j = jc(jb, j, "{\x22game\x22:\x22nx_coc_engine\x22,\x22class\x22:\x22CoC-class text-RPG engine (composed certified parts)\x22" as *u8)
209 j = jc(jb, j, ",\x22proofs_pass\x22:" as *u8); j = jn(jb, j, pass); j = jc(jb, j, ",\x22proofs_total\x22:6" as *u8)
210 j = jc(jb, j, ",\x22P1_winnable\x22:" as *u8); j = jn(jb, j, p1)
211 j = jc(jb, j, ",\x22P2_losable\x22:" as *u8); j = jn(jb, j, p2)
212 j = jc(jb, j, ",\x22P3_deterministic\x22:" as *u8); j = jn(jb, j, p3)
213 j = jc(jb, j, ",\x22P4_save_transparent\x22:" as *u8); j = jn(jb, j, p4)
214 j = jc(jb, j, ",\x22P5_adult_gate_holds\x22:" as *u8); j = jn(jb, j, p5)
215 j = jc(jb, j, ",\x22P6_solvable\x22:" as *u8); j = jn(jb, j, p6)
216 j = jc(jb, j, ",\x22win_level\x22:" as *u8); j = jn(jb, j, rW[2])
217 j = jc(jb, j, ",\x22win_cycles\x22:" as *u8); j = jn(jb, j, rW[3])
218 j = jc(jb, j, ",\x22lose_hp\x22:" as *u8); j = jn(jb, j, Vl[2])
219 j = jc(jb, j, ",\x22lose_cycles\x22:" as *u8); j = jn(jb, j, rL[3])
220 j = jc(jb, j, ",\x22minor_chest_cov\x22:" as *u8); j = jn(jb, j, minor_chest)
221 j = jc(jb, j, ",\x22adult_chest_cov\x22:" as *u8); j = jn(jb, j, adult_chest)
222 j = jc(jb, j, ",\x22exposure_attempts\x22:" as *u8); j = jn(jb, j, rW[4])
223 j = jc(jb, j, ",\x22frame_chain\x22:" as *u8); j = jn(jb, j, rW[1])
224 j = jc(jb, j, ",\x22nodes\x22:" as *u8); j = jn(jb, j, CE_NODES)
225 j = jc(jb, j, ",\x22parts\x22:\x22plotgen+story_vm+rpgstats+wardrobe_state+gamesave\x22" as *u8)
226 j = jc(jb, j, ",\x22honest\x22:\x22ENGINE (state machine+stats+transformation+adult-gating+persistence); prose slots into story-graph nodes as a later LLM-authored rung. Adult invariant fails closed BY CONSTRUCTION through the whole loop.\x22}" as *u8)
227 sys_write(1, jb, j)
228 sys_write(1, "\n" as *u8, 1)
229 if pass != 6 { return 1 }
230 return 0
231}