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}