code wiki / _hdl_build / nx_drift_engine.nx
nx_drift_engine.nx source
↩ module page · 269 lines · 13551 B
1// nx_drift_engine.nx -- the SOVEREIGN engine behind /world/drift: "Nishi Drift", a SURVIVAL game emitted
2// by composing certified parts in a DIFFERENT mix than Frontier (no worldsim -- survival is depletion,
3// not a conserved economy). Stranded on a dying hauler: oxygen + hull bleed each cycle, scavenge sector
4// wrecks (loot tiers), dive deep for double parts at the cost of hull or grab safe to recover air, repair
5// the beacon (60 parts) and survive to cycle 12 for rescue -- or die. Proves the recombinator composes
6// into a SECOND genre. The proof battery is genre-honest: the flagship is LOSABILITY (a survival game that
7// cannot be lost is hollow), not conservation.
8// Parts: nx_loottable · nx_rpgstats (rising scavenge skill) · nx_gamehud + nx_wire_harness (risk/safe
9// menu) · nx_game_raster (render) · nx_gamesave · nx_frame_sanity (via harness) · nx_png_write.
10// license_tier: ORIGINAL expect_exit: 0
11import "nx_syscalls.nx"
12import "nx_loottable.nx"
13import "nx_rpgstats.nx"
14import "nx_gamehud.nx"
15import "nx_game_raster.nx"
16import "nx_wire_harness.nx"
17import "nx_gamesave.nx"
18import "nx_png_write.nx"
19import "nx_game_depth.nx"
20import "nx_game_art.nx"
21import "nx_game_critic.nx"
22const WIN_MAGIC_1469598103: i64 = 1469598103
23const WIN_MAGIC_20260721: i64 = 20260721
24const WIN_MAGIC_7402: i64 = 7402
25const WIN_MAGIC_2000: i64 = 2000
26
27const NS: i64 = 5
28const FW: i64 = 400
29const FH: i64 = 240
30const WORDS: i64 = 512
31const WIN_CYCLE: i64 = 12
32const WIN_PARTS: i64 = 60
33const F_TICK:i64=0
34const F_SEC: i64=1
35const F_CYC: i64=2
36const F_OXY: i64=3
37const F_HULL:i64=4
38const F_PARTS:i64=5
39const F_SCAV:i64=6
40const F_SKILL:i64=7
41const F_DEEP:i64=8
42const F_WIN: i64=9
43const F_LOSE:i64=10
44const F_RNG: i64=11
45const F_PX: i64=12
46const F_PY: i64=13
47const F_CUR: i64=14 // current wreck tier
48const F_HDR: i64=24
49const O_HUD: i64=32
50func g_hud(g: *i64) -> *i64 { return (g as i64 + O_HUD*8) as *i64 }
51func d_rng(g: *i64) -> i64 {
52 var x: i64=g[F_RNG]
53 x = x ^ (x << 13); x = x ^ (x >> 7); x = x ^ (x << 17)
54 g[F_RNG]=x
55 if x<0 { return 0-x }
56 return x
57}
58func sec_x(i: i64) -> i64 { return 44 + i*76 }
59func sec_y(i: i64) -> i64 { if i%2==0 { return 84 } else { return 150 } }
60
61func de_new(g: *i64, seed: i64) -> i64 {
62 var i: i64=0
63 while i<WORDS { g[i]=0; i=i+1 }
64 g[F_RNG]=seed
65 if g[F_RNG]==0 { g[F_RNG]=1 }
66 g[F_OXY]=100
67 g[F_HULL]=100
68 g[F_SKILL]=1
69 g[F_PX]=sec_x(0)
70 g[F_PY]=sec_y(0)
71 gh_init(g_hud(g), 5)
72 return 0
73}
74func loot_weights(wts: *i64) -> i64 { wts[0]=520; wts[1]=280; wts[2]=120; wts[3]=60; wts[4]=20; return 0 }
75
76// one cycle; policy 1 = dive deep (item 0), policy 0 = safe grab (item 0). Returns 0.
77func de_tick(g: *i64, policy: i64) -> i64 {
78 if g[F_WIN]==1 { return 0 }
79 if g[F_LOSE]==1 { return 0 }
80 let hud: *i64 = g_hud(g)
81 g[F_SEC]=(g[F_SEC]+1)%NS
82 g[F_PX]=sec_x(g[F_SEC])
83 g[F_PY]=sec_y(g[F_SEC])
84 g[F_CYC]=g[F_CYC]+1
85 g[F_OXY]=g[F_OXY]-8
86 let wts: *i64 = sys_mmap(NS*8) as *i64
87 loot_weights(wts)
88 let tier: i64 = lt_pick(wts, 5, d_rng(g)%1000)
89 g[F_CUR]=tier
90 if g[F_OXY]<=0 { g[F_LOSE]=1; return 0 }
91 // rising scavenge skill from uses (rpgstats), lifts every yield
92 g[F_SKILL]=1+rs_skill_rank(g[F_SCAV], 4, 5)
93 let base: i64 = (tier+1)*(3+g[F_SKILL])
94 // risk/safe decision THROUGH THE MENU (causal): item 0 is the policy action, returned id drives it.
95 var id_a: i64=2
96 var id_b: i64=1
97 if policy==1 { id_a=1; id_b=2 } // policy 1 -> item0 = DIVE (id 1); policy 0 -> item0 = SAFE (id 2)
98 let dec: i64 = wh_menu_pick2(hud, id_a, base*2, id_b, base)
99 if dec==1 {
100 g[F_DEEP]=g[F_DEEP]+1
101 g[F_PARTS]=g[F_PARTS]+base*2
102 let hazard: i64 = 6 + d_rng(g)%16
103 g[F_HULL]=g[F_HULL]-hazard
104 g[F_OXY]=g[F_OXY]-4
105 }
106 if dec==2 {
107 g[F_PARTS]=g[F_PARTS]+base
108 g[F_OXY]=g[F_OXY]+3
109 }
110 g[F_SCAV]=g[F_SCAV]+1
111 if g[F_HULL]<=0 { g[F_LOSE]=1; return 0 }
112 if g[F_OXY]<=0 { g[F_LOSE]=1; return 0 }
113 if g[F_OXY]>100 { g[F_OXY]=100 }
114 if g[F_PARTS]>=WIN_PARTS { if g[F_CYC]>=WIN_CYCLE { g[F_WIN]=1 } }
115 g[F_TICK]=g[F_TICK]+1
116 return 0
117}
118
119func de_render(g: *i64, fb: *i64) -> i64 {
120 art_nebula(fb, FW, FH, 9, 5, 18, 34, 16, 52) // survival: deep purple-red nebula gradient
121 art_stardust(fb, FW, FH, 150)
122 var f: i64=0
123 while f<NS { gr_hline(fb, FW, FH, sec_x(f), sec_x((f+1)%NS), (sec_y(f)+sec_y((f+1)%NS))/2, gr_pack(38,28,58)); f=f+1 }
124 f=0
125 while f<NS {
126 let cx: i64=sec_x(f)
127 let cy: i64=sec_y(f)
128 var cr: i64=120
129 var cg: i64=150
130 var cb: i64=240
131 if f==1 { cr=210; cg=110; cb=150 }
132 if f==2 { cr=110; cg=200; cb=170 }
133 if f==3 { cr=228; cg=180; cb=90 }
134 if f==4 { cr=180; cg=120; cb=220 }
135 art_glow_orb(fb, FW, FH, cx, cy, 17, cr, cg, cb) // glowing wreck
136 gr_disc(fb, FW, FH, cx, cy, 7, gr_pack(10,8,20)) // dark salvage core (the ring look)
137 f=f+1
138 }
139 let px: i64=g[F_PX]
140 let py: i64=g[F_PY]
141 gr_disc(fb, FW, FH, px, py, 5, gr_pack(232,240,255))
142 gr_disc(fb, FW, FH, px, py, 8, gr_pack(60,90,140))
143 gr_disc(fb, FW, FH, px, py, 4, gr_pack(232,240,255))
144 // HUD: oxygen (cyan) + hull (red) meters, parts + cycle
145 gr_rect(fb, FW, FH, 0, 206, FW-1, FH-1, gr_pack(14,10,28))
146 art_meter(fb, FW, FH, 4, 211, 180, 6, g[F_OXY]*180/100, 40,120,140, 90,210,225)
147 art_meter(fb, FW, FH, 4, 220, 180, 6, g[F_HULL]*180/100, 120,50,60, 225,122,138)
148 var pb: i64 = g[F_PARTS]*140/WIN_PARTS
149 if pb>140 { pb=140 }
150 art_meter(fb, FW, FH, 210, 211, 140, 6, pb, 110,90,50, 210,185,110)
151 var lp: i64=0
152 while lp<g[F_CYC] { if lp<WIN_CYCLE { gr_rect(fb, FW, FH, 210+lp*13, 221, 218+lp*13, 226, gr_pack(150,140,200)) } lp=lp+1 }
153 return 0
154}
155func de_fbck(fb: *i64) -> i64 { return wh_fbck(fb, FW*FH) }
156func de_quality(fb: *i64) -> i64 {
157 let m: *i64 = sys_mmap(GC_N*8) as *i64
158 gc_score(fb, FW, FH, m)
159 return gc_quality(m)
160}
161func de_png(fb: *i64, path: *u8) -> i64 {
162 let rgb: *u8 = sys_mmap(FW*FH*3)
163 var p: i64=0
164 let n: i64=FW*FH
165 while p<n { let v: i64=fb[p]; rgb[p*3]=(v & 0xff) as u8; rgb[p*3+1]=((v>>8) & 0xff) as u8; rgb[p*3+2]=((v>>16) & 0xff) as u8; p=p+1 }
166 return nx_png_write_rgb(path, rgb, FW, FH)
167}
168func ww(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
169func wn(v: i64) -> i64 {
170 if v==0 { sys_write(1,"0" as *u8,1); return 0 }
171 var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m }
172 let t: *u8=sys_mmap(32); var k: i64=0
173 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
174 let o: *u8=sys_mmap(32); var q: i64=k-1; var i: i64=0
175 while q>=0 { o[i]=t[q]; i=i+1; q=q-1 }
176 sys_write(1,o,i); return 0
177}
178// run a scripted session under a fixed policy; returns the frame chain, writes final state to caller's g
179func de_run(g: *i64, seed: i64, policy: i64, fb: *i64) -> i64 {
180 de_new(g, seed)
181 var chain: i64=WIN_MAGIC_1469598103
182 var t: i64=0
183 while t<30 {
184 if g[F_WIN]==0 { if g[F_LOSE]==0 { de_tick(g, policy) } }
185 de_render(g, fb)
186 chain = wh_chain(chain, de_fbck(fb))
187 t=t+1
188 }
189 return chain
190}
191
192func main() -> i64 {
193 let SEED: i64 = WIN_MAGIC_20260721
194 var fails: i64=0
195 ww("=== Nishi Drift -- sovereign engine, a SURVIVAL game EMITTED from certified parts ===\n")
196 let g: *i64 = sys_mmap(WORDS*8) as *i64
197 let fb: *i64 = sys_mmap(FW*FH*8) as *i64
198 // SAFE policy session -> should WIN (rescue)
199 let chain_safe: i64 = de_run(g, SEED, 0, fb)
200 de_png(fb, "knowledge/nx_drift_win.png" as *u8)
201 ww(" SAFE run: cycle="); wn(g[F_CYC]); ww(" parts="); wn(g[F_PARTS]); ww(" oxy="); wn(g[F_OXY])
202 ww(" hull="); wn(g[F_HULL]); ww(" skill="); wn(g[F_SKILL]); ww(" win="); wn(g[F_WIN]); ww(" lose="); wn(g[F_LOSE]); ww("\n")
203 let win_cyc: i64 = g[F_CYC]
204 let win_parts: i64 = g[F_PARTS]
205 // capture a mid frame from a fresh short safe run
206 let gm: *i64 = sys_mmap(WORDS*8) as *i64
207 de_new(gm, SEED)
208 var mt: i64=0
209 while mt<6 { de_tick(gm, 0); mt=mt+1 }
210 de_render(gm, fb); de_png(fb, "knowledge/nx_drift_mid.png" as *u8)
211 // DEEP policy session -> should LOSE (hull/oxygen out)
212 let g2: *i64 = sys_mmap(WORDS*8) as *i64
213 let fb2: *i64 = sys_mmap(FW*FH*8) as *i64
214 de_run(g2, SEED, 1, fb2)
215 ww(" DEEP run: cycle="); wn(g2[F_CYC]); ww(" parts="); wn(g2[F_PARTS]); ww(" oxy="); wn(g2[F_OXY])
216 ww(" hull="); wn(g2[F_HULL]); ww(" win="); wn(g2[F_WIN]); ww(" lose="); wn(g2[F_LOSE]); ww("\n")
217
218 // P1: WINNABLE -- the safe strategy survives to rescue
219 if g[F_WIN]==1 { if win_cyc>=WIN_CYCLE { if win_parts>=WIN_PARTS { ww("P1 GREEN winnable: safe scavenging reached rescue (cycle "); wn(win_cyc); ww(", "); wn(win_parts); ww(" parts)\n") } else { fails=fails+1; ww("P1 RED parts\n") } } else { fails=fails+1; ww("P1 RED cycle\n") } } else { fails=fails+1; ww("P1 RED no win\n") }
220 // P2: LOSABLE (flagship, genre-honest) -- reckless deep-diving kills the run
221 if g2[F_LOSE]==1 { if g2[F_WIN]==0 { ww("P2 GREEN LOSABLE: reckless deep-diving died at cycle "); wn(g2[F_CYC]); ww(" (hull "); wn(g2[F_HULL]); ww(" oxy "); wn(g2[F_OXY]); ww(") -- a survival game that CAN be lost\n") } else { fails=fails+1; ww("P2 RED won-when-should-lose\n") } } else { fails=fails+1; ww("P2 RED deep run did not die\n") }
222 // P3: DETERMINISM -- replay the safe session, identical frame chain
223 let g3: *i64 = sys_mmap(WORDS*8) as *i64
224 let fb3: *i64 = sys_mmap(FW*FH*8) as *i64
225 let chain_safe2: i64 = de_run(g3, SEED, 0, fb3)
226 if chain_safe2==chain_safe { ww("P3 GREEN deterministic: replayed session -> identical frame chain "); wn(chain_safe); ww("\n") } else { fails=fails+1; ww("P3 RED chain "); wn(chain_safe); ww(" != "); wn(chain_safe2); ww("\n") }
227 // P4: SAVE/LOAD transparency
228 let sv: i64 = gs_save("knowledge/nx_drift.sav" as *u8, WIN_MAGIC_7402, g, F_HDR, SEED)
229 let gl: *i64 = sys_mmap(WORDS*8) as *i64
230 let meta: *i64 = sys_mmap(8*8) as *i64
231 let lr: i64 = gs_load("knowledge/nx_drift.sav" as *u8, gl, WORDS, meta)
232 var oks: i64=0
233 if sv>0 { if lr==F_HDR { if gl[F_PARTS]==g[F_PARTS] { if gl[F_WIN]==g[F_WIN] { if gl[F_OXY]==g[F_OXY] { oks=1 } } } } }
234 if oks==1 { ww("P4 GREEN save/load transparent: the survived run persisted + restored (parts+oxy+win intact)\n") } else { fails=fails+1; ww("P4 RED save="); wn(sv); ww(" load="); wn(lr); ww("\n") }
235 // P5: EXPERIENTIAL -- the win frame reads as a real scene
236 let fsm: *i64 = sys_mmap(FS_NMETRIC*8) as *i64
237 let okexp: i64 = wh_experiential(fb, FW, FH, fsm)
238 if okexp==1 { ww("P5 GREEN experiential: the emitted frames read as real scenes ("); wn(fsm[0]); ww("/"); wn(fsm[1]); ww("/"); wn(fsm[2]); ww("/"); wn(fsm[3]); ww("/"); wn(fsm[4]); ww(")\n") } else { fails=fails+1; ww("P5 RED experiential "); wn(fsm[0]); ww("/"); wn(fsm[1]); ww("/"); wn(fsm[2]); ww("/"); wn(fsm[3]); ww("/"); wn(fsm[4]); ww("\n") }
239 // P6: MECHANICAL DEPTH -- strategy DECIDES the outcome. The cautious run WON, the reckless run LOST;
240 // gd_score proves the two outcomes diverge with real stakes (win AND loss both reachable) = DEEP,
241 // not a walkover. (nx_game_depth: a game you cannot lose scores SHALLOW by construction.)
242 // MEASURE skill-not-luck: run each strategy TWICE (run1 = g/g2 above, run2 = g3/g2b) so gd_score can
243 // verify the outcomes REPLAY IDENTICALLY (deterministic skill), which a coin-flip cannot -- the red-team
244 // hardening. g3 is the safe replay from P3; g2b is a fresh reckless replay.
245 let g2b: *i64 = sys_mmap(WORDS*8) as *i64
246 let fb2b: *i64 = sys_mmap(FW*FH*8) as *i64
247 de_run(g2b, SEED, 1, fb2b)
248 let dsc: *i64 = sys_mmap(2*8) as *i64
249 let dsc2: *i64 = sys_mmap(2*8) as *i64
250 let dres: *i64 = sys_mmap(2*8) as *i64
251 dsc[0]=WIN_MAGIC_2000+win_parts; dsc[1]=g2[F_PARTS]
252 dsc2[0]=WIN_MAGIC_2000+g3[F_PARTS]; dsc2[1]=g2b[F_PARTS] // run-2 of each strategy
253 dres[0]=1; dres[1]=0
254 let dm: *i64 = sys_mmap(GD_N*8) as *i64
255 gd_score(dsc, dsc2, dres, 2, dm)
256 let dq: i64 = gd_quality(dm)
257 if dq >= GD_BASIC { ww("P6 GREEN mechanical DEPTH: cautious WON, reckless LOST -> gd_score "); wn(dq); ww(" = "); ww(gd_verdict(dq)); ww(" (strategy decides win/loss)\n") } else { fails=fails+1; ww("P6 RED depth only "); wn(dq); ww(" = "); ww(gd_verdict(dq)); ww(" -- strategies do not diverge\n") }
258 // P7: VISUAL QUALITY (the real critic) -- the frame must read as RICH art, not flat rings
259 let qv: i64 = de_quality(fb)
260 if qv >= GC_BASIC { ww("P7 GREEN visual quality: frame scores "); wn(qv); ww(" = "); ww(gc_verdict(qv)); ww(" (nebula + glow wrecks beat the old flat rings)\n") } else { fails=fails+1; ww("P7 RED quality only "); wn(qv); ww(" = "); ww(gc_verdict(qv)); ww("\n") }
261
262 ww("{\"organ\":\"nx_drift_engine\",\"game\":\"nishi-drift\",\"genre\":\"survival\",\"emitted\":1,\"proofs_pass\":")
263 wn(7-fails); ww(",\"proofs_total\":7,\"depth_score\":"); wn(dq); ww(",\"quality_score\":"); wn(qv); ww(",\"winnable\":"); wn(g[F_WIN]); ww(",\"losable\":"); wn(g2[F_LOSE])
264 ww(",\"win_cycle\":"); wn(win_cyc); ww(",\"win_parts\":"); wn(win_parts); ww(",\"frame_chain\":"); wn(chain_safe)
265 ww(",\"frames\":[\"knowledge/nx_drift_mid.png\",\"knowledge/nx_drift_win.png\"]}\n")
266 if fails==0 { ww("=== Nishi Drift EMITTED + PROVEN (7/7: winnable+LOSABLE+deterministic+save+RICH+DEEP) ===\n"); return 0 }
267 ww("=== Nishi Drift RED fails="); wn(fails); ww(" ===\n")
268 return 1
269}