code wiki / _hdl_build / nx_wasm_mineworld_tick_gate.nx
nx_wasm_mineworld_tick_gate.nx source
↩ module page · 224 lines · 9969 B
1// nx_wasm_mineworld_tick_gate.nx -- gate for the SOVEREIGN TICK (operator law: NO JS game logic -- the wasm
2// owns camera/physics/trig/aim). T0 integer-trig sanity. T1 walk+mouse-look move the camera (turned heading
3// moves BOTH axes). T2 gravity settles to the surface; jump rises then lands back exactly. T3 a 3-high wall
4// BLOCKS walking (step-up rule <=1.3). T4 aim-ray dig/put edit the world from camera state alone. T5 the whole
5// sim is DETERMINISTIC: an identical input script on two fresh worlds renders byte-identical frames. T6 the
6// per-voxel texture hash varies. PNG knowledge/nx_mineworld_tick.png = post-walk frame (fog + textured blocks).
7// license_tier: ORIGINAL expect_exit: 0
8import "nx_syscalls.nx"
9import "nx_f32_hw.nx"
10import "nx_png.nx"
11import "nx_wasm_mineworld.nx"
12
13func hw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
14func pn(v: i64) -> i64 {
15 let b: *u8 = sys_mmap(32) as *u8
16 var x: i64 = v
17 var neg: i64 = 0
18 if x < 0 { neg = 1; x = 0 - x }
19 var i: i64 = 31
20 if x == 0 { b[i] = 48 as u8; i = i - 1 }
21 while x > 0 { b[i] = (48 + x % 10) as u8; x = x / 10; i = i - 1 }
22 if neg == 1 { b[i] = 45 as u8; i = i - 1 }
23 sys_write(1, (b as i64 + i + 1) as *u8, 31 - i)
24 return 0
25}
26func fbsum(base: i64) -> i64 {
27 let fb: *i64 = (base + fb_off()) as *i64
28 var s: i64 = 0
29 var i: i64 = 0
30 while i < ww() * hh() { s = s * 31 + fb[i]; i = i + 1 }
31 return s
32}
33func iabs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
34// is the camera's HEAD cell still below roof_gy? (the ceiling-clamp assert)
35func c_a_head_below(base: i64, roof_gy: i64) -> i64 {
36 let c: *i64 = cam_ptr(base)
37 let hgy: i64 = mw_fd256(c[1] + 60)
38 if hgy < roof_gy { return 1 }
39 return 0
40}
41// a fixed input script: walk, turn, walk, jump, walk -- exercised identically on two fresh worlds for T5
42func script(base: i64) -> i64 {
43 var i: i64 = 0
44 while i < 20 { tick_at(base, 1, 0, 0); i = i + 1 }
45 tick_at(base, 0, 180, 0 - 40)
46 i = 0
47 while i < 15 { tick_at(base, 1 + 8, 0, 0); i = i + 1 }
48 tick_at(base, 16, 0, 0)
49 i = 0
50 while i < 25 { tick_at(base, 1, 5, 0); i = i + 1 }
51 return 0
52}
53
54func main() -> i64 {
55 var fails: i64 = 0
56
57 // ---- T0 integer trig ----
58 var t0: i64 = 1
59 if mw_sin4096(0) != 0 { t0 = 0 }
60 if iabs(mw_sin4096(PI2_4096) - 4096) > 25 { t0 = 0 }
61 if iabs(mw_sin4096(PI4096)) > 25 { t0 = 0 }
62 if iabs(mw_sin4096(0 - PI2_4096) + 4096) > 25 { t0 = 0 }
63 if iabs(mw_cos4096(0) - 4096) > 25 { t0 = 0 }
64 if t0 == 1 { hw("T0 PASS integer trig (sin 0/90/180/-90, cos 0 within 0.6%)\n" as *u8) }
65 else { hw("T0 FAIL trig\n" as *u8); fails = fails + 1 }
66
67 // ---- T1 walk + look (base A) ----
68 let bA: i64 = sys_mmap(mem_bytes()) as i64
69 start_at(bA)
70 let cA: *i64 = cam_ptr(bA)
71 let z0: i64 = cA[2]
72 var i: i64 = 0
73 while i < 30 { tick_at(bA, 17, 0, 0); i = i + 1 } // W+Space: voxel physics has NO auto-step -> hop the bumps
74 let zgain: i64 = cA[2] - z0
75 tick_at(bA, 0, 245, 0) // yaw += ~0.78 rad
76 let x1: i64 = cA[0]
77 let z1: i64 = cA[2]
78 i = 0
79 while i < 30 { tick_at(bA, 17, 0, 0); i = i + 1 }
80 var t1: i64 = 1
81 if zgain < 400 { hw("T1 sub: zgain=" as *u8); pn(zgain); hw("\n" as *u8); t1 = 0 } // trees are solid: the lane may legitimately end at a trunk
82 if cA[0] - x1 < 500 { t1 = 0 }
83 if cA[2] - z1 < 500 { t1 = 0 }
84 if t1 == 1 { hw("T1 PASS walk straight then turned heading moves both axes (in-wasm trig)\n" as *u8) }
85 else { hw("T1 FAIL walk/look\n" as *u8); fails = fails + 1 }
86
87 // ---- T2 gravity + jump (re-anchor on base A wherever it walked to) ----
88 // GROUND TRUTH is voxel-local, not the column top: the old surface_y assert put you ON TREETOPS (that
89 // WAS the physics bug). Correct rest = feet exactly on a cell boundary, phys-solid directly below, air
90 // at the feet cell (standing under a canopy is legal now).
91 i = 0
92 while i < 30 { tick_at(bA, 0, 0, 0); i = i + 1 }
93 let gy0: i64 = cA[1]
94 let tgx: i64 = mw_fd256(cA[0])
95 let tgz: i64 = mw_fd256(cA[2])
96 let tfy: i64 = mw_fd256(gy0 - 410)
97 var t2: i64 = 1
98 if (gy0 - 410) % 256 != 0 { t2 = 0 }
99 if phys_solid(bA, tgx, tfy - 1, tgz) == 0 { t2 = 0 }
100 if phys_solid(bA, tgx, tfy, tgz) == 1 { t2 = 0 }
101 if cA[7] != 1 { t2 = 0 }
102 tick_at(bA, 16, 0, 0)
103 tick_at(bA, 0, 0, 0)
104 if cA[1] <= gy0 { t2 = 0 }
105 i = 0
106 while i < 80 { tick_at(bA, 0, 0, 0); i = i + 1 }
107 if cA[1] != gy0 { t2 = 0 }
108 if cA[7] != 1 { t2 = 0 }
109 if t2 == 1 { hw("T2 PASS gravity settles on the surface; jump rises then lands back exactly\n" as *u8) }
110 else { hw("T2 FAIL gravity/jump\n" as *u8); fails = fails + 1 }
111
112 // ---- T2b VOXEL PHYSICS: ceiling stops the head; water is swimmable not walkable ----
113 var t2b: i64 = 1
114 // ceiling: build a roof 3 above the ground under the player, jump -> head must stop below it
115 let rgx: i64 = mw_fd256(cA[0])
116 let rgz: i64 = mw_fd256(cA[2])
117 let rg: i64 = floor_y(bA, rgx, rgz, YMAX - 1)
118 mw_eset(bA, rgx, rg + 2, rgz, 1)
119 tick_at(bA, 16, 0, 0)
120 var j2: i64 = 0
121 while j2 < 10 { tick_at(bA, 0, 0, 0); j2 = j2 + 1 }
122 // eye must stay below the roof cell bottom the whole arc's end state (head clamp held)
123 if c_a_head_below(bA, rg + 2) == 0 { t2b = 0 }
124 mw_eset(bA, rgx, rg + 2, rgz, 2) // remove the roof (dug)
125 // water: teleport the column state -- find an ocean column near origin scanning gz
126 var wgx: i64 = 0 - 999
127 var wgz: i64 = 0
128 var sz2: i64 = 0 - 60
129 while sz2 < 60 {
130 var sx2: i64 = 0 - 60
131 while sx2 < 60 {
132 if wgx == 0 - 999 { if terrain_h0(sx2, sz2) <= 4 { wgx = sx2; wgz = sz2 } }
133 sx2 = sx2 + 1
134 }
135 sz2 = sz2 + 1
136 }
137 if wgx == 0 - 999 { hw("T2b sub: no ocean column found nearby\n" as *u8); t2b = 0 }
138 else {
139 let cB2: *i64 = cam_ptr(bA)
140 cB2[0] = wgx * 256 + 128
141 cB2[2] = wgz * 256 + 128
142 cB2[1] = 10 * 256 // drop from above sea level
143 cB2[5] = 0
144 var j3: i64 = 0
145 while j3 < 60 { tick_at(bA, 0, 0, 0); j3 = j3 + 1 }
146 // feet must be BELOW the water surface (submerged -- the old physics stood ON the sea at WWATER+1)
147 let feetw: i64 = cB2[1] - 410
148 if feetw >= (WWATER + 1) * 256 { t2b = 0 }
149 // Space swims UP
150 let ybefore: i64 = cB2[1]
151 var j4: i64 = 0
152 while j4 < 8 { tick_at(bA, 16, 0, 0); j4 = j4 + 1 }
153 if cB2[1] <= ybefore { t2b = 0 }
154 }
155 if t2b == 1 { hw("T2b PASS voxel physics: ceiling stops the head; water submerges + Space swims up\n" as *u8) }
156 else { hw("T2b FAIL ceiling/water physics\n" as *u8); fails = fails + 1 }
157
158 // ---- T3 wall blocks walking (fresh base B) ----
159 let bB: i64 = sys_mmap(mem_bytes()) as i64
160 start_at(bB)
161 let cB: *i64 = cam_ptr(bB)
162 let hh31: i64 = surface_y(bB, 30, 31)
163 mw_eset(bB, 30, hh31, 31, 1)
164 mw_eset(bB, 30, hh31 + 1, 31, 1)
165 mw_eset(bB, 30, hh31 + 2, 31, 1)
166 i = 0
167 while i < 20 { tick_at(bB, 1, 0, 0); i = i + 1 }
168 if mw_fd256(cB[2]) == 30 { hw("T3 PASS 3-high wall blocks walking (step-up <=1.3 enforced in-wasm)\n" as *u8) }
169 else { hw("T3 FAIL walked through the wall\n" as *u8); fails = fails + 1 }
170
171 // ---- T4 aim-ray dig/put from camera state (fresh base C) ----
172 let bC: i64 = sys_mmap(mem_bytes()) as i64
173 start_at(bC)
174 let s30: i64 = surface_y(bC, 30, 30)
175 let s31: i64 = surface_y(bC, 30, 31)
176 tick_at(bC, 0, 0, 500) // POSITIVE mdy (mouse-back) = pitch DOWN (standard); clamps ~straight down
177 dig_at(bC)
178 var t4: i64 = 1
179 if edit_count_at(bC) != 1 { t4 = 0 }
180 var dropped: i64 = 0
181 if surface_y(bC, 30, 30) < s30 { dropped = 1 }
182 if surface_y(bC, 30, 31) < s31 { dropped = 1 }
183 if dropped == 0 { t4 = 0 }
184 put_at(bC)
185 // aiming the same way, put fills the just-dug cell -> the SAME edit key flips 2->1 (count stays 1) and the
186 // world is EXACTLY restored -- the stronger property (naive count==2 was the wrong expectation, fixed).
187 if edit_count_at(bC) < 1 { t4 = 0 }
188 var restored: i64 = 0
189 if surface_y(bC, 30, 30) == s30 { if surface_y(bC, 30, 31) == s31 { restored = 1 } }
190 if restored == 0 { t4 = 0 }
191 if t4 == 1 { hw("T4 PASS aim-ray dig lowers the surface; put restores it EXACTLY (same-cell edit, in-wasm rays)\n" as *u8) }
192 else { hw("T4 FAIL dig/put count=" as *u8); pn(edit_count_at(bC)); hw(" restored=" as *u8); pn(restored); hw("\n" as *u8); fails = fails + 1 }
193
194 // ---- T5 whole-sim determinism (fresh bases D, E) ----
195 let bD: i64 = sys_mmap(mem_bytes()) as i64
196 let bE: i64 = sys_mmap(mem_bytes()) as i64
197 start_at(bD)
198 script(bD)
199 render_cam_at(bD)
200 let d1: i64 = fbsum(bD)
201 start_at(bE)
202 script(bE)
203 render_cam_at(bE)
204 let d2: i64 = fbsum(bE)
205 if d1 == d2 { hw("T5 PASS identical input script on two fresh worlds -> byte-identical frames\n" as *u8) }
206 else { hw("T5 FAIL sim nondeterministic\n" as *u8); fails = fails + 1 }
207 write_png((bD + fb_off()) as *i64, ww(), hh(), "knowledge/nx_mineworld_tick.png" as *u8)
208
209 // ---- T6 per-voxel texture hash varies ----
210 var distinct: i64 = 0
211 let seen: *i64 = sys_mmap(32 * 8) as *i64
212 var k: i64 = 0
213 while k < 10 {
214 let vh: i64 = mw_h2(k * 33 + 5, k * 91 + 2, 999) % 21
215 if seen[vh] == 0 { seen[vh] = 1; distinct = distinct + 1 }
216 k = k + 1
217 }
218 if distinct >= 3 { hw("T6 PASS texture hash varies (distinct=" as *u8); pn(distinct); hw("/10 samples)\n" as *u8) }
219 else { hw("T6 FAIL texture hash flat\n" as *u8); fails = fails + 1 }
220
221 if fails == 0 { hw("VERDICT GREEN: sovereign tick 6/6 -- zero JS game logic (PNG knowledge/nx_mineworld_tick.png)\n" as *u8) }
222 else { hw("VERDICT RED fails=" as *u8); pn(fails); hw("\n" as *u8) }
223 return fails
224}