nx_procgen_features_test.nx source
↩ module page · 139 lines · 5766 B
1// nx_procgen_features_test.nx -- KATs for the P3 biome-lawed feature kinds.
2// Exit 0 = all pass; first failing KAT's number is the exit code.
3//
4// KAT 1 determinism: same (land, biomes, seed) twice -> identical kinds.
5// KAT 2 validity: every kind is sealed (0..3).
6// KAT 3 histogram conservation: counts sum to n_features.
7// KAT 4 variety axis LIVE: grader FEATURE_VARIETY >= 9830 (WIN floor)
8// worst-of-3-seeds on the mountain preset.
9// KAT 5 variety discriminates: an all-ICE biome map (rock-only law)
10// scores 0; the real map scores strictly higher.
11// KAT 6 biome law holds: a pure-DESERT map grows NO trees.
12// KAT 7 independent streams: kinds seed does not change the biome map.
13// KAT 8 width: every preset x 3 seeds stays >= 6553 (marginal floor) --
14// the variety axis must never fall back into LOSS territory
15// (honest 2026-06-10 baseline: meadow worst = 6585; forest/meadow
16// rock-band skew is the named P4/P5 improvement surface).
17// license_tier: ORIGINAL
18
19import "nx_syscalls.nx"
20import "nx_tier.nx"
21import "nx_procgen_preset.nx"
22import "nx_procgen_biome.nx"
23import "nx_procgen_features.nx"
24import "nx_world_quality_grader.nx"
25
26const FW: nx_int = 64
27const FH: nx_int = 64
28
29func main() -> i64 {
30 let n: nx_int = FW * FH
31 let bm: *i64 = sys_mmap(n * 8) as *i64
32 let v: *i64 = sys_mmap(8 * 12) as *i64
33 let hist: *i64 = sys_mmap(NX_FEAT_N_KINDS * 8) as *i64
34 let null_ptr: *i64 = 0 as *i64
35
36 let land: *Landscape = nx_procgen_landscape(4242, NX_PROCGEN_PRESET_MOUNTAIN, FW, FH, 1024)
37 let nf: nx_int = land.n_features
38 if nf <= 0 { return 99 } // generator must yield features
39 let kinds: *i64 = sys_mmap(nf * 8) as *i64
40 let kinds2: *i64 = sys_mmap(nf * 8) as *i64
41 nx_biome_map_build(land.heightmap, FW, FH, 4242, bm)
42
43 // ---- KAT 1: determinism ----
44 nx_feature_assign(land.feature_xs, land.feature_ys, nf, bm, FW, FH, 4242, kinds)
45 nx_feature_assign(land.feature_xs, land.feature_ys, nf, bm, FW, FH, 4242, kinds2)
46 var i: nx_int = 0
47 while i < nf {
48 if kinds[i] != kinds2[i] { return 1 }
49 i = i + 1
50 }
51
52 // ---- KAT 2: validity ----
53 i = 0
54 while i < nf {
55 if nx_feature_kind_is_valid(kinds[i]) != 1 { return 2 }
56 i = i + 1
57 }
58
59 // ---- KAT 3: histogram conservation ----
60 nx_feature_hist_build(kinds, nf, hist)
61 var total: nx_int = 0
62 var k: nx_int = 0
63 while k < NX_FEAT_N_KINDS { total = total + hist[k]; k = k + 1 }
64 if total != nf { return 3 }
65
66 // ---- KAT 4: variety axis live, worst-of-3 seeds ----
67 var worst: nx_int = 99999
68 var s: nx_int = 0
69 while s < 3 {
70 let seed: nx_int = 1000 + s * 777
71 let wl: *Landscape = nx_procgen_landscape(seed, NX_PROCGEN_PRESET_MOUNTAIN, FW, FH, 1024)
72 if wl.n_features <= 0 { return 4 }
73 let wk: *i64 = sys_mmap(wl.n_features * 8) as *i64
74 nx_biome_map_build(wl.heightmap, FW, FH, seed, bm)
75 nx_feature_assign(wl.feature_xs, wl.feature_ys, wl.n_features, bm, FW, FH, seed, wk)
76 nx_feature_hist_build(wk, wl.n_features, hist)
77 nx_world_quality_grade(wl.heightmap, FW, FH, 1024, null_ptr, hist, NX_FEAT_N_KINDS, v)
78 if v[NX_WQG_OFF_FEATURE_VARIETY] < worst { worst = v[NX_WQG_OFF_FEATURE_VARIETY] }
79 s = s + 1
80 }
81 if worst < 9830 { return 4 }
82
83 // ---- KAT 5: discriminates -- rock-only law scores 0 ----
84 let bm_ice: *i64 = sys_mmap(n * 8) as *i64
85 i = 0
86 while i < n { bm_ice[i] = NX_BIOME_ICE; i = i + 1 }
87 nx_feature_assign(land.feature_xs, land.feature_ys, nf, bm_ice, FW, FH, 4242, kinds2)
88 nx_feature_hist_build(kinds2, nf, hist)
89 nx_world_quality_grade(land.heightmap, FW, FH, 1024, null_ptr, hist, NX_FEAT_N_KINDS, v)
90 let ice_variety: nx_int = v[NX_WQG_OFF_FEATURE_VARIETY]
91 if ice_variety != 0 { return 5 }
92 if worst <= ice_variety { return 5 }
93
94 // ---- KAT 6: no trees in the desert ----
95 let bm_des: *i64 = sys_mmap(n * 8) as *i64
96 i = 0
97 while i < n { bm_des[i] = NX_BIOME_DESERT; i = i + 1 }
98 nx_feature_assign(land.feature_xs, land.feature_ys, nf, bm_des, FW, FH, 4242, kinds2)
99 i = 0
100 while i < nf {
101 if kinds2[i] == NX_FEAT_TREE { return 6 }
102 i = i + 1
103 }
104
105 // ---- KAT 7: kind stream independent of biome stream ----
106 // (rebuild the reference FRESH -- earlier KATs reuse bm for other
107 // worlds; comparing against stale state was a latent KAT bug the
108 // honest gate channel surfaced 2026-06-10)
109 let bm2: *i64 = sys_mmap(n * 8) as *i64
110 nx_biome_map_build(land.heightmap, FW, FH, 4242, bm)
111 nx_feature_assign(land.feature_xs, land.feature_ys, nf, bm, FW, FH, 9999, kinds2)
112 nx_biome_map_build(land.heightmap, FW, FH, 4242, bm2)
113 i = 0
114 while i < n {
115 if bm2[i] != bm[i] { return 7 }
116 i = i + 1
117 }
118
119 // ---- KAT 8: width -- all presets x 3 seeds above the marginal floor ----
120 var preset: nx_int = 0
121 while preset < NX_PROCGEN_N_PRESETS {
122 var s8: nx_int = 0
123 while s8 < 3 {
124 let seed: nx_int = 1000 + s8 * 777
125 let wl: *Landscape = nx_procgen_landscape(seed, preset, FW, FH, 1024)
126 if wl.n_features <= 0 { return 8 }
127 let wk: *i64 = sys_mmap(wl.n_features * 8) as *i64
128 nx_biome_map_build(wl.heightmap, FW, FH, seed, bm)
129 nx_feature_assign(wl.feature_xs, wl.feature_ys, wl.n_features, bm, FW, FH, seed, wk)
130 nx_feature_hist_build(wk, wl.n_features, hist)
131 nx_world_quality_grade(wl.heightmap, FW, FH, 1024, null_ptr, hist, NX_FEAT_N_KINDS, v)
132 if v[NX_WQG_OFF_FEATURE_VARIETY] < 6553 { return 8 }
133 s8 = s8 + 1
134 }
135 preset = preset + 1
136 }
137
138 return 0
139}