code wiki / _hdl_build / nx_game_scaffold_gate.nx
nx_game_scaffold_gate.nx source
↩ module page · 121 lines · 7844 B
1// nx_game_scaffold_gate.nx -- GATE: the hardware-rung-up SCAFFOLD, catalog -> ... -> AUTOGENERATION. Seed a temp
2// catalog, then assert each rung: COMPOSE+RUN a level from catalog parts; RASTER it to an integer (no-float)
3// packed-RGB framebuffer + PNG (gold coins / red foes / green hero / cyan exit pixels present); AUTOGENERATE 5
4// NEW playable levels into the catalog (all win, counts VARY = real generation, non-degenerate); DETERMINISM
5// (same seed -> identical levels); INTEGRITY neg-control (autogen grows ONLY what it made -- a non-generated id
6// is absent); SOVEREIGNTY (generated specs are nb_template_safe; detector fires on a planted tag). PNG ->
7// knowledge/staging/game/platformer_1-1.png. license_tier: ORIGINAL
8import "nx_game_scaffold.nx"
9import "nx_game_render.nx"
10import "nx_nishi_builder.nx"
11import "nx_shade.nx"
12import "nx_png.nx"
13import "nx_ad_serve.nx"
14import "nx_syscalls.nx"
15import "nx_gate_verdict.nx"
16
17const SG_PATH: *u8 = "/tmp/nishi_game_scaffold_gate.tsv"
18
19func g_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
20func g_i(v: i64) -> i64 { let t: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0; if m == 0 { t[0]=48 as u8; k=1 } while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } let o: *u8=sys_mmap(24); var w: i64=0; var q: i64=k-1; while q>=0 { o[w]=t[q]; w=w+1; q=q-1 } sys_write(1,o,w); return 0 }
21
22func main(argc: i64, argv: *i64) -> i64 {
23 g_p("=== nx_game_scaffold_gate (hardware-rung-up: catalog -> run -> raster -> AUTOGENERATE) ===\n" as *u8)
24 let fd: i64 = sys_openat_wr(SG_PATH, 420); if fd >= 0 { sys_close(fd) }
25 nb_register(SG_PATH, "game" as *u8, "tilemap" as *u8, "overworld" as *u8, "Overworld" as *u8, "32x32|grass,dirt,water,stone|autotile" as *u8)
26 nb_register(SG_PATH, "game" as *u8, "mechanic" as *u8, "platform-jump" as *u8, "Platform jump" as *u8, "impulse=12|gravity=0.6|coyote=80|jumpbuffer=120" as *u8)
27 nb_register(SG_PATH, "game" as *u8, "entity" as *u8, "patroller" as *u8, "Patrol enemy" as *u8, "hp=3|speed=2|ai=patrol|drop=coin" as *u8)
28 nb_register(SG_PATH, "game" as *u8, "level" as *u8, "1-1" as *u8, "First level" as *u8, "overworld|coin*12|patroller*3|exit-right" as *u8)
29
30 let st: *i64 = sys_mmap(512) as *i64
31 var pass: i64 = 0; var tot: i64 = 0
32
33 // R2+R4 COMPOSE + RUN
34 ng_sim_run(SG_PATH, "1-1" as *u8, "platform-jump" as *u8, "patroller" as *u8, st)
35 tot = tot + 1; var ok1: i64 = 1
36 if st[7] != 1 { ok1 = 0 }
37 if st[1] != 12 { ok1 = 0 }
38 if st[3] != 3 { ok1 = 0 }
39 if st[14] != 1 { ok1 = 0 }
40 if st[5] != 16 { ok1 = 0 }
41 if ok1 == 1 { pass = pass + 1; g_p("PASS R2/R4 compose+run: 1-1 composed from catalog parts plays (12 coins, 3 foes, exit_x=16, WIN)\n" as *u8) } else { g_p("FAIL R2/R4\n" as *u8) }
42
43 // R5 RASTER -> integer framebuffer + PNG
44 let CELL: i64 = 20; let W: i64 = (st[5] + 1) * CELL; let H: i64 = 28
45 let fb: *i64 = sys_mmap(8 * 340 * 28) as *i64
46 gs_raster(st, fb, W, H, CELL)
47 sys_mkdir("knowledge/staging/game" as *u8, 0x1ed)
48 write_png(fb, W, H, "knowledge/staging/game/platformer_1-1.png" as *u8)
49 let cy: i64 = 14
50 let pHero: i64 = fb[cy * W + 10]
51 let pCoin: i64 = fb[cy * W + (1 * CELL + 10)]
52 let pFoe: i64 = fb[cy * W + ((st[1] + 1) * CELL + 10)]
53 let pExit: i64 = fb[cy * W + (st[5] * CELL + 10)]
54 tot = tot + 1; var ok2: i64 = 1
55 if sh_g(pHero) <= sh_r(pHero) { ok2 = 0 }
56 if sh_g(pHero) <= sh_b(pHero) { ok2 = 0 }
57 if sh_r(pCoin) <= 200 { ok2 = 0 }
58 if sh_b(pCoin) >= 120 { ok2 = 0 }
59 if sh_r(pFoe) <= sh_g(pFoe) { ok2 = 0 }
60 if sh_r(pFoe) <= sh_b(pFoe) { ok2 = 0 }
61 if sh_b(pExit) <= 150 { ok2 = 0 }
62 if sh_r(pExit) >= 120 { ok2 = 0 }
63 if ok2 == 1 { pass = pass + 1; g_p("PASS R5 raster: integer no-float framebuffer -> PNG (green hero, gold coins, red foes, cyan exit)\n" as *u8) } else { g_p("FAIL R5 raster pixels\n" as *u8) }
64
65 // R6 AUTOGENERATE 5 new playable levels
66 let coins: *i64 = sys_mmap(64) as *i64; let foes: *i64 = sys_mmap(64) as *i64
67 let cbox: *i64 = sys_mmap(16) as *i64; let fbox: *i64 = sys_mmap(16) as *i64
68 let seed: *i64 = sys_mmap(16) as *i64; seed[0] = 12345
69 var wins: i64 = 0; var cmin: i64 = 999; var cmax: i64 = 0
70 var idx: i64 = 1
71 while idx <= 5 {
72 let win: i64 = gs_autogen_one(SG_PATH, seed, idx, "platform-jump" as *u8, "overworld" as *u8, "patroller" as *u8, st, cbox, fbox)
73 coins[idx-1] = cbox[0]; foes[idx-1] = fbox[0]
74 if win == 1 { if st[2] == cbox[0] { if st[4] == fbox[0] { wins = wins + 1 } } }
75 if cbox[0] < cmin { cmin = cbox[0] }
76 if cbox[0] > cmax { cmax = cbox[0] }
77 g_p(" autogen auto-" as *u8); g_i(idx); g_p(": coins=" as *u8); g_i(cbox[0]); g_p(" foes=" as *u8); g_i(fbox[0]); g_p(" -> " as *u8); if win == 1 { g_p("WIN\n" as *u8) } else { g_p("REFUSED\n" as *u8) }
78 idx = idx + 1
79 }
80 tot = tot + 1; var ok3: i64 = 1
81 if wins != 5 { ok3 = 0 }
82 if cmax <= cmin { ok3 = 0 } // counts VARY -> real generation, not a constant clone
83 if ok3 == 1 { pass = pass + 1; g_p("PASS R6 autogenerate: 5 NEW playable levels taught to the catalog, all WIN, counts vary (real generation)\n" as *u8) } else { g_p("FAIL R6 wins=" as *u8); g_i(wins); g_p(" cmin=" as *u8); g_i(cmin); g_p(" cmax=" as *u8); g_i(cmax); g_p("\n" as *u8) }
84
85 // R6b DETERMINISM: same seed -> identical generated levels
86 let coins2: *i64 = sys_mmap(64) as *i64
87 seed[0] = 12345
88 idx = 1
89 while idx <= 5 { gs_autogen_one(SG_PATH, seed, idx, "platform-jump" as *u8, "overworld" as *u8, "patroller" as *u8, st, cbox, fbox); coins2[idx-1] = cbox[0]; idx = idx + 1 }
90 tot = tot + 1; var ok4: i64 = 1
91 var di: i64 = 0
92 while di < 5 { if coins2[di] != coins[di] { ok4 = 0 } di = di + 1 }
93 if ok4 == 1 { pass = pass + 1; g_p("PASS R6b determinism: same seed -> byte-identical levels (reproducible autogen, idempotent re-teach)\n" as *u8) } else { g_p("FAIL R6b\n" as *u8) }
94
95 // R6c INTEGRITY (negative control): autogen grows ONLY what it made -- a non-generated id is ABSENT
96 tot = tot + 1; var ok5: i64 = 1
97 if nb_present(SG_PATH, "game" as *u8, "level" as *u8, "auto-1" as *u8) != 1 { ok5 = 0 }
98 if nb_present(SG_PATH, "game" as *u8, "level" as *u8, "auto-99" as *u8) != 0 { ok5 = 0 }
99 var ci: i64 = 0
100 while ci < 5 { if coins[ci] < 5 { ok5 = 0 } if coins[ci] > 30 { ok5 = 0 } ci = ci + 1 } // non-degenerate range
101 if ok5 == 1 { pass = pass + 1; g_p("PASS R6c integrity: autogen grew ONLY auto-1..5 (auto-99 absent); every level non-degenerate (5..30 coins)\n" as *u8) } else { g_p("FAIL R6c\n" as *u8) }
102
103 // SOVEREIGNTY
104 tot = tot + 1; var ok6: i64 = 1
105 let atpl: *u8 = sys_mmap(256)
106 if nb_lookup(SG_PATH, "game" as *u8, "level" as *u8, "auto-1" as *u8, atpl) == 1 { if nb_template_safe(atpl) != 1 { ok6 = 0 } } else { ok6 = 0 }
107 if nb_template_safe("<script>x</script>" as *u8) != 0 { ok6 = 0 }
108 if as_has_thirdparty_js("<img src='//x'>" as *u8, 15) != 1 { ok6 = 0 }
109 if ok6 == 1 { pass = pass + 1; g_p("PASS S sovereignty: generated specs are sovereign-safe; <script/src= detector fires on a planted tag\n" as *u8) } else { g_p("FAIL S\n" as *u8) }
110
111 g_p("nx_game_scaffold_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot)
112 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
113 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
114 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
115 let ctr__dry: *i64 = gv_ctr()
116 ctr__dry[0] = pass
117 ctr__dry[1] = tot
118 let rc__dry: i64 = gv_verdict("GAME-SCAFFOLD-GATE" as *u8, ctr__dry, "catalog scaffolds games hardware-rung-up to AUTOGENERATION)" as *u8)
119 sys_exit(rc__dry)
120 return rc__dry
121}