code wiki / _hdl_build / nx_loottable_gate.nx
nx_loottable_gate.nx source
↩ module page · 211 lines · 8871 B
1// nx_loottable_gate.nx -- CERTIFICATION of nx_loottable (the LAST hard GAP on the gamebench board).
2// T1 ★EVERY TIER REACHABLE -- 100k rolls must observe every declared tier at least once. This is the
3// off-by-one killer: legendaries that can never drop.
4// T2 ★DISTRIBUTION MATCHES DECLARED WEIGHTS -- observed frequency per tier within 10% relative of expected
5// T3 DETERMINISM -- the same seed yields the identical item (tier, affixes, values)
6// T4 NO DUPLICATE AFFIXES -- across 20k items, no item carries the same affix twice
7// T5 VALUES IN RANGE -- every rolled value lies within its affix's declared [lo,hi]
8// T6 TIER DRIVES AFFIX COUNT -- higher tiers grant more affixes, exactly as the data says
9// T7 ★ANTI-VACUITY -- items genuinely VARY across seeds. A generator returning one fixed item would
10// satisfy determinism, range and no-duplicate perfectly.
11// T8 composes with nx_gamesave: a rolled item round-trips through save/load
12// license_tier: ORIGINAL expect_exit: 0
13import "nx_syscalls.nx"
14import "nx_loottable.nx"
15import "nx_gamesave.nx"
16
17func lw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
18func ln(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}
27
28func main() -> i64 {
29 lw("=== nx_loottable_gate: does the loot table actually obey its own numbers? ===\n\n")
30 var pass: i64 = 0
31 var checks: i64 = 0
32
33 // ---- DATA: 5 tiers (common..legendary) and an 8-affix pool ----
34 let NT: i64 = 5
35 let tw: *i64 = sys_mmap(NT*8) as *i64
36 let ta: *i64 = sys_mmap(NT*8) as *i64
37 tw[0]=600; tw[1]=250; tw[2]=100; tw[3]=45; tw[4]=5 // legendary = 5/1000
38 ta[0]=0; ta[1]=1; ta[2]=2; ta[3]=3; ta[4]=5
39 let NA: i64 = 8
40 let aw: *i64 = sys_mmap(NA*8) as *i64
41 let alo: *i64 = sys_mmap(NA*8) as *i64
42 let ahi: *i64 = sys_mmap(NA*8) as *i64
43 var i: i64 = 0
44 while i < NA { aw[i] = 10 + i; alo[i] = 1 + i*2; ahi[i] = 10 + i*5; i = i + 1 }
45
46 let oa: *i64 = sys_mmap(LT_MAXAFFIX*8) as *i64
47 let ov: *i64 = sys_mmap(LT_MAXAFFIX*8) as *i64
48 let on: *i64 = sys_mmap(8) as *i64
49
50 // ---------- T1 + T2 tier reachability and distribution over 100k rolls ----------
51 let ROLLS: i64 = 100000
52 let seen: *i64 = sys_mmap(NT*8) as *i64
53 i = 0
54 while i < NT { seen[i] = 0; i = i + 1 }
55 var s: i64 = 1
56 while s <= ROLLS {
57 let t: i64 = lt_roll(s*2654435761, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
58 if t >= 0 { seen[t] = seen[t] + 1 }
59 s = s + 1
60 }
61 checks = checks + 1
62 var unreachable: i64 = 0
63 i = 0
64 while i < NT { if seen[i]==0 { unreachable = unreachable + 1 } i = i + 1 }
65 if unreachable==0 {
66 lw("T1 GREEN every tier reachable over "); ln(ROLLS); lw(" rolls: ")
67 i = 0
68 while i < NT { ln(seen[i]); if i < NT-1 { lw("/") } i = i + 1 }
69 lw(" (legendary DID drop)\n"); pass=pass+1
70 } else { lw("T1 RED "); ln(unreachable); lw(" declared tiers NEVER rolled -- unreachable loot\n") }
71
72 checks = checks + 1
73 var totw: i64 = 0
74 i = 0
75 while i < NT { totw = totw + tw[i]; i = i + 1 }
76 var drift: i64 = 0
77 var worst: i64 = 0
78 i = 0
79 while i < NT {
80 let expect: i64 = (ROLLS * tw[i]) / totw
81 var d: i64 = seen[i] - expect
82 if d < 0 { d = 0 - d }
83 let tol: i64 = expect / 10 // 10% relative tolerance
84 if d > tol { drift = drift + 1 }
85 let relp: i64 = (d * 1000) / (expect + 1) // permil deviation
86 if relp > worst { worst = relp }
87 i = i + 1
88 }
89 if drift==0 {
90 lw("T2 GREEN distribution matches declared weights: worst tier deviates "); ln(worst)
91 lw(" permil of expected (tolerance 100)\n"); pass=pass+1
92 } else { lw("T2 RED "); ln(drift); lw(" tiers outside 10% of declared weight, worst "); ln(worst); lw(" permil\n") }
93
94 // ---------- T3 determinism ----------
95 checks = checks + 1
96 let oa2: *i64 = sys_mmap(LT_MAXAFFIX*8) as *i64
97 let ov2: *i64 = sys_mmap(LT_MAXAFFIX*8) as *i64
98 let on2: *i64 = sys_mmap(8) as *i64
99 let t1a: i64 = lt_roll(987654321, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
100 let t1b: i64 = lt_roll(987654321, tw, ta, NT, aw, alo, ahi, NA, oa2, ov2, on2)
101 var det: i64 = 1
102 if t1a != t1b { det = 0 }
103 if on[0] != on2[0] { det = 0 }
104 i = 0
105 while i < on[0] { if oa[i]!=oa2[i] { det=0 } if ov[i]!=ov2[i] { det=0 } i=i+1 }
106 if det==1 {
107 lw("T3 GREEN deterministic: seed 987654321 -> tier "); ln(t1a); lw(" with "); ln(on[0])
108 lw(" affixes, identical both times\n"); pass=pass+1
109 } else { lw("T3 RED same seed produced different items\n") }
110
111 // ---------- T4 no duplicate affixes ----------
112 checks = checks + 1
113 var dupitems: i64 = 0
114 s = 1
115 while s <= 20000 {
116 lt_roll(s*40503, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
117 var a: i64 = 0
118 while a < on[0] {
119 var b: i64 = a + 1
120 while b < on[0] { if oa[a]==oa[b] { dupitems = dupitems + 1 } b = b + 1 }
121 a = a + 1
122 }
123 s = s + 1
124 }
125 if dupitems==0 {
126 lw("T4 GREEN no duplicate affixes across 20000 items (sampling without replacement holds)\n")
127 pass=pass+1
128 } else { lw("T4 RED "); ln(dupitems); lw(" duplicate-affix pairs found\n") }
129
130 // ---------- T5 values in range ----------
131 checks = checks + 1
132 var oor: i64 = 0
133 s = 1
134 while s <= 20000 {
135 lt_roll(s*22695477, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
136 var a: i64 = 0
137 while a < on[0] {
138 let id: i64 = oa[a]
139 if id < 0 { oor = oor + 1 }
140 if id >= NA { oor = oor + 1 }
141 if id >= 0 { if id < NA {
142 if ov[a] < alo[id] { oor = oor + 1 }
143 if ov[a] > ahi[id] { oor = oor + 1 }
144 } }
145 a = a + 1
146 }
147 s = s + 1
148 }
149 if oor==0 {
150 lw("T5 GREEN every affix value inside its declared [lo,hi] across 20000 items\n"); pass=pass+1
151 } else { lw("T5 RED "); ln(oor); lw(" out-of-range affix values\n") }
152
153 // ---------- T6 tier drives affix count ----------
154 checks = checks + 1
155 var t6: i64 = 1
156 s = 1
157 while s <= 20000 {
158 let t: i64 = lt_roll(s*69069, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
159 if t >= 0 { if on[0] != lt_affix_count(ta, t) { t6 = 0 } }
160 s = s + 1
161 }
162 if t6==1 {
163 lw("T6 GREEN affix count is exactly what the tier data declares (0/1/2/3/5 per tier)\n"); pass=pass+1
164 } else { lw("T6 RED affix count disagrees with the tier table\n") }
165
166 // ---------- T7 anti-vacuity: items actually vary ----------
167 checks = checks + 1
168 var distinct: i64 = 0
169 let firstv: *i64 = sys_mmap(8) as *i64
170 lt_roll(11, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
171 firstv[0] = oa[0]*1000 + ov[0] + on[0]*7
172 s = 12
173 while s <= 400 {
174 lt_roll(s, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
175 let sig: i64 = oa[0]*1000 + ov[0] + on[0]*7
176 if sig != firstv[0] { distinct = distinct + 1 }
177 s = s + 1
178 }
179 if distinct > 100 {
180 lw("T7 GREEN anti-vacuity: "); ln(distinct)
181 lw("/389 sampled items differ from the first -- real variety, not one fixed drop\n"); pass=pass+1
182 } else { lw("T7 RED only "); ln(distinct); lw(" distinct items -- generator is near-constant\n") }
183
184 // ---------- T8 composes with nx_gamesave ----------
185 checks = checks + 1
186 let IP: *u8 = "knowledge/nx_loottable_item.sav" as *u8
187 sys_unlinkat(IP)
188 let tier: i64 = lt_roll(20260720, tw, ta, NT, aw, alo, ahi, NA, oa, ov, on)
189 let NV: i64 = 2 + LT_MAXAFFIX*2
190 let vec: *i64 = sys_mmap(NV*8) as *i64
191 vec[0] = tier; vec[1] = on[0]
192 i = 0
193 while i < LT_MAXAFFIX { vec[2+i] = oa[i]; vec[2+LT_MAXAFFIX+i] = ov[i]; i = i + 1 }
194 let wrote: i64 = gs_save(IP, 80808, vec, NV, 1784580500)
195 let rd: *i64 = sys_mmap(NV*8) as *i64
196 let got: i64 = gs_load(IP, rd, NV, 0 as *i64)
197 var t8: i64 = 1
198 if got != NV { t8 = 0 }
199 if wrote <= 0 { t8 = 0 }
200 i = 0
201 while i < NV { if rd[i]!=vec[i] { t8=0 } i=i+1 }
202 if t8==1 {
203 lw("T8 GREEN composes with nx_gamesave: tier-"); ln(tier); lw(" item with "); ln(on[0])
204 lw(" affixes round-tripped ("); ln(wrote); lw("B)\n"); pass=pass+1
205 } else { lw("T8 RED item did not survive save/load, rc="); ln(got); lw("\n") }
206
207 lw("\n=== nx_loottable_gate "); ln(pass); lw("/"); ln(checks)
208 if pass == checks { lw(" GREEN ===\n"); return 0 }
209 lw(" RED ===\n")
210 return 1
211}