nx_pets_wasm.nx source
↩ module page · 614 lines · 19714 B
1// nx_pets_wasm.nx -- Generates a procedurally created 16x12 grid world with terrain and structures for a turn-based pet capture game.
2const K_MAGIC_1103515245: i64 = 1103515245
3const K_MAGIC_12345: i64 = 12345
4const K_MAGIC_32767: i64 = 32767
5const K_MAGIC_4096: i64 = 4096
6const K_MAGIC_147456: i64 = 147456
7const K_MAGIC_8000: i64 = 8000
8const K_MAGIC_1100: i64 = 1100
9const K_MAGIC_1047: i64 = 1047
10const K_MAGIC_1200: i64 = 1200
11const K_MAGIC_8192: i64 = 8192
12const K_MAGIC_1024: i64 = 1024
13const K_MAGIC_65536: i64 = 65536
14const K_MAGIC_20260613: i64 = 20260613
15// nx_pets_wasm.nx -- PIXELMON-LITE pets game, wasm-friendly (compiles via the SOVEREIGN
16// pipeline: nx -> wat (nxc2 --target wat, NO --opt) -> wasm (Nishi nx_wat_compiler) ->
17// served by nx_arcade_serve at /pets). Pokemon-x-Minecraft loop: walk a procgen overworld,
18// wild creatures in tall grass, STRATEGIC turn-based battle (type triangle fire>grass>water>
19// fire; neutral Strike + typed Special; PARTY-SWITCH to a type-advantaged captured pet),
20// weaken then CAPTURE, build a party/collection of up to 6. NO syscalls (fixed linear-memory
21// offsets + exported funcs); the JS canvas shim blits the framebuffer. HONEST: tutor-authored
22// PLAYABLE ALPHA of the core loop, NOT a measured pixelmon/minecraft exceed. license_tier: ORIGINAL
23//
24// memory: gs[] i64 at 1024 ; world 16x12 u8 at 4096 ; party roster i64 at 8192 ; fb 320x240 at 65536
25// gs: 0 px 1 py 2 mode 3 rng 4 party_count 5 msg 6 my_hp 7 my_max 8 my_lvl 9 my_species
26// 10 captured 11 wild_hp 12 wild_max 13 wild_lvl 14 wild_species 15 xp 16 seen_mask
27// 17 last_eff(0 none 1 super 2 weak 3 normal) 18 last_dmg 19 active_idx
28// roster[i] stride 4: +0 species +1 level +2 hp +3 max (max 6 members)
29// types: 0 fire 1 water 2 grass. species->type: 0 grass 1 fire 2 water 3 grass
30
31func g_rng(gs: *i64) -> i64 {
32 var s: i64 = gs[3]
33 s = s * K_MAGIC_1103515245 + K_MAGIC_12345
34 gs[3] = s
35 return (s >> 16) & K_MAGIC_32767
36}
37func g_cell(x: i64, y: i64) -> i64 {
38 if x < 0 { return 1 }
39 if y < 0 { return 1 }
40 if x >= 16 { return 1 }
41 if y >= 12 { return 1 }
42 let w: *u8 = (K_MAGIC_4096 as i64) as *u8
43 return w[y * 16 + x] as i64
44}
45func g_set(x: i64, y: i64, v: i64) -> i64 {
46 let w: *u8 = (K_MAGIC_4096 as i64) as *u8
47 w[y * 16 + x] = v as u8
48 return 0
49}
50func g_build(gs: *i64) -> i64 {
51 var y: i64 = 0
52 while y < 12 {
53 var x: i64 = 0
54 while x < 16 {
55 var c: i64 = 0
56 if x == 0 { c = 1 }
57 if y == 0 { c = 1 }
58 if x == 15 { c = 1 }
59 if y == 11 { c = 1 }
60 g_set(x, y, c)
61 x = x + 1
62 }
63 y = y + 1
64 }
65 var i: i64 = 0
66 while i < 26 {
67 let rx: i64 = 1 + (g_rng(gs) % 14)
68 let ry: i64 = 1 + (g_rng(gs) % 10)
69 var ok: i64 = 1
70 if rx < 3 { if ry < 3 { ok = 0 } }
71 if ok == 1 { g_set(rx, ry, 2) }
72 i = i + 1
73 }
74 var j: i64 = 0
75 while j < 10 {
76 let rx: i64 = 1 + (g_rng(gs) % 14)
77 let ry: i64 = 1 + (g_rng(gs) % 10)
78 var ok2: i64 = 1
79 if rx < 3 { if ry < 3 { ok2 = 0 } }
80 if ok2 == 1 { g_set(rx, ry, 1) }
81 j = j + 1
82 }
83 g_set(1, 1, 0)
84 g_set(2, 1, 0)
85 g_set(1, 2, 0)
86 gs[0] = 1
87 gs[1] = 1
88 return 0
89}
90func g_max_for(lvl: i64) -> i64 { return 16 + lvl * 4 }
91func g_base(sp: i64) -> i64 { if sp >= 10 { return sp - 10 } return sp }
92func g_type_of(sp: i64) -> i64 {
93 let b: i64 = g_base(sp)
94 if b == 1 { return 0 }
95 if b == 2 { return 1 }
96 return 2
97}
98func g_effect(at: i64, df: i64) -> i64 {
99 if at == 0 { if df == 2 { return 20 } if df == 1 { return 5 } return 10 }
100 if at == 1 { if df == 0 { return 20 } if df == 2 { return 5 } return 10 }
101 if df == 1 { return 20 }
102 if df == 0 { return 5 }
103 return 10
104}
105// --- SFX: the organ SYNTHESIZES 8-bit PCM into linear memory (128 = silence); the JS shim is
106// a pure DAC sink that copies samples into a Web Audio buffer and plays them -- exactly the
107// role canvas plays for the framebuffer. NO oscillator/synth in JS. audio buf u8 at 147456,
108// 8000 Hz; gs[30] = pending sfx id (the team owns BOTH the waveform and the event->sound map).
109// amp <= 90 keeps 128+/-amp inside [38,218] (no clip). sfx: 1 hit 2 super 3 catch 4 faint
110// 5 level/evolve/dex 6 mine 7 encounter.
111func g_tone(start: i64, len: i64, freq: i64, amp0: i64) -> i64 {
112 let buf: *u8 = (K_MAGIC_147456 as i64) as *u8
113 var period: i64 = 0
114 if freq > 0 { period = K_MAGIC_8000 / freq }
115 var i: i64 = 0
116 while i < len {
117 var s: i64 = 128
118 if period > 0 {
119 let amp: i64 = amp0 * (len - i) / len
120 if (i % period) * 2 < period { s = 128 + amp } else { s = 128 - amp }
121 }
122 buf[start + i] = s as u8
123 i = i + 1
124 }
125 return start + len
126}
127func g_synth(sfx: i64) -> i64 {
128 var n: i64 = 0
129 if sfx == 1 { n = g_tone(0, 900, 220, 78) }
130 if sfx == 2 { n = g_tone(0, 1000, 660, 88); n = g_tone(n, 700, 990, 70) }
131 if sfx == 3 { n = g_tone(0, 520, 523, 82); n = g_tone(n, 520, 659, 82); n = g_tone(n, 1000, 784, 86) }
132 if sfx == 4 { n = g_tone(0, 700, 392, 80); n = g_tone(n, 1000, 196, 78) }
133 if sfx == 5 { n = g_tone(0, 420, 523, 84); n = g_tone(n, 420, 659, 84); n = g_tone(n, 420, 784, 84); n = g_tone(n, K_MAGIC_1100, K_MAGIC_1047, 90) }
134 if sfx == 6 { n = g_tone(0, 260, K_MAGIC_1200, 66) }
135 if sfx == 7 { n = g_tone(0, 380, 440, 72); n = g_tone(n, 520, 880, 80) }
136 return n
137}
138// --- party roster accessors (source of truth for non-active members) ---
139func g_party_sp(i: i64) -> i64 { let r: *i64 = (K_MAGIC_8192 as i64) as *i64; return r[i * 4 + 0] }
140func g_party_lvl(i: i64) -> i64 { let r: *i64 = (K_MAGIC_8192 as i64) as *i64; return r[i * 4 + 1] }
141func g_party_hp(i: i64) -> i64 { let r: *i64 = (K_MAGIC_8192 as i64) as *i64; return r[i * 4 + 2] }
142func g_party_max(i: i64) -> i64 { let r: *i64 = (K_MAGIC_8192 as i64) as *i64; return r[i * 4 + 3] }
143func g_sync_active(gs: *i64) -> i64 {
144 let r: *i64 = (K_MAGIC_8192 as i64) as *i64
145 let a: i64 = gs[19]
146 gs[9] = r[a * 4 + 0]
147 gs[8] = r[a * 4 + 1]
148 gs[6] = r[a * 4 + 2]
149 gs[7] = r[a * 4 + 3]
150 return 0
151}
152func g_save_active(gs: *i64) -> i64 {
153 let r: *i64 = (K_MAGIC_8192 as i64) as *i64
154 let a: i64 = gs[19]
155 r[a * 4 + 0] = gs[9]
156 r[a * 4 + 1] = gs[8]
157 r[a * 4 + 2] = gs[6]
158 r[a * 4 + 3] = gs[7]
159 return 0
160}
161func g_add_party(gs: *i64, sp: i64, lvl: i64) -> i64 {
162 let r: *i64 = (K_MAGIC_8192 as i64) as *i64
163 let c: i64 = gs[4]
164 if c >= 6 { return 0 }
165 let mx: i64 = g_max_for(lvl)
166 r[c * 4 + 0] = sp
167 r[c * 4 + 1] = lvl
168 r[c * 4 + 2] = mx
169 r[c * 4 + 3] = mx
170 gs[4] = c + 1
171 return 0
172}
173func g_count_alive(gs: *i64) -> i64 {
174 let r: *i64 = (K_MAGIC_8192 as i64) as *i64
175 let c: i64 = gs[4]
176 var n: i64 = 0
177 var i: i64 = 0
178 while i < c { if r[i * 4 + 2] > 0 { n = n + 1 } i = i + 1 }
179 return n
180}
181func g_switch_next(gs: *i64) -> i64 {
182 let r: *i64 = (K_MAGIC_8192 as i64) as *i64
183 let c: i64 = gs[4]
184 let a: i64 = gs[19]
185 var k: i64 = 1
186 while k < c {
187 let idx: i64 = (a + k) % c
188 if r[idx * 4 + 2] > 0 { gs[19] = idx; g_sync_active(gs); return 1 }
189 k = k + 1
190 }
191 return 0
192}
193func g_heal_all(gs: *i64) -> i64 {
194 let r: *i64 = (K_MAGIC_8192 as i64) as *i64
195 let c: i64 = gs[4]
196 var i: i64 = 0
197 while i < c { r[i * 4 + 2] = r[i * 4 + 3] i = i + 1 }
198 gs[19] = 0
199 g_sync_active(gs)
200 return 0
201}
202func gi_init(seed: i64) -> i64 {
203 let gs: *i64 = (K_MAGIC_1024 as i64) as *i64
204 let r: *i64 = (K_MAGIC_8192 as i64) as *i64
205 gs[3] = seed
206 gs[2] = 0
207 gs[5] = 0
208 gs[10] = 0
209 gs[15] = 0
210 gs[16] = 1
211 gs[17] = 0
212 gs[18] = 0
213 gs[19] = 0
214 gs[20] = 0
215 gs[21] = 0
216 gs[22] = 0
217 gs[23] = 1
218 gs[24] = 0
219 gs[25] = 0
220 gs[26] = 0
221 gs[27] = 0
222 gs[28] = 1
223 gs[29] = 0
224 gs[30] = 0
225 var i: i64 = 0
226 while i < 24 { r[i] = 0 i = i + 1 }
227 r[0] = 0
228 r[1] = 5
229 r[2] = g_max_for(5)
230 r[3] = g_max_for(5)
231 gs[4] = 1
232 g_sync_active(gs)
233 g_build(gs)
234 return 0
235}
236func g_encounter(gs: *i64) -> i64 {
237 gs[2] = 1
238 gs[14] = 1 + (g_rng(gs) % 3)
239 gs[13] = 2 + (g_rng(gs) % 5)
240 gs[12] = g_max_for(gs[13])
241 gs[11] = gs[12]
242 gs[5] = 1
243 gs[17] = 0
244 let bit: i64 = 1 << gs[14]
245 gs[16] = gs[16] | bit
246 gs[30] = 7
247 return 0
248}
249func g_move(gs: *i64, dx: i64, dy: i64) -> i64 {
250 let nx: i64 = gs[0] + dx
251 let ny: i64 = gs[1] + dy
252 let c: i64 = g_cell(nx, ny)
253 if c == 1 { return 0 }
254 gs[0] = nx
255 gs[1] = ny
256 if c == 2 { if (g_rng(gs) % 5) == 0 { g_encounter(gs) } }
257 return 0
258}
259// the cell the player faces; clamped to the interior so the border stays intact
260func g_facex(gs: *i64) -> i64 {
261 let f: i64 = gs[23]
262 if f == 2 { return gs[0] - 1 }
263 if f == 3 { return gs[0] + 1 }
264 return gs[0]
265}
266func g_facey(gs: *i64) -> i64 {
267 let f: i64 = gs[23]
268 if f == 0 { return gs[1] - 1 }
269 if f == 1 { return gs[1] + 1 }
270 return gs[1]
271}
272func g_interior(x: i64, y: i64) -> i64 {
273 if x < 1 { return 0 }
274 if x > 14 { return 0 }
275 if y < 1 { return 0 }
276 if y > 10 { return 0 }
277 return 1
278}
279// MINE the block in front: tree/placed -> +wood, grass -> +fiber; clears to path
280func g_break(gs: *i64) -> i64 {
281 let fx: i64 = g_facex(gs)
282 let fy: i64 = g_facey(gs)
283 if g_interior(fx, fy) == 0 { return 0 }
284 let c: i64 = g_cell(fx, fy)
285 if c == 1 { g_set(fx, fy, 0); gs[24] = gs[24] + 1; gs[5] = 13; gs[30] = 6 }
286 if c == 2 { g_set(fx, fy, 0); gs[25] = gs[25] + 1; gs[5] = 14; gs[30] = 6 }
287 if c == 4 { g_set(fx, fy, 0); gs[24] = gs[24] + 1; gs[5] = 13; gs[30] = 6 }
288 return 0
289}
290// PLACE a wood block in front (costs 1 wood) onto an empty path cell
291func g_place(gs: *i64) -> i64 {
292 let fx: i64 = g_facex(gs)
293 let fy: i64 = g_facey(gs)
294 if g_interior(fx, fy) == 0 { gs[5] = 16; return 0 }
295 let c: i64 = g_cell(fx, fy)
296 if c == 0 {
297 if gs[24] > 0 { g_set(fx, fy, 4); gs[24] = gs[24] - 1; gs[5] = 15 } else { gs[5] = 16 }
298 } else { gs[5] = 16 }
299 return 0
300}
301func g_my_base(gs: *i64) -> i64 {
302 var d: i64 = 4 + gs[8] + (g_rng(gs) % 4)
303 if gs[9] >= 10 { d = d + 3 }
304 return d
305}
306func g_wild_base(gs: *i64) -> i64 { return 2 + gs[13] + (g_rng(gs) % 3) }
307func g_wild_turn(gs: *i64) -> i64 {
308 let wt: i64 = g_type_of(gs[14])
309 let mt: i64 = g_type_of(gs[9])
310 let eff: i64 = g_effect(wt, mt)
311 let d: i64 = g_wild_base(gs) * eff / 10
312 gs[6] = gs[6] - d
313 if gs[6] <= 0 {
314 gs[6] = 0
315 g_save_active(gs)
316 if g_switch_next(gs) == 1 {
317 gs[5] = 11
318 } else {
319 g_heal_all(gs)
320 gs[2] = 0
321 gs[5] = 5
322 }
323 }
324 return 0
325}
326func g_wild_faint(gs: *i64) -> i64 {
327 gs[30] = 4
328 gs[15] = gs[15] + gs[13] * 2
329 if gs[15] >= gs[8] * 10 {
330 gs[8] = gs[8] + 1
331 gs[15] = 0
332 gs[7] = g_max_for(gs[8])
333 gs[6] = gs[7]
334 gs[5] = 6
335 gs[30] = 5
336 if gs[8] >= 8 { if gs[9] < 10 { gs[9] = gs[9] + 10; gs[7] = g_max_for(gs[8]) + 20; gs[6] = gs[7]; gs[5] = 22 } }
337 } else {
338 gs[5] = 3
339 }
340 g_save_active(gs)
341 gs[2] = 0
342 return 0
343}
344func g_strike(gs: *i64) -> i64 {
345 if gs[2] != 1 { return 0 }
346 gs[21] = 10
347 gs[22] = 1
348 let d: i64 = g_my_base(gs)
349 gs[18] = d
350 gs[17] = 3
351 gs[30] = 1
352 gs[11] = gs[11] - d
353 if gs[11] <= 0 { g_wild_faint(gs); return 0 }
354 g_wild_turn(gs)
355 return 0
356}
357func g_element(gs: *i64) -> i64 {
358 if gs[2] != 1 { return 0 }
359 gs[21] = 10
360 gs[22] = 1
361 let mt: i64 = g_type_of(gs[9])
362 let wt: i64 = g_type_of(gs[14])
363 let eff: i64 = g_effect(mt, wt)
364 let d: i64 = g_my_base(gs) * eff / 10
365 gs[18] = d
366 if eff == 20 { gs[17] = 1 } else { if eff == 5 { gs[17] = 2 } else { gs[17] = 3 } }
367 if eff == 20 { gs[30] = 2 } else { gs[30] = 1 }
368 gs[11] = gs[11] - d
369 if gs[11] <= 0 { g_wild_faint(gs); return 0 }
370 g_wild_turn(gs)
371 return 0
372}
373func g_switch_action(gs: *i64) -> i64 {
374 if gs[2] != 1 { return 0 }
375 g_save_active(gs)
376 if g_count_alive(gs) <= 1 { gs[5] = 12; return 0 }
377 g_switch_next(gs)
378 gs[5] = 10
379 gs[17] = 0
380 g_wild_turn(gs)
381 return 1
382}
383func g_do_capture(gs: *i64, bonus: i64) -> i64 {
384 if gs[2] != 1 { return 0 }
385 gs[17] = 0
386 var chance: i64 = 250 + bonus
387 if gs[12] > 0 { chance = chance + (gs[12] - gs[11]) * 650 / gs[12] }
388 if (g_rng(gs) % 1000) < chance {
389 g_save_active(gs)
390 g_add_party(gs, gs[14], gs[13])
391 gs[10] = gs[10] + 1
392 gs[28] = gs[28] | (1 << g_base(gs[14]))
393 gs[2] = 0
394 gs[5] = 4
395 gs[30] = 3
396 if (gs[28] & 15) == 15 { gs[29] = 1; gs[5] = 21; gs[30] = 5 }
397 } else {
398 gs[5] = 7
399 gs[30] = 1
400 g_wild_turn(gs)
401 }
402 return 0
403}
404func g_capture(gs: *i64) -> i64 { return g_do_capture(gs, 0) }
405// craft items fuse the mine-half into the catch-half: better odds + healing
406func g_throw_ball(gs: *i64) -> i64 {
407 if gs[2] != 1 { return 0 }
408 if gs[27] > 0 { gs[27] = gs[27] - 1; g_do_capture(gs, 300) } else { gs[5] = 18 }
409 return 0
410}
411func g_use_potion(gs: *i64) -> i64 {
412 if gs[2] != 1 { return 0 }
413 if gs[26] > 0 {
414 gs[26] = gs[26] - 1
415 gs[6] = gs[6] + 25
416 if gs[6] > gs[7] { gs[6] = gs[7] }
417 g_save_active(gs)
418 gs[5] = 20
419 g_wild_turn(gs)
420 } else { gs[5] = 18 }
421 return 0
422}
423func g_craft_potion(gs: *i64) -> i64 {
424 if gs[25] >= 2 { gs[25] = gs[25] - 2; gs[26] = gs[26] + 1; gs[5] = 17 } else { gs[5] = 18 }
425 return 0
426}
427func g_craft_ball(gs: *i64) -> i64 {
428 if gs[24] >= 1 { if gs[25] >= 1 { gs[24] = gs[24] - 1; gs[25] = gs[25] - 1; gs[27] = gs[27] + 1; gs[5] = 19; return 0 } }
429 gs[5] = 18
430 return 0
431}
432// key: 0 up 1 down 2 left 3 right 4 strike 5 restart 6 capture 7 flee 8 special 9 switch
433func gi_input(key: i64) -> i64 {
434 let gs: *i64 = (K_MAGIC_1024 as i64) as *i64
435 if gs[2] == 1 {
436 if key == 4 { g_strike(gs) }
437 if key == 8 { g_element(gs) }
438 if key == 9 { g_switch_action(gs) }
439 if key == 6 { g_capture(gs) }
440 if key == 10 { g_use_potion(gs) }
441 if key == 11 { g_throw_ball(gs) }
442 if key == 7 { gs[2] = 0; gs[5] = 8; gs[17] = 0 }
443 g_save_active(gs)
444 return 0
445 }
446 if key == 0 { gs[23] = 0 g_move(gs, 0, 0 - 1) }
447 if key == 1 { gs[23] = 1 g_move(gs, 0, 1) }
448 if key == 2 { gs[23] = 2 g_move(gs, 0 - 1, 0) }
449 if key == 3 { gs[23] = 3 g_move(gs, 1, 0) }
450 if key == 4 { g_break(gs) }
451 if key == 8 { g_place(gs) }
452 if key == 12 { g_craft_potion(gs) }
453 if key == 13 { g_craft_ball(gs) }
454 if key == 5 { gi_init(gs[3] + 9) }
455 return 0
456}
457func g_fill(x0: i64, y0: i64, ww: i64, hh: i64, col: i64) -> i64 {
458 let fb: *u8 = (K_MAGIC_65536 as i64) as *u8
459 var y: i64 = y0
460 while y < y0 + hh {
461 if y >= 0 { if y < 240 {
462 var x: i64 = x0
463 while x < x0 + ww {
464 if x >= 0 { if x < 320 { fb[y * 320 + x] = col as u8 } }
465 x = x + 1
466 }
467 } }
468 y = y + 1
469 }
470 return 0
471}
472func g_species_col(sp: i64) -> i64 {
473 let b: i64 = g_base(sp)
474 if b == 0 { return 6 }
475 if b == 1 { return 7 }
476 if b == 2 { return 8 }
477 return 9
478}
479// distinct per-species creature sprite (composed rects) + vertical bob offset.
480// sp 0 Leafling=leaf ears, 1 Emberpup=pointy ears+tail, 2 Aquafin=dorsal fin, 3 Sprout=stem.
481func g_draw_pet(sp: i64, x: i64, y: i64, w: i64, h: i64, bob: i64) -> i64 {
482 let b: i64 = g_base(sp)
483 let col: i64 = g_species_col(sp)
484 let yy: i64 = y + bob
485 if b == 0 {
486 g_fill(x + 6, yy - 8, 12, 10, 9)
487 g_fill(x + w - 18, yy - 8, 12, 10, 9)
488 }
489 if b == 1 {
490 g_fill(x + 8, yy - 10, 8, 12, col)
491 g_fill(x + w - 16, yy - 10, 8, 12, col)
492 }
493 if b == 2 { g_fill(x + w / 2 - 6, yy - 12, 12, 14, col) }
494 if b == 3 {
495 g_fill(x + w / 2 - 3, yy - 12, 6, 12, 1)
496 g_fill(x + w / 2 - 8, yy - 16, 16, 7, 9)
497 }
498 g_fill(x + 4, yy, w - 8, h, col)
499 g_fill(x, yy + 6, w, h - 12, col)
500 g_fill(x + 10, yy + 16, 16, 16, 4)
501 g_fill(x + w - 26, yy + 16, 16, 16, 4)
502 g_fill(x + 16, yy + 22, 7, 7, 12)
503 g_fill(x + w - 20, yy + 22, 7, 7, 12)
504 g_fill(x + w / 2 - 8, yy + h - 18, 16, 7, 12)
505 if b == 1 { g_fill(x - 6, yy + h - 20, 10, 8, col) }
506 if sp >= 10 { g_fill(x + w / 2 - 12, yy - 22, 24, 7, 14) }
507 return 0
508}
509func g_render_overworld(gs: *i64) -> i64 {
510 var cy: i64 = 0
511 while cy < 12 {
512 var cx: i64 = 0
513 while cx < 16 {
514 let c: i64 = g_cell(cx, cy)
515 var col: i64 = 0
516 if c == 1 { col = 1 }
517 if c == 2 { col = 2 }
518 if c == 3 { col = 3 }
519 if c == 4 { col = 13 }
520 g_fill(cx * 20, cy * 20, 20, 20, col)
521 cx = cx + 1
522 }
523 cy = cy + 1
524 }
525 g_fill(gs[0] * 20 + 4, gs[1] * 20 + 4, 12, 12, 4)
526 var tx: i64 = gs[0] * 20 + 8
527 var ty: i64 = gs[1] * 20 + 8
528 if gs[23] == 0 { ty = gs[1] * 20 }
529 if gs[23] == 1 { ty = gs[1] * 20 + 16 }
530 if gs[23] == 2 { tx = gs[0] * 20 }
531 if gs[23] == 3 { tx = gs[0] * 20 + 16 }
532 g_fill(tx, ty, 4, 4, 12)
533 return 0
534}
535func g_bar(x0: i64, y0: i64, val: i64, max: i64, col: i64) -> i64 {
536 var n: i64 = 0
537 if max > 0 { n = val * 120 / max }
538 if n < 0 { n = 0 }
539 if n > 120 { n = 120 }
540 g_fill(x0, y0, 120, 12, 12)
541 g_fill(x0, y0, n, 12, col)
542 return 0
543}
544// party dots: one small square per member, dim if fainted, white ring on active
545func g_render_party(gs: *i64) -> i64 {
546 let c: i64 = gs[4]
547 var i: i64 = 0
548 while i < c {
549 let px: i64 = 8 + i * 22
550 if i == gs[19] { g_fill(px - 2, 44, 20, 20, 4) }
551 var col: i64 = g_species_col(g_party_sp(i))
552 if g_party_hp(i) <= 0 { col = 1 }
553 g_fill(px, 46, 16, 16, col)
554 i = i + 1
555 }
556 return 0
557}
558func g_render_battle(gs: *i64) -> i64 {
559 g_fill(0, 0, 320, 240, 5)
560 g_fill(20, 150, 110, 60, 2)
561 g_fill(200, 60, 100, 50, 2)
562 let fr: i64 = gs[20]
563 var bob: i64 = (fr / 6) % 4
564 if bob == 3 { bob = 1 }
565 let fx: i64 = gs[21]
566 let kind: i64 = gs[22]
567 var myx: i64 = 36
568 if fx > 0 { if kind == 1 {
569 var l: i64 = fx
570 if l > 5 { l = 10 - l }
571 myx = 36 + l * 6
572 } }
573 g_draw_pet(gs[14], 216, 64, 70, 84, bob)
574 if fx > 0 { if kind == 1 { if fx >= 4 { if fx <= 7 { g_fill(216, 64, 70, 84, 4) } } } }
575 g_draw_pet(gs[9], myx, 96, 70, 84, bob)
576 g_bar(20, 24, gs[11], gs[12], 11)
577 g_bar(180, 214, gs[6], gs[7], 10)
578 g_render_party(gs)
579 return 0
580}
581func gi_tick() -> i64 {
582 let gs: *i64 = (K_MAGIC_1024 as i64) as *i64
583 gs[20] = gs[20] + 1
584 if gs[21] > 0 { gs[21] = gs[21] - 1 }
585 return gs[21]
586}
587func gi_render() -> i64 {
588 let gs: *i64 = (K_MAGIC_1024 as i64) as *i64
589 if gs[2] == 1 { g_render_battle(gs); return 0 }
590 g_render_overworld(gs)
591 return 0
592}
593func gi_get(field: i64) -> i64 {
594 let gs: *i64 = (K_MAGIC_1024 as i64) as *i64
595 if field >= 0 { if field < 30 { return gs[field] } }
596 return 0
597}
598func gi_fb_offset() -> i64 { return K_MAGIC_65536 }
599func gi_fb_w() -> i64 { return 320 }
600func gi_fb_h() -> i64 { return 240 }
601func gi_synth(sfx: i64) -> i64 { return g_synth(sfx) }
602func gi_audio_offset() -> i64 { return K_MAGIC_147456 }
603func gi_audio_rate() -> i64 { return K_MAGIC_8000 }
604func gi_take_sfx() -> i64 {
605 let gs: *i64 = (K_MAGIC_1024 as i64) as *i64
606 let v: i64 = gs[30]
607 gs[30] = 0
608 return v
609}
610func main() -> i64 {
611 gi_init(K_MAGIC_20260613)
612 gi_render()
613 return gi_get(4)
614}