code wiki / _hdl_build / nx_maze_gate.nx

nx_maze_gate.nx source

↩ module page · 76 lines · 5130 B

1// nx_maze_gate.nx -- GATE for the provably-solvable maze rung (procgen-solvable + gate-solvable + rules-engine). 2// Proves: a generated maze is a SPANNING TREE (every cell reachable BY CONSTRUCTION), the solver finds a 3// start->exit path, the solver DETECTS an unsolvable level (NEG-CONTROL: seal the exit -> UNSOLVABLE, so the 4// solvability gate is real, not a rubber-stamp -- the property that makes autonomous emission safe), generation 5// is DETERMINISTIC (same seed -> identical) and VARIES (different seed -> different maze), and the render is 6// sovereign (pure ASCII, 0 third-party). Emits knowledge/staging/game/maze.txt. license_tier: ORIGINAL expect_exit: 0 7import "nx_maze_gen.nx" 8import "nx_ad_serve.nx" 9import "nx_syscalls.nx" 10import "nx_gate_verdict.nx" 11 12func g_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 13func g_i(v: i64) -> i64 { let t: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0; if m == 0 { t[0]=48 as u8; k=1 } while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } let o: *u8=sys_mmap(24); var w: i64=0; var q: i64=k-1; while q>=0 { o[w]=t[q]; w=w+1; q=q-1 } sys_write(1,o,w); return 0 } 14func eqbytes(a: *u8, b: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } 15 16func main(argc: i64, argv: *i64) -> i64 { 17 g_p("=== nx_maze_gate (procgen-solvable + gate-solvable + rules-engine; pure-integer, sovereign) ===\n" as *u8) 18 let W: i64 = 8; let H: i64 = 8; let N: i64 = 64 19 let start: i64 = 0; let exit_c: i64 = N - 1 20 let cells: *u8 = sys_mmap(N); let cellsB: *u8 = sys_mmap(N); let cellsC: *u8 = sys_mmap(N) 21 let dist: *i64 = sys_mmap(8*N) as *i64; let queue: *i64 = sys_mmap(8*N) as *i64 22 var pass: i64 = 0; var tot: i64 = 0 23 24 // T1 SPANNING TREE: every cell reachable by construction 25 mz_gen(7, W, H, cells) 26 mz_solve(cells, W, H, start, exit_c, dist, queue) 27 let reach: i64 = mz_reachable(dist, N) 28 tot = tot + 1 29 if reach == N { pass = pass + 1; g_p("PASS T1 procgen-solvable: maze is a spanning tree -- all 64/64 cells reachable BY CONSTRUCTION\n" as *u8) } else { g_p("FAIL T1 reachable=" as *u8); g_i(reach); g_p("/64\n" as *u8) } 30 31 // T2 SOLVE: start->exit path exists with a real length 32 let d: i64 = mz_solve(cells, W, H, start, exit_c, dist, queue) 33 tot = tot + 1 34 if d >= 14 { pass = pass + 1; g_p("PASS T2 gate-solvable: solver found a start->exit path, length=" as *u8); g_i(d); g_p(" (>=14 manhattan floor)\n" as *u8) } else { g_p("FAIL T2 d=" as *u8); g_i(d); g_p("\n" as *u8) } 35 36 // T3 NEG-CONTROL: seal the exit -> solver MUST report UNSOLVABLE 37 mz_gen(7, W, H, cells) 38 mz_seal(cells, W, H, exit_c) 39 let dn: i64 = mz_solve(cells, W, H, start, exit_c, dist, queue) 40 tot = tot + 1 41 if dn == (0 - 1) { pass = pass + 1; g_p("PASS T3 neg-control: sealed exit -> solver reports UNSOLVABLE (-1) -- the solvability gate is REAL\n" as *u8) } else { g_p("FAIL T3 dn=" as *u8); g_i(dn); g_p(" (should be -1)\n" as *u8) } 42 43 // T4 DETERMINISM: same seed -> identical maze 44 mz_gen(7, W, H, cells); mz_gen(7, W, H, cellsB) 45 tot = tot + 1 46 if eqbytes(cells, cellsB, N) == 1 { pass = pass + 1; g_p("PASS T4 determinism: seed 7 -> byte-identical maze (reproducible emission)\n" as *u8) } else { g_p("FAIL T4\n" as *u8) } 47 48 // T5 VARIETY: different seed -> different maze (real generation) 49 mz_gen(99, W, H, cellsC) 50 tot = tot + 1 51 if eqbytes(cells, cellsC, N) == 0 { pass = pass + 1; g_p("PASS T5 variety: seed 7 vs 99 -> different mazes (real generation, not a constant)\n" as *u8) } else { g_p("FAIL T5 mazes identical\n" as *u8) } 52 53 // T6 SOVEREIGN RENDER: ASCII maze -> file; markers present; 0 third-party 54 mz_gen(7, W, H, cells) 55 let buf: *u8 = sys_mmap(2048) 56 let blen: i64 = mz_ascii(cells, W, H, start, exit_c, buf) 57 sys_mkdir("knowledge/staging/game" as *u8, 0x1ed) 58 let fd: i64 = sys_openat_wr("knowledge/staging/game/maze.txt" as *u8, 420); if fd >= 0 { sys_write(fd, buf, blen); sys_close(fd) } 59 tot = tot + 1; var ok6: i64 = 1 60 if as_contains(buf, blen, "S" as *u8) != 1 { ok6 = 0 } 61 if as_contains(buf, blen, "E" as *u8) != 1 { ok6 = 0 } 62 if as_contains(buf, blen, "#" as *u8) != 1 { ok6 = 0 } 63 if as_has_thirdparty_js(buf, blen) != 0 { ok6 = 0 } 64 if ok6 == 1 { pass = pass + 1; g_p("PASS T6 sovereign render: ASCII maze (S/E/# present) -> knowledge/staging/game/maze.txt, 0 third-party\n" as *u8) } else { g_p("FAIL T6\n" as *u8) } 65 66 g_p("nx_maze_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot) 67 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 68 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 69 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 70 let ctr__dry: *i64 = gv_ctr() 71 ctr__dry[0] = pass 72 ctr__dry[1] = tot 73 let rc__dry: i64 = gv_verdict("MAZE-GATE" as *u8, ctr__dry, "provably-solvable procedural puzzle rung; safe to AUTO-EMIT)" as *u8) 74 sys_exit(rc__dry) 75 return rc__dry 76}