- Nibbits
- StarCraft 2
- Articles
- Guides
- Galaxy Scripting
- Writing your own StarCraft II AI
Writing your own StarCraft II AI
I recommend you use the stock Blizzard AI and not a custom one for this tutorial.
Basics
Galaxy is a spin-off of ANSI C. Any C/C++ programmers will feel at home. If you're not from a programming background, it's going to take you a while to get a hold of things. But basic build orders should be easily within your grasp.
A few things to remember:
- Variables must be defined at the top of functions
- "//" is the only acceptable comment syntax
- Standard C/C++ functions do not exist here!
Where To Start
You're going to want mpqeditor.
Download Link
This program will let you modify the internals of the AI. Once you've downloaded that, you want to open :
C:\Program Files (x86)\StarCraft II Beta\Mods\Liberty.SC2Mod\Base.sc2data
or (for 32-bit OS)
C:\Program Files\StarCraft II Beta\Mods\Liberty.SC2Mod\Base.sc2data
You should see something like this.
Then open the "TriggerLibs" folder. This is where most of the AI files are located. Important files in here are:
- RequirementsAI.galaxy"
This is a very important file, this contains all of the units/buildings/upgrades we can call using "AISetStock(int player, int count, string aliasType)" - "AI.galaxy"
This one contains all of the native functions we can use in our AI. - "MeleeAI.galaxy"
This one contains a lot of blizzard functions definitions. - "Terran0.galaxy"
This contains terran build orders - "Zerg0.galaxy"
This contains zerg build orders - "Protoss0.galaxy"
This contains protoss build orders
If you've downloaded a custom AI, the last three may not contain the builds orders, you'll have to look in the folders "Terran","Zerg","Protoss"
To modify a file, drag it out of MPQEditor. Make what modifications you want to make then save that file and drag it back into MPQEditor, you'll know you've done it correctly if it asks you to overwrite. Then save.
Advanced Modification
If you don't want to keep pulling files in and out of the MPQEditor. You can drag the "TriggerLibs" folder into your StarCraft II directory. Any modifications made to files in this folder will load up before Base.sc2data.
Basic Build Orders
At the very basic level, a lot of AI code is build orders. These are simple commands that tell the AI what to build and in what order. Most of the build orders are in files like Terran0.galaxy, Protoss0.galaxy and Zerg0.galaxy.
The original Blizzard AI function for a build order will look like this, this one is from Terran0.galaxy. (might look different in a custom AI).
void TerranOpenGnd0 (int player) {
AIClearStock(player);AISetStock( player, 1, c_TB_CommandCenter_Alias );
AISetStock( player, 8, c_TU_SCV );// around 100 resources in about 2 units
AISetStock( player, 2, c_TU_Marine );
TerranTechUp(player, 1);if (AIEnableVeryEasyStockOpen(player, c_TU_SCV)) {
return;
}// around 300 resources in about 3 unit
RandomInfantry(player);
}
(If you're working off StarCrack ai, they're going to be in "Zerg","Terran" and "Protoss" folders)
void AISetStock (int player, int count, string aliasType);
This is the main build order function. The best way to explain it is by example:
AISetStock(player, 5, c_ZU_Drone);
AISetStock(player, 10, c_ZU_Zergling);
This function will build 5 drones, once it's done it will build 10 zerglings. It's important to remember you need to build supply depots/overlords/pylons manually, otherwise the AI will just get stuck.
So, for example:
AISetStock( player, 7, c_TU_SCV );
AISetStock( player, 1, c_TB_Refinery);
AISetStock( player, 10, c_TU_SCV );
AISetStock( player, 1, c_TB_Barracks);
AISetStock( player, 11, c_TU_SCV );
AISetStock( player, 1, c_TB_BarracksReactor);
AISetStock( player, 1, c_TB_SupplyDepot );
AISetStock( player, 14, c_TU_SCV );
AISetStock( player, 2, c_TB_Barracks);
AISetStock( player, 4, c_TU_Marine );
This would be the start of a build order for a terran open. As you can see, we've set stock for "SupplyDepot" so the AI doesn't run out of supplies.
If you want to skip this, you can use economy functions, in StarCrack AI it's as simple as calling "AIManageSupply(player)". In the stock StarCraft AI you're going to need to use this function.
void AIDefaultEconomy (int player, string hall, string gas, string food, string peon, int cap, bool peonMode);
for example in a protoss build order you'd call this.
AIDefaultEconomy(player, c_PB_Nexus, c_PB_Assimilator, c_PB_Pylon, c_PU_Probe, 30, c_stockAlways);
This function won't only make sure you don't run out of supplies, it will also make sure all of your bases have gas extractors and try to get your peon count to the supplied number. (In this case it's 30, the protoss saturation number for a single base (24 minerals, 6 on gas)).
Cheating?
Blizzard has included functions that allow the AI to cheat. These are the two important ones:
AIHarvestBonus(player, 2.0);
AISetDifficulty(player, c_diffNormalVision, false);
AIHarvestBonus will multiply resources collected by the supplied amount. In this case it's two, so instead of each SCV collecting 5 minerals he'll collect 10. AISetDifficulty(player, c_diffNormalVision, false) this function will allow the AI to see the entire map. This is particularly important with countering.
These functions are used at the bottom of "MeleeAI.galaxy" in the stock Blizzard AI. But putting them anywhere with your own values should work.
Attacking
The stock Blizzard AI is programmed to attack at the end of every stage of the game. Open, Mid and Late. This is the function that causes this.
AIEnableVeryEasyStockOpen(player, c_TU_SCV);
This function will also cause the AI to change state at a pre-defined time. So he'll always attack and change state at the same time.
Now, to get him to attack when you want you can use this function.
(go here for a version without line numbers: Attack Function)
//------------------------------------------------------------
// AIAttackNow(int player, int size) by turdburgler
// Attacks with full force of main wave
//------------------------------------------------------------
void AIAttackNow(int player, int size)
{
wave atk = AIWaveGet(player, c_waveAttack);if (AIWaveState(atk) != c_waveStateRetreat)
{
if (AIWaveUnitCount(AIWaveGet(player, c_waveMain)) >= size)
{
DebugAIPlayerWave(player, "merge1 merge main -> attack");
AIWaveMerge(player, c_waveMain, c_waveAttack);
}
}atk = AIWaveGet(player, c_waveAttack);
if (AIWaveUnitCount(atk) >= size) {
AISetAttackState(player, e_attackState_Attack);
}
}
Don't worry about understanding this function too much, you just need to open up "MeleeAI.galaxy", put it at the end and save the file. Then you can, from now on, in your build orders use it.
Here's a full example of a Protoss open from StarCrack AI V 7.0. Note the use of AIAttackNow().
AIClearStock(player);AISetStock( player, 1, c_PB_Nexus );
AISetStock( player, 9, c_PU_Probe )
AISetStock( player, 1, c_PB_Pylon );
AISetStock( player, 11, c_PU_Probe );
AISetStock( player, 1, c_PB_Gateway );
AISetStock( player, 14, c_PU_Probe );
AISetStock( player, 2, c_PB_Gateway );
AISetStock( player, 16, c_PU_Probe );
AISetStock( player, 1, c_PU_Zealot );
AISetStock( player, 18, c_PU_Probe );
AISetStock( player, 2, c_PB_Pylon );
AISetStock( player, 20, c_PU_Probe );
AISetStock( player, 2, c_PU_Zealot );
AISetStock( player, 3, c_PB_Pylon );
AISetStock( player, 4, c_PU_Zealot );
AISetStock( player, 4, c_PB_Pylon );
AISetStock( player, 1, c_PB_Forge );
AISetStock( player, 7, c_PU_Zealot );
AISetStock( player, 5, c_PB_Pylon );
AISetStock( player, 14, c_PU_Zealot );
AISetStock( player, 8, c_PB_Pylon );
AISetStock( player, 17, c_PU_Zealot );AISetStockUnitNext( player, 1, c_PR_Shields1, c_stockAlways );
AISetStock( player, 1, c_PB_CyberneticsCore);AISetStock( player, 20, c_PU_Zealot );
AIAttackNow( player, 15 );
So, this AI will build two gateways then mass zealots, if it any time his main wave (the wave which ANY offensive units built end up in) reaches over 15 units he will attack as caused by AIAttackNow(player,15).
Countering
Countering is the new black. Every half decent AI is implementing countering in some form.
int AIKnownUnitCount (int player, int testPlayerId, string aliasUnitType);
This is the most important function for writing your own countering code. It returns the number of any unit (that's passed to it) that the AI knows about. For example, this is how i'd work out how many zerglings player 2 has.
int lingcount = AIKnownUnitCount(player, 2, c_ZU_Zergling);
Now, that's not very useful by itself. How do we know if player 2 is our ally or enemy? We could be wasting time countering units that our ally has. Unfortunetly, the ally hack means that we can't use the blizz functions to work out if a player is allied. But, it's not that hard to hack yourself. In StarCrack V 7.0, I know that team members share vision so to check teams, I run one check at the start if we can see our allies HQ.
Ok, so now we know who's got what. We can counter, a good place to look at good counters is in-game in the help menu. Here's an example of basic countering code.
int lingcount = AIKnownUnitCount(player, 2, c_ZU_Zergling);if(lingcount > 15)
{
AISetStock(player, 8, c_TU_Hellion);
}
Now, I know that's only going to work for terran, but it's just an example of a simple way to implement countering. You'd want to have each counter race specific.
Links
StarCrack AI
MPQEditor
Galaxy Reference
Summary
You should now have a half decent idea of how to write your own StarCraft II AI. From here, the best way to learn is to download AIs and pick them apart and take a look at what makes them tick. If you've got any comments, post them on this site (nibbits) and I'll be happy to answer.
If you have any ideas for a follow up article post them too!
Meta
- Author:
- Turdburgler 4
- Views (Total):
- 41,659
- Views (Daily):
- 7
- Posted On:
- March 20, 2010
Rating
- Opinion:
7 votes considered -
- Good
Good
Your Rating
Do you like this article? Rate it to help fellow players find what they're looking for.
If you were logged in you could rate this.
User Comments
Support Nibbits by linking to us:
Hello. Your article is useful for many people. That is the information that I need. Thank you! a10
14.160.27.xxx
This is a fine tutorial it is just missing a pretty key thing.
If you actually completed your own AI how would you go about playing against it in game. An actual AI not editing the terran0 very easy computer ai
24.2.59.xxx
Very kewl Article *****
Guys just musn't get too excited, even the most basic coders can write this so let's not go calling ourselves AI Coders, the AI is already written.
You're just directing the movie!
41.243.73.xxx
I just have the beta and not the starcrack version so I'm not sure if this tutorial can help me. I tried copying the triggers in both places you mentioned but the ai builds exactly the same no matter what. Later I found something: Apparently the map itself can be treated as an mpq if the extension is changed from SC2map to S2Ma and I found a map where someone added AI to the triggerlib within the map.
(Trigger Variables)
Where I can find lexique of script supported?
How much can you control with these AI files? Only what the AI has to build and when to attack?
Because I would like an AI that scans a base for weaknesses in the defenses and attack from that direction, not the always-so-predictable direct line assault.
That and more...
95.36.45.xxx
how to cheating harvest bonus and map hack please explain easier please
58.9.137.xxx
Awesome! I must start to practice my C+ again. stoked to start making mods for this!
I will note that the poster of this article is the main author of StarCrack's AI, and a real POS to admire, above and beyond the rank of Mr. Hanky.
5 stars.
Interesting, thanks for the post. I will try my own hand at some AI coding.