code wiki / _hdl_build / nx_wasm_mineworld_mod_gate.nx
nx_wasm_mineworld_mod_gate.nx source
↩ module page · 127 lines · 5493 B
1// nx_wasm_mineworld_mod_gate.nx -- gate for BLOCKS-AS-DATA (the first loose-coupling rung of the moddable
2// architecture; operator: games = data-io + logic layers, mods change data, no recompile).
3// T1 the built-in DATA pack lazy-loads and the world renders (frame mostly terrain).
4// T2 a MOD = runtime data records: override grass -> RED via blk_set -> the SAME world re-renders visibly
5// differently (re-skin live, zero recompile) + PNG knowledge/nx_mineworld_mod.png (eyeball: red world).
6// T3 pack reset restores the base pack -> frame BYTE-IDENTICAL to T1 (reversible, deterministic).
7// T4 boundaries: block id 0 / >=MAXBLK REJECTED; an undefined in-range block renders LOUD MAGENTA (never silent).
8// T5 determinism re-render.
9// license_tier: ORIGINAL expect_exit: 0
10import "nx_syscalls.nx"
11import "nx_f32_hw.nx"
12import "nx_png.nx"
13import "nx_wasm_mineworld.nx"
14
15func hw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
16func pn(v: i64) -> i64 {
17 let b: *u8 = sys_mmap(32) as *u8
18 var x: i64 = v
19 var neg: i64 = 0
20 if x < 0 { neg = 1; x = 0 - x }
21 var i: i64 = 31
22 if x == 0 { b[i] = 48 as u8; i = i - 1 }
23 while x > 0 { b[i] = (48 + x % 10) as u8; x = x / 10; i = i - 1 }
24 if neg == 1 { b[i] = 45 as u8; i = i - 1 }
25 sys_write(1, (b as i64 + i + 1) as *u8, 31 - i)
26 return 0
27}
28func fbsum(base: i64) -> i64 {
29 let fb: *i64 = (base + fb_off()) as *i64
30 var s: i64 = 0
31 var i: i64 = 0
32 while i < ww() * hh() { s = s * 31 + fb[i]; i = i + 1 }
33 return s
34}
35func rend(base: i64) -> i64 {
36 let eye: i64 = terrain_h0(30, 30) + 8
37 let camx: i64 = f32_div(f32_of(30 * 256 + 128), f32_of(256))
38 let camy: i64 = f32_div(f32_of(eye * 256), f32_of(256))
39 build_R(base, 1000, 0, 927, 0 - 375)
40 render_at(base, camx, camy, camx, 30, 30)
41 return 0
42}
43
44func main() -> i64 {
45 let base: i64 = sys_mmap(mem_bytes()) as i64
46 var fails: i64 = 0
47
48 // T1 default pack renders (ground truth = the renderer's own drawn-pixel counter)
49 rend(base)
50 let c1: i64 = fbsum(base)
51 let dpx: i64 = drawn_px_at(base)
52 if dpx * 3 >= ww() * hh() { hw("T1 PASS built-in data pack lazy-loads + world renders (drawn-px=" as *u8); pn(dpx); hw(")\n" as *u8) }
53 else { hw("T1 FAIL mostly sky drawn-px=" as *u8); pn(dpx); hw("\n" as *u8); fails = fails + 1 }
54
55 // T2 a MOD (pure data, runtime) re-skins the SAME world
56 blk_set(base, K_GRASS, rgb(200, 40, 40), rgb(150, 30, 30), ST_PLAIN)
57 blk_set(base, K_LEAF, rgb(210, 120, 30), rgb(210, 120, 30), ST_LEAF)
58 rend(base)
59 let c2: i64 = fbsum(base)
60 write_png((base + fb_off()) as *i64, ww(), hh(), "knowledge/nx_mineworld_mod.png" as *u8)
61 if c2 != c1 { hw("T2 PASS mod override (grass->red, leaves->autumn) re-skins LIVE, zero recompile + PNG\n" as *u8) }
62 else { hw("T2 FAIL mod had no visible effect\n" as *u8); fails = fails + 1 }
63
64 // T3 reset restores the base pack exactly
65 pack_default_at(base)
66 rend(base)
67 let c3: i64 = fbsum(base)
68 if c3 == c1 { hw("T3 PASS pack reset -> frame BYTE-IDENTICAL to default (reversible, deterministic)\n" as *u8) }
69 else { hw("T3 FAIL reset did not restore\n" as *u8); fails = fails + 1 }
70
71 // T4 boundaries + loud-undefined
72 var t4: i64 = 1
73 if blk_set(base, 0, 1, 1, 0) != 0 - 1 { t4 = 0 }
74 if blk_set(base, MAXBLK, 1, 1, 0) != 0 - 1 { t4 = 0 }
75 let und: i64 = tex(base, 25, 0, 3, 3)
76 if und != rgb(200, 60, 200) { t4 = 0 }
77 if t4 == 1 { hw("T4 PASS id bounds rejected + undefined block renders loud magenta\n" as *u8) }
78 else { hw("T4 FAIL boundary/undefined handling\n" as *u8); fails = fails + 1 }
79
80 // T5 determinism
81 rend(base)
82 let c4: i64 = fbsum(base)
83 if c4 == c1 { hw("T5 PASS re-render byte-identical\n" as *u8) }
84 else { hw("T5 FAIL nondeterministic\n" as *u8); fails = fails + 1 }
85
86 // T6 ORE VEINS (harvested minecraftclone vocabulary) generate underground with sane rarity ordering
87 var n_coal: i64 = 0
88 var n_iron: i64 = 0
89 var n_gold: i64 = 0
90 var n_emer: i64 = 0
91 var oz: i64 = 0
92 while oz < 50 {
93 var ox2: i64 = 0
94 while ox2 < 50 {
95 var oy: i64 = 1
96 while oy <= 12 {
97 let kk: i64 = kind_c(base, ox2, oy, oz)
98 if kk == K_COAL { n_coal = n_coal + 1 }
99 if kk == K_IRON { n_iron = n_iron + 1 }
100 if kk == K_GOLD { n_gold = n_gold + 1 }
101 if kk == K_EMER { n_emer = n_emer + 1 }
102 oy = oy + 1
103 }
104 ox2 = ox2 + 1
105 }
106 oz = oz + 1
107 }
108 var t6: i64 = 1
109 if n_coal == 0 { t6 = 0 }
110 if n_iron == 0 { t6 = 0 }
111 if n_gold == 0 { t6 = 0 }
112 if n_emer == 0 { t6 = 0 }
113 if n_coal <= n_iron { t6 = 0 }
114 if n_iron <= n_gold { t6 = 0 }
115 if t6 == 1 {
116 hw("T6 PASS ore veins generate (coal=" as *u8); pn(n_coal); hw(" iron=" as *u8); pn(n_iron)
117 hw(" gold=" as *u8); pn(n_gold); hw(" emerald=" as *u8); pn(n_emer); hw(", rarity ordered)\n" as *u8)
118 } else {
119 hw("T6 FAIL ores coal=" as *u8); pn(n_coal); hw(" iron=" as *u8); pn(n_iron); hw(" gold=" as *u8); pn(n_gold)
120 hw(" emer=" as *u8); pn(n_emer); hw("\n" as *u8)
121 fails = fails + 1
122 }
123
124 if fails == 0 { hw("VERDICT GREEN: blocks-as-DATA 5/5 -- a mod is runtime data (PNG knowledge/nx_mineworld_mod.png)\n" as *u8) }
125 else { hw("VERDICT RED fails=" as *u8); pn(fails); hw("\n" as *u8) }
126 return fails
127}