code wiki / _hdl_build / nx_breeder_arena_gate.nx

nx_breeder_arena_gate.nx source

↩ module page · 214 lines · 11381 B

1// nx_breeder_arena_gate.nx -- proves the COMPOSED loop is a game: a player moving in a real world with 2// collision, wilds that hunt him, duels that resolve, capture that preserves identity, and breeding that 3// pays off -- winnable AND losable, bit-deterministic, with the world's invariants intact all run. 4// This is the gate that EARNS the gamebench physics-collision flip; without it that flip would be a claim. 5// MUTATION TARGET (documented): make the player invulnerable (BA_LOSS_HP=0) => the reckless policy can no 6// longer lose => stakes collapse => nx_game_depth caps the score below SHALLOW => T2 and T6 RED. 7// license_tier: ORIGINAL 8import "nx_syscalls.nx" 9import "nx_breeder_arena.nx" 10import "nx_game_depth.nx" 11 12func 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 pn(v: i64) -> i64 { 14 let t: *u8 = sys_mmap(32) as *u8 15 var m: i64 = v 16 var w: i64 = 0 17 if m < 0 { t[w] = 45 as u8; w = w + 1; m = 0 - m } 18 if m == 0 { t[w] = 48 as u8; sys_write(1, t, w + 1); return 0 } 19 let d: *u8 = sys_mmap(32) as *u8 20 var k: i64 = 0 21 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 22 var j: i64 = 0 23 while j < k { t[w] = d[k - 1 - j]; w = w + 1; j = j + 1 } 24 sys_write(1, t, w) 25 return 0 26} 27func nl() -> i64 { p("\n" as *u8); return 0 } 28 29const K: i64 = 4 // strategies scored by the depth critic (2 hunt, 2 reckless) 30 31func newG() -> *i64 { return sys_mmap(ba_words() * 8) as *i64 } 32func newBT() -> *i64 { let b: *i64 = sys_mmap((1 + 512*BRD_BEAT_STRIDE) * 8) as *i64; b[0] = 0; return b } 33func newEV() -> *i64 { let e: *i64 = sys_mmap((1 + 512*EV_STRIDE) * 8) as *i64; e[0] = 0; return e } 34 35func main() -> i64 { 36 p("=== nx_breeder_arena_gate (the composed loop IS a game) ===\n" as *u8) 37 var pass: i64 = 0 38 let checks: i64 = 7 39 40 // ---------- T1 WINNABLE: the hunt-and-breed policy reaches a BIRTH ---------- 41 var wins: i64 = 0 42 var best_captures: i64 = 0 43 var best_births: i64 = 0 44 var best_duels: i64 = 0 45 var winseed: i64 = 0-1 46 var sd: i64 = 1 47 while sd <= 24 { 48 let G: *i64 = newG() 49 let rc: i64 = ba_run(sd * 1013, 0, G, newBT(), 512, newEV(), 512) 50 if rc == 1 { 51 wins = wins + 1 52 if winseed < 0 { winseed = sd * 1013; best_captures = G[2]; best_duels = G[3]; best_births = G[4] } 53 } 54 sd = sd + 1 55 } 56 var t1: i64 = 0 57 if wins > 0 { if best_births > 0 { if best_captures >= BA_NEED_CAPTURES { t1 = 1 } } } 58 if t1 == 1 { pass = pass + 1; p("T1 GREEN WINNABLE: " as *u8); pn(wins); p("/24 seeds won under hunt-and-breed; the first win took " as *u8); pn(best_duels); p(" duels -> " as *u8); pn(best_captures); p(" captures -> " as *u8); pn(best_births); p(" birth\n" as *u8) } 59 if t1 == 0 { p("T1 RED wins=" as *u8); pn(wins); p(" births=" as *u8); pn(best_births); p(" captures=" as *u8); pn(best_captures); nl() } 60 61 // ---------- T2 LOSABLE: the reckless policy genuinely dies (a game you cannot lose is not a game) ---- 62 var losses: i64 = 0 63 var loss_duels: i64 = 0 64 var sd2: i64 = 1 65 while sd2 <= 24 { 66 let G: *i64 = newG() 67 let rc: i64 = ba_run(sd2 * 1013, 1, G, newBT(), 512, newEV(), 512) 68 if rc == 0-1 { losses = losses + 1; if loss_duels == 0 { loss_duels = G[3] } } 69 sd2 = sd2 + 1 70 } 71 var t2: i64 = 0 72 if losses > 0 { t2 = 1 } 73 if t2 == 1 { pass = pass + 1; p("T2 GREEN LOSABLE: " as *u8); pn(losses); p("/24 reckless runs ended in DEFEAT (player HP hit zero after " as *u8); pn(loss_duels); p(" duels)\n" as *u8) } 74 if t2 == 0 { p("T2 RED losses=" as *u8); pn(losses); nl() } 75 76 // ---------- T3 DETERMINISM: same seed+policy replays bit-exact (lockstep/replay/repro are free) ---- 77 let Ga: *i64 = newG() 78 let Gb: *i64 = newG() 79 let ra: i64 = ba_run(777001, 0, Ga, newBT(), 512, newEV(), 512) 80 let rb: i64 = ba_run(777001, 0, Gb, newBT(), 512, newEV(), 512) 81 var t3: i64 = 0 82 if Ga[5] == Gb[5] { if ra == rb { if Ga[3] == Gb[3] { if Ga[5] != 0 { if Ga[3] > 0 { t3 = 1 } } } } } 83 if t3 == 1 { pass = pass + 1; p("T3 GREEN deterministic: replay chain " as *u8); pn(Ga[5]); p(" bit-identical, same outcome, same " as *u8); pn(Ga[3]); p(" duels (non-vacuous: the world actually ran)\n" as *u8) } 84 if t3 == 0 { p("T3 RED cka=" as *u8); pn(Ga[5]); p(" ckb=" as *u8); pn(Gb[5]); nl() } 85 86 // ---------- T4 DIVERGENCE: different seeds produce genuinely different runs (not one scripted path) -- 87 let Gc: *i64 = newG() 88 ba_run(31337, 0, Gc, newBT(), 512, newEV(), 512) 89 var t4: i64 = 0 90 if Gc[5] != Ga[5] { t4 = 1 } 91 if t4 == 1 { pass = pass + 1; p("T4 GREEN seeds diverge: chain " as *u8); pn(Ga[5]); p(" vs " as *u8); pn(Gc[5]); p(" -- the world is generated, not replayed from one script\n" as *u8) } 92 if t4 == 0 { p("T4 RED seeds did not diverge\n" as *u8) } 93 94 // ---------- T5 BEATS ARE CAUSAL through the whole composed loop ---------- 95 // every SUBMIT must be preceded by a DOMINATE, every BIRTH by a MATE -- across a REAL run, not a unit test 96 let bt5: *i64 = newBT() 97 let G5: *i64 = newG() 98 ba_run(winseed, 0, G5, bt5, 512, newEV(), 512) 99 var causal: i64 = 1 100 var sawSub: i64 = 0 101 var sawBirth: i64 = 0 102 var sawWin: i64 = 0 103 var i5: i64 = 0 104 let nb: i64 = brd_beats(bt5) 105 while i5 < nb { 106 let k: i64 = brd_beat_kind(bt5, i5) 107 if k == BEAT_WIN { sawWin = 1 } 108 if k == BEAT_SUBMIT { 109 sawSub = 1 110 if i5 == 0 { causal = 0 } 111 if i5 > 0 { if brd_beat_kind(bt5, i5 - 1) != BEAT_DOMINATE { causal = 0 } } 112 } 113 if k == BEAT_BIRTH { 114 sawBirth = 1 115 if i5 == 0 { causal = 0 } 116 if i5 > 0 { if brd_beat_kind(bt5, i5 - 1) != BEAT_MATE { causal = 0 } } 117 } 118 i5 = i5 + 1 119 } 120 var t5: i64 = 0 121 if causal == 1 { if sawSub == 1 { if sawBirth == 1 { if sawWin == 1 { if nb > 4 { t5 = 1 } } } } } 122 if t5 == 1 { pass = pass + 1; p("T5 GREEN beats causal in a REAL run: " as *u8); pn(nb); p(" beats, every SUBMIT preceded by DOMINATE and every BIRTH by MATE\n" as *u8) } 123 if t5 == 0 { p("T5 RED causal=" as *u8); pn(causal); p(" sub=" as *u8); pn(sawSub); p(" birth=" as *u8); pn(sawBirth); p(" beats=" as *u8); pn(nb); nl() } 124 125 // ---------- T6 MECHANICAL DEPTH, measured by the hardened critic (not by my opinion) ---------- 126 // nx_game_depth needs TWO replays per strategy and CAPS to SHALLOW if they diverge (luck != skill) 127 // or if both a win and a loss are not reachable (unlosable == shallow by definition). 128 let s1: *i64 = sys_mmap(K * 8) as *i64 129 let s2: *i64 = sys_mmap(K * 8) as *i64 130 let res: *i64 = sys_mmap(K * 8) as *i64 131 // ★HONESTY GUARD (added after a mutation test caught this tooth being HOLLOW): gd_score only sees 132 // 1/0, so feeding it "timeout" as 0 would let an UNLOSABLE game still report stakes=1000. The tooth 133 // must therefore independently require a genuine DEFEAT (rc == -1) and a genuine WIN (rc == 1) among 134 // the scored strategies. Proven necessary: with BA_LOSS_HP=0 the old tooth stayed GREEN at 741. 135 var real_wins: i64 = 0 136 var real_defeats: i64 = 0 137 var pi: i64 = 0 138 while pi < K { 139 var policy: i64 = 0 140 if pi >= 2 { policy = 1 } 141 let seed: i64 = 4001 + pi * 977 142 let A: *i64 = newG() 143 let B: *i64 = newG() 144 let rA: i64 = ba_run(seed, policy, A, newBT(), 512, newEV(), 512) 145 let rB: i64 = ba_run(seed, policy, B, newBT(), 512, newEV(), 512) 146 // score a run by what it achieved: captures and births are the objective 147 s1[pi] = A[2] * 100 + A[4] * 500 + A[3] * 10 148 s2[pi] = B[2] * 100 + B[4] * 500 + B[3] * 10 149 res[pi] = 0 150 if rA == 1 { res[pi] = 1; real_wins = real_wins + 1 } 151 if rA == 0-1 { real_defeats = real_defeats + 1 } 152 pi = pi + 1 153 } 154 let dout: *i64 = sys_mmap(GD_N * 8) as *i64 155 gd_score(s1, s2, res, K, dout) 156 let depth: i64 = gd_quality(dout) 157 var t6: i64 = 0 158 if depth >= GD_SHALLOW { if dout[GD_M_DET] == 1000 { if dout[GD_M_STAKES] == 1000 { 159 if real_wins > 0 { if real_defeats > 0 { t6 = 1 } } 160 } } } 161 if t6 == 1 { pass = pass + 1; p("T6 GREEN mechanical depth MEASURED: " as *u8); pn(depth); p(" = " as *u8); p(gd_verdict(depth)); p(" (determinism " as *u8); pn(dout[GD_M_DET]); p(", stakes " as *u8); pn(dout[GD_M_STAKES]); p("; " as *u8); pn(real_wins); p(" genuine wins and " as *u8); pn(real_defeats); p(" genuine DEFEATS -- not timeouts)\n" as *u8) } 162 if t6 == 0 { p("T6 RED depth=" as *u8); pn(depth); p(" det=" as *u8); pn(dout[GD_M_DET]); p(" stakes=" as *u8); pn(dout[GD_M_STAKES]); p(" real_wins=" as *u8); pn(real_wins); p(" real_defeats=" as *u8); pn(real_defeats); nl() } 163 164 // ---------- T7 WORLD INVARIANT + ANTI-VACUITY: occupancy consistent, and the world actually MOVED ---- 165 // Re-run one game step-by-step so we can assert ac_occ_check after every tick, not just at the end. 166 let wd7: *i64 = sys_mmap(wd_bytes(BA_W, BA_H)) as *i64 167 ba_world_build(wd7) 168 let ar7: *i64 = sys_mmap(en_bytes(32, AC_NC)) as *i64 169 en_init(ar7, 32, AC_NC) 170 let rosP7: *i64 = sys_mmap(en_bytes(64, COMP_NC)) as *i64 171 en_init(rosP7, 64, COMP_NC) 172 let rosW7: *i64 = sys_mmap(en_bytes(64, COMP_NC)) as *i64 173 en_init(rosW7, 64, COMP_NC) 174 let tbl7: *i64 = sys_mmap(64 * 8) as *i64 175 ag_species_default(tbl7) 176 let btbl7: *i64 = sys_mmap(64 * 8) as *i64 177 brd_species_default(btbl7) 178 let scr7: *i64 = sys_mmap(ag_scratch_words(BA_W, BA_H) * 8) as *i64 179 let buf7: *u8 = sys_mmap(65536) as *u8 180 let out7: *i64 = sys_mmap(64) as *i64 181 let G7: *i64 = newG() 182 var gi: i64 = 0 183 while gi < ba_words() { G7[gi] = 0; gi = gi + 1 } 184 G7[5] = 1469598103 185 G7[6] = ac_spawn(wd7, ar7, 12, 13, 0, BA_PLAYER_HP, 0, 5, 5150) 186 let sh7: i64 = en_spawn(rosP7) 187 en_set(rosP7, sh7, C_SPEC, 1) 188 en_set(rosP7, sh7, C_IV0, 22); en_set(rosP7, sh7, C_IV1, 24) 189 en_set(rosP7, sh7, C_IV2, 20); en_set(rosP7, sh7, C_IV3, 23) 190 en_set(rosP7, sh7, C_XP, 0); en_set(rosP7, sh7, C_LVL, 6); en_set(rosP7, sh7, C_NICK, 0) 191 G7[7] = sh7 192 ba_seed_wilds(wd7, ar7, rosW7, G7, 5150) 193 let px0: i64 = en_get(ar7, G7[6], A_X) 194 let py0: i64 = en_get(ar7, G7[6], A_Y) 195 var violations: i64 = 0 196 var moved_player: i64 = 0 197 var t7t: i64 = 0 198 while t7t < 200 { 199 ba_tick(wd7, ar7, rosP7, rosW7, G7, tbl7, scr7, newEV(), 512, newBT(), 512, buf7, 0, out7) 200 if ac_occ_check(wd7, ar7) != 0 { violations = violations + 1 } 201 if en_get(ar7, G7[6], A_X) != px0 { moved_player = 1 } 202 if en_get(ar7, G7[6], A_Y) != py0 { moved_player = 1 } 203 t7t = t7t + 1 204 } 205 var t7: i64 = 0 206 if violations == 0 { if moved_player == 1 { if G7[3] > 0 { t7 = 1 } } } 207 if t7 == 1 { pass = pass + 1; p("T7 GREEN world invariant held every tick of 200 (0 occupancy violations) and the run was non-vacuous: player moved, " as *u8); pn(G7[3]); p(" duels fought\n" as *u8) } 208 if t7 == 0 { p("T7 RED violations=" as *u8); pn(violations); p(" moved=" as *u8); pn(moved_player); p(" duels=" as *u8); pn(G7[3]); nl() } 209 210 p("nx_breeder_arena_gate: " as *u8); pn(pass); p("/" as *u8); pn(checks); nl() 211 if pass == checks { p("VERDICT GREEN\n" as *u8); return 0 } 212 p("VERDICT RED\n" as *u8) 213 return 1 214}