Building an AI

Tutorial for Generals Gen

Avatar of Calamity_Jones

Calamity_Jones

Category: Code
Level: Expert
Created: Wednesday July 29, 2009 - 7:24
Updated: Sunday October 11, 2009 - 8:10
Views: 4427
Summary: A step by step guide to building an AI for your mod.
Rating
  • Staff-
  • Members-
  • Average-

0 votes

Page 1 2 3 4 5 6 7 8
Original Author: Calamity_Jones

Right. Leave this folder and run off to "###_Setup" And add these scripts: (The actions are in Player/AI)

TYPE: [nsAD][E]
NAME: "###_E_Build Times"
              
Code

*** IF ***
    True.
*** THEN ***
Player '<This Player>' seconds between building teams. 20


TYPE: [nsAD][N]
NAME: "###_N_Build Times"
              
Code

*** IF ***
    True.
*** THEN ***
Player '<This Player>' seconds between building teams. 15


TYPE: [nsAD][H]
NAME: "###_H_Build Times"
              
Code

*** IF ***
    True.
*** THEN ***
Player '<This Player>' seconds between building teams. 10


This simply tells the AI how often to build a team of units.

Now things get a bit tedious... You'll need to define what every unit you use in the game is, in order to make priorities. Start by making a [nsAD][ENH] script called "###_Define Object Types". Then add an action like: "'Tanks' : add 'TANK NAME'" which is under Scripting/ObjectTypeList. The list is Tanks, and the object is your tank. Continue to define types and add objects for each faction that are of that type. Part of mine looks like this:

              
Code

*** IF ***
    True.
*** THEN ***
'Tanks' : add 'CadianLemanRuss'
'Tanks' : add 'CadianLemanRussVanquisher'
'Tanks' : add 'TauHammerHead'
'Tanks' : add 'TauCrisis'
'Tanks' : add 'UltramarinePredator'
'Tanks' : add 'UltramarineLandRaider'
'Artillery' : add 'CadianBasilisk'
'SuperUnit' : add 'ImperialNavyVulture'
'Transport' : add 'CadianChimera'
'Transport' : add 'CadianChimeraLoadK'
'Transport' : add 'CadianChimeraLoadN'
'Transport' : add 'TauDevilFish'
'Transport' : add 'TauDevilFishLoadN'
'Transport' : add 'TauDevilFishLoadP'
'Transport' : add 'UltramarineRhino'
'Heavy Weapons Infantry' : add 'CadianMissileLauncher'
'Heavy Weapons Infantry' : add 'TauInfantryPathfinderRailGun'
'Heavy Weapons Infantry' : add 'UltramarineMissileLauncher'
'Heavy Weapons Infantry' : add 'UltramarineLasCannon'
'Heavy Weapons Infantry' : add 'UltramarinePlasmaGun'
'Standard Infantry' : add 'CadianDevastatorSargeant'
'Standard Infantry' : add 'CadianLasgun'
'Standard Infantry' : add 'CadianLasgun1'
'Standard Infantry' : add 'CadianLasgun2'
'Standard Infantry' : add 'CadianLasgun3'
'Standard Infantry' : add 'CadianLasgun4'


Once you've finished this script you need to OK the scripts window to update the map. (If you don't, the script editor will not know your object types exist... Also, you should probably save.) Then re-open the scripts window and add a script like this:

TYPE: [nsAD][ENH]
NAME: "###_Define Priorities_Generic"
              
Code

*** IF ***
    True.
*** THEN ***
For Attack priority set 'CAD_Generic' set the priority of object type 'Artillery' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'Base Buildings' to 90
For Attack priority set 'CAD_Generic' set the priority of object type 'Base Defences' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'Builder' to 90
For Attack priority set 'CAD_Generic' set the priority of object type 'Bunkers' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'Heavy Weapons Infantry' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'Special Weapons Infantry' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'Standard Infantry' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'SuperUnit' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'Tanks' to 100
For Attack priority set 'CAD_Generic' set the priority of object type 'Tech Buildings' to 0
For Attack priority set 'CAD_Generic' set the priority of object type 'Transport' to 100


The action is in AttackPrioritySet/CreateSet (Modify a sets priority for a single unit type) For yours, name the set "###_Generic" and set your different types in order of their importance... i.e. what you want your AI to want to attack more. You can set things to the same value if you want. You could even set everything to the same value.

You can also define priority sets for different unit types, or specific units. It's cleaner to do this in a separate script. If you have rocket soldiers and machine gun soldiers for example, make one script called "###_Define Priorities_Machine Gun Soldier" and another called "###_Define Priorities_Rocket Soldier" with the sets named accordingly. Then, set tanks to have higher priorities than soldiers for the rocket guy, and vice versa for the Machine Gun guy... simple!

Now for the next script, a simple affair: (Action under Player/Build)

TYPE: [nsAD][ENH]
NAME: "###_Enable Building"
              
Code

*** IF ***
    True.
*** THEN ***
Player '<This Player>' is able to build units.
Player '<This Player>' is able to build buildings.


Add another script like this: (Action under Scripting/Flags)

TYPE: [nsAD][ENH]
NAME: "###_Set Flags Initial"
              
Code

*** IF ***
    True.
*** THEN ***
Set Flag named '###_INFANTRY BUILDING' to FALSE
Set Flag named '###_VEHICLE BUILDING' to FALSE
Set Flag named '###_I Am Crippled' to FALSE
Set Flag named '###_Enemy Crippled' to FALSE
Set Flag named '###_Enemy In My Base' to FALSE


This script defines a bunch of really important flags that the AI uses to define what's going on. (Refer to my other tutorial). The infantry and vehicle building ones are called when a team starts building to tell the AI that its factory is busy. The crippled one is called when the AI cannot win the game. Enemy crippled is to tell the Ai to finish off an opponent. Enemy in my base is... well... obvious.. :p

Finally, add: (Action under Scripting/Counters)

TYPE: [nsAD][ENH]
NAME: "###_Set Counters Initial"
              
Code

*** IF ***
    True.
*** THEN ***
Set '###_TL_Overall' to 0
Set '###_TLB_Tanks' to 0
Set '###_TLB_Troops' to 0
Set '###_TLC_Tanks' to 0
Set '###_TLC_Troops' to 0
Set '###_TLF_Tanks' to 0
Set '###_TLF_Troops' to 0


The names of these are short for "###_Teams Lost_Overall"... "###_Teams Lost_Centre_Tanks" etc... The main attack routes defined by waypoint paths are Centre (Spelt Center ingame due to silly American spelling :dry: ), Backdoor and Flank. These scripts set up counters that count how many teams that have been dispatched down these routes have died, and the overall number of teams lost. (Which is used back in our master counters! You'll see how everything links together in very complicated and subtle ways. This is what's so damn difficult about making an AI. There's no clear lines between parts, everything is linked together...)

Okay, we're done setting things up. Now we're gonna see what's going on in the world. Go to "###_World Status" and add this script: (Player/Destroyed for the condition and Scripting/Flags for the action)

TYPE: [nsAD][ENH]
NAME: "###_I Am Crippled"
              
Code

*** IF ***
    All factories belonging to Player '<This Player>' have been destroyed.
*** THEN ***
Set Flag named '###_I Am Crippled' to TRUE


This as you might guess, checks to see if the player can build anything. If it can't, it's fucked.

Next, add these scripts: (condition in Player/Area and actions in Scripting/Flags and Scripting/Script)

TYPE: [nsAD][ENH]
NAME: "###_Base Invaded False"
              
Code

*** IF ***
     Player '<This Player's Enemy>' has Less Than or Equal 2000 within area area '[Skirmish]MyOuterPerimeter'
*** THEN ***
Set Flag named '###_Enemy In My Base' to FALSE
Disable Script '###_Base Invaded False'.
Enable Script '###_Base Invaded True'.


and

TYPE: [nsAD][ENH]
NAME: "###_Base Invaded True"
              
Code

*** IF ***
     Player '<This Player's Enemy>' has Greater Than or Equal To 4000 within area area '[Skirmish]MyInnerPerimeter'
*** THEN ***
Set Flag named '###_Enemy In My Base' to TRUE
Disable Script '###_Base Invaded True'.
Enable Script '###_Base Invaded False'.


As you might guess, these two scripts work together like a switch, checking to see if the AI is in danger or not. The reason that the switch is split into two separate scripts rather than using the false action is that if the enemy sends units into the AI's base and the script is set to say the base is invaded with any value of units, a single rifleman could walk in who costs say 200 and cause the AI to gather it's army at it's base for defence. Even if base guards and defence could easily dispatch a single soldier. So, it only calls a state of emergency if there's a lot of stuff inside the base. Later we'll see some other scripts that reset this switch once the threat is removed.

Oh, for the love of god, click "OK" on the scripts window and save your map from the file menu. Clicking cancel removes any changes to scripts, and if you just close your map it WILL NOT PROMPT YOU TO SAVE if you have only made scripting changes.

Return to top