code wiki / _hdl_build / nx_game_scaffold.nx
nx_game_scaffold.nx source
↩ module page · 73 lines · 4531 B
1// nx_game_scaffold.nx -- LIB: the SCAFFOLD that ties the universal Nishi-builder catalog (the parts SSOT) to the
2// game ecosystem, HARDWARE-RUNG-UP, each rung building on the one below, up to AUTOGENERATION. The rungs:
3// R0 catalog SSOT (nb_*) -> R1 parts (mechanic/entity/level/tilemap emitters) -> R2 COMPOSE (pick parts)
4// -> R3 VALIDATE (all parts resolve, sovereign-safe) -> R4 RUN (ng_sim_run = the deterministic runtime)
5// -> R5 RASTER (integer, NO FLOAT, packed-RGB framebuffer -> PNG, the ecosystem's sovereign visual standard)
6// -> R6 AUTOGENERATE (procedurally synthesize NEW playable levels into the catalog, each verified by the runtime).
7// This is the platformer genre rung of project-nishi-game-ecosystem-generative, sourced from the ONE universal
8// catalog. Sovereign: NO float (decimals already milli-fixed in nx_game_render), NO JS, NO 3rd-party draw -- the
9// raster is pure-Nishi integer pixels (reuses nx_shade + nx_png, the same chain the arcade/2048 rungs ship through).
10// license_tier: ORIGINAL
11import "nx_game_render.nx"
12import "nx_nishi_builder.nx"
13import "nx_shade.nx"
14import "nx_png.nx"
15import "nx_ad_serve.nx"
16import "nx_syscalls.nx"
17const K_MAGIC_1103515245: i64 = 1103515245
18const K_MAGIC_12345: i64 = 12345
19const K_MAGIC_32767: i64 = 32767
20
21// deterministic LCG (seed lives in a 1-slot box so callers thread it) -- the autogen randomness, NO clock => reproducible.
22func gs_rng(seedbox: *i64) -> i64 { var x: i64 = seedbox[0]; x = x * K_MAGIC_1103515245 + K_MAGIC_12345; seedbox[0] = x; return (x >> 16) & K_MAGIC_32767 }
23
24// integer rectangle fill into the packed-RGB framebuffer (no float) -- same primitive the arcade rung uses.
25func gs_fill(fb: *i64, w: i64, h: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 {
26 var yy: i64 = y0; if yy < 0 { yy = 0 }
27 var ye: i64 = y1; if ye > h { ye = h }
28 while yy < ye {
29 var xx: i64 = x0; if xx < 0 { xx = 0 }
30 var xe: i64 = x1; if xe > w { xe = w }
31 while xx < xe { fb[yy*w + xx] = c; xx = xx + 1 }
32 yy = yy + 1
33 }
34 return 0
35}
36
37// R5 RASTER: draw a finished run's 1-D track into the framebuffer. cell 0 = hero (green); 1..coins = gold coins;
38// coins+1..coins+foes = red foes; exit cell = cyan. Pure integer, no float, no canvas-draw. Returns track width in px.
39func gs_raster(st: *i64, fb: *i64, w: i64, h: i64, cell: i64) -> i64 {
40 sh_clear(fb, w, h, sh_rgb(16, 20, 30))
41 let coins: i64 = st[1]; let foes: i64 = st[3]; let exitx: i64 = st[5]
42 var i: i64 = 0
43 while i <= exitx {
44 let x0: i64 = i * cell
45 var col: i64 = sh_rgb(40, 46, 60) // bare track tile
46 if i >= 1 { if i <= coins { col = sh_rgb(255, 210, 70) } } // coin = gold
47 if i > coins { if i <= coins + foes { col = sh_rgb(224, 80, 58) } } // foe = red
48 if i == exitx { col = sh_rgb(60, 200, 210) } // exit = cyan
49 gs_fill(fb, w, h, x0 + 2, cell / 2, x0 + cell - 2, cell - 2, col)
50 i = i + 1
51 }
52 gs_fill(fb, w, h, 2, cell / 2, cell - 2, cell - 2, sh_rgb(90, 210, 122)) // hero = green, at the start cell
53 return (exitx + 1) * cell
54}
55
56// R6 AUTOGENERATE one level: synthesize a NEW level spec deterministically from the seed, TEACH it to the catalog
57// (grow), then RUN it through the runtime. Leaves the run in st; returns win (1). out_c/out_f get the generated
58// coin/foe counts so a caller can verify the run matches what was generated. id = "auto-<idx>".
59func gs_autogen_one(path: *u8, seedbox: *i64, idx: i64, mech: *u8, tilemap: *u8, foe: *u8, st: *i64, out_c: *i64, out_f: *i64) -> i64 {
60 let c: i64 = 5 + (gs_rng(seedbox) % 26) // 5..30 coins (non-degenerate -- build intelligence, never an empty level)
61 let f: i64 = 1 + (gs_rng(seedbox) % 8) // 1..8 foes
62 out_c[0] = c; out_f[0] = f
63 let id: *u8 = sys_mmap(32); var o: i64 = 0
64 o = as_append(id, o, "auto-" as *u8); o = ng_num(id, o, idx); id[o] = 0 as u8
65 let spec: *u8 = sys_mmap(160); var s: i64 = 0
66 s = as_append(spec, s, tilemap); spec[s] = 124 as u8; s = s + 1
67 s = as_append(spec, s, "coin*" as *u8); s = ng_num(spec, s, c); spec[s] = 124 as u8; s = s + 1
68 s = as_append(spec, s, foe); spec[s] = 42 as u8; s = s + 1; s = ng_num(spec, s, f)
69 s = as_append(spec, s, "|exit-right" as *u8); spec[s] = 0 as u8
70 nb_register(path, "game" as *u8, "level" as *u8, id, "Autogen level" as *u8, spec)
71 ng_sim_run(path, id, mech, foe, st)
72 return st[7]
73}