nx_indoorgen_lib.nx source
↩ module page · 428 lines · 19111 B
1// nx_indoorgen_lib.nx -- GR6 INDOOR ROOMS BY CONSTRAINT SOLVE (the Infinigen 2.0 expansion,
2// /compare/graphics watch contract ig_room_solve, operator 2026-08-17 "properly emitting in the
3// infinigen way"). COMPOSES the incumbent solver (nx_part_solver_lib, the Infinigen-Indoors
4// transfer) -- one solver in the estate; this file only DECLARES rooms and consumes solutions.
5//
6// Shape: an ARCHETYPE (cottage / hut / stonecot) is data rows here; ig_room_solve(arch,variant,salt)
7// builds a declarative constraint set in memory (envelope + pairwise noclip + door clearance +
8// wall-hug bands + mate face rows), runs ps_solve, then QUANTIZES the solved placements to voxel
9// cells and enforces the pre-declared ACCEPT RULE:
10// solved AND quantized-disjoint AND door-approach-free AND all-inside.
11// A set that cannot satisfy is REFUSED (return 0, nothing emitted) -- never overlapped furniture.
12// Variants differ by hashed initial placements (different local optima of the SAME constraints --
13// the Infinigen pattern: one program, seeded variation). The world engine consumes only the
14// emitted DATA TABLE (nx_indoorgen_data.nx, written by the nx_indoorgen CLI): the wasm worlds
15// never run the solver, so the solver's mmap arena never meets the wasm memory bound.
16// license_tier: ORIGINAL
17
18import "nx_syscalls.nx"
19import "nx_part_solver_lib.nx"
20
21const IG_CELL: i64 = 16 // solver units per voxel cell (extents are half-units)
22const IG_NARCH: i64 = 3
23const IG_NVAR: i64 = 4
24const IG_SALTS: i64 = 8 // deterministic re-rolls before a variant is REFUSED (4 was
25 // measured too few: cottage var3 died on a clear-by-4-units
26 // local optimum at every one of 4 starts; 8 clears it)
27const IG_MAXF: i64 = 16 // emitted furniture rows cap per (arch,variant)
28const IG_CONF_CAP: i64 = 8192
29const IG_NEGCTL: i64 = 99 // the named negative control: a 1x2 room that CANNOT hold a bed
30const IG_NOCLIP_GAP: i64 = 16 // one full cell -> quantized cells can touch, never overlap
31const IG_HUG_LO: i64 = 24 // wall-hug band: off-center, toward the wall ring
32const IG_HUG_HI: i64 = 72
33const IG_MATE_LO: i64 = 16 // mate band: adjacent cells (stool by its table/bed)
34const IG_MATE_HI: i64 = 28
35
36// furniture part kinds
37const IGK_PLAIN: i64 = 1 // one cell, one block at floor+1
38const IGK_BED: i64 = 2 // two cells along the facing axis, white bedding blocks
39const IGK_HEARTH: i64 = 3 // one cell, stone at floor+1 and an ember glow at floor+2
40
41// block ids AS THE ENGINE PALETTE READS THEM (wcol): named here, consumed as data downstream
42const IG_BLK_STONE: i64 = 3
43const IG_BLK_SAND: i64 = 5
44const IG_BLK_WOOD: i64 = 6
45const IG_BLK_SCRUB: i64 = 7 // leaves slot -- reads as thatch on the hut roof
46const IG_BLK_BED: i64 = 8 // snow slot -- reads as white bedding indoors
47const IG_BLK_EMBER: i64 = 11 // gold slot -- the hearth glow
48
49// packed part-row fields (all under bit 31 -- no wide shifts anywhere in this file)
50const IGP_KIND_MASK: i64 = 15 // bits 0-3
51const IGP_BLK_SH: i64 = 4 // bits 4-7
52const IGP_EX_SH: i64 = 8 // bits 8-13
53const IGP_EY_SH: i64 = 14 // bits 14-19
54const IGP_CLR_SH: i64 = 20 // bits 20-26 (door clearance, solver units)
55const IGP_HUG_SH: i64 = 27 // bit 27 (wall-hug band)
56const IGP_MATE_SH: i64 = 28 // bits 28-30 (mate part index + 1)
57
58static IG_CONF: i64
59static IG_ROWS: i64 // accepted rows: cx | cz<<8 | block<<16 | dy<<24
60static IG_NROWS: i64
61static IG_LASTWHY: i64 // 0 ok / 1 solver-refused / 2 quantize-collision
62
63func ig_reset() -> i64 {
64 if IG_CONF == 0 {
65 IG_CONF = sys_mmap(IG_CONF_CAP) as i64
66 IG_ROWS = sys_mmap(IG_MAXF*8) as i64
67 }
68 IG_NROWS = 0
69 IG_LASTWHY = 0
70 return 0
71}
72
73func ig_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
74
75func ig_ws(b: *u8, p: i64, s: *u8) -> i64 {
76 var i: i64 = 0
77 while s[i] != (0 as u8) { b[p + i] = s[i]; i = i + 1 }
78 return p + i
79}
80
81func ig_wn(b: *u8, p: i64, v: i64) -> i64 {
82 var q: i64 = p
83 var u: i64 = v
84 if u < 0 { b[q] = 45 as u8; q = q + 1; u = 0 - u }
85 var tmp: i64 = u
86 var nd: i64 = 1
87 while tmp >= 10 { tmp = tmp/10; nd = nd + 1 }
88 var k: i64 = nd - 1
89 while k >= 0 {
90 var dpow: i64 = 1
91 var j: i64 = 0
92 while j < k { dpow = dpow*10; j = j + 1 }
93 b[q] = (48 + (u/dpow) % 10) as u8
94 q = q + 1
95 k = k - 1
96 }
97 return q
98}
99
100// deterministic mul-add-shift mix (the estate's xor-free idiom); always non-negative
101func ig_hash(a: i64, b2: i64) -> i64 {
102 var h: i64 = a*374761393 + b2*668265263 + 1442695041
103 h = h + (h >> 13)
104 h = h*1274126177
105 h = h + (h >> 16)
106 if h < 0 { h = 0 - h }
107 return h
108}
109
110// ---------- ARCHETYPE CANON (data rows; the emitted table mirrors dims/mats and the gate's
111// freshness tooth byte-pins the mirror, so the duplicate cannot drift) ----------
112// dims: interior cells w | d<<8 | wall-height<<16
113func ig_dims(arch: i64) -> i64 {
114 if arch == 1 { return 5 | (4 << 8) | (3 << 16) } // HUT (shore)
115 if arch == 2 { return 6 | (5 << 8) | (3 << 16) } // STONECOT (vale)
116 if arch == IG_NEGCTL { return 1 | (2 << 8) | (3 << 16) } // neg-control: cannot hold a bed
117 return 6 | (5 << 8) | (3 << 16) // COTTAGE (craft)
118}
119// mats: wall | floor<<8 | roof<<16
120func ig_mats(arch: i64) -> i64 {
121 if arch == 1 { return IG_BLK_WOOD | (IG_BLK_SAND << 8) | (IG_BLK_SCRUB << 16) }
122 if arch == 2 { return IG_BLK_STONE | (IG_BLK_WOOD << 8) | (IG_BLK_WOOD << 16) }
123 return IG_BLK_WOOD | (IG_BLK_STONE << 8) | (IG_BLK_WOOD << 16)
124}
125func ig_doorx(arch: i64) -> i64 { return (ig_dims(arch) & 255)/2 }
126
127func ig_nparts(arch: i64) -> i64 {
128 if arch == 1 { return 3 }
129 if arch == 2 { return 4 }
130 if arch == IG_NEGCTL { return 1 }
131 return 5
132}
133
134func ig_mkpart(kind: i64, blk: i64, ex: i64, ey: i64, clr: i64, hug: i64, mate: i64) -> i64 {
135 return kind | (blk << IGP_BLK_SH) | (ex << IGP_EX_SH) | (ey << IGP_EY_SH) | (clr << IGP_CLR_SH) | (hug << IGP_HUG_SH) | (mate << IGP_MATE_SH)
136}
137
138// part table per archetype: bed / table / stool / chest / hearth as constraint DATA
139func ig_part(arch: i64, i: i64) -> i64 {
140 if arch == 1 {
141 if i == 0 { return ig_mkpart(IGK_BED, IG_BLK_BED, 16, 8, 44, 1, 0) }
142 if i == 1 { return ig_mkpart(IGK_PLAIN, IG_BLK_WOOD, 8, 8, 36, 1, 0) } // chest
143 return ig_mkpart(IGK_PLAIN, IG_BLK_WOOD, 8, 8, 32, 0, 1) // stool by the bed
144 }
145 if arch == 2 {
146 if i == 0 { return ig_mkpart(IGK_BED, IG_BLK_BED, 16, 8, 44, 1, 0) }
147 if i == 1 { return ig_mkpart(IGK_PLAIN, IG_BLK_WOOD, 8, 8, 36, 0, 0) } // table
148 if i == 2 { return ig_mkpart(IGK_PLAIN, IG_BLK_WOOD, 8, 8, 36, 1, 0) } // chest
149 return ig_mkpart(IGK_HEARTH, IG_BLK_STONE, 8, 8, 44, 1, 0)
150 }
151 if arch == IG_NEGCTL {
152 return ig_mkpart(IGK_BED, IG_BLK_BED, 16, 8, 0, 0, 0)
153 }
154 if i == 0 { return ig_mkpart(IGK_BED, IG_BLK_BED, 16, 8, 44, 1, 0) }
155 if i == 1 { return ig_mkpart(IGK_PLAIN, IG_BLK_WOOD, 8, 8, 36, 0, 0) } // table
156 if i == 2 { return ig_mkpart(IGK_PLAIN, IG_BLK_WOOD, 8, 8, 32, 0, 2) } // stool by the table
157 if i == 3 { return ig_mkpart(IGK_PLAIN, IG_BLK_WOOD, 8, 8, 36, 1, 0) } // chest
158 return ig_mkpart(IGK_HEARTH, IG_BLK_STONE, 8, 8, 44, 1, 0)
159}
160
161func ig_pname(b: *u8, p: i64, i: i64) -> i64 {
162 var q: i64 = ig_ws(b, p, "p" as *u8)
163 return ig_wn(b, q, i)
164}
165
166// the accept-rule checker, callable on ANY row set (the gate proves it can FIRE on a planted bad)
167func ig_ck_accept(rows: *i64, nr: i64, w: i64, d: i64, doorx: i64) -> i64 {
168 var i: i64 = 0
169 while i < nr {
170 let cx: i64 = rows[i] & 255
171 let cz: i64 = (rows[i] >> 8) & 255
172 let dy: i64 = (rows[i] >> 24) & 255
173 if cx < 0 { return 0 }
174 if cx >= w { return 0 }
175 if cz < 0 { return 0 }
176 if cz >= d { return 0 }
177 if dy == 1 {
178 if cx == doorx { if cz <= 1 { return 0 } } // the door approach stays walkable
179 var j: i64 = i + 1
180 while j < nr {
181 if ((rows[j] >> 24) & 255) == 1 {
182 if (rows[j] & 255) == cx { if ((rows[j] >> 8) & 255) == cz { return 0 } }
183 }
184 j = j + 1
185 }
186 }
187 i = i + 1
188 }
189 return 1
190}
191
192// ---------- THE WATCH SYMBOL: build the constraint set, solve, quantize, accept-or-refuse ----------
193func ig_room_solve(arch: i64, variant: i64, salt: i64) -> i64 {
194 ig_reset()
195 let dims: i64 = ig_dims(arch)
196 let w: i64 = dims & 255
197 let d: i64 = (dims >> 8) & 255
198 let hw: i64 = w*IG_CELL/2
199 let hd: i64 = d*IG_CELL/2
200 let np: i64 = ig_nparts(arch)
201 let b: *u8 = IG_CONF as *u8
202 var p: i64 = 0
203 // shell + door datum (the door is architecture, typed; furniture is SOLVED)
204 p = ig_ws(b, p, "part shell 0 0 0 0\n" as *u8)
205 p = ig_ws(b, p, "extent shell " as *u8); p = ig_wn(b, p, hw)
206 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, hd)
207 p = ig_ws(b, p, " 8\npart door 0 0 0 0\nattach door shell 0 " as *u8)
208 p = ig_wn(b, p, 0 - hd)
209 p = ig_ws(b, p, " 0\n" as *u8)
210 // furniture parts: hashed initial placements (variant+salt pick the local optimum)
211 var i: i64 = 0
212 while i < np {
213 let row: i64 = ig_part(arch, i)
214 let ex: i64 = (row >> IGP_EX_SH) & 63
215 let ey: i64 = (row >> IGP_EY_SH) & 63
216 let h1: i64 = ig_hash(arch*131 + i*29 + 3, variant*17 + salt*997 + 5)
217 let h2: i64 = ig_hash(arch*151 + i*31 + 7, variant*19 + salt*991 + 11)
218 var sx0: i64 = hw - ex
219 if sx0 < 1 { sx0 = 1 }
220 var sy0: i64 = hd - ey
221 if sy0 < 1 { sy0 = 1 }
222 let ix: i64 = (h1 % (sx0*2 + 1)) - sx0
223 let iy: i64 = (h2 % (sy0*2 + 1)) - sy0
224 p = ig_ws(b, p, "part " as *u8); p = ig_pname(b, p, i)
225 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, ix)
226 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, iy)
227 p = ig_ws(b, p, " 0 0\nextent " as *u8); p = ig_pname(b, p, i)
228 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, ex)
229 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, ey)
230 p = ig_ws(b, p, " 0\n" as *u8)
231 if (row & IGP_KIND_MASK) == IGK_BED {
232 if variant % 2 == 1 {
233 p = ig_ws(b, p, "facing " as *u8); p = ig_pname(b, p, i)
234 p = ig_ws(b, p, " 0 1\n" as *u8)
235 }
236 }
237 i = i + 1
238 }
239 // constraints: envelope, door clearance, wall-hug, mate bands, pairwise noclip
240 i = 0
241 while i < np {
242 let row: i64 = ig_part(arch, i)
243 p = ig_ws(b, p, "envelope " as *u8); p = ig_pname(b, p, i)
244 p = ig_ws(b, p, " shell\n" as *u8)
245 let dc: i64 = (row >> IGP_CLR_SH) & 127
246 if dc > 0 {
247 p = ig_ws(b, p, "clear " as *u8); p = ig_pname(b, p, i)
248 p = ig_ws(b, p, " door " as *u8); p = ig_wn(b, p, dc)
249 p = ig_ws(b, p, "\n" as *u8)
250 }
251 if ((row >> IGP_HUG_SH) & 1) == 1 {
252 p = ig_ws(b, p, "band " as *u8); p = ig_pname(b, p, i)
253 p = ig_ws(b, p, " shell " as *u8); p = ig_wn(b, p, IG_HUG_LO)
254 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, IG_HUG_HI)
255 p = ig_ws(b, p, "\n" as *u8)
256 }
257 let mate: i64 = (row >> IGP_MATE_SH) & 7
258 if mate > 0 {
259 p = ig_ws(b, p, "band " as *u8); p = ig_pname(b, p, i)
260 p = ig_ws(b, p, " " as *u8); p = ig_pname(b, p, mate - 1)
261 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, IG_MATE_LO)
262 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, IG_MATE_HI)
263 p = ig_ws(b, p, "\nface " as *u8); p = ig_pname(b, p, i)
264 p = ig_ws(b, p, " " as *u8); p = ig_pname(b, p, mate - 1)
265 p = ig_ws(b, p, "\n" as *u8)
266 }
267 var j: i64 = i + 1
268 while j < np {
269 let rj: i64 = ig_part(arch, j)
270 var mated: i64 = 0
271 if ((rj >> IGP_MATE_SH) & 7) == i + 1 { mated = 1 }
272 if ((row >> IGP_MATE_SH) & 7) == j + 1 { mated = 1 }
273 if mated == 0 {
274 p = ig_ws(b, p, "noclip " as *u8); p = ig_pname(b, p, i)
275 p = ig_ws(b, p, " " as *u8); p = ig_pname(b, p, j)
276 p = ig_ws(b, p, " " as *u8); p = ig_wn(b, p, IG_NOCLIP_GAP)
277 p = ig_ws(b, p, "\n" as *u8)
278 }
279 j = j + 1
280 }
281 i = i + 1
282 }
283 if ps_load(b, p) != 0 { IG_LASTWHY = 1; return 0 }
284 if ps_solve() != 1 { IG_LASTWHY = 1; return 0 }
285 // quantize to cells + the accept rule (declared in the header, enforced here)
286 let nb: *u8 = sys_mmap(64) as *u8
287 var nr: i64 = 0
288 let rows: *i64 = IG_ROWS as *i64
289 i = 0
290 while i < np {
291 let row: i64 = ig_part(arch, i)
292 let kind: i64 = row & IGP_KIND_MASK
293 let blk: i64 = (row >> IGP_BLK_SH) & 15
294 let q0: i64 = ig_pname(nb, 0, i)
295 nb[q0] = 0 as u8
296 let pi: i64 = ps_find(nb)
297 if pi < 0 { IG_LASTWHY = 1; return 0 }
298 let sx: i64 = ps_x(pi)
299 let sy: i64 = ps_y(pi)
300 if kind == IGK_BED {
301 // two cells along the facing axis; head from the low side of the span
302 if ps_fy(pi) == 0 {
303 var c1x: i64 = (sx - 8 + hw)/IG_CELL
304 var c1z: i64 = (sy + hd)/IG_CELL
305 if c1x > w - 2 { c1x = w - 2 }
306 if c1x < 0 { c1x = 0 }
307 if c1z > d - 1 { c1z = d - 1 }
308 if c1z < 0 { c1z = 0 }
309 rows[nr] = c1x | (c1z << 8) | (blk << 16) | (1 << 24); nr = nr + 1
310 rows[nr] = (c1x + 1) | (c1z << 8) | (blk << 16) | (1 << 24); nr = nr + 1
311 } else {
312 var c2x: i64 = (sx + hw)/IG_CELL
313 var c2z: i64 = (sy - 8 + hd)/IG_CELL
314 if c2x > w - 1 { c2x = w - 1 }
315 if c2x < 0 { c2x = 0 }
316 if c2z > d - 2 { c2z = d - 2 }
317 if c2z < 0 { c2z = 0 }
318 rows[nr] = c2x | (c2z << 8) | (blk << 16) | (1 << 24); nr = nr + 1
319 rows[nr] = c2x | ((c2z + 1) << 8) | (blk << 16) | (1 << 24); nr = nr + 1
320 }
321 } else {
322 var cx: i64 = (sx + hw)/IG_CELL
323 var cz: i64 = (sy + hd)/IG_CELL
324 if cx > w - 1 { cx = w - 1 }
325 if cx < 0 { cx = 0 }
326 if cz > d - 1 { cz = d - 1 }
327 if cz < 0 { cz = 0 }
328 rows[nr] = cx | (cz << 8) | (blk << 16) | (1 << 24); nr = nr + 1
329 if kind == IGK_HEARTH {
330 rows[nr] = cx | (cz << 8) | (IG_BLK_EMBER << 16) | (2 << 24); nr = nr + 1
331 }
332 }
333 i = i + 1
334 }
335 IG_NROWS = nr
336 if ig_ck_accept(rows, nr, w, d, ig_doorx(arch)) != 1 {
337 IG_LASTWHY = 2
338 IG_NROWS = 0
339 return 0
340 }
341 return 1
342}
343
344func ig_nrows() -> i64 { return IG_NROWS }
345func ig_row(i: i64) -> i64 { let r: *i64 = IG_ROWS as *i64; return r[i] }
346func ig_why() -> i64 { return IG_LASTWHY }
347
348// solve with the deterministic salt ladder; returns the salt used (>=0) or -1 REFUSED
349func ig_solve_salted(arch: i64, variant: i64) -> i64 {
350 var salt: i64 = 0
351 while salt < IG_SALTS {
352 if ig_room_solve(arch, variant, salt) == 1 { return salt }
353 salt = salt + 1
354 }
355 return 0 - 1
356}
357
358// ---------- DATA EMIT: the .nx table the world engine imports (NO timestamp -- regeneration
359// must be byte-identical; that is the gate's freshness tooth) ----------
360func ige_emit(out: *u8) -> i64 {
361 var p: i64 = 0
362 p = ig_ws(out, p, "// nx_indoorgen_data.nx -- NX-DERIVED: regenerated artefact, not authored source.\n" as *u8)
363 p = ig_ws(out, p, "// Emitted by nx_indoorgen (ig_room_solve: constraint-solved room layouts, quantized\n" as *u8)
364 p = ig_ws(out, p, "// to voxel cells). DO NOT hand-edit: re-run nx_indoorgen; nx_indoorgen_gate byte-pins\n" as *u8)
365 p = ig_ws(out, p, "// this file against a fresh regeneration, so a hand edit goes RED on the next gate run.\n" as *u8)
366 p = ig_ws(out, p, "// row: cx | cz<<8 | block<<16 | dy<<24 (interior cells, dy above floor).\n" as *u8)
367 p = ig_ws(out, p, "const IGD_NARCH: i64 = " as *u8); p = ig_wn(out, p, IG_NARCH)
368 p = ig_ws(out, p, "\nconst IGD_NVAR: i64 = " as *u8); p = ig_wn(out, p, IG_NVAR)
369 p = ig_ws(out, p, "\nconst IGD_MAXF: i64 = " as *u8); p = ig_wn(out, p, IG_MAXF)
370 p = ig_ws(out, p, "\nfunc igd_dims(a: i64) -> i64 {\n" as *u8)
371 var a: i64 = 1
372 while a < IG_NARCH {
373 p = ig_ws(out, p, " if a == " as *u8); p = ig_wn(out, p, a)
374 p = ig_ws(out, p, " { return " as *u8); p = ig_wn(out, p, ig_dims(a))
375 p = ig_ws(out, p, " }\n" as *u8)
376 a = a + 1
377 }
378 p = ig_ws(out, p, " return " as *u8); p = ig_wn(out, p, ig_dims(0))
379 p = ig_ws(out, p, "\n}\nfunc igd_mats(a: i64) -> i64 {\n" as *u8)
380 a = 1
381 while a < IG_NARCH {
382 p = ig_ws(out, p, " if a == " as *u8); p = ig_wn(out, p, a)
383 p = ig_ws(out, p, " { return " as *u8); p = ig_wn(out, p, ig_mats(a))
384 p = ig_ws(out, p, " }\n" as *u8)
385 a = a + 1
386 }
387 p = ig_ws(out, p, " return " as *u8); p = ig_wn(out, p, ig_mats(0))
388 p = ig_ws(out, p, "\n}\nfunc igd_doorx(a: i64) -> i64 { return (igd_dims(a) & 255)/2 }\n" as *u8)
389 // per-(arch,variant) row counts and rows, flat-keyed
390 let nf: *i64 = sys_mmap(IG_NARCH*IG_NVAR*8) as *i64
391 let allrows: *i64 = sys_mmap(IG_NARCH*IG_NVAR*IG_MAXF*8) as *i64
392 a = 0
393 while a < IG_NARCH {
394 var v2: i64 = 0
395 while v2 < IG_NVAR {
396 let salt: i64 = ig_solve_salted(a, v2)
397 if salt < 0 { return 0 - (a*100 + v2) - 1 }
398 let k: i64 = a*IG_NVAR + v2
399 nf[k] = ig_nrows()
400 var i: i64 = 0
401 while i < ig_nrows() { allrows[k*IG_MAXF + i] = ig_row(i); i = i + 1 }
402 v2 = v2 + 1
403 }
404 a = a + 1
405 }
406 p = ig_ws(out, p, "func igd_nf(a: i64, v2: i64) -> i64 {\n let k: i64 = a*IGD_NVAR + v2\n" as *u8)
407 var k2: i64 = 0
408 while k2 < IG_NARCH*IG_NVAR {
409 p = ig_ws(out, p, " if k == " as *u8); p = ig_wn(out, p, k2)
410 p = ig_ws(out, p, " { return " as *u8); p = ig_wn(out, p, nf[k2])
411 p = ig_ws(out, p, " }\n" as *u8)
412 k2 = k2 + 1
413 }
414 p = ig_ws(out, p, " return 0\n}\nfunc igd_f(a: i64, v2: i64, i: i64) -> i64 {\n let k: i64 = (a*IGD_NVAR + v2)*IGD_MAXF + i\n" as *u8)
415 k2 = 0
416 while k2 < IG_NARCH*IG_NVAR {
417 var i3: i64 = 0
418 while i3 < nf[k2] {
419 p = ig_ws(out, p, " if k == " as *u8); p = ig_wn(out, p, k2*IG_MAXF + i3)
420 p = ig_ws(out, p, " { return " as *u8); p = ig_wn(out, p, allrows[k2*IG_MAXF + i3])
421 p = ig_ws(out, p, " }\n" as *u8)
422 i3 = i3 + 1
423 }
424 k2 = k2 + 1
425 }
426 p = ig_ws(out, p, " return 0\n}\n" as *u8)
427 return p
428}