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}