code wiki / _hdl_build / nx_wasm_platformer_gate.nx
nx_wasm_platformer_gate.nx source
↩ module page · 117 lines · 7452 B
1// nx_wasm_platformer_gate.nx -- native test harness + PNG proof for the sovereign browser platformer
2// (nx_wasm_platformer). Drives the SAME integer logic the wasm exports (base = mmap here, base = 0 in wasm):
3// a scripted jump-AI auto-runs the level and must collect all floating coins + clear all foes + reach the exit;
4// a NO-JUMP control proves the floating coins are UNREACHABLE without the jump mechanic (the platformer-ness is
5// real, not decorative); the integer jump ARC is measured (apex >= 30px); determinism (two runs identical); and
6// a mid-play frame is rastered to knowledge/staging/game/platformer_play.png. license_tier: ORIGINAL expect_exit: 0
7import "nx_wasm_platformer.nx"
8import "nx_png.nx"
9import "nx_syscalls.nx"
10import "nx_gate_verdict.nx"
11
12func 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 }
13func 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 }
14
15// run a full playthrough; dojump=1 uses the jump-AI (jump when a floating coin is just ahead), 0 never jumps.
16func play(base: i64, dojump: i64) -> i64 {
17 init_impl(base)
18 var run: i64 = 1
19 while run == 1 {
20 if sget(base, 7) == 1 { run = 0 }
21 if sget(base, 8) > 400 { run = 0 }
22 if run == 1 {
23 var cmd: i64 = 2
24 if dojump == 1 { if sget(base, 3) == 1 {
25 var i: i64 = 0
26 while i < NCOIN { if cget(base, i) == 0 { let d: i64 = coin_x(i) - sget(base, 0); if d > 10 { if d < 24 { cmd = 0 } } } i = i + 1 }
27 } }
28 tick_impl(base, cmd)
29 }
30 }
31 return sget(base, 8)
32}
33
34func main(argc: i64, argv: *i64) -> i64 {
35 g_p("=== nx_wasm_platformer_gate (sovereign browser platformer: integer logic + raster) ===\n" as *u8)
36 let base: i64 = sys_mmap(2097152) as i64
37 var pass: i64 = 0; var tot: i64 = 0
38
39 // T1 jump-AI playthrough collects everything + reaches exit
40 play(base, 1)
41 let coins1: i64 = sget(base, 5); let foes1: i64 = sget(base, 6); let score1: i64 = sget(base, 4); let won1: i64 = sget(base, 7)
42 tot = tot + 1; var ok1: i64 = 1
43 if coins1 != NCOIN { ok1 = 0 }
44 if foes1 != NFOE { ok1 = 0 }
45 if score1 != NCOIN + NFOE { ok1 = 0 }
46 if won1 != 1 { ok1 = 0 }
47 if ok1 == 1 { pass = pass + 1; g_p("PASS T1 playthrough: jumped+collected 4/4 coins, cleared 2/2 foes, score=6, reached exit (WIN)\n" as *u8) } else { g_p("FAIL T1 coins=" as *u8); g_i(coins1); g_p(" foes=" as *u8); g_i(foes1); g_p(" score=" as *u8); g_i(score1); g_p(" won=" as *u8); g_i(won1); g_p("\n" as *u8) }
48
49 // T2 NEGATIVE CONTROL: without jumping, the floating coins are unreachable (mechanic is real)
50 play(base, 0)
51 let coins0: i64 = sget(base, 5); let foes0: i64 = sget(base, 6); let won0: i64 = sget(base, 7)
52 tot = tot + 1; var ok2: i64 = 1
53 if coins0 != 0 { ok2 = 0 }
54 if foes0 != NFOE { ok2 = 0 }
55 if won0 != 1 { ok2 = 0 }
56 if ok2 == 1 { pass = pass + 1; g_p("PASS T2 neg-control: no-jump run collects 0/4 floating coins (jump is REQUIRED), still clears 2 ground foes + exits\n" as *u8) } else { g_p("FAIL T2 coins0=" as *u8); g_i(coins0); g_p(" foes0=" as *u8); g_i(foes0); g_p("\n" as *u8) }
57
58 // T3 integer jump ARC: a single jump rises >= 30px (proves the no-float gravity parabola)
59 init_impl(base); tick_impl(base, 0)
60 var apex: i64 = sget(base, 1)
61 var k: i64 = 0
62 while k < 14 { tick_impl(base, 1); if sget(base, 1) < apex { apex = sget(base, 1) } k = k + 1 }
63 let rise: i64 = GROUNDY - apex
64 tot = tot + 1
65 if rise >= 30 { pass = pass + 1; g_p("PASS T3 jump arc: integer gravity parabola rises " as *u8); g_i(rise); g_p("px (>=30), lands back on the ground\n" as *u8) } else { g_p("FAIL T3 rise=" as *u8); g_i(rise); g_p("\n" as *u8) }
66
67 // T4 DETERMINISM: same script -> identical outcome
68 play(base, 1); let f1: i64 = sget(base, 8); let s1: i64 = sget(base, 4)
69 play(base, 1); let f2: i64 = sget(base, 8); let s2: i64 = sget(base, 4)
70 tot = tot + 1
71 if f1 == f2 { if s1 == s2 { pass = pass + 1; g_p("PASS T4 determinism: two runs identical (frames=" as *u8); g_i(f1); g_p(", score=" as *u8); g_i(s1); g_p(")\n" as *u8) } else { g_p("FAIL T4\n" as *u8) } } else { g_p("FAIL T4\n" as *u8) }
72
73 // T5 RASTER a mid-play frame -> PNG; hero pixel must be green
74 init_impl(base)
75 var fr: i64 = 0
76 while fr < 56 {
77 var cmd: i64 = 2
78 if sget(base, 3) == 1 { var i: i64 = 0; while i < NCOIN { if cget(base, i) == 0 { let d: i64 = coin_x(i) - sget(base, 0); if d > 10 { if d < 24 { cmd = 0 } } } i = i + 1 } }
79 tick_impl(base, cmd); fr = fr + 1
80 }
81 render_impl(base)
82 sys_mkdir("knowledge/staging/game" as *u8, MODE_0755)
83 write_png((base + O_FB) as *i64, W, H, "knowledge/staging/game/platformer_play.png" as *u8)
84 let fb: *i64 = (base + O_FB) as *i64
85 let hx: i64 = sget(base, 0); let hy: i64 = sget(base, 1)
86 // ★T5 ASKS WHETHER THE HERO IS IN THE PICTURE, NOT WHETHER A PIXEL IS GREENISH. The old predicate
87 // was ((hc>>8)&255) > (hc&255) -- "greener than red" -- and EVERY background colour in
88 // render_impl satisfies it: sky rgb(28,38,60), ground rgb(46,84,52), ground edge rgb(70,120,76),
89 // exit rgb(60,200,210). Delete the hero draw entirely and that tooth still passed, because it was
90 // measuring the sky. Found 2026-08-14 by nx_vacuity_census -- the second confirmed instance after
91 // nx_wasm_thirdperson_gate, and the same class that let nx_wasm_craft_gate ship a world with no
92 // characters in it under 58 green teeth.
93 // The honest question is whether the hero's pixel differs from the BACKGROUND behind it. This names
94 // no colour, so it cannot rot when the palette moves, and it fails closed the moment the hero
95 // stops being drawn.
96 let hc: i64 = fb[(hy + 8) * W + (hx + 6)]
97 let sky1: i64 = fb[2 * W + 2]
98 tot = tot + 1
99 if hc != sky1 { pass = pass + 1; g_p("PASS T5 raster: the hero is IN the frame -- hero pixel differs from the sky behind it\n" as *u8) } else { g_p("FAIL T5 the hero pixel IS the sky: nothing was drawn there\n" as *u8) }
100
101 // T6 neg-control-background-uniform: two widely separated sky samples must be EQUAL. Without this,
102 // T5 could be passing on ordinary background variation rather than on the hero.
103 let sky2: i64 = fb[2 * W + (W - 3)]
104 tot = tot + 1
105 if sky1 == sky2 { pass = pass + 1; g_p("PASS T6 neg-control-background-uniform: two sky samples agree, so T5's difference is the hero\n" as *u8) } else { g_p("FAIL T6 the background is not uniform where T5 samples it\n" as *u8) }
106
107 g_p("nx_wasm_platformer_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot)
108 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
109 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
110 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
111 let ctr__dry: *i64 = gv_ctr()
112 ctr__dry[0] = pass
113 ctr__dry[1] = tot
114 let rc__dry: i64 = gv_verdict("WASM-PLATFORMER-GATE" as *u8, ctr__dry, "sovereign integer platformer; browser-ready via the wasm chain)" as *u8)
115 sys_exit(rc__dry)
116 return rc__dry
117}