code wiki / _hdl_build / nx_frontier_engine.nx

nx_frontier_engine.nx source

↩ module page · 265 lines · 12388 B

1// nx_frontier_engine.nx -- the SOVEREIGN engine behind the playable /world/frontier game: "Nishi 2// Frontier" emitted by COMPOSING certified parts (the gamebench recombinator realized in NishiLang, not 3// JS). A trader-explorer crossing a star map of faction stations -- find cargo (loot tiers), hold or SELL 4// on a CONSERVED faction economy, level up, retire rich. A genre blend matching NO ingested reference 5// title. The browser page is the last-mile playtest; THIS is the sovereign truth: it renders real PNG 6// frames and PROVES the composition (conservation, determinism, save-load, experiential) so the same 7// design is verified in the sovereign stack, not just the shim. Economics match the tuned live game 8// exactly (hold-then-sell, sell = cargo*(50+lvl*12), win at 2400cr & level 5). 9// Parts: nx_worldsim · nx_rpgstats · nx_loottable · nx_gamehud + nx_wire_harness · nx_game_raster · 10// nx_gamesave · nx_frame_sanity (via harness) · nx_png_write. license_tier: ORIGINAL expect_exit: 0 11import "nx_syscalls.nx" 12import "nx_worldsim.nx" 13import "nx_rpgstats.nx" 14import "nx_loottable.nx" 15import "nx_gamehud.nx" 16import "nx_game_raster.nx" 17import "nx_wire_harness.nx" 18import "nx_gamesave.nx" 19import "nx_png_write.nx" 20import "nx_game_art.nx" 21import "nx_game_critic.nx" 22const F_MAGIC_1400: i64 = 1400 23const F_MAGIC_20260721: i64 = 20260721 24const F_MAGIC_1469598103: i64 = 1469598103 25const F_MAGIC_7401: i64 = 7401 26 27const NF: i64 = 5 28const FW: i64 = 400 29const FH: i64 = 240 30const WORDS: i64 = 512 31const F_TICK:i64=0 32const F_STN: i64=1 33const F_XP: i64=2 34const F_LVL: i64=3 35const F_HP: i64=4 36const F_CRED:i64=5 37const F_CARGO:i64=6 38const F_VIS: i64=7 39const F_SELLS:i64=8 40const F_FINDS:i64=9 41const F_WIN: i64=10 42const F_RNG: i64=11 43const F_PX: i64=12 44const F_PY: i64=13 45const F_HDR: i64=24 46const O_WS: i64=32 // ws_words(5)=56 -> 32..88 47const O_HUD: i64=96 // 96..160 48const XB: i64=20 49const XQ: i64=10 50const HPB: i64=12 51const HPC: i64=2 52const HPL: i64=3 53const CON: i64=14 54const WIN_CRED: i64=2400 55const WIN_LVL: i64=5 56 57func g_ws(g: *i64) -> *i64 { return (g as i64 + O_WS*8) as *i64 } 58func g_hud(g: *i64) -> *i64 { return (g as i64 + O_HUD*8) as *i64 } 59func g_rng(g: *i64) -> i64 { 60 var x: i64 = g[F_RNG] 61 x = x ^ (x << 13); x = x ^ (x >> 7); x = x ^ (x << 17) 62 g[F_RNG] = x 63 if x < 0 { return 0 - x } 64 return x 65} 66func stn_x(i: i64) -> i64 { return 44 + i*76 } 67func stn_y(i: i64) -> i64 { if i%2==0 { return 84 } else { return 150 } } 68// sell value of the whole hold at a given rank (matches the browser game exactly) 69func sell_value(cargo: i64, lvl: i64) -> i64 { return cargo * (50 + lvl*12) } 70 71func fe_new(g: *i64, seed: i64) -> i64 { 72 var i: i64=0 73 while i<WORDS { g[i]=0; i=i+1 } 74 g[F_RNG]=seed 75 if g[F_RNG]==0 { g[F_RNG]=1 } 76 g[F_LVL]=rs_level_for_xp(0, XB, XQ) 77 g[F_HP]=rs_derived_hp(CON, g[F_LVL], HPB, HPC, HPL) 78 g[F_CRED]=500 79 g[F_PX]=stn_x(0) 80 g[F_PY]=stn_y(0) 81 let w: *i64 = g_ws(g) 82 ws_init(w, NF, seed) 83 ws_set_res(w, 0, 500) 84 ws_set_terr(w, 0, 0) 85 var f: i64=1 86 while f<NF { ws_set_res(w,f,F_MAGIC_1400+f*350); ws_set_pop(w,f,400); ws_set_terr(w,f,2+f); f=f+1 } 87 gh_init(g_hud(g), 5) 88 return 0 89} 90func cargo_weights(wts: *i64) -> i64 { wts[0]=600; wts[1]=250; wts[2]=100; wts[3]=40; wts[4]=10; return 0 } 91 92func fe_tick(g: *i64) -> i64 { 93 if g[F_WIN]==1 { return 0 } 94 let w: *i64 = g_ws(g) 95 let hud: *i64 = g_hud(g) 96 let nxt: i64 = (g[F_STN]+1)%NF 97 g[F_STN]=nxt 98 g[F_PX]=stn_x(nxt) 99 g[F_PY]=stn_y(nxt) 100 g[F_VIS]=g[F_VIS]+1 101 // find cargo: weighted loot-tier roll 102 let wts: *i64 = sys_mmap(NF*8) as *i64 103 cargo_weights(wts) 104 let tier: i64 = lt_pick(wts, 5, g_rng(g)%1000) 105 if tier>=0 { g[F_FINDS]=g[F_FINDS]+1; g[F_CARGO]=g[F_CARGO]+(tier+1) } 106 // SELL decision THROUGH THE MENU (causal): policy = sell when holding cargo at a solvent station. 107 if nxt!=0 { if g[F_CARGO]>0 { if ws_res(w,nxt)>150 { 108 let dec: i64 = wh_menu_pick2(hud, 1, sell_value(g[F_CARGO], g[F_LVL]), 2, g[F_CRED]) 109 if dec==1 { 110 let got: i64 = ws_trade(w, nxt, 0, sell_value(g[F_CARGO], g[F_LVL])) // station->player, conserved 111 if got>0 { 112 g[F_SELLS]=g[F_SELLS]+1 113 g[F_XP]=g[F_XP]+g[F_CARGO]*6+got/20 114 g[F_CARGO]=0 115 let nl: i64 = rs_level_for_xp(g[F_XP], XB, XQ) 116 if nl>g[F_LVL] { g[F_LVL]=nl; g[F_HP]=rs_derived_hp(CON, nl, HPB, HPC, HPL) } 117 } 118 } 119 } } } 120 g[F_CRED]=ws_res(w,0) 121 if g[F_CRED]>=WIN_CRED { if g[F_LVL]>=WIN_LVL { g[F_WIN]=1 } } 122 g[F_TICK]=g[F_TICK]+1 123 return 0 124} 125 126func fe_render(g: *i64, fb: *i64) -> i64 { 127 let w: *i64 = g_ws(g) 128 art_nebula(fb, FW, FH, 6, 7, 22, 30, 16, 58) // deep-space -> nebula purple gradient 129 art_stardust(fb, FW, FH, 160) 130 var f: i64=0 131 while f<NF { 132 gr_hline(fb, FW, FH, stn_x(f), stn_x((f+1)%NF), (stn_y(f)+stn_y((f+1)%NF))/2, gr_pack(34,30,60)) 133 f=f+1 134 } 135 f=0 136 while f<NF { 137 let cx: i64=stn_x(f) 138 let cy: i64=stn_y(f) 139 var rad: i64 = 10 + ws_res(w,f)/210 140 if rad>24 { rad=24 } 141 if rad<9 { rad=9 } 142 var cr: i64=95 143 var cg: i64=155 144 var cb: i64=248 145 if f==1 { cr=235; cg=100; cb=110 } 146 if f==2 { cr=95; cg=220; cb=150 } 147 if f==3 { cr=240; cg=195; cb=82 } 148 if f==4 { cr=200; cg=122; cb=240 } 149 art_glow_orb(fb, FW, FH, cx, cy, rad, cr, cg, cb) // glowing station, radial gradient 150 f=f+1 151 } 152 let px: i64=g[F_PX] 153 let py: i64=g[F_PY] 154 art_glow_orb(fb, FW, FH, px, py, 7, 255, 232, 120) // ship: glowing core 155 gr_rect(fb, FW, FH, px-1, py-11, px+1, py+11, gr_pack(255,255,220)) 156 gr_rect(fb, FW, FH, px-11, py-1, px+11, py+1, gr_pack(255,255,220)) 157 // HUD: gradient meters + glowing level pips 158 gr_rect(fb, FW, FH, 0, 206, FW-1, FH-1, gr_pack(13,15,30)) 159 var credf: i64 = g[F_CRED]*(FW-8)/WIN_CRED 160 if credf>FW-8 { credf=FW-8 } 161 art_meter(fb, FW, FH, 4, 211, FW-8, 7, credf, 40,120,90, 130,240,155) 162 var lp: i64=0 163 while lp<g[F_LVL] { art_glow_orb(fb, FW, FH, 13+lp*17, 232, 5, 245,205,72); lp=lp+1 } 164 var cg2: i64=0 165 while cg2<g[F_CARGO] { if cg2<20 { art_glow_orb(fb, FW, FH, FW-12-cg2*11, 232, 4, 232,150,64) } cg2=cg2+1 } 166 return 0 167} 168// self-quality: score the current frame with the critic (the standing experiential proof) 169func fe_quality(fb: *i64) -> i64 { 170 let m: *i64 = sys_mmap(GC_N*8) as *i64 171 gc_score(fb, FW, FH, m) 172 return gc_quality(m) 173} 174func fe_fbck(fb: *i64) -> i64 { return wh_fbck(fb, FW*FH) } 175func fe_png(fb: *i64, path: *u8) -> i64 { 176 let rgb: *u8 = sys_mmap(FW*FH*3) 177 var p: i64=0 178 let n: i64=FW*FH 179 while p<n { 180 let v: i64=fb[p] 181 rgb[p*3]=(v & 0xff) as u8 182 rgb[p*3+1]=((v>>8) & 0xff) as u8 183 rgb[p*3+2]=((v>>16) & 0xff) as u8 184 p=p+1 185 } 186 return nx_png_write_rgb(path, rgb, FW, FH) 187} 188 189func ww(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 190func wn(v: i64) -> i64 { 191 if v==0 { sys_write(1,"0" as *u8,1); return 0 } 192 var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m } 193 let t: *u8=sys_mmap(32); var k: i64=0 194 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 195 let o: *u8=sys_mmap(32); var q: i64=k-1; var i: i64=0 196 while q>=0 { o[i]=t[q]; i=i+1; q=q-1 } 197 sys_write(1,o,i); return 0 198} 199 200func main() -> i64 { 201 let SEED: i64 = F_MAGIC_20260721 202 var fails: i64=0 203 ww("=== Nishi Frontier -- sovereign engine, a game EMITTED from certified parts ===\n") 204 let g: *i64 = sys_mmap(WORDS*8) as *i64 205 fe_new(g, SEED) 206 let fb: *i64 = sys_mmap(FW*FH*8) as *i64 207 let start_total: i64 = ws_total_res(g_ws(g)) 208 fe_render(g, fb); fe_png(fb, "knowledge/nx_frontier_start.png" as *u8) 209 var chain: i64 = F_MAGIC_1469598103 210 var t: i64=0 211 while t<40 { 212 if g[F_WIN]==0 { fe_tick(g) } 213 fe_render(g, fb) 214 chain = wh_chain(chain, fe_fbck(fb)) 215 if t==6 { fe_png(fb, "knowledge/nx_frontier_mid.png" as *u8) } 216 t=t+1 217 } 218 fe_render(g, fb); fe_png(fb, "knowledge/nx_frontier_win.png" as *u8) 219 ww(" played: visits="); wn(g[F_VIS]); ww(" finds="); wn(g[F_FINDS]); ww(" sells="); wn(g[F_SELLS]) 220 ww(" xp="); wn(g[F_XP]); ww(" lvl="); wn(g[F_LVL]); ww(" credits="); wn(g[F_CRED]); ww(" win="); wn(g[F_WIN]); ww("\n") 221 222 // P1: a real playthrough that reaches the win state 223 if g[F_WIN]==1 { if g[F_VIS]>8 { if g[F_SELLS]>=3 { ww("P1 GREEN reached the win by trading (the composed loop is a real, winnable game)\n") } else { fails=fails+1; ww("P1 RED sells\n") } } else { fails=fails+1; ww("P1 RED visits\n") } } else { fails=fails+1; ww("P1 RED no win\n") } 224 // P2: worldsim CONSERVATION end-to-end 225 let end_total: i64 = ws_total_res(g_ws(g)) 226 if end_total==start_total { ww("P2 GREEN economy CONSERVED end-to-end: "); wn(end_total); ww(" (no wealth minted or burned across every trade)\n") } else { fails=fails+1; ww("P2 RED conservation "); wn(start_total); ww("->"); wn(end_total); ww("\n") } 227 // P3: DETERMINISM 228 let g2: *i64 = sys_mmap(WORDS*8) as *i64 229 fe_new(g2, SEED) 230 let fb2: *i64 = sys_mmap(FW*FH*8) as *i64 231 var chain2: i64 = F_MAGIC_1469598103 232 var t2: i64=0 233 while t2<40 { if g2[F_WIN]==0 { fe_tick(g2) } fe_render(g2, fb2); chain2 = wh_chain(chain2, fe_fbck(fb2)); t2=t2+1 } 234 if chain2==chain { ww("P3 GREEN deterministic: replayed session -> identical frame chain "); wn(chain); ww("\n") } else { fails=fails+1; ww("P3 RED chain "); wn(chain); ww(" != "); wn(chain2); ww("\n") } 235 // P4: SAVE/LOAD transparency 236 let sv: i64 = gs_save("knowledge/nx_frontier.sav" as *u8, F_MAGIC_7401, g, F_HDR, SEED) 237 let g3: *i64 = sys_mmap(WORDS*8) as *i64 238 let meta: *i64 = sys_mmap(8*8) as *i64 239 let lr: i64 = gs_load("knowledge/nx_frontier.sav" as *u8, g3, WORDS, meta) 240 var oks: i64=0 241 if sv>0 { if lr==F_HDR { if g3[F_CRED]==g[F_CRED] { if g3[F_LVL]==g[F_LVL] { if g3[F_WIN]==g[F_WIN] { oks=1 } } } } } 242 if oks==1 { ww("P4 GREEN save/load transparent: won game persisted + restored (credits+level+win intact)\n") } else { fails=fails+1; ww("P4 RED save="); wn(sv); ww(" load="); wn(lr); ww("\n") } 243 // P5: EXPERIENTIAL -- the win frame reads as a real scene 244 let fsm: *i64 = sys_mmap(FS_NMETRIC*8) as *i64 245 let okexp: i64 = wh_experiential(fb, FW, FH, fsm) 246 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") } 247 248 // P6: EXPERIENTIAL QUALITY (the real critic, not a floor check) -- the frame must read as RICH art, 249 // not a toy of flat discs. This is the honest instrument the operator demanded; the engine climbs it. 250 let qscore: i64 = fe_quality(fb) 251 if qscore >= GC_BASIC { ww("P6 GREEN experiential quality: frame scores "); wn(qscore); ww(" = "); ww(gc_verdict(qscore)); ww(" (gradient nebula + glow orbs beat the old flat-disc TOY render)\n") } else { fails=fails+1; ww("P6 RED quality only "); wn(qscore); ww(" = "); ww(gc_verdict(qscore)); ww(" -- still toy, needs richer art\n") } 252 253 ww("frames: knowledge/nx_frontier_{start,mid,win}.png\n") 254 // machine-readable summary (MCP tools/call consumers parse this; the human report is above) 255 ww("{\"organ\":\"nx_frontier_engine\",\"game\":\"nishi-frontier\",\"emitted\":1,\"proofs_pass\":") 256 wn(6-fails); ww(",\"proofs_total\":6,\"quality_score\":"); wn(fe_quality(fb)); ww(",\"win\":"); wn(g[F_WIN]) 257 ww(",\"visits\":"); wn(g[F_VIS]); ww(",\"sells\":"); wn(g[F_SELLS]); ww(",\"level\":"); wn(g[F_LVL]) 258 ww(",\"credits\":"); wn(g[F_CRED]); ww(",\"conserved\":") 259 if end_total==start_total { ww("1") } else { ww("0") } 260 ww(",\"galaxy_wealth\":"); wn(end_total); ww(",\"frame_chain\":"); wn(chain) 261 ww(",\"frames\":[\"knowledge/nx_frontier_start.png\",\"knowledge/nx_frontier_mid.png\",\"knowledge/nx_frontier_win.png\"]}\n") 262 if fails==0 { ww("=== Nishi Frontier EMITTED + PROVEN (6/6 incl experiential QUALITY) ===\n"); return 0 } 263 ww("=== Nishi Frontier RED fails="); wn(fails); ww(" ===\n") 264 return 1 265}