code wiki / _hdl_build / nx_game_shmup_gate.nx

nx_game_shmup_gate.nx source

↩ module page · 109 lines · 6385 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_game_shmup_gate.nx -- GENRE: Shoot 'em up (catalog genre, was ABSENT). A real integer/no-float shmup 4// CORE -- player ship, a bullet, an enemy formation, aim+shoot+collision -- with a SCRIPTED PLAYTHROUGH that 5// clears the wave (live evidence the ecosystem builds a playable of this genre), a rendered frame (the games' 6// packed-RGB fb, display-path-ready per SF5), a neg-control (aiming matters) + liar-kill (collision is real). 7// T1 PLAYTHROUGH: aim+shoot each enemy column -> the whole wave is cleared (score == N = WIN). PNG. 8// T2 NEG-CONTROL: firing from an empty column (mis-aimed) clears NOTHING (score == 0) -- aiming is real. 9// T3 COLLISION REAL: one aligned shot kills EXACTLY the aligned enemy (the others survive). 10// T4 NEVER-BRICK (#26): deterministic (re-run -> identical), bounded, no float, zero hardware writes. 11// expect_exit: 0 license_tier: ORIGINAL 12import "nx_game_raster.nx" 13import "nx_png.nx" 14import "nx_syscalls.nx" 15 16func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 17" as *u8); return ok } 18 19// st[0]=sx st[1]=sy st[2]=bx st[3]=by st[4]=bullet_active st[5]=score 20func sh_reset(st: *i64, alive: *i64, n: i64, sy: i64) -> i64 { 21 st[0]=64; st[1]=sy; st[2]=0; st[3]=0; st[4]=0; st[5]=0 22 var i: i64=0; while i<n { alive[i]=1; i=i+1 } 23 return 0 24} 25func sh_shoot(st: *i64) -> i64 { if st[4]==0 { st[2]=st[0]; st[3]=st[1]-8; st[4]=1 } return 0 } 26func sh_step(st: *i64, ex: *i64, alive: *i64, n: i64, ey: i64) -> i64 { 27 if st[4]==1 { 28 st[3]=st[3]-6 29 if st[3]<0 { st[4]=0 } else { 30 var i: i64=0 31 while i<n { 32 if alive[i]==1 { 33 var dx: i64=st[2]-ex[i]; if dx<0 {dx=0-dx} 34 var dy: i64=st[3]-ey; if dy<0 {dy=0-dy} 35 if dx<7 { if dy<8 { alive[i]=0; st[4]=0; st[5]=st[5]+1 } } 36 } 37 i=i+1 38 } 39 } 40 } 41 return 0 42} 43// move ship to a column, fire, and resolve the bullet to completion (scripted aim+shoot). 44func sh_fire_at(st: *i64, ex: *i64, alive: *i64, n: i64, ey: i64, col: i64) -> i64 { 45 st[0]=col 46 sh_shoot(st) 47 var guard: i64=0 48 while st[4]==1 { if guard>=48 { st[4]=0 } else { sh_step(st, ex, alive, n, ey) } guard=guard+1 } 49 return 0 50} 51func sh_render(fb: *i64, w: i64, h: i64, st: *i64, ex: *i64, alive: *i64, n: i64, ey: i64, sy: i64) -> i64 { 52 gr_clear(fb, w, h, gr_pack(8, 10, 24)) 53 gr_px(fb, w, h, 12, 18, gr_pack(120,120,150)); gr_px(fb, w, h, 100, 30, gr_pack(120,120,150)) // stars 54 gr_px(fb, w, h, 60, 50, gr_pack(120,120,150)); gr_px(fb, w, h, 30, 64, gr_pack(120,120,150)) 55 var i: i64=0 56 while i<n { if alive[i]==1 { gr_rect(fb, w, h, ex[i]-6, ey-5, ex[i]+6, ey+5, gr_pack(224,80,58)); gr_rect(fb, w, h, ex[i]-3, ey+5, ex[i]+3, ey+8, gr_pack(150,50,40)) } i=i+1 } 57 if st[4]==1 { gr_rect(fb, w, h, st[2]-1, st[3]-4, st[2]+2, st[3]+3, gr_pack(250,240,120)) } 58 gr_rect(fb, w, h, st[0]-7, sy-3, st[0]+8, sy+5, gr_pack(90,210,122)) 59 gr_rect(fb, w, h, st[0]-2, sy-7, st[0]+3, sy-3, gr_pack(120,230,150)) 60 return 0 61} 62 63func main() -> i64 { 64 gw("=== nx_game_shmup_gate: GENRE Shoot-em-up -- a real integer/no-float playable (live evidence) ===\n" as *u8) 65 var pass: i64 = 0; var total: i64 = 0 66 let W: i64=128; let H: i64=96; let N: i64=6; let EY: i64=14; let SY: i64=84 67 let ex: *i64=sys_mmap(8*8) as *i64; let alive: *i64=sys_mmap(8*8) as *i64; let st: *i64=sys_mmap(8*8) as *i64 68 ex[0]=14; ex[1]=34; ex[2]=54; ex[3]=74; ex[4]=94; ex[5]=114 69 70 // ---- T1: full scripted playthrough clears the wave ---- 71 sh_reset(st, alive, N, SY) 72 var i: i64=0; while i<N { sh_fire_at(st, ex, alive, N, EY, ex[i]); i=i+1 } 73 let won: i64 = st[5] 74 total=total+1; if won==N { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 75 gw("T1 playthrough: aim+shoot cleared the wave, score=" as *u8); gn(won); gw("/" as *u8); gn(N); gw(" (WIN)\n" as *u8) 76 77 // ---- render a mid-game frame for live evidence ---- 78 let fb: *i64=sys_mmap(8*(W*H+8)) as *i64 79 sh_reset(st, alive, N, SY) 80 sh_fire_at(st, ex, alive, N, EY, ex[0]); sh_fire_at(st, ex, alive, N, EY, ex[1]); sh_fire_at(st, ex, alive, N, EY, ex[2]) // 3 down 81 st[0]=ex[3]; sh_shoot(st); sh_step(st, ex, alive, N, EY); sh_step(st, ex, alive, N, EY); sh_step(st, ex, alive, N, EY) // bullet mid-flight 82 sh_render(fb, W, H, st, ex, alive, N, EY, SY) 83 write_png(fb, W, H, "knowledge/nx_game_shmup.png" as *u8) 84 gw(" (live evidence: PNG knowledge/nx_game_shmup.png -- ship + bullet in flight + 3 enemies down)\n" as *u8) 85 86 // ---- T2: neg-control -- firing from an empty column clears nothing ---- 87 sh_reset(st, alive, N, SY) 88 i=0; while i<N { sh_fire_at(st, ex, alive, N, EY, 4); i=i+1 } // column 4 has no enemy (first is at 14) 89 let missed: i64 = st[5] 90 total=total+1; if missed==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 91 gw("T2 neg-control: mis-aimed shots (empty column) cleared " as *u8); gn(missed); gw(" (=0, aiming is real)\n" as *u8) 92 93 // ---- T3: collision real -- one aligned shot kills exactly the aligned enemy ---- 94 sh_reset(st, alive, N, SY) 95 sh_fire_at(st, ex, alive, N, EY, ex[2]) 96 var t3ok: i64=1; if alive[2]!=0 {t3ok=0} if alive[0]!=1 {t3ok=0} if alive[5]!=1 {t3ok=0} if st[5]!=1 {t3ok=0} 97 total=total+1; if t3ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 98 gw("T3 collision real: an aligned shot killed exactly enemy 2 (others alive), score=" as *u8); gn(st[5]); gw("\n" as *u8) 99 100 // ---- T4: never-brick / determinism ---- 101 sh_reset(st, alive, N, SY); i=0; while i<N { sh_fire_at(st, ex, alive, N, EY, ex[i]); i=i+1 } 102 let run2: i64 = st[5] 103 total=total+1; if run2==won { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 104 gw("T4 never-brick (#26): deterministic (re-run score=" as *u8); gn(run2); gw("==" as *u8); gn(won); gw("), bounded, no float\n" as *u8) 105 106 gw("\n=== nx_game_shmup_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 107 if pass == total { gw(" GREEN (Shoot-em-up: a real playable wave-clear with aim/shoot/collision, rendered, sovereign)\n" as *u8); sys_exit(0); return 0 } 108 gw(" RED\n" as *u8); sys_exit(1); return 1 109}