Untitled diff

Created Diff never expires
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// general ai for skirmish game
// general ai for skirmish game
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// Warzone2100, Pumpkin Studios,
// Warzone2100, Pumpkin Studios,
// alex lee.98/99.
// alex lee.98/99.
//
//
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////


//Tile in world units
//Tile in world units
#define TILE 128
#define TILE 128
#define NONE (-1)
#define NONE (-1)


// These are final rules of the lexical parser
// These are final rules of the lexical parser
#define R_REQUEST_HELP "help me"
#define R_REQUEST_HELP "help me"
#define R_REQUEST_BEACON "drop a beacon"
#define R_REQUEST_BEACON "drop a beacon"
#define R_REPORT_SAFETY "i'm ok"
#define R_REPORT_SAFETY "i'm ok"
#define R_REQUEST_ALLY "ally me"
#define R_REQUEST_ALLY "ally me"


// These are our own messages - lexical parser should be able to handle them
// These are our own messages - lexical parser should be able to handle them
#define M_REQUEST_HELP "help me!!"
#define M_REQUEST_HELP "help me!!"
#define M_REQUEST_BEACON "drop a beacon"
#define M_REQUEST_BEACON "drop a beacon"
#define M_AFFIRMATIVE_OK "ok"
#define M_AFFIRMATIVE_OK "ok"
#define M_AFFIRMATIVE_ROGER "roger"
#define M_AFFIRMATIVE_ROGER "roger"
#define M_ANNOYED "bug off"
#define M_ANNOYED "bug off"
#define M_HELPERS_KILLED "that was all I had.."
#define M_HELPERS_KILLED "that was all I had.."
#define M_HELP_NO_UNITS "I don't have anything"
#define M_HELP_NO_UNITS "I don't have anything"


#define MAX_PROBABILITY 100
#define MAX_PROBABILITY 100


// Base threat range in world units
// Base threat range in world units
#define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE)
#define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE)
#define ALL_ALLIES -1
#define ALL_ALLIES -1


#define BASE_DEFEND_DURATION (3 * 60)
#define BASE_DEFEND_DURATION (3 * 60)


// Delay before we repeat our request, in seconds
// Delay before we repeat our request, in seconds
#define HELP_REQUEST_INTERVAL (3 * 60)
#define HELP_REQUEST_INTERVAL (3 * 60)


//in secs
//in secs
#define BEACON_TIMEOUT 30
#define BEACON_TIMEOUT 30


#define MAX_DROIDS 150
#define MAX_DROIDS 150


//range for trucks to look for more oil
//range for trucks to look for more oil
#define MORE_OIL_RANGE (10 * TILE)
#define MORE_OIL_RANGE (10 * TILE)
//don't try to build on oil if there's threat within this range
//don't try to build on oil if there's threat within this range
#define OIL_THREAT_RANGE (9 * TILE)
#define OIL_THREAT_RANGE (9 * TILE)


#define MAX_TRUCKS 12
#define MAX_TRUCKS 15
#define MIN_TRUCKS 5
#define MIN_TRUCKS 12


//Enter power saving mode when lower than this
//Enter power saving mode when lower than this
#define LOW_POWER 250
#define LOW_POWER 250


//Target type values
//Target type values
#define NO_TARGET_VALUE 0
#define NO_TARGET_VALUE 0
#define DROID_TARGET_VALUE 1
#define DROID_TARGET_VALUE 1
#define OTHER_TARGET_VALUE 2
#define OTHER_TARGET_VALUE 2
#define DEFENSE_TARGET_VALUE 3
#define DEFENSE_TARGET_VALUE 3
#define RESEARCH_TARGET_VALUE 4
#define RESEARCH_TARGET_VALUE 4
#define HQ_TARGET_VALUE 5
#define HQ_TARGET_VALUE 5
#define OIL_TARGET_VALUE 6
#define OIL_TARGET_VALUE 6
#define FACTORY_TARGET_VALUE 7
#define FACTORY_TARGET_VALUE 7


#define UNLIMITED (-1)
#define UNLIMITED (-1)


#define AA_THREAT_RANGE (TILE * 12)
#define AA_THREAT_RANGE (TILE * 12)


#define MAX_DEFENDERS_RADIUS (TILE * 40)
#define MAX_DEFENDERS_RADIUS (TILE * 40)


#define MAX_VTOL_DEFEND_RADIUS (TILE * 25)
#define MAX_VTOL_DEFEND_RADIUS (TILE * 25)


// AI will remember max this number of structures
// AI will remember max this number of structures
#define MAX_REBUILD_STRUCT 100
#define MAX_REBUILD_STRUCT 100


//Total number of technology branches
//Total number of technology branches
#define TECHS 2
#define TECHS 2


//How many best templates to choose from when deciding what template to build
//How many best templates to choose from when deciding what template to build
#define MAX_RANDOM_TEMPLATES 4
#define MAX_RANDOM_TEMPLATES 6






private int me; // player for this instance.
private int me; // player for this instance.
public int tileExpand; // rate of exploration
public int tileExpand; // rate of exploration


public int numScouts[TECHS],maxScouts[TECHS]; // aim for...
public int numScouts[TECHS],maxScouts[TECHS]; // aim for...
public int numDefenders[TECHS],maxDefenders[TECHS];
public int numDefenders[TECHS],maxDefenders[TECHS];
public int numAttackers[TECHS],maxAttackers[TECHS];
public int numAttackers[TECHS],maxAttackers[TECHS];
public int numCyborgs[TECHS],maxCyborgs[TECHS];
public int numCyborgs[TECHS],maxCyborgs[TECHS];


public int branchDefault,branchVTOL,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS],
public int branchDefault,branchVTOL,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS],
maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS];
maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS];
public RESEARCHSTAT tech[TECHS][30]; //technology for different research branches
public RESEARCHSTAT tech[TECHS][30]; //technology for different research branches
public STRUCTURESTAT vtolTarget[10],rebuildStat[TECHS][2];
public STRUCTURESTAT vtolTarget[10],rebuildStat[TECHS][2];


// structures
// structures
private int baseX,baseY,minx,miny,maxx,maxy;
private int baseX,baseY,minx,miny,maxx,maxy;
public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs,numFundamental;
public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs,numFundamental;
private STRUCTURESTAT structChoice[5];
private STRUCTURESTAT structChoice[5];
public STRUCTURESTAT incendrys[8],structs[13],defStructs[26],extraStructs[TECHS][6],wallWeaps[11];
public STRUCTURESTAT incendrys[10],structs[13],defStructs[26],extraStructs[TECHS][6],wallWeaps[11];
public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory,
public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,cybFactory,
vtolDefStruct[5],vtolPad,vtolFactory,uplink,baseStruct[8];
vtolDefStruct[9],vtolPad,vtolFactory,uplink,baseStruct[8];
public STRUCTURESTAT powModule,facModule,resModule,vtolModule;
public STRUCTURESTAT powModule,facModule,resModule,vtolModule;
public int extraStruct;
public int extraStruct;


// unit templates
// unit templates
public int numTemplates[TECHS];
public int numTemplates[TECHS];
public TEMPLATE tmpl[TECHS][70];
public TEMPLATE tmpl[TECHS][70];
private TEMPLATE tmplChoice[5];
private TEMPLATE tmplChoice[67];


public TEMPLATE cybTempl[10],superCyb[4],cybMechanic,cybEngineer,hovertruck;
public TEMPLATE cybTempl[7],superCyb[21],cybMechanic,cybEngineer,hovertruck;


public TEMPLATE vtols[18];
public TEMPLATE vtols[20];
public int numVtolTemplates;
public int numVtolTemplates;


public TEMPLATE sense[11];
public TEMPLATE sense[8];
public int numSenseTemplates;
public int numSenseTemplates;


public TEMPLATE constructor,repair;
public TEMPLATE constructor,repair[7];
public int numRepairUnits;
public int numRepairUnits;
public int numSensorUnits;
public int numRepairTemplates;


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


public RESEARCHSTAT nexusDefence;
public RESEARCHSTAT nexusDefence;
private RESEARCHSTAT research;
private RESEARCHSTAT research;


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


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


// attack
// attack
private GROUP attackGroup;
private GROUP attackGroup;
private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[10];
private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[39];


// vtols
// vtols
private GROUP vtolDefendGr,vtolAttackGr[10];
private GROUP vtolDefendGr,vtolAttackGr[10];


// generic
// generic
private STRUCTURE structure,structure2,rebuildObj[100];
private STRUCTURE structure,structure2,rebuildObj[100];
private DROID droid;
private DROID droid;
private FEATURE feature;
private FEATURE feature;
private BASEOBJ baseobj,baseobj2;
private BASEOBJ baseobj,baseobj2;
private int count,count2,result,result2,tempx,tempy;
private int count,count2,result,result2,tempx,tempy;
private bool boolResult,boolResult2;
private bool boolResult,boolResult2;


private bool powerSave,_DEBUG,bRunning;
private bool powerSave,_DEBUG,bRunning;
// Hopefully this will be at least as large as MAX_PLAYERS... Why can't I just use MAX_PLAYERS as the array size?!
// Hopefully this will be at least as large as MAX_PLAYERS... Why can't I just use MAX_PLAYERS as the array size?!
// P.S. And why can't I put a comment on the same line as a #define??!! Gah, who cares if the lua2 branch works, lets switch to it, anyway.
// P.S. And why can't I put a comment on the same line as a #define??!! Gah, who cares if the lua2 branch works, lets switch to it, anyway.
#define MAX_PLAYERS_HACK 17
#define MAX_PLAYERS_HACK 17
private int allianceTime[MAX_PLAYERS_HACK];
private int allianceTime[MAX_PLAYERS_HACK];
private int sender,x,y,beaconX[8],beaconY[8],tBeacon[8],
private int sender,x,y,beaconX[8],beaconY[8],tBeacon[8],
tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY;
tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY;
private string message;
private string message;


private int defendX,defendY,__defendRadiusUnused,tDefendStart,tDefendTimeout,
private int defendX,defendY,__defendRadiusUnused,tDefendStart,tDefendTimeout,
defendMoveType,baseRange,curTech,numVtolAttackGroups,numAttackVtols,
defendMoveType,baseRange,curTech,numVtolAttackGroups,numAttackVtols,
numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct;
numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct;
private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT];
private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT];


private STRUCTURESTAT fundamentalBeingBuilt;
private STRUCTURESTAT fundamentalBeingBuilt;
private int order; // callback global
private int order; // callback global


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


#region triggers
#region triggers
trigger reachedTr (CALL_DROID_REACH_LOCATION, me, ref droid, ref order);
trigger reachedTr (CALL_DROID_REACH_LOCATION, me, ref droid, ref order);
trigger buildExpandTr (every, 600);
trigger buildExpandTr (every, 300);
trigger fortifyTr (every, 1000);
trigger fortifyTr (every, 400);
trigger upgradeStructuresTr (every, 360);
trigger upgradeStructuresTr (every, 50);
trigger conDroidsTr (every, 900); // was 1400
trigger conDroidsTr (every, 200); // was 1400
trigger repairDroidsTr (every, 2600);
trigger repairDroidsTr (every, 400);
trigger sensorDroidsTr (every, 400);
trigger basedetailsTr (every, 600 );
trigger basedetailsTr (every, 600 );
trigger buildDerrickTr (every, 80 );
trigger buildDerrickTr (every, 80 );
trigger buildOilDefenseOrRetreatTr (every, 120 );
trigger buildOilDefenseOrRetreatTr (every, 200 );
trigger incendryTr (every, 250 );
trigger incendryTr (every, 120 );
trigger buildPowerGeneratorsTr (every, 80 );
trigger buildPowerGeneratorsTr (every, 80 );
trigger buildBaseTr (every, 150 );
trigger buildBaseTr (every, 150 );
trigger finishStructsTr (every, 210);
trigger finishStructsTr (every, 210);
trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure);
trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure);
trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure);
trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure);
trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid);
trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid);
trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure);
trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure);
trigger rebuildStructureTr (every, 50);
trigger rebuildStructureTr (every, 50);
trigger consolidateEventTr (every, 3100);
trigger consolidateEventTr (every, 3100);
trigger factoryEventTr (every, 170 );
trigger factoryEventTr (every, 90 );
trigger cyborgFactoryEventTr (every, 170 );
trigger cyborgFactoryEventTr (every, 90 );
trigger chooseScoutAreaTr (every, 200 );
trigger chooseScoutAreaTr (every, 200 );
trigger expandScoutAreaTr (every, 600 );
trigger expandScoutAreaTr (every, 600 );
trigger scoutMainTr (every, 150 );
trigger scoutMainTr (every, 150 );
trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2);
trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2);
trigger attackStuffTr (every, 300 );
trigger attackStuffTr (every, 200 );
trigger allOutAttackTr (every, 4000);
trigger allOutAttackTr (every, 2000);
trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger defendReturnTr (every, 500 );
trigger defendReturnTr (every, 100000 );
trigger doResearchTr (CALL_RESEARCHCOMPLETED, ref research, ref structure, me);
trigger doResearchTr (CALL_RESEARCHCOMPLETED, ref research, ref structure, me);
trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger vtolStructsTr (every, 290);
trigger vtolStructsTr (every, 600);
trigger buildVtolsTr (every, 360);
trigger buildVtolsTr (every, 180);
trigger vtolAttackTr (every, 150);
trigger vtolAttackTr (every, 10);
trigger vtolEnablerTr (every, 700);
trigger vtolEnablerTr (every, 700);
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
trigger useLassatTr (every, 3000);
trigger useLassatTr (every, 3000);
trigger reassignTr (CALL_PLAYERLEFT,ref count);
trigger reassignTr (CALL_PLAYERLEFT,ref count);
trigger formAllianceEventTr (every,170);
trigger formAllianceEventTr (every,170);
trigger breakAllianceEventTr (every,3000);
trigger breakAllianceEventTr (every,3000);
trigger difficultyModifierTr (every,600);
trigger difficultyModifierTr (every,600);
trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2);
trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2);
trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message);
trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message);
trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message);
trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message);
trigger consoleTr (CALL_CONSOLE, ref sender, ref message);
trigger consoleTr (CALL_CONSOLE, ref sender, ref message);
trigger watchBaseThreatTr (every, 120);
trigger watchBaseThreatTr (every, 120);
trigger manageAllyHelpTr (every, 80);
trigger manageAllyHelpTr (every, 80);
trigger everySec (every, 10);
trigger everySec (every, 10);
trigger manageDefendLocationTr (every, 70);
trigger manageDefendLocationTr (every, 70);
trigger startLevelTr (CALL_START_NEXT_LEVEL);
trigger startLevelTr (CALL_START_NEXT_LEVEL);
trigger chainloadTr (wait, 1);
trigger chainloadTr (wait, 1);
trigger slowloadTr (wait, 13);
trigger slowloadTr (wait, 13);
trigger checkResearchTr (every, 400);
trigger checkResearchTr (every, 50);


/* Events */
/* Events */
event conDroids;
event conDroids;
event multiMsgEv;
event multiMsgEv;
event beaconEv;
event beaconEv;
event watchBaseThreat;
event watchBaseThreat;
event manageAllyHelp;
event manageAllyHelp;
event everySecEv;
event everySecEv;
event manageDefendLocationEv;
event manageDefendLocationEv;
event structureDestroyed;
event structureDestroyed;
event rebuildStructureEv;
event rebuildStructureEv;
event doResearch;
event doResearch;
event buildDerrick;
event buildDerrick;


/* Function prototypes */
/* Function prototypes */
function bool haveBeacon(int _player);
function bool haveBeacon(int _player);
function bool beaconTimeout(int _player);
function bool beaconTimeout(int _player);
function void processCommand(string _message, int _sender, bool _bBlipMessage);
function void processCommand(string _message, int _sender, bool _bBlipMessage);
function bool haveHelpers();
function bool haveHelpers();
function bool attemptToHelp(int _playerToHelp, int _x, int _y);
function bool attemptToHelp(int _playerToHelp, int _x, int _y);
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY);
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY);
function bool canStopHelpingAlly();
function bool canStopHelpingAlly();
function void stopHelpingAlly();
function void stopHelpingAlly();
function bool helpingAlly();
function bool helpingAlly();
function bool helpAllyTimeout();
function bool helpAllyTimeout();
function void requestHelp(int _helpX, int _helpY);
function void requestHelp(int _helpX, int _helpY);
function void doRequestHelp(int _helpX, int _helpY);
function void doRequestHelp(int _helpX, int _helpY);
function bool allyBaseAtLoc(int _ally, int _x, int _y);
function bool allyBaseAtLoc(int _ally, int _x, int _y);
function void messagePlayer(int _playerToMessage, string _message, int _probability);
function void messagePlayer(int _playerToMessage, string _message, int _probability);
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message);
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message);
function bool canSeeAllies();
function bool canSeeAllies();
function bool baseInTrouble();
function bool baseInTrouble();
function string m_affirmative();
function string m_affirmative();
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove);
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove);
function void stopDefendingLocation();
function void stopDefendingLocation();
function bool defendingLocation();
function bool defendingLocation();
function bool defendLocationTimeout();
function bool defendLocationTimeout();
function bool friendlyPlayer(int _playerToCheck);
function bool friendlyPlayer(int _playerToCheck);
function void factoryBuildDroid(STRUCTURE _factory);
function void factoryBuildDroid(STRUCTURE _factory);
function void cybFactorBuildCyborg(STRUCTURE _factory);
function void cybFactorBuildCyborg(STRUCTURE _factory);
function void vtolFactoryBuildVtol(STRUCTURE _factory);
function void vtolFactoryBuildVtol(STRUCTURE _factory);
function bool insideBase(int _x, int _y);
function bool insideBase(int _x, int _y);
function int numAlliesInBase(bool _bVtols);
function int numAlliesInBase(bool _bVtols);
function int numEnemiesInBase(bool _bVtols);
function int numEnemiesInBase(bool _bVtols);
function bool defendingOwnBase();
function bool defendingOwnBase();
function int targetTypeValue(BASEOBJ _target);
function int targetTypeValue(BASEOBJ _target);
function int numBitsSet(int _integer);
function int numBitsSet(int _integer);
function int findResearch(int _searchStart, int _techTree);
function int findResearch(int _searchStart, int _techTree);
function bool upgradeFactory(DROID _truck, int _maxBuilders);
function bool upgradeFactory(DROID _truck, int _maxBuilders);
function bool upgradeVtolFactory(DROID _truck, int _maxBuilders);
function bool upgradeVtolFactory(DROID _truck, int _maxBuilders);
function bool upgradeResearch(DROID _truck, int _maxBuilders);
function bool upgradeResearch(DROID _truck, int _maxBuilders);
function bool upgradePowGen(DROID _truck, int _maxBuilders);
function bool upgradePowGen(DROID _truck, int _maxBuilders);
function void buildRearmPads();
function void buildRearmPads();
function int numEnemyAAInRange(int _x, int _y, int _range);
function int numEnemyAAInRange(int _x, int _y, int _range);
function BASEOBJ chooseVtolTarget(bool bExclusiveTarget);
function BASEOBJ chooseVtolTarget(bool bExclusiveTarget);
function int getVtolTargetWeight(BASEOBJ _target);
function int getVtolTargetWeight(BASEOBJ _target);
function bool vtolTargetAssigned(BASEOBJ _target);
function bool vtolTargetAssigned(BASEOBJ _target);
function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y);
function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y);
function int totalVtols();
function int totalVtols();
function bool needTank();
function bool needTank();
function void setTechBranch(int _tech);
function void setTechBranch(int _tech);
function DROID closestIdleTruck(int _x, int _y);
function DROID closestIdleTruck(int _x, int _y);
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat);
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat);
function void rebuildStructures();
function void rebuildStructures();
function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget);
function BASEOBJ chooseVtolDefenceTarget(int _x, int _y, int _range, bool bExclusiveTarget);
function int numGroupSameOrder(GROUP _group, int _orderIndex);
function int numGroupSameOrder(GROUP _group, int _orderIndex);
function void rearrangeAttackVtols();
function void rearrangeAttackVtols();
function int numStructBusyByType(STRUCTURESTAT _busyStructType);
function int numStructBusyByType(STRUCTURESTAT _busyStructType);
function bool aiResponsibleForPlayer(int _player);
function bool aiResponsibleForPlayer(int _player);
function void reassignAI();
function void reassignAI();
function void shutDownAI();
function void shutDownAI();
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly);
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly);
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly);
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly);
#endregion triggers
#endregion triggers


/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// HouseKeeping
// HouseKeeping
event initialisedEvent(CALL_GAMEINIT)
event initialisedEvent(CALL_GAMEINIT)
{
{
local int player;
local int player;
// initialise
// initialise
me = getPlayer("Nexus");
me = getPlayer("Nexus");
_DEBUG = FALSE;
_DEBUG = FALSE;
dbgMsgOn(me, _DEBUG);
dbgMsgOn(me, _DEBUG);


extraStruct = 0;
extraStruct = 0;
numRepairUnits = 0;
numRepairUnits = 0;
numSensorUnits = 0;
allOutAttack = NULLOBJECT;
allOutAttack = NULLOBJECT;


tLastHelpRequest = -1; //when we requested help for the last time
tLastHelpRequest = -1; //when we requested help for the last time
lastHelpPlayer = -1; //we are not currently helping anyone
lastHelpPlayer = -1; //we are not currently helping anyone
tHelp = -1; //when we started helping last time
tHelp = -1; //when we started helping last time
tHelpTimeout = -1; //time when help times out
tHelpTimeout = -1; //time when help times out
helpX = -1;
helpX = -1;
helpY = -1;
helpY = -1;
defendX = -1;
defendX = -1;
defendY = -1;
defendY = -1;
tDefendStart = -1;
tDefendStart = -1;
tDefendTimeout = -1;
tDefendTimeout = -1;
defendMoveType = -1; //move or scout
defendMoveType = -1; //move or scout


baseRange = 4 * TILE;
baseRange = 4 * TILE;


// set current research branch
// set current research branch
setTechBranch(-1);
setTechBranch(-1);


numVtolAttackGroups = 10;
numVtolAttackGroups = 10;
numAttackVtols = 10; //num vtols in an attack group
numAttackVtols = 10; //num vtols in an attack group
numDefendVtols = 5; //num vtols in an attack group
numDefendVtols = 5; //num vtols in an attack group


// setup build group - all initial droids are in buildgroup!
// setup build group - all initial droids are in buildgroup!
groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128));
groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128));


// note where our base is.
// note where our base is.
getPlayerStartPosition(me, ref baseX, ref baseY);
getPlayerStartPosition(me, ref baseX, ref baseY);


// defence.
// defence.
defendbusy = FALSE;
defendbusy = FALSE;


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


// clear the alliance array...
// clear the alliance array...
player = 0;
player = 0;
while (player != MAX_PLAYERS)
while (player != MAX_PLAYERS)
{
{
allianceTime[player] = 0;
allianceTime[player] = 0;
player = player + 1;
player = player + 1;
}
}


fundamentalBeingBuilt = derrick; // to avoid ever being null
fundamentalBeingBuilt = derrick; // to avoid ever being null
if(aiResponsibleForPlayer(me))
if(aiResponsibleForPlayer(me))
{
{
bRunning = true;
bRunning = true;
}
}
else
else
{
{
bRunning = false;
bRunning = false;
shutDownAI();
shutDownAI();
}
}
}
}


// check whether we have at least one structure of that type
// check whether we have at least one structure of that type
function bool haveStructure(STRUCTURESTAT type)
function bool haveStructure(STRUCTURESTAT type)
{
{
return getStructure(type, me) != NULLOBJECT;
return getStructure(type, me) != NULLOBJECT;
}
}


// check if we are getting any income
// check if we are getting any income
function bool havePowerSource()
function bool havePowerSource()
{
{
// we don't check buildings being finished here
// we don't check buildings being finished here
return haveStructure(powGen) and haveStructure(derrick);
return haveStructure(powGen) and haveStructure(derrick);
}
}


// I am not sure why we need this hack, but the AI can still end up not researching anything at times
// I am not sure why we need this hack, but the AI can still end up not researching anything at times
event checkResearch(checkResearchTr)
event checkResearch(checkResearchTr)
{
{
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
}
}


function void dbgPlr(string message)
function void dbgPlr(string message)
{
{
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
if (me == selectedPlayer)
if (me == selectedPlayer)
{
{
console(message);
console(message);
}
}
}
}


function void dbgObj(DROID obj, string message)
function void dbgObj(DROID obj, string message)
{
{
if (obj.selected)
if (obj.selected)
{
{
console(message);
console(message);
}
}
}
}


function bool conCanHelp(DROID mydroid, int bx, int by)
function bool conCanHelp(DROID mydroid, int bx, int by)
{
{
return (mydroid.order != DORDER_HELPBUILD and mydroid.order != DORDER_BUILD and mydroid.order != DORDER_LINEBUILD and droidCanReach(mydroid, bx, by));
return (mydroid.order != DORDER_HELPBUILD and mydroid.order != DORDER_BUILD and mydroid.order != DORDER_LINEBUILD and droidCanReach(mydroid, bx, by));
}
}


// Build something in main base, grab trucks to do it within tiles range
// Build something in main base, grab trucks to do it within tiles range
function bool grabTrucksAndBuild(int range, STRUCTURESTAT bstats, int maxBlockingTiles)
function bool grabTrucksAndBuild(int range, STRUCTURESTAT bstats, int maxBlockingTiles)
{
{
local DROID mydroid, closestDroid;
local DROID mydroid, closestDroid;
local int closestDist, currDist, numHelpDroids, tilerange, bx, by;
local int closestDist, currDist, numHelpDroids, tilerange, bx, by;


initIterateGroup(buildGroup); // find idle droids in build group.
initIterateGroup(buildGroup); // find idle droids in build group.
mydroid = iterateGroup(buildGroup);
mydroid = iterateGroup(buildGroup);
closestDist = 99999;
closestDist = 99999;
closestDroid = NULLOBJECT;
closestDroid = NULLOBJECT;
numHelpDroids = 0;
numHelpDroids = 0;
tilerange = range * TILE;
tilerange = range * TILE;
while (mydroid != NULLOBJECT)
while (mydroid != NULLOBJECT)
{
{
if (conCanHelp(mydroid, baseX, baseY))
if (conCanHelp(mydroid, baseX, baseY))
{
{
bx = baseX;
bx = baseX;
by = baseY;
by = baseY;
if (pickDroidStructLocation(mydroid, bstats, ref bx, ref by, me, maxBlockingTiles))
if (pickDroidStructLocation(mydroid, bstats, ref bx, ref by, me, maxBlockingTiles))
{
{
currDist = distBetweenTwoPoints(bx, by, mydroid.x, mydroid.y);
currDist = distBetweenTwoPoints(bx, by, mydroid.x, mydroid.y);
if (currDist < tilerange)
if (currDist < tilerange)
{
{
orderDroidStatsLoc(mydroid, DORDER_BUILD, bstats, bx, by); // close, so help build it
orderDroidStatsLoc(mydroid, DORDER_BUILD, bstats, bx, by); // close, so help build it
numHelpDroids = numHelpDroids + 1;
numHelpDroids = numHelpDroids + 1;
}
}
else if (currDist < closestDist)
else if (currDist < closestDist)
{
{
closestDroid = mydroid; // record this droid as being closest so far
closestDroid = mydroid; // record this droid as being closest so far
closestDist = currDist;
closestDist = currDist;
}
}
}
}
}
}
mydroid = iterateGroup(buildGroup);
mydroid = iterateGroup(buildGroup);
}
}
if (numHelpDroids == 0 and closestDroid != NULLOBJECT) // found none within help radius, so force someone to go long distance traveling
if (numHelpDroids == 0 and closestDroid != NULLOBJECT) // found none within help radius, so force someone to go long distance traveling
{
{
orderDroidStatsLoc(closestDroid, DORDER_BUILD, bstats, bx, by); // you, book a plane ticket and go!
orderDroidStatsLoc(closestDroid, DORDER_BUILD, bstats, bx, by); // you, book a plane ticket and go!
return true;
return true;
}
}
return (numHelpDroids > 0);
return (numHelpDroids > 0);
}
}


event arrived(reachedTr)
event arrived(reachedTr)
{
{
local bool found;
local bool found;
local STRUCTURESTAT myChoice;
local STRUCTURESTAT myChoice;


if (droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT)
if (droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT)
{
{
dbgObj(droid, "Failed to build where we should - attempt to screw up enemy oil derrick");
dbgObj(droid, "Failed to build where we should - attempt to screw up enemy oil derrick");


// Check if at oil well, and it was taken by enemy
// Check if at oil well, and it was taken by enemy
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5 * 128), -1);
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5 * 128), -1);
if (structure != NULLOBJECT)
if (structure != NULLOBJECT)
{
{
if (not friendlyPlayer(structure.player) and droid.health == 100)
if (not friendlyPlayer(structure.player) and droid.health == 100)
{
{
// Ok, at enemy derrick, and nobody has hurt us yet. Start being nasty.
// Ok, at enemy derrick, and nobody has hurt us yet. Start being nasty.
count = 0;
count = 0;
found = false;
found = false;
// find simplest/cheapest one available to build
// find simplest/cheapest one available to build
while (count < numDefStructs and not found)
while (count < numDefStructs and not found)
{
{
if (isStructureAvailable(defStructs[count], me))
if (isStructureAvailable(defStructs[count], me))
{
{
found = true;
found = true;
}
}
else
else
{
{
count++;
count++;
}
}
}
}
if (found)
if (found)
{
{
buildX = droid.x;
buildX = droid.x;
buildY = droid.y;
buildY = droid.y;
if (pickDroidStructLocation(droid, defStructs[count], ref buildX, ref buildY, me, -1))
if (pickDroidStructLocation(droid, defStructs[count], ref buildX, ref buildY, me, -1))
{
{
orderDroidStatsLoc(droid, DORDER_BUILD, defStructs[count], buildX, buildY);
orderDroidStatsLoc(droid, DORDER_BUILD, defStructs[count], buildX, buildY);
}
}
else
else
{
{
dbgObj(droid, "Wanted to be nasty, but found nowhere to build defense");
dbgObj(droid, "Wanted to be nasty, but found nowhere to build defense");
orderDroid(droid, DORDER_RTB); // nothing more to do here.
orderDroid(droid, DORDER_RTB); // nothing more to do here.
}
}
}
}
else
else
{
{
dbgObj(droid, "Wanted to be nasty, but had nothing nasty to build - returning to base");
dbgObj(droid, "Wanted to be nasty, but had nothing nasty to build - returning to base");
orderDroid(droid, DORDER_RTB); // oh, well. nothing more to do here.
orderDroid(droid, DORDER_RTB); // oh, well. nothing more to do here.
}
}
exit;
exit;
}
}
else if (droid.health < 100 and !insideBase(droid.x, droid.y))
else if (droid.health < 100 and !insideBase(droid.x, droid.y))
{
{
orderDroid(droid, DORDER_RTR); // bolt back to base now!
orderDroid(droid, DORDER_RTR); // bolt back to base now!
exit;
exit;
}
}
}
}
}
}
}
}


event buildFundamentals(inactive)
event buildFundamentals(inactive)
{
{
count = 0;
count = 0;
while (count < numFundamental)
while (count < numFundamental)
{
{
// check that struct.
// check that struct.
structure = getStructure(structs[count], me);
structure = getStructure(structs[count], me);
if (structure == NULLOBJECT) // if missing build it.
if (structure == NULLOBJECT) // if missing build it.
{
{
if (isStructureAvailable(structs[count], me))
if (isStructureAvailable(structs[count], me))
{
{
if (grabTrucksAndBuild(12, structs[count], 0))
if (grabTrucksAndBuild(12, structs[count], 0))
{
{
exit; // no need to check more
exit; // no need to check more
}
}
}
}
}
}
count = count + 1;
count = count + 1;
}
}
fundamentalBeingBuilt = derrick;
fundamentalBeingBuilt = derrick;
setEventTrigger(buildFundamentals, inactive);
setEventTrigger(buildFundamentals, inactive);
}
}


event startLevel(startLevelTr)
event startLevel(startLevelTr)
{
{
setEventTrigger(buildFundamentals, slowloadTr);
setEventTrigger(buildFundamentals, slowloadTr);
setEventTrigger(conDroids, chainloadTr);
setEventTrigger(conDroids, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(buildDerrick, slowloadTr);
setEventTrigger(buildDerrick, slowloadTr);
setEventTrigger(startLevel, inactive);
setEventTrigger(startLevel, inactive);
}
}


// decide what technology branch we will use
// decide what technology branch we will use
function void setTechBranch(int _tech)
function void setTechBranch(int _tech)
{
{
local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize;
local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd,_mapSize;


_mapSize = (float)((mapWidth + mapHeight) / 2);
_mapSize = (float)((mapWidth + mapHeight) / 2);


if(_tech != -1)
if(_tech != -1)
{
{
curTech = _tech;
curTech = _tech;
}
}
else
else
{
{
//probability to choose vtol branch for map size 90 = 0; probability for map size 200 = 45
//probability to choose vtol branch for map size 90 = 0; probability for map size 200 = 45
//build a linear function: y = ((y2 - y1) / (x2 - x1)) * x + a depending on two values given (short: y = mx+a)
//build a linear function: y = ((y2 - y1) / (x2 - x1)) * x + a depending on two values given (short: y = mx+a)
_x1 = 90.0; _y1 = 0.0;
_x1 = 90.0; _y1 = 0.0;
_x2 = 200.0; _y2 = 45.0;
_x2 = 200.0; _y2 = 45.0;
_m = ((_y2 - _y1) / (_x2 - _x1));
_m = ((_y2 - _y1) / (_x2 - _x1));
_a = -(_m * _x1);
_a = -(_m * _x1);


//calculate probability for the current map
//calculate probability for the current map
_y = _m * _mapSize + _a;
_y = _m * _mapSize + _a;


dbg("_m = " & _m & ", a = " & _a, me);
dbg("_m = " & _m & ", a = " & _a, me);


_rnd = (float)random(100);
_rnd = (float)random(100);
if(_rnd < _y)
if(_rnd < _y)
{
{
curTech = branchVTOL;
curTech = branchVTOL;
dbg("going air (" & _y & "/" & _rnd & ")", me);
dbg("going air (" & _y & "/" & _rnd & ")", me);
}
}
else
else
{
{
curTech = branchDefault;
curTech = branchDefault;
dbg("going land (" & _y & "/" & _rnd & ")", me);
dbg("going land (" & _y & "/" & _rnd & ")", me);
}
}
}
}
}
}


/* returns TRUE if AI is responsible for the _player */
/* returns TRUE if AI is responsible for the _player */
function bool aiResponsibleForPlayer(int _player)
function bool aiResponsibleForPlayer(int _player)
{
{
if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player)))
if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player)))
{
{
return FALSE;
return FALSE;
}
}


return TRUE;
return TRUE;
}
}


/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// keep details about the size and postion of the ai players base
// keep details about the size and postion of the ai players base
event basedetails(basedetailsTr)
event basedetails(basedetailsTr)
{
{
// clear old extremities.
// clear old extremities.
maxy = 0;
maxy = 0;
maxx = 0;
maxx = 0;
miny = (mapHeight*128);
miny = (mapHeight*128);
minx = (mapWidth*128);
minx = (mapWidth*128);


baseRange = 4 * TILE;
baseRange = 4 * TILE;


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


result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);
result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);


if(result > baseRange){
if(result > baseRange){
baseRange = result;
baseRange = result;
}
}


structure= enumStruct();
structure= enumStruct();
}
}


count = count + 1;
count = count + 1;
}
}


result = 3 * 128;
result = 3 * 128;
minx = minx - result;
minx = minx - result;
maxx = maxx + result;
maxx = maxx + result;
miny = miny - result;
miny = miny - result;
maxy = maxy + result;
maxy = maxy + result;


baseRange = baseRange + (4 * 128);
baseRange = baseRange + (4 * 128);
}
}


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


// build derricks on oil.
// build derricks on oil.
event buildDerrick(buildDerrickTr)
event buildDerrick(buildDerrickTr)
{
{
local bool foundOne, _same;
local bool foundOne, _same;
local FEATURE _oil, _closestOil;
local FEATURE _oil, _closestOil;
local int _bestDist, _newDist;
local int _bestDist, _newDist;
local DROID _search;
local DROID _search;


// what if we can't waste power on building derricks because we don't have a gen yet?
// what if we can't waste power on building derricks because we don't have a gen yet?
if (playerPower(me) < 300 and haveStructure(derrick) and not haveStructure(powGen))
if (playerPower(me) < 300 and haveStructure(derrick) and not haveStructure(powGen))
{
{
setEventTrigger(buildDerrick, slowloadTr);
setEventTrigger(buildDerrick, slowloadTr);
exit;
exit;
}
}


_bestDist = 99999;
_bestDist = 99999;
_closestOil = NULLOBJECT;
_closestOil = NULLOBJECT;
foundOne = false;
foundOne = false;
initIterateGroup(buildGroup); // find all units in build group
initIterateGroup(buildGroup); // find all units in build group
droid = iterateGroup(buildGroup);
droid = iterateGroup(buildGroup);
while (droid != NULLOBJECT && !foundOne)
while (droid != NULLOBJECT && !foundOne)
{
{
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
{
{
foundOne = true;
foundOne = true;
}
}
else
else
{
{
droid = iterateGroup(buildGroup);
droid = iterateGroup(buildGroup);
}
}
}
}
if (droid != NULLOBJECT)
if (droid != NULLOBJECT)
{
{
initGetFeature(oilRes, -1, me);
initGetFeature(oilRes, -1, me);
_oil = getFeatureB(me);
_oil = getFeatureB(me);
while (_oil != NULLOBJECT)
while (_oil != NULLOBJECT)
{
{
_newDist = distBetweenTwoPoints(droid.x, droid.y, _oil.x, _oil.y);
_newDist = distBetweenTwoPoints(droid.x, droid.y, _oil.x, _oil.y);
_same = false;
_same = false;


if (_newDist < _bestDist and droidCanReach(droid, _oil.x, _oil.y)) // this one is closer
if (_newDist < _bestDist and droidCanReach(droid, _oil.x, _oil.y)) // this one is closer
{
{
if (!threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE))
if (!threatInRange(me, _oil.x, _oil.y, OIL_THREAT_RANGE, FALSE))
{
{
initIterateGroup(buildGroup); // find all units in build group.
initIterateGroup(buildGroup); // find all units in build group.
_search = iterateGroup(buildGroup);
_search = iterateGroup(buildGroup);
foundOne = false;
foundOne = false;
while (_search != NULLOBJECT && !foundOne)
while (_search != NULLOBJECT && !foundOne)
{
{
if (_search.orderx == _oil.x and _search.ordery == _oil.y and _search != droid)
if (_search.orderx == _oil.x and _search.ordery == _oil.y and _search != droid)
{
{
_same = true;
_same = true;
foundOne = true;
foundOne = true;
}
}
_search = iterateGroup(buildGroup);
_search = iterateGroup(buildGroup);
}
}
if (!_same) // do not go to same spot as another droid
if (!_same) // do not go to same spot as another droid
{
{
_bestDist = _newDist;
_bestDist = _newDist;
_closestOil = _oil;
_closestOil = _oil;
}
}
}
}
}
}
_oil = getFeatureB(me);
_oil = getFeatureB(me);
}
}
if (_closestOil != NULLOBJECT)
if (_closestOil != NULLOBJECT)
{
{
orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _closestOil.x, _closestOil.y); // build a derick
orderDroidStatsLoc(droid, DORDER_BUILD, derrick, _closestOil.x, _closestOil.y); // build a derick
if (idleGroup(buildGroup) > 0)
if (idleGroup(buildGroup) > 0)
{
{
setEventTrigger(buildDerrick, slowloadTr); // do it again for next droid
setEventTrigger(buildDerrick, slowloadTr); // do it again for next droid
exit;
exit;
}
}
}
}
}
}
setEventTrigger(buildDerrick, buildDerrickTr);
setEventTrigger(buildDerrick, buildDerrickTr);
}
}


/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// if idle and derrick in range and no defense then build defense, else ret to base .
// if idle and derrick in range and no defense then build defense, else ret to base .
event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr)
event buildOilDefenseOrRetreat(buildOilDefenseOrRetreatTr)
{
{
local int _numBuilders,_maxBuilders;
local int _numBuilders,_maxBuilders;


_maxBuilders = 1;
_maxBuilders = 1;


// check idle.
// check idle.
initIterateGroup(buildGroup); // find idle droids in build group.
initIterateGroup(buildGroup); // find idle droids in build group.
droid = iterateGroup(buildGroup);
droid = iterateGroup(buildGroup);
while(droid != NULLOBJECT)
while(droid != NULLOBJECT)
{
{
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
if (droid.order != DORDER_BUILD and droid.order != DORDER_LINEBUILD and droid.order != DORDER_HELPBUILD)
{
{
// if in range of a derrick
// if in range of a derrick
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me);
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5*128), me);


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


if(structure != NULLOBJECT)
if(structure != NULLOBJECT)
{
{
buildX = structure.x;
buildX = structure.x;
buildY = structure.y;
buildY = structure.y;


// not many defenses nearby
// not many defenses nearby
if(numFriendlyWeapStructsInRange(me, buildX, buildY, (3*128), FALSE) < 2)
if(numFriendlyWeapStructsInRange(me, buildX, buildY, (3*128), FALSE) < 2)
{
{
count = numDefStructs - 1; //pick a struct to build..
count = numDefStructs - 1; //pick a struct to build..
count2 = 0;
count2 = 0;
while( (count2 < 5) and (count >= 0) )
while( (count2 < 5) and (count >= 0) )
{
{
if( isStructureAvailable(defStructs[count],me))
if( isStructureAvailable(defStructs[count],me))
{
{
structChoice[count2] = defStructs[count];
structChoice[count2] = defStructs[count];
count2 = count2 + 1;
count2 = count2 + 1;
}
}
count = count - 1;
count = count - 1;
}
}
count =0;
count =0;
if(count2 > 0)
if(count2 > 0)
{
{
count = random(count2); //count = choice!
count = random(count2); //count = choice!


// pick a location
// pick a location
boolResult = pickDroidStructLocation(droid, structChoice[count], ref buildX, ref buildY, me, -1);
boolResult = pickDroidStructLocation(droid, structChoice[count], ref buildX, ref buildY, me, -1);


_numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY);
_numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY);


if((boolResult == TRUE) and (_numBuilders < _maxBuilders) and droidCanReach(droid, buildX, buildY))
if((boolResult == TRUE) and (_numBuilders < _maxBuilders) and droidCanReach(droid, buildX, buildY))
{
{
// build it.
// build it.
orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY);
orderDroidStatsLoc(droid, DORDER_BUILD,structChoice[count], buildX,buildY);
_numBuilders++;
_numBuilders++;
}
}
}
}
}
}
else
else
{
{
structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
if(structure == NULLOBJECT)
if(structure == NULLOBJECT)
{
{
if(!insideBase(droid.x, droid.y))
if(!insideBase(droid.x, droid.y))
{
{
orderDroid(droid,DORDER_RTB); // return to base;
orderDroid(droid,DORDER_RTB); // return to base;
}
}
}
}
}
}
}
}
else
else
{
{
structure = structureBuiltInRange(playerHQ, droid.x, droid.y, (5*128), me);
structure = structureBuiltInRange(playerHQ, dr
if(structure == NULLOBJECT)
{
if(!insideBase(droid.x, droid.y))
{
orderD