code wiki / _hdl_build / nx_plotgen_gate.nx

nx_plotgen_gate.nx source

↩ module page · 201 lines · 8570 B

1// nx_plotgen_gate.nx -- CERTIFICATION of nx_plotgen (gamebench hard GAP; the operator's "our own plot generator"). 2// T1 STRUCTURAL VALIDITY -- every choice target is in range, forward-only (acyclic), endings marked 3// T2 ★SOLVABILITY ACROSS 200 SEEDS -- the graph is WALKED with the real sv_choose from nx_story_vm and must 4// reach an ending every time. This is the unwinnable-quest killer, proven by execution not inspection. 5// T3 NO DEAD ENDS -- every non-ending node offers at least one choice 6// T4 DETERMINISM -- same seed -> byte-identical plot (a story is reproducible from its seed) 7// T5 VARIETY -- different seeds -> materially different plots (not one template) 8// T6 GATES ARE REAL -- generated plots actually contain flag-gated choices; without this, solvability 9// would be trivially satisfied by emitting an ungated linear chain 10// T7 ★ANTI-VACUITY -- a gated choice is GENUINELY BLOCKED when its flag is missing. Proves the gating is 11// enforced rather than decorative, and that T2 passes on merit rather than because nothing gates. 12// T8 composes: runs on nx_story_vm and the plot DATA round-trips through nx_gamesave 13// license_tier: ORIGINAL expect_exit: 0 14import "nx_syscalls.nx" 15import "nx_plotgen.nx" 16import "nx_gamesave.nx" 17 18func pw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 19func pn(v: i64) -> i64 { 20 if v==0 { sys_write(1,"0" as *u8,1); return 0 } 21 var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m } 22 let t: *u8=sys_mmap(32); var k: i64=0 23 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 24 let o: *u8=sys_mmap(32); var q: i64=k-1; var i: i64=0 25 while q>=0 { o[i]=t[q]; i=i+1; q=q-1 } 26 sys_write(1,o,i); return 0 27} 28 29func main() -> i64 { 30 pw("=== nx_plotgen_gate: can the generator emit a plot that is always winnable? ===\n\n") 31 var pass: i64 = 0 32 var checks: i64 = 0 33 let N: i64 = 24 34 let CH: i64 = N*SV_NCH 35 36 let tg: *i64 = sys_mmap(CH*8) as *i64 37 let rq: *i64 = sys_mmap(CH*8) as *i64 38 let sf: *i64 = sys_mmap(CH*8) as *i64 39 let ie: *i64 = sys_mmap(N*8) as *i64 40 41 // ---------- T1 structural validity ---------- 42 checks = checks + 1 43 let gated0: i64 = pg_gen(tg, rq, sf, ie, N, 20260720) 44 var bad: i64 = 0 45 var backward: i64 = 0 46 var i: i64 = 0 47 while i < N { 48 var c: i64 = 0 49 while c < SV_NCH { 50 let t: i64 = tg[i*SV_NCH + c] 51 if t != 0-1 { 52 if t < 0 { bad = bad + 1 } 53 if t >= N { bad = bad + 1 } 54 if t <= i { backward = backward + 1 } // forward-only => acyclic => always terminates 55 } 56 c = c + 1 57 } 58 i = i + 1 59 } 60 if bad==0 { if backward==0 { if ie[N-1]==1 { 61 pw("T1 GREEN structural: all targets in range, forward-only (acyclic), ending marked at node ") 62 pn(N-1); pw("\n"); pass=pass+1 63 } } } 64 if bad>0 { pw("T1 RED "); pn(bad); pw(" out-of-range targets\n") } 65 if bad==0 { if backward>0 { pw("T1 RED "); pn(backward); pw(" backward edges -- graph may cycle\n") } } 66 67 // ---------- T2 solvability across 200 seeds ---------- 68 checks = checks + 1 69 var solved: i64 = 0 70 var trials: i64 = 0 71 var totalgated: i64 = 0 72 var s: i64 = 1 73 while s <= 200 { 74 totalgated = totalgated + pg_gen(tg, rq, sf, ie, N, s*7919) 75 let endnode: i64 = pg_walk(tg, rq, sf, ie, N, N*4) 76 if endnode >= 0 { if sv_is_end(ie, endnode)==1 { solved = solved + 1 } } 77 trials = trials + 1 78 s = s + 1 79 } 80 if solved==trials { 81 pw("T2 GREEN solvability: "); pn(solved); pw("/"); pn(trials) 82 pw(" generated plots WALKED to an ending via the real sv_choose (0 unwinnable), ") 83 pn(totalgated); pw(" gated choices total\n"); pass=pass+1 84 } else { 85 pw("T2 RED "); pn(trials-solved); pw("/"); pn(trials); pw(" plots were UNWINNABLE\n") 86 } 87 88 // ---------- T3 no dead ends ---------- 89 checks = checks + 1 90 pg_gen(tg, rq, sf, ie, N, 4242) 91 var dead: i64 = 0 92 i = 0 93 while i < N { 94 if ie[i]==0 { 95 var any: i64 = 0 96 var c: i64 = 0 97 while c < SV_NCH { if tg[i*SV_NCH + c] != 0-1 { any = 1 } c = c + 1 } 98 if any==0 { dead = dead + 1 } 99 } 100 i = i + 1 101 } 102 if dead==0 { 103 pw("T3 GREEN no dead ends: every non-ending node offers at least one choice\n"); pass=pass+1 104 } else { pw("T3 RED "); pn(dead); pw(" dead-end nodes\n") } 105 106 // ---------- T4 determinism ---------- 107 checks = checks + 1 108 let tg2: *i64 = sys_mmap(CH*8) as *i64 109 let rq2: *i64 = sys_mmap(CH*8) as *i64 110 let sf2: *i64 = sys_mmap(CH*8) as *i64 111 let ie2: *i64 = sys_mmap(N*8) as *i64 112 pg_gen(tg, rq, sf, ie, N, 31337) 113 pg_gen(tg2, rq2, sf2, ie2, N, 31337) 114 var det: i64 = 1 115 i = 0 116 while i < CH { 117 if tg[i]!=tg2[i] { det=0 } 118 if rq[i]!=rq2[i] { det=0 } 119 if sf[i]!=sf2[i] { det=0 } 120 i = i + 1 121 } 122 i = 0 123 while i < N { if ie[i]!=ie2[i] { det=0 } i=i+1 } 124 if det==1 { 125 pw("T4 GREEN deterministic: seed 31337 twice -> identical plot (a story is reproducible from its seed)\n") 126 pass=pass+1 127 } else { pw("T4 RED same seed produced different plots\n") } 128 129 // ---------- T5 variety ---------- 130 checks = checks + 1 131 pg_gen(tg2, rq2, sf2, ie2, N, 90210) 132 var diff: i64 = 0 133 i = 0 134 while i < CH { if tg[i]!=tg2[i] { diff = diff + 1 } i=i+1 } 135 if diff > 8 { 136 pw("T5 GREEN variety: a different seed changed "); pn(diff) 137 pw(" of "); pn(CH); pw(" choice slots -- not one template\n"); pass=pass+1 138 } else { pw("T5 RED seeds barely differ ("); pn(diff); pw(" slots) -- generator is a template\n") } 139 140 // ---------- T6 gates are real ---------- 141 checks = checks + 1 142 pg_gen(tg, rq, sf, ie, N, 555) 143 var ngate: i64 = 0 144 i = 0 145 while i < CH { if rq[i] > 0 { ngate = ngate + 1 } i=i+1 } 146 if ngate > 0 { 147 pw("T6 GREEN gates are real: "); pn(ngate) 148 pw(" flag-gated choices in this plot -- solvability is not trivially satisfied by a linear chain\n") 149 pass=pass+1 150 } else { pw("T6 RED no gated choices generated -- T2 would be vacuous\n") } 151 152 // ---------- T7 anti-vacuity: a gate genuinely BLOCKS ---------- 153 checks = checks + 1 154 // find a gated choice and try it with EMPTY flags -- sv_choose must refuse it 155 var gi: i64 = 0-1 156 i = 0 157 while i < CH { if rq[i] > 0 { if gi < 0 { gi = i } } i=i+1 } 158 var t7: i64 = 0 159 if gi >= 0 { 160 let node: i64 = gi / SV_NCH 161 let cho: i64 = gi % SV_NCH 162 let flags: *i64 = sys_mmap(8) as *i64 163 flags[0] = 0 // no flags raised 164 let blocked: i64 = sv_choose(tg, rq, sf, node, cho, flags) 165 flags[0] = rq[gi] // exactly the required bits 166 let allowed: i64 = sv_choose(tg, rq, sf, node, cho, flags) 167 if blocked == 0-1 { if allowed >= 0 { t7 = 1 } } 168 if t7==1 { 169 pw("T7 GREEN anti-vacuity: gated choice at node "); pn(node); pw(" REFUSED without its flag (-1) and ") 170 pw("ALLOWED with it (-> node "); pn(allowed); pw(") -- gating is enforced, not decorative\n") 171 pass=pass+1 172 } else { 173 pw("T7 RED gate not enforced: blocked="); pn(blocked); pw(" allowed="); pn(allowed); pw("\n") 174 } 175 } else { pw("T7 RED no gated choice found to test\n") } 176 177 // ---------- T8 composes: story_vm execution + gamesave round-trip ---------- 178 checks = checks + 1 179 let PP: *u8 = "knowledge/nx_plotgen_story.sav" as *u8 180 sys_unlinkat(PP) 181 pg_gen(tg, rq, sf, ie, N, 777001) 182 let endn: i64 = pg_walk(tg, rq, sf, ie, N, N*4) 183 let wrote: i64 = gs_save(PP, 70707, tg, CH, 1784580000) 184 let rd: *i64 = sys_mmap(CH*8) as *i64 185 let got: i64 = gs_load(PP, rd, CH, 0 as *i64) 186 var t8: i64 = 1 187 if got != CH { t8 = 0 } 188 if wrote <= 0 { t8 = 0 } 189 if endn < 0 { t8 = 0 } 190 i = 0 191 while i < CH { if rd[i]!=tg[i] { t8=0 } i=i+1 } 192 if t8==1 { 193 pw("T8 GREEN composes: plot ran on nx_story_vm to ending node "); pn(endn) 194 pw(" and its graph round-tripped through nx_gamesave ("); pn(wrote); pw("B)\n"); pass=pass+1 195 } else { pw("T8 RED compose failed: end="); pn(endn); pw(" rc="); pn(got); pw("\n") } 196 197 pw("\n=== nx_plotgen_gate "); pn(pass); pw("/"); pn(checks) 198 if pass == checks { pw(" verdict=GREEN ===\n"); return 0 } 199 pw(" RED ===\n") 200 return 1 201}