Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - Kernel64

#106
AI Development / Re: Improved combat AI
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?
#107
That's very interesting! Can you explain more on creating triggers, what triggers are?
#108
The functions are still for testing. What they do is modularize blocks of lines that tell the engine to do something.

I use AISetStock in the past, and have conditions when these stocks fire in order to have a precise order of training and building. This one makes the setting of conditions easier, and allows me to make blocks of sets of orders (e.g. AISetStock() or AITrain/AIBuild) accessible depending on certain conditions.

For example:

this block:
Quote
        if (RCountUnit(c_ZU_Drone, 9, 10, 0, 1, 0, 1, player) == true) {
            ZEnsureFood(18, 9, c_townOne, player);
            ZEnsureWorker(13, 10, c_townOne, player);
            ZEnsureTech(1, c_ZB_SpawningPool, 10, c_townOne, c_nearCloseDropoff, player);
        }

which trains +3 drones, one pool, and +1 overlord can be replaced with:

Quote
   if (RCountUnit(c_ZU_Drone, 9, 10, 0, 1, 0, 1, player) == true) {
            ZEnsureFood(18, 9, c_townOne, player);
            ZEnsureTech(1, c_ZB_SpawningPool, 10, c_townOne, c_nearCloseDropoff, player);
        if (RCountUnit(c_ZB_SpawningPool, 0, 1, 1, 1, 0, 0, player) == true) {
            ZEnsureWorker(13, 3, c_townOne, player);
        }
   }

Which builds a pool first before the +3drones.

Now, Imagine adding another condition. Say, && (AIPersonality(100,150) == true),
where bool AIPersonality(int AggMin, intAggMax); is a function that returns true if the AI's personality, after randomization is within that range.

This way, I can have multiple blocks of orders and have the AI do them within the parameters specified by the given functions, depending on the changes of its personality or any other condition we might think necessary later. Like, say, ((AIStateNow(player) == "PrepareDefense") == true), where a block of orders to train certain units will then fire.

That block of code can then clear the current queue and insert these items, etc.

Edit:

How AITrain and AIBuild works is add them to some queue, and the engine will buy the one that is most available.

Say, if it had a queue:
1 pool
4 Drones
2 ovie

it will morph drones first because they are cheaper, then ovies, then the pool.

I've also noticed this happen in AISetStock() where if you set pool first, then drone, drones still get morphed first. This is why having conditions are better for me, since each build order yields different results.

I'll post the BOs later for Zerg, and with corresponding effects and drawbacks.
#109
The problem with the default Queen is that if you have multiple queens, they are bunched together at the main. And if you have >10 drones anywhere, even if say your expo has only 3 drones, it will not cast spawn larva.

This one fixes that, so you can train Queens at expos or other bases, and have that queen spawn larva and only keep count of the larva in front of her. Also, this allows your Queens to stay where they're trained from unless grabbed and given an order somewhere else.

at TactZergAI.galaxy replace the respective code with this:

Quote
order SpawnLarva (int player, unit aiUnit) {
    order ord;
    unitgroup hatcheries;
    unitgroup larvas;
    int larvaCount;

    //  Only cast if idle.
    //
    if (UnitOrder(aiUnit, 0) != null) {
        return null;
    }

    ord = AICreateOrder(player, c_AB_SpawnMutantLarva, 0);
    if (!UnitOrderIsValid(aiUnit, ord)) {
        return null;
    }

    larvas = AIFindUnits(player,
                             c_ZU_Larva,
                             UnitGetPosition(aiUnit),
                             15,
                             c_noMaxCount)
                             ;
    //  Don't cast if we already own at least 10 larva
    //
    larvaCount = UnitGroupCount(larvas, c_unitCountAll);
        //TechTreeBehaviorCount(player, c_BF_MutantLarvaTimer, c_techCountQueuedOrBetter) * 4
      //+ TechTreeUnitCount(player, c_ZU_Larva, c_techCountQueuedOrBetter)
    //;
    if (larvaCount >= 10) {
        return null;
    }

    hatcheries = AIFindUnits(player,
                             c_ZB_Hatchery_Alias,
                             UnitGetPosition(aiUnit),
                             15,
                             c_noMaxCount)
                             ;
    return AIUnitGroupGetValidOrder(hatcheries, ord, aiUnit, c_backwards);
}

This will make the engine scan larva count local to where the Queen was trained. Remember to train Queen at specific town since our next code prevents the grouping and taking home of all queens:

At Zerg.galaxy, find the function "void AINewUnitZerg (int player, unit u)"
and comment out the line which adds queens into a wave.

it should say something like:
Quote
    if (type == c_ZU_Queen) {
        //AIWaveAddUnitPriority(AIWaveGet(player, c_waveHome), u, c_prioWavePeon);c_prioWaveIdle doesn't work
        return;
    }

Perhaps through here we can code so that ovies are not automatically added as scouts, but positioned somewhere at edges of creep. Then we can add a Think for the overlord and give it an order to drop creep.

edit: It would be nice to have the limit of counting of larva multiplied by the number of hateries/lair/hive within range of the queen. This way, one queen can cast spawn larva on two hatcheries. Coding where to cast the order depending on the number of larva of that specific grabbed hatchery would be the awesome.
#110
I've been trying these recently:

Declarations:
Quote
bool CountUnit(string UCheck, int Complete, int Progressing, int Queued, int Tplayer);
bool RCountUnit(string UCheck, int MinComplete, int MaxComplete, int MinProgressing, int MaxProgressing, int MinQueued, int MaxQueued, int Tplayer);
void FCountUnit(string UCheck, int MinComplete, int MaxComplete, int MinProgressing, int MaxProgressing, int MinQueued, int MaxQueued, bool CFeedback, bool PFeedback, bool QFeedback, int Tplayer);
int TotalUnit(string UCheck, int Tplayer);
void ZEnsureFood(int FoodLvL, int TPriority, int TownWhere, int Tplayer);
void ZEnsureWorker(int UCount, int TPriority, int TownWhere, int Tplayer); //, string PreConUnit, int PreConCount);
void ZEnsureTech(int UCount, string UTech, int TPriority, int TownWhere, int BFlag, int Tplayer);
void ZEnsureUnit(int UCount, string UTech, int TPriority, int TownWhere, int Tplayer);

string WeAreThrough(int Tplayer, string ThroughState);
string WeAreAt(int Tplayer);

The Functions Themselves:
Quote
//--------------------------------------------------------------------------------------------------
//  Checks and returns true if it is so. Within range this time.
//--------------------------------------------------------------------------------------------------
bool RCountUnit(string UCheck, int MinComplete, int MaxComplete, int MinProgressing, int MaxProgressing, int MinQueued, int MaxQueued, int Tplayer)
{
    if(  (AITechCount(Tplayer, UCheck, c_techCountCompleteOnly) >= MinComplete) &&
          (AITechCount(Tplayer, UCheck, c_techCountCompleteOnly) <= MaxComplete)  &&
         (AITechCount(Tplayer, UCheck, c_techCountInProgressOnly) >= MinProgressing) &&
          (AITechCount(Tplayer, UCheck, c_techCountInProgressOnly) <= MaxProgressing)  &&
         (AITechCount(Tplayer, UCheck, c_techCountQueuedOnly) >= MinQueued) &&
          (AITechCount(Tplayer, UCheck, c_techCountQueuedOnly) <= MaxQueued) ){
        return true;   
    }
    else { return false; }
}

//--------------------------------------------------------------------------------------------------
//  Checks and returns true if it is so. Range Specific bool setting.
//--------------------------------------------------------------------------------------------------
void FCountUnit(string UCheck, int MinComplete, int MaxComplete, int MinProgressing, int MaxProgressing, int MinQueued, int MaxQueued, bool CFeedback, bool PFeedback, bool QFeedback, int Tplayer)
{
    if( (AITechCount(Tplayer, UCheck, c_techCountCompleteOnly) >= MinComplete) &&
        (AITechCount(Tplayer, UCheck, c_techCountCompleteOnly) <= MaxComplete) ){
        CFeedback = true;
    }
    else { CFeedback = false; }

    if( (AITechCount(Tplayer, UCheck, c_techCountInProgressOnly) >= MinProgressing) &&
        (AITechCount(Tplayer, UCheck, c_techCountInProgressOnly) <= MaxProgressing) ){
        PFeedback = true;
    }
    else { PFeedback = false; }
    if( (AITechCount(Tplayer, UCheck, c_techCountQueuedOnly) >= MinQueued) &&
        (AITechCount(Tplayer, UCheck, c_techCountQueuedOnly) <= MaxQueued) ){
        QFeedback = true;
    }
    else { QFeedback = false; }   
}

//--------------------------------------------------------------------------------------------------
//  Counts the specified unit all including in progress and queued
//--------------------------------------------------------------------------------------------------
int TotalUnit(string UCheck, int Tplayer){
    int a = 0;
    a = (AITechCount(Tplayer, UCheck, c_techCountInProgressOnly) +
                AITechCount(Tplayer, UCheck, c_techCountQueuedOnly) +
                AITechCount(Tplayer, UCheck, c_techCountCompleteOnly));
    return a;
}

//--------------------------------------------------------------------------------------------------
//  Checks the total number of food if low, add one Ovie
//--------------------------------------------------------------------------------------------------
void ZEnsureFood(int FoodLvL, int TPriority, int TownWhere, int Tplayer){
int TotalFood = 0;

    TotalFood = (( AITechCount(Tplayer, c_ZU_Overlord, c_techCountInProgressOnly) +
                AITechCount(Tplayer, c_ZU_Overlord, c_techCountQueuedOnly) +
                AITechCount(Tplayer, c_ZU_Overlord, c_techCountCompleteOnly) ) * 8 );
    // adds hatchery count
    TotalFood = TotalFood + (( AITechCount(Tplayer, c_ZB_Hatchery, c_techCountInProgressOnly) +
                AITechCount(Tplayer, c_ZB_Hatchery, c_techCountQueuedOnly) +
                AITechCount(Tplayer, c_ZB_Hatchery, c_techCountCompleteOnly) ) * 2);
    // add lair count
    TotalFood = TotalFood + (( AITechCount(Tplayer, c_ZB_Lair, c_techCountInProgressOnly) +
                AITechCount(Tplayer, c_ZB_Lair, c_techCountQueuedOnly) +
                AITechCount(Tplayer, c_ZB_Lair, c_techCountCompleteOnly) ) * 2);
    // add hive count
    TotalFood = TotalFood + (( AITechCount(Tplayer, c_ZB_Hive, c_techCountInProgressOnly) +
                AITechCount(Tplayer, c_ZB_Hive, c_techCountQueuedOnly) +
                AITechCount(Tplayer, c_ZB_Hive, c_techCountCompleteOnly) ) * 2);
    // add overseers
    TotalFood = TotalFood + (( AITechCount(Tplayer, c_ZU_Overseer, c_techCountInProgressOnly) +
                AITechCount(Tplayer, c_ZU_Overseer, c_techCountQueuedOnly) +
                AITechCount(Tplayer, c_ZU_Overseer, c_techCountCompleteOnly) ) * 8 );               

    if ( TotalFood < FoodLvL ){
        AITrain (Tplayer, TPriority, TownWhere, c_ZU_Overlord, 1);
    }
}

//--------------------------------------------------------------------------------------------------
//  Checks the total number of worker and trains one if less
//--------------------------------------------------------------------------------------------------
void ZEnsureWorker(int UCount, int TPriority, int TownWhere, int Tplayer){ //, string PreConUnit, int PreConCount){
int TotalWorker = 0;

    TotalWorker = ( AITechCount(Tplayer, c_ZU_Drone, c_techCountInProgressOnly) +
                AITechCount(Tplayer, c_ZU_Drone, c_techCountQueuedOnly) +
                AITechCount(Tplayer, c_ZU_Drone, c_techCountCompleteOnly) );
   
// blocked, since even if AI queues pool first, it morphs drones. It must be: cheaper goes first
//    if (PreConUnit != "None") {
//        if ( ( TotalWorker < UCount ) && (TotalUnit(PreConUnit, Tplayer)==PreConCount) ){
//            AITrain (Tplayer, TPriority, TownWhere, c_ZU_Drone, 1);
//        }
//    }
//    else {
        if ( TotalWorker < UCount ) {
            AITrain (Tplayer, TPriority, TownWhere, c_ZU_Drone, 1);
        }
//    }
}

//--------------------------------------------------------------------------------------------------
//  Checks the total number of a certain tech and build 1 of it if low
//--------------------------------------------------------------------------------------------------
void ZEnsureTech(int UCount, string UTech, int TPriority, int TownWhere, int BFlag, int Tplayer){
int TotalTech = 0;

    TotalTech = ( AITechCount(Tplayer, UTech, c_techCountInProgressOnly) +
                AITechCount(Tplayer, UTech, c_techCountQueuedOnly) +
                AITechCount(Tplayer, UTech, c_techCountCompleteOnly) );
   
    if ( TotalTech < UCount ){
        AIBuild (Tplayer, TPriority, TownWhere, UTech, 1, BFlag);
    }
}

void ZEnsureUnit(int UCount, string UTech, int TPriority, int TownWhere, int Tplayer){
int TotalTech = 0;

    TotalTech = ( AITechCount(Tplayer, UTech, c_techCountInProgressOnly) +
                AITechCount(Tplayer, UTech, c_techCountQueuedOnly) +
                AITechCount(Tplayer, UTech, c_techCountCompleteOnly) );
   
    if ( TotalTech < UCount ){
        AITrain (Tplayer, TPriority, TownWhere, UTech, UCount);
    }
}

//---returns strings that describe states
string WeAreThrough(int Tplayer, string ThroughState){
   
    if( ThroughState == "GameStart") {
        if( (TotalUnit(c_ZB_Hatchery, Tplayer) == 1) &&
            ((TotalUnit(c_ZU_Overlord, Tplayer) >= 1) && (TotalUnit(c_ZU_Overlord, Tplayer) <= 2)) &&
            ((TotalUnit(c_ZU_Drone, Tplayer) >= 10) && (TotalUnit(c_ZU_Drone, Tplayer) <= 13)) &&
            (TotalUnit(c_ZB_SpawningPool, Tplayer) < 1) ) {
       
            return "DoneGameStart";
        }
        else {
            return "NotDoneGameStart";
        }
    }
   
    else if( ThroughState == "Block1") {
        if( (TotalUnit(c_ZB_Hatchery, Tplayer) == 1) &&
            ((TotalUnit(c_ZU_Overlord, Tplayer) >= 2) && (TotalUnit(c_ZU_Overlord, Tplayer) <= 3)) &&
            ((TotalUnit(c_ZU_Drone, Tplayer) >= 13) && (TotalUnit(c_ZU_Drone, Tplayer) <= 16)) &&
            (TotalUnit(c_ZB_SpawningPool, Tplayer) == 1) ) {
       
            return "DoneBlock1";
        }
        else {
            return "NotDoneBlock1";
        }
    }
    else {
        return "Error";
    }
}

//---returns strings that describe states
string WeAreAt(int Tplayer){
    if( (TotalUnit(c_ZB_Hatchery, Tplayer) == 1) &&
        (TotalUnit(c_ZU_Overlord, Tplayer) <= 1) &&
        (TotalUnit(c_ZU_Drone, Tplayer) <= 10) &&
        (TotalUnit(c_ZB_SpawningPool, Tplayer) < 1) ) {

        return "GameStart";
    }
    if( (TotalUnit(c_ZB_Hatchery, Tplayer) == 1) &&
        (TotalUnit(c_ZU_Overlord, Tplayer) == 2) &&
        (TotalUnit(c_ZU_Drone, Tplayer) == 13) &&
        (TotalUnit(c_ZB_SpawningPool, Tplayer) == 1) ) {

        return "Block1";
    }
    else {
        return "NoWhere";
    }
}

You can notice there two functions that returns strings, which is handy for having the AI stack blocks of actions. This is still very new to me, and I'm also trying to figure out a way to use Train and build with priority but without such things as this:

Quote
AISetDifficulty(player, c_diffNormalVision, false);

AIClearStock(player);

//this makes AI automate resourcing like gas structs
AIDefaultEconomy(player, c_ZB_Hatchery_Alias, null, c_ZU_Overlord_Alias, c_ZU_Drone, 45, c_stockIdle);

        //debug WeAreAt-------------------------------------------------
        UIDisplayMessage(PlayerGroupAll(), 1, StringToText(WeAreAt(player)));
        //queue debug:--------------------------------------------------
        IQU = AITechCount(player, c_ZU_Drone, c_techCountQueuedOnly);
        SQU = IntToString(IQU);
        UIDisplayMessage(PlayerGroupAll(), 3, StringToText(SQU  + " Drones"));
        IQU = AITechCount(player, c_ZB_SpawningPool, c_techCountQueuedOnly);
        SQU = IntToString(IQU);
        UIDisplayMessage(PlayerGroupAll(), 3, StringToText(SQU  + " Pool"));
        //--------------------------------------------------------------

    if ( (WeAreAt(player) == "GameStart") &&
        (WeAreThrough(player, "GameStart") == "NotDoneGameStart") ){
        //note: this thing works by queueing things. Train that is.
        //ZEnsureWorker(10, 10, c_townOne, player);
        AISetStock( player, 10, c_ZU_Drone );
    }

    if( WeAreThrough(player, "GameStart") == "DoneGameStart" ) {
        //choose next block here
    }

    // >>> BLOCK 1: [OVIE.2, +3 DRONES, +POOL] process start ______________________________
        // drones: complete 9-10, inprogress 0-1, queued 0-1
        if (RCountUnit(c_ZU_Drone, 9, 10, 0, 1, 0, 1, player) == true) {
            ZEnsureFood(18, 9, c_townOne, player);
            ZEnsureTech(1, c_ZB_SpawningPool, 10, c_townOne, c_nearCloseDropoff, player);
            ZEnsureWorker(13, 10, c_townOne, player);
        }
    // >>> OVIE.2, +3 DRONES, +POOL process end __________________________________________
        // we have 0 pool built, 1 inprogress, 0 queued
        //note: setstock doesn't come up in queue
        if (RCountUnit(c_ZB_SpawningPool, 0, 0, 1, 1, 0, 0, player) == true) {
            //ZEnsureWorker(13, 3, c_townOne, player);
            AISetStock( player, 16, c_ZU_Drone );
            ZEnsureTech(1, c_ZB_Extractor, 10, c_townOne, c_onVespeneGas, player);
            //AISetStock( player, 1, c_ZB_Extractor );
        }
        if (RCountUnit(c_ZU_Drone, 15, 16, 0, 1, 0, 1, player) == true) {
            //AISetStock( player, 16, c_ZU_Drone );
            ZEnsureUnit(1, c_ZU_Queen, 10, c_townOne, player);
            ZEnsureFood(26, 1, c_townOne, player);
        }
   
    // >>> BLOCK (undefined): [OVIE.2, +POOL, +3 DRONES] process start ______________________________
    // drones: complete 9-10, inprogress 0-1, queued 0-1
    //    if (RCountUnit(c_ZU_Drone, 9, 10, 0, 1, 0, 1, player) == true) {
    //        ZEnsureFood(18, 9, c_townOne, player);
    //        ZEnsureTech(1, c_ZB_SpawningPool, 10, c_townOne, c_nearCloseDropoff, player);
    //    }
    //    if (RCountUnit(c_ZB_SpawningPool, 0, 1, 1, 1, 0, 0, player) == true) {
    //        ZEnsureWorker(13, 3, c_townOne, player);
    //    }
    // >>> OVIE.2, +POOL, +3 DRONES process end __________________________________________
   

    if (AIEnableVeryEasyStockOpen(player, c_ZU_Drone)) {
        return;
    }

Now, all of these are placed inside the Zerg0.galaxy.

The commented lines up there, which goes into void ZergOpenGnd0 (int player) of zerg0.galaxy, is part of a block which I'd like the AI to have as choices later on when I get an idea how to do it.

As of now, I'm thinking of a 2dimensional array, that stores both the block name and priority. This way, we can make a function that sorts out these said blocks and allow the AI to execute script lines within those blocks also with priority.

So, each block is stored in a 2dimensional array as the condition calls for, and each line within that block is stored in another 2dimensional array that has set of conditions before the next one will be executed.

I don't exactly have a workable code yet, only a concept.

Also, adding AI personality() with variables like aggitation, passivity, calmvalue, aggrivatevalue, aggrivateMinRangeValue, aggrivateMaxRangeValue, etc, much like L4d's witch, would give the AI some bias as to what block to store in response to certain conditions.

So no two AI personalityies will respond the same. For example, a "Rusher" personality with Aggressiveness value = 150, and passivity value = 50, and AggressivenessPassivityDiffMin = 20, will most likely choose to rush early even if it's passivity value is increased by certain conditions.

Aggressiveness Value is the minimum value the AI will get even if CalmValue is deducted to it. Aggressiveness Value is added to, for example by Aggitate Value, if enemies are found within AggrivateMinRangeValue, and will be deducted by Calm value if there were no enemies there.

So, for example, if the Personality.CalmValue = 10, this personality will calm down at this rate, etc.

All of these values will affect what Block the AI will choose, and what block to discard if conditions are appropriate, and it's personality allows it or favors it, etc.

Sorry, if I sound to be in a rush. I hope these will give you guys some ideas to consider though, as I've not been coding since some 15 years ago now.

Will post some Zerg builds later.

edit: Oh, and AISetStock() doesn't seem to queue the unit. Train and Build will appear in the queued only but not items using AISetStock()
#111
et2010,

I hope you don't mind; Can you add a "Save Map As.." option? I mean, the launcher won't launch SC2, but just save the selected map with the selected settings.

Please?
#112
Quick question:

Since it saves to the \download folder, can I then just copy that modified map, and use LazyLauncher2 directly and start up a game with the same settings?

I mean, say, I set, 1 toss vs 2 zerg, start game, exit starcraft2. Go to the download folder, copy that map and place it under 00\11 and rename it to say,

0011 1v2 PvZZ Lost Temple

then launch lazylauncher2 select the renamed map and expect to see the same matchup?
#113
I don't understand what this is. Can I use this to install starcraft2 without having an online connection?
#114
True. After testing, while kind of makes the game into stop motion. Ifs work better.

Do you guys know how the galaxy files interact? where do we define global variables, which one gets executed, which ones are just libraries, etc.
#115
Brilliant. I'm currently focusing on the AI in a defensive mode. It wants to tech to lair asap, and use minimal expenses on defense units, and will build them only when necessary. Once it get's lair, it starts two things:

want to 3rd expo, while harassing, and building up an offensive army.

Before, I get to that though, I'm working on the script for the early game, and give it priority shifting. I'm trying to write code, which I want to be as dynamic as possible, and can be reused later up in the tiers where multiple options, and more data are involved.
#116
I'd like to request a feature to just save the map with settings without launching SC2? Thanks.
#117
It does. My above post is really not refined nor exactly useful (sort of inductive). They're vague concepts still, as I'm yet trying to get a handle on the whats that gets swapped around within the first 5mins of the game.

Anyway, I'll post what I find.
#118
It's like this:

Quote
//begin: Bane Defense
    AISetStock( player, 1, c_ZB_Hatchery_Alias );
    AISetStock( player, 10, c_ZU_Drone );
    AISetStock( player, 2, c_ZU_Overlord );
    AISetStock( player, 1, c_ZB_SpawningPool );
    if ( AITechCount(player, c_ZB_SpawningPool, c_techCountQueuedOrBetter ) == 1 ) { //we've started pool
        AISetStock( player, 12, c_ZU_Drone );
        AISetStock( player, 1, c_ZB_Extractor );       
        AISetStock( player, 15, c_ZU_Drone );
    }
    if ( (AITechCount(player, c_ZU_Drone, c_techCountInProgressOrBetter ) >= 13) &&
         (AITechCount(player, c_ZU_Drone, c_techCountInProgressOrBetter ) <= 16) &&
         (AIHasRes (player, 150, 0) == true) )
    {
        AISetStock( player, 1, c_ZU_Queen );
        AISetStock( player, 3, c_ZU_Overlord );
        AISetStock( player, 12, c_ZU_Zergling );   
        AISetStock( player, 1, c_ZB_BanelingNest );       
        AISetStock( player, 16, c_ZU_Drone );
    }
    if ( (AITechCount(player, c_ZU_Zergling, c_techCountInProgressOrBetter ) >= 4) &&
         (AITechCount(player, c_ZU_Zergling, c_techCountInProgressOrBetter ) <= 12) &&
         (AIHasRes (player, 250, 0) == true) )
    {
        AIDefaultExpansion(player, c_ZB_Hatchery_Alias, 12000, 6000, c_expandDefault);   
    }
    if    ( (AITechCount(player, c_ZB_BanelingNest, c_techCountCompleteOnly ) == 1) ) {
        AISetStock( player, 6, c_ZU_Zergling );
        AISetStock( player, 8, c_ZU_Baneling );
    }
   
    if ( (AITechCount(player, c_ZB_Hatchery, c_techCountInProgressOrBetter ) == 2)  &&
        (AITechCount(player, c_ZU_Drone, c_techCountCompleteOnly ) <= 18) &&
        (AIGetTime() < 300)    )
    {
        AISetStock( player, 8, c_ZU_Zergling );   
        AISetStock( player, 8, c_ZU_Baneling );
        AISetStock( player, 10, c_ZU_Zergling );
    }

I wrote this without the funcs yet, which I believe you guys can do. Funcs that are conditional which will run in parallel.

From testing, the script should either choose to make banes immediately or lings, or skip them all together if the enemy had no zealots, right? That's where the while comes.

I want the AI to enter a while and stay there until a break is called. And once that while has been entered, a key will be set so the next while will not be true anymore.

Before each while, conditions tested and the script will parse multiple ifs repeatedly until a while condition is met. Once in a while, at some cases, a key will be set and break called so as to call the other while.

All this will loop over and over, just as a state does, and might even leave a state early and move to MidGndA or B. All depending on the conditions.

From the above example, we can later create a code that has one main, and two conditional states it will enter. This so called states are the ones in the while statement.

So for example, while the protoss player is maintaining a number of zealots, it will enter the while and keep TrainZerglings(UnitToCounter, Min, Max, PriorityKey).

So it's probably going to look like this:
returned 1 -- minimum is reached
returned 2 -- maximum is reached
returned 3 -- we cannot try min, we cannot try max, we're not needing this.

while (TrainZerglings("Zealot", 3, 7, 8 ) != 3) and some condition is true here) { //we are facing 1-7 zeals, and we've not trained zerglings 1x4 (minimum which returns 1) to zerglings 7x4 (max which returns 3)

     [do stuff here]
}

if (we have more than 6 lings complete and TrainZerglings(..) >= 1 and != 3 and some condition here is true) {
     while (TrainBanes("Zealot", 1, 3, 10) !=3)) {}
}

So, as you can see, the script should jump back and forth from each other and maintain a number of lings, then morph them to banelings, etc, until everything is satisfied.

Something like this. Haven't put a lot of thought yet in implementation, since I'm still trying to figure out the thinking process and loop holes of ZvP @ < 5:00 mins.

So far though, the above will most likely be needed should it make the AI more dynamic.
#119
Excellent. Here's a sample format that might work. Gamewiz has hinted of this format. We see that there is a priority and a secondary one. His strategy is in ready anticipation, and works like this in concept:

The 13 Hatch (vs 7-8 Zeal):

>Once the pool is done:
     [we only make Spines if the enemy will likely send Zealots...]
          if so, 2 sunks vs 1-3 zeals must be the desired state.
          * do not make spines until our expo is done, and
          * some time have elapsed for the creep to expand, and
          * make sure the spines are at the expo

          [we prioritize lings instead of drones ONLY if the enemy has more than 3 zeals]
          *do so only if we have at least 18 drones complete or in production, and
          *if we have 1 Queen.

               if so, for every +1 Zeal of the basic (1 min to 3 max zeal):

                    add 4 lings.
                    if 5 zeals, only want 6 lings.
                    if 6 - 7 zeals, want 10 min, 12 max lings
                   *do not stock, train only when called for, and
                   *keep to the limits to avoid overspending.

Basicallythe subs are conditional. The script must prioritize getting it's 13Hatch goal, unless military is required. 13 Hatch can then proceed toLair Tech + muta.

That Lair Tech + Muta is actually another nextstate, but there are other sates, like mass ling 3rd expo. But thosehaven't been tested or considered yet.

The thing is if there were no enemies, econ is always the main goal. But threats to that make us try to find the most optimal route. And to accomplish that, we need to know the ranges of what can be done against us and respond accordingly.

If you like, you may use this format, or keep to what your comfortable with. But it will help a lot if the conditions are clear and responses are measured like the example above.
#120
Update: March 09, 2010
-----------------------

After some games, there's this:

The 13 Hatch (vs 7-8 Zeal):

>Once the pool is done:
     [we only make Spines if the enemy will likely send Zealots...]
          if so, 2 sunks vs 1-3 zeals must be the desired state.
          * do not make spines until our expo is done, and
          * some time have elapsed for the creep to expand, and
          * make sure the spines are at the expo

          [we prioritize lings instead of drones ONLY if the enemy has more than 3 zeals]
          *do so only if we have at least 18 drones complete or in production, and
          *if we have 1 Queen.

               if so, for every +1 Zeal of the basic (1 min to 3 max zeal):

                    add 4 lings.
                    if 5 zeals, only want 6 lings.
                    if 6 - 7 zeals, want 10 min, 12 max lings
                   *do not stock, train only when called for, and
                   *keep to the limits to avoid overspending.

Basically the subs are conditional. The script must prioritize getting it's 13 Hatch goal, unless military is required. 13 Hatch can then proceed to Lair Tech + muta.

That Lair Tech + Muta is actually another next state, but there are other sates, like mass ling 3rd expo. But those haven't been tested or considered yet.

This is the BO for 13hatch:

Drones 7-10
Ovie 2
Drones 11-13
   *wait 300 meaner'aalzz.
Expand
   Drones 13-15
      Pool
      Drones 15-18
      Ovie 3
optional: 2 Spine Crawlers (or Extractor 2)
         Extractor 1, Queen 1 (or if no spine crawler, gas mining 6)
            Drones 19-21 (if spine crawler, start gas mining)
optional: lings production
(we are ready for next state)