code wiki / (root) / nx_colonize_gate.nx

nx_colonize_gate.nx source

↩ module page · 139 lines · 6697 B

1// nx_colonize_gate.nx -- PG21: DO TREES GROW BY COMPETITION FOR SPACE, AND DOES THE CANOPY MATCH THE LAYOUT? 2// 3// SUBJECT: nx_treegen.tg_colonize (in-process) fed by nx_forest_layout's OWN species params (in-process), so the 4// envelope the grower is asked for is the envelope the LIVE layout will place it in. The rung's done-rule in its own 5// words: distinct seeds yield distinct branching, and the canopy envelope matches the layout's species params. 6// Every value is emitted with gv_kv; the per-species numbers name any failing species without a second run. 7import "nx_syscalls.nx" 8import "nx_gate_verdict.nx" 9import "nx_treegen.nx" 10import "nx_forest_layout.nx" 11const CG_UNITS_NUM: i64 = 640 // tree units per CG_UNITS_DEN forest Q: the tallest species (pine, 25000 Q) spans 640 units 12const CG_UNITS_DEN: i64 = 25000 13const CG_SEED: i64 = 2026 14const CG_SEEDS: i64 = 8 15const CG_R_LO: i64 = 550 // measured crown reach as permil of the requested radius: lower and upper bands 16const CG_R_HI: i64 = 1100 17const CG_H_LO: i64 = 800 // measured height as permil of the requested height 18const CG_H_HI: i64 = 1100 19const CG_LEAF_R: i64 = 22 20const CG_TINY_H: i64 = 30 // the neg-control envelope: a crown narrower than one step 21const CG_TINY_R: i64 = 1 22const CG_TINY_MAXP: i64 = 20 23const CG_PARAMS: i64 = 3 24// trunk fraction per species, permil of height: the crown base the layout's silhouettes imply 25func cg_trunk_permil(species: i64) -> i64 { 26 if species == NX_TREE_OAK { return 350 } 27 if species == NX_TREE_PINE { return 200 } 28 if species == NX_TREE_BIRCH { return 400 } 29 if species == NX_TREE_SPRUCE { return 150 } 30 if species == NX_TREE_WILLOW { return 300 } 31 if species == NX_TREE_MAPLE { return 350 } 32 if species == NX_TREE_DEAD { return 450 } 33 if species == NX_TREE_PALM { return 850 } 34 return 350 35} 36// grow one species from the LIVE layout's params; prm receives height, crown radius, trunk radius in tree units 37func cg_grow(P: *i64, seed: i64, species: i64, prm: *i64) -> i64 { 38 let q: *i64 = sys_mmap(64) as *i64 39 _forest_species_params(species, q) 40 prm[0] = q[0]*CG_UNITS_NUM/CG_UNITS_DEN 41 prm[1] = q[1]*CG_UNITS_NUM/CG_UNITS_DEN 42 prm[2] = q[2]*CG_UNITS_NUM/CG_UNITS_DEN 43 if prm[2] < TG_COL_RMIN { prm[2] = TG_COL_RMIN } 44 var lr: i64 = CG_LEAF_R 45 if q[1] == 0 { lr = 0 } 46 return tg_colonize(P, seed, prm[0], prm[1], cg_trunk_permil(species), prm[2], lr) 47} 48func cg_same(P: *i64, np: i64, Q: *i64, nq: i64) -> i64 { 49 if np != nq { return 0 } 50 var k: i64 = 0 51 while k < np*TG_STR { 52 if P[k] != Q[k] { return 0 } 53 k = k + 1 54 } 55 return 1 56} 57 58func main() -> i64 { 59 let ctr: *i64 = gv_ctr() 60 gv_head("=== NX-COLONIZE gate (PG21): space colonization grows distinct trees that fill the layout's envelope ===" as *u8) 61 let P: *i64 = sys_mmap(TG_CAP*TG_STR*8) as *i64 62 let Q: *i64 = sys_mmap(TG_CAP*TG_STR*8) as *i64 63 let prm: *i64 = sys_mmap(32) as *i64 64 let env: *i64 = sys_mmap(64) as *i64 65 // 1. every layout species grows inside the band the layout asked for 66 var env_ok: i64 = 1 67 var bounded: i64 = 1 68 var pipe_ok: i64 = 1 69 var dead_leafless: i64 = 1 70 var grown: i64 = 0 71 var s: i64 = 0 72 let base_y: i64 = 0 - TG_COL_BASE_Y 73 let rperm: *i64 = sys_mmap(64) as *i64 74 let hperm: *i64 = sys_mmap(64) as *i64 75 let npk: *i64 = sys_mmap(64) as *i64 76 while s < NX_TREE_SPECIES_COUNT { 77 let np: i64 = cg_grow(P, CG_SEED, s, prm) 78 npk[s] = np 79 if np > 0 { grown = grown + 1 } 80 if np > TG_CAP { bounded = 0 } 81 tg_col_envelope(P, np, env) 82 hperm[s] = (env[0] - base_y)*1000/prm[0] 83 if hperm[s] < CG_H_LO { env_ok = 0 } 84 if hperm[s] > CG_H_HI { env_ok = 0 } 85 if prm[1] > 0 { 86 rperm[s] = env[1]*1000/prm[1] 87 if rperm[s] < CG_R_LO { env_ok = 0 } 88 if rperm[s] > CG_R_HI { env_ok = 0 } 89 } else { 90 rperm[s] = 0 91 if env[3] != 0 { dead_leafless = 0 } 92 } 93 if env[4] != prm[2] { pipe_ok = 0 } 94 if env[5] < TG_COL_RMIN { pipe_ok = 0 } 95 s = s + 1 96 } 97 gv_check("every-layout-species-grows (parts > 0 for all 8)" as *u8, (grown == NX_TREE_SPECIES_COUNT) as i64, ctr) 98 gv_check("envelope-matches-the-layout: height and crown reach inside the bands for every species with a canopy" as *u8, env_ok, ctr) 99 gv_check("a-canopy-of-zero-grows-no-leaves (the dead species)" as *u8, dead_leafless, ctr) 100 gv_check("parts-bounded-by-TG_CAP for every species" as *u8, bounded, ctr) 101 gv_check("pipe-model: the thickest capsule IS the trunk radius and no capsule is thinner than TG_COL_RMIN" as *u8, pipe_ok, ctr) 102 // 2. determinism and distinct seeds on the oak 103 let np1: i64 = cg_grow(P, 1, NX_TREE_OAK, prm) 104 let np2: i64 = cg_grow(Q, 1, NX_TREE_OAK, prm) 105 gv_check("determinism: the same seed grows the same tree, every part byte-equal" as *u8, cg_same(P, np1, Q, np2), ctr) 106 var distinct_pairs: i64 = 0 107 var pairs: i64 = 0 108 var i: i64 = 1 109 while i <= CG_SEEDS { 110 let na: i64 = cg_grow(P, i, NX_TREE_OAK, prm) 111 var j: i64 = i + 1 112 while j <= CG_SEEDS { 113 let nb: i64 = cg_grow(Q, j, NX_TREE_OAK, prm) 114 pairs = pairs + 1 115 if cg_same(P, na, Q, nb) == 0 { distinct_pairs = distinct_pairs + 1 } 116 j = j + 1 117 } 118 i = i + 1 119 } 120 gv_check_eq("distinct-seeds-distinct-branching: every seed pair differs (denominator bound: pairs)" as *u8, distinct_pairs, pairs, ctr) 121 gv_check("pairs-denominator-is-the-declared-8-choose-2" as *u8, (pairs == CG_SEEDS*(CG_SEEDS-1)/2) as i64, ctr) 122 // 3. neg-control: an envelope narrower than one step still grows a trunk and nothing wild 123 let npt: i64 = tg_colonize(P, CG_SEED, CG_TINY_H, CG_TINY_R, 500, TG_COL_RMIN, CG_LEAF_R) 124 gv_check("neg-control-tiny-envelope: grows at least the trunk and fewer than CG_TINY_MAXP parts" as *u8, ((npt >= 1) as i64) * ((npt < CG_TINY_MAXP) as i64), ctr) 125 gv_values_head() 126 var s2: i64 = 0 127 while s2 < NX_TREE_SPECIES_COUNT { 128 gv_kv("species" as *u8, s2) 129 gv_kv("parts" as *u8, npk[s2]) 130 gv_kv("height_permil_of_requested" as *u8, hperm[s2]) 131 gv_kv("crown_reach_permil_of_requested" as *u8, rperm[s2]) 132 s2 = s2 + 1 133 } 134 gv_kv("oak_seed1_parts" as *u8, np1) 135 gv_kv("distinct_pairs" as *u8, distinct_pairs) 136 gv_kv("pairs" as *u8, pairs) 137 gv_kv("tiny_envelope_parts" as *u8, npt) 138 return gv_verdict("NX-COLONIZE" as *u8, ctr, "trees are grown by competition for space inside the envelope the layout asks for, then placed" as *u8) 139}