Instructions for programming AI with Battlegen
Create an an8 file with figures, sequences all set up.
Start Battlegen
Go to setup->files, and select a file containing the figures you will use
The program will load the files, and you will be able to verify that they are there by looking at the left listbox. The middle listbox will show the sequences associated with the selected figure.
Press Hide Me to return to the main menu
On the main menu, go to setup->Types
Add a type, give it an appropriate name.
You may set up the stats as much as you want, but only maximum life, # in action, damage, range, figure used and team are required. You must type in the figure used properly, or it will warn you that you didn’t. Press apply changes. Make sure that you have assigned types to different teams, or else many of the more advanced AI functions won’t work.
Repeat for however many types you want.
Close the type editor.
On the main menu, go to setup->positioning
Select each type, and follow the instructions at the top of the screen. The view you see is a top-down representation of the game area, and is approx. 200 an8 units wide by 200 high.
Now, it is time to program AI.
For those of you with experience in VBScript, this shouldn’t be TOO difficult, but it may be somewhat steep for those with none. Here is a sample program, that will cause the type that is running it to run towards the closest enemy unit, and “attack” it. Instructions for what to replace to customize this script are in red. General comments are in green. One thing to remember is:
SAVE THE
CODE. YOU MUST PRESS THE RED ‘SAVE
CODE’ BUTTON IN ORDER FOR YOUR WORK TO BE SAVED.
Sub main
Thisguy.whatframe = thisguy.whatframe – Not Particularly required, but is very useful to keep
track of what frame this character is on
If thisguy.whatframe = 1 then
Thisguy.posoutput
= thisguy.posoutput &
outputloc(thisguy.xpos,thisguy.ypos,thisguy.zpos,thisguy.whatframe)
This line sets a keyframe in
anim8or that sets the guy’s position at the first frame.
Thisguy.posoutput
= thisguy.posoutput &
movetoclosest(thisguy.xpos,thisguy.ypos,thisguy.zpos,thisguy.whatframe + 30,1)
This line sets a keyframe in
anim8or at frame 31, so that this guy will be on top of the closest enemy by
frame 31. You can adjust the 30 so that it is
a later frame. You can adjust the 1 at
the end, and he will be on top of the closest guy on team n, where n is the
number you put in there.
Thisguy.faceoutput
= thisguy.faceoutput & faceclosest(thisguy.xpos,thisguy.ypos,thisguy.zpos,thisguy.whatframe,1)
This line sets a keyframe for
the target that this guy points towards, so it is on top of the closest enemy
on this frame, and stays that way. You can
change thisguy.whatframe so that the target is there at a different time, and
you can change 1 to another team to have the target on top of the closest guy
on another team.
End if – this ends the block of the if statement that occurs only
on the first frame
Thisguy.xpos = thisguy.xpos +
wheremyx(thisguy.xpos,game.getclx(thisguy.xpos,thisguy.ypos,thisguy.zpos,1),thisguy.whatframe,30)
Thisguy.ypos = thisguy.ypos +
wheremyy(thisguy.ypos,game.getcly(thisguy.xpos,thisguy.ypos,thisguy.zpos,1),thisguy.whatframe,30)
Thisguy.zpos = thisguy.zpos +
wheremyz(thisguy.zpos,game.getclz(thisguy.xpos,thisguy.ypos,thisguy.zpos,1),thisguy.whatframe,30)
These lines allow the person in question to tell where in the world they are. A problem with the keyframing in the If block above is that the figure moves in anim8or, but the variables that tell it where it is do not. So, the wheremyx, y, and z functions will give you a value that tells you how far to move this turn, if you are at a certain location and want to be somewhere by a certain time (a keyframe). The getclx, getcly, and getclz functions tell you the x,y, and z co-ordinates of the closest enemy, on a certain team. These functions are somewhat advanced, so don’t change them until you’ve read the function definitions (coming later).
If
disttoclosest(thisguy.xpos,thisguy.ypos,thisguy.zpos,1) < 30 and
thisguy.seqrunning = false then
Thisguy.seqrunning = true
Thisguy.seqdonewhen = thisguy.whatframe + 30
Thisguy.seqoutput = thisguy.seqoutput &
dosomething(“lingattack”,thisguy.whatframe)
End if
This block is the attack block. Basically, if the distance to the closest enemy is less than 30
units, and this guy is not currently running a sequence, then set his
seqrunning variable to true. This tells
it that now is not the time to start another sequence, and prevents it from
starting a new attack sequence on every frame that it’s close to an enemy. Then it sets it’s seqdonewhen variable to
thisguy.whatframe + 30. This tells it
that the sequence will be done in 30 frames, and then the code below will tell
it that seqrunning = false. The third
line appends a namedsequence(“lingattack” thisguy.whatframe) to the file that
is constantly being built. This is
later written to a file that anim8or can read.
You can change 1 in the disttoclosest function
in the if statement, the 30 in the if statement. The “lingattack” refers to the sequence that you want to run when
the attack cycle is run.
If thisguy.seqdonewhen <
thisguy.whatframe then
Thisguy.seqrunning = false
End if
This code looks at when the currently running sequence is done, and if the current frame is past that, then thisguy tells himself that the sequence isn’t running anymore.
End Sub
For all your other unit
types, simply type
Sub main
End sub
Now that the code is
complete, you have some more things to accomplish. You have to duplicate figures and you have to actually run the
simulation.
Duplicating Figures:
To duplicate figures, run
the dupefigs.exe program included in the battlegen zip. Open the file that contains the figures you
want to work with, and then enter the numbers of each unit you need. A problem may be: if you have the figures in
your an8 file in a different order than the figures in your battlegen program,
it won’t work. You will be able to tell
the order of the figures by the order that the inputboxes ask for data about
them. If this happens, then e-mail me
the file at artartartartort@hotmail.com, and I can fix the order for you. Specify the order you want. Future versions of dupefigs will allow for
order changing. You will need the same
amount of figures of each type as the “# in action” that you entered when you
created the types.
Once the figures are
duplicated, all that remains is to run the simulation and to import the
file. Save the file (file->save). Select how many frames you want to run, the
2 textboxes below it should tell you how many units are in each army, and then
press run. The first dialog box will be
asking you where you want to save the battlegen file you have made. This is in case of a fatal error. The second dialog box will hopefully be
asking you where you want it saved. If
you get an error, then make the appropriate changes in the code, and try again. Whenever you get a coding error, save your
work and restart battlegen and load it.
There are bugs that make is so that the second running after an error
will create a lot of problems.
Function Descriptions
GetCX(whatC as variant) –
this function will return the x co-ordinate of and given ‘contact’.
GetCY(whatC as variant) –
same as above, but for Y
GetCZ(whatC as variant) –
same
GetCT(whatC as variant) –
tells you want team a specific contact is on
GetCLx(xpos as double, ypos
as double, zpos as double, onteam as long) as double
This function returns the x
position of the closest contact to the position (x,y,z) specified on the team
(onteam) that you specify.
GetCLy(xpos as double, ypos
as double, zpos as double, onteam as long) as double
Same as GetCLx, but for y
co-ordinates
GetCLz(xpos as double, ypos
as double, zpos as double, onteam as long) as double
Same as GetCLy, but for z
co-ordinates
Outputloc(xpos as
double,ypos as double,zpos as double,whatframe as long) as string
This function will output a
string that you will append onto the posoutput string on thisguy. This is a new keyframe, at a specified
frame(whatframe)
DoSomething(dowhat as
string, whatframe as long) as string
This is like outputloc, but
it adds a key for a sequence (dowhat) to start at a specified frame (whatframe)
FacePos(xpos as double,
ypos, as double, zpos as double, whatframe as long) as string
This is like outputloc and
dosomething, except it outputs a key for the target that thisguy faces. The key is at (x,y,z), at a frame you
specify (whatframe)
DistFromMe(x1 as double, y1
as double, z1 as double, whatC as long) as double
This will return how far
away a location (x,y,z) is from a specified contact (whatC)
FaceContact(whatC as
long,whatframe as long) as string
This will output a string
that will key the target to be on top of a contact (whatc), at a specified
frame (whatframe)
WhoClosest(xpos as
double,ypos as double, zpos as double, onteam as long) as long
This will return which
contact is the closest to a specified loction, on a specified team
Attack(whatc as long,
damage as long) as Boolean
This function tells the
game engine to damage a specific contact.
Suggestion: you should sub whoclosest() in for whatc. This will cause thisguy to attack whatc. Note: All this does is subtract health and
say if it is dead. This DOES NOT run
any animations. The Boolean value
returned will tell you if your attack killed anything.
Movetoclosest(xpos as
double, ypos as double, zpos as double, bywhen as long, onteam as long) as
string
This function will return a
string to be appended onto posoutput, that will key thisguy to be at the
closest member of team (onteam) by frame (bywhen).
FaceClosest(xpos as double,
ypos as double, zpos as double,bywhen as long, onteam as long) as string
This function will return a
string to be appended onto faceoutput, that will key the target that thisguy
faces to be on the closest member of team (onteam) by frame (bywhen)
DisttoClosest(xpos as
double, ypos as double, zpos as double, onteam as long) as double
This function will return
the distance to the closest member of team (onteam). This could be used for flocking maneuvers, but there is no
direction associated with it – yet.
WheremyX – explained in
sample code
WheremyY – explained in
sample code
WheremyZ – expliained in
sample code
MovetoRandom(bywhen as
long, onteam as long) as string
This will key thisguy to
move to a random member of team (onteam) by frame (bywhen).