code wiki / _hdl_build / nx_game_actor.nx
nx_game_actor.nx
buildroot/runtime/_hdl_build/nx_game_actor.nx
about
nx_game_actor.nx -- the character<->environment INTERACTION substrate (ws=game-interact 2026-07-27).
The gamebench honest audit says the emitted games are click-loops: nothing lets a character MOVE through
a world, be STOPPED by it, or MEET another character. This lib is that missing floor, first-byte-up:
- ONE walkability grid (0=open 1=wall, the exact nx_pathfind convention) shared by movement, entity
collision AND pf_astar => the player and every NPC agree on passability BY CONSTRUCTION -- there is
no second copy of the map to drift (the dual-source hazard killed at design time).
- an OCCUPANCY index (cell -> actor handle) kept consistent by the ONLY mover, ac_step.
- BUMP-TO-INTERACT: moving into an occupied cell does not move you -- it RETURNS the occupant. The
bump is the interaction primitive (NetHack/Crawl/CDDA idiom -- the ingested corpus's own model):
bump an enemy = engage, bump an NPC = talk. The GAME decides; this lib only reports truthfully.
Actors live in the certified nx_entity_store (handle = index+generation => stale handles detectably
invalid). All integer, deterministic, no globals. LIB, no main. license_tier: ORIGINAL
dependencies 2 imports · 2 importers
imports: nx_syscalls.nxnx_entity_store.nx
imported by: nx_game_actor_gate.nxnx_game_agent.nx
structs
| none |
consts
| 17 | const WD_HDR: i64 = 2 |
| 61 | const AC_NC: i64 = 12 |
| 62 | const A_X: i64 = 0 |
| 63 | const A_Y: i64 = 1 |
| 64 | const A_KIND: i64 = 2 // 0 player, 1 enemy, 2 npc |
| 65 | const A_STATE: i64 = 3 // agent brain writes this (see nx_game_agent) |
| 66 | const A_HP: i64 = 4 |
| 67 | const A_MAXHP: i64 = 5 |
| 68 | const A_HOMEX: i64 = 6 |
| 69 | const A_HOMEY: i64 = 7 |
| 70 | const A_TICK: i64 = 8 // per-actor deterministic phase counter |
| 71 | const A_SPEC: i64 = 9 // species row (links battle/companion data) |
| 72 | const A_LVL: i64 = 10 |
| 73 | const A_SEED: i64 = 11 // per-actor rng stream seed |
| 100 | const AC_MOVED: i64 = 0 |
| 101 | const AC_WALL: i64 = 1 |
| 102 | const AC_OOB: i64 = 2 |
| 103 | const AC_BUMP: i64 = 3 // out[0] = the occupant's handle |
| 104 | const AC_DEAD: i64 = 4 // stale/invalid handle |
functions
| 19 | func wd_words(w: i64, h: i64) -> i64 { return WD_HDR + w*h*2 } |
| 20 | func wd_bytes(w: i64, h: i64) -> i64 { return wd_words(w, h) * 8 } |
| 22 | func wd_init(wd: *i64, w: i64, h: i64) -> i64 |
| 29 | func wd_w(wd: *i64) -> i64 { return wd[0] } called by 1: ag_step_astar |
| 30 | func wd_h(wd: *i64) -> i64 { return wd[1] } called by 1: ag_step_astar |
| 32 | func wd_grid(wd: *i64) -> *i64 { return ((wd as i64) + WD_HDR*8) as *i64 } |
| 34 | func wd_in(wd: *i64, x: i64, y: i64) -> i64 |
| 41 | func wd_set_wall(wd: *i64, x: i64, y: i64, v: i64) -> i64 |
| 46 | func wd_wall(wd: *i64, x: i64, y: i64) -> i64 |
| 50 | func wd_occ(wd: *i64, x: i64, y: i64) -> i64 |
| 54 | func wd_set_occ(wd: *i64, x: i64, y: i64, hnd: i64) -> i64 |
| 76 | func ac_spawn(wd: *i64, ar: *i64, x: i64, y: i64, kind: i64, hp: i64, spec: i64, lvl: i64, seed: i64) -> i64 |
| 92 | func ac_remove(wd: *i64, ar: *i64, hnd: i64) -> i64 |
| 108 | func ac_step(wd: *i64, ar: *i64, hnd: i64, dx: i64, dy: i64, out: *i64) -> i64 called by 5: mainag_step_towardag_step_astarag_step_patrolmain calls 7: en_validen_getwd_inwd_wallwd_occwd_set_occ+1 |
| 130 | func ac_dist2(ar: *i64, a: i64, b: i64) -> i64 |
| 135 | func ac_adjacent(ar: *i64, a: i64, b: i64) -> i64 |
| 145 | func ac_los(wd: *i64, x0: i64, y0: i64, x1: i64, y1: i64) -> i64 |
| 175 | func ac_occ_check(wd: *i64, ar: *i64) -> i64 |
| 206 | func ac_ck(wd: *i64, ar: *i64) -> i64 |