nx_world_grade.nx source
↩ module page · 224 lines · 8518 B
1// nx_world_grade.nx -- GRADE A LIVE nx_wasm_craft WORLD WITH nx_world_quality_grader.
2//
3// The gap this closes, measured 2026-09-01: nx_world_quality_grader.nx had shipped on
4// 2026-05-16 and had NEVER BEEN BUILT, and even once built it takes a heightmap ARRAY in
5// process and has no argv -- so it could not be pointed at any world that actually exists.
6// The published /world/beach page had no referee at all. This organ is the missing arm: it
7// runs the SAME engine source the page wasm is compiled from (nx_wasm_craft as a lib, which
8// nx_world_snap already does natively) and hands the grader the real terrain.
9//
10// NO DUPLICATE RULER IS CREATED HERE. The terrain comes from the engine own mob_ground, the
11// verdict comes from the shipped grader, and this file only composes the two and prints.
12//
13// usage: nx_world_grade <identity_v> <seed> [ticks]
14// identity_v 2 + seed 20260728 IS the served beach: sites/nishifamily/world/beach.html
15// carries const NXV=2 and ex.init_v(BigInt(NXV),BigInt(20260728)).
16// exit: 0 graded | 2 usage
17//
18// SCOPE, DECLARED SO THE NUMBER CANNOT BE OVER-READ: the heightmap axes are measured from
19// the live world; BIOME_COHERENCE and FEATURE_VARIETY are NOT supplied, so the grader
20// abstains on them (score 0, verdict MARGINAL) and the grade therefore CANNOT reach S by
21// construction. That ceiling is printed beside the grade rather than left for the reader to
22// discover. license_tier: ORIGINAL No hw writes (Rule 26).
23import "nx_wasm_craft.nx"
24import "nx_world_quality_grader.nx"
25
26const WGD_PAD: i64 = 4096 // the slack nx_world_snap also leaves past CRAFT_TOTAL
27const WGD_ARGC_MIN: i64 = 3 // program + identity + seed
28const WGD_ARGC_TICKS: i64 = 4
29const WGD_EXIT_USAGE: i64 = 2
30const WGD_NUMBUF: i64 = 32
31const WGD_TICK_MS: i64 = 16 // the engine frame budget nx_world_snap ticks with
32const WGD_ASCII_ZERO: i64 = 48
33const WGD_ASCII_NINE: i64 = 57
34const WGD_ASCII_MINUS: i64 = 45
35const WGD_TEN: i64 = 10
36const WGD_PERMIL: i64 = 1000
37
38func wgd_slen(s: *u8) -> i64 {
39 var i: i64 = 0
40 while s[i] != (0 as u8) { i = i + 1 }
41 return i
42}
43
44func wgd_puts(s: *u8) -> i64 {
45 sys_write(1, s, wgd_slen(s))
46 return 0
47}
48
49func wgd_putn(v: i64) -> i64 {
50 if v == 0 {
51 sys_write(1, "0" as *u8, 1)
52 return 0
53 }
54 var m: i64 = v
55 if m < 0 {
56 sys_write(1, "-" as *u8, 1)
57 m = 0 - m
58 }
59 let t: *u8 = sys_mmap(WGD_NUMBUF)
60 var k: i64 = 0
61 while m > 0 {
62 t[k] = ((m % WGD_TEN) + WGD_ASCII_ZERO) as u8
63 m = m / WGD_TEN
64 k = k + 1
65 }
66 let o: *u8 = sys_mmap(WGD_NUMBUF)
67 var j: i64 = 0
68 while j < k {
69 o[j] = t[k - 1 - j]
70 j = j + 1
71 }
72 sys_write(1, o, k)
73 sys_munmap(t, WGD_NUMBUF)
74 sys_munmap(o, WGD_NUMBUF)
75 return 0
76}
77
78func wgd_row(label: *u8, val: i64) -> i64 {
79 wgd_puts(label)
80 wgd_putn(val)
81 wgd_puts("\n" as *u8)
82 return 0
83}
84
85// Q14 score rendered in permil beside its raw value, because a reader comparing axes should
86// not have to divide by 16384 in their head to see which one lost.
87func wgd_axis(label: *u8, q: i64) -> i64 {
88 wgd_puts(label)
89 wgd_putn(q)
90 wgd_puts(" q14 permil=" as *u8)
91 wgd_putn((q * WGD_PERMIL) / NX_WQG_Q)
92 if q >= NX_WQG_AXIS_WIN_FLOOR { wgd_puts(" WIN\n" as *u8) }
93 if q < NX_WQG_AXIS_WIN_FLOOR {
94 if q >= NX_WQG_AXIS_MARGINAL_FLOOR { wgd_puts(" MARGINAL\n" as *u8) }
95 if q < NX_WQG_AXIS_MARGINAL_FLOOR { wgd_puts(" LOSS\n" as *u8) }
96 }
97 return 0
98}
99
100func wgd_grade_word(g: i64) -> *u8 {
101 if g == NX_GRADE_F { return "F" as *u8 }
102 if g == NX_GRADE_D { return "D" as *u8 }
103 if g == NX_GRADE_C { return "C" as *u8 }
104 if g == NX_GRADE_B { return "B" as *u8 }
105 if g == NX_GRADE_A { return "A" as *u8 }
106 if g == NX_GRADE_S { return "S" as *u8 }
107 return "UNKNOWN-GRADE" as *u8
108}
109
110func wgd_refine_word(r: i64) -> *u8 {
111 if r == NX_WQG_REFINE_NONE { return "NONE" as *u8 }
112 if r == NX_WQG_REFINE_MORE_RELIEF { return "MORE_RELIEF" as *u8 }
113 if r == NX_WQG_REFINE_MORE_FEATURES { return "MORE_FEATURES" as *u8 }
114 if r == NX_WQG_REFINE_LESS_FLATNESS { return "LESS_FLATNESS" as *u8 }
115 if r == NX_WQG_REFINE_ADD_DETAIL { return "ADD_DETAIL" as *u8 }
116 if r == NX_WQG_REFINE_SMOOTH_NOISE { return "SMOOTH_NOISE" as *u8 }
117 if r == NX_WQG_REFINE_FIX_FRACTAL { return "FIX_FRACTAL" as *u8 }
118 if r == NX_WQG_REFINE_FIX_BIOMES { return "FIX_BIOMES" as *u8 }
119 if r == NX_WQG_REFINE_MORE_VARIETY { return "MORE_VARIETY" as *u8 }
120 if r == NX_WQG_REFINE_IMPROVE_READ { return "IMPROVE_READ" as *u8 }
121 return "UNKNOWN-REFINE" as *u8
122}
123
124func wgd_num(s: *u8) -> i64 {
125 var i: i64 = 0
126 var neg: i64 = 0
127 if s[0] == (WGD_ASCII_MINUS as u8) {
128 neg = 1
129 i = 1
130 }
131 var acc: i64 = 0
132 while s[i] != (0 as u8) {
133 let c: i64 = s[i] as i64
134 if c >= WGD_ASCII_ZERO {
135 if c <= WGD_ASCII_NINE { acc = acc * WGD_TEN + (c - WGD_ASCII_ZERO) }
136 }
137 i = i + 1
138 }
139 if neg == 1 { return 0 - acc }
140 return acc
141}
142
143func main(argc: i64, argv: *i64) -> i64 {
144 if argc < WGD_ARGC_MIN {
145 wgd_puts("usage: nx_world_grade <identity_v> <seed> [ticks]\n" as *u8)
146 wgd_puts(" the served beach is identity 2 seed 20260728\n" as *u8)
147 return WGD_EXIT_USAGE
148 }
149 let v: i64 = wgd_num(argv[1] as *u8)
150 let seed: i64 = wgd_num(argv[2] as *u8)
151 var ticks: i64 = 0
152 if argc >= WGD_ARGC_TICKS { ticks = wgd_num(argv[3] as *u8) }
153
154 wgd_puts("NX-WORLD-GRADE nx_wasm_craft world graded by nx_world_quality_grader\n" as *u8)
155 wgd_row("identity_v=" as *u8, v)
156 wgd_row("seed=" as *u8, seed)
157 wgd_row("ticks=" as *u8, ticks)
158
159 let base: i64 = sys_mmap(CRAFT_TOTAL + WGD_PAD) as i64
160 init_impl_v(base, v, seed)
161 var t: i64 = 0
162 while t < ticks {
163 tick_impl(base, WGD_TICK_MS)
164 t = t + 1
165 }
166
167 // THE HEIGHTMAP IS THE ENGINE OWN ANSWER, NOT A RE-IMPLEMENTATION: mob_ground walks the
168 // column from the sky down and returns the topmost solid block, which is exactly the
169 // surface a player stands on. A column with no solid block at all answers -1; those are
170 // clamped to 0 for the grader AND COUNTED, because an uncounted clamp is a fabricated
171 // measurement and the count is the only thing that says how much of the grid was real.
172 let n: i64 = WX * WZ
173 let hmap: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
174 var empty_cols: i64 = 0
175 var z: i64 = 0
176 while z < WZ {
177 var x: i64 = 0
178 while x < WX {
179 var g: i64 = mob_ground(base, x, WY - 1, z)
180 if g < 0 {
181 g = 0
182 empty_cols = empty_cols + 1
183 }
184 hmap[z * WX + x] = g
185 x = x + 1
186 }
187 z = z + 1
188 }
189
190 wgd_row("grid_w=" as *u8, WX)
191 wgd_row("grid_h=" as *u8, WZ)
192 wgd_row("cells=" as *u8, n)
193 wgd_row("max_expected_relief=" as *u8, WY)
194 wgd_row("columns_with_no_solid_block=" as *u8, empty_cols)
195
196 let out: *i64 = (sys_mmap(NX_WQG_OUT_STRIDE * NX_SIZEOF_NX_INT)) as *i64
197 let nullp: *i64 = 0 as *i64
198 nx_world_quality_grade(hmap, WX, WZ, WY, nullp, nullp, 0, out)
199
200 wgd_puts("min_height=" as *u8)
201 wgd_putn(out[NX_WQG_OFF_MIN_HEIGHT])
202 wgd_puts(" max_height=" as *u8)
203 wgd_putn(out[NX_WQG_OFF_MAX_HEIGHT])
204 wgd_puts("\n" as *u8)
205
206 wgd_axis("DIVERSITY = " as *u8, out[NX_WQG_OFF_DIVERSITY])
207 wgd_axis("LOCAL_VARIATION = " as *u8, out[NX_WQG_OFF_LOCAL_VAR])
208 wgd_axis("EXTREMES = " as *u8, out[NX_WQG_OFF_EXTREMES])
209 wgd_axis("FLATNESS_PENALTY = " as *u8, out[NX_WQG_OFF_FLATNESS_PENALTY])
210 wgd_puts(" (FLATNESS is INVERTED: higher means flatter means worse)\n" as *u8)
211 wgd_axis("FRACTAL_DIM = " as *u8, out[NX_WQG_OFF_FRACTAL_DIM])
212 wgd_axis("READABILITY = " as *u8, out[NX_WQG_OFF_READABILITY])
213 wgd_puts("BIOME_COHERENCE = NOT SUPPLIED -- the grader abstains (MARGINAL), it does not acquit\n" as *u8)
214 wgd_puts("FEATURE_VARIETY = NOT SUPPLIED -- the grader abstains (MARGINAL), it does not acquit\n" as *u8)
215 wgd_puts("CEILING: with two axes abstaining this world CANNOT reach S; the grade below is bounded above by A\n" as *u8)
216
217 wgd_puts("refine_axis=" as *u8)
218 wgd_puts(wgd_refine_word(out[NX_WQG_OFF_REFINE_AXIS]))
219 wgd_puts("\n" as *u8)
220 wgd_puts("grade=" as *u8)
221 wgd_puts(wgd_grade_word(out[NX_WQG_OFF_GRADE]))
222 wgd_puts("\n" as *u8)
223 return 0
224}