i've been writing a scripting engine to describe the player AI in the gridiron football game i've been working on. the premise behind it is that for each play i have 11 pointers to what is internally referred to as "behaviors." so to line up in the I-formation:
copy the above pointers into the "script pointer" field for each of the player structs. now behaviors are further broken down into "commands."
so those two commands position the the player 16 and 64 pixels (respectively) away from the ball (x-coor) followed by setting their stance. 8 pixels = 1 yard. after the positioning scripts are ran for the formation, the scripts pointers for that particular play are written.
commands are grouped based on what they do. ex $Cx commands handle placement/movement:
every $2x is a random jump from the current behavior to another behavior. this allows for a degree of randomness in defensive coverage, offensive blocking, turnovers, etc. $Fx commands simulate control statements like loops or if-then/if-then-else.
the problem i have is speed. so far i have a big switch that first decides the type of command with a series of cmp VAL and bcs THERE. THERE is an entry in a jump table. from there it further compares to find the exact command (like say SET_POS_FROM_BALL and SET_POS_FROM_SCREEN). these two commands share most of the same code except FROM_BALL first converts the x-coor argument into the equivilent FROM_SCREEN x-coor argument. MOVE_ABS and MOVE_REL are similar in that they fill the high byte with the high byte of the camera position and jump to their _FAR equivilents.
this seems to be the most straight forward way to do it, but as more and more gamplay features are added, as well as a second team, i know that a series of compares is not gonna cut it. i'm reluctant to use a pointer table for all 255 possible commands because some commands are exactly the same (like $2x) except for the argument. i also have about 64 commands that are really only 4 commands just with the target player changed. ex:
on top of the AI processing for 22 players, there is the conversion from absolute positions into screen positions. though much simpler then tokumaru's situation since i only scroll left and right. it just seems like all the compares/branches will really take a toll on speed once i start adding other things that need to be handled.
Code:
; W
;
; T
; G
; HFQC
; G
; T
; E
;
; W
off_form_I:
.dw _off_QB_PosUnderCenter, _off_RB_PosAsHB, _off_RB_PosAsFB
.dw _off_WR_PosSplitEndTop, _off_WR_PosFlankerBot, _off_TE_PosAsTEBot
.dw _off_ol_PosAsLT, _off_ol_PosAsLG, _off_ol_PosAsC, _off_ol_PosAsRG, _off_ol_PosAsRT
;
; T
; G
; HFQC
; G
; T
; E
;
; W
off_form_I:
.dw _off_QB_PosUnderCenter, _off_RB_PosAsHB, _off_RB_PosAsFB
.dw _off_WR_PosSplitEndTop, _off_WR_PosFlankerBot, _off_TE_PosAsTEBot
.dw _off_ol_PosAsLT, _off_ol_PosAsLG, _off_ol_PosAsC, _off_ol_PosAsRG, _off_ol_PosAsRT
copy the above pointers into the "script pointer" field for each of the player structs. now behaviors are further broken down into "commands."
Code:
_off_QB_PosUnderCenter: .db SET_POS_FROM_BALL, $10, $00
.db QB_STANCE
_off_QB_PosShotgun: .db SET_POS_FROM_BALL, $40, $00
.db QB_STANCE
.db QB_STANCE
_off_QB_PosShotgun: .db SET_POS_FROM_BALL, $40, $00
.db QB_STANCE
so those two commands position the the player 16 and 64 pixels (respectively) away from the ball (x-coor) followed by setting their stance. 8 pixels = 1 yard. after the positioning scripts are ran for the formation, the scripts pointers for that particular play are written.
commands are grouped based on what they do. ex $Cx commands handle placement/movement:
Code:
...
SET_POS_FROM_BALL equ $C0 ; SET_POS_FROM_BALL (signed byte x, signed byte y)
SET_POS_FROM_SCREEN equ $C1 ; SET_POS_FROM_SCREEN (signed byte x, byte y)
MOVE_ABS equ $C2 ; MOVE_ABS (byte x, byte y)
MOVE_ABS_FAR equ $C3 ; MOVE_ABS_FAR (word x, byte y)
MOVE_REL equ $C4 ; MOVE_REL (signed byte x, singed byte y)
MOVE_REL_FAR equ $C5 ; MOVE_REL_FAR (signed word x, singed byte y)
...
SET_POS_FROM_BALL equ $C0 ; SET_POS_FROM_BALL (signed byte x, signed byte y)
SET_POS_FROM_SCREEN equ $C1 ; SET_POS_FROM_SCREEN (signed byte x, byte y)
MOVE_ABS equ $C2 ; MOVE_ABS (byte x, byte y)
MOVE_ABS_FAR equ $C3 ; MOVE_ABS_FAR (word x, byte y)
MOVE_REL equ $C4 ; MOVE_REL (signed byte x, singed byte y)
MOVE_REL_FAR equ $C5 ; MOVE_REL_FAR (signed word x, singed byte y)
...
every $2x is a random jump from the current behavior to another behavior. this allows for a degree of randomness in defensive coverage, offensive blocking, turnovers, etc. $Fx commands simulate control statements like loops or if-then/if-then-else.
the problem i have is speed. so far i have a big switch that first decides the type of command with a series of cmp VAL and bcs THERE. THERE is an entry in a jump table. from there it further compares to find the exact command (like say SET_POS_FROM_BALL and SET_POS_FROM_SCREEN). these two commands share most of the same code except FROM_BALL first converts the x-coor argument into the equivilent FROM_SCREEN x-coor argument. MOVE_ABS and MOVE_REL are similar in that they fill the high byte with the high byte of the camera position and jump to their _FAR equivilents.
this seems to be the most straight forward way to do it, but as more and more gamplay features are added, as well as a second team, i know that a series of compares is not gonna cut it. i'm reluctant to use a pointer table for all 255 possible commands because some commands are exactly the same (like $2x) except for the argument. i also have about 64 commands that are really only 4 commands just with the target player changed. ex:
Code:
HANDOFF_QB equ $50
HANDOFF_HB equ $51
HANDOFF_FB equ $52
HANDOFF_WR1 equ $53
...
HANDOFF_HB equ $51
HANDOFF_FB equ $52
HANDOFF_WR1 equ $53
...
on top of the AI processing for 22 players, there is the conversion from absolute positions into screen positions. though much simpler then tokumaru's situation since i only scroll left and right. it just seems like all the compares/branches will really take a toll on speed once i start adding other things that need to be handled.