Instructions for programming AI with Battlegen

 

Sample AI creation

 

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).

 

 

 

1