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}