nx_procgen_signature_test.nx source
↩ module page · 151 lines · 5023 B
1// nx_procgen_signature_test.nx -- KATs for the P1 composed-primitives
2// signature features. Exit 0 = all pass; first failing KAT's number is
3// the exit code (loud, names the failure).
4//
5// KAT 1 peak apex: center cell rises by exactly amp (d2=0 term).
6// KAT 2 peak reach: a cell beyond radius is untouched.
7// KAT 3 ridge symmetry: cells mirrored across the segment move equally.
8// KAT 4 valley is ridge negated: same geometry, opposite sign.
9// KAT 5 cliff is antisymmetric: left side up, right side down.
10// KAT 6 compose determinism: same (seed,preset) twice -> identical maps.
11// KAT 7 compose moves EXTREMES: graded ext after >= before on the same
12// fbm base (the P1 gate axis, proven at module level).
13// license_tier: ORIGINAL
14
15import "nx_syscalls.nx"
16import "nx_tier.nx"
17import "nx_procgen_signature.nx"
18import "nx_world_quality_grader.nx"
19import "nx_perlin.nx"
20
21const TW: nx_int = 64
22const TH: nx_int = 64
23
24func t_fill_zero(hm: *nx_int, n: nx_int) -> nx_int {
25 var i: nx_int = 0
26 while i < n { hm[i] = 0; i = i + 1 }
27 return 0
28}
29
30func t_fill_fbm(hm: *nx_int, seed: nx_int) -> nx_int {
31 let st: *PerlinState = nx_perlin_alloc(seed)
32 var y: nx_int = 0
33 while y < TH {
34 var x: nx_int = 0
35 while x < TW {
36 hm[y * TW + x] = nx_perlin_fbm_2d(st, x * 102, y * 102, 4, 614)
37 x = x + 1
38 }
39 y = y + 1
40 }
41 return 0
42}
43
44func main() -> i64 {
45 let n: nx_int = TW * TH
46 let hm: *nx_int = sys_mmap(n * 8) as *nx_int
47 let hm2: *nx_int = sys_mmap(n * 8) as *nx_int
48
49 // ---- KAT 1: peak apex == amp on a zero map ----
50 t_fill_zero(hm, n)
51 nx_sig_peak(hm, TW, TH, 32, 32, 10, 700)
52 if hm[32 * TW + 32] != 700 { return 1 }
53
54 // ---- KAT 2: beyond radius untouched ----
55 if hm[32 * TW + 32 + 11] != 0 { return 2 }
56
57 // ---- KAT 3: ridge symmetry across a horizontal segment ----
58 t_fill_zero(hm, n)
59 nx_sig_ridge(hm, TW, TH, 16, 32, 48, 32, 6, 500)
60 if hm[(32 - 3) * TW + 32] != hm[(32 + 3) * TW + 32] { return 3 }
61 if hm[32 * TW + 32] <= 0 { return 3 }
62
63 // ---- KAT 4: valley == negated ridge ----
64 t_fill_zero(hm2, n)
65 nx_sig_valley(hm2, TW, TH, 16, 32, 48, 32, 6, 0 - 500)
66 var i: nx_int = 0
67 while i < n {
68 if hm2[i] != 0 - hm[i] { return 4 }
69 i = i + 1
70 }
71
72 // ---- KAT 5: cliff antisymmetric across the segment ----
73 t_fill_zero(hm, n)
74 nx_sig_cliff(hm, TW, TH, 32, 16, 32, 48, 8, 400)
75 let up: nx_int = hm[32 * TW + (32 + 3)]
76 let dn: nx_int = hm[32 * TW + (32 - 3)]
77 if up <= 0 { return 5 }
78 if dn >= 0 { return 5 }
79 if up != 0 - dn { return 5 }
80
81 // ---- KAT 6: compose determinism ----
82 t_fill_fbm(hm, 42)
83 t_fill_fbm(hm2, 42)
84 nx_sig_compose(hm, TW, TH, 42, 4)
85 nx_sig_compose(hm2, TW, TH, 42, 4)
86 i = 0
87 while i < n {
88 if hm[i] != hm2[i] { return 6 }
89 i = i + 1
90 }
91
92 // ---- KAT 7: EXTREMES axis moves up on the fbm base ----
93 let v_before: *i64 = sys_mmap(8 * 12) as *i64
94 let v_after: *i64 = sys_mmap(8 * 12) as *i64
95 var worst_gain: nx_int = 99999
96 var s: nx_int = 0
97 while s < 3 {
98 let seed: nx_int = 1000 + s * 777
99 t_fill_fbm(hm, seed)
100 nx_world_quality_grade(hm, TW, TH, 1024, 0 as *i64, 0 as *i64, 0, v_before)
101 nx_sig_compose(hm, TW, TH, seed, 4)
102 nx_world_quality_grade(hm, TW, TH, 1024, 0 as *i64, 0 as *i64, 0, v_after)
103 let gain: nx_int = v_after[3] - v_before[3]
104 if gain < worst_gain { worst_gain = gain }
105 s = s + 1
106 }
107 if worst_gain <= 0 { return 7 }
108
109 // ---- KAT 8: mesa core is FLAT on a varied base ----
110 t_fill_fbm(hm, 42)
111 nx_sig_peak(hm, TW, TH, 32, 32, 16, 700)
112 if hm[32 * TW + 32] != hm[32 * TW + 36] { return 8 }
113 if hm[32 * TW + 32] != hm[36 * TW + 32] { return 8 }
114
115 // ---- KAT 9: terraced rim = few distinct strata, smooth rim = many ----
116 t_fill_zero(hm, n)
117 nx_sig_peak_t(hm, TW, TH, 32, 32, 16, 800, 4)
118 var d_terr: nx_int = 0
119 var px: nx_int = 32
120 var prev: nx_int = hm[32 * TW + 32] + 1 // sentinel != first
121 while px <= 48 {
122 let v: nx_int = hm[32 * TW + px]
123 if v != prev { d_terr = d_terr + 1; prev = v }
124 px = px + 1
125 }
126 t_fill_zero(hm2, n)
127 nx_sig_peak(hm2, TW, TH, 32, 32, 16, 800)
128 var d_smooth: nx_int = 0
129 px = 32
130 prev = hm2[32 * TW + 32] + 1
131 while px <= 48 {
132 let v: nx_int = hm2[32 * TW + px]
133 if v != prev { d_smooth = d_smooth + 1; prev = v }
134 px = px + 1
135 }
136 if d_terr > 6 { return 9 } // core + <= steps rings + outside
137 if d_terr >= d_smooth { return 9 } // strictly fewer strata
138
139 // ---- KAT 10: steps=0 == smooth contract, byte-identical ----
140 t_fill_fbm(hm, 42)
141 t_fill_fbm(hm2, 42)
142 nx_sig_peak_t(hm, TW, TH, 32, 32, 16, 700, 0)
143 nx_sig_peak(hm2, TW, TH, 32, 32, 16, 700)
144 i = 0
145 while i < n {
146 if hm[i] != hm2[i] { return 10 }
147 i = i + 1
148 }
149
150 return 0
151}