code wiki / (root) / nx_indoorgen_lib.nx

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}