code wiki / (root) / nx_wasm_city.nx

nx_wasm_city.nx source

↩ module page · 140 lines · 5956 B

1// nx_wasm_city.nx -- BROWSER-PLAYABLE sovereign City-Building: BASE-RELATIVE integer core, runs native (-> PNG) 2// AND in the browser (base = 0). NO float, NO JS logic, NO canvas drawing. CLICK a toolbar button to pick a 3// building, CLICK the grid to place it (costs gold): farms make food, houses raise population capacity, and 4// population grows when fed; markets make gold. Balance food vs houses vs markets to grow the city. Uses the 5// click(x,y) export. init()/tick(input)/render()/score()/ww()/hh()/fb_off()/click(x,y) = the wasm interface. 6// license_tier: ORIGINAL 7import "nx_nishi_font_core.nx" 8const W: i64 = 200 9const H: i64 = 170 10const GW: i64 = 10 11const GH: i64 = 7 12const CELL: i64 = 20 13const GY0: i64 = 24 // grid top (toolbar above) 14const TOOLH: i64 = 22 15const ECON: i64 = 30 // economy ticks 16const HCOST: i64 = 10 17const FCOST: i64 = 8 18const MCOST: i64 = 12 19const O_FB: i64 = 0 // framebuffer W*H i64 20const O_MAP: i64 = 272000 // map[GW*GH]: 0 empty,1 house,2 farm,3 market (W*H*8) 21const O_ST: i64 = 272560 // scalars[16]: 0=gold 1=food 2=pop 3=sel 4=tick 5=nhouse 6=nfarm 7=nmarket 22const O_MSK: i64 = 272688 23const O_STR: i64 = 280880 24 25func rgb(r: i64, g: i64, b: i64) -> i64 { return (r & 255) | ((g & 255) << 8) | ((b & 255) << 16) } 26 27func fillr(base: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 { 28 let fb: *i64 = (base + O_FB) as *i64 29 var yy: i64 = y0; if yy < 0 { yy = 0 } 30 var ye: i64 = y1; if ye > H { ye = H } 31 while yy < ye { 32 var xx: i64 = x0; if xx < 0 { xx = 0 } 33 var xe: i64 = x1; if xe > W { xe = W } 34 while xx < xe { fb[yy*W + xx] = c; xx = xx + 1 } 35 yy = yy + 1 36 } 37 return 0 38} 39func bcolor(typ: i64) -> i64 { 40 if typ == 1 { return rgb(80, 130, 220) } // house blue 41 if typ == 2 { return rgb(90, 200, 110) } // farm green 42 return rgb(235, 200, 80) // market gold 43} 44func bcost(typ: i64) -> i64 { if typ == 1 { return HCOST } if typ == 2 { return FCOST } return MCOST } 45 46func init_impl(base: i64) -> i64 { 47 let mp: *i64 = (base + O_MAP) as *i64 48 let st: *i64 = (base + O_ST) as *i64 49 var i: i64 = 0; while i < GW*GH { mp[i] = 0; i = i + 1 } 50 st[0] = 50; st[1] = 15; st[2] = 0; st[3] = 2; st[4] = 0; st[5] = 0; st[6] = 0; st[7] = 0 51 return 0 52} 53 54func click_impl(base: i64, x: i64, y: i64) -> i64 { 55 let mp: *i64 = (base + O_MAP) as *i64 56 let st: *i64 = (base + O_ST) as *i64 57 if y < TOOLH { 58 if x < 20 { st[3] = 1 } else { if x < 40 { st[3] = 2 } else { if x < 60 { st[3] = 3 } } } 59 return 0 60 } 61 let gx: i64 = x / CELL 62 let gy: i64 = (y - GY0) / CELL 63 if gx < 0 { return 0 } if gy < 0 { return 0 } if gx >= GW { return 0 } if gy >= GH { return 0 } 64 if mp[gy*GW + gx] != 0 { return 0 } 65 let typ: i64 = st[3] 66 let cost: i64 = bcost(typ) 67 if st[0] < cost { return 0 } 68 mp[gy*GW + gx] = typ; st[0] = st[0] - cost 69 if typ == 1 { st[5] = st[5] + 1 } else { if typ == 2 { st[6] = st[6] + 1 } else { st[7] = st[7] + 1 } } 70 return 0 71} 72 73func tick_impl(base: i64, input: i64) -> i64 { 74 let st: *i64 = (base + O_ST) as *i64 75 st[4] = st[4] + 1 76 if (st[4] % ECON) == 0 { 77 st[1] = st[1] + st[6]*3 - st[2] // food += farms*3 - population eats 78 if st[1] < 0 { st[1] = 0 } 79 let cap: i64 = st[5]*4 // house capacity 80 if st[1] > 0 { if st[2] < cap { st[2] = st[2] + 1; st[1] = st[1] - 1 } } 81 st[0] = st[0] + st[7]*2 // gold += markets*2 82 } 83 return 0 84} 85 86func num(base: i64, x: i64, off: i64, val: i64, col: i64) -> i64 { 87 let fb: *i64 = (base + O_FB) as *i64 88 let sbuf: *u8 = (base + O_STR + off) as *u8 89 var slen: i64 = 0; var sv: i64 = val 90 if sv <= 0 { sbuf[0] = 48 as u8; slen = 1 } else { 91 let tmp: *u8 = (base + O_STR + off + 12) as *u8; var k: i64 = 0 92 while sv > 0 { tmp[k] = (48 + (sv % 10)) as u8; sv = sv / 10; k = k + 1 } 93 var q: i64 = 0; while q < k { sbuf[q] = tmp[k - 1 - q]; q = q + 1 } 94 slen = k 95 } 96 let mask: *u8 = (base + O_MSK) as *u8 97 nf_draw_text_mem(fb, W, H, mask, x, 4, 16, sbuf, slen, col) 98 return 0 99} 100func render_impl(base: i64) -> i64 { 101 let fb: *i64 = (base + O_FB) as *i64 102 let mp: *i64 = (base + O_MAP) as *i64 103 let st: *i64 = (base + O_ST) as *i64 104 var p: i64 = 0; while p < W*H { fb[p] = rgb(30, 40, 34); p = p + 1 } 105 // toolbar 106 fillr(base, 0, 0, W, TOOLH, rgb(20, 26, 24)) 107 var b: i64 = 1 108 while b <= 3 { 109 let bx: i64 = (b-1)*20 110 fillr(base, bx+2, 3, bx+18, 19, bcolor(b)) 111 if st[3] == b { fillr(base, bx+1, 1, bx+19, 2, rgb(240,240,255)); fillr(base, bx+1, 20, bx+19, 21, rgb(240,240,255)); fillr(base, bx+1, 1, bx+2, 21, rgb(240,240,255)); fillr(base, bx+18, 1, bx+19, 21, rgb(240,240,255)) } 112 b = b + 1 113 } 114 num(base, 70, 0, st[0], rgb(235,200,80)) // gold 115 num(base, 120, 32, st[1], rgb(90,200,110)) // food 116 num(base, 165, 64, st[2], rgb(235,240,250)) // population 117 // grid 118 var gy: i64 = 0 119 while gy < GH { 120 var gx: i64 = 0 121 while gx < GW { 122 let cx: i64 = gx*CELL; let cy: i64 = GY0 + gy*CELL 123 fillr(base, cx+1, cy+1, cx+CELL-1, cy+CELL-1, rgb(44, 56, 48)) 124 let c: i64 = mp[gy*GW + gx] 125 if c != 0 { fillr(base, cx+3, cy+3, cx+CELL-3, cy+CELL-3, bcolor(c)) } 126 gx = gx + 1 127 } 128 gy = gy + 1 129 } 130 return 0 131} 132 133func init() -> i64 { return init_impl(0) } 134func tick(input: i64) -> i64 { return tick_impl(0, input) } 135func render() -> i64 { return render_impl(0) } 136func click(x: i64, y: i64) -> i64 { return click_impl(0, x, y) } 137func score() -> i64 { let st: *i64 = (0 + O_ST) as *i64; return st[2] } 138func fb_off() -> i64 { return O_FB } 139func ww() -> i64 { return W } 140func hh() -> i64 { return H }