code wiki / _hdl_build / nx_wasm_mineworld_gate.nx
nx_wasm_mineworld_gate.nx source
↩ module page · 220 lines · 10453 B
1// nx_wasm_mineworld_gate.nx -- NATIVE gate for the INFINITE procgen voxel world (the Minecraft-procgen rung).
2// T1 DETERMINISM: same seed+view renders byte-identical (checksum) -- twice, fresh.
3// T2 INFINITE+CONTINUOUS: terrain is defined at far/negative coords; |dh/dx| <= 3 across 120 blocks incl. biome
4// borders (the continuous-amplitude blend = no border cliff); far render differs from spawn render.
5// T3 PROCGEN VARIETY + LIAR-KILL: >=5 distinct heights per region, two distant regions differ, >=2 biomes on a
6// strip; NEG-CONTROL: the same variety detector run on a constant "liar" terrain MUST FAIL (detector is real).
7// T4 EDIT PERSISTENCE ACROSS ROAMING (the Minecraft-critical property the fixed 48x48 grid could not do):
8// dig+place via the raycast+edit-table path (exactly what break_at/place_at wrap at base=0), roam the render
9// window 200 blocks away and back -> edits still there, still render (frame checksum changes).
10// T5 CAVES+BEDROCK: natural interior air pockets exist (before any edits); y=0 always solid everywhere.
11// Windows never-brick N/A (pure user-space render); determinism doubles as the re-run-safe proof.
12// license_tier: ORIGINAL
13import "nx_syscalls.nx"
14import "nx_f32_hw.nx"
15import "nx_png.nx"
16import "nx_wasm_mineworld.nx"
17
18func hw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
19func pn(v: i64) -> i64 {
20 let b: *u8 = sys_mmap(32) as *u8
21 var x: i64 = v
22 var neg: i64 = 0
23 if x < 0 { neg = 1; x = 0 - x }
24 var i: i64 = 31
25 if x == 0 { b[i] = 48 as u8; i = i - 1 }
26 while x > 0 { b[i] = (48 + x % 10) as u8; x = x / 10; i = i - 1 }
27 if neg == 1 { b[i] = 45 as u8; i = i - 1 }
28 sys_write(1, (b as i64 + i + 1) as *u8, 31 - i)
29 return 0
30}
31func fbsum(base: i64) -> i64 {
32 let fb: *i64 = (base + fb_off()) as *i64
33 var s: i64 = 0
34 var i: i64 = 0
35 while i < ww() * hh() { s = s * 31 + fb[i]; i = i + 1 }
36 return s
37}
38func rend(base: i64, cgx: i64, cgz: i64, ycos: i64, ysin: i64, pcos: i64, psin: i64) -> i64 {
39 let eye: i64 = terrain_h0(cgx, cgz) + 8
40 let camx256: i64 = cgx * 256 + 128
41 let camy256: i64 = eye * 256
42 let camz256: i64 = cgz * 256 + 128
43 let camx: i64 = f32_div(f32_of(camx256), f32_of(256))
44 let camy: i64 = f32_div(f32_of(camy256), f32_of(256))
45 let camz: i64 = f32_div(f32_of(camz256), f32_of(256))
46 build_R(base, ycos, ysin, pcos, psin)
47 render_at(base, camx, camy, camz, cgx, cgz)
48 return 0
49}
50
51func main() -> i64 {
52 let base: i64 = sys_mmap(mem_bytes()) as i64
53 var fails: i64 = 0
54
55 // ---- T1 determinism ----
56 rend(base, 8, 8, 1000, 0, 927, 0 - 375)
57 let c1: i64 = fbsum(base)
58 // frame must actually contain terrain (the liar-kill that caught the inverted-pitch bug). Ground truth =
59 // the renderer's own DRAWN-PIXEL counter (sky is a gradient now, so a sky-constant compare is meaningless).
60 let dpx: i64 = drawn_px_at(base)
61 if dpx * 3 < ww() * hh() { hw("T1 FAIL frame is mostly sky: drawn-px=" as *u8); pn(dpx); hw("\n" as *u8); fails = fails + 1 }
62 else { hw("T1a PASS terrain fills the frame: drawn-px=" as *u8); pn(dpx); hw("\n" as *u8) }
63 write_png((base + fb_off()) as *i64, ww(), hh(), "knowledge/nx_mineworld_1.png" as *u8)
64 rend(base, 8, 8, 1000, 0, 927, 0 - 375)
65 let c2: i64 = fbsum(base)
66 if c1 == c2 { hw("T1 PASS determinism: re-render byte-identical\n" as *u8) }
67 else { hw("T1 FAIL determinism\n" as *u8); fails = fails + 1 }
68
69 // ---- T2 infinite + continuous ----
70 var maxd: i64 = 0
71 var prev: i64 = terrain_h0(0 - 61, 13)
72 var gx: i64 = 0 - 60
73 while gx <= 60 {
74 let hh2: i64 = terrain_h0(gx, 13)
75 var d: i64 = hh2 - prev
76 if d < 0 { d = 0 - d }
77 if d > maxd { maxd = d }
78 prev = hh2
79 gx = gx + 1
80 }
81 let hfar1: i64 = terrain_h0(10007, 0 - 9973)
82 let hfar2: i64 = terrain_h0(10007, 0 - 9973)
83 if maxd <= 3 { if hfar1 == hfar2 { if hfar1 >= 1 { if hfar1 <= 20 {
84 hw("T2 PASS infinite+continuous: max step d=" as *u8); pn(maxd); hw(" far h=" as *u8); pn(hfar1); hw("\n" as *u8)
85 } } } }
86 if maxd > 3 { hw("T2 FAIL discontinuity d=" as *u8); pn(maxd); hw("\n" as *u8); fails = fails + 1 }
87
88 // ---- T3 variety + biomes + liar-kill neg-control ----
89 let seen: *i64 = sys_mmap(32 * 8) as *i64
90 var dv: i64 = 0
91 var rz: i64 = 0
92 while rz < 20 {
93 var rx: i64 = 0
94 while rx < 20 {
95 let hv: i64 = terrain_h0(rx, rz)
96 if seen[hv] == 0 { seen[hv] = 1; dv = dv + 1 }
97 rx = rx + 1
98 }
99 rz = rz + 1
100 }
101 var suma: i64 = 0
102 var sumb: i64 = 0
103 var k: i64 = 0
104 while k < 400 {
105 suma = suma * 31 + terrain_h0(k % 20, k / 20)
106 sumb = sumb * 31 + terrain_h0(5000 + k % 20, 0 - 3000 + k / 20)
107 k = k + 1
108 }
109 let bseen: *i64 = sys_mmap(8 * 8) as *i64
110 var bcount: i64 = 0
111 var bx: i64 = 0 - 400
112 while bx <= 400 {
113 let bio: i64 = biome_of(bx, 50)
114 if bseen[bio] == 0 { bseen[bio] = 1; bcount = bcount + 1 }
115 bx = bx + 16
116 }
117 // liar-kill: run the SAME distinct-count detector on a constant terrain -> must FAIL variety
118 var nv: i64 = 0
119 let nseen: *i64 = sys_mmap(32 * 8) as *i64
120 var nk: i64 = 0
121 while nk < 400 { let lh: i64 = 7; if nseen[lh] == 0 { nseen[lh] = 1; nv = nv + 1 } nk = nk + 1 }
122 if dv >= 5 { if suma != sumb { if bcount >= 2 { if nv < 5 {
123 hw("T3 PASS variety: distinct-h=" as *u8); pn(dv); hw(" biomes=" as *u8); pn(bcount)
124 hw(" regions-differ=1 negctl-fails=1\n" as *u8)
125 } } } }
126 if dv < 5 { hw("T3 FAIL variety dv=" as *u8); pn(dv); hw("\n" as *u8); fails = fails + 1 }
127 if suma == sumb { hw("T3 FAIL regions identical\n" as *u8); fails = fails + 1 }
128 if bcount < 2 { hw("T3 FAIL biomes=" as *u8); pn(bcount); hw("\n" as *u8); fails = fails + 1 }
129 if nv >= 5 { hw("T3 FAIL neg-control did not fail\n" as *u8); fails = fails + 1 }
130
131 // ---- T5 caves + bedrock (BEFORE edits so air pockets are natural) ----
132 var caves: i64 = 0
133 var cz: i64 = 0
134 while cz < 80 {
135 var cx: i64 = 0
136 while cx < 80 {
137 let ch: i64 = terrain_h0(cx, cz)
138 if ch >= 8 {
139 var cy: i64 = 2
140 while cy <= ch - 2 {
141 if solid_h(base, cx, cy, cz, ch) == 0 { caves = caves + 1 }
142 cy = cy + 1
143 }
144 }
145 cx = cx + 1
146 }
147 cz = cz + 1
148 }
149 var bed: i64 = 1
150 if solid_h(base, 0, 0, 0, 0 - 1) == 0 { bed = 0 }
151 if solid_h(base, 0 - 33, 0, 17, 0 - 1) == 0 { bed = 0 }
152 if solid_h(base, 4021, 0, 0 - 777, 0 - 1) == 0 { bed = 0 }
153 if caves > 0 { if bed == 1 {
154 hw("T5 PASS caves+bedrock: interior air cells=" as *u8); pn(caves); hw(" bedrock-solid=1\n" as *u8)
155 } }
156 if caves == 0 { hw("T5 FAIL no caves\n" as *u8); fails = fails + 1 }
157 if bed == 0 { hw("T5 FAIL bedrock broken\n" as *u8); fails = fails + 1 }
158
159 // ---- T2b far render differs + window-slide leaves no state ----
160 rend(base, 0 - 500, 300, 866, 500, 985, 0 - 174)
161 let cf: i64 = fbsum(base)
162 write_png((base + fb_off()) as *i64, ww(), hh(), "knowledge/nx_mineworld_2.png" as *u8)
163 rend(base, 8, 8, 1000, 0, 927, 0 - 375)
164 let c3: i64 = fbsum(base)
165 if cf != c1 { if c3 == c1 {
166 hw("T2b PASS far(-500,300) frame differs; return-to-spawn frame identical (no window-state leak)\n" as *u8)
167 } }
168 if cf == c1 { hw("T2b FAIL far frame identical to spawn\n" as *u8); fails = fails + 1 }
169 if c3 != c1 { hw("T2b FAIL window slide leaked state\n" as *u8); fails = fails + 1 }
170
171 // ---- T4 edit persistence across roaming (raycast+edit-table = the break_at/place_at path at base) ----
172 // pick two TREE-FREE dry columns for the edit test (trees are SOLID blocks now -- surface_y == terrain_h0
173 // guarantees nothing stands or hangs over the column, so the down-ray hits the terrain top exactly)
174 var gxa: i64 = 0 - 999
175 var gza: i64 = 0
176 var gxb: i64 = 0 - 999
177 var gzb: i64 = 0
178 var sz: i64 = 14
179 while sz <= 26 {
180 var sx: i64 = 4
181 while sx <= 12 {
182 if terrain_h0(sx, sz) > 4 { if surface_y(base, sx, sz) == terrain_h0(sx, sz) {
183 if gxa == 0 - 999 { gxa = sx; gza = sz }
184 else { if gxb == 0 - 999 { gxb = sx; gzb = sz } }
185 } }
186 sx = sx + 1
187 }
188 sz = sz + 1
189 }
190 var t4: i64 = 1
191 if gxb == 0 - 999 { hw("T4 sub: no tree-free columns found\n" as *u8); t4 = 0 }
192 rend(base, gxa, gza, 1000, 0, 0, 0 - 1000)
193 let cpre: i64 = fbsum(base)
194 let o: *i64 = sys_mmap(8 * 8) as *i64
195 let hA: i64 = terrain_h0(gxa, gza)
196 raycast(base, gxa * 256 + 128, (hA + 4) * 256, gza * 256 + 128, 0, 0 - 1000, 0, o)
197 if o[0] != 1 { hw("T4 sub: rayA no-hit\n" as *u8); t4 = 0 }
198 if o[2] != hA - 1 { hw("T4 sub: rayA hit gy=" as *u8); pn(o[2]); hw(" want " as *u8); pn(hA - 1); hw("\n" as *u8); t4 = 0 }
199 mw_eset(base, o[1], o[2], o[3], 2)
200 if solid(base, gxa, hA - 1, gza) != 0 { hw("T4 sub: dig not air\n" as *u8); t4 = 0 }
201 let hB: i64 = terrain_h0(gxb, gzb)
202 raycast(base, gxb * 256 + 128, (hB + 4) * 256, gzb * 256 + 128, 0, 0 - 1000, 0, o)
203 if o[0] != 1 { hw("T4 sub: rayB no-hit\n" as *u8); t4 = 0 }
204 mw_eset(base, o[4], o[5], o[6], 1)
205 if solid(base, gxb, hB, gzb) != 1 { hw("T4 sub: place not solid\n" as *u8); t4 = 0 }
206 // roam the window 200+ blocks away and back
207 rend(base, 208, 208, 1000, 0, 927, 0 - 375)
208 rend(base, gxa, gza, 1000, 0, 0, 0 - 1000)
209 let cpost: i64 = fbsum(base)
210 if solid(base, gxa, hA - 1, gza) != 0 { hw("T4 sub: dig lost after roam\n" as *u8); t4 = 0 }
211 if solid(base, gxb, hB, gzb) != 1 { hw("T4 sub: place lost after roam\n" as *u8); t4 = 0 }
212 if edit_count_at(base) != 2 { hw("T4 sub: edit_count=" as *u8); pn(edit_count_at(base)); hw("\n" as *u8); t4 = 0 }
213 if cpost == cpre { hw("T4 sub: edits not visible in frame\n" as *u8); t4 = 0 }
214 if t4 == 1 { hw("T4 PASS edits persist across 200-block roam + render differs (dig+place visible), count=2\n" as *u8) }
215 else { hw("T4 FAIL edit persistence\n" as *u8); fails = fails + 1 }
216
217 if fails == 0 { hw("VERDICT GREEN: mineworld infinite-procgen 5/5 (PNGs knowledge/nx_mineworld_1.png, _2.png)\n" as *u8) }
218 else { hw("VERDICT RED fails=" as *u8); pn(fails); hw("\n" as *u8) }
219 return fails
220}