code wiki / (root) / nx_crummy_detector.nx

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}