code wiki / _hdl_build / nx_charjudge_gate.nx

nx_charjudge_gate.nx source

↩ module page · 277 lines · 10048 B

1// nx_charjudge_gate.nx -- the LIAR-KILLER battery for the v2 character judge, all fixtures SYNTHETIC + 2// deterministic (no file deps): a composed "character" (smooth bg + textured figure + border contours + 3// face patch with an eye pair), its eyeless twin, a flat blob, an aligned-16px patch-scramble of the 4// composed image, and the smooth+noise+palette COLLAGE that games v1. Teeth assert the HUMAN ordering, 5// per-axis kills, determinism, and the conf override path. Designing this battery already killed two 6// contour-axis designs before they shipped (plain run-length: dense noise is fully connected; scramble 7// seams are long lines) -- that is the gate doing its job at design time. license_tier: ORIGINAL expect_exit: 0 8import "nx_syscalls.nx" 9import "nx_charjudge_lib.nx" 10const CHG_W: i64 = 256 11const CHG_H: i64 = 256 12const CHG_LCG_A: i64 = 1103515245 13const CHG_LCG_C: i64 = 12345 14const CHG_LCG_M: i64 = 2147483647 15 16func gw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 17func gn(v: i64) -> i64 { 18 let b: *u8 = sys_mmap(32) 19 var x: i64 = v; var ng: i64 = 0 20 if x < 0 { ng = 1; x = 0-x } 21 var i: i64 = 31 22 if x == 0 { b[i]=48 as u8; i=i-1 } 23 while x > 0 { b[i]=(48+x%10) as u8; x=x/10; i=i-1 } 24 if ng == 1 { b[i]=45 as u8; i=i-1 } 25 sys_write(1,(b as i64+i+1) as *u8,31-i) 26 return 0 27} 28func chg_px(r: i64, g: i64, b: i64) -> i64 { 29 var r2: i64 = r 30 var g2: i64 = g 31 var b2: i64 = b 32 if r2 < 0 { r2 = 0 } 33 if r2 > 255 { r2 = 255 } 34 if g2 < 0 { g2 = 0 } 35 if g2 > 255 { g2 = 255 } 36 if b2 < 0 { b2 = 0 } 37 if b2 > 255 { b2 = 255 } 38 return r2 + g2*256 + b2*CHJ_MAGIC_65536 39} 40// composed character fixture. eyes=1 draws the eye pair. 41func chg_composed(fb: *i64, eyes: i64) -> i64 { 42 var s: i64 = 777 43 var y: i64 = 0 44 while y < CHG_H { 45 var x: i64 = 0 46 while x < CHG_W { 47 fb[y*CHG_W+x] = chg_px(40 + y, 80 + y/2, 250 - y/2) 48 x = x + 1 49 } 50 y = y + 1 51 } 52 y = 48 53 while y < 224 { 54 var x: i64 = 64 55 while x < 192 { 56 s = (s*CHG_LCG_A + CHG_LCG_C) & CHG_LCG_M 57 let nz: i64 = (s>>15) % 51 - 25 58 fb[y*CHG_W+x] = chg_px(60 + y%128 + nz, 50 + (x+y)%150 + nz, 90 + x%120 + nz) 59 x = x + 1 60 } 61 y = y + 1 62 } 63 // face patch (flat skin) so the eyes are the only compact dark blobs there 64 y = 64 65 while y < 120 { 66 var x: i64 = 96 67 while x < 176 { 68 fb[y*CHG_W+x] = chg_px(230, 200, 180) 69 x = x + 1 70 } 71 y = y + 1 72 } 73 if eyes == 1 { 74 var ey: i64 = 0-3 75 while ey <= 3 { 76 var ex: i64 = 0-3 77 while ex <= 3 { 78 if ex*ex + ey*ey <= 9 { 79 fb[(89+ey)*CHG_W + 113+ex] = chg_px(25, 20, 20) 80 fb[(89+ey)*CHG_W + 145+ex] = chg_px(25, 20, 20) 81 } 82 ex = ex + 1 83 } 84 ey = ey + 1 85 } 86 } 87 // 2px dark border = the long contours 88 y = 48 89 while y < 224 { 90 fb[y*CHG_W+64] = chg_px(30,30,40) 91 fb[y*CHG_W+65] = chg_px(30,30,40) 92 fb[y*CHG_W+190] = chg_px(30,30,40) 93 fb[y*CHG_W+191] = chg_px(30,30,40) 94 y = y + 1 95 } 96 var x5: i64 = 64 97 while x5 < 192 { 98 fb[48*CHG_W+x5] = chg_px(30,30,40) 99 fb[49*CHG_W+x5] = chg_px(30,30,40) 100 fb[222*CHG_W+x5] = chg_px(30,30,40) 101 fb[223*CHG_W+x5] = chg_px(30,30,40) 102 x5 = x5 + 1 103 } 104 return 0 105} 106func chg_blob(fb: *i64) -> i64 { 107 var y: i64 = 0 108 while y < CHG_H { 109 var x: i64 = 0 110 while x < CHG_W { 111 fb[y*CHG_W+x] = chg_px(40 + y, 80 + y/2, 250 - y/2) 112 x = x + 1 113 } 114 y = y + 1 115 } 116 y = 48 117 while y < 224 { 118 var x: i64 = 64 119 while x < 192 { 120 fb[y*CHG_W+x] = chg_px(200, 170, 150) 121 x = x + 1 122 } 123 y = y + 1 124 } 125 y = 48 126 while y < 224 { 127 fb[y*CHG_W+64] = chg_px(30,30,40) 128 fb[y*CHG_W+191] = chg_px(30,30,40) 129 y = y + 1 130 } 131 var x6: i64 = 64 132 while x6 < 192 { 133 fb[48*CHG_W+x6] = chg_px(30,30,40) 134 fb[223*CHG_W+x6] = chg_px(30,30,40) 135 x6 = x6 + 1 136 } 137 return 0 138} 139func chg_scramble(src: *i64, dst: *i64) -> i64 { 140 let P: i64 = 16 141 let nx: i64 = CHG_W/P 142 let ny: i64 = CHG_H/P 143 let n: i64 = nx*ny 144 let perm: *i64 = sys_mmap(n*8) as *i64 145 var i: i64 = 0 146 while i < n { perm[i] = i; i = i + 1 } 147 var s: i64 = 80404 148 i = n - 1 149 while i > 0 { 150 s = (s*CHG_LCG_A + CHG_LCG_C) & CHG_LCG_M 151 let j: i64 = s % (i+1) 152 let t: i64 = perm[i]; perm[i] = perm[j]; perm[j] = t 153 i = i - 1 154 } 155 i = 0 156 while i < n { 157 let src2: i64 = perm[i] 158 let dx: i64 = (i%nx)*P 159 let dy: i64 = (i/nx)*P 160 let sx: i64 = (src2%nx)*P 161 let sy: i64 = (src2/nx)*P 162 var yy: i64 = 0 163 while yy < P { 164 var xx: i64 = 0 165 while xx < P { dst[(dy+yy)*CHG_W + dx+xx] = src[(sy+yy)*CHG_W + sx+xx]; xx = xx + 1 } 166 yy = yy + 1 167 } 168 i = i + 1 169 } 170 return 0 171} 172func chg_collage(fb: *i64) -> i64 { 173 var s: i64 = 4242 174 var y: i64 = 0 175 while y < CHG_H { 176 var x: i64 = 0 177 while x < CHG_W { 178 if x < CHG_W/2 { fb[y*CHG_W+x] = chg_px(120, 140, 160) } 179 if x >= CHG_W/2 { 180 // high bits: an LCG's LOW bits have period 2^k -- s%256 gave PERIODIC stripes, i.e. 181 // real coherent contours, and the "noise" collage wasn't noise (gate T4 caught it) 182 s = (s*CHG_LCG_A + CHG_LCG_C) & CHG_LCG_M 183 let r: i64 = (s>>15) % 256 184 s = (s*CHG_LCG_A + CHG_LCG_C) & CHG_LCG_M 185 let g: i64 = (s>>15) % 256 186 s = (s*CHG_LCG_A + CHG_LCG_C) & CHG_LCG_M 187 let b: i64 = (s>>15) % 256 188 fb[y*CHG_W+x] = chg_px(r, g, b) 189 } 190 x = x + 1 191 } 192 y = y + 1 193 } 194 return 0 195} 196func tooth(name: *u8, ok: i64, fails: *i64) -> i64 { 197 if ok == 1 { gw("PASS " as *u8) } 198 if ok != 1 { gw("FAIL " as *u8); fails[0] = fails[0] + 1 } 199 gw(name) 200 gw("\n" as *u8) 201 return 0 202} 203 204func main() -> i64 { 205 gw("=== nx_charjudge_gate -- liar-killer battery for the v2 character judge ===\n" as *u8) 206 let fails: *i64 = sys_mmap(16) as *i64 207 fails[0] = 0 208 let npx: i64 = CHG_W*CHG_H 209 let fA: *i64 = sys_mmap(npx*8) as *i64 210 let fB: *i64 = sys_mmap(npx*8) as *i64 211 let fS: *i64 = sys_mmap(npx*8) as *i64 212 let fC: *i64 = sys_mmap(npx*8) as *i64 213 let fE: *i64 = sys_mmap(npx*8) as *i64 214 chg_composed(fA, 1) 215 chg_blob(fB) 216 chg_scramble(fA, fS) 217 chg_collage(fC) 218 chg_composed(fE, 0) 219 let oA: *i64 = sys_mmap(96) as *i64 220 let oA2: *i64 = sys_mmap(96) as *i64 221 let oB: *i64 = sys_mmap(96) as *i64 222 let oS: *i64 = sys_mmap(96) as *i64 223 let oC: *i64 = sys_mmap(96) as *i64 224 let oE: *i64 = sys_mmap(96) as *i64 225 let cp: *u8 = "knowledge/charjudge.conf" as *u8 226 chj_judge(fA, CHG_W, CHG_H, cp, oA) 227 chj_judge(fA, CHG_W, CHG_H, cp, oA2) 228 chj_judge(fB, CHG_W, CHG_H, cp, oB) 229 chj_judge(fS, CHG_W, CHG_H, cp, oS) 230 chj_judge(fC, CHG_W, CHG_H, cp, oC) 231 chj_judge(fE, CHG_W, CHG_H, cp, oE) 232 gw("composed: head=" as *u8); gn(oA[4]); gw(" comp=" as *u8); gn(oA[0]); gw(" pal=" as *u8); gn(oA[1]); gw(" con=" as *u8); gn(oA[2]); gw(" face=" as *u8); gn(oA[3]); gw("\n" as *u8) 233 gw("blob: head=" as *u8); gn(oB[4]); gw(" comp=" as *u8); gn(oB[0]); gw(" face=" as *u8); gn(oB[3]); gw("\n" as *u8) 234 gw("scramble: head=" as *u8); gn(oS[4]); gw(" comp=" as *u8); gn(oS[0]); gw(" con=" as *u8); gn(oS[2]); gw("\n" as *u8) 235 gw("collage: head=" as *u8); gn(oC[4]); gw(" comp=" as *u8); gn(oC[0]); gw(" con=" as *u8); gn(oC[2]); gw("\n" as *u8) 236 gw("eyeless: head=" as *u8); gn(oE[4]); gw(" face=" as *u8); gn(oE[3]); gw("\n" as *u8) 237 var t: i64 = 0 238 if oA[4] >= 600 { t = 1 } 239 tooth("T1 composed character scores >= 600" as *u8, t, fails) 240 t = 0 241 if oB[3] == 0 { if oB[4] == 0 { t = 1 } } 242 tooth("T2 faceless flat blob floors to 0 (face axis)" as *u8, t, fails) 243 // a 16px-grid scramble GENUINELY contains long straight seam lines, so contour cannot floor it to 244 // zero -- the honest claim is a deep drop below the composed original (real-content scrambles 245 // measured 20/1000 on the kk portrait; this synthetic bg has gentler seams) 246 t = 0 247 if oS[4] < 300 { if oS[4]*3 < oA[4] { t = 1 } } 248 tooth("T3 16px scramble drops below 300 and below composed/3" as *u8, t, fails) 249 t = 0 250 if oC[2] < 100 { if oC[4] < 100 { t = 1 } } 251 tooth("T4 smooth+noise+palette collage floors (contour kills the v1 gameable vector)" as *u8, t, fails) 252 t = 0 253 if oE[3] == 0 { if oE[4] == 0 { if oA[3] == 1000 { t = 1 } } } 254 tooth("T5 face axis isolated: eyeless twin 0, eyed twin 1000" as *u8, t, fails) 255 t = 0 256 if oA[4] == oA2[4] { t = 1 } 257 tooth("T6 deterministic (same fixture twice, same headline)" as *u8, t, fails) 258 // T7: conf override path -- face_required=0 lifts the eyeless twin off the floor 259 let cfd: i64 = sys_openat_wr("/tmp/chj_face_off.conf" as *u8, 0x1a4) 260 let cstr: *u8 = "face_required=0\n" as *u8 261 var cn: i64 = 0 262 while cstr[cn] != (0 as u8) { cn = cn + 1 } 263 sys_write(cfd, cstr, cn) 264 sys_close(cfd) 265 let oE2: *i64 = sys_mmap(96) as *i64 266 chj_judge(fE, CHG_W, CHG_H, "/tmp/chj_face_off.conf" as *u8, oE2) 267 t = 0 268 if oE2[4] > 0 { t = 1 } 269 tooth("T7 conf override proven live (face_required=0 lifts the eyeless twin)" as *u8, t, fails) 270 t = 0 271 if oA[4] > oB[4] { if oA[4] > oS[4] { if oA[4] > oC[4] { t = 1 } } } 272 tooth("T8 strict ordering: composed above blob, scramble, collage" as *u8, t, fails) 273 if fails[0] == 0 { gw("CHARJUDGE-GATE GREEN 8/8\n" as *u8); sys_exit(0); return 0 } 274 gw("CHARJUDGE-GATE RED fails=" as *u8); gn(fails[0]); gw("\n" as *u8) 275 sys_exit(1) 276 return 1 277}