code wiki / _hdl_build / nx_wasm_pong_gate.nx

nx_wasm_pong_gate.nx source

↩ module page · 97 lines · 5679 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_wasm_pong_gate.nx -- NATIVE gate for the browser-playable Pong core (nx_wasm_pong). 4// T1 RETURN + SCORE: a ball aligned with the paddle is RETURNED (bvx flips); a missed ball SCORES. 5// T2 RENDER REAL: a green player paddle + a red AI paddle + a white ball (PNG). 6// T3 WALL BOUNCE: the ball reflects off the top wall (bvy flips). 7// T4 NEVER-BRICK (#26): deterministic, bounded, no float, base-relative. 8// expect_exit: 0 license_tier: ORIGINAL 9import "nx_wasm_pong.nx" 10import "nx_png.nx" 11import "nx_syscalls.nx" 12import "nx_gate_verdict.nx" 13 14func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 15" as *u8); return ok } 16 17func main() -> i64 { 18 gw("=== nx_wasm_pong_gate: browser-playable Pong core, verified NATIVE before wasm ===\n" as *u8) 19 var pass: i64 = 0; var total: i64 = 0 20 let base: i64 = sys_mmap(2*1024*1024) as i64 21 let st: *i64 = (base + O_ST) as *i64 22 23 // ---- T1: return + score ---- 24 init_impl(base) 25 st[0] = LX + 3; st[2] = 0 - 3; st[1] = st[4] // ball at the paddle, aligned 26 tick_impl(base, 0) 27 let returned: i64 = st[2] // should flip to +3 28 init_impl(base) 29 st[0] = 1; st[2] = 0 - 3; st[4] = H - PADH // ball at top heading off the left, paddle low 30 let rs0: i64 = st[7] 31 tick_impl(base, 0) 32 let scored: i64 = st[7] - rs0 33 var t1ok: i64=1; if returned <= 0 {t1ok=0} if scored != 1 {t1ok=0} 34 total=total+1; if t1ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 35 gw("T1 return+score: aligned paddle returned the ball (bvx=" as *u8); gn(returned); gw("), a miss scored (+" as *u8); gn(scored); gw(")\n" as *u8) 36 37 // ---- render a mid-rally frame ---- 38 init_impl(base) 39 var a: i64=0; while a < 12 { tick_impl(base, 0); a=a+1 } 40 render_impl(base) 41 let fb: *i64 = (base + O_FB) as *i64 42 write_png(fb, W, H, "knowledge/nx_wasm_pong_native.png" as *u8) 43 gw(" (live evidence: PNG knowledge/nx_wasm_pong_native.png -- paddles + ball + scores)\n" as *u8) 44 45 // ---- T2/T5/T6: render real -- BOTH PADDLES ARE ACTUALLY IN THE PICTURE ---- 46 // ★THE OLD TOOTH WAS HALF VACUOUS AND COMPOUND, so it could not name the failing half. The 47 // background is rgb(12,16,22), whose g=16 EXCEEDS r=12 -- so "player paddle green" passed on 48 // EMPTY BACKGROUND and would have kept passing with the paddle draw deleted. (The AI conjunct was 49 // genuine: the background is not reddish.) Found 2026-08-14 by nx_vacuity_census, the same class 50 // as nx_wasm_shmup_gate and nx_wasm_racing_gate. 51 // Both are now DIFFERENCES against the background, naming no colour, each its own counted tooth. 52 let lp: i64 = fb[st[4]*W + LX] 53 let rp: i64 = fb[st[5]*W + RX] 54 let bg1: i64 = fb[(H-10)*W + (W/4)] 55 let bg2: i64 = fb[(H-10)*W + (W/4 + 4)] 56 total=total+1; if lp != bg1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 57 gw("T2 render real: the PLAYER paddle is in frame -- differs from the background (paddle=" as *u8); gn(lp); gw(" bg=" as *u8); gn(bg1); gw(")\n" as *u8) 58 59 total=total+1; if rp != bg1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 60 gw("T5 render real: the AI paddle is in frame -- differs from the background (paddle=" as *u8); gn(rp); gw(" bg=" as *u8); gn(bg1); gw(")\n" as *u8) 61 62 // neg-control: the two background samples must AGREE, or the teeth above could be passing on 63 // ordinary background variation. A centre dash or the ball landing on one makes this FAIL LOUDLY. 64 total=total+1; if bg1 == bg2 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 65 gw("T6 neg-control-background-uniform: two background samples agree (" as *u8); gn(bg1); gw(" vs " as *u8); gn(bg2); gw(")\n" as *u8) 66 67 // ---- T3: wall bounce ---- 68 init_impl(base) 69 st[1] = 2; st[3] = 0 - 2 70 tick_impl(base, 0) 71 var t3ok: i64=1; if st[3] <= 0 {t3ok=0} 72 total=total+1; if t3ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 73 gw("T3 wall bounce: the ball reflected off the top wall (bvy=" as *u8); gn(st[3]); gw(")\n" as *u8) 74 75 // ---- T4: determinism ---- 76 init_impl(base) 77 a=0; while a < 30 { tick_impl(base, 0); a=a+1 } 78 let bx1: i64 = st[0]; let by1: i64 = st[1] 79 init_impl(base) 80 a=0; while a < 30 { tick_impl(base, 0); a=a+1 } 81 var t4ok: i64=1; if st[0] != bx1 {t4ok=0} if st[1] != by1 {t4ok=0} 82 total=total+1; if t4ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 83 gw("T4 never-brick (#26): deterministic re-run (ball " as *u8); gn(st[0]); gw("," as *u8); gn(st[1]); gw("), base-relative, no float, no sys_mmap in the core\n" as *u8) 84 85 gw("\n=== nx_wasm_pong_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 86 // D001 ANCHOR: the rich line above stays as this gate's public signature; the canonical verdict 87 // goes LAST because the estate's judge anchors by POSITION, taking only the final line. 88 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 89 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 90 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 91 let ctr__dry: *i64 = gv_ctr() 92 ctr__dry[0] = pass 93 ctr__dry[1] = total 94 let rc__dry: i64 = gv_verdict("WASM-PONG-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 95 sys_exit(rc__dry) 96 return rc__dry 97}