nx_crummy_detector.nx source
↩ module page · 597 lines · 23113 B
1// nx_crummy_detector.nx -- direct "is this world crummy?" detector.
2//
3// Per user 2026-05-16: "i just dont want them to be crummy"
4//
5// Crummy worlds share a small set of failure modes that statistical
6// graders (nx_world_quality_grader) sometimes miss because they
7// reward heightmap diversity even when the OVERALL experience is
8// bland. This primitive grades the 7 failure modes that produce
9// "crummy" output regardless of underlying statistics:
10//
11// AXIS 0 -- RANGE_USAGE: Does the heightmap use the available relief
12// budget? Worlds with all hills at the same height (small range
13// relative to the body's max relief) are crummy.
14// AXIS 1 -- LOCAL_CONTRAST: Is neighbour-to-neighbour height
15// variation perceivable? Smooth-noise worlds score high on
16// diversity but low here -- they look like a putting green.
17// AXIS 2 -- SIGNATURE_PEAK_COUNT: Does the world have AT LEAST a
18// few extremes (peaks above 0.7 of relief; valleys below 0.1)?
19// Uniform mid-elevation worlds score 0 here.
20// AXIS 3 -- BIOME_DIVERSITY: If a biome map is supplied, is biome
21// distribution non-degenerate? An all-FOREST or all-DESERT world
22// is crummy. Shannon entropy of the biome histogram.
23// AXIS 4 -- PALETTE_RICHNESS: If a color palette is supplied, are
24// there at least 5 distinct hues? Monochrome worlds are crummy.
25// AXIS 5 -- HORIZON_VARIATION: If horizon ray samples are supplied,
26// does the silhouette have meaningful stddev? Pancake-horizon
27// worlds are crummy.
28// AXIS 6 -- SPATIAL_NON_REPETITION: Auto-correlation check. Does
29// the heightmap repeat at scale N? Worlds that tile (because the
30// noise was sampled with too-low frequency) are crummy.
31//
32// EMITS LAYER_VERDICT (16 i64) with kind = NX_LAYER_KIND_READABILITY
33// (the closest existing kind; could split to a CRUMMY kind later).
34//
35// CRUMMY-IS-NOT-A-LOSS CONVENTION: each axis is HIGHER = LESS CRUMMY.
36// Caller composes through nx_meta_verdict for the God-said-good check.
37//
38// Skipped axes (null inputs) score MARGINAL (= 0.5Q) so they don't
39// drag the verdict. Caller can supply biome_map = 0, palette = 0,
40// horizon = 0 to skip those axes.
41//
42// genealogy_id: elder_ai_crummy_detector_canon +
43// nx_quality_grade_sclass_canon
44// lineage_id: nx_crummy_detector_7axis_v1
45
46// nx_safety_envelope:
47// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
48// sil_target: SIL1
49// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
50// verdict: NOT_YET_EVALUATED
51
52import "nx_syscalls.nx"
53import "nx_tier.nx"
54import "nx_layer_verdict.nx"
55const NX_MAGIC_16384: i64 = 16384
56const NX_MAGIC_25976: i64 = 25976
57const NX_MAGIC_32768: i64 = 32768
58const NX_MAGIC_38048: i64 = 38048
59const NX_MAGIC_42361: i64 = 42361
60const NX_MAGIC_46006: i64 = 46006
61const NX_MAGIC_49152: i64 = 49152
62const NX_MAGIC_51916: i64 = 51916
63const NX_MAGIC_54432: i64 = 54432
64const NX_MAGIC_56619: i64 = 56619
65const NX_MAGIC_58744: i64 = 58744
66const NX_MAGIC_60686: i64 = 60686
67const NX_MAGIC_62390: i64 = 62390
68const NX_MAGIC_63984: i64 = 63984
69const NX_MAGIC_65536: i64 = 65536
70
71// ===== Q14 ==========================================================
72const NX_CRUMMY_Q: nx_int = 16384
73
74// ===== Crumminess axis indices (within LAYER_VERDICT) =============
75const NX_CRUMMY_AXIS_RANGE_USAGE: nx_int = 0
76const NX_CRUMMY_AXIS_LOCAL_CONTRAST: nx_int = 1
77const NX_CRUMMY_AXIS_SIGNATURE_PEAKS: nx_int = 2
78const NX_CRUMMY_AXIS_BIOME_DIVERSITY: nx_int = 3
79const NX_CRUMMY_AXIS_PALETTE_RICHNESS: nx_int = 4
80const NX_CRUMMY_AXIS_HORIZON_VARIATION: nx_int = 5
81const NX_CRUMMY_AXIS_NON_REPETITION: nx_int = 6
82
83const NX_CRUMMY_AXIS_COUNT: nx_int = 7
84
85// ===== Internal: log2(bin) for entropy (Q14) =======================
86func _crummy_log2_q14(bin: nx_int) -> nx_int {
87 if bin <= 1 { return 0 }
88 if bin == 2 { return NX_MAGIC_16384 }
89 if bin == 3 { return NX_MAGIC_25976 }
90 if bin == 4 { return NX_MAGIC_32768 }
91 if bin == 5 { return NX_MAGIC_38048 }
92 if bin == 6 { return NX_MAGIC_42361 }
93 if bin == 7 { return NX_MAGIC_46006 }
94 if bin == 8 { return NX_MAGIC_49152 }
95 if bin == 9 { return NX_MAGIC_51916 }
96 if bin == 10 { return NX_MAGIC_54432 }
97 if bin == 11 { return NX_MAGIC_56619 }
98 if bin == 12 { return NX_MAGIC_58744 }
99 if bin == 13 { return NX_MAGIC_60686 }
100 if bin == 14 { return NX_MAGIC_62390 }
101 if bin == 15 { return NX_MAGIC_63984 }
102 return NX_MAGIC_65536 // log2(16) = 4.0
103}
104
105// ===== Internal: heightmap range + min/max ========================
106func _crummy_range_usage_q14(
107 heightmap: *i64, w: nx_int, h: nx_int, max_relief: nx_int
108) -> nx_int {
109 let n: nx_int = w * h
110 if n <= 0 { return 0 }
111 if max_relief <= 0 { return 0 }
112 var hmin: nx_int = heightmap[0]
113 var hmax: nx_int = heightmap[0]
114 var i: nx_int = 0
115 while i < n {
116 let v: nx_int = heightmap[i]
117 if v < hmin { hmin = v }
118 if v > hmax { hmax = v }
119 i = i + 1
120 }
121 let range: nx_int = hmax - hmin
122 let q: nx_int = NX_CRUMMY_Q
123 var usage: nx_int = (range * q) / max_relief
124 if usage > q { usage = q }
125 if usage < 0 { usage = 0 }
126 return usage
127}
128
129// ===== Internal: local contrast (mean neighbor diff / max) =========
130func _crummy_local_contrast_q14(
131 heightmap: *i64, w: nx_int, h: nx_int, max_relief: nx_int
132) -> nx_int {
133 let n: nx_int = w * h
134 if n <= 1 { return 0 }
135 if max_relief <= 0 { return 0 }
136 var sum: nx_int = 0
137 var count: nx_int = 0
138 var i: nx_int = 0
139 while i < n {
140 let xi: nx_int = i % w
141 let yi: nx_int = i / w
142 if xi + 1 < w {
143 let d: nx_int = heightmap[i + 1] - heightmap[i]
144 var ad: nx_int = d
145 if ad < 0 { ad = 0 - ad }
146 sum = sum + ad
147 count = count + 1
148 }
149 if yi + 1 < h {
150 let d: nx_int = heightmap[i + w] - heightmap[i]
151 var ad: nx_int = d
152 if ad < 0 { ad = 0 - ad }
153 sum = sum + ad
154 count = count + 1
155 }
156 i = i + 1
157 }
158 if count == 0 { return 0 }
159 let mean_diff: nx_int = sum / count
160 let q: nx_int = NX_CRUMMY_Q
161 // Target: mean_diff = max_relief / 20 (5% per neighbour); score
162 // peaks there, decays on both sides.
163 let target: nx_int = max_relief / 20
164 if target <= 0 { return 0 }
165 var ratio: nx_int = (mean_diff * q) / target
166 if ratio > q { ratio = q - (ratio - q) } // overshoot also bad
167 if ratio < 0 { ratio = 0 }
168 if ratio > q { ratio = q }
169 return ratio
170}
171
172// ===== Internal: signature peak/valley count =======================
173func _crummy_signature_peaks_q14(
174 heightmap: *i64, w: nx_int, h: nx_int, max_relief: nx_int
175) -> nx_int {
176 let n: nx_int = w * h
177 if n <= 0 { return 0 }
178 if max_relief <= 0 { return 0 }
179 var hmin: nx_int = heightmap[0]
180 var hmax: nx_int = heightmap[0]
181 var i: nx_int = 0
182 while i < n {
183 let v: nx_int = heightmap[i]
184 if v < hmin { hmin = v }
185 if v > hmax { hmax = v }
186 i = i + 1
187 }
188 let range: nx_int = hmax - hmin
189 if range <= 0 { return 0 }
190 // Peak threshold: hmin + range * 0.7
191 let peak_t: nx_int = hmin + (range * 7) / 10
192 // Valley threshold: hmin + range * 0.1
193 let valley_t: nx_int = hmin + range / 10
194 var n_peak: nx_int = 0
195 var n_valley: nx_int = 0
196 var j: nx_int = 0
197 while j < n {
198 let v: nx_int = heightmap[j]
199 if v >= peak_t { n_peak = n_peak + 1 }
200 if v <= valley_t { n_valley = n_valley + 1 }
201 j = j + 1
202 }
203 let q: nx_int = NX_CRUMMY_Q
204 // Target: 3-12% peak cells AND 3-12% valley cells.
205 let target_lo: nx_int = (n * 3) / 100
206 let target_hi: nx_int = (n * 12) / 100
207 var peak_score: nx_int = 0
208 if n_peak >= target_lo {
209 if n_peak <= target_hi { peak_score = q }
210 if n_peak > target_hi { peak_score = q - (n_peak - target_hi) * q / n }
211 }
212 if n_peak < target_lo { peak_score = (n_peak * q) / target_lo }
213 var valley_score: nx_int = 0
214 if n_valley >= target_lo {
215 if n_valley <= target_hi { valley_score = q }
216 if n_valley > target_hi { valley_score = q - (n_valley - target_hi) * q / n }
217 }
218 if n_valley < target_lo { valley_score = (n_valley * q) / target_lo }
219 if peak_score < 0 { peak_score = 0 }
220 if valley_score < 0 { valley_score = 0 }
221 return (peak_score + valley_score) / 2
222}
223
224// ===== Internal: biome diversity (Shannon entropy) ================
225func _crummy_biome_diversity_q14(
226 biome_map: *i64, n_cells: nx_int, n_biome_kinds: nx_int
227) -> nx_int {
228 if (biome_map as i64) == 0 { return NX_CRUMMY_Q / 2 } // skip => MARGINAL
229 if n_cells <= 0 { return NX_CRUMMY_Q / 2 }
230 if n_biome_kinds <= 1 { return 0 }
231 let q: nx_int = NX_CRUMMY_Q
232 // Tally biome counts (cap at 16 distinct).
233 let hist: *i64 = (sys_mmap(16 * NX_SIZEOF_NX_INT)) as *i64
234 var i: nx_int = 0
235 while i < 16 { hist[i] = 0; i = i + 1 }
236 var c: nx_int = 0
237 while c < n_cells {
238 let b: nx_int = biome_map[c]
239 var bb: nx_int = b
240 if bb < 0 { bb = 0 }
241 if bb > 15 { bb = 15 }
242 hist[bb] = hist[bb] + 1
243 c = c + 1
244 }
245 // Compute Shannon entropy in Q14.
246 var ent: nx_int = 0
247 var k: nx_int = 0
248 while k < 16 {
249 let cnt: nx_int = hist[k]
250 if cnt > 0 {
251 var bin: nx_int = n_cells / cnt
252 if bin < 1 { bin = 1 }
253 if bin > 16 { bin = 16 }
254 let log_bin: nx_int = _crummy_log2_q14(bin)
255 ent = ent + (cnt * log_bin) / n_cells
256 }
257 k = k + 1
258 }
259 var nb: nx_int = n_biome_kinds
260 if nb > 16 { nb = 16 }
261 let max_ent: nx_int = _crummy_log2_q14(nb)
262 if max_ent <= 0 { return 0 }
263 var norm: nx_int = (ent * q) / max_ent
264 if norm > q { norm = q }
265 if norm < 0 { norm = 0 }
266 return norm
267}
268
269// ===== Internal: palette richness =================================
270// palette_hist: i64 array of counts per palette slot. n_slots = length.
271// Score is fraction of NON-ZERO slots, weighted by their distribution
272// non-uniformity (penalty for one-dominant-color palettes).
273func _crummy_palette_richness_q14(
274 palette_hist: *i64, n_slots: nx_int
275) -> nx_int {
276 if (palette_hist as i64) == 0 { return NX_CRUMMY_Q / 2 }
277 if n_slots <= 0 { return 0 }
278 let q: nx_int = NX_CRUMMY_Q
279 var n_present: nx_int = 0
280 var total: nx_int = 0
281 var max_slot: nx_int = 0
282 var i: nx_int = 0
283 while i < n_slots {
284 let c: nx_int = palette_hist[i]
285 if c > 0 { n_present = n_present + 1 }
286 if c > max_slot { max_slot = c }
287 total = total + c
288 i = i + 1
289 }
290 if total == 0 { return 0 }
291 // Distinct hues: target >= 5; cap at 8.
292 var hue_score: nx_int = (n_present * q) / 8
293 if hue_score > q { hue_score = q }
294 // Dominance penalty: max_slot / total should NOT exceed 0.5.
295 let dom_q: nx_int = (max_slot * q) / total
296 var dom_penalty: nx_int = q
297 if dom_q > q / 2 {
298 // Excess above 0.5 reduces score linearly.
299 let excess: nx_int = dom_q - q / 2
300 dom_penalty = q - excess * 2
301 if dom_penalty < 0 { dom_penalty = 0 }
302 }
303 return (hue_score * dom_penalty) / q
304}
305
306// ===== Internal: horizon variation =================================
307// horizon_samples: i64 array of N height values along the silhouette.
308// Returns Q14 score: normalised stddev of the samples vs the mean.
309func _crummy_horizon_variation_q14(
310 horizon: *i64, n_samples: nx_int, max_relief: nx_int
311) -> nx_int {
312 if (horizon as i64) == 0 { return NX_CRUMMY_Q / 2 }
313 if n_samples <= 1 { return 0 }
314 if max_relief <= 0 { return 0 }
315 let q: nx_int = NX_CRUMMY_Q
316 // Compute mean.
317 var sum: nx_int = 0
318 var i: nx_int = 0
319 while i < n_samples {
320 sum = sum + horizon[i]
321 i = i + 1
322 }
323 let mean: nx_int = sum / n_samples
324 // Compute sum of |x_i - mean|.
325 var abs_dev_sum: nx_int = 0
326 var j: nx_int = 0
327 while j < n_samples {
328 var d: nx_int = horizon[j] - mean
329 if d < 0 { d = 0 - d }
330 abs_dev_sum = abs_dev_sum + d
331 j = j + 1
332 }
333 let mean_abs_dev: nx_int = abs_dev_sum / n_samples
334 // Target: mean_abs_dev = max_relief / 10 (10% as the "interesting" band).
335 let target: nx_int = max_relief / 10
336 if target <= 0 { return 0 }
337 var score: nx_int = (mean_abs_dev * q) / target
338 if score > q { score = q }
339 if score < 0 { score = 0 }
340 return score
341}
342
343// ===== Internal: spatial non-repetition ============================
344// Compares heightmap[i] to heightmap[i + offset] for several offsets;
345// computes mean abs diff. If diffs are LOW (i.e. high auto-correlation),
346// the world repeats and is crummy. Returns Q14 score: higher = less
347// repetitive.
348//
349// Offsets used: w/4, w/3, w/2.
350func _crummy_non_repetition_q14(
351 heightmap: *i64, w: nx_int, h: nx_int, max_relief: nx_int
352) -> nx_int {
353 if w <= 8 { return NX_CRUMMY_Q / 2 }
354 if max_relief <= 0 { return 0 }
355 let q: nx_int = NX_CRUMMY_Q
356 var total_diff: nx_int = 0
357 var n_pairs: nx_int = 0
358 let offsets: *i64 = (sys_mmap(3 * NX_SIZEOF_NX_INT)) as *i64
359 offsets[0] = w / 4
360 offsets[1] = w / 3
361 offsets[2] = w / 2
362 var oi: nx_int = 0
363 while oi < 3 {
364 let off: nx_int = offsets[oi]
365 var y: nx_int = 0
366 while y < h {
367 var x: nx_int = 0
368 while x + off < w {
369 let a: nx_int = heightmap[y * w + x]
370 let b: nx_int = heightmap[y * w + x + off]
371 var d: nx_int = a - b
372 if d < 0 { d = 0 - d }
373 total_diff = total_diff + d
374 n_pairs = n_pairs + 1
375 x = x + 1
376 }
377 y = y + 1
378 }
379 oi = oi + 1
380 }
381 if n_pairs == 0 { return 0 }
382 let mean_diff: nx_int = total_diff / n_pairs
383 // Target: mean_diff > max_relief / 8 (very-different distant cells).
384 let target: nx_int = max_relief / 8
385 if target <= 0 { return 0 }
386 var score: nx_int = (mean_diff * q) / target
387 if score > q { score = q }
388 if score < 0 { score = 0 }
389 return score
390}
391
392// ===== Public: detect crumminess ===================================
393// Inputs:
394// heightmap w*h flat array (required)
395// w, h grid dimensions
396// max_relief expected max relief for normalisation
397// biome_map parallel i64 (optional; pass 0 to skip)
398// n_biome_kinds biome ID space size
399// palette_hist i64 per-color counts (optional; pass 0)
400// n_palette_slots palette histogram length
401// horizon i64 silhouette samples (optional; pass 0)
402// n_horizon sample count
403//
404// Output: LAYER_VERDICT (16 i64). Higher axis scores = LESS crummy.
405// God-said-good = 1 iff all axes >= MARGINAL (0.4Q).
406func nx_crummy_detect(
407 heightmap: *i64, w: nx_int, h: nx_int, max_relief: nx_int,
408 biome_map: *i64, n_biome_kinds: nx_int,
409 palette_hist: *i64, n_palette_slots: nx_int,
410 horizon: *i64, n_horizon: nx_int,
411 out_verdict: *i64
412) {
413 let range_usage: nx_int = _crummy_range_usage_q14(heightmap, w, h, max_relief)
414 let local_contrast: nx_int = _crummy_local_contrast_q14(heightmap, w, h, max_relief)
415 let signature: nx_int = _crummy_signature_peaks_q14(heightmap, w, h, max_relief)
416 let biome: nx_int = _crummy_biome_diversity_q14(biome_map, w * h, n_biome_kinds)
417 let palette: nx_int = _crummy_palette_richness_q14(palette_hist, n_palette_slots)
418 let horizon_score: nx_int = _crummy_horizon_variation_q14(horizon, n_horizon, max_relief)
419 let non_rep: nx_int = _crummy_non_repetition_q14(heightmap, w, h, max_relief)
420
421 nx_layer_verdict_init(out_verdict, NX_LAYER_KIND_READABILITY,
422 NX_CRUMMY_AXIS_COUNT, NX_LAYER_REFINE_IMPROVE_READ)
423 out_verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_RANGE_USAGE] = range_usage
424 out_verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_LOCAL_CONTRAST] = local_contrast
425 out_verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_SIGNATURE_PEAKS] = signature
426 out_verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_BIOME_DIVERSITY] = biome
427 out_verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_PALETTE_RICHNESS] = palette
428 out_verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_HORIZON_VARIATION] = horizon_score
429 out_verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_NON_REPETITION] = non_rep
430 nx_layer_verdict_finalize(out_verdict)
431}
432
433// ===== Public: is_crummy predicate =================================
434// Convenience: returns 1 if the world IS crummy (any axis below 0.3Q
435// or grade <= D); 0 if non-crummy. Caller may use this for the
436// iterative loop: "regenerate if crummy".
437func nx_is_crummy(verdict: *i64) -> nx_int {
438 let g: nx_int = verdict[NX_LV_OFF_GRADE]
439 if g <= NX_LV_GRADE_D { return 1 }
440 let q: nx_int = NX_CRUMMY_Q
441 let threshold: nx_int = (q * 30) / 100 // 0.3Q
442 var i: nx_int = 0
443 while i < NX_CRUMMY_AXIS_COUNT {
444 let s: nx_int = verdict[NX_LV_OFF_AXIS_0 + i]
445 if s < threshold { return 1 }
446 i = i + 1
447 }
448 return 0
449}
450
451// ===== Self-test ====================================================
452func main() -> i64 {
453 let q: nx_int = NX_CRUMMY_Q
454 let verdict: *i64 = (sys_mmap(NX_LV_STRIDE * NX_SIZEOF_NX_INT)) as *i64
455
456 // T1: All-constant heightmap -> crummy (range usage = 0).
457 let w: nx_int = 16
458 let h: nx_int = 16
459 let n: nx_int = w * h
460 let map_flat: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
461 var i: nx_int = 0
462 while i < n { map_flat[i] = 500; i = i + 1 }
463 let null_ptr: *i64 = 0 as *i64
464 nx_crummy_detect(map_flat, w, h, 1000, null_ptr, 0, null_ptr, 0, null_ptr, 0, verdict)
465 if nx_is_crummy(verdict) != 1 { return __syscall(93, 1, 0, 0, 0, 0, 0) }
466 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_RANGE_USAGE] != 0 {
467 return __syscall(93, 2, 0, 0, 0, 0, 0)
468 }
469
470 // T2: Linear ramp 0..1000. Range usage = full Q. Local contrast
471 // OK (mean_diff = ~62, target = 50 -> overshoot a bit but should
472 // be > MARGINAL). Signature peaks: ramp has ~10% peaks and ~10%
473 // valleys -> good. Spatial non-repetition: high diff at distant
474 // cells -> good.
475 let map_ramp: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
476 var j: nx_int = 0
477 while j < n {
478 map_ramp[j] = j * 1000 / n
479 j = j + 1
480 }
481 nx_crummy_detect(map_ramp, w, h, 1000, null_ptr, 0, null_ptr, 0, null_ptr, 0, verdict)
482 // Range usage should be near Q (max - min = 1000-ish out of 1000).
483 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_RANGE_USAGE] < q * 9 / 10 {
484 return __syscall(93, 10, 0, 0, 0, 0, 0)
485 }
486
487 // T3: Biome-diversity skip (NULL biome_map) -> MARGINAL.
488 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_BIOME_DIVERSITY] != q / 2 {
489 return __syscall(93, 20, 0, 0, 0, 0, 0)
490 }
491
492 // T4: Diverse biome map -> high diversity score.
493 let biome_map: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
494 var bi: nx_int = 0
495 while bi < n { biome_map[bi] = bi % 4; bi = bi + 1 } // 4-biome uniform
496 nx_crummy_detect(map_ramp, w, h, 1000, biome_map, 4, null_ptr, 0, null_ptr, 0, verdict)
497 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_BIOME_DIVERSITY] < q * 9 / 10 {
498 return __syscall(93, 30, 0, 0, 0, 0, 0)
499 }
500
501 // T5: All-one-biome map -> 0 diversity.
502 var bi2: nx_int = 0
503 while bi2 < n { biome_map[bi2] = 7; bi2 = bi2 + 1 }
504 nx_crummy_detect(map_ramp, w, h, 1000, biome_map, 4, null_ptr, 0, null_ptr, 0, verdict)
505 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_BIOME_DIVERSITY] != 0 {
506 return __syscall(93, 40, 0, 0, 0, 0, 0)
507 }
508
509 // T6: Palette richness: 4 evenly distributed colors -> high.
510 let palette: *i64 = (sys_mmap(8 * NX_SIZEOF_NX_INT)) as *i64
511 palette[0] = 10
512 palette[1] = 10
513 palette[2] = 10
514 palette[3] = 10
515 palette[4] = 0
516 palette[5] = 0
517 palette[6] = 0
518 palette[7] = 0
519 nx_crummy_detect(map_ramp, w, h, 1000, null_ptr, 0, palette, 8, null_ptr, 0, verdict)
520 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_PALETTE_RICHNESS] < q * 3 / 10 {
521 return __syscall(93, 50, 0, 0, 0, 0, 0)
522 }
523 // All-one-color palette -> low score (high dominance penalty).
524 palette[0] = 100
525 palette[1] = 0
526 palette[2] = 0
527 palette[3] = 0
528 nx_crummy_detect(map_ramp, w, h, 1000, null_ptr, 0, palette, 8, null_ptr, 0, verdict)
529 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_PALETTE_RICHNESS] >= q / 4 {
530 return __syscall(93, 51, 0, 0, 0, 0, 0)
531 }
532
533 // T7: Horizon variation -- flat horizon = 0, varied = high.
534 let horizon_flat: *i64 = (sys_mmap(32 * NX_SIZEOF_NX_INT)) as *i64
535 var hi: nx_int = 0
536 while hi < 32 { horizon_flat[hi] = 500; hi = hi + 1 }
537 nx_crummy_detect(map_ramp, w, h, 1000, null_ptr, 0, null_ptr, 0, horizon_flat, 32, verdict)
538 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_HORIZON_VARIATION] != 0 {
539 return __syscall(93, 60, 0, 0, 0, 0, 0)
540 }
541 // Varied horizon: alternating high/low.
542 let horizon_var: *i64 = (sys_mmap(32 * NX_SIZEOF_NX_INT)) as *i64
543 var hv: nx_int = 0
544 while hv < 32 {
545 if hv % 2 == 0 { horizon_var[hv] = 100 }
546 if hv % 2 == 1 { horizon_var[hv] = 500 }
547 hv = hv + 1
548 }
549 nx_crummy_detect(map_ramp, w, h, 1000, null_ptr, 0, null_ptr, 0, horizon_var, 32, verdict)
550 if verdict[NX_LV_OFF_AXIS_0 + NX_CRUMMY_AXIS_HORIZON_VARIATION] < q * 9 / 10 {
551 return __syscall(93, 61, 0, 0, 0, 0, 0)
552 }
553
554 // T8: nx_is_crummy on the all-constant map = crummy.
555 nx_crummy_detect(map_flat, w, h, 1000, null_ptr, 0, null_ptr, 0, null_ptr, 0, verdict)
556 if nx_is_crummy(verdict) != 1 { return __syscall(93, 70, 0, 0, 0, 0, 0) }
557
558 // T9: A varied heightmap with diverse biome + palette + horizon is
559 // NOT crummy.
560 let map_complex: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
561 var mi: nx_int = 0
562 while mi < n {
563 let x: nx_int = mi % w
564 let y: nx_int = mi / w
565 let d2: nx_int = (x - 8) * (x - 8) + (y - 8) * (y - 8)
566 var v: nx_int = 800 - d2 * 10
567 if v < 0 { v = 0 }
568 if (x + y) % 2 == 0 { v = v + 50 }
569 map_complex[mi] = v
570 mi = mi + 1
571 }
572 var bi3: nx_int = 0
573 while bi3 < n {
574 if map_complex[bi3] > 600 { biome_map[bi3] = 12 }
575 if map_complex[bi3] <= 600 {
576 if map_complex[bi3] > 300 { biome_map[bi3] = 5 }
577 if map_complex[bi3] <= 300 { biome_map[bi3] = 8 }
578 }
579 bi3 = bi3 + 1
580 }
581 palette[0] = 10
582 palette[1] = 10
583 palette[2] = 10
584 palette[3] = 10
585 palette[4] = 10
586 palette[5] = 0
587 palette[6] = 0
588 palette[7] = 0
589 nx_crummy_detect(map_complex, w, h, 1000, biome_map, 16, palette, 8, horizon_var, 32, verdict)
590 // Not crummy: grade >= C and no axis below 0.3Q.
591 // (We don't insist on B+ -- caller's meta_verdict handles that.)
592 if verdict[NX_LV_OFF_GRADE] < NX_LV_GRADE_D {
593 return __syscall(93, 80, 0, 0, 0, 0, 0)
594 }
595
596 return 0
597}