Where to Find AI Queen Management

Started by Kernel64, March 04, 2010, 07:58:19 AM

Previous topic - Next topic

Kernel64

I'd like to see the codes related to the AI's control of the queen. It seems that the AI cannot handle two queens and use them on two different towns each.

Does anyone know where to find these or how to override them? Like, manually ordering a queen to cast an ability at a certain point, for example.

Yuna_Q

queen related functions at tactzergai.galaxy

Kernel64

Quote from: Yuna_Q on March 04, 2010, 08:16:15 AM
queen related functions at tactzergai.galaxy

Okay, I found the functions. But, Yuna_Q, I want to find the codes that call these functions.

You see, I want to use this as template for making ChronoBoost. The one discovered doesn't work.

imbalisk

Quote from: Kernel64 on March 04, 2010, 08:38:56 AM
Quote from: Yuna_Q on March 04, 2010, 08:16:15 AM
queen related functions at tactzergai.galaxy

Okay, I found the functions. But, Yuna_Q, I want to find the codes that call these functions.

You see, I want to use this as template for making ChronoBoost. The one discovered doesn't work.


Seems like you want to add ChronoBoost, try this:
In UnitData.xml you can find this:
<TacticalAIThink value="AIThinkQueen"/>
The function calls for the AIThink functions are hardcoded, if the AI has a queen or more, it searches for a TacticalAIThink value, if it finds one, it calls this the function AIThinkQueen.
As I mentioned in my LOOOOOOOOOOOOOOONG post in this other thread, you need to add a <TacticalAIThink value="AIThinkNexus"/> for the Nexus inside the UnitData.xml and create a AIThinkNexus function inside the TacticalThinkProtoss galaxy file that calls the ChronoBoost function.


In order to improve the AI of the queen, you can change transfusion function


order Transfusion (int player, unit aiUnit) {
    order ord;
    unitgroup group;
    aifilter filter;


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


    group = AIFindUnits(player, null, UnitGetPosition(aiUnit),
                        AIAbilityFixed(player, c_AB_Transfusion, c_fieldRange0) + 1,
                        c_noMaxCount)
    ;


    filter = AIFilter(player);
    AISetFilterAlliance(filter, c_playerGroupAlly);
    AISetFilterLifeLost(filter, AIEffectFixed(player, c_EF_Transfusion, c_fieldEffectChange0), c_noMax);
    group = AIGetFilterGroup(filter, group);


    return AIUnitGroupGetValidOrder(group, ord, aiUnit, c_forwards);
}


//--------------------------------------------------------------------------------------------------
order SpawnLarva (int player, unit aiUnit) {
    order ord;
    unitgroup hatcheries;
    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;
    }


    //  Don't cast if we already own at least 10 larva
    //
    larvaCount =
        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);
}

and code as the position for the search of the hatcheries the expansion point (overwrite UnitGetPosition(aiUnit) to the expansion point) when AI have more then 1 queen.

Kernel64

#4
Holy! Thanks a lot! I used the CC supply drop for this and just added <TacticalAIThink value="AIThinkNexus"/> into the xml.

here's the code for the Nexus's Chrono boost:

Quote
//--------------------------------------------------------------------------------------------------
//  *** Nexus CB ***
//--------------------------------------------------------------------------------------------------
static order ChronoBoost (int player, unit aiUnit) {
    unitgroup scanGroup;
    int scanCount;
    unit depot;
    order ord;
    aifilter filter;
   
    ord = AICreateOrder(player, "TimeWarp", 0);
    if (!UnitOrderIsValid(aiUnit, ord)) {
        return null;
    }

    scanGroup = AIFindUnits(player, "Nexus", UnitGetPosition(aiUnit),
                            AIUnitFixed(player, c_PB_Nexus, c_fieldRadius)
                            + AIAbilityFixed(player, "TimeWarp", c_fieldRange0),
                            c_noMaxCount
    );

    //  Filter out supply depots that are already buffed.
    //
    filter = AIFilter(player);
    AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, "TimeWarp", c_fieldTargetFiltersAB)));
    AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, "TimeWarp");
   
    scanGroup = AIGetFilterGroup (filter, scanGroup);
    return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}

void AIThinkNexus(int player, unit aiUnit, unitgroup scanGroup) {
    order ord;

    if (AIEvalTacticalData(aiUnit, null)) {
        return;
    }

    if (AIIsCampaign(player)) {
        return;
    }
   
    //----for saving energy; might be useful.
    //if (AISuspectDetectionDanger(player)) {
    //    if (UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent) < 150) {
    //        return; // save for two comsats
    //    }
    //}

    //  For now do supply only if we can't do mule,
    //  tempted to comment this out entirely
    ord = ChronoBoost(player, aiUnit);
    if (ord != null) {
        AICast(aiUnit, ord, c_noMarker, c_castHold);
        return;
    }
}


This goes into the TactProtAI.galaxy file.

This however applies to itself only. Any ideas on how we can control the nexus and where it casts the ability? I'm looking to manually order the nexus to cast chronoboost on specific structures at different conditions through Protoss0.galaxy

imbalisk

#5
Try the AIFindUnits just like in the QueenAI:
hatcheries = AIFindUnits(player,                              c_ZB_Hatchery_Alias,
                             UnitGetPosition(aiUnit),
                             15,
                             c_noMaxCount)

                             ;

like this:


unitgroup gateways;
gateways = AIFindUnits(player,                        c_PB_Gateway ,
                       UnitGetPosition(aiUnit),
                       15, // or more, thats the range
                       c_noMaxCount)

                       ;
forges = AIFindUnits(player,
                           c_PB_Forge,
                           15,
                           c_noMaxCount)
                           ;

and try to find out if the gates are producing something (dont boost non building structures) or researches sth (dont boost forge if it doesn't produce).
Still don't know how to do this :)

Kernel64

#6
Quote
//--------------------------------------------------------------------------------------------------
//  *** Nexus CB ***
//--------------------------------------------------------------------------------------------------
static order ChronoBoostGate (int player, unit aiUnit) {     // gateway boosting
    unitgroup scanGroup;

    int scanCount;
    unit depot;
    order ord;
    aifilter filter;

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

    filter = AIFilter(player);
    AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, "TimeWarp", c_fieldTargetFiltersAB)));
    AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, "TimeWarp");


    scanGroup = AIFindUnits(player, "Gateway", UnitGetPosition(aiUnit),
                            AIUnitFixed(player, c_PB_Nexus, c_fieldRadius)
                            + AIAbilityFixed(player, "TimeWarp", c_fieldRange0),
                            c_noMaxCount
    );
    scanGroup = AIGetFilterGroup (filter, scanGroup);
    return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}

static order ChronoBoostNex (int player, unit aiUnit) {     // Nexus boosting
    unitgroup scanGroup;

    int scanCount;
    unit depot;
    order ord;
    aifilter filter;

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

    filter = AIFilter(player);
    AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, "TimeWarp", c_fieldTargetFiltersAB)));
    AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, "TimeWarp");


    scanGroup = AIFindUnits(player, "Nexus", UnitGetPosition(aiUnit),
                            AIUnitFixed(player, c_PB_Nexus, c_fieldRadius)
                            + AIAbilityFixed(player, "TimeWarp", c_fieldRange0),
                            c_noMaxCount
    );
    scanGroup = AIGetFilterGroup (filter, scanGroup);
    return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}

static order ChronoBoostCore (int player, unit aiUnit) {     // Core boosting
    unitgroup scanGroup;

    int scanCount;
    unit depot;
    order ord;
    aifilter filter;

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

    filter = AIFilter(player);
    AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, "TimeWarp", c_fieldTargetFiltersAB)));
    AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, "TimeWarp");


    scanGroup = AIFindUnits(player, "CyberneticsCore", UnitGetPosition(aiUnit),
                            AIUnitFixed(player, c_PB_Nexus, c_fieldRadius)
                            + AIAbilityFixed(player, "TimeWarp", c_fieldRange0),
                            c_noMaxCount
    );
    scanGroup = AIGetFilterGroup (filter, scanGroup);
    return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}

void AIThinkNexus(int player, unit aiUnit, unitgroup scanGroup) {
    order ord;
    marker mark;

    if (AIEvalTacticalData(aiUnit, null)) {
        return;
    }

    if (AIIsCampaign(player)) {
        return;
    }
   
    //----for saving energy; might be useful.
    //if (AISuspectDetectionDanger(player)) {
    //    if (UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent) < 150) {
    //        return; // save for two comsats
    //    }
    //}


    // less that 120seconds only into the game, and we have a probe in production
    if ((AITechCount(player, c_PU_Probe, c_techCountInProgressOnly) == 1) && (UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent) > 25) && (AIGetTime() < 120) ) {
        ord = ChronoBoostNex(player, aiUnit);
        if (ord != null) {
            AICast(aiUnit, ord, c_noMarker, c_castHold);
            return;
        }
    }

// we have Zealot in production...
    else if (AITechCount(player, c_PU_Zealot, c_techCountInProgressOnly) == 1) {

        //mark = AIMarker(aiUnit, c_MK_PhaseShift);
        //ord = ChronoBoost(player, AIGrabUnit( player, c_PB_Gateway, c_prioNone, AIGetTownLocation(player, c_townOne) )  );
        ord = ChronoBoostGate(player, aiUnit);
        if (ord != null) {
            AICast(aiUnit, ord, mark, c_castHold);
            return;
        }
    }

    // if we have cybernetics core, and warpgate researching, target chronoboost!
    else if (AITechCount(player, c_PR_WarpGateResearch, c_techCountInProgressOnly) == 1) {
        ord = ChronoBoostCore(player, aiUnit);
        if (ord != null) {
            AICast(aiUnit, ord, mark, c_castHold);
            return;
        }
    }


}

Each structure is given it's own order. ChronoBoostNex for nexus, ChronoBoostGate for gateways, etc.

Here are the issues:
- The filter does not work with gateways. Nexus fires the ability twice on it given 50 energy.
- The AIThinkNexus clearly needs better logic so priority can be set. At this point it's who gets to have a go when the Nexus has energy to spare.


Aeg1s

if (AITechCount(player, c_PU_Zealot, c_techCountInProgressOnly) == 1) {
One problem with this is the gateway the Nexus chooses to Chrono Boost can't be guaranteed to have a zealot in production. Certainly most of the time all gateways should be used but there will be instances where at least one is sitting idle.
[/size][/color]
[/size][/color]Unfortunately I haven't found any way to determine if a building is producing something :/
[/size][/color]
[/size][/color]I'm currently using a hacked queue using a static array for prioritizing targets (this has the downside of not working if there's more than one instance of the Protoss AI in a game); I can post it if anyone wants.

Kernel64

#8
please do. Also, where do you put the chrono boost function you posted up yesterday? I can't seem to figure out where to call it, since at Protoss0.galaxy, it makes the game blank.