code wiki / _hdl_build / nx_creature_game.nx

nx_creature_game.nx source

↩ module page · 80 lines · 4323 B

1// nx_creature_game.nx -- the creature-collector exposed as a REAL, PLAYABLE black-box interface (so an automated 2// playtester can drive it blind, like a player). Genuine agency + fail states: encounters are TWO-WAY (the wild 3// fights back; your lead can FAINT = lose), balls are limited, KOing a wild loses the catch, the route ends. 4// WIN = catch the goal number of creatures; LOSE = lead faints / route ends short / step cap. Interface the 5// playtester is allowed to use: cg_init / cg_status / cg_nlegal / cg_observe / cg_step. NO privileged internals. 6// Pure-integer, deterministic. license_tier: ORIGINAL 7import "nx_creature_battle.nx" 8import "nx_creature_world.nx" 9import "nx_syscalls.nx" 10const CG_MAGIC_1103515245: i64 = 1103515245 11const CG_MAGIC_12345: i64 = 12345 12const CG_MAGIC_32767: i64 = 32767 13 14const CG_LEAD: i64 = 8 // lead creature at st[8..31] 15const CG_WILD: i64 = 32 // wild creature at st[32..55] 16const CG_STEP_CAP: i64 = 500 17 18func st_rngbox(st: *i64) -> *i64 { return ((st as i64) + 58*8) as *i64 } 19func cg_rng(st: *i64) -> i64 { let b: *i64 = st_rngbox(st); var x: i64 = b[0]; x = x*CG_MAGIC_1103515245 + CG_MAGIC_12345; b[0] = x; return (x >> 16) & CG_MAGIC_32767 } 20 21func cg_init(seed: i64) -> *i64 { 22 let st: *i64 = sys_mmap(8*64) as *i64 23 var z: i64 = 0; while z < 64 { st[z] = 0; z = z + 1 } 24 st[0] = 0; st[1] = 0; st[2] = 2; st[3] = 0; st[4] = 6; st[5] = 0; st[58] = seed 25 let lead: *i64 = ((st as i64) + CG_LEAD*8) as *i64 26 cb_set(lead, 1, 25, 240, 70, 70, 70, "Embercat" as *u8); cb_addmove(lead, 1, 40, 100); cb_addmove(lead, 0, 60, 100) 27 let route: *u8 = sys_mmap(16); var i: i64 = 0; while i < 14 { route[i] = 0 as u8; i = i + 1 } 28 route[1]=1 as u8; route[3]=1 as u8; route[5]=1 as u8; route[7]=1 as u8; route[9]=1 as u8; route[11]=1 as u8; route[13]=1 as u8 29 st[56] = route as i64; st[57] = 14 30 return st 31} 32func cg_status(st: *i64) -> i64 { if st[0] == 2 { return 1 } if st[0] == 3 { return 2 } return 0 } 33func cg_nlegal(st: *i64) -> i64 { if st[0] == 1 { return 4 } if st[0] == 0 { return 1 } return 0 } 34// player-visible observation: [0]mode [1]leadhp [2]leadmax [3]wildhp [4]wildmax [5]balls [6]caught [7]goal [8]pos [9]routelen [10]steps 35func cg_observe(st: *i64, o: *i64) -> i64 { 36 let lead: *i64 = ((st as i64) + CG_LEAD*8) as *i64; let wild: *i64 = ((st as i64) + CG_WILD*8) as *i64 37 o[0]=st[0]; o[1]=lead[3]; o[2]=lead[2]; o[3]=0; o[4]=0 38 if st[0] == 1 { o[3]=wild[3]; o[4]=wild[2] } 39 o[5]=st[4]; o[6]=st[3]; o[7]=st[2]; o[8]=st[1]; o[9]=st[57]; o[10]=st[5] 40 return 0 41} 42func cg_wild_attacks(st: *i64, lead: *i64, wild: *i64) -> i64 { 43 let mi: i64 = cb_best(wild, lead); let mt: i64 = wild[8+mi*3]; let mp: i64 = wild[8+mi*3+1] 44 let dmg: i64 = cb_damage(wild, lead, mt, mp, st_rngbox(st)) 45 lead[3] = lead[3] - dmg 46 if lead[3] <= 0 { lead[3] = 0; st[0] = 3 } 47 return 0 48} 49// advance one step. a is a legal action index (walk: 0=step ; encounter: 0/1=attack move, 2=ball, 3=flee). 50func cg_step(st: *i64, a: i64) -> i64 { 51 if st[0] >= 2 { return 0 } 52 st[5] = st[5] + 1 53 if st[5] > CG_STEP_CAP { st[0] = 3; return 0 } 54 let lead: *i64 = ((st as i64) + CG_LEAD*8) as *i64 55 let wild: *i64 = ((st as i64) + CG_WILD*8) as *i64 56 let route: *u8 = st[56] as *u8 57 if st[0] == 0 { 58 var hp: i64 = lead[3] + lead[2]/8; if hp > lead[2] { hp = lead[2] } lead[3] = hp // regen between encounters 59 st[1] = st[1] + 1 60 if st[1] >= st[57] { if st[3] >= st[2] { st[0] = 2 } else { st[0] = 3 } return 0 } 61 if route[st[1]] == (1 as u8) { if (cg_rng(st) % 100) < 70 { cw_spawn(wild, 0); st[0] = 1 } } 62 return 0 63 } 64 if a == 3 { st[0] = 0; return 0 } 65 if a == 2 { 66 if st[4] > 0 { 67 st[4] = st[4] - 1 68 if cw_try_catch(wild, 1, st_rngbox(st)) == 1 { st[3] = st[3] + 1; st[0] = 0; if st[3] >= st[2] { st[0] = 2 } return 0 } 69 } 70 cg_wild_attacks(st, lead, wild) 71 return 0 72 } 73 var mv: i64 = a; if mv > lead[7] - 1 { mv = 0 } 74 let mt: i64 = lead[8+mv*3]; let mp: i64 = lead[8+mv*3+1] 75 let dmg: i64 = cb_damage(lead, wild, mt, mp, st_rngbox(st)) 76 wild[3] = wild[3] - dmg 77 if wild[3] <= 0 { wild[3] = 0; st[0] = 0; return 0 } // KO'd -> lost the catch, back to walk 78 cg_wild_attacks(st, lead, wild) 79 return 0 80}