code wiki / _hdl_build / nx_worldsim_gate.nx

nx_worldsim_gate.nx source

↩ module page · 226 lines · 9336 B

1// nx_worldsim_gate.nx -- CERTIFICATION of nx_worldsim (gamebench rank 1, hard GAP, Strive:Conquest keystone). 2// T1 ★CONSERVATION -- 500 randomised trades move wealth without minting or burning a single unit 3// T2 ★SYMMETRIC RELATIONS -- rel(A,B) and rel(B,A) can never disagree, after arbitrary one-sided edits 4// T3 ACCOUNTED PRODUCTION -- a tick adds EXACTLY ws_production(), no more, no less 5// T4 DETERMINISM -- two worlds, same seed, 200 ticks -> identical state 6// T5 BOUNDED -- relations clamp to [-1000,1000]; resources never go negative; overdraw is refused 7// T6 NO SELF-DEALING -- a faction cannot trade with itself or edit its own relation 8// T7 ★ANTI-VACUITY -- the world actually EVOLVES (wealth grows, relations move). A frozen world would 9// satisfy conservation, symmetry and determinism perfectly while simulating nothing. 10// T8 composes with nx_gamesave: a whole world arena round-trips through save/load 11// license_tier: ORIGINAL expect_exit: 0 12import "nx_syscalls.nx" 13import "nx_worldsim.nx" 14import "nx_gamesave.nx" 15import "nx_gate_verdict.nx" 16 17func ww(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 18func wn(v: i64) -> i64 { 19 if v==0 { sys_write(1,"0" as *u8,1); return 0 } 20 var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m } 21 let t: *u8=sys_mmap(32); var k: i64=0 22 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 23 let o: *u8=sys_mmap(32); var q: i64=k-1; var i: i64=0 24 while q>=0 { o[i]=t[q]; i=i+1; q=q-1 } 25 sys_write(1,o,i); return 0 26} 27func seedworld(a: *i64, n: i64, seed: i64) -> i64 { 28 ws_init(a, n, seed) 29 var i: i64 = 0 30 while i < n { 31 ws_set_res(a, i, 1000 + i*250) 32 ws_set_pop(a, i, 500 + i*100) 33 ws_set_terr(a, i, 3 + i) 34 i = i + 1 35 } 36 return 0 37} 38 39func main() -> i64 { 40 ww("=== nx_worldsim_gate: is the faction/economy world sim safe to build a campaign on? ===\n\n") 41 var pass: i64 = 0 42 var checks: i64 = 0 43 let N: i64 = 6 44 let a: *i64 = sys_mmap(ws_bytes(N)) as *i64 45 46 // ---------- T1 conservation ---------- 47 checks = checks + 1 48 seedworld(a, N, 12345) 49 let before: i64 = ws_total_res(a) 50 var moved: i64 = 0 51 var t: i64 = 0 52 while t < 500 { 53 let f: i64 = ws_rng(a) % N 54 let g: i64 = ws_rng(a) % N 55 let amt: i64 = ws_rng(a) % 400 56 moved = moved + ws_trade(a, f, g, amt) 57 t = t + 1 58 } 59 let after: i64 = ws_total_res(a) 60 var neg: i64 = 0 61 var i: i64 = 0 62 while i < N { if ws_res(a,i) < 0 { neg = neg + 1 } i = i + 1 } 63 if before==after { if neg==0 { 64 ww("T1 GREEN conservation: 500 trades moved "); wn(moved); wn(0) 65 ww(" units, total "); wn(before); ww(" -> "); wn(after); ww(" (exact, 0 negative balances)\n") 66 pass=pass+1 67 } } 68 if before!=after { ww("T1 RED wealth leaked/minted: "); wn(before); ww(" -> "); wn(after); ww("\n") } 69 if before==after { if neg>0 { ww("T1 RED negative balances: "); wn(neg); ww("\n") } } 70 71 // ---------- T2 symmetric relations ---------- 72 checks = checks + 1 73 seedworld(a, N, 999) 74 ws_adjust_rel(a, 0, 3, 250) 75 ws_adjust_rel(a, 3, 0, 0-100) // opposite direction, same pair 76 ws_adjust_rel(a, 1, 4, 0-400) 77 ws_adjust_rel(a, 2, 5, 700) 78 var sym: i64 = 1 79 i = 0 80 while i < N { 81 var j: i64 = 0 82 while j < N { 83 if ws_rel(a,i,j) != ws_rel(a,j,i) { sym = 0 } 84 j = j + 1 85 } 86 i = i + 1 87 } 88 if sym==1 { if ws_rel(a,0,3)==150 { 89 ww("T2 GREEN relations symmetric by construction: rel(0,3)=rel(3,0)="); wn(ws_rel(a,0,3)) 90 ww(" after opposing one-sided edits -- diplomacy cannot desync\n") 91 pass=pass+1 92 } } 93 if sym==0 { ww("T2 RED asymmetric relation found\n") } 94 if sym==1 { if ws_rel(a,0,3)!=150 { ww("T2 RED edits did not accumulate: "); wn(ws_rel(a,0,3)); ww("\n") } } 95 96 // ---------- T3 accounted production ---------- 97 checks = checks + 1 98 seedworld(a, N, 4242) 99 let RATE: i64 = 7 100 let pre: i64 = ws_total_res(a) 101 let expect: i64 = ws_production(a, RATE) 102 ws_tick(a, RATE) 103 let post: i64 = ws_total_res(a) 104 if post - pre == expect { if expect > 0 { 105 ww("T3 GREEN production accounted: tick added exactly "); wn(expect) 106 ww(" (predicted == actual), total "); wn(pre); ww(" -> "); wn(post); ww("\n") 107 pass=pass+1 108 } } 109 if post - pre != expect { 110 ww("T3 RED production unaccounted: expected +"); wn(expect); ww(" got +"); wn(post-pre); ww("\n") 111 } 112 113 // ---------- T4 determinism ---------- 114 checks = checks + 1 115 let w1: *i64 = sys_mmap(ws_bytes(N)) as *i64 116 let w2: *i64 = sys_mmap(ws_bytes(N)) as *i64 117 seedworld(w1, N, 777); seedworld(w2, N, 777) 118 var k: i64 = 0 119 while k < 200 { ws_tick(w1, 5); ws_tick(w2, 5); k = k + 1 } 120 var det: i64 = 1 121 i = 0 122 while i < ws_words(N) { if w1[i]!=w2[i] { det=0 } i=i+1 } 123 if det==1 { 124 ww("T4 GREEN deterministic: 2 worlds, same seed, 200 ticks -> identical arena (tick=") 125 wn(ws_tickno(w1)); ww(", total="); wn(ws_total_res(w1)); ww(")\n") 126 pass=pass+1 127 } else { ww("T4 RED worlds diverged -- campaigns would not replay\n") } 128 129 // ---------- T5 bounded ---------- 130 checks = checks + 1 131 seedworld(a, N, 31) 132 ws_adjust_rel(a, 0, 1, 999999) 133 let relhi: i64 = ws_rel(a,0,1) 134 ws_adjust_rel(a, 2, 3, 0-999999) 135 let rello: i64 = ws_rel(a,2,3) 136 ws_set_res(a, 4, 100) 137 let over: i64 = ws_trade(a, 4, 5, 100000) // overdraw attempt 138 let left: i64 = ws_res(a, 4) 139 var t5: i64 = 0 140 if relhi==WS_RELMAX { if rello==WS_RELMIN { if over==100 { if left==0 { t5=1 } } } } 141 if t5==1 { 142 ww("T5 GREEN bounded: rel clamps "); wn(rello); ww("/"); wn(relhi) 143 ww("; overdraw of 100000 moved only the "); wn(over); ww(" held, balance "); wn(left); ww("\n") 144 pass=pass+1 145 } else { 146 ww("T5 RED bounds breached: relhi="); wn(relhi); ww(" rello="); wn(rello) 147 ww(" moved="); wn(over); ww(" left="); wn(left); ww("\n") 148 } 149 150 // ---------- T6 no self-dealing ---------- 151 checks = checks + 1 152 seedworld(a, N, 55) 153 let r0: i64 = ws_res(a,0) 154 let self_trade: i64 = ws_trade(a, 0, 0, 500) 155 let selfrel_before: i64 = ws_rel(a,2,2) 156 ws_adjust_rel(a, 2, 2, 0-500) 157 let selfrel_after: i64 = ws_rel(a,2,2) 158 var t6: i64 = 0 159 if self_trade==0 { if ws_res(a,0)==r0 { if selfrel_before==selfrel_after { t6=1 } } } 160 if t6==1 { 161 ww("T6 GREEN no self-dealing: self-trade refused (balance unchanged "); wn(r0) 162 ww("), self-relation immutable\n"); pass=pass+1 163 } else { ww("T6 RED self-dealing permitted, moved="); wn(self_trade); ww("\n") } 164 165 // ---------- T7 anti-vacuity ---------- 166 checks = checks + 1 167 seedworld(a, N, 20260720) 168 let v0_total: i64 = ws_total_res(a) 169 let v0_rel: i64 = ws_rel(a,0,1) 170 var relmoved: i64 = 0 171 k = 0 172 while k < 300 { 173 ws_tick(a, 4) 174 if ws_rel(a,0,1) != v0_rel { relmoved = 1 } 175 k = k + 1 176 } 177 let v1_total: i64 = ws_total_res(a) 178 var t7: i64 = 0 179 if v1_total > v0_total { if ws_tickno(a)==300 { if relmoved==1 { t7=1 } } } 180 if t7==1 { 181 ww("T7 GREEN anti-vacuity: 300 ticks grew wealth "); wn(v0_total); ww(" -> "); wn(v1_total) 182 ww(" and relations moved -- the world actually simulates\n"); pass=pass+1 183 } else { 184 ww("T7 RED world is frozen: total "); wn(v0_total); ww(" -> "); wn(v1_total) 185 ww(" relmoved="); wn(relmoved); ww("\n") 186 } 187 188 // ---------- T8 composes with nx_gamesave ---------- 189 checks = checks + 1 190 let WP: *u8 = "knowledge/nx_worldsim_world.sav" as *u8 191 sys_unlinkat(WP) 192 let words: i64 = ws_words(N) 193 let wrote: i64 = gs_save(WP, 60613, a, words, 1784579500) 194 let rd: *i64 = sys_mmap(ws_bytes(N)) as *i64 195 let got: i64 = gs_load(WP, rd, words, 0 as *i64) 196 var t8: i64 = 1 197 if got != words { t8=0 } 198 if wrote <= 0 { t8=0 } 199 i = 0 200 while i < words { if rd[i]!=a[i] { t8=0 } i=i+1 } 201 // and the restored world must keep simulating identically 202 if t8==1 { 203 let cont: *i64 = sys_mmap(ws_bytes(N)) as *i64 204 i = 0 205 while i < words { cont[i]=rd[i]; i=i+1 } 206 ws_tick(a, 4); ws_tick(cont, 4) 207 i = 0 208 while i < words { if cont[i]!=a[i] { t8=0 } i=i+1 } 209 } 210 if t8==1 { 211 ww("T8 GREEN composes with nx_gamesave: "); wn(N); ww("-faction world ("); wn(words) 212 ww(" words, "); wn(wrote); ww("B) round-tripped AND resumed simulating identically\n") 213 pass=pass+1 214 } else { ww("T8 RED world did not survive save/load or diverged on resume, rc="); wn(got); ww("\n") } 215 216 ww("\n=== nx_worldsim_gate "); wn(pass); ww("/"); wn(checks) 217 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 218 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 219 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 220 let ctr__dry: *i64 = gv_ctr() 221 ctr__dry[0] = pass 222 ctr__dry[1] = checks 223 let rc__dry: i64 = gv_verdict("WORLDSIM-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 224 sys_exit(rc__dry) 225 return rc__dry 226}