Untitled diff

Created Diff never expires
223 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
835 lines
238 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
846 lines
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// 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 1


// 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 20


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


#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 14
#define MIN_TRUCKS 5
#define MIN_TRUCKS 2


//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 1


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


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



// 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 6


//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 4






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 branchRocket,branchVTOL,branchCannon,branchArtillery,branchOneAlly,branchTwoAlly,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][47]; //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[11],structs[16],defStructs[37],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,gderrick,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][100];
private TEMPLATE tmplChoice[5];
private TEMPLATE tmplChoice[100];


public TEMPLATE cybTempl[10],superCyb[4],cybMechanic,cybEngineer,hovertruck;
public TEMPLATE cybTempl[9],superCyb[15],cybMechanic,cybEngineer,hovertruck;


public TEMPLATE vtols[18];
public TEMPLATE vtols[27],vtolAAdroid;
public int numVtolTemplates;
public int numVtolTemplates;


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


public TEMPLATE constructor,repairUnit;
public TEMPLATE constructor,repair[6];
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[10];


// 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, 999999999);
trigger fortifyTr (every, 1000);
trigger fortifyTr (every, 1200);
trigger upgradeStructuresTr (every, 360);
trigger upgradeStructuresTr (every, 40);
trigger conDroidsTr (every, 900); // was 1400
trigger conDroidsTr (every, 400); // was 1400
trigger repairDroidsTr (every, 2600);
trigger repairDroidsTr (every, 500);
trigger sensorDroidsTr (every, 800);
trigger basedetailsTr (every, 600 );
trigger basedetailsTr (every, 600 );
trigger buildDerrickTr (every, 80 );
trigger buildDerrickTr (every, 140 );
trigger buildOilDefenseOrRetreatTr (every, 120 );
trigger buildOilDefenseOrRetreatTr (every, 400 );
trigger incendryTr (every, 250 );
trigger incendryTr (every, 60 );
trigger buildPowerGeneratorsTr (every, 80 );
trigger buildPowerGeneratorsTr (every, 50 );
trigger buildBaseTr (every, 150 );
trigger buildResearchCentersTr (every, 70 );
trigger finishStructsTr (every, 210);
trigger buildFactoryTr (every, 120 );
trigger buildCyborgFactoryTr (every, 150 );
trigger buildVTOLFactoryTr (every, 350 );
trigger buildBaseTr (every, 1800);
trigger finishStructsTr (every, 30);
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 enemyInBaseTr (every, 120);
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, 999999);
trigger factoryEventTr (every, 170 );
trigger factoryEventTr (every, 180 );
trigger cyborgFactoryEventTr (every, 170 );
trigger cyborgFactoryEventTr (every, 120 );
trigger chooseScoutAreaTr (every, 200 );
trigger chooseScoutAreaTr (every, 80 );
trigger expandScoutAreaTr (every, 600 );
trigger expandScoutAreaTr (every, 240 );
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, 100 );
trigger allOutAttackTr (every, 4000);
trigger allOutAttackTr (every, 6000);
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, 185);
trigger buildVtolsTr (every, 360);
trigger buildVtolsTr (every, 360);
trigger vtolAttackTr (every, 150);
trigger vtolAttackTr (every, 75);
trigger vtolEnablerTr (every, 700);
trigger vtolEnablerTr (every, 80);
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
trigger useLassatTr (every, 3000);
trigger useLassatTr (every, 1000);
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 delayedloadTr (wait, 50);
trigger checkResearchTr (every, 100);


/* 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;
event findEnemy;
//event newfortify;
//event incendry;


/* 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 = 1; //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) or haveStructure(gderrick));
}
}


// 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;

local STRUCTURE _structure,_target;
local int _groupIndex,_newTargetWeight,_oldTargetWeight;
local DROID _droid;
local BASEOBJ _newTarget;
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);
_structure = structureBuiltInRange(gderrick, 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;
}
}
}
}
}
}
if (isVtol(droid))
{
//if(droid.order == DORDER_SCOUT and )
//{
// orderDroid(droid, DORDER_RTR);
//}
// if(numEnemyObjInRange(me,droid.x,droid.y,1024,FALSE,TRUE) > 1)
// {
// orderDroid(droid, DORDER_RTR);
// _groupIndex = 0;
// while(_groupIndex < numVtolAttackGroups)
// {
// if(attackObj != NULLOBJECT)
// {
// initIterateGroup(vtolAttackGr[_groupIndex]);
// _droid = iterateGroup(vtolAttackGr[_groupIndex]);
// while(_droid != NULLOBJECT)
// {
// if(!friendlyPlayer(attackObj.player))
// {
// //_target = objToStructure(attackObj);
//
// orderDroidObj(droid, DORDER_ATTACK, attackObj);
//
// }
// _droid = iterateGroup(vtolAttackGr[_groupIndex]);
// }
//
// }
// _groupIndex++;
// }
// }
// else
// {
setDroidSecondary(droid, DSO_PATROL, DSS_PATROL_SET);
// }
// _groupIndex = 0;
// while(_groupIndex < numVtolAttackGroups)
// {
// if(vtolAttackGr[_groupIndex].members > 0)
// {
// _newTarget = NULLOBJECT;
//
// //reset attack targets once in a while
// if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
// {
// if(random(10) > 8)
// {
// vtolGrAttackObj[_groupIndex] = NULLOBJECT;
// }
// }
//
// //now try to find an attack target if we have no defence target
// //find best attack target
// _newTarget = chooseVtolTarget(TRUE); //search for an exclusive target
// if(_newTarget == NULLOBJECT)
// {
// _newTarget = chooseVtolTarget(FALSE); //search for any target
// }
//
// _newTargetWeight = getVtolTargetWeight(_newTarget);
// _oldTargetWeight = getVtolTargetWeight(vtolGrAttackObj[_groupIndex]);
//
// // new one or a much better one
// if((_newTargetWeight >= (_oldTargetWeight + 10)) or
// (vtolGrAttackObj[_groupIndex] == NULLOBJECT ))
// {
// dbg("choosing new attack object for " & _groupIndex, me);
// vtolGrAttackObj[_groupIndex] = _newTarget;
// }
//
//
// if(vtolGrAttackObj[_groupIndex] != NULLOBJECT)
// {
// if(!friendlyPlayer(vtolGrAttackObj[_groupIndex].player))
// {
// if(vtolAttackGr[_groupIndex].members > 0)
// {
// initIterateGroup(vtolAttackGr[_groupIndex]);
// _droid = iterateGroup(vtolAttackGr[_groupIndex]);
// while(_droid != NULLOBJECT)
// {
// if(attackObj != NULLOBJECT) // consolidate any ongoing attack.
// {
// if(!friendlyPlayer(attackObj.player))
// {
// setDroidSecondary(droid, DSO_PATROL, DSS_PATROL_SET);
// orderDroidObj(droid, DORDER_ATTACK,attackObj);
// }
// }
// else
// {
// orderDroid(droid, DORDER_RTB);
// }
//
// _droid = iterateGroup(vtolAttackGr[_groupIndex]);
// }
// }
// }
// }
// }
// _groupIndex++;
// }
}
}
}


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, delayedloadTr);
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;

local int __rnd,_ally,_count;
_mapSize = (float)((mapWidth + mapHeight) / 2);
_mapSize = (float)((mapWidth + mapHeight) / 2);


if(_tech != -1)
if(_tech != -1)
{
{
curTech = _tech;
curTech = _tech;
}
//messagePlayer(ALL_ALLIES, M_REQUEST_HELP, MAX_PROBABILITY);
//messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message);
_ally = 0;
_count = 0;
while(_ally < MAX_PLAYERS)
{
if(allianceExistsBetween(me, _ally)){
_count++;
}
_ally++;
}

if(_count > 0 and multiPlayerAlliancesType == ALLIANCES_TEAMS)
{
if(_mapSize < 150.0)
{
curTech = branchOneAlly;
messagePlayerAddressed(0, 1, "Branch One Reporting");
Text moved with changes from lines 699-702 (92.5% similarity)
}
else
{
curTech = branchTwoAlly;
messagePlayerAddressed(1, 0, "Branch Two Reporting");
}
if(_count > 4)
{
maxIdleRes[curTech] = -1;
}
}
}
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 = 55
//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 = 55.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;
__rnd = random(10);
dbg("going air (" & _y & "/" & _rnd & ")", me);
if(__rnd < 5)
{
curTech = branchVTOL;
dbg("going air (" & _y & "/" & _rnd & ")", me);
Text moved from lines 827-829
}
else
{
curTech = branchArtillery;
dbg("going air (" & _y & "/" & _rnd & ")", me);
}
}
}
else
else
{
{
curTech = branchDefault;
__rnd = random(10);
dbg("going land (" & _y & "/" & _rnd & ")", me);
if(__rnd < 5)
{
curTech = branchRocket;
dbg("going rockets (" & _y & "/" & _rnd & ")", me);
}
else
{
curTech = branchCannon;
dbg("going cannons (" & _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

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

// 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))
{
setEventTrigger(buildDerrick, slowloadTr);
exit;
}

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

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

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

_maxBuilders = 1;

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

// 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;

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

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

_numBuilders = numBuildSameBuilding(NULLSTRUCTURESTAT, buildX, buildY);


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