code wiki / _hdl_build / nx_wire_nethack_gate.nx
nx_wire_nethack_gate.nx source
↩ module page · 917 lines · 37130 B
1// nx_wire_nethack_gate.nx -- TITLE WIRING #1: NetHack (roguelike), the first nx_gamebench title wired
2// through the certified parts. Until now every gamebench readiness number was SELF-GRADED (titles_wired=0):
3// the parts exist, but nothing proved they COMPOSE into this title's genre loop. This gate is that proof --
4// an actual playable roguelike loop (procgen dungeon -> descend -> fight -> loot rations -> level up ->
5// save/resume) built ONLY from certified parts, with every exercised capability measured by a tooth.
6//
7// CAPS EXERCISED (bit = nx_gamebench capability index, set ONLY if its tooth passes; the mask is written
8// into the wiring artifact payload[0] so the board's declared mask can be cross-checked by nx_gamebench_gate):
9// bit 3 procgen-world (deterministic carved dungeon, seed-diverse, stairs reachable)
10// bit 7 pathfinding-ai (nx_pathfind pf_astar drives the player every move turn)
11// bit 6 entity-component-sim (nx_entity_store holds monsters; stale handle of a killed monster refused)
12// bit 9 rpg-stats-progression(nx_rpgstats XP curve/level inverse/derived HP drive combat + level-ups)
13// bit 11 inventory-crafting (rations picked up, 2 rations CRAFT a feast, ledger conserves exactly)
14// bit 15 save-load-persistence(nx_gamesave mid-run save -> load into ZEROED state -> resume TRANSPARENT)
15// bit 18 ui-menus-hud (nx_gamehud: the eat decision goes THROUGH a modal menu -- open/wrap/select
16// CAUSES the eat, it is not painted after the fact; HUD slots bind live
17// hp/lvl/depth/kills/food per turn, render-chain deterministic across runs)
18// NOT exercised (title requires, this loop does not prove -> the board must down-score them for NetHack):
19// bit 14 text-render-typography (the HUD blits glyphs, but typography = layout/wrap/paragraphs; honest no-claim).
20//
21// FLAGSHIP PROPERTY (mutation target): save/load TRANSPARENCY -- play N..M continuously vs play N, save,
22// load into a zeroed world, resume to M: EVERY per-turn checksum identical (the GX-9 test most engines
23// cannot run; it catches the whole "the save forgot a field" class). Non-vacuity guard: the resumed world
24// must be non-trivial (live monsters, xp earned, items picked) or the equality proves nothing.
25// license_tier: ORIGINAL expect_exit: 0
26import "nx_syscalls.nx"
27import "nx_gamesave.nx"
28import "nx_rpgstats.nx"
29import "nx_entity_store.nx"
30import "nx_pathfind.nx"
31import "nx_gamehud.nx"
32import "nx_wire_harness.nx"
33
34// ---- world shape (data at the top, per rule 11) ----
35const NH_W: i64 = 24
36const NH_H: i64 = 12
37const NH_DEPTH: i64 = 3
38const NH_NMON: i64 = 6
39const NH_NITEM: i64 = 5
40const NH_CAP: i64 = 16 // entity arena capacity
41const NH_NCOMP: i64 = 4 // components: 0=x 1=y 2=hp 3=xp_reward
42const NH_CARVE: i64 = 140 // carve steps per level
43const NH_AGGRO: i64 = 8 // monster chase radius (manhattan)
44const NH_MAXT: i64 = 600
45// rpg tuning (feeds the data-driven nx_rpgstats curves)
46const NH_XB: i64 = 20 // xp curve base
47const NH_XQ: i64 = 10 // xp curve quad
48const NH_HPB: i64 = 10
49const NH_HPC: i64 = 2
50const NH_HPL: i64 = 3
51const NH_CON: i64 = 14
52const NH_BITE: i64 = 2
53const NH_MHPB: i64 = 12 // monster base hp (tanky enough that the save point sees a LIVE world)
54const NH_HEAL_R: i64 = 10 // ration heal
55const NH_HEAL_F: i64 = 25 // feast heal (crafted from 2 rations -> crafting is worth it)
56// save shape
57const NH_HDRN: i64 = 26 // game header fields serialized
58const NH_NSV: i64 = 106 // 26 hdr + 1 nmon + 16*4 monsters + 5*3 items
59const NH_SCHEMA: i64 = 7307
60const NH_ART_SCHEMA: i64 = 7317 // the wiring-evidence artifact schema
61// transparency test window (the full run wins at ~turn 62; the window must sit fully before the win)
62const NH_T1W: i64 = 20
63const NH_T2W: i64 = 45
64// ---- game arena offsets (i64 words; grid 288, scratch blocks padded to 296) ----
65const NG_O_GRID: i64 = 32
66const NG_O_ITEM: i64 = 320
67const NG_O_ENT: i64 = 336 // en_words(16,4) = 156, padded to 160
68const NG_O_PATH: i64 = 496
69const NG_O_G: i64 = 792
70const NG_O_F: i64 = 1088
71const NG_O_CAME: i64 = 1384
72const NG_O_OPENF: i64 = 1680
73const NG_O_CLOSED: i64 = 1976
74const NG_O_CARVE: i64 = 2272
75const NG_O_HUD: i64 = 2576 // nx_gamehud arena (GH_WORDS=64) APPENDED -- UI state rides the game
76 // arena but stays OUT of the save (transient UI, re-init on restore;
77 // the PART's own gate proves hud state CAN persist -- the TITLE keeps
78 // it ephemeral, which is what real roguelikes do with menu state)
79const NG_WORDS: i64 = 2640
80const NH_HUDINK: i64 = 50 // min ink px for a non-vacuous HUD frame (T10 guard)
81// header field indices inside the game arena
82const F_WS: i64 = 0
83const F_DEPTH: i64 = 1
84const F_TURN: i64 = 2
85const F_PX: i64 = 3
86const F_PY: i64 = 4
87const F_XP: i64 = 5
88const F_LVL: i64 = 6
89const F_HP: i64 = 7
90const F_KILLS: i64 = 8
91const F_RATION: i64 = 9
92const F_FEAST: i64 = 10
93const F_PICKED: i64 = 11
94const F_USED: i64 = 12
95const F_WIN: i64 = 13
96const F_COMB: i64 = 14
97const F_EATR: i64 = 15
98const F_EATF: i64 = 16
99const F_PSTEPS: i64 = 17
100const F_ATT: i64 = 18
101const F_BITES: i64 = 19
102const F_SPAWNED: i64 = 20
103const F_SX: i64 = 21
104const F_SY: i64 = 22
105const F_NCARVE: i64 = 23
106const F_GENRNG: i64 = 24
107const F_ABAND: i64 = 25 // monsters left alive on a level when the player descended
108
109func ww(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
110func wn(v: i64) -> i64 {
111 if v==0 { sys_write(1,"0" as *u8,1); return 0 }
112 var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m }
113 let t: *u8=sys_mmap(32); var k: i64=0
114 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
115 let o: *u8=sys_mmap(32); var q: i64=k-1; var i: i64=0
116 while q>=0 { o[i]=t[q]; i=i+1; q=q-1 }
117 sys_write(1,o,i); return 0
118}
119func nbit(i: i64) -> i64 { var v: i64=1; var k: i64=0; while k<i { v=v*2; k=k+1 } return v }
120func nrng(g: *i64) -> i64 {
121 var x: i64 = g[F_GENRNG]
122 x = x ^ (x << 13)
123 x = x ^ (x >> 7)
124 x = x ^ (x << 17)
125 g[F_GENRNG] = x
126 if x < 0 { return 0 - x }
127 return x
128}
129func nabs(v: i64) -> i64 { if v<0 { return 0-v } return v }
130
131// ---- level structure: PURE function of (worldseed, depth). Restore regenerates it exactly. ----
132func nh_genstruct(g: *i64) -> i64 {
133 g[F_GENRNG] = g[F_WS]*1000 + g[F_DEPTH]*7919
134 if g[F_GENRNG]==0 { g[F_GENRNG]=1 }
135 let grid: *i64 = (g as i64 + NG_O_GRID*8) as *i64
136 let carve: *i64 = (g as i64 + NG_O_CARVE*8) as *i64
137 var i: i64=0
138 while i<NH_W*NH_H { grid[i]=1; i=i+1 }
139 var cx: i64=1
140 var cy: i64=1
141 grid[cy*NH_W+cx]=0
142 carve[0]=cy*NH_W+cx
143 var nc: i64=1
144 var steps: i64=0
145 while steps<NH_CARVE {
146 let d: i64 = nrng(g)%4
147 var tx: i64=cx
148 var ty: i64=cy
149 if d==0 { tx=cx+1 }
150 if d==1 { tx=cx-1 }
151 if d==2 { ty=cy+1 }
152 if d==3 { ty=cy-1 }
153 if tx>=1 { if tx<=NH_W-2 { if ty>=1 { if ty<=NH_H-2 {
154 cx=tx; cy=ty
155 if grid[cy*NH_W+cx]==1 { grid[cy*NH_W+cx]=0; carve[nc]=cy*NH_W+cx; nc=nc+1 }
156 } } } }
157 steps=steps+1
158 }
159 g[F_SX]=cx
160 g[F_SY]=cy
161 g[F_NCARVE]=nc
162 return nc
163}
164// place monsters + items on carved floor, reset player to the entrance (level entry only, never on restore)
165func nh_populate(g: *i64) -> i64 {
166 let carve: *i64 = (g as i64 + NG_O_CARVE*8) as *i64
167 let item: *i64 = (g as i64 + NG_O_ITEM*8) as *i64
168 let a: *i64 = (g as i64 + NG_O_ENT*8) as *i64
169 en_init(a, NH_CAP, NH_NCOMP)
170 let nc: i64 = g[F_NCARVE]
171 let d: i64 = g[F_DEPTH]
172 var m: i64=0
173 while m<NH_NMON {
174 var placed: i64=0
175 var guard: i64=0
176 while placed==0 {
177 guard=guard+1
178 if guard>200 { placed=1 }
179 let pick: i64 = 1 + (nrng(g) % (nc-1))
180 let cell: i64 = carve[pick]
181 let mx: i64 = cell % NH_W
182 let my: i64 = cell / NH_W
183 // not on another monster
184 var clash: i64=0
185 var k: i64=0
186 while k<en_count(a) {
187 let h: i64 = en_nth(a,k)
188 let ox: i64 = en_get(a,h,0)
189 let oy: i64 = en_get(a,h,1)
190 if ox==mx { if oy==my { clash=1 } }
191 k=k+1
192 }
193 if clash==0 { if placed==0 {
194 let h2: i64 = en_spawn(a)
195 if h2!=EN_NULL {
196 en_set(a,h2,0,mx)
197 en_set(a,h2,1,my)
198 let mhp: i64 = NH_MHPB + d*2
199 en_set(a,h2,2,mhp)
200 let mxp: i64 = 15*d
201 en_set(a,h2,3,mxp)
202 g[F_SPAWNED]=g[F_SPAWNED]+1
203 placed=1
204 }
205 } }
206 }
207 m=m+1
208 }
209 var it: i64=0
210 while it<NH_NITEM {
211 var placed2: i64=0
212 var guard2: i64=0
213 while placed2==0 {
214 guard2=guard2+1
215 if guard2>200 { placed2=1 }
216 let pick2: i64 = 1 + (nrng(g) % (nc-1))
217 let cell2: i64 = carve[pick2]
218 let ix: i64 = cell2 % NH_W
219 let iy: i64 = cell2 / NH_W
220 var clash2: i64=0
221 var q: i64=0
222 while q<it { if item[q*3]==ix { if item[q*3+1]==iy { clash2=1 } } q=q+1 }
223 // not on the stairs (items on stairs would be fine, keep them distinct for clarity)
224 if ix==g[F_SX] { if iy==g[F_SY] { clash2=1 } }
225 if clash2==0 { if placed2==0 {
226 item[it*3]=ix
227 item[it*3+1]=iy
228 item[it*3+2]=0
229 placed2=1
230 } }
231 }
232 it=it+1
233 }
234 g[F_PX]=1
235 g[F_PY]=1
236 return 0
237}
238func nh_new(g: *i64, ws: i64) -> i64 {
239 var i: i64=0
240 while i<32 { g[i]=0; i=i+1 }
241 g[F_WS]=ws
242 g[F_DEPTH]=1
243 let l1: i64 = rs_level_for_xp(0, NH_XB, NH_XQ)
244 g[F_LVL]=l1
245 let hp0: i64 = rs_derived_hp(NH_CON, l1, NH_HPB, NH_HPC, NH_HPL)
246 g[F_HP]=hp0
247 nh_genstruct(g)
248 nh_populate(g)
249 let hud: *i64 = (g as i64 + NG_O_HUD*8) as *i64
250 gh_init(hud, 5)
251 return 0
252}
253// serialize game-visible state into S[NH_NSV] (monsters via DENSE order so restore preserves iteration order)
254func nh_serialize(g: *i64, S: *i64) -> i64 {
255 var i: i64=0
256 while i<NH_HDRN { S[i]=g[i]; i=i+1 }
257 let a: *i64 = (g as i64 + NG_O_ENT*8) as *i64
258 let n: i64 = en_count(a)
259 S[NH_HDRN]=n
260 var k: i64=0
261 while k<NH_CAP*4 { S[NH_HDRN+1+k]=0; k=k+1 }
262 k=0
263 while k<n {
264 let h: i64 = en_nth(a,k)
265 let b: i64 = NH_HDRN+1+k*4
266 let v0: i64 = en_get(a,h,0)
267 let v1: i64 = en_get(a,h,1)
268 let v2: i64 = en_get(a,h,2)
269 let v3: i64 = en_get(a,h,3)
270 S[b]=v0
271 S[b+1]=v1
272 S[b+2]=v2
273 S[b+3]=v3
274 k=k+1
275 }
276 let item: *i64 = (g as i64 + NG_O_ITEM*8) as *i64
277 let ib: i64 = NH_HDRN+1+NH_CAP*4
278 var q: i64=0
279 while q<NH_NITEM*3 { S[ib+q]=item[q]; q=q+1 }
280 return NH_NSV
281}
282// restore a game from S into a (possibly ZEROED) arena: header, regenerated structure, monsters, items
283func nh_restore(g: *i64, S: *i64) -> i64 {
284 var i: i64=0
285 while i<32 { g[i]=0; i=i+1 }
286 g[F_WS]=S[F_WS]
287 g[F_DEPTH]=S[F_DEPTH]
288 nh_genstruct(g) // grid + stairs: pure function of (ws,depth), matches by determinism
289 // copy the FULL header AFTER genstruct: genstruct clobbers F_GENRNG (it re-runs the carve), and the
290 // saved value is the post-populate stream -- restoring it after keeps the checksum bit-exact.
291 i=0
292 while i<NH_HDRN { g[i]=S[i]; i=i+1 }
293 let a: *i64 = (g as i64 + NG_O_ENT*8) as *i64
294 en_init(a, NH_CAP, NH_NCOMP)
295 let n: i64 = S[NH_HDRN]
296 var k: i64=0
297 while k<n {
298 let b: i64 = NH_HDRN+1+k*4
299 let h: i64 = en_spawn(a)
300 en_set(a,h,0,S[b])
301 en_set(a,h,1,S[b+1])
302 en_set(a,h,2,S[b+2])
303 en_set(a,h,3,S[b+3])
304 k=k+1
305 }
306 let item: *i64 = (g as i64 + NG_O_ITEM*8) as *i64
307 let ib: i64 = NH_HDRN+1+NH_CAP*4
308 var q: i64=0
309 while q<NH_NITEM*3 { item[q]=S[ib+q]; q=q+1 }
310 let hud: *i64 = (g as i64 + NG_O_HUD*8) as *i64
311 gh_init(hud, 5) // UI state is transient: fresh menu machine on restore, game state untouched
312 return 0
313}
314func nh_ckv(ck: i64, v0: i64) -> i64 {
315 var v: i64 = v0
316 if v<0 { v = (0-v)*2+1 } else { v = v*2 }
317 return (ck*131 + v) & 0x7FFFFFFFFFFFFFFF
318}
319// order-sensitive rolling checksum of the FULL game-visible state.
320// DELIBERATELY INDEPENDENT of nh_serialize: it walks the live arena directly, so a serializer that
321// "forgets a field" produces a restore whose checksum diverges -- the T6 transparency tooth catches it.
322// (A ck routed THROUGH the serializer would inherit the same amnesia and prove nothing.)
323func nh_ck(g: *i64) -> i64 {
324 var ck: i64 = 1469598103
325 var i: i64=0
326 while i<NH_HDRN { ck = nh_ckv(ck, g[i]); i=i+1 }
327 let a: *i64 = (g as i64 + NG_O_ENT*8) as *i64
328 let n: i64 = en_count(a)
329 ck = nh_ckv(ck, n)
330 var k: i64=0
331 while k<n {
332 let h: i64 = en_nth(a,k)
333 var c: i64=0
334 while c<4 {
335 let v: i64 = en_get(a,h,c)
336 ck = nh_ckv(ck, v)
337 c=c+1
338 }
339 k=k+1
340 }
341 let item: *i64 = (g as i64 + NG_O_ITEM*8) as *i64
342 var q: i64=0
343 while q<NH_NITEM*3 { ck = nh_ckv(ck, item[q]); q=q+1 }
344 return ck
345}
346// is any OTHER monster on (x,y)?
347func nh_moncell(a: *i64, x: i64, y: i64, skip: i64) -> i64 {
348 var k: i64=0
349 while k<en_count(a) {
350 let h: i64 = en_nth(a,k)
351 if h!=skip {
352 let ox: i64 = en_get(a,h,0)
353 let oy: i64 = en_get(a,h,1)
354 if ox==x { if oy==y { return 1 } }
355 }
356 k=k+1
357 }
358 return 0
359}
360// one game turn. returns the handle of a monster KILLED this turn (0 if none) -- the stale-handle witness.
361func nh_tick(g: *i64) -> i64 {
362 if g[F_WIN]==1 { return 0 }
363 let grid: *i64 = (g as i64 + NG_O_GRID*8) as *i64
364 let a: *i64 = (g as i64 + NG_O_ENT*8) as *i64
365 let item: *i64 = (g as i64 + NG_O_ITEM*8) as *i64
366 var killed: i64 = 0
367 let px: i64 = g[F_PX]
368 let py: i64 = g[F_PY]
369 // ---- player action: attack an adjacent monster, else descend on stairs, else A* step toward stairs ----
370 var adj: i64 = 0
371 var k: i64=0
372 while k<en_count(a) {
373 if adj==0 {
374 let h: i64 = en_nth(a,k)
375 let mx: i64 = en_get(a,h,0)
376 let my: i64 = en_get(a,h,1)
377 let dd: i64 = nabs(mx-px)+nabs(my-py)
378 if dd==1 { adj=h }
379 }
380 k=k+1
381 }
382 // DIALECT NOTE: no `else if` / `||` / `else` in this file from here on -- multiline else-branches
383 // DESYNC the nx_cc parser (found by THIS gate; minimal repro nx_wire_probe.nx aux2: the next func
384 // fuses into this one as an empty stub and the binary runs silent exit-0). The certified parts are
385 // mostly plain-if code; this file uses flag vars instead of else-chains.
386 var acted: i64=0
387 if adj!=0 {
388 acted=1
389 g[F_ATT]=g[F_ATT]+1
390 let dmg: i64 = 4 + g[F_LVL]*2
391 let mhp: i64 = en_get(a,adj,2) - dmg
392 if mhp<=0 {
393 let reward: i64 = en_get(a,adj,3)
394 en_destroy(a,adj)
395 killed=adj
396 g[F_KILLS]=g[F_KILLS]+1
397 g[F_XP]=g[F_XP]+reward
398 let nl: i64 = rs_level_for_xp(g[F_XP], NH_XB, NH_XQ)
399 if nl>g[F_LVL] {
400 g[F_LVL]=nl
401 let mh: i64 = rs_derived_hp(NH_CON, nl, NH_HPB, NH_HPC, NH_HPL)
402 g[F_HP]=mh
403 }
404 }
405 if mhp>0 { en_set(a,adj,2,mhp) }
406 }
407 if acted==0 { if px==g[F_SX] { if py==g[F_SY] {
408 acted=1
409 g[F_DEPTH]=g[F_DEPTH]+1
410 if g[F_DEPTH]>NH_DEPTH { g[F_WIN]=1 }
411 if g[F_DEPTH]<=NH_DEPTH {
412 let leftover: i64 = en_count(a)
413 g[F_ABAND]=g[F_ABAND]+leftover
414 nh_genstruct(g)
415 nh_populate(g)
416 }
417 } } }
418 if acted==0 { if g[F_WIN]==0 {
419 let pg: *i64 = (g as i64 + NG_O_G*8) as *i64
420 let pf: *i64 = (g as i64 + NG_O_F*8) as *i64
421 let pc: *i64 = (g as i64 + NG_O_CAME*8) as *i64
422 let po: *i64 = (g as i64 + NG_O_OPENF*8) as *i64
423 let pz: *i64 = (g as i64 + NG_O_CLOSED*8) as *i64
424 let pp: *i64 = (g as i64 + NG_O_PATH*8) as *i64
425 let plen: i64 = pf_astar(grid, NH_W, NH_H, px, py, g[F_SX], g[F_SY], pg, pf, pc, po, pz, pp)
426 if plen>=1 {
427 let nxt: i64 = pp[1]
428 let nx: i64 = nxt % NH_W
429 let ny: i64 = nxt / NH_W
430 // never step ONTO a monster (an adjacent one would have been attacked; this is belt+braces)
431 let occ: i64 = nh_moncell(a, nx, ny, 0)
432 if occ==0 { g[F_PX]=nx; g[F_PY]=ny; g[F_PSTEPS]=g[F_PSTEPS]+1 }
433 }
434 } }
435 // ---- pickup ----
436 let qx: i64 = g[F_PX]
437 let qy: i64 = g[F_PY]
438 var q: i64=0
439 while q<NH_NITEM {
440 if item[q*3+2]==0 { if item[q*3]==qx { if item[q*3+1]==qy {
441 item[q*3+2]=1
442 g[F_RATION]=g[F_RATION]+1
443 g[F_PICKED]=g[F_PICKED]+1
444 } } }
445 q=q+1
446 }
447 // ---- craft: 2 rations -> 1 feast (one combine per turn) ----
448 if g[F_RATION]>=2 {
449 g[F_RATION]=g[F_RATION]-2
450 g[F_FEAST]=g[F_FEAST]+1
451 g[F_COMB]=g[F_COMB]+1
452 }
453 // ---- eat when hurt, THROUGH THE MENU (bit 18): the selection CAUSES the eat. Feast-first policy
454 // is encoded as menu ORDER (feast listed first, cursor selects item 0 after a FULL WRAP -- the wrap
455 // exercises gh_menu_move's both-directions arithmetic on every single eat of every run). Same
456 // decisions as the old inline chain => game-state evolution and every banked checksum unchanged. ----
457 let maxhp: i64 = rs_derived_hp(NH_CON, g[F_LVL], NH_HPB, NH_HPC, NH_HPL)
458 let hud: *i64 = (g as i64 + NG_O_HUD*8) as *i64
459 if g[F_HP] < maxhp {
460 var edible: i64=0
461 if g[F_FEAST]>0 { edible=edible+1 }
462 if g[F_RATION]>0 { edible=edible+1 }
463 if edible>0 {
464 gh_menu_open(hud, edible)
465 var slot: i64=0
466 if g[F_FEAST]>0 { gh_menu_item(hud, slot, 1, g[F_FEAST]); slot=slot+1 }
467 if g[F_RATION]>0 { gh_menu_item(hud, slot, 2, g[F_RATION]); slot=slot+1 }
468 let choice: i64 = wh_menu_wrapsel(hud, edible) // MIGRATED: shared variable-menu wrap+select
469 if choice==1 {
470 g[F_FEAST]=g[F_FEAST]-1
471 g[F_HP]=g[F_HP]+NH_HEAL_F
472 g[F_USED]=g[F_USED]+1
473 g[F_EATF]=g[F_EATF]+1
474 }
475 if choice==2 {
476 g[F_RATION]=g[F_RATION]-1
477 g[F_HP]=g[F_HP]+NH_HEAL_R
478 g[F_USED]=g[F_USED]+1
479 g[F_EATR]=g[F_EATR]+1
480 }
481 }
482 if g[F_HP]>maxhp { g[F_HP]=maxhp }
483 }
484 // ---- monsters: bite when adjacent, chase when in aggro range ----
485 // ⚠nx_cc PARSER TRAP (found by THIS gate, minimal repro nx_wire_probe.nx aux2): a var/let declared
486 // DIRECTLY inside an `else if` branch DESYNCS the parser -- later funcs fuse into this one as empty
487 // stubs and the binary exits 0 silently. Workaround: hoist ALL decls above the if/else-if.
488 var mI: i64=0
489 var msx: i64=0
490 var msy: i64=0
491 var mtx: i64=0
492 var mty: i64=0
493 var moved: i64=0
494 var occ2: i64=0
495 var occ3: i64=0
496 let mtot: i64 = en_count(a)
497 while mI<mtot {
498 let h2: i64 = en_nth(a,mI)
499 let mx2: i64 = en_get(a,h2,0)
500 let my2: i64 = en_get(a,h2,1)
501 let da: i64 = nabs(mx2-g[F_PX])
502 let db: i64 = nabs(my2-g[F_PY])
503 let d2: i64 = da+db
504 if d2==1 {
505 g[F_HP]=g[F_HP]-NH_BITE
506 g[F_BITES]=g[F_BITES]+1
507 }
508 if d2>1 { if d2<=NH_AGGRO {
509 msx=0
510 if g[F_PX]>mx2 { msx=1 }
511 if g[F_PX]<mx2 { msx=0-1 }
512 moved=0
513 if msx!=0 {
514 mtx=mx2+msx
515 if grid[my2*NH_W+mtx]==0 {
516 occ2 = nh_moncell(a,mtx,my2,h2)
517 var onp: i64=0
518 if mtx==g[F_PX] { if my2==g[F_PY] { onp=1 } }
519 if occ2==0 { if onp==0 { en_set(a,h2,0,mtx); moved=1 } }
520 }
521 }
522 if moved==0 {
523 msy=0
524 if g[F_PY]>my2 { msy=1 }
525 if g[F_PY]<my2 { msy=0-1 }
526 if msy!=0 {
527 mty=my2+msy
528 if grid[mty*NH_W+mx2]==0 {
529 occ3 = nh_moncell(a,mx2,mty,h2)
530 var onp2: i64=0
531 if mx2==g[F_PX] { if mty==g[F_PY] { onp2=1 } }
532 if occ3==0 { if onp2==0 { en_set(a,h2,1,mty) } }
533 }
534 }
535 }
536 } }
537 mI=mI+1
538 }
539 g[F_TURN]=g[F_TURN]+1
540 return killed
541}
542// T10 instrument: replay a real game for `turns`, binding the HUD to live state and rendering every
543// turn; returns the rolling chain of frame checksums. out[0]=frames that CHANGED vs the previous
544// (a state-blind renderer scores 0), out[1]=final-frame ink px, out[2]=menu selections made in-loop.
545func nh_hudchain(seed: i64, turns: i64, out: *i64) -> i64 {
546 let g: *i64 = sys_mmap(NG_WORDS*8) as *i64
547 nh_new(g, seed)
548 let font: *u8 = font8x8_table()
549 let labels: *i64 = sys_mmap(8*8) as *i64
550 labels[0]="HP" as i64
551 labels[1]="LVL" as i64
552 labels[2]="DEPTH" as i64
553 labels[3]="KILLS" as i64
554 labels[4]="FOOD" as i64
555 let mlabels: *i64 = sys_mmap(8*8) as *i64
556 mlabels[0]="feast" as i64
557 mlabels[1]="ration" as i64
558 let fb: *u8 = sys_mmap(72000)
559 let hud: *i64 = (g as i64 + NG_O_HUD*8) as *i64
560 var chain: i64 = 1469598103
561 var prev: i64 = 0
562 var moved: i64 = 0
563 var t: i64 = 0
564 while t < turns {
565 nh_tick(g)
566 gh_slot_set(hud, 0, g[F_HP])
567 gh_slot_set(hud, 1, g[F_LVL])
568 gh_slot_set(hud, 2, g[F_DEPTH])
569 gh_slot_set(hud, 3, g[F_KILLS])
570 gh_slot_set(hud, 4, g[F_RATION]+g[F_FEAST])
571 var z: i64=0
572 while z<72000 { fb[z]=0 as u8; z=z+1 }
573 gh_render(hud, fb, 200, 120, font, labels, mlabels)
574 let fk: i64 = gh_frame_ck(fb, 200, 120)
575 if t>0 { if fk!=prev { moved=moved+1 } }
576 prev=fk
577 chain = (chain*131 + (fk & 0xFFFFFFFF)) & 0x7FFFFFFFFFFFFFFF
578 t=t+1
579 }
580 out[0]=moved
581 out[1]=gh_ink(fb, 200, 120)
582 out[2]=hud[GH_F_NSEL]
583 return chain
584}
585// run until win or maxturns; returns first-killed handle (the stale witness)
586func nh_run_full(g: *i64) -> i64 {
587 var firstkill: i64=0
588 var go: i64=1
589 while go==1 {
590 if g[F_WIN]==1 { go=0 }
591 if g[F_TURN]>=NH_MAXT { go=0 }
592 if g[F_HP]<=0 { go=0 }
593 if go==1 {
594 let kh: i64 = nh_tick(g)
595 if kh!=0 { if firstkill==0 { firstkill=kh } }
596 }
597 }
598 return firstkill
599}
600
601func main() -> i64 {
602 ww("=== nx_wire_nethack_gate: does NetHack's genre loop actually run on the certified parts? ===\n\n")
603 var pass: i64 = 0
604 var checks: i64 = 0
605 var mask: i64 = 0
606 let SEED: i64 = 4242
607 let g1: *i64 = sys_mmap(NG_WORDS*8) as *i64
608 let g2: *i64 = sys_mmap(NG_WORDS*8) as *i64
609 let S: *i64 = sys_mmap(NH_NSV*8+64) as *i64
610 let S2: *i64 = sys_mmap(NH_NSV*8+64) as *i64
611
612 // ---------- T1 procgen-world (bit 3): deterministic, seed-diverse, stairs reachable ----------
613 checks=checks+1
614 nh_new(g1, SEED)
615 nh_new(g2, SEED)
616 let cka: i64 = nh_ck(g1)
617 let ckb: i64 = nh_ck(g2)
618 nh_new(g2, SEED+1)
619 let grid1: *i64 = (g1 as i64 + NG_O_GRID*8) as *i64
620 let grid2: *i64 = (g2 as i64 + NG_O_GRID*8) as *i64
621 var diff: i64=0
622 var i: i64=0
623 while i<NH_W*NH_H { if grid1[i]!=grid2[i] { diff=diff+1 } i=i+1 }
624 let pg1: *i64 = (g1 as i64 + NG_O_G*8) as *i64
625 let pf1: *i64 = (g1 as i64 + NG_O_F*8) as *i64
626 let pc1: *i64 = (g1 as i64 + NG_O_CAME*8) as *i64
627 let po1: *i64 = (g1 as i64 + NG_O_OPENF*8) as *i64
628 let pz1: *i64 = (g1 as i64 + NG_O_CLOSED*8) as *i64
629 let pp1: *i64 = (g1 as i64 + NG_O_PATH*8) as *i64
630 let plen0: i64 = pf_astar(grid1, NH_W, NH_H, 1, 1, g1[F_SX], g1[F_SY], pg1, pf1, pc1, po1, pz1, pp1)
631 // every monster and item sits on a floor cell
632 let a1: *i64 = (g1 as i64 + NG_O_ENT*8) as *i64
633 let item1: *i64 = (g1 as i64 + NG_O_ITEM*8) as *i64
634 var badcell: i64=0
635 var k: i64=0
636 while k<en_count(a1) {
637 let h: i64 = en_nth(a1,k)
638 let mx: i64 = en_get(a1,h,0)
639 let my: i64 = en_get(a1,h,1)
640 if grid1[my*NH_W+mx]!=0 { badcell=badcell+1 }
641 k=k+1
642 }
643 k=0
644 while k<NH_NITEM {
645 let ix: i64=item1[k*3]
646 let iy: i64=item1[k*3+1]
647 if grid1[iy*NH_W+ix]!=0 { badcell=badcell+1 }
648 k=k+1
649 }
650 var t1: i64=0
651 if cka==ckb { if diff>=30 { if plen0>=1 { if badcell==0 {
652 ww("T1 GREEN procgen: same seed identical (ck "); wn(cka)
653 ww("), seed+1 differs in "); wn(diff); ww(" cells, stairs reachable (path "); wn(plen0)
654 ww("), 0 off-floor placements\n")
655 t1=1; pass=pass+1
656 mask=mask+nbit(3)
657 } } } }
658 if t1==0 {
659 ww("T1 RED procgen: ckA="); wn(cka); ww(" ckB="); wn(ckb)
660 ww(" diff="); wn(diff); ww(" plen="); wn(plen0); ww(" badcell="); wn(badcell); ww("\n")
661 }
662
663 // ---------- T2 pathfinding-ai (bit 7): the A* path is valid cell-by-cell ----------
664 checks=checks+1
665 var pathok: i64=1
666 i=1
667 while i<=plen0 {
668 let c0: i64 = pp1[i-1]
669 let c1: i64 = pp1[i]
670 let x0: i64 = c0 % NH_W
671 let y0: i64 = c0 / NH_W
672 let x1: i64 = c1 % NH_W
673 let y1: i64 = c1 / NH_W
674 let ad: i64 = nabs(x1-x0)+nabs(y1-y0)
675 if ad!=1 { pathok=0 }
676 if grid1[c1]!=0 { pathok=0 }
677 i=i+1
678 }
679 var t2: i64=0
680 if plen0>=1 { if pathok==1 {
681 ww("T2 GREEN pathfinding: pf_astar path of "); wn(plen0)
682 ww(" steps is 4-adjacent floor cell-by-cell (the part drives every player move)\n")
683 t2=1; pass=pass+1
684 mask=mask+nbit(7)
685 } }
686 if t2==0 { ww("T2 RED pathfinding: plen="); wn(plen0); ww(" pathok="); wn(pathok); ww("\n") }
687
688 // ---------- full deterministic run (the actual game) ----------
689 nh_new(g1, SEED)
690 let fk: i64 = nh_run_full(g1)
691 let a1b: *i64 = (g1 as i64 + NG_O_ENT*8) as *i64
692 let fck: i64 = nh_ck(g1)
693 let runwin: i64 = g1[F_WIN]
694 let runturn: i64 = g1[F_TURN]
695 let runkills: i64 = g1[F_KILLS]
696 let runxp: i64 = g1[F_XP]
697 let runlvl: i64 = g1[F_LVL]
698 ww(" [run] turns="); wn(g1[F_TURN]); ww(" depth="); wn(g1[F_DEPTH]); ww(" win="); wn(g1[F_WIN])
699 ww(" kills="); wn(g1[F_KILLS]); ww(" xp="); wn(g1[F_XP]); ww(" level="); wn(g1[F_LVL])
700 ww(" hp="); wn(g1[F_HP]); ww(" picked="); wn(g1[F_PICKED]); ww(" used="); wn(g1[F_USED])
701 ww(" combines="); wn(g1[F_COMB]); ww(" psteps="); wn(g1[F_PSTEPS]); ww(" bites="); wn(g1[F_BITES])
702 ww(" ck="); wn(fck); ww("\n")
703
704 // ---------- T3 entity-component-sim (bit 6): stale handle refused, census exact ----------
705 checks=checks+1
706 var t3: i64=0
707 var stale: i64=0-1
708 if fk!=0 { stale = en_valid(a1b, fk) }
709 let alive: i64 = en_count(a1b)
710 let census: i64 = g1[F_SPAWNED] - g1[F_KILLS] - g1[F_ABAND]
711 if fk!=0 { if stale==0 { if alive==census {
712 ww("T3 GREEN entity store: first-killed monster's handle "); wn(fk)
713 ww(" is DETECTABLY STALE (en_valid=0); census exact: spawned "); wn(g1[F_SPAWNED])
714 ww(" - kills "); wn(g1[F_KILLS]); ww(" - abandoned-on-descend "); wn(g1[F_ABAND])
715 ww(" = alive "); wn(alive); ww("\n")
716 t3=1; pass=pass+1
717 mask=mask+nbit(6)
718 } } }
719 if t3==0 {
720 ww("T3 RED entity: firstkill="); wn(fk); ww(" stale-valid="); wn(stale)
721 ww(" alive="); wn(alive); ww(" census="); wn(census); ww("\n")
722 }
723
724 // ---------- T4 rpg-stats-progression (bit 9): curve honored, level inverse exact, hp derived ----------
725 checks=checks+1
726 let wantlvl: i64 = rs_level_for_xp(g1[F_XP], NH_XB, NH_XQ)
727 let maxhp: i64 = rs_derived_hp(NH_CON, g1[F_LVL], NH_HPB, NH_HPC, NH_HPL)
728 let thresh: i64 = rs_xp_for_level(g1[F_LVL], NH_XB, NH_XQ)
729 var t4: i64=0
730 if g1[F_XP]>0 { if g1[F_LVL]>1 { if g1[F_LVL]==wantlvl { if g1[F_HP]<=maxhp { if g1[F_XP]>=thresh {
731 ww("T4 GREEN rpgstats: xp "); wn(g1[F_XP]); ww(" -> level "); wn(g1[F_LVL])
732 ww(" == rs_level_for_xp EXACT (threshold "); wn(thresh); ww(" <= xp), hp "); wn(g1[F_HP])
733 ww(" <= derived max "); wn(maxhp); ww("\n")
734 t4=1; pass=pass+1
735 mask=mask+nbit(9)
736 } } } } }
737 if t4==0 {
738 ww("T4 RED rpgstats: xp="); wn(g1[F_XP]); ww(" lvl="); wn(g1[F_LVL])
739 ww(" want="); wn(wantlvl); ww(" hp="); wn(g1[F_HP]); ww(" maxhp="); wn(maxhp); ww("\n")
740 }
741
742 // ---------- T5 inventory-crafting (bit 11): the ledger conserves exactly ----------
743 checks=checks+1
744 // picked rations = held + eaten + 2*crafted ; crafted feasts = held + eaten
745 let led1: i64 = g1[F_RATION] + g1[F_EATR] + 2*g1[F_COMB]
746 let led2: i64 = g1[F_FEAST] + g1[F_EATF]
747 var t5: i64=0
748 if g1[F_PICKED]>=3 { if g1[F_USED]>=1 { if g1[F_COMB]>=1 {
749 if g1[F_PICKED]==led1 { if g1[F_COMB]==led2 {
750 ww("T5 GREEN inventory-crafting: picked "); wn(g1[F_PICKED]); ww(" == held ")
751 wn(g1[F_RATION]); ww(" + eaten "); wn(g1[F_EATR]); ww(" + 2*crafted "); wn(g1[F_COMB])
752 ww("; feasts "); wn(g1[F_COMB]); ww(" == held "); wn(g1[F_FEAST]); ww(" + eaten "); wn(g1[F_EATF])
753 ww(" (conserved, "); wn(g1[F_USED]); ww(" consumed)\n")
754 t5=1; pass=pass+1
755 mask=mask+nbit(11)
756 } }
757 } } }
758 if t5==0 {
759 ww("T5 RED inventory: picked="); wn(g1[F_PICKED]); ww(" led1="); wn(led1)
760 ww(" comb="); wn(g1[F_COMB]); ww(" led2="); wn(led2); ww(" used="); wn(g1[F_USED]); ww("\n")
761 }
762
763 // ---------- T6 save-load TRANSPARENCY (bit 15, FLAGSHIP) ----------
764 checks=checks+1
765 // run A: continuous 0..T2W, banking a checksum EVERY turn in the window T1W..T2W
766 let bank: *i64 = sys_mmap((NH_T2W-NH_T1W+2)*8) as *i64
767 nh_new(g1, SEED)
768 var t: i64=0
769 while t<NH_T1W { nh_tick(g1); t=t+1 }
770 // non-vacuity guard: the world at the save point must be NON-TRIVIAL
771 let g1a: *i64 = (g1 as i64 + NG_O_ENT*8) as *i64
772 let nv_alive: i64 = en_count(g1a)
773 let nv_xp: i64 = g1[F_XP]
774 let nv_picked: i64 = g1[F_PICKED]
775 let ckt1: i64 = nh_ck(g1)
776 bank[0]=ckt1
777 t=NH_T1W
778 while t<NH_T2W { nh_tick(g1); t=t+1; let c: i64 = nh_ck(g1); bank[t-NH_T1W]=c }
779 let contwin: i64 = g1[F_WIN]
780 // run B: fresh game to T1W, SAVE, load into a ZEROED arena, resume to T2W comparing every turn
781 nh_new(g2, SEED)
782 t=0
783 while t<NH_T1W { nh_tick(g2); t=t+1 }
784 nh_serialize(g2,S2)
785 let sr: i64 = gs_save("knowledge/nx_wire_nethack_mid.sav" as *u8, NH_SCHEMA, S2, NH_NSV, 20260720)
786 var zi: i64=0
787 while zi<NG_WORDS { g2[zi]=0; zi=zi+1 } // ZERO the whole arena: nothing survives but the file
788 let Sl: *i64 = sys_mmap(NH_NSV*8+64) as *i64
789 let lr: i64 = gs_load("knowledge/nx_wire_nethack_mid.sav" as *u8, Sl, NH_NSV, 0 as *i64)
790 nh_restore(g2, Sl)
791 let ckr: i64 = nh_ck(g2)
792 var mismatch: i64=0
793 if ckr!=bank[0] { mismatch=mismatch+1 }
794 t=NH_T1W
795 while t<NH_T2W {
796 nh_tick(g2)
797 t=t+1
798 let c2: i64 = nh_ck(g2)
799 if c2!=bank[t-NH_T1W] { mismatch=mismatch+1 }
800 }
801 // field-by-field final compare
802 nh_serialize(g1,S)
803 nh_serialize(g2,S2)
804 var fdiff: i64=0
805 i=0
806 while i<NH_NSV { if S[i]!=S2[i] { fdiff=fdiff+1 } i=i+1 }
807 var t6: i64=0
808 if sr>0 { if lr==NH_NSV { if mismatch==0 { if fdiff==0 { if nv_alive>=1 { if nv_xp>0 { if nv_picked>=1 { if contwin==0 {
809 ww("T6 GREEN save/load TRANSPARENT: save at turn "); wn(NH_T1W)
810 ww(" -> load into ZEROED arena -> resume to "); wn(NH_T2W)
811 ww(": all "); wn(NH_T2W-NH_T1W+1); ww(" per-turn checksums identical, 0/"); wn(NH_NSV)
812 ww(" state fields differ (non-trivial world: alive="); wn(nv_alive)
813 ww(" xp="); wn(nv_xp); ww(" picked="); wn(nv_picked); ww(")\n")
814 t6=1; pass=pass+1
815 mask=mask+nbit(15)
816 } } } } } } } }
817 if t6==0 {
818 ww("T6 RED transparency: save="); wn(sr); ww(" load="); wn(lr)
819 ww(" ck-mismatches="); wn(mismatch); ww(" field-diffs="); wn(fdiff)
820 ww(" alive="); wn(nv_alive); ww(" xp="); wn(nv_xp); ww(" picked="); wn(nv_picked)
821 ww(" contwin="); wn(contwin); ww("\n")
822 }
823
824 // ---------- T7 corruption refused, state untouched ----------
825 checks=checks+1
826 let lenp: *i64 = sys_mmap(8) as *i64
827 lenp[0]=0
828 let raw: *u8 = sys_read_file("knowledge/nx_wire_nethack_mid.sav" as *u8, lenp)
829 var t7: i64=0
830 if (raw as i64)!=0 {
831 let rl: i64 = lenp[0]
832 let flip: i64 = 48+24 // a payload byte (past the 48B header)
833 raw[flip] = (raw[flip] as i64 ^ 255) as u8
834 let cfd: i64 = sys_openat_wr("knowledge/nx_wire_nethack_corrupt.sav" as *u8, 0x1a4)
835 if cfd>=0 {
836 sys_write(cfd, raw, rl)
837 sys_close(cfd)
838 let Sc: *i64 = sys_mmap(NH_NSV*8+64) as *i64
839 Sc[0]=777777
840 let cr: i64 = gs_load("knowledge/nx_wire_nethack_corrupt.sav" as *u8, Sc, NH_NSV, 0 as *i64)
841 if cr==(0-6) { if Sc[0]==777777 { t7=1 } }
842 if t7==1 {
843 ww("T7 GREEN corruption refused LOUD (rc=-6 CHECKSUM-CORRUPT) and caller state untouched\n")
844 pass=pass+1
845 } else {
846 ww("T7 RED corrupt load rc="); wn(cr); ww(" sentinel="); wn(Sc[0]); ww("\n")
847 }
848 } else { ww("T7 RED cannot write corrupt copy\n") }
849 } else { ww("T7 RED cannot read the mid-save back\n") }
850
851 // ---------- T8 determinism: two independent full runs, bit-identical ----------
852 checks=checks+1
853 nh_new(g2, SEED)
854 nh_run_full(g2)
855 let fck2: i64 = nh_ck(g2)
856 var t8: i64=0
857 if fck==fck2 { if runwin==g2[F_WIN] {
858 ww("T8 GREEN deterministic: two independent full runs -> identical final checksum "); wn(fck)
859 ww(" at turn "); wn(g2[F_TURN]); ww("\n")
860 t8=1; pass=pass+1
861 } }
862 if t8==0 { ww("T8 RED run1 ck="); wn(fck); ww(" run2 ck="); wn(fck2); ww("\n") }
863
864 // ---------- T9 anti-vacuity: the LOOP is a real game that was actually played and WON ----------
865 checks=checks+1
866 var t9: i64=0
867 if g2[F_WIN]==1 { if g2[F_TURN]>20 { if g2[F_TURN]<NH_MAXT { if g2[F_KILLS]>=4 { if g2[F_DEPTH]==NH_DEPTH+1 { if g2[F_HP]>0 {
868 ww("T9 GREEN the game was PLAYED and WON: "); wn(NH_DEPTH); ww(" dungeon levels cleared in ")
869 wn(g2[F_TURN]); ww(" turns, "); wn(g2[F_KILLS]); ww(" kills, survived at hp "); wn(g2[F_HP]); ww("\n")
870 t9=1; pass=pass+1
871 } } } } } }
872 if t9==0 {
873 ww("T9 RED loop hollow: win="); wn(g2[F_WIN]); ww(" turns="); wn(g2[F_TURN])
874 ww(" kills="); wn(g2[F_KILLS]); ww(" depth="); wn(g2[F_DEPTH]); ww(" hp="); wn(g2[F_HP]); ww("\n")
875 }
876
877 // ---------- T10 ui-menus-hud (bit 18): menu CAUSES the eats; HUD binds live state per turn ----------
878 checks=checks+1
879 let hud2: *i64 = (g2 as i64 + NG_O_HUD*8) as *i64
880 let menusel: i64 = hud2[GH_F_NSEL]
881 let o10a: *i64 = sys_mmap(4*8) as *i64
882 let o10b: *i64 = sys_mmap(4*8) as *i64
883 let ch10a: i64 = nh_hudchain(SEED, NH_T2W, o10a)
884 let ch10b: i64 = nh_hudchain(SEED, NH_T2W, o10b)
885 var t10: i64=0
886 if ch10a==ch10b { if o10a[0]>=2 { if o10a[1]>=NH_HUDINK { if menusel>=1 { if menusel==g2[F_USED] {
887 ww("T10 GREEN ui-menus-hud: "); wn(menusel); ww(" eats ALL caused by menu selections (nsel==used), HUD ")
888 ww("render chain deterministic over "); wn(NH_T2W); ww(" turns ("); wn(o10a[0])
889 ww(" frame changes, "); wn(o10a[1]); ww(" ink px)\n")
890 t10=1; pass=pass+1
891 mask=mask+nbit(18)
892 } } } } }
893 if t10==0 {
894 ww("T10 RED ui-menus-hud: chA="); wn(ch10a); ww(" chB="); wn(ch10b)
895 ww(" changes="); wn(o10a[0]); ww(" ink="); wn(o10a[1])
896 ww(" nsel="); wn(menusel); ww(" used="); wn(g2[F_USED]); ww("\n")
897 }
898
899 // ---------- wiring evidence artifact: measured mask + run summary (board cross-checks payload[0]) ----------
900 let art: *i64 = sys_mmap(16*8) as *i64
901 art[0]=mask
902 art[1]=fck
903 art[2]=runturn
904 art[3]=runkills
905 art[4]=runxp
906 art[5]=runlvl
907 art[6]=NH_DEPTH
908 art[7]=runwin
909 let aw: i64 = gs_save("knowledge/nx_wire_nethack.sav" as *u8, NH_ART_SCHEMA, art, 8, 20260720)
910 ww("\nwiring artifact knowledge/nx_wire_nethack.sav bytes="); wn(aw)
911 ww(" exercised_mask="); wn(mask); ww(" (bits 3,7,6,9,11,15,18 when all their teeth pass)\n")
912
913 ww("\n=== nx_wire_nethack_gate "); wn(pass); ww("/"); wn(checks)
914 if pass==checks { ww(" verdict=GREEN ===\n"); return 0 }
915 ww(" RED ===\n")
916 return 1
917}