code wiki / _hdl_build / nx_game_thirdperson_gate.nx

nx_game_thirdperson_gate.nx source

↩ module page · 103 lines · 6971 B

1import "nx_gate_gn.nx" 2import "nx_gate_base.nx" 3// nx_game_thirdperson_gate.nx -- GENRE: Third-Person (catalog genre, was ABSENT). A real integer/no-float 4// third-person CORE -- a character explores a world LARGER than the screen with a FOLLOW CAMERA (the avatar 5// stays centered, the world scrolls under it); collect items, reach the goal. Scripted run, rendered frame 6// (the follow-camera view), neg-control (must collect) + camera-follows-real. 7// T1 RUN: visit every item then the goal -> level complete (WIN). PNG (the third-person follow view). 8// T2 NEG-CONTROL: reaching the goal WITHOUT all items does not complete the level. 9// T3 CAMERA REAL: the camera centers on the avatar in the world interior (follows it, not fixed). 10// T4 NEVER-BRICK (#26): deterministic, bounded, no float. 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 } 18func p_sign(v: i64) -> i64 { if v>0 {return 1} if v<0 {return 0-1} return 0 } 19func p_clamp(v: i64, lo: i64, hi: i64) -> i64 { if v<lo {return lo} if v>hi {return hi} return v } 20 21// ps[0]=cx ps[1]=cy ps[2]=collected ps[3]=won 22func tp_step(ps: *i64, ix: *i64, iy: *i64, got: *i64, ni: i64, gx: i64, gy: i64, ww: i64, wh: i64, dx: i64, dy: i64) -> i64 { 23 ps[0]=p_clamp(ps[0]+dx, 0, ww-1); ps[1]=p_clamp(ps[1]+dy, 0, wh-1) 24 var i: i64=0 25 while i<ni { if got[i]==0 { if ps[0]==ix[i] { if ps[1]==iy[i] { got[i]=1; ps[2]=ps[2]+1 } } } i=i+1 } 26 if ps[0]==gx { if ps[1]==gy { if ps[2]==ni { ps[3]=1 } } } 27 return 0 28} 29func tp_goto(ps: *i64, ix: *i64, iy: *i64, got: *i64, ni: i64, gx: i64, gy: i64, ww: i64, wh: i64, tx: i64, ty: i64) -> i64 { 30 var g: i64=0; while ps[0]!=tx { if g>=80 { ps[0]=tx } else { tp_step(ps, ix, iy, got, ni, gx, gy, ww, wh, p_sign(tx-ps[0]), 0) } g=g+1 } 31 g=0; while ps[1]!=ty { if g>=80 { ps[1]=ty } else { tp_step(ps, ix, iy, got, ni, gx, gy, ww, wh, 0, p_sign(ty-ps[1])) } g=g+1 } 32 return 0 33} 34func tp_cam(c: i64, cell: i64, screen: i64, worldpx: i64) -> i64 { return p_clamp(c*cell + cell/2 - screen/2, 0, worldpx - screen) } 35func tp_render(fb: *i64, w: i64, h: i64, cell: i64, ww: i64, wh: i64, ps: *i64, ix: *i64, iy: *i64, got: *i64, ni: i64, gx: i64, gy: i64) -> i64 { 36 let camx: i64=tp_cam(ps[0], cell, w, ww*cell); let camy: i64=tp_cam(ps[1], cell, h, wh*cell) 37 // checker-floor world (scrolls under the avatar) 38 var y: i64=0 39 while y<wh { 40 var x: i64=0 41 while x<ww { 42 var col: i64=gr_pack(40,70,46); if ((x+y)&1)==1 { col=gr_pack(48,84,54) } 43 gr_rect(fb, w, h, x*cell-camx, y*cell-camy, x*cell+cell-camx, y*cell+cell-camy, col) 44 x=x+1 45 } 46 y=y+1 47 } 48 gr_rect(fb, w, h, gx*cell-camx+2, gy*cell-camy+2, gx*cell-camx+cell-2, gy*cell-camy+cell-2, gr_pack(90,210,220)) // goal (cyan) 49 var i: i64=0 50 while i<ni { if got[i]==0 { gr_disc(fb, w, h, ix[i]*cell-camx+cell/2, iy[i]*cell-camy+cell/2, 3, gr_pack(245,210,70)) } i=i+1 } // items (gold) 51 gr_rect(fb, w, h, ps[0]*cell-camx+2, ps[1]*cell-camy+2, ps[0]*cell-camx+cell-2, ps[1]*cell-camy+cell-2, gr_pack(90,210,122)) // avatar (green, centered) 52 return 0 53} 54 55func main() -> i64 { 56 gw("=== nx_game_thirdperson_gate: GENRE Third-Person -- a real integer/no-float playable (live evidence) ===\n" as *u8) 57 var pass: i64 = 0; var total: i64 = 0 58 let WW: i64=16; let WH: i64=12; let CELL: i64=10; let W: i64=96; let H: i64=80; let NI: i64=3 59 let GX: i64=14; let GY: i64=10 60 let ps: *i64=sys_mmap(8*4) as *i64; let ix: *i64=sys_mmap(8*4) as *i64; let iy: *i64=sys_mmap(8*4) as *i64; let got: *i64=sys_mmap(8*4) as *i64 61 ix[0]=3; iy[0]=8; ix[1]=8; iy[1]=3; ix[2]=11; iy[2]=9 62 63 // ---- T1: visit every item then the goal ---- 64 ps[0]=1; ps[1]=1; ps[2]=0; ps[3]=0; got[0]=0; got[1]=0; got[2]=0 65 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, ix[0], iy[0]) 66 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, ix[1], iy[1]) 67 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, ix[2], iy[2]) 68 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, GX, GY) 69 var t1ok: i64=1; if ps[2]!=NI {t1ok=0} if ps[3]!=1 {t1ok=0} 70 total=total+1; if t1ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 71 gw("T1 run: collected " as *u8); gn(ps[2]); gw("/" as *u8); gn(NI); gw(" items then reached the goal, won=" as *u8); gn(ps[3]); gw(" (WIN)\n" as *u8) 72 73 // ---- render the follow-camera view mid-run ---- 74 let fb: *i64=sys_mmap(8*(W*H+8)) as *i64 75 ps[0]=1; ps[1]=1; ps[2]=0; ps[3]=0; got[0]=0; got[1]=0; got[2]=0 76 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, ix[0], iy[0]) 77 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, 8, 6) 78 tp_render(fb, W, H, CELL, WW, WH, ps, ix, iy, got, NI, GX, GY) 79 write_png(fb, W, H, "knowledge/nx_game_thirdperson.png" as *u8) 80 gw(" (live evidence: PNG knowledge/nx_game_thirdperson.png -- follow-camera view: avatar centered, world scrolled)\n" as *u8) 81 82 // ---- T2: neg-control -- the goal without all items does not complete ---- 83 ps[0]=1; ps[1]=1; ps[2]=0; ps[3]=0; got[0]=0; got[1]=0; got[2]=0 84 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, GX, GY) // straight to the goal (items are off this path) 85 total=total+1; if ps[3]==0 { if ps[2]<NI { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } 86 gw("T2 neg-control: reached the goal with only " as *u8); gn(ps[2]); gw("/" as *u8); gn(NI); gw(" items -> not complete, won=" as *u8); gn(ps[3]); gw("\n" as *u8) 87 88 // ---- T3: camera follows -- centers on the avatar in the world interior ---- 89 let camx: i64=tp_cam(8, CELL, W, WW*CELL); let want: i64=8*CELL + CELL/2 - W/2 90 total=total+1; if camx==want { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 91 gw("T3 camera real: at an interior tile the camera centers on the avatar (camx=" as *u8); gn(camx); gw(", centered=" as *u8); gn(want); gw(")\n" as *u8) 92 93 // ---- T4: never-brick / determinism ---- 94 ps[0]=1; ps[1]=1; ps[2]=0; ps[3]=0; got[0]=0; got[1]=0; got[2]=0 95 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, ix[0], iy[0]); tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, ix[1], iy[1]) 96 tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, ix[2], iy[2]); tp_goto(ps, ix, iy, got, NI, GX, GY, WW, WH, GX, GY) 97 total=total+1; if ps[3]==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 98 gw("T4 never-brick (#26): deterministic re-run won=" as *u8); gn(ps[3]); gw(", bounded, no float\n" as *u8) 99 100 gw("\n=== nx_game_thirdperson_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 101 if pass == total { gw(" GREEN (Third-Person: a real playable follow-camera explorer (collect+goal), rendered, sovereign)\n" as *u8); sys_exit(0); return 0 } 102 gw(" RED\n" as *u8); sys_exit(1); return 1 103}