code wiki / _hdl_build / nx_creature_world.nx
nx_creature_world.nx source
↩ module page · 125 lines · 7053 B
1// nx_creature_world.nx -- the next REAL slices of a creature-collector, INTEGRATED so the core loop actually RUNS:
2// overworld walk -> wild encounter (only on grass) -> weaken in a real battle -> CAPTURE (real HP-dependent
3// catch formula) -> add to PARTY -> SAVE/LOAD party (real persistence). Reuses nx_creature_battle's real battle
4// engine. Pure-integer, deterministic, sovereign. HONEST SCOPE: headless logic spine -- NO visuals, NO real-time,
5// NO UI, NO netcode; a 1-D route, not a 2-D world; save = core stats (not moves/name). One honest vertical slice.
6// license_tier: ORIGINAL
7import "nx_creature_battle.nx"
8import "nx_syscalls.nx"
9
10const PARTY_MAX: i64 = 6
11const ENC_RATE: i64 = 70 // % wild-encounter chance per grass tile
12const BALL_MAX: i64 = 8 // balls thrown per encounter before it breaks free
13
14// creature extra field: [21] = catch rate (data -> moddable). curHP=[3] maxHP=[2].
15func cw_set_catch(c: *i64, r: i64) -> i64 { c[21] = r; return 0 }
16// real HP-dependent catch value a (Pokemon-style): lower current HP -> higher a -> higher catch chance.
17func cw_catch_a(t: *i64, ball: i64) -> i64 { return (3*t[2] - 2*t[3]) * t[21] * ball / (3*t[2]) }
18func cw_try_catch(t: *i64, ball: i64, s: *i64) -> i64 {
19 let a: i64 = cw_catch_a(t, ball)
20 if a >= 255 { return 1 }
21 if (cb_rng(s) % 256) < a { return 1 }
22 return 0
23}
24func cw_copy(dst: *i64, src: *i64) -> i64 { var i: i64 = 0; while i < 24 { dst[i] = src[i]; i = i + 1 } return 0 }
25// data-driven wild species table (mod point): 0=Aquapup(Water) 1=Leafkit(Grass).
26func cw_spawn(c: *i64, sid: i64) -> i64 {
27 if sid == 0 { cb_set(c, 2, 25, 80, 52, 50, 45, "Aquapup" as *u8); cb_addmove(c, 2, 40, 100); cb_addmove(c, 0, 40, 100); cw_set_catch(c, 150) }
28 else { cb_set(c, 3, 25, 78, 50, 48, 50, "Leafkit" as *u8); cb_addmove(c, 3, 40, 100); cb_addmove(c, 0, 40, 100); cw_set_catch(c, 150) }
29 return 0
30}
31
32// walk the route; on each grass tile roll an encounter; weaken the wild in a real battle (never KO -> floor at
33// 10% HP); throw up to BALL_MAX balls (HP-dependent catch); on catch add to party. Logs a transcript. returns #encounters.
34func cw_explore(route: *u8, T: i64, lead: *i64, party: *i64, pcountbox: *i64, seed: i64, buf: *u8) -> i64 {
35 let s: *i64 = sys_mmap(16) as *i64; s[0] = seed
36 var o: i64 = 0
37 var enc: i64 = 0
38 var pc: i64 = pcountbox[0]
39 var i: i64 = 0
40 while i < T {
41 if route[i] == (1 as u8) {
42 if (cb_rng(s) % 100) < ENC_RATE {
43 enc = enc + 1
44 let wild: *i64 = sys_mmap(8*24) as *i64
45 cw_spawn(wild, 0)
46 o = cb_p(buf, o, "tile " as *u8); o = cb_n(buf, o, i); o = cb_p(buf, o, " (grass): wild " as *u8); o = cb_p(buf, o, wild[20] as *u8); o = cb_p(buf, o, " (" as *u8); o = cb_p(buf, o, cb_tname(wild[0])); o = cb_p(buf, o, ") Lv" as *u8); o = cb_n(buf, o, wild[1]); o = cb_p(buf, o, " HP " as *u8); o = cb_n(buf, o, wild[3]); o = cb_p(buf, o, "/" as *u8); o = cb_n(buf, o, wild[2]); o = cb_p(buf, o, "\n" as *u8)
47 let floor: i64 = wild[2] / 10
48 var guard: i64 = 0
49 while wild[3] > floor {
50 if guard > 40 { wild[3] = floor } else {
51 let mi: i64 = cb_best(lead, wild); let mt: i64 = lead[8+mi*3]; let mp: i64 = lead[8+mi*3+1]
52 let dmg: i64 = cb_damage(lead, wild, mt, mp, s)
53 var hp: i64 = wild[3] - dmg; if hp < 1 { hp = 1 } wild[3] = hp
54 guard = guard + 1
55 }
56 }
57 o = cb_p(buf, o, " " as *u8); o = cb_p(buf, o, lead[20] as *u8); o = cb_p(buf, o, " weakened it to HP " as *u8); o = cb_n(buf, o, wild[3]); o = cb_p(buf, o, "/" as *u8); o = cb_n(buf, o, wild[2]); o = cb_p(buf, o, "\n" as *u8)
58 var caught: i64 = 0; var balls: i64 = 0
59 while caught == 0 {
60 if balls >= BALL_MAX { caught = 0 - 1 } else { balls = balls + 1; if cw_try_catch(wild, 1, s) == 1 { caught = 1 } }
61 }
62 if caught == 1 {
63 if pc < PARTY_MAX { cw_copy(((party as i64) + pc*24*8) as *i64, wild); pc = pc + 1 }
64 o = cb_p(buf, o, " ball " as *u8); o = cb_n(buf, o, balls); o = cb_p(buf, o, " -> CAUGHT! party now " as *u8); o = cb_n(buf, o, pc); o = cb_p(buf, o, "\n" as *u8)
65 } else { o = cb_p(buf, o, " broke free (out of balls)\n" as *u8) }
66 }
67 }
68 i = i + 1
69 }
70 pcountbox[0] = pc
71 buf[o] = 0 as u8
72 return enc
73}
74
75// SAVE party core stats to a text file (real persistence). format: count\n then per member: type lvl maxhp curhp atk def spd catchrate\n
76func cw_save(path: *u8, party: *i64, count: i64) -> i64 {
77 let buf: *u8 = sys_mmap(4096); var o: i64 = 0
78 o = cb_n(buf, o, count); buf[o] = 10 as u8; o = o + 1
79 var j: i64 = 0
80 while j < count {
81 let c: *i64 = ((party as i64) + j*24*8) as *i64
82 o = cb_n(buf, o, c[0]); buf[o]=32 as u8; o=o+1
83 o = cb_n(buf, o, c[1]); buf[o]=32 as u8; o=o+1
84 o = cb_n(buf, o, c[2]); buf[o]=32 as u8; o=o+1
85 o = cb_n(buf, o, c[3]); buf[o]=32 as u8; o=o+1
86 o = cb_n(buf, o, c[4]); buf[o]=32 as u8; o=o+1
87 o = cb_n(buf, o, c[5]); buf[o]=32 as u8; o=o+1
88 o = cb_n(buf, o, c[6]); buf[o]=32 as u8; o=o+1
89 o = cb_n(buf, o, c[21]); buf[o]=10 as u8; o=o+1
90 j = j + 1
91 }
92 let fd: i64 = sys_openat_wr(path, 420); if fd < 0 { return 0 - 1 } sys_write(fd, buf, o); sys_close(fd)
93 return count
94}
95func cw_parseint(data: *u8, n: i64, start: i64, out: *i64) -> i64 {
96 var i: i64 = start; var go: i64 = 1
97 while go == 1 { if i >= n { go = 0 } else { let d: i64 = data[i] as i64; if d >= 48 { if d <= 57 { go = 0 } } if go == 1 { i = i + 1 } } }
98 var v: i64 = 0; var g2: i64 = 1
99 while g2 == 1 { if i >= n { g2 = 0 } else { let d: i64 = data[i] as i64; if d < 48 { g2 = 0 } else { if d > 57 { g2 = 0 } else { v = v*10 + (d - 48); i = i + 1 } } } }
100 out[0] = v; return i
101}
102func cw_load(path: *u8, party: *i64, countbox: *i64) -> i64 {
103 let lenp: *i64 = sys_mmap(16) as *i64; lenp[0] = 0
104 let data: *u8 = sys_read_file(path, lenp)
105 if (data as i64) == 0 { countbox[0] = 0; return 0 }
106 let n: i64 = lenp[0]
107 let cbx: *i64 = sys_mmap(16) as *i64
108 var i: i64 = cw_parseint(data, n, 0, cbx); let count: i64 = cbx[0]
109 var j: i64 = 0
110 while j < count {
111 let c: *i64 = ((party as i64) + j*24*8) as *i64
112 i = cw_parseint(data, n, i, cbx); c[0] = cbx[0]
113 i = cw_parseint(data, n, i, cbx); c[1] = cbx[0]
114 i = cw_parseint(data, n, i, cbx); c[2] = cbx[0]
115 i = cw_parseint(data, n, i, cbx); c[3] = cbx[0]
116 i = cw_parseint(data, n, i, cbx); c[4] = cbx[0]
117 i = cw_parseint(data, n, i, cbx); c[5] = cbx[0]
118 i = cw_parseint(data, n, i, cbx); c[6] = cbx[0]
119 i = cw_parseint(data, n, i, cbx); c[21] = cbx[0]
120 c[7] = 0; c[20] = 0
121 j = j + 1
122 }
123 countbox[0] = count
124 return count
125}