nx_beach_contact_gate.nx source
↩ module page · 775 lines · 30516 B
1// nx_beach_contact_gate.nx -- BEACH GROUND CONTACT: every body path that can leave feet under the
2// rendered sand has a tooth, and each tooth prints the numbers it judged (2026-09-11 beach lane).
3// Causes held here, from the 2026-09-11 fall-through diagnosis: rank 1 collision floor versus the
4// rendered field; rank 2 block-sized camera pops while walking; rank 3 an NPC buried by a window
5// shift and never walked out; rank 4 player support with feet under the field, and the stale-spawn
6// respawn that reaches it; rank 5 an NPC push across a rise; rank 6 arrivals placed on overhead
7// structures. Also a large-dt fall (15 fixed ticks per 250 ms frame from the window top) and NPCs held
8// at both window corners. A checker the current engine cannot fail is paired with a neg-control that
9// runs the SAME checker over the served rule on the same data, so a checker that cannot fire is
10// visible. Native world and fixtures only; browser visual acceptance stays with the operator.
11// license_tier: ORIGINAL
12import "nx_wasm_craft.nx"
13import "nx_gate_verdict.nx"
14import "nx_dec_emit.nx"
15
16const BCG_BLOCK_Q8: i64 = 256 // one block in Q8 world units (the engine's S_CX: 256 = one block)
17const BCG_BODY_CELLS: i64 = 2 // the two body cells mob_fits proves above a floor
18const BCG_CLAMP_BLOCKS: i64 = 2 // wc_shift's window clamp margin in blocks
19const BCG_STRUCTURE: i64 = 6 // a non-terrain solid; the legacy teeth plant the same block
20const BCG_FLAT_HQ: i64 = 1152 // the legacy teeth's flat field corner height
21const BCG_FIX_COL: i64 = 10 // the legacy teeth's fixture column
22const BCG_PATCH_REACH: i64 = 4 // half-width in blocks of a rewritten fixture field
23const BCG_WALK_TICKS: i64 = 240 // four seconds of the page's 60 Hz fixed tick per heading
24const BCG_HEADINGS: i64 = 4 // +x, -x, +z, -z
25const BCG_EDGE_BLOCKS: i64 = 4 // walks stop this far from the window edge; the shift has its own tooth
26const BCG_BURY_BLOCKS: i64 = 2 // the diagnosed burial depth the NPC rise limit never climbs
27const BCG_SHIFT_MAX: i64 = 8 // window slides allowed before the spawn must reach the clamp
28const BCG_SETTLE_TICKS: i64 = 60 // one second of fixed ticks after a placement, push or respawn
29const BCG_EDGE_TICKS: i64 = 240 // ticks the corner NPCs are observed
30const BCG_PAGE_DT_MS: i64 = 250 // the page's NXFRAME_OOR_MS frame clamp
31const BCG_TICK_US: i64 = 16667 // the page accumulator's 16.6667 ms fixed tick
32const BCG_MS_US: i64 = 1000
33const BCG_FALL_TICKS: i64 = 900 // fifteen seconds; a fall from the window top lands long before
34const BCG_PROBES: i64 = 6 // depths under the field probed by the support tooth
35const BCG_PUSH_BOX_Q8: i64 = 100 // apply2_impl's body-presence push distance
36const BCG_PUSH_GAP_Q8: i64 = SPEED+SPEED/2 // an NPC one and a half walk steps behind the player
37const BCG_PUSH_COL: i64 = WX/2 // mid-window, so no window slide fires during the push ticks
38const BCG_CANOPY_REACH: i64 = 9 // canopy half-width in blocks: summon ring 4..7 blocks, passport 3
39const BCG_PASS_ARRIVALS: i64 = 3 // wc_pass_apply spawns at most three companions
40const BCG_STALE_SINK_Q8: i64 = EYE/2 // a stale spawn height: feet under the sand, eye above it
41
42func bcg_number(value: i64, scratch: *u8) -> i64 {
43 let n: i64=nx_dec_emit_u63(scratch,0,value)
44 sys_write(1,scratch,n)
45 return 0
46}
47func bcg_abs(v: i64) -> i64 {
48 if v < 0 { return 0-v }
49 return v
50}
51// Q8 depth of feet under a floor; 0 when at or above it.
52func bcg_below(feet: i64, floor: i64) -> i64 {
53 if feet < floor { return floor-feet }
54 return 0
55}
56// A solid the terrain field does not replace, written from primitives rather than the engine's contact helper.
57func bcg_structure(base: i64, x: i64, y: i64, z: i64) -> i64 {
58 if vsolid(base,x,y,z) != 1 { return 0 }
59 if wsp(base)[P_SURF] == 1 { if wterrain(vget(base,x,y,z)) == 1 { return 0 } }
60 return 1
61}
62// Independent placement oracle: the lowest feet height at or above the terrain field whose body cells
63// hold no structure. Voxel identities fall back to the column scan.
64func bcg_place_oracle(base: i64, xq: i64, zq: i64) -> i64 {
65 if wsp(base)[P_SURF] != 1 { return wc_contact_floor_q(base,xq,zq,WY-1) }
66 var feet: i64 = wc_surface_source(base,xq,zq)
67 if feet < 0 { return -1 }
68 var cell: i64 = feet/BCG_BLOCK_Q8
69 while cell < WY && cell*BCG_BLOCK_Q8 < feet+BCG_BODY_CELLS*BCG_BLOCK_Q8 {
70 if bcg_structure(base,xq/BCG_BLOCK_Q8,cell,zq/BCG_BLOCK_Q8) == 1 { feet=(cell+1)*BCG_BLOCK_Q8 }
71 cell=cell+1
72 }
73 return feet
74}
75func bcg_arena() -> i64 { return sys_mmap(CRAFT_EXT_TOTAL) as i64 }
76func bcg_world() -> i64 {
77 let base: i64 = bcg_arena()
78 init_impl_v(base,BEACH_RELEASE_WORLD,CRAFT_DEFAULT_SEED)
79 return base
80}
81func bcg_free(base: i64) -> i64 {
82 sys_munmap(base as *u8,CRAFT_EXT_TOTAL)
83 return 0
84}
85
86func bcg_checks() -> i64 {
87 let base: i64 = sys_mmap(CRAFT_TOTAL) as i64
88 let spec: *i64 = wsp(base)
89 spec[P_SURF] = 1
90 spec[P_WATER] = 0
91 vset(base, 10, 4, 10, 5)
92 hq_set(base,10,10,1152)
93 hq_set(base,11,10,1408)
94 hq_set(base,10,11,1152)
95 hq_set(base,11,11,1408)
96 let px: i64 = 10*256+128
97 let pz: i64 = 10*256+128
98 let surface: i64 = wc_surface_source(base,px,pz)
99 let floor: i64 = wstand_here(base,px,pz)-EYE
100 if surface != 1536 { return 2 }
101 if floor != 1536 { return 3 }
102 if surface-floor != 0 { return 4 }
103 vset(base,10,8,10,6)
104 if wc_contact_floor_q(base,px,pz,WY-1) != 2304 { return 5 }
105 if wc_contact_floor_q(base,-1,pz,WY-1) != -1 { return 6 }
106 spec[P_SURF] = 0
107 if wc_contact_floor_q(base,px,pz,WY-1) != 2304 { return 7 }
108 vset(base,10,8,10,0)
109 if wc_contact_floor_q(base,px,pz,WY-1) != 1280 { return 8 }
110 spec[P_SURF] = 1
111 hq_set(base,10,11,1280)
112 hq_set(base,11,11,1536)
113 var sx: i64 = 0
114 while sx < 256 {
115 var sz: i64 = 0
116 while sz < 256 {
117 let x: i64 = 10*256+sx
118 let z: i64 = 10*256+sz
119 let expected: i64 = 1408+sx+sz/2
120 if wc_surface_source(base,x,z) != expected { return 10 }
121 if wstand_here(base,x,z)-EYE != expected { return 11 }
122 if wstand(base,x,z,expected+EYE) != expected+EYE { return 12 }
123 sz = sz+1
124 }
125 sx = sx+1
126 }
127 if wstand(base,px,pz,EYE) != -1 { return 13 }
128 if wstand(base,-1,pz,1536+EYE) != -1 { return 14 }
129 if wc_contact_floor_q(base,(WX-1)*256,pz,WY-1) != -1 { return 15 }
130 spec[P_WATER] = 8
131 vset(base,10,8,10,4)
132 if wstand_here(base,px,pz) != 9*256+EYE-96 { return 16 }
133 wc_spec(base,2)
134 var seed: i64 = 1
135 while seed <= 16 {
136 gencol(base,10,10,10,10,seed)
137 gencol(base,11,10,11,10,seed)
138 gencol(base,10,11,10,11,seed)
139 gencol(base,11,11,11,11,seed)
140 var offset: i64 = 0
141 while offset < 256 {
142 let gx: i64 = 10*256+offset
143 let gz: i64 = 10*256+255-offset
144 let field: i64 = wc_surface_source(base,gx,gz)
145 if field < 0 { return 20 }
146 if wc_contact_floor_q(base,gx,gz,WY-1) != field { return 21 }
147 offset = offset+1
148 }
149 seed=seed+1
150 }
151 let generated: i64 = sys_mmap(CRAFT_TOTAL) as i64
152 init_impl_v(generated,2,17)
153 let gs: *i64 = wst(generated)
154 if gs[S_CY] != wstand_here(generated,gs[S_CX],gs[S_CZ]) { return 30 }
155 let gm: *i64 = mobp(generated)
156 if en_count(gm) <= 0 { return 31 }
157 var ci: i64 = 0
158 while ci < en_count(gm) {
159 let handle: i64 = en_nth(gm,ci)
160 let expectedfloor: i64 = wc_contact_floor_q(generated,en_get(gm,handle,MC_X),en_get(gm,handle,MC_Z),WY-1)
161 if expectedfloor < 0 { return 32 }
162 if en_get(gm,handle,MC_Y) != expectedfloor { return 33 }
163 ci=ci+1
164 }
165 let initial: *i64 = sys_mmap(MOB_CAP*16) as *i64
166 let observed: *i64 = sys_mmap(MOB_CAP*24) as *i64
167 let actorCount: i64 = en_count(gm)
168 let numberText: *u8 = sys_mmap(NX_DEC_EMIT_MAX_BYTES)
169 ci=0
170 while ci < en_count(gm) {
171 let handle: i64 = en_nth(gm,ci)
172 observed[ci*3]=handle
173 initial[ci*2]=en_get(gm,handle,MC_X)
174 initial[ci*2+1]=en_get(gm,handle,MC_Z)
175 ci=ci+1
176 }
177 var frame: i64 = 0
178 while frame < 120 {
179 gs[S_T]=gs[S_T]+1
180 mob_tick(generated)
181 if en_count(gm) != actorCount { return 37 }
182 ci=0
183 while ci < en_count(gm) {
184 let handle: i64 = en_nth(gm,ci)
185 if handle != observed[ci*3] { return 38 }
186 let floorNow: i64 = wc_contact_floor_q(generated,en_get(gm,handle,MC_X),en_get(gm,handle,MC_Z),WY-1)
187 if floorNow < 0 { return 34 }
188 if en_get(gm,handle,MC_Y) < floorNow { return 35 }
189 let clearance: i64 = en_get(gm,handle,MC_Y)-floorNow
190 if clearance > observed[ci*3+2] { observed[ci*3+2]=clearance }
191 if en_get(gm,handle,MC_X) != initial[ci*2] || en_get(gm,handle,MC_Z) != initial[ci*2+1] { observed[ci*3+1]=observed[ci*3+1]+1 }
192 ci=ci+1
193 }
194 frame=frame+1
195 }
196 var moved: i64 = 0
197 var stationary: i64 = 0
198 ci=0
199 while ci < en_count(gm) {
200 let handle: i64 = en_nth(gm,ci)
201 if observed[ci*3+1] > 0 { moved=moved+1 } else { stationary=stationary+1 }
202 sys_write(1,"ACTOR handle=" as *u8,13); bcg_number(handle,numberText)
203 sys_write(1," displaced_frames=" as *u8,18); bcg_number(observed[ci*3+1],numberText)
204 sys_write(1," max_clearance_q8=" as *u8,18); bcg_number(observed[ci*3+2],numberText)
205 sys_write(1,"\n" as *u8,1)
206 ci=ci+1
207 }
208 sys_write(1,"CAST moved=" as *u8,11); bcg_number(moved,numberText)
209 sys_write(1," stationary=" as *u8,12); bcg_number(stationary,numberText)
210 sys_write(1,"\n" as *u8,1)
211 if moved == 0 { return 36 }
212 let trapped: i64 = sys_mmap(CRAFT_TOTAL) as i64
213 init_impl_v(trapped,2,17)
214 let tm: *i64 = mobp(trapped)
215 let ts: *i64 = wst(trapped)
216 let tn: *i64 = (trapped+O_NEED) as *i64
217 let savedGait: *i64 = sys_mmap(MOB_CAP*8) as *i64
218 ci=0
219 while ci < en_count(tm) {
220 let h: i64 = en_nth(tm,ci)
221 savedGait[ci]=tn[ci*4+WC_NEED_GAIT]
222 let tx: i64 = en_get(tm,h,MC_X)>>8
223 let tz: i64 = en_get(tm,h,MC_Z)>>8
224 let ty: i64 = (en_get(tm,h,MC_Y)>>8)+1
225 var ax: i64 = tx-1
226 while ax <= tx+1 {
227 var az: i64 = tz-1
228 while az <= tz+1 {
229 var ay: i64 = ty
230 while ay < WY { vset(trapped,ax,ay,az,6); ay=ay+1 }
231 az=az+1
232 }
233 ax=ax+1
234 }
235 ci=ci+1
236 }
237 ts[S_T]=ts[S_T]+1
238 mob_tick(trapped)
239 let applied: *i64 = (trapped+O_MOBAUX) as *i64
240 ci=0
241 while ci < en_count(tm) {
242 if applied[ci*3] != 0 || applied[ci*3+1] != 0 { return 39 }
243 if tn[ci*4+WC_NEED_GAIT] != savedGait[ci] { return 40 }
244 ci=ci+1
245 }
246 return 0
247}
248
249// RANK 1: the collision floor is the rendered field on every structure-free column of the served seed.
250func bcg_census(ctr: *i64) -> i64 {
251 let base: i64 = bcg_world()
252 var checked: i64 = 0
253 var fieldOnly: i64 = 0
254 var structured: i64 = 0
255 var mismatch: i64 = 0
256 var servedBelow: i64 = 0
257 var servedBlock: i64 = 0
258 var servedEye: i64 = 0
259 var servedMax: i64 = 0
260 var x: i64 = 0
261 while x < WX-1 {
262 var z: i64 = 0
263 while z < WZ-1 {
264 let xq: i64 = x*BCG_BLOCK_Q8+BCG_BLOCK_Q8/2
265 let zq: i64 = z*BCG_BLOCK_Q8+BCG_BLOCK_Q8/2
266 let field: i64 = wc_surface_source(base,xq,zq)
267 let contact: i64 = wc_contact_floor_q(base,xq,zq,WY-1)
268 checked=checked+1
269 if contact > field { structured=structured+1 } else {
270 fieldOnly=fieldOnly+1
271 if contact != field { mismatch=mismatch+1 }
272 }
273 let top: i64 = wground(base,x,z)
274 if top >= 0 {
275 let gap: i64 = field-(top+1)*BCG_BLOCK_Q8
276 if gap > 0 { servedBelow=servedBelow+1 }
277 if gap > BCG_BLOCK_Q8 { servedBlock=servedBlock+1 }
278 if gap > EYE { servedEye=servedEye+1 }
279 if gap > servedMax { servedMax=gap }
280 }
281 z=z+1
282 }
283 x=x+1
284 }
285 gv_kv("rank1_columns_checked",checked)
286 gv_kv("rank1_field_only_columns",fieldOnly)
287 gv_kv("rank1_structure_columns",structured)
288 gv_kv("rank1_partition_sum",fieldOnly+structured)
289 gv_kv("rank1_contact_field_mismatch_columns",mismatch)
290 gv_kv("served_rule_feet_under_field_columns",servedBelow)
291 gv_kv("served_rule_gap_over_one_block_columns",servedBlock)
292 gv_kv("served_rule_gap_over_eye_height_columns",servedEye)
293 gv_kv("served_rule_gap_max_q8",servedMax)
294 gv_check("rank1 contact floor equals the rendered field on every structure-free column of world 2 seed 20260728",(checked > 0 && fieldOnly+structured == checked && mismatch == 0) as i64,ctr)
295 gv_check("neg-control-served-voxel-top-rule-puts-feet-under-the-field-on-the-same-columns",(servedBelow > 0) as i64,ctr)
296 bcg_free(base)
297 return 0
298}
299
300// RANK 2: walking the served seed in four headings never pops the camera by a block, never leaves the
301// feet under the field, and a grounded tick always rests exactly on contact support.
302func bcg_walk(ctr: *i64) -> i64 {
303 let base: i64 = bcg_world()
304 let s: *i64 = wst(base)
305 let edgeLo: i64 = BCG_EDGE_BLOCKS*BCG_BLOCK_Q8
306 let edgeHiX: i64 = (WX-BCG_EDGE_BLOCKS)*BCG_BLOCK_Q8
307 let edgeHiZ: i64 = (WZ-BCG_EDGE_BLOCKS)*BCG_BLOCK_Q8
308 var ticks: i64 = 0
309 var movedTicks: i64 = 0
310 var groundedTicks: i64 = 0
311 var below: i64 = 0
312 var pops: i64 = 0
313 var groundedMismatch: i64 = 0
314 var maxRise: i64 = 0
315 var maxDrop: i64 = 0
316 var servedBelow: i64 = 0
317 var servedPops: i64 = 0
318 var heading: i64 = 0
319 while heading < BCG_HEADINGS {
320 s[S_CX]=s[S_SPX]; s[S_CY]=s[S_SPY]; s[S_CZ]=s[S_SPZ]; s[S_VY]=0; s[S_GROUNDED]=1
321 var mx: i64 = 0
322 var mz: i64 = 0
323 if heading == 0 { mx=SPEED }
324 if heading == 1 { mx=0-SPEED }
325 if heading == 2 { mz=SPEED }
326 if heading == 3 { mz=0-SPEED }
327 var servedPrev: i64 = -1
328 var walking: i64 = 1
329 var t: i64 = 0
330 while walking == 1 && t < BCG_WALK_TICKS {
331 let nx: i64 = s[S_CX]+mx
332 let nz: i64 = s[S_CZ]+mz
333 if nx < edgeLo || nz < edgeLo || nx > edgeHiX || nz > edgeHiZ { walking=0 } else {
334 let px: i64 = s[S_CX]
335 let pz: i64 = s[S_CZ]
336 let py: i64 = s[S_CY]
337 wc_player_motion(base,mx,mz,0)
338 ticks=ticks+1
339 if s[S_CX] != px || s[S_CZ] != pz { movedTicks=movedTicks+1 }
340 let field: i64 = wc_surface_source(base,s[S_CX],s[S_CZ])
341 if field >= 0 { if bcg_below(s[S_CY]-EYE,field) > 0 { below=below+1 } }
342 let dy: i64 = s[S_CY]-py
343 if bcg_abs(dy) >= BCG_BLOCK_Q8 { pops=pops+1 }
344 if dy > maxRise { maxRise=dy }
345 if 0-dy > maxDrop { maxDrop=0-dy }
346 if s[S_GROUNDED] == 1 {
347 groundedTicks=groundedTicks+1
348 if wc_player_support(base,s[S_CX],s[S_CZ],s[S_CY]-EYE) != s[S_CY] { groundedMismatch=groundedMismatch+1 }
349 }
350 let top: i64 = wground(base,s[S_CX]/BCG_BLOCK_Q8,s[S_CZ]/BCG_BLOCK_Q8)
351 if top >= 0 {
352 let served: i64 = (top+1)*BCG_BLOCK_Q8+EYE
353 if field >= 0 { if bcg_below(served-EYE,field) > 0 { servedBelow=servedBelow+1 } }
354 if servedPrev >= 0 { if bcg_abs(served-servedPrev) >= BCG_BLOCK_Q8 { servedPops=servedPops+1 } }
355 servedPrev=served
356 }
357 t=t+1
358 }
359 }
360 heading=heading+1
361 }
362 gv_kv("rank2_walk_ticks",ticks)
363 gv_kv("rank2_walk_moved_ticks",movedTicks)
364 gv_kv("rank2_walk_grounded_ticks",groundedTicks)
365 gv_kv("rank2_walk_max_rise_per_tick_q8",maxRise)
366 gv_kv("rank2_walk_max_drop_per_tick_q8",maxDrop)
367 gv_kv("served_rule_walk_ticks_feet_under_field",servedBelow)
368 gv_kv("served_rule_walk_block_pops",servedPops)
369 gv_check("rank2 walk fixture moved the player and grounded it on this seed",(movedTicks > 0 && groundedTicks > 0) as i64,ctr)
370 gv_check_eq("rank2 walk ticks with feet under the rendered field",below,0,ctr)
371 gv_check_eq("rank2 walk ticks with a block-sized camera pop or drop",pops,0,ctr)
372 gv_check_eq("rank2 walk grounded ticks whose height differs from contact support",groundedMismatch,0,ctr)
373 gv_check("neg-control-served-voxel-top-rule-pops-a-block-on-the-same-walk",(servedPops > 0) as i64,ctr)
374 bcg_free(base)
375 return 0
376}
377
378// RANK 3: a window shift clamps an NPC onto another column and must not leave her buried; her own tick
379// must lift a girl found under her floor.
380func bcg_shift_burial(ctr: *i64) -> i64 {
381 let base: i64 = bcg_world()
382 let m: *i64 = mobp(base)
383 let gs: *i64 = wst(base)
384 let h: i64 = en_nth(m,0)
385 let hz: i64 = en_get(m,h,MC_Z)
386 let landing: i64 = (BCG_CLAMP_BLOCKS+SHIFT_STRIDE)*BCG_BLOCK_Q8
387 let planned: i64 = bcg_place_oracle(base,landing,hz)
388 en_set(m,h,MC_X,BCG_BLOCK_Q8+BCG_BLOCK_Q8/2)
389 en_set(m,h,MC_Y,planned-BCG_BURY_BLOCKS*BCG_BLOCK_Q8)
390 wc_shift(base,SHIFT_STRIDE,0)
391 let seatX: i64 = en_get(m,h,MC_X)
392 let floorAfter: i64 = bcg_place_oracle(base,seatX,en_get(m,h,MC_Z))
393 let yAfter: i64 = en_get(m,h,MC_Y)
394 var worst: i64 = 0
395 var t: i64 = 0
396 while t < BCG_SETTLE_TICKS {
397 gs[S_T]=gs[S_T]+1
398 mob_tick(base)
399 let d: i64 = bcg_below(en_get(m,h,MC_Y),wc_surface_source(base,en_get(m,h,MC_X),en_get(m,h,MC_Z)))
400 if d > worst { worst=d }
401 t=t+1
402 }
403 gv_kv("rank3_shift_landing_x_q8",seatX)
404 gv_kv("rank3_planned_floor_q8",planned)
405 gv_kv("rank3_floor_after_shift_q8",floorAfter)
406 gv_kv("rank3_npc_y_after_shift_q8",yAfter)
407 gv_kv("rank3_worst_under_field_after_shift_q8",worst)
408 gv_check("rank3 shift fixture clamped the npc onto a column whose floor is two blocks above her feet",(seatX == BCG_CLAMP_BLOCKS*BCG_BLOCK_Q8 && planned >= 0 && floorAfter == planned) as i64,ctr)
409 gv_check_eq("rank3 npc q8 under her floor straight after the window shift",bcg_below(yAfter,floorAfter),0,ctr)
410 gv_check_eq("rank3 npc worst q8 under the field over the ticks after the shift",worst,0,ctr)
411 bcg_free(base)
412 let own: i64 = bcg_world()
413 let om: *i64 = mobp(own)
414 let os: *i64 = wst(own)
415 let oh: i64 = en_nth(om,0)
416 let ownFloor: i64 = bcg_place_oracle(own,en_get(om,oh,MC_X),en_get(om,oh,MC_Z))
417 en_set(om,oh,MC_Y,ownFloor-BCG_BURY_BLOCKS*BCG_BLOCK_Q8)
418 os[S_T]=os[S_T]+1
419 mob_tick(own)
420 let lifted: i64 = bcg_below(en_get(om,oh,MC_Y),wc_surface_source(own,en_get(om,oh,MC_X),en_get(om,oh,MC_Z)))
421 gv_kv("rank3_own_column_floor_q8",ownFloor)
422 gv_kv("rank3_own_column_under_field_after_tick_q8",lifted)
423 gv_check_eq("rank3 buried npc q8 under the field after one tick of her own",lifted,0,ctr)
424 bcg_free(own)
425 return 0
426}
427
428// RANK 4: player support never discards the field above the feet. Feet under a flat field at six
429// depths are lifted onto it within one tick and held; a body above the field falls and lands on it.
430func bcg_support_depths(ctr: *i64) -> i64 {
431 let base: i64 = bcg_arena()
432 let spec: *i64 = wsp(base)
433 spec[P_SURF]=1
434 spec[P_WATER]=0
435 var cx: i64 = BCG_FIX_COL-BCG_PATCH_REACH
436 while cx <= BCG_FIX_COL+BCG_PATCH_REACH {
437 var cz: i64 = BCG_FIX_COL-BCG_PATCH_REACH
438 while cz <= BCG_FIX_COL+BCG_PATCH_REACH { hq_set(base,cx,cz,BCG_FLAT_HQ); cz=cz+1 }
439 cx=cx+1
440 }
441 let s: *i64 = wst(base)
442 let p: i64 = BCG_FIX_COL*BCG_BLOCK_Q8+BCG_BLOCK_Q8/2
443 let field: i64 = wc_surface_source(base,p,p)
444 var failures: i64 = 0
445 var firstDepth: i64 = -1
446 var firstEye: i64 = 0
447 var i: i64 = 0
448 while i < BCG_PROBES {
449 var depth: i64 = 1
450 if i == 1 { depth=BCG_BLOCK_Q8-1 }
451 if i == 2 { depth=BCG_BLOCK_Q8 }
452 if i == 3 { depth=EYE-1 }
453 if i == 4 { depth=EYE }
454 if i == 5 { depth=EYE+BCG_BLOCK_Q8 }
455 s[S_CX]=p; s[S_CZ]=p; s[S_CY]=field+EYE-depth; s[S_VY]=0; s[S_GROUNDED]=0
456 var bad: i64 = 0
457 var t: i64 = 0
458 while t < BCG_SETTLE_TICKS {
459 wc_player_vertical_apply(base,0)
460 if s[S_CY] != field+EYE { bad=1 }
461 t=t+1
462 }
463 if s[S_GROUNDED] != 1 { bad=1 }
464 if bad == 1 {
465 failures=failures+1
466 if firstDepth < 0 { firstDepth=depth; firstEye=s[S_CY] }
467 }
468 i=i+1
469 }
470 s[S_CX]=p; s[S_CZ]=p; s[S_CY]=field+EYE+BCG_BLOCK_Q8; s[S_VY]=0; s[S_GROUNDED]=0
471 var t2: i64 = 0
472 while t2 < BCG_SETTLE_TICKS { wc_player_vertical_apply(base,0); t2=t2+1 }
473 gv_kv("rank4_field_q8",field)
474 gv_kv("rank4_first_failing_depth_q8",firstDepth)
475 gv_kv("rank4_first_failing_eye_y_q8",firstEye)
476 gv_kv("rank4_control_eye_y_q8",s[S_CY])
477 gv_check_eq("rank4 fixture field height q8",field,BCG_FLAT_HQ+BCG_BLOCK_Q8,ctr)
478 gv_check_eq("rank4 probe depths under the field not lifted onto it and held",failures,0,ctr)
479 gv_check_eq("rank4 control body a block above the field lands on it (q8 error)",bcg_abs(s[S_CY]-(field+EYE)),0,ctr)
480 bcg_free(base)
481 return 0
482}
483
484// RANK 4 entry: after window slides clamp the spawn column, a stale stored height must not respawn the
485// player under the sand (the H key and the void rescue share wc_respawn).
486func bcg_respawn(ctr: *i64) -> i64 {
487 let base: i64 = bcg_world()
488 let s: *i64 = wst(base)
489 let startX: i64 = s[S_SPX]
490 var shifts: i64 = 0
491 while shifts < BCG_SHIFT_MAX && s[S_SPX] > BCG_CLAMP_BLOCKS*BCG_BLOCK_Q8 {
492 wc_shift(base,SHIFT_STRIDE,0)
493 shifts=shifts+1
494 }
495 let spawnFloor: i64 = bcg_place_oracle(base,s[S_SPX],s[S_SPZ])
496 s[S_SPY]=spawnFloor+EYE-BCG_STALE_SINK_Q8
497 wc_respawn(base)
498 let eyeAfterRespawn: i64 = s[S_CY]
499 var below: i64 = 0
500 var worst: i64 = 0
501 var t: i64 = 0
502 while t < BCG_SETTLE_TICKS {
503 wc_player_motion(base,0,0,0)
504 let d: i64 = bcg_below(s[S_CY]-EYE,wc_surface_source(base,s[S_CX],s[S_CZ]))
505 if d > 0 { below=below+1 }
506 if d > worst { worst=d }
507 t=t+1
508 }
509 gv_kv("rank4_respawn_start_spawn_x_q8",startX)
510 gv_kv("rank4_respawn_shifts",shifts)
511 gv_kv("rank4_respawn_clamped_spawn_x_q8",s[S_SPX])
512 gv_kv("rank4_respawn_spawn_floor_q8",spawnFloor)
513 gv_kv("rank4_respawn_eye_after_respawn_q8",eyeAfterRespawn)
514 gv_kv("rank4_respawn_worst_feet_under_field_q8",worst)
515 gv_check("rank4 respawn fixture clamped the spawn column and found its floor",(shifts > 0 && s[S_SPX] == BCG_CLAMP_BLOCKS*BCG_BLOCK_Q8 && spawnFloor >= 0) as i64,ctr)
516 gv_check_eq("rank4 respawn ticks with feet under the field after the clamp",below,0,ctr)
517 bcg_free(base)
518 return 0
519}
520
521// NPCs held at both window corners: the field is sampled where they stand and they never stand under it.
522func bcg_edge_npc(ctr: *i64) -> i64 {
523 let base: i64 = bcg_world()
524 let m: *i64 = mobp(base)
525 let gs: *i64 = wst(base)
526 let maxX: i64 = (WX-BCG_CLAMP_BLOCKS)*BCG_BLOCK_Q8
527 let maxZ: i64 = (WZ-BCG_CLAMP_BLOCKS)*BCG_BLOCK_Q8
528 let minQ: i64 = BCG_CLAMP_BLOCKS*BCG_BLOCK_Q8
529 let hHi: i64 = en_nth(m,0)
530 let hLo: i64 = en_nth(m,1)
531 en_set(m,hHi,MC_X,maxX)
532 en_set(m,hHi,MC_Z,maxZ)
533 en_set(m,hHi,MC_Y,bcg_place_oracle(base,maxX,maxZ))
534 en_set(m,hLo,MC_X,minQ)
535 en_set(m,hLo,MC_Z,minQ)
536 en_set(m,hLo,MC_Y,bcg_place_oracle(base,minQ,minQ))
537 var invalid: i64 = 0
538 var below: i64 = 0
539 var moved: i64 = 0
540 var farX: i64 = 0
541 var nearX: i64 = maxX
542 var t: i64 = 0
543 while t < BCG_EDGE_TICKS {
544 gs[S_T]=gs[S_T]+1
545 mob_tick(base)
546 var j: i64 = 0
547 while j < 2 {
548 var hh: i64 = hHi
549 var startX: i64 = maxX
550 var startZ: i64 = maxZ
551 if j == 1 { hh=hLo; startX=minQ; startZ=minQ }
552 let ex: i64 = en_get(m,hh,MC_X)
553 let ez: i64 = en_get(m,hh,MC_Z)
554 let field: i64 = wc_surface_source(base,ex,ez)
555 if field < 0 { invalid=invalid+1 } else { if en_get(m,hh,MC_Y) < field { below=below+1 } }
556 if ex != startX || ez != startZ { moved=moved+1 }
557 if ex > farX { farX=ex }
558 if ex < nearX { nearX=ex }
559 j=j+1
560 }
561 t=t+1
562 }
563 gv_kv("edge_far_x_q8",farX)
564 gv_kv("edge_near_x_q8",nearX)
565 gv_kv("edge_moved_observations",moved)
566 gv_kv("edge_unsampled_observations",invalid)
567 gv_kv("edge_under_field_observations",below)
568 gv_check("edge corner npcs observed away from their start",(moved > 0) as i64,ctr)
569 gv_check_eq("edge observations where a corner npc stood where the field cannot be sampled",invalid,0,ctr)
570 gv_check_eq("edge observations where a corner npc stood under the field",below,0,ctr)
571 gv_check("neg-control-the-field-sampler-refuses-the-last-window-column",(wc_surface_source(base,(WX-1)*BCG_BLOCK_Q8,maxZ) < 0) as i64,ctr)
572 bcg_free(base)
573 return 0
574}
575
576// RANK 5: an NPC body pushing the player across a one-block rise never leaves the feet under the field.
577func bcg_push(ctr: *i64) -> i64 {
578 let base: i64 = bcg_world()
579 let spec: *i64 = wsp(base)
580 spec[P_WATER]=0
581 let s: *i64 = wst(base)
582 var cx: i64 = BCG_PUSH_COL-BCG_PATCH_REACH
583 while cx <= BCG_PUSH_COL+BCG_PATCH_REACH {
584 var cz: i64 = BCG_PUSH_COL-BCG_PATCH_REACH
585 while cz <= BCG_PUSH_COL+BCG_PATCH_REACH {
586 var hqv: i64 = BCG_FLAT_HQ
587 if cx > BCG_PUSH_COL { hqv=BCG_FLAT_HQ+BCG_BLOCK_Q8 }
588 hq_set(base,cx,cz,hqv)
589 var y: i64 = 0
590 while y < WY { if bcg_structure(base,cx,y,cz) == 1 { vset(base,cx,y,cz,0) }; y=y+1 }
591 cz=cz+1
592 }
593 cx=cx+1
594 }
595 let px: i64 = BCG_PUSH_COL*BCG_BLOCK_Q8+BCG_BLOCK_Q8/2
596 let pz: i64 = BCG_PUSH_COL*BCG_BLOCK_Q8+BCG_BLOCK_Q8/2
597 s[S_CX]=px; s[S_CZ]=pz; s[S_CY]=wc_surface_source(base,px,pz)+EYE; s[S_VY]=0; s[S_GROUNDED]=1
598 s[S_SPX]=px; s[S_SPY]=s[S_CY]; s[S_SPZ]=pz
599 let m: *i64 = mobp(base)
600 en_init(m,MOB_CAP,MOB_NCOMP)
601 let h: i64 = en_spawn(m)
602 en_set(m,h,MC_X,px-BCG_PUSH_GAP_Q8)
603 en_set(m,h,MC_Z,pz)
604 en_set(m,h,MC_Y,s[S_CY]-EYE)
605 let startFeet: i64 = s[S_CY]-EYE
606 let servedGap: i64 = bcg_below(startFeet,wc_surface_source(base,px-BCG_PUSH_GAP_Q8+BCG_PUSH_BOX_Q8,pz))
607 var below: i64 = 0
608 var worst: i64 = 0
609 var farX: i64 = px
610 var t: i64 = 0
611 while t < BCG_SETTLE_TICKS {
612 apply2_impl(base,0,0,0,0,0,0,0,0,0)
613 let d: i64 = bcg_below(s[S_CY]-EYE,wc_surface_source(base,s[S_CX],s[S_CZ]))
614 if d > 0 { below=below+1 }
615 if d > worst { worst=d }
616 if s[S_CX] > farX { farX=s[S_CX] }
617 t=t+1
618 }
619 gv_kv("rank5_start_x_q8",px)
620 gv_kv("rank5_far_x_q8",farX)
621 gv_kv("rank5_worst_feet_under_field_q8",worst)
622 gv_kv("served_rule_push_feet_under_field_q8",servedGap)
623 gv_check("rank5 push fixture moved the player across the rise",(farX > px) as i64,ctr)
624 gv_check_eq("rank5 push ticks with feet under the field",below,0,ctr)
625 gv_check("neg-control-served-push-without-a-stand-check-leaves-feet-under-the-rise",(servedGap > 0) as i64,ctr)
626 bcg_free(base)
627 return 0
628}
629
630// Plant one structure cell above the body span of every field point in a column, so a body standing on
631// the field fits beneath it while a scan from the sky meets the canopy first.
632func bcg_canopy(base: i64, cx: i64, cz: i64) -> i64 {
633 var high: i64 = hq_get(base,cx,cz)
634 if hq_get(base,cx+1,cz) > high { high=hq_get(base,cx+1,cz) }
635 if hq_get(base,cx,cz+1) > high { high=hq_get(base,cx,cz+1) }
636 if hq_get(base,cx+1,cz+1) > high { high=hq_get(base,cx+1,cz+1) }
637 let fieldTop: i64 = high+BCG_BLOCK_Q8
638 let cell: i64 = (fieldTop+BCG_BODY_CELLS*BCG_BLOCK_Q8+BCG_BLOCK_Q8-1)/BCG_BLOCK_Q8
639 vset(base,cx,cell,cz,BCG_STRUCTURE)
640 return cell
641}
642
643// RANK 6: summoned girls and passport arrivals stand on the lowest body-fitting floor, never on a canopy.
644func bcg_placement(ctr: *i64) -> i64 {
645 let base: i64 = bcg_world()
646 let s: *i64 = wst(base)
647 let m: *i64 = mobp(base)
648 let pcx: i64 = s[S_CX]/BCG_BLOCK_Q8
649 let pcz: i64 = s[S_CZ]/BCG_BLOCK_Q8
650 var planted: i64 = 0
651 var cx: i64 = pcx-BCG_CANOPY_REACH
652 while cx <= pcx+BCG_CANOPY_REACH {
653 var cz: i64 = pcz-BCG_CANOPY_REACH
654 while cz <= pcz+BCG_CANOPY_REACH {
655 if cx >= BCG_CLAMP_BLOCKS && cz >= BCG_CLAMP_BLOCKS && cx < WX-BCG_CLAMP_BLOCKS && cz < WZ-BCG_CLAMP_BLOCKS {
656 bcg_canopy(base,cx,cz)
657 planted=planted+1
658 }
659 cz=cz+1
660 }
661 cx=cx+1
662 }
663 let summoned: i64 = summon_impl(base)
664 var covered: i64 = 0
665 var misplaced: i64 = 0
666 var k: i64 = 0
667 while k < en_count(m) {
668 let h: i64 = en_nth(m,k)
669 let x: i64 = en_get(m,h,MC_X)
670 let z: i64 = en_get(m,h,MC_Z)
671 if bcg_abs(x/BCG_BLOCK_Q8-pcx) <= BCG_CANOPY_REACH && bcg_abs(z/BCG_BLOCK_Q8-pcz) <= BCG_CANOPY_REACH {
672 covered=covered+1
673 if en_get(m,h,MC_Y) != bcg_place_oracle(base,x,z) { misplaced=misplaced+1 }
674 }
675 k=k+1
676 }
677 let pass: *i64 = passp(base)
678 pass[0]=PASS_MAGIC
679 pass[1]=1
680 pass[11]=BCG_PASS_ARRIVALS
681 var pc: i64 = 0
682 while pc < BCG_PASS_ARRIVALS { pass[12+pc*3]=pc; pass[13+pc*3]=0; pass[14+pc*3]=pc+1; pc=pc+1 }
683 pass[21]=wc_pass_ck(pass)
684 let before: i64 = en_count(m)
685 let passRc: i64 = wc_pass_apply(base)
686 let arrivals: i64 = en_count(m)-before
687 var passMisplaced: i64 = 0
688 k=before
689 while k < en_count(m) {
690 let h: i64 = en_nth(m,k)
691 if en_get(m,h,MC_Y) != bcg_place_oracle(base,en_get(m,h,MC_X),en_get(m,h,MC_Z)) { passMisplaced=passMisplaced+1 }
692 k=k+1
693 }
694 gv_kv("rank6_canopy_columns",planted)
695 gv_kv("rank6_cast_after_summon",summoned)
696 gv_kv("rank6_girls_under_canopies",covered)
697 gv_kv("rank6_summon_misplaced",misplaced)
698 gv_kv("rank6_passport_rc",passRc)
699 gv_kv("rank6_passport_arrivals",arrivals)
700 gv_kv("rank6_passport_misplaced",passMisplaced)
701 gv_check("rank6 placement fixture planted canopies over summoned and arriving girls",(planted > 0 && covered > 0 && arrivals > 0) as i64,ctr)
702 gv_check_eq("rank6 summoned girls not on the lowest body-fitting floor",misplaced,0,ctr)
703 gv_check_eq("rank6 passport arrivals not on the lowest body-fitting floor",passMisplaced,0,ctr)
704 bcg_free(base)
705 return 0
706}
707
708// LARGE DT: the page clamps a frame to 250 ms and runs fixed ticks; 15 ticks per frame is the uncapped
709// worst. A fall from the window top never passes under the field and rests exactly on support.
710func bcg_fall(ctr: *i64) -> i64 {
711 let base: i64 = bcg_world()
712 let s: *i64 = wst(base)
713 let perFrame: i64 = (BCG_PAGE_DT_MS*BCG_MS_US+BCG_TICK_US-1)/BCG_TICK_US
714 let field0: i64 = wc_surface_source(base,s[S_CX],s[S_CZ])
715 let start: i64 = (WY-BCG_BODY_CELLS)*BCG_BLOCK_Q8
716 s[S_CY]=start
717 s[S_VY]=0
718 s[S_GROUNDED]=0
719 var below: i64 = 0
720 var overspeed: i64 = 0
721 var landed: i64 = -1
722 var ghostY: i64 = start
723 var ghostV: i64 = 0
724 var ghostBelow: i64 = 0
725 var t: i64 = 0
726 while t < BCG_FALL_TICKS {
727 var f: i64 = 0
728 while f < perFrame {
729 wc_player_motion(base,0,0,0)
730 if bcg_below(s[S_CY]-EYE,wc_surface_source(base,s[S_CX],s[S_CZ])) > 0 { below=below+1 }
731 if s[S_VY] < 0-VTERM { overspeed=overspeed+1 }
732 if landed < 0 && s[S_GROUNDED] == 1 { landed=t }
733 ghostV=ghostV-GRAV
734 if ghostV < 0-VTERM { ghostV=0-VTERM }
735 ghostY=ghostY+ghostV
736 if bcg_below(ghostY-EYE,field0) > 0 { ghostBelow=ghostBelow+1 }
737 f=f+1
738 t=t+1
739 }
740 }
741 let support: i64 = wc_player_support(base,s[S_CX],s[S_CZ],s[S_CY]-EYE)
742 gv_kv("largedt_ticks_per_frame",perFrame)
743 gv_kv("largedt_field_q8",field0)
744 gv_kv("largedt_landed_tick",landed)
745 gv_kv("largedt_final_eye_q8",s[S_CY])
746 gv_kv("largedt_support_q8",support)
747 gv_kv("largedt_unsupported_integrator_under_field_ticks",ghostBelow)
748 gv_check_eq("large-dt fall ticks with feet under the field at 15 fixed ticks per 250 ms frame",below,0,ctr)
749 gv_check_eq("large-dt fall ticks faster than terminal velocity",overspeed,0,ctr)
750 gv_check("large-dt fall landed and rests exactly on contact support",(landed >= 0 && s[S_GROUNDED] == 1 && s[S_CY] == support) as i64,ctr)
751 s[S_CY]=field0+EYE+1
752 s[S_VY]=0-VTERM
753 s[S_GROUNDED]=0
754 wc_player_motion(base,0,0,0)
755 gv_check_eq("terminal-velocity tick from one q8 above the field lands on it (q8 error)",bcg_abs(s[S_CY]-(field0+EYE)),0,ctr)
756 gv_check("neg-control-an-integrator-without-support-falls-through-the-field-on-the-same-fall",(ghostBelow > 0) as i64,ctr)
757 bcg_free(base)
758 return 0
759}
760
761func main() -> i64 {
762 let c: *i64 = gv_ctr()
763 let result: i64 = bcg_checks()
764 gv_check_eq("main-world ground and cast contact regression exit code",result,0,c)
765 bcg_census(c)
766 bcg_walk(c)
767 bcg_shift_burial(c)
768 bcg_support_depths(c)
769 bcg_respawn(c)
770 bcg_edge_npc(c)
771 bcg_push(c)
772 bcg_placement(c)
773 bcg_fall(c)
774 return gv_verdict("BEACH-CONTACT",c,"Native main world and fixtures; browser visual acceptance is separate.")
775}