DarkBlizz

Game On => Land of AI => STARCRAFT II: WINGS OF LIBERTY => AI Development => Topic started by: Aeg1s on March 09, 2010, 12:32:46 AM

Title: Improved combat AI
Post by: Aeg1s on March 09, 2010, 12:32:46 AM
I've been spending a lot of time lately on improving the games ridiculous combat AI and have come up with the following that I think a lot of people would be interested in so I'm posting it here. Any suggestions and feedback would be appreciated, thanks.  :)


Features:
-Several new attack states to provide a wider range of tactical options to the AI.
-Added a function to set the town gather location (for example to the Natural so the army will gather outside there instead of inside your main)
-Tweaked some values in the attack handling to hopefully provide better engagement/retreat logic
-Raised the retreat threshold so the AI will not abandon attacked towns so quickly and easily.
-The AI will now try and regroup instead of retreating all the way back to its main base.
-The AI will turn around and fire on pursuing units while its retreating if it has a distinct advantage (will revert to retreat when odds drop).




Usage:
Here's the current source for the new and changed code:
http://pastebin.com/nwgRtS1c (http://pastebin.com/nwgRtS1c)


If you want to use this copy the constants and town gather functions to the top of MeleeAI.galaxy; and replace the AttackStateName, AIDefendTown, and AIWaveAttack functions.


Or, if you haven't changed MeleeAI or just want a .sc2data version here's the mpq with just a changed MeleeAI.galaxy:
http://dl.dropbox.com/u/5031322/CombatMod/Base.SC2Data (http://dl.dropbox.com/u/5031322/CombatMod/Base.SC2Data)


New States:
-Pressure: similar to attack but with a lower threshold for retreating
-Commit: commit to a fight with no chance of retreat (don't set this manually, it is used when the AI is close in strength to the enemy and retreating would most likely result in many losses).
-Defend: Stay back and defend the main base
-Regroup: Retreat for a little ways until out of combat; then regroup, wait for reinforcements and try to move in again (used instead of retreat in most instances).
-Scared_Snipe/Regroup_Snipe: if retreating and spotting a target of opportunity (like lead elements of a pursuit) stop and engage while we have a distinct advantage.


Todo:
-Fix drop attacks
-Fix retreating through the enemy
-Add multiple attack waves (harassing expos with a small force while your main army is engaged)
-Improve idle state logic to improve attack decisisons
Title: Re: Improved combat AI
Post by: Aeg1s on March 09, 2010, 12:36:06 AM

Ability Improvements:
Guardian Shield
function for the Sentry:
http://pastebin.com/dEJeJLG0 (http://pastebin.com/dEJeJLG0)
(As of right now the sentry will default to using the Guardian Shield. Also, all sentries with enough energy in a group will use it as soon as possible; I intend to fix this soon.


include and add the following to the begging of AIThinkDisruptor in TactProtAI.galaxy:


    if (GuardianShield(player, aiUnit, scanGroup)) {
        return;
    }



Todo:
-Command Centers lift off when under attack.
Title: Re: Improved combat AI
Post by: hd on March 09, 2010, 12:51:59 AM
i've almost completely finished my early game attack rush logic and afterwords am going to work on harassment logic. i think getting at least the early and mid game attack logic should be our first priority.

i also have a few ideas for build logic once i get a usable early/mid attack logic. I plan on making a few posts with code / details once its a little bit more polished. I am curious how you set the gather location and I assume it can be adjusted on the fly...
Title: Re: Improved combat AI
Post by: hd on March 09, 2010, 02:19:06 AM
Quote from: Aeg1s on March 09, 2010, 12:36:06 AM

Ability Improvements:
Guardian Shield
function for the Sentry:
http://pastebin.com/dEJeJLG0 (http://pastebin.com/dEJeJLG0)
(As of right now the sentry will default to using the Guardian Shield. Also, all sentries with enough energy in a group will use it as soon as possible; I intend to fix this soon.


include and add the following to the begging of AIThinkDisruptor in TactProtAI.galaxy:


    if (GuardianShield(player, aiUnit, scanGroup)) {
        return;
    }



Todo:
-Command Centers lift off when under attack.

As for the cc lifting, one thing you should keep in mind is to do a sweep around the command center for vikings, phoenix and whatever teh zerg one is called

you need to do a risk reward analysis for lifting the cc, in some situations it might be more beneficial to the ai to keep it on the ground rather than lift off.
Title: Re: Improved combat AI
Post by: Kernel64 on March 09, 2010, 05:29:41 AM
Awesome, hd! I'll focus on my stuff, and contribute everything to you guys. This is great progress.
Title: Re: Improved combat AI
Post by: Aeg1s on March 09, 2010, 03:42:17 PM
Quote from: hd on March 09, 2010, 12:51:59 AM
I am curious how you set the gather location and I assume it can be adjusted on the fly...


I just made a function to set which town the attack waves gather at (it was using c_townMain). So once your nat goes up you can just call it and set it to the natural and they'll start gathering outside of it.
Title: Re: Improved combat AI
Post by: Doix on March 09, 2010, 03:56:29 PM
Hi Aeg1s. Nice work on changing the AI stuff. Do you have a reason to use an array instead of AISetUserInt/GetUserInt?


const int c_townGather = 109;

int GetTownGather(int player) {
    AIGetUserInt(player,c_townGather);
}

void SetTownGather(int player, int town) {
    AISetUserInt(player,c_townGather,town);
}


Don't you think that is better? This way it'd work for an unlimited number of players + you're not allocating space in an array which doesn't get used (assuming there are less than 8 players).

Sorry, if it looks like I'm trying to convince you :p, had this discussion with Sylvex and he really doesn't like AISetUserInt and AIGetUserInt for a reason which is beyond my comprehension.
Title: Re: Improved combat AI
Post by: hd on March 09, 2010, 04:44:54 PM
Quote from: Aeg1s on March 09, 2010, 03:42:17 PM
Quote from: hd on March 09, 2010, 12:51:59 AM
I am curious how you set the gather location and I assume it can be adjusted on the fly...


I just made a function to set which town the attack waves gather at (it was using c_townMain). So once your nat goes up you can just call it and set it to the natural and they'll start gathering outside of it.

I wonder, can we set a location like UnitGetPosition(UnitGroupUnit(AIWaveGetUnits(c_waveAttack), RandomInt(1, AIWaveUnitCount(c_waveAttack)))) and modify it to be a little ways back towards their main base so we can set a rally location not too far from where they last fought if an attack was successful.

For example...

point hdGetOffensiveGatherLocation(int player, wave w)
{
    point pHome = AIGetTownLocation(player, c_townMain);
    point pWave = UnitGetPosition(UnitGroupUnit(AIWaveGetUnits(w), RandomInt(1, AIWaveUnitCount(w))));
    point pTest = PointAlongLine(pHome, pWave, DistanceBetweenPoints(pHome, pWave) * 0.9);
   
    // hd: return 90% of the distance between where the wave is and where the wave is from but make sure it's pathable.
    if (AIFilterPathable(AIWaveGetUnits(w), pTest))
    {
        return pTest;
    }
   
    // hd: otherwise, go recursive subtracting some distance until we find a pathable spot
    // TODO add recursive check
}
Title: Re: Improved combat AI
Post by: Aeg1s on March 09, 2010, 05:06:36 PM
Quote from: hd on March 09, 2010, 04:44:54 PM
I wonder, can we set a location like UnitGetPosition(UnitGroupUnit(AIWaveGetUnits(c_waveAttack), RandomInt(1, AIWaveUnitCount(c_waveAttack)))) and modify it to be a little ways back towards their main base so we can set a rally location not too far from where they last fought if an attack was successful.


Yeah, that should be possible; I'll look into it; access to a point's data would help a lot. I've also been messing around with getting a contain state working that'll sit outside an opponent's base.
Title: Re: Improved combat AI
Post by: Astazha on March 10, 2010, 09:10:24 PM
I'm extremely interested in this.  I just got an MPQ editor and started poking around the day before yesterday so it will take me some time to get up to speed, but I'm envisioning a modular AI with multiple states to track, and a priority based system of control.


The key part is to make it modular in such a way that multiple people can work on it.


I'd also like to deal with the unknown.  The priority of scouting changes dramatically if you haven't seen your opponent's army in the last 10 minutes, or if it's been that long since you've verified what expansions they have. 


Assumptions can also be made about what the player is building based on how far into the game we are, what the race is, and what units have been seen (particularly recently.)  There might also be some anticipatory functions.  If I just exposed my Brood Lords to my opponent for the first time then I expect an uptake in anti-air.  Doubly so if they wiped out his expansion.


Over time the behavior can be tuned by adjusting constants and multipliers.  We'll also be able to set different versions of play just by tweaking values for Aggressiveness or Defensiveness, and to change those values based on what happens in game.


Initially in creating the framework we can make dummy function that always return "yes, you should be scouting now." or return a random build order.  Once the structure is in place we can begin to refine the individual components.


I don't have anything concrete right now, but this is the direction I'm thinking in.
Title: Re: Improved combat AI
Post by: hd on March 10, 2010, 09:32:05 PM
Quote from: Astazha on March 10, 2010, 09:10:24 PM
I'm extremely interested in this.  I just got an MPQ editor and started poking around the day before yesterday so it will take me some time to get up to speed, but I'm envisioning a modular AI with multiple states to track, and a priority based system of control.


The key part is to make it modular in such a way that multiple people can work on it.


I'd also like to deal with the unknown.  The priority of scouting changes dramatically if you haven't seen your opponent's army in the last 10 minutes, or if it's been that long since you've verified what expansions they have. 


Assumptions can also be made about what the player is building based on how far into the game we are, what the race is, and what units have been seen (particularly recently.)  There might also be some anticipatory functions.  If I just exposed my Brood Lords to my opponent for the first time then I expect an uptake in anti-air.  Doubly so if they wiped out his expansion.


Over time the behavior can be tuned by adjusting constants and multipliers.  We'll also be able to set different versions of play just by tweaking values for Aggressiveness or Defensiveness, and to change those values based on what happens in game.


Initially in creating the framework we can make dummy function that always return "yes, you should be scouting now." or return a random build order.  Once the structure is in place we can begin to refine the individual components.


I don't have anything concrete right now, but this is the direction I'm thinking in.

By turning e_flagsScouting, or something along those lines, on and off, it will scout or stop scouting.

Personally, I think the top priority is attack logic, then build logic. Responding to what the opponent does should be last. I assure you, with good attack logic and build logic, the AI will be pretty tough while response logic alone won't really do much with out giving the AI extra resources to pump massive units.
Title: Re: Improved combat AI
Post by: Astazha on March 10, 2010, 11:17:44 PM
From what I've seen of the scouting AI so far, it's pretty weak.  I've been playing with that flag today, trying to get the AI to even scout all expansion locations with multiple scouts and I haven't been able to do it, even when it can operate largely unopposed.


I agree with the priorities, I just think that in the longer term the AI will need a framework to become really good.  The beauty of modularity is that it allows the contributors to focus on what interests them.


The reason I'm interested in scouting is because it relates to the attack logic.  Not just from a unit counter standpoint, which is complicated, but because the AI needs to be taking out expansions.  The current Starcrack AI often doesn't even know that I have expansions unless it stumbles into them accidentally.  Especially on maps with hidden island expansions, you can just set up camp there and be left alone more or less indefinitely, even if all of your ground accessible bases have been destroyed.  I'd like to teach the AI to exhibit better map control.
Title: Re: Improved combat AI
Post by: hd on March 10, 2010, 11:28:38 PM
Quote from: Astazha on March 10, 2010, 11:17:44 PM
From what I've seen of the scouting AI so far, it's pretty weak.  I've been playing with that flag today, trying to get the AI to even scout all expansion locations with multiple scouts and I haven't been able to do it, even when it can operate largely unopposed.


I agree with the priorities, I just think that in the longer term the AI will need a framework to become really good.  The beauty of modularity is that it allows the contributors to focus on what interests them.


The reason I'm interested in scouting is because it relates to the attack logic.  Not just from a unit counter standpoint, which is complicated, but because the AI needs to be taking out expansions.  The current Starcrack AI often doesn't even know that I have expansions unless it stumbles into them accidentally.  Especially on maps with hidden island expansions, you can just set up camp there and be left alone more or less indefinitely, even if all of your ground accessible bases have been destroyed.  I'd like to teach the AI to exhibit better map control.

I don't think that it's that the AI doesn't know about the expansion but rather it's not told to attack it.
Title: Re: Improved combat AI
Post by: Astazha on March 11, 2010, 08:00:05 AM
I'm still new at all this as I said before, but when I watch the replays in question and select the AI's point of view it has no vision of the expansion, no buildings showing on the mini-map.  Without the AI cheating I would assume that means it's unaware of the presence. 



Title: Re: Improved combat AI
Post by: Kernel64 on March 12, 2010, 04:38:43 PM
Do you guys know how to make multiple waves? Like, two main attack waves, one for main attack and the other for back door drops?

Or is this even possible?

How do we control attack waves?
Title: Re: Improved combat AI
Post by: hd on March 12, 2010, 09:29:49 PM
Quote from: Kernel64 on March 12, 2010, 04:38:43 PM
Do you guys know how to make multiple waves? Like, two main attack waves, one for main attack and the other for back door drops?

Or is this even possible?

How do we control attack waves?

waveDivert1 and waveDivert2 are already in the game for harassing / drop attacks.
Title: Re: Improved combat AI
Post by: Aeg1s on March 13, 2010, 02:36:47 AM
Quote from: Kernel64 on March 12, 2010, 04:38:43 PM
Do you guys know how to make multiple waves? Like, two main attack waves, one for main attack and the other for back door drops?

Or is this even possible?

How do we control attack waves?


Yeah that should be easy; the attack waves are usually controlled by setting the AI attack state.
Title: Re: Improved combat AI
Post by: Kernel64 on March 13, 2010, 08:57:27 AM
Okay, thanks guys.
Title: Re: Improved combat AI
Post by: Aeg1s on March 14, 2010, 04:31:11 PM
As an update I've decided to hard code a graph of points of interest on the map (right now just Lost Temple but it should be easy to determine the map based on starting positions) to help create a much improved tactical AI. As a start I'm rewriting the scouting routines.


Here's the graph I'm using for Lost Temple:


(http://i40.tinypic.com/2vuc0au.jpg)


Connections have a type (blue lines are air only, orange cliffs, and black normal).
Title: Re: Improved combat AI
Post by: Astazha on March 16, 2010, 04:23:20 AM
Quote from: Doix on March 09, 2010, 03:56:29 PM
Hi Aeg1s. Nice work on changing the AI stuff. Do you have a reason to use an array instead of AISetUserInt/GetUserInt?


const int c_townGather = 109;

int GetTownGather(int player) {
    AIGetUserInt(player,c_townGather);
}

void SetTownGather(int player, int town) {
    AISetUserInt(player,c_townGather,town);
}


Don't you think that is better? This way it'd work for an unlimited number of players + you're not allocating space in an array which doesn't get used (assuming there are less than 8 players).

Sorry, if it looks like I'm trying to convince you :p, had this discussion with Sylvex and he really doesn't like AISetUserInt and AIGetUserInt for a reason which is beyond my comprehension.


I have a question about this.  Why 109?  The only documentation I can find on the UserInt functions is:

const int c_playerPropMinerals              = 0;
const int c_playerPropVespene               = 1;
const int c_playerPropSuppliesUsed          = 4;
const int c_playerPropSuppliesMade          = 5;


Is 109 an arbitrary user-defined spot in that player array?  How big is it? 


If they are user-defined, should we create a thread documenting which slots are being used and by what scripts for what purpose so that conflicts can be minimized?
Title: Re: Improved combat AI
Post by: Aeg1s on March 16, 2010, 09:37:14 AM
Quote from: Astazha on March 16, 2010, 04:23:20 AM
I have a question about this.  Why 109?  The only documentation I can find on the UserInt functions is:

const int c_playerPropMinerals              = 0;
const int c_playerPropVespene               = 1;
const int c_playerPropSuppliesUsed          = 4;
const int c_playerPropSuppliesMade          = 5;


Is 109 an arbitrary user-defined spot in that player array?  How big is it? 


If they are user-defined, should we create a thread documenting which slots are being used and by what scripts for what purpose so that conflicts can be minimized?


The player prop constants aren't used for Get/SetUserInt; I think blizzard's functions are using 1-10 (I remember seeing this somewhere). 109 is just an arbitrary index in the array; I'm not sure how large of an index we can use but so far I've been using indices below 256.
Title: Re: Improved combat AI
Post by: Astazha on March 17, 2010, 12:12:11 PM
Do you know where the player prop constants are used?  I'd like to directly read mineral/gas instead of using AIHasRes()
Title: Re: Improved combat AI
Post by: Doix on March 17, 2010, 01:37:03 PM
PlayerGetPropertyInt(player, c_playerPropMinerals);
Title: Re: Improved combat AI
Post by: Astazha on March 17, 2010, 03:34:42 PM
Thank you Doix.




256 is the maximum possible index for the UserInt() functions.  Accessing anything above that returns 0.