code wiki / _hdl_build / nx_char_ai_gate.nx

nx_char_ai_gate.nx source

↩ module page · 65 lines · 3651 B

1// nx_char_ai_gate.nx -- proves G-R2 char-AI (behavior tree + FSM). NPC BT (priority selector): 2// SEL[ SEQ[COND health_low, ACT flee], SEQ[COND enemy_visible, ACT attack], ACT patrol ] 3// blackboard bits: 0=health_low, 1=enemy_visible. actions: flee=1, attack=2, patrol=3. 4// FSM: IDLE--see-->ATTACK--health_low-->FLEE--healed-->IDLE (no other transitions). GREEN only if every 5// decision + transition is correct, incl. priority and neg-controls. license_tier: ORIGINAL expect_exit: 0 6import "nx_syscalls.nx" 7import "nx_char_ai.nx" 8 9func cw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 10func cn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 } 11 12func bt_action(ty: *i64, a0: *i64, nk: *i64, kids: *i64, bb: i64) -> i64 { 13 let ao: *i64 = sys_mmap(8) as *i64 14 ao[0] = -1 15 bt_tick(ty, a0, nk, kids, 0, bb, ao) 16 return ao[0] 17} 18 19func main() -> i64 { 20 // ---- behavior tree (8 nodes) ---- 21 let ty: *i64 = sys_mmap(8 * 8) as *i64 22 let a0: *i64 = sys_mmap(8 * 8) as *i64 23 let nk: *i64 = sys_mmap(8 * 8) as *i64 24 let kids: *i64 = sys_mmap(8 * 32) as *i64 25 var i: i64 = 0 26 while i < 32 { kids[i] = -1; i = i + 1 } 27 // node 0 SEL(flee-seq, attack-seq, patrol); 1 SEQ(cond hp, act flee); 2 COND hp; 3 ACT flee; 28 // 4 SEQ(cond vis, act atk); 5 COND vis; 6 ACT atk; 7 ACT patrol 29 ty[0]=NT_SEL; nk[0]=3; kids[0]=1; kids[1]=4; kids[2]=7 30 ty[1]=NT_SEQ; nk[1]=2; kids[4]=2; kids[5]=3 31 ty[2]=NT_COND; a0[2]=0 32 ty[3]=NT_ACT; a0[3]=1 33 ty[4]=NT_SEQ; nk[4]=2; kids[16]=5; kids[17]=6 34 ty[5]=NT_COND; a0[5]=1 35 ty[6]=NT_ACT; a0[6]=2 36 ty[7]=NT_ACT; a0[7]=3 37 38 var pass: i64 = 0 39 var total: i64 = 0 40 41 total=total+1; if bt_action(ty,a0,nk,kids, 1)==1 { pass=pass+1 } else { cw("BT1 FAIL health_low!=flee got "); cn(bt_action(ty,a0,nk,kids,1)); cw("\n") } // health_low -> flee 42 total=total+1; if bt_action(ty,a0,nk,kids, 2)==2 { pass=pass+1 } else { cw("BT2 FAIL enemy!=attack\n") } // enemy_visible -> attack 43 total=total+1; if bt_action(ty,a0,nk,kids, 3)==1 { pass=pass+1 } else { cw("BT3 FAIL priority (both)!=flee\n") } // both -> flee (priority) 44 total=total+1; if bt_action(ty,a0,nk,kids, 0)==3 { pass=pass+1 } else { cw("BT4 FAIL none!=patrol\n") } // nothing -> patrol 45 46 // ---- FSM (3 states x 4 events) ---- 47 // states IDLE=0 ATTACK=1 FLEE=2 ; events SEE=0 LOSE=1 HPLOW=2 HEALED=3 48 let trans: *i64 = sys_mmap(8 * 12) as *i64 49 var j: i64 = 0 50 while j < 12 { trans[j] = -1; j = j + 1 } 51 trans[0*4 + 0] = 1 // IDLE + SEE -> ATTACK 52 trans[1*4 + 1] = 0 // ATTACK + LOSE -> IDLE 53 trans[1*4 + 2] = 2 // ATTACK + HPLOW -> FLEE 54 trans[2*4 + 3] = 0 // FLEE + HEALED -> IDLE 55 56 total=total+1; if fsm_step(trans,4, 0,0)==1 { pass=pass+1 } else { cw("FSM1 FAIL idle+see!=attack\n") } 57 total=total+1; if fsm_step(trans,4, 1,2)==2 { pass=pass+1 } else { cw("FSM2 FAIL attack+hplow!=flee\n") } 58 total=total+1; if fsm_step(trans,4, 2,3)==0 { pass=pass+1 } else { cw("FSM3 FAIL flee+healed!=idle\n") } 59 total=total+1; if fsm_step(trans,4, 0,1)==0 { pass=pass+1 } else { cw("FSM4 FAIL idle+lose should STAY idle\n") } // NEG-CONTROL: no transition 60 61 cw("CHAR-AI "); cn(pass); cw("/"); cn(total); cw("\n") 62 if pass == total { cw("CHAR-AI ALL-PASS (BT priority decisions + FSM transitions + neg-control)\n"); sys_exit(0) } 63 sys_exit(1) 64 return 1 65}