code wiki / (root) / nx_wasm_sandbox.nx

nx_wasm_sandbox.nx source

↩ module page · 127 lines · 5704 B

1// nx_wasm_sandbox.nx -- BROWSER-PLAYABLE sovereign Sandbox (falling-sand): BASE-RELATIVE integer core, runs 2// native (-> PNG) AND in the browser (base = 0). NO float, NO JS logic, NO canvas drawing. CLICK a palette 3// swatch (sand / water / wall / eraser), CLICK the grid to paint a brush; a cellular-automata tick makes sand 4// pile, water flow, walls hold. Uses the click(x,y) export. init()/tick(input)/render()/score()/ww()/hh()/ 5// fb_off()/click(x,y) = the wasm interface. license_tier: ORIGINAL 6const W: i64 = 180 7const H: i64 = 160 8const TOOLH: i64 = 20 9const CELL: i64 = 4 10const GW: i64 = 45 // W/CELL 11const GH: i64 = 35 // (H-TOOLH)/CELL 12const O_FB: i64 = 0 // framebuffer W*H i64 13const O_MAP: i64 = 230400 // map[GW*GH]: 0 empty,1 sand,2 water,3 wall (W*H*8) 14const O_ST: i64 = 243000 // scalars[16]: 0=sel 1=placed 15 16func rgb(r: i64, g: i64, b: i64) -> i64 { return (r & 255) | ((g & 255) << 8) | ((b & 255) << 16) } 17func matcolor(m: i64) -> i64 { 18 if m == 1 { return rgb(222, 200, 128) } // sand 19 if m == 2 { return rgb(64, 120, 224) } // water 20 if m == 3 { return rgb(112, 112, 124) } // wall 21 return rgb(20, 22, 30) // empty 22} 23 24func fillr(base: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 { 25 let fb: *i64 = (base + O_FB) as *i64 26 var yy: i64 = y0; if yy < 0 { yy = 0 } 27 var ye: i64 = y1; if ye > H { ye = H } 28 while yy < ye { 29 var xx: i64 = x0; if xx < 0 { xx = 0 } 30 var xe: i64 = x1; if xe > W { xe = W } 31 while xx < xe { fb[yy*W + xx] = c; xx = xx + 1 } 32 yy = yy + 1 33 } 34 return 0 35} 36 37func init_impl(base: i64) -> i64 { 38 let mp: *i64 = (base + O_MAP) as *i64 39 let st: *i64 = (base + O_ST) as *i64 40 var i: i64 = 0; while i < GW*GH { mp[i] = 0; i = i + 1 } 41 st[0] = 1; st[1] = 0 42 return 0 43} 44 45func click_impl(base: i64, x: i64, y: i64) -> i64 { 46 let mp: *i64 = (base + O_MAP) as *i64 47 let st: *i64 = (base + O_ST) as *i64 48 if y < TOOLH { 49 let s: i64 = x / 20 50 if s == 0 { st[0] = 1 } else { if s == 1 { st[0] = 2 } else { if s == 2 { st[0] = 3 } else { st[0] = 0 } } } 51 return 0 52 } 53 let cx: i64 = x / CELL; let cy: i64 = (y - TOOLH) / CELL 54 var by: i64 = cy - 1 55 while by <= cy + 1 { 56 var bx: i64 = cx - 1 57 while bx <= cx + 1 { 58 if bx >= 0 { if by >= 0 { if bx < GW { if by < GH { mp[by*GW + bx] = st[0]; st[1] = st[1] + 1 } } } } 59 bx = bx + 1 60 } 61 by = by + 1 62 } 63 return 0 64} 65 66func tick_impl(base: i64, input: i64) -> i64 { 67 let mp: *i64 = (base + O_MAP) as *i64 68 var y: i64 = GH - 1 69 while y >= 0 { 70 var x: i64 = 0 71 while x < GW { 72 let c: i64 = mp[y*GW + x] 73 if c == 1 { // sand: down, down-left, down-right 74 if y+1 < GH { 75 if mp[(y+1)*GW + x] == 0 { mp[(y+1)*GW + x] = 1; mp[y*GW + x] = 0 } 76 else { if x-1 >= 0 { if mp[(y+1)*GW + x-1] == 0 { mp[(y+1)*GW + x-1] = 1; mp[y*GW + x] = 0 } 77 else { if x+1 < GW { if mp[(y+1)*GW + x+1] == 0 { mp[(y+1)*GW + x+1] = 1; mp[y*GW + x] = 0 } } } } 78 else { if x+1 < GW { if mp[(y+1)*GW + x+1] == 0 { mp[(y+1)*GW + x+1] = 1; mp[y*GW + x] = 0 } } } } 79 } 80 } else { if c == 2 { // water: fall, else flow sideways 81 var moved: i64 = 0 82 if y+1 < GH { if mp[(y+1)*GW + x] == 0 { mp[(y+1)*GW + x] = 2; mp[y*GW + x] = 0; moved = 1 } } 83 if moved == 0 { if y+1 < GH { if x-1 >= 0 { if mp[(y+1)*GW + x-1] == 0 { mp[(y+1)*GW + x-1] = 2; mp[y*GW + x] = 0; moved = 1 } } } } 84 if moved == 0 { if y+1 < GH { if x+1 < GW { if mp[(y+1)*GW + x+1] == 0 { mp[(y+1)*GW + x+1] = 2; mp[y*GW + x] = 0; moved = 1 } } } } 85 if moved == 0 { if x-1 >= 0 { if mp[y*GW + x-1] == 0 { mp[y*GW + x-1] = 2; mp[y*GW + x] = 0; moved = 1 } } } 86 if moved == 0 { if x+1 < GW { if mp[y*GW + x+1] == 0 { mp[y*GW + x+1] = 2; mp[y*GW + x] = 0; moved = 1 } } } 87 } } 88 x = x + 1 89 } 90 y = y - 1 91 } 92 return 0 93} 94 95func render_impl(base: i64) -> i64 { 96 let mp: *i64 = (base + O_MAP) as *i64 97 let st: *i64 = (base + O_ST) as *i64 98 fillr(base, 0, 0, W, TOOLH, rgb(16, 18, 24)) // palette bar 99 var s: i64 = 0 100 while s < 4 { 101 var m: i64 = s + 1; if s == 3 { m = 0 } // 0=sand,1=water,2=wall,3=eraser(empty) 102 fillr(base, s*20 + 2, 3, s*20 + 18, 17, matcolor(m)) 103 var selm: i64 = st[0]; var seli: i64 = selm - 1; if selm == 0 { seli = 3 } 104 if seli == s { fillr(base, s*20+1, 1, s*20+19, 2, rgb(240,240,255)); fillr(base, s*20+1, 18, s*20+19, 19, rgb(240,240,255)); fillr(base, s*20+1, 1, s*20+2, 19, rgb(240,240,255)); fillr(base, s*20+18, 1, s*20+19, 19, rgb(240,240,255)) } 105 s = s + 1 106 } 107 var y: i64 = 0 108 while y < GH { 109 var x: i64 = 0 110 while x < GW { 111 let c: i64 = mp[y*GW + x] 112 if c != 0 { fillr(base, x*CELL, TOOLH + y*CELL, x*CELL + CELL, TOOLH + y*CELL + CELL, matcolor(c)) } 113 x = x + 1 114 } 115 y = y + 1 116 } 117 return 0 118} 119 120func init() -> i64 { return init_impl(0) } 121func tick(input: i64) -> i64 { return tick_impl(0, input) } 122func render() -> i64 { return render_impl(0) } 123func click(x: i64, y: i64) -> i64 { return click_impl(0, x, y) } 124func score() -> i64 { let st: *i64 = (0 + O_ST) as *i64; return st[1] } 125func fb_off() -> i64 { return O_FB } 126func ww() -> i64 { return W } 127func hh() -> i64 { return H }