Return

 

1998/1999
 

Back to beginners guide to A.I.
to DancingMoogles short guide to A.i editor


As we progress with the tutorial for the A.I. this will become the benchmark that all other A.I. will go by - as it was the first to work correctly ( some would argue that point) but anyways, on with the battle - first being to translate this mass of code into one that everyone can read and understand. Never have I undertaken such a task but as with all things - there is a first time for everything... you will notice that I am in process of highlighting in RED his comments - looks to be a pretty straight forward task - but you all know what that means - (see murphy's law - ie: code ):>
CAUTION: EXTREMELY LONG DOCUMENTATION AHEAD! Coffee is mandatory!

///////////////////////////////////////////////////////////////////////
general ai for skirmish game
/////////////////////////////////////////////////////////////////////
Warzone2100, Pumpkin Studios,
alex lee.98/99.
/////////////////////////////////////////////////////////////////////



public        INT                                player;                                // player for this instance.
public        INT                                tileExpand;                        // rate of exploration

public        INT                                numScouts;                        // aim for...
public        INT                                numDefenders;
public        INT                                numAttackers;

// structures
private INT                                baseX,baseY,minx,miny,maxx,maxy;
public        INT                                numStructs,numIncendrys,numDefStructs,numExtraStructs,numWallWeaps;                                                        
public        STRUCTURESTAT        incendrys[8],structs[13],defStructs[26],extraStructs[6],structChoice[5],wallWeaps[11];
public        STRUCTURESTAT        sensorTower,wallStruct,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory,vtolDefStruct[5],vtolPad,vtolFactory,repairFacility;
public        STRUCTURESTAT        powModule,facModule,resModule,vtolModule;
public        INT                                extraStruct;

// unit templates
public        INT                                numTemplates;
public        TEMPLATE                tmpl[80];
private        TEMPLATE                tmplChoice[5];

public        TEMPLATE                cybTempl[4],superCyb[4];

public        TEMPLATE                vtols[18];
public        INT                                numVtolTemplates;

public        TEMPLATE                sense[11];
public        INT                                numSenseTemplates;

public        TEMPLATE                constructor,repairUnit;                                
public        INT                                numCyborgs,numRepairUnits;
private INT                                currentCyborgs,currentCyborgTemplate;

//defend
private GROUP                        defendGroup;
private BOOL                        defendbusy;
private BASEOBJ                        defendObj;

public RESEARCHSTAT        nexusDefence;

//build
private GROUP                        buildGroup;
private INT                                buildX,buildY,buildX2,buildY2;
public        FEATURESTAT                oilRes;

// scout
private GROUP                        scoutGroup;
private INT                                scoutX,scoutY;
private INT                                scoutTLX,scoutTLY,scoutW,scoutH;

// attack
private GROUP                        attackGroup;
private BASEOBJ                        attackObj,allOutAttack;

// vtols
private GROUP                        vtolGroup;

// generic
private STRUCTURE                structure,structure2;
private DROID                        droid;
private FEATURE                        feature;
private BASEOBJ                        baseobj,baseobj2;
private INT                                count,count2,result,result2,tempx,tempy;
private BOOL                        boolResult,boolResult2;

private BOOL                        powerSave;
private        INT                                allianceTime[8];

/////////////////////////////////////////////////////////////////////
// triggers.


trigger buildExpandTr                                (every, 900);
trigger fortifyTr                                        (every,        1250);
trigger upgradeStructuresTr                        (every, 590 );
trigger conDroidsTr                                        (every, 1800);        // was 3600
trigger repairDroidsTr                                (every, 2600);
trigger        managePowerTr                                (every, 2000);
trigger basedetailsTr                                (every, 700        );
trigger buildDerrickTr                                (every, 110        );
trigger buildOilDefenseOrRetreatTr        (every, 170        );
trigger incendryTr                                        (every, 310 );
trigger buildPowerGeneratorsTr                (every, 90        );
trigger buildBaseTr                                        (every, 210        );
trigger finishStructsTr                                (every, 610 );
trigger droidBuiltTr                                (CALL_NEWDROID,player, ref droid,ref structure);
trigger droidDestroyedTr                        (CALL_DROID_DESTROYED, player, ref droid);
trigger consolidateEventTr                        (every,        3100);
trigger factoryEventTr                                (every, 200        );
trigger cyborgFactoryEventTr                (every, 200        );
trigger chooseScoutAreaTr                        (every,        200        );
trigger expandScoutAreaTr                        (every,        600        );
trigger scoutMainTr                                        (every,        150        );
trigger newObjectReportTr                        (CALL_OBJ_SEEN, player, ref baseobj, ref baseobj2);
trigger attackStuffTr                                (every, 300        );
trigger allOutAttackTr                                (every, 2380);
trigger defendWatchTr                                (CALL_STRUCT_ATTACKED, player, ref structure, ref baseobj);
trigger defendReturnTr                                (every,        600        );
trigger doResearchTr                                (every, 500 );
trigger vtolDefendTr                                (CALL_STRUCT_ATTACKED, player, ref structure, ref baseobj);
trigger vtolStructsTr                                (every, 360);                
trigger buildVtolsTr                                (every, 360);                
trigger vtolAttackTr                                (every, 460);                        
trigger vtolEnablerTr                                (every, 2100);
trigger takeoverTr                                        (CALL_UNITTAKEOVER, ref droid);
trigger useLassatTr                                        (every, 3000);
trigger reassignTr                                        (CALL_PLAYERLEFT,count);        
trigger formAllianceEventTr                        (every,170);
trigger breakAllianceEventTr                (every,700);
trigger difficultyModifierTr                (every,600);
trigger humanAllianceTr                                (CALL_ALLIANCEOFFER,ref count, ref count2);

/////////////////////////////////////////////////////////////////////
// HouseKeeping

event initialisedEvent(CALL_GAMEINIT)
{
        // initialise
        extraStruct = 0;
        numRepairUnits = 0;
        allOutAttack = NULLOBJECT;
        currentCyborgTemplate = 0;
        powerSave = FALSE;
        
        // setup build group
        //all initial droids are in buildgroup!
        groupAddArea(buildGroup, player, 0, 0, (mapWidth*128), (mapHeight*128));
        initGetFeature(oilRes,player,player);                // use bucket = player

        // note where our base is.
        initIterateGroup(buildGroup);                // find idle droids in build group.
        droid = iterateGroup(buildGroup);
        if(droid != NULLOBJECT)
        {
                baseX = droid.x;
                baseY = droid.y;
        }
        else
        {
                baseX = (128*mapWidth)/2;
                baseY = (128*mapHeight)/2;
        }

        // defence.
        defendbusy = FALSE;
        
        // setup scouts
        structure = getStructure(factory, player);
        if(structure != NULLOBJECT)
        {        
                scoutTLX                = structure.x;
                scoutTLY                = structure.y;
        }
        else
        {
                scoutTLX                = baseX;
                scoutTLY                = baseY;
        }
        scoutW                        = 256;
        scoutH                        = 256;
        scoutX                        = scoutTLX;
        scoutY                        = scoutTLY;



        // clear the alliance array...
        allianceTime[0] = 0;                
        allianceTime[1] = 0;
        allianceTime[2] = 0;
        allianceTime[3] = 0;
        allianceTime[4] = 0;
        allianceTime[5] = 0;
        allianceTime[6] = 0;
        allianceTime[7] = 0;
}

/////////////////////////////////////////////////////////////////////
// initial force setup thing. plonk down a force.
event givehelp(every, 100)
{
        if( (player == selectedPlayer) or (not myResponsibility(player)) )
        {
                setEventTrigger(givehelp,        inactive);                        
        }
        else
        {
                if(multiPlayerBaseType == CAMP_WALLS)
                {
                        // free power
                        addPower(1500, player);

                        // free droids.
                        structure = getStructure(factory, player);
                        if(structure != NULLOBJECT)
                        {
                                count = 0;
                                while(count<10)
                                {
                                        tempx = baseX;
                                        tempy = baseY;
                                        
                                
                                        boolResult = pickStructLocation(defStructs[0], ref tempx, ref tempy,player);
                                        if(boolResult == TRUE)
                                        {
                                                addDroid(tmpl[ random(6) ] , tempx, tempy, player);
                                        }

                                        count = count + 1;
                                }
                        }
                }
                setEventTrigger(givehelp,        inactive);                        

        }
}

/////////////////////////////////////////////////////////////////////
// keep details about the size and postion of the ai players base
event basedetails(basedetailsTr)
{
        if( (player == selectedPlayer) or (not myResponsibility(player)) )
        {
                setEventTrigger(basedetails,        inactive);                        
        }
        else
        {
                // clear old extremities.
                maxy = 0;
                maxx = 0;
                miny = (mapHeight*128);
                minx = (mapWidth*128);

                // now find the extremities of our vital structures.        
                count = 0;
                while(count < numStructs)
                {
                        initEnumStruct(FALSE,structs[count],player,player);                                        
                        structure= enumStruct();
                        while(structure != NULLOBJECT)        
                        {
                                if(structure.x < minx)
                                {
                                        minx = structure.x;
                                }
                                if(structure.x > maxx)
                                {
                                        maxx = structure.x;        
                                }
                                if(structure.y < miny)
                                {
                                        miny = structure.y;
                                }
                                if(structure.y > maxy)
                                {
                                        maxy = structure.y;
                                }
                                structure= enumStruct();
                        }
                        count = count + 1;
                }
        }
}

/////////////////////////////////////////////////////////////////////
// structure building rules

// build derricks on oil.
event buildDerrick(buildDerrickTr)
{
        if( (player == selectedPlayer) or (not myResponsibility(player)) )
        {        
                setEventTrigger(buildDerrick,        inactive);                        
        }
        else
        {
                feature = getFeature(player);                                        // find unoccupied oil resource.
                if(feature != NULLOBJECT)
                {
                        buildX = feature.x;
                        buildY = feature.y;

                        // if no more than 2 units already trying to build
                        initIterateGroup(buildGroup);                                // find all units in build group.
                        droid = iterateGroup(buildGroup);
                        count = 0;
                        while(droid != NULLOBJECT)
                        {
                                if((droid.orderx == buildX) and (droid.ordery == buildY))
                                {
                                        count = count + 1;
                                }
                                droid = iterateGroup(buildGroup);
                        }

                        if(count < 3)
                        {
                                initIterateGroup(buildGroup);                                // find all units in build group.
                                droid = iterateGroup(buildGroup);
                                boolResult = FALSE;                                                        // only send 1 droid to each derrick
                                while( (boolResult == FALSE) and (droid != NULLOBJECT) )
                                {
                                        if( (droid.order == DORDER_NONE) or (droid.order == DORDER_RTB))
                                        {
                                                orderDroidStatsLoc(droid, DORDER_BUILD,derrick, buildX,buildY);        //build a derick
                                                boolResult = TRUE;
                                        }
                                        droid = iterateGroup(buildGroup);
                                }
                        }
                }
                else                                                                                        // feature is null
                {
                        initGetFeature(oilRes,player,player);                // start again next time.
                }
        }
}

/////////////////////////////////////////////////////////////////////
// if idle and derrick in range and no defense then build defense, else ret to base .
event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr)
{
        if( (player == selectedPlayer) or (not myResponsibility(player)) )
        {        
                setEventTrigger(buildOilDefenseOrRetreat,        inactive);                        
        }
        else
        {
                // check idle.
                initIterateGroup(buildGroup);                                        // find idle droids in build group.
                droid = iterateGroup(buildGroup);
                while(droid != NULLOBJECT)
                {
                        if(droid.order == DORDER_NONE)
                        {
                                // if in range of a derrick                                 
                                structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), player);

                                // if inside base limits then presume ok..
                                if( structure != NULLOBJECT)
                                {
                                        if((structure.x > minx) and (structure.y > miny) and (structure.x < maxx) and (structure.y <maxy))        
                                        {
                                                structure = NULLOBJECT;
                                        }
                                }

                                if(structure != NULLOBJECT)
                                {
                                        buildX = structure.x;
                                        buildY = structure.y;
                                        
                                        count = 0;                                                        // if derrick has no defense near it.
                                        result = 0;
                                        while(count < numDefStructs)
                                        {        
                                                structure = structureBuiltInRange(defStructs[count], buildX, buildX,(3*128), player);
                                                if(structure != NULLOBJECT)
                                                {                                
                                                        result = result + 1;                                                        // found a defense.
                                                }
                                                count = count + 1;
                                        }

                                        // not many defenses nearby
                                        if(result < 2)
                                        {
                                                count = numDefStructs - 1;                                                        //pick a struct to build..
                                                count2 = 0;
                                                while( (count2 < 5) and (count >= 0) )
                                                {
                                                        if( isStructureAvailable(defStructs[count],player))
                                                        {

                                                                // don't build multiple sensors together.
                                                                if(count == 5)
                                                                {
                                                                        structure = structureBuiltInRange(defStructs[count], buildX, buildY,(6*128), player);
                                                                        if(structure != NULLOBJECT)
                                                                        {
                                                                                count = 8;
                                                                        }
                                                                }

                                                                structChoice[count2] = defStructs[count];
                                                                count2 = count2 + 1;
                                                                
                                                        }
                                                        count = count - 1;
                                                }
                                                count =0;
                                                if(count2 > 0)
                                                {
                                                        count = random(count2);                                                 //count = choice!
                                                        // pick a location
                                                        boolResult = pickStructLocation(structChoice[count], ref buildX, ref buildY,player);
                                                        if(boolResult == TRUE)
                                                        {        
                                                                // build it.
                                                                orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY);
                                                        }
                                                }                                
                                        }
                                        else
                                        {        
                                                structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), player);        
                                                if(structure == NULLOBJECT)
                                                {
                                                        orderDroid(droid,DORDER_RTB);                                // return to base;
                                                }
                                        }                                        
                                }
                                else
                                {
                                        structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), player);        
                                        if(structure == NULLOBJECT)
                                        {
                                                orderDroid(droid,DORDER_RTB);                                        // return to base;
                                        }
                                }
                        }        
                        droid = iterateGroup(buildGroup);
                }
        }
}

/////////////////////////////////////////////////////////////////////
//mortar etc.. rules. build sensor towers and emplacements.
event incendry(incendryTr)
{
        if( (player == selectedPlayer) or (not myResponsibility(player)) )
        {        
                setEventTrigger(incendry,        inactive);                        
        }
        else
        {
                initEnumStruct(FALSE,sensorTower,player,player);
                
                count = 0;
                structure = enumStruct();
                while(structure != NULLOBJECT)
                {
                        count = count + 1;
                        structure = enumStruct();
                }
        
                if(count < (gameTime/4200) )                // every 7 mins
                {
                        // if not found build a sensor tower.
                        // find a place to build.
                        buildX = 0;
                        buildY = 0;
                        initEnumStruct(FALSE,derrick,player,player);                        
                        structure= enumStruct();
                        while(structure != NULLOBJECT)
                        {
                                count = 0;                        
                                result = 0;
                                while(count < numDefStructs)
                                {        
                                        structure2 = structureBuiltInRange(defStructs[count], structure.x, structure.y,(4*128), player);
                                        if(structure2 != NULLOBJECT)
                                        {                                
                                                result = result + 1;                                
                                        }
                                        count = count + 1;
                                }
                                
                                // check for sensor nearby,
                                structure2 = structureBuiltInRange(sensorTower, structure.x, structure.y,(5*128), player);
                                if(structure2 != NULLOBJECT)
                                {
                                        result = 4;
                                }

                                if(result < 3)
                                {
                                        buildX = structure.x;
                                        buildY = structure.y;
                                        structure = NULLOBJECT;
                                }
                                else
                                {
                                        structure = enumStruct();
                                }
                        }
                
                        if(buildX != 0)
                        {
                                boolResult = pickStructLocation(sensorTower, ref buildX, ref buildY,player);        // pick spot.
                                if(boolResult == TRUE)
                                {
                                        // find unit
                                        initIterateGroup(buildGroup);                                
                                        droid = iterateGroup(buildGroup);
                                        while(droid != NULLOBJECT)
                                        {
                                                if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
                                                {
                                                        orderDroidStatsLoc(droid, DORDER_BUILD,sensorTower, buildX,buildY);
                                                        droid = NULLOBJECT;
                                                }
                                                else
                                                {
                                                        droid = iterateGroup(buildGroup);
                                                }
                                        }        
                                }
                        }
                }
                else
                {
                        // find a sensor tower with least incencdry structs around it..
                        buildX = 0;
                        buildY = 0;        

                        initEnumStruct(FALSE,sensorTower,player,player);                        
                        structure= enumStruct();
                        count = 999;
                        while(structure != NULLOBJECT)
                        {
                                // count incendrys near this tower.                 
                                result = 0;
                                count2 = 0;
                                while(count2 < numIncendrys)
                                {        
                                        structure2 = structureBuiltInRange(incendrys[count2], structure.x, structure.y,(4*128), player);
                                        if(structure2 != NULLOBJECT)
                                        {                                
                                                result = result + 1;                                
                                        }
                                        count2 = count2 + 1;
                                }

                                if((result < 6) and (result < count))                // lowest found yet. only sites with <6 too.
                                {
                                        buildX = structure.x;
                                        buildY = structure.y;
                                        count = result;
                                }
                                structure = enumStruct();
                        }

                        if(buildX != 0)
                        {

                                // choose a device
                                count = numIncendrys - 1;
                                result = 99;
                                while(count >= 0 )
                                {
                                        if(isStructureAvailable(incendrys[count],player))
                                        {
                                                result = count;
                                                count = -1;
                                        }
                                        else
                                        {
                                                count = count - 1;
                                        }
                                }
                                
                        
                                // find a unit and build an incendry device.
                                if(result != 99)
                                {
                                        boolResult = pickStructLocation(incendrys[result], ref buildX, ref buildY,player);        // pick spot.
                                        if(boolResult == TRUE)
                                        {

                                                initIterateGroup(buildGroup);                                
                                                droid = iterateGroup(buildGroup);
                                                while(droid != NULLOBJECT)
                                                {
                                                        if(droid.order == DORDER_NONE or droid.order == DORDER_RTB)
                                                        {
                                                                orderDroidStatsLoc(droid, DORDER_BUILD,incendrys[result], buildX,buildY);
                                                        }
                                                        droid = iterateGroup(buildGroup);
                                                }
                                        }        
                                }        
                        }
                }

        }
}






/////////////////////////////////////////////////////////////////////
// build a power gen for every 4 derricks. VITAL!
event buildPowerGenerators(buildPowerGeneratorsTr)
{
        if( (player == selectedPlayer) or (not myResponsibility(player)) )
        {        
                setEventTrigger(buildPowerGenerators,        inactive);                        
        }
        else
        {
                initEnumStruct(FALSE,derrick,player,player);                                        // count = numderricks
                structure= enumStruct();
                count         = 0;
                while(structure != NULLOBJECT)        
                {
                        count = count + 1;
                        structure= enumStruct();
                }
                        
                initEnumStruct(FALSE,powGen,player,player);                                        // count2 = numpowgens
                structure= enumStruct();
                count2         = 0;
                while(structure != NULLOBJECT)        
                {
                        count2 = count2 + 1;
                        structure= enumStruct();
                }
                                                                
                if( (count2 * 4) < count )                                                                // if we need powergen
                {
                        buildX = baseX;                                                                                // try build powergen.
                        buildY = baseY;
                        boolResult = pickStructLocation(powGen, ref buildX, ref buildY,player);
                        if(boolResult == TRUE)
                        {        
                                initIterateGroup(buildGroup);                                
                                droid = iterateGroup(buildGroup);
                  &nb