-
Notifications
You must be signed in to change notification settings - Fork 3
/
nexus.slo
5257 lines (4585 loc) · 132 KB
/
nexus.slo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/////////////////////////////////////////////////////////////////////
// general ai for skirmish game
/////////////////////////////////////////////////////////////////////
// Warzone2100, Pumpkin Studios,
// alex lee.98/99.
//
/////////////////////////////////////////////////////////////////////
//Tile in world units
#define TILE 128
#define NONE (-1)
// These are final rules of the lexical parser
#define R_REQUEST_HELP "help me"
#define R_REQUEST_BEACON "drop a beacon"
#define R_REPORT_SAFETY "i'm ok"
#define R_REQUEST_ALLY "ally me"
// These are our own messages - lexical parser should be able to handle them
#define M_REQUEST_HELP "help me!!"
#define M_REQUEST_BEACON "drop a beacon"
#define M_AFFIRMATIVE_OK "ok"
#define M_AFFIRMATIVE_ROGER "roger"
#define M_ANNOYED "bug off"
#define M_HELPERS_KILLED "that was all I had.."
#define M_HELP_NO_UNITS "I don't have anything"
#define MAX_PROBABILITY 100
// Base threat range in world units
#define W_BASE_THREAT_RANGE ((17 + (mapWidth + mapHeight) / 2 / 35) * TILE)
#define ALL_ALLIES -1
#define BASE_DEFEND_DURATION 60
// Delay before we repeat our request, in seconds
#define HELP_REQUEST_INTERVAL 50
//in secs
#define BEACON_TIMEOUT 40
#define MAX_DROIDS 150
//range for trucks to look for more oil
#define MORE_OIL_RANGE (10 * TILE)
//don't try to build on oil if there's threat within this range
#define OIL_THREAT_RANGE (9 * TILE)
#define MAX_TRUCKS 14
#define MIN_TRUCKS 3
//Target type values
#define NO_TARGET_VALUE 0
#define DROID_TARGET_VALUE 1
#define OTHER_TARGET_VALUE 2
#define DEFENSE_TARGET_VALUE 3
#define RESEARCH_TARGET_VALUE 4
#define HQ_TARGET_VALUE 5
#define OIL_TARGET_VALUE 6
#define FACTORY_TARGET_VALUE 7
#define UNLIMITED (-1)
#define AA_THREAT_RANGE 1
#define MAX_DEFENDERS_RADIUS (TILE * 50)
#define MAX_VTOL_DEFEND_RADIUS (TILE * 250)
#define MIN_BUILDPOWER_CYBFACTORY 25
#define MIN_BUILDPOWER_FACTORY 400
#define MIN_BUILDPOWER_RESCENTER 250
#define MIN_BUILDPOWER_VTOLFACTORY 200
#define MIN_PRODUCTIONPOWER_FACTORY 25
#define MIN_PRODUCTIONPOWER_CYBFACTORY 10
#define MIN_PRODUCTIONPOWER_VTOLFACTORY 100
#define MIN_PRODUCTIONPOWER_TRUCK 50
#define MIN_BUILDPOWER_DEFENSE 200
#define MIN_BUILDPOWER_EXTRASTRUCTS 200
#define MIN_BUILDPOWER_ARTILLERY 0
// AI will remember max this number of structures
#define MAX_REBUILD_STRUCT 100
//Total number of technology branches
#define TECHS 8
//How many best templates to choose from when deciding what template to build
#define MAX_RANDOM_TEMPLATES 4
private int me; // player for this instance.
public int tileExpand; // rate of exploration
public int numDefenders[TECHS],maxDefenders[TECHS];
public int numAttackers[TECHS],maxAttackers[TECHS];
public int numCyborgs[TECHS],maxCyborgs[TECHS];
public int branchRocket,branchFlamer,branchCannon,branchMG,branchArtillery,branchCannonMGMortar,branchRocketMGMortar,branchFlameVtolLaser,techCount[TECHS],maxVtolFacs[TECHS],maxIdleRes[TECHS],
maxVTOLs[TECHS],numVtolTargets,vtolTargetWeight[10],numRebuildStat[TECHS];
public RESEARCHSTAT tech[TECHS][72]; //technology for different research branches
public STRUCTURESTAT rebuildStat[TECHS][2];
// structures
private int baseX,baseY,minx,miny,maxx,maxy,ebaseX,ebaseY;
public float mapSize;
public int numStructs,numIncendrys,numDefStructs,numExtraStructs[TECHS],numWallWeaps,numBaseStruct,numLightCyborgs,numFundamental;
private STRUCTURESTAT structChoice[5];
public STRUCTURESTAT incendrys[11],structs[16],defStructs[35],extraStructs[TECHS][6],wallWeaps[11];
public STRUCTURESTAT sensorTower,wall,cornerWall,resLab,powGen,playerHQ,lassat,factory,derrick,gderrick,cybFactory,archAngel,rippleRocket,
vtolDefStruct[9],vtolPad,vtolFactory,uplink,baseStruct[8];
public STRUCTURESTAT powModule,facModule,resModule,vtolModule,gTower;
public int extraStruct;
// unit templates
public int numTemplates[TECHS];
public TEMPLATE tmpl[TECHS][105];
private TEMPLATE tmplChoice[105];
public TEMPLATE cybTempl[9],superCyb[15],cybMechanic,cybEngineer,hovertruck;
public TEMPLATE vtols[38],vtolAAdroid;
public int numVtolTemplates;
public TEMPLATE sense[8];
public int numSenseTemplates;
public TEMPLATE constructor,repair[6],transporterTemp;
public int numRepairUnits;
public int numSensorUnits;
public int numRepairTemplates;
private int closestAlly;
private int closestAllyHQx;
private int closestAllyHQy;
private int closestAllyDist;
private int numAllyUnits;
private int numAlly;
private int numDerricks;
public int AllyBaseY[10];
public int AllyBaseX[10];
private int closestEnemy;
private int closestEnemyHQx;
private int closestEnemyHQy;
private int closestEnemyDist;
private int numFactories;
private int numResearchLab;
private int numVtolFactory;
private int numCybFactory;
private int numFactory;
private int numPowerGen;
//defend
private GROUP defendGroup;
private bool defendbusy;
private BASEOBJ defendObj;
public RESEARCHSTAT nexusDefence,dragon,guardTower,retribution,transporter,cybRepair,hover;
private RESEARCHSTAT research;
public WEAPON empBomb;
//build
private GROUP buildGroup;
private int buildX,buildY,buildX2,buildY2;
public FEATURESTAT oilRes;
// attack
private GROUP attackGroup;
private GROUP repairGroup;
private BASEOBJ attackObj,allOutAttack,vtolGrAttackObj[10];
// vtols
private GROUP vtolDefendGr,vtolAttackGr;
// transport
//private GROUP transportGroup;
// generic
private STRUCTURE structure,structure2,rebuildObj[100];
private DROID droid;
private FEATURE feature;
private BASEOBJ baseobj,baseobj2;
private int count,count2,result,result2,tempx,tempy;
private bool boolResult,boolResult2;
private bool powerSave,_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?!
// 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
private int allianceTime[MAX_PLAYERS_HACK];
private int sender,x,y,beaconX[20],beaconY[20],tBeacon[20],
tLastHelpRequest,lastHelpPlayer,tHelp,tHelpTimeout,helpX,helpY;
private string message;
private int defendX,defendY,__defendRadiusUnused,tDefendStart,tDefendTimeout,
defendMoveType,baseRange,curTech,numAttackVtols,
numDefendVtols,rebuildStructX[MAX_REBUILD_STRUCT],rebuildStructY[MAX_REBUILD_STRUCT],countRebuildStruct;
private STRUCTURESTAT rebuildStructStat[MAX_REBUILD_STRUCT];
private STRUCTURESTAT fundamentalBeingBuilt;
private int order; // callback global
/////////////////////////////////////////////////////////////////////
// TRIGGERS
#region triggers
// GAME START AND TIME DEFINITIONS
trigger startLevelTr (CALL_START_NEXT_LEVEL);
trigger everySec (every, 10); // for example, a value of 130 = 13 seconds
trigger chainloadTr (wait, 1);
trigger slowloadTr (wait, 13);
trigger delayedloadTr (wait, 35);
trigger announcementTr (wait, 100);
// BASE BUILD TRIGGERS
trigger basedetailsTr (every, 300 );
trigger upgradeStructuresTr (every, 40);
trigger buildPowerGeneratorsTr (every, 50 );
trigger buildReCentersTr (every, 70 );
trigger buildDerrickTr (every, 140 );
trigger buildFactoryTr (every, 120 );
trigger buildCyFactoryTr (every, 150 );
trigger buildVTOLFactoryTr (every, 350 );
trigger buildBaseTr (every, 1800);
trigger finishStructsTr (every, 30);
// FACTORY PRODUCTION
trigger conDroidsTr (every, 300); // was 1400
trigger repairDroidsTr (every, 400);
trigger sensorDroidsTr (every, 700);
trigger factoryEventTr (every, 180 );
trigger cyborgFactoryEventTr (every, 120 );
// DROID AND GROUP ORDER TRIGGER
trigger droidOrdersTr (every, 100 );
trigger repairGrpTr (every, 50 );
trigger manageDefendLocationTr (every, 70);
trigger attackStuffTr (every, 100 );
trigger remainingEnemyTr (every, 1400);
// MISC THINGS TO CHECK FOR TRIGGERS
trigger repairBaseTr (every, 200 );
trigger checkOnAllyTr (every, 200 );
trigger enemyNearBaseTr (every, 100);
trigger checkResearchTr (every, 100);
trigger useLassatTr (every, 1000);
// BUILD DEFENSE TRIGGERS
trigger fortifyTr (every, 200);
trigger incendryTr (every, 60 );
trigger buildOilDefenseOrRetreatTr (every, 400 );
trigger rebuildStructureTr (every, 50);
trigger spendPowerTr (every, 150);
// EVENT DRIVEN TRIGGERS
trigger reachedTr (CALL_DROID_REACH_LOCATION, me, ref droid, ref order);
trigger droidBuiltTr (CALL_NEWDROID,me, ref droid,ref structure);
trigger structBuiltTr (CALL_STRUCTBUILT, me, ref droid, ref structure);
trigger droidDestroyedTr (CALL_DROID_DESTROYED, me, ref droid);
trigger structureDestroyedTr (CALL_STRUCT_DESTROYED, me, ref structure);
trigger newObjectReportTr (CALL_OBJ_SEEN, me, ref baseobj, ref baseobj2);
trigger defendWatchTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger doResearchTr (CALL_RESEARCHCOMPLETED, ref research, ref structure, me);
trigger vtolDefendTr (CALL_STRUCT_ATTACKED, me, ref structure, ref baseobj);
trigger reassignTr (CALL_PLAYERLEFT,ref count);
trigger takeoverTr (CALL_UNITTAKEOVER, ref droid);
// VTOL TRIGGERS
trigger vtolStructsTr (every, 185);
trigger buildVtolsTr (every, 180);
trigger vtolAttackTr (every, 200);
trigger vtolEnablerTr (every, 150);
// MANAGE ALLIANCES
trigger formAllianceEventTr (every,170);
trigger breakAllianceEventTr (every,3000);
trigger humanAllianceTr (CALL_ALLIANCEOFFER,ref count, ref count2);
trigger multiMsgTr (CALL_AI_MSG, me, ref sender, ref message);
trigger beaconTr (CALL_BEACON, me, ref sender, ref x, ref y, ref message);
trigger consoleTr (CALL_CONSOLE, ref sender, ref message);
trigger watchBaseThreatTr (every, 120);
trigger manageAllyHelpTr (every, 80);
/* Events */
event conDroids;
event multiMsgEv;
event beaconEv;
event watchBaseThreat;
event manageAllyHelp;
event everySecEv;
event manageDefendLocationEv;
event structureDestroyed;
event rebuildStructureEv;
event doResearch;
event buildDerrick;
event findEnemy;
event announceResearch;
event factoryEvent;
event basedetails;
event droidOrders;
event checkOnAlly;
event repairBase;
event repairDroids;
event newfortify;
event incendry;
event enemyNearBase;
event beaconEv;
/* Function prototypes */
function bool haveBeacon(int _player);
function bool beaconTimeout(int _player);
function void processCommand(string _message, int _sender, bool _bBlipMessage);
function bool haveHelpers();
function bool attemptToHelp(int _playerToHelp, int _x, int _y);
function void helpPlayer(int _playerToHelp, int _helpX, int _helpY);
function bool canStopHelpingAlly();
function void stopHelpingAlly();
function bool helpingAlly();
function bool helpAllyTimeout();
function void requestHelp(int _helpX, int _helpY);
function void doRequestHelp(int _helpX, int _helpY);
function bool allyBaseAtLoc(int _ally, int _x, int _y);
function void messagePlayer(int _playerToMessage, string _message, int _probability);
function void messagePlayerAddressed(int _playerToMessage, int _playersToAddress, string _message);
function bool canSeeAllies();
function bool baseInTrouble();
function string m_affirmative();
function void defendLocation(int _defendX, int _defendY, int _tDefendTimeout, bool _bMove);
function void stopDefendingLocation();
function int nearestEnemy();
function int nearestAlly();
function bool defendingLocation();
function bool defendLocationTimeout();
function bool friendlyPlayer(int _playerToCheck);
function void factoryBuildDroid(STRUCTURE _factory);
function void cybFactorBuildCyborg(STRUCTURE _factory);
function void vtolFactoryBuildVtol(STRUCTURE _factory);
function bool insideBase(int _x, int _y);
function int numAlliesInBase(bool _bVtols);
function int numEnemiesInBase(bool _bVtols);
function bool defendingOwnBase();
function int targetTypeValue(BASEOBJ _target);
function int numBitsSet(int _integer);
function int findResearch(int _searchStart, int _techTree);
function void buildRearmPads();
function int numEnemyAAInRange(int _x, int _y, int _range);
function void buildBaseStruct(STRUCTURESTAT _structure);
function int countStruct(STRUCTURESTAT _structure);
function bool upgradeStruct(DROID _truck, int _maxBuilders, STRUCTURESTAT _struct);
function void finishStruct(STRUCTURESTAT _structure);
function int numBuildSameBuilding(STRUCTURESTAT _checkStat, int _x, int _y);
function int totalVtols();
function bool needTank();
function void setTechBranch(int _tech);
function DROID closestIdleTruck(int _x, int _y);
function void buildOnExactLocation(DROID _truck, int _x, int _y, STRUCTURESTAT _stat);
function void rebuildStructures();
function int numGroupSameOrder(GROUP _group, int _orderIndex);
function int numStructBusyByType(STRUCTURESTAT _busyStructType);
function bool aiResponsibleForPlayer(int _player);
function void reassignAI();
function void shutDownAI();
function bool buildUnit(TEMPLATE _tankTemplate, STRUCTURE _factory, STRUCTURESTAT _factoryType, bool _bIdleOnly);
function STRUCTURE findIdleStructure(STRUCTURESTAT _structType, bool _bIdleOnly);
#endregion triggers
/////////////////////////////////////////////////////////////////////
// HouseKeeping
event initialisedEvent(CALL_GAMEINIT)
{
local int player;
// initialise
me = getPlayer("Nexus");
_DEBUG = FALSE;
dbgMsgOn(me, _DEBUG);
extraStruct = 0;
numRepairUnits = 0;
numSensorUnits = 0;
allOutAttack = NULLOBJECT;
tLastHelpRequest = -1; //when we requested help for the last time
lastHelpPlayer = -1; //we are not currently helping anyone
tHelp = -1; //when we started helping last time
tHelpTimeout = -1; //time when help times out
helpX = -1;
helpY = -1;
defendX = -1;
defendY = -1;
tDefendStart = -1;
tDefendTimeout = -1;
defendMoveType = -1; //move or scout
closestEnemy = -1;
closestAlly = -1;
numAllyUnits = -1;
closestAllyDist = -1;
baseRange = 4 * TILE;
// set current research branch
setTechBranch(-1);
numAttackVtols = 100; //num vtols in an attack group
numDefendVtols = 5; //num vtols in the defend group
// setup build group - all initial droids are in buildgroup!
groupAddArea(buildGroup, me, 0, 0, (mapWidth*128), (mapHeight*128));
// note where our base is.
getPlayerStartPosition(me, ref baseX, ref baseY);
// defence.
defendbusy = FALSE;
// clear the alliance array...
player = 0;
while (player != MAX_PLAYERS)
{
allianceTime[player] = 0;
player = player + 1;
}
mapSize = (float)((mapWidth + mapHeight) / 2);
fundamentalBeingBuilt = derrick; // to avoid ever being null
if(aiResponsibleForPlayer(me))
{
bRunning = true;
}
else
{
bRunning = false;
shutDownAI();
}
}
// check whether we have at least one structure of that type
function bool haveStructure(STRUCTURESTAT type)
{
return getStructure(type, me) != NULLOBJECT;
}
// check if we are getting any income
function bool havePowerSource()
{
// we don't check buildings being finished here
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
event checkResearch(checkResearchTr)
{
setEventTrigger(doResearch, chainloadTr);
}
function void dbgPlr(string message)
{
setEventTrigger(doResearch, chainloadTr);
if (me == selectedPlayer)
{
console(message);
}
}
function void dbgObj(DROID obj, string message)
{
if (obj.selected)
{
console(message);
}
}
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 mydroid.order != DORDER_REPAIR and droidCanReach(mydroid, bx, by));
}
// Build something in main base, grab trucks to do it within tiles range
function bool grabTrucksAndBuild(int range, STRUCTURESTAT bstats, int maxBlockingTiles)
{
local DROID mydroid, closestDroid;
local int closestDist, currDist, numHelpDroids, tilerange, bx, by;
initIterateGroup(buildGroup); // find idle droids in build group.
mydroid = iterateGroup(buildGroup);
closestDist = 99999;
closestDroid = NULLOBJECT;
numHelpDroids = 0;
tilerange = range * TILE;
while (mydroid != NULLOBJECT)
{
if (conCanHelp(mydroid, baseX, baseY))
{
bx = baseX;
by = baseY;
if (pickDroidStructLocation(mydroid, bstats, ref bx, ref by, me, maxBlockingTiles))
{
currDist = distBetweenTwoPoints(bx, by, mydroid.x, mydroid.y);
if (currDist < tilerange)
{
orderDroidStatsLoc(mydroid, DORDER_BUILD, bstats, bx, by); // close, so help build it
numHelpDroids = numHelpDroids + 1;
}
else if (currDist < closestDist)
{
closestDroid = mydroid; // record this droid as being closest so far
closestDist = currDist;
}
}
}
mydroid = iterateGroup(buildGroup);
}
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!
return true;
}
return (numHelpDroids > 0);
}
function int nearestAlly()
{
local int _ally,_closestAlly,_newDist,_bestDist,_closestAllyX,_closestAllyY,_numUnits;
local bool _haveTruck;
_bestDist = 99999;
_closestAlly = -1;
_ally = 0;
_numUnits = 0;
numAlly = 0;
while(_ally < 10)
{
if(allianceExistsBetween(me, _ally) and me != _ally)
{
numAlly = numAlly + 1;
initEnumStruct(FALSE,playerHQ,_ally,_ally);
structure= enumStruct();
while(structure != NULLOBJECT)
{
_newDist = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);
AllyBaseY[_ally] = structure.y;
AllyBaseX[_ally] = structure.x;
if (_newDist < _bestDist)
{
_bestDist = _newDist;
_closestAlly = structure.player;
_closestAllyX = structure.x;
_closestAllyY = structure.y;
}
structure= enumStruct();
}
if(getStructure(playerHQ, _ally) == NULLOBJECT)
{
_haveTruck = FALSE;
InitEnumDroids(_ally,_ally);
droid = EnumDroid();
while (droid != NULLOBJECT and _haveTruck == FALSE)
{
if(droid.droidType == DROID_CONSTRUCT or droid.droidType == DROID_CYBORG_CONSTRUCT) // check to see if any of our allies don't have a truck
{
_haveTruck = TRUE;
_newDist = distBetweenTwoPoints(baseX, baseY, droid.x, droid.y);
AllyBaseY[_ally] = droid.y;
AllyBaseX[_ally] = droid.x;
if (_newDist < _bestDist)
{
_bestDist = _newDist;
_closestAlly = droid.player;
_closestAllyX = droid.x;
_closestAllyY = droid.y;
}
}
_numUnits++;
droid = EnumDroid();
}
}
}
_ally++;
}
if (_bestDist != 99999)
{
closestAllyDist = _bestDist;
closestAllyHQx = _closestAllyX;
closestAllyHQy = _closestAllyY;
numAllyUnits = _numUnits;
}
return _closestAlly;
}
event arrived(reachedTr)
{
local bool found;
local STRUCTURESTAT myChoice;
local STRUCTURE _structure,_target,_allyHQ;
local int _groupIndex,_newTargetWeight,_oldTargetWeight,_closestAlly;
local DROID _droid;
local BASEOBJ _newTarget;
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");
// Check if at oil well, and it was taken by enemy
structure = structureBuiltInRange(derrick, droid.x, droid.y, (5 * 128), -1);
_structure = structureBuiltInRange(gderrick, droid.x, droid.y, (5 * 128), -1);
if (structure != NULLOBJECT)
{
if (not friendlyPlayer(structure.player))
{
// Ok, at enemy derrick, and nobody has hurt us yet. Start being nasty.
count = 0;
found = false;
// find simplest/cheapest one available to build
while (count < numDefStructs and not found)
{
if (isStructureAvailable(defStructs[count], me))
{
found = true;
}
else
{
count++;
}
}
if (found)
{
buildX = droid.x;
buildY = droid.y;
if (pickDroidStructLocation(droid, defStructs[count], ref buildX, ref buildY, me, -1))
{
orderDroidStatsLoc(droid, DORDER_BUILD, defStructs[count], buildX, buildY);
}
else
{
dbgObj(droid, "Wanted to be nasty, but found nowhere to build defense");
orderDroid(droid, DORDER_RTB); // nothing more to do here.
}
}
else
{
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.
}
exit;
}
else if (droid.health < 80 and !insideBase(droid.x, droid.y))
{
orderDroid(droid, DORDER_RTR); // bolt back to base now!
exit;
}
}
}
else if (isVtol(droid))
{
if(droid.order == DORDER_SCOUT)
{
orderDroidLoc(droid, DORDER_SCOUT, baseX, baseY);
}
if (droid.action == DACTION_MOVETOREARMPOINT or droid.action == DACTION_WAITFORREARM or droid.action == DACTION_MOVETOREARM or droid.action == DACTION_WAITDURINGREARM and droid.health < 75)
{
droidLeaveGroup(droid);
exit;
}
if (droid.group == vtolDefendGr)
{
droidLeaveGroup(droid);
}
setDroidSecondary(droid, DSO_PATROL, DSS_PATROL_SET);
}
}
event buildFundamentals(inactive)
{
count = 0;
while (count < numFundamental)
{
// check that struct.
structure = getStructure(structs[count], me);
if (structure == NULLOBJECT) // if missing build it.
{
if (isStructureAvailable(structs[count], me))
{
if (grabTrucksAndBuild(12, structs[count], 0))
{
exit; // no need to check more
}
}
}
count = count + 1;
}
fundamentalBeingBuilt = derrick;
setEventTrigger(buildFundamentals, inactive);
}
event spendPower(spendPowerTr)
{
if(getPlayerName(me) == "Nexus" || not isHumanPlayer(me)) // not human
{
if(playerPower(me) > 6000 and idleGroup(buildGroup) > 0)
{
if (isStructureAvailable(archAngel, me))
{
if (grabTrucksAndBuild(12, archAngel, 0))
{
exit; // no need to check more
}
}
if (isStructureAvailable(rippleRocket, me))
{
if (grabTrucksAndBuild(12, rippleRocket, 0))
{
exit; // no need to check more
}
}
count = numDefStructs - 1;
while (count > 0)
{
// check that struct.
if (isStructureAvailable(defStructs[count], me))
{
if (grabTrucksAndBuild(12, defStructs[count], 0))
{
exit; // no need to check more
}
}
count = count - 1;
}
}
}
}
event startLevel(startLevelTr)
{
setEventTrigger(buildFundamentals, slowloadTr);
setEventTrigger(conDroids, chainloadTr);
setEventTrigger(doResearch, chainloadTr);
setEventTrigger(buildDerrick, delayedloadTr);
setEventTrigger(startLevel, inactive);
closestAlly = nearestAlly();
closestEnemy = nearestEnemy();
}
// decide what technology branch we will use
function void setTechBranch(int _tech)
{
local float _y2,_y1,_x2,_x1,_a,_y,_m,_rnd;
local int __rnd,_ally,_count;
if(_tech != -1)
{
curTech = _tech;
}
_ally = 0;
_count = 0;
while(_ally < MAX_PLAYERS)
{
if(allianceExistsBetween(me, _ally)){
_count++;
}
_ally++;
}
// If shared research then use flamers for map size < 130, cannons <170 else rocket
if(_count > 0 and multiPlayerAlliancesType == ALLIANCES_TEAMS and _count < 4)
{
__rnd = random(100);
if(mapSize < 120.0 and __rnd < 50)
{
curTech = branchFlameVtolLaser;
}
else if(mapSize < 160.0 and __rnd < 50)
{
curTech = branchCannonMGMortar;
}
else
{
curTech = branchRocketMGMortar;
}
}
else
{
//probability to choose artillery 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)
_x1 = 90.0; _y1 = 0.0;
_x2 = 250.0; _y2 = 65.0;
_m = ((_y2 - _y1) / (_x2 - _x1));
_a = -(_m * _x1);
//calculate probability for the current map
_y = _m * mapSize + _a;
dbg("_m = " & _m & ", a = " & _a, me);
_rnd = (float)random(100);
if(_rnd < _y)
{
curTech = branchArtillery;
}
else
{
// if no allies or allies with no shared research then use these profiles
__rnd = random(16);
if(__rnd <= 4)
{
curTech = branchRocket; // 5/16 chance to select profile
}
else if(__rnd >= 12)
{
curTech = branchCannon; // 4/16 chance to select profile
}
else if(__rnd <= 8)
{
curTech = branchMG; // 4/16 chance to select profile
}
else
{
curTech = branchFlamer; // 4/16 chance to select profile
}
}
}
// by default grenadiers are highest priority light cyborg in early game so we change that here depending on research profile
if(curTech == branchFlamer and multiPlayerAlliancesType == ALLIANCES_UNSHARED) //prioritize flamer borgs over grenadier
{
cybTempl[5] = cybTempl[3];
cybTempl[6] = cybTempl[4];
}
else if(curTech == branchCannon and multiPlayerAlliancesType == ALLIANCES_UNSHARED) //prioritize cannon borgs over grenadier
{
cybTempl[5] = cybTempl[1];
cybTempl[6] = cybTempl[2];
}
else if(curTech == branchRocket or curTech == branchMG and multiPlayerAlliancesType == ALLIANCES_UNSHARED) //prioritize mg borgs over grenadier
{
cybTempl[5] = cybTempl[0];
cybTempl[6] = cybTempl[0];
}
else if(curTech == branchFlameVtolLaser) //prioritize flamer borgs over grenadier
{
cybTempl[5] = cybTempl[3];
cybTempl[6] = cybTempl[4];
}
// else if(curTech == branchMG and multiPlayerAlliancesType == ALLIANCES_UNSHARED) //prioritize mg borgs over grenadier
//{
// cybTempl[5] = cybTempl[0];
// cybTempl[6] = cybTempl[0];
//}
}
/* returns TRUE if AI is responsible for the _player */
function bool aiResponsibleForPlayer(int _player)
{
if(not _DEBUG and ((_player == selectedPlayer) or not myResponsibility(_player)))
{
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// keep details about the size and postion of the ai players base
event basedetails(basedetailsTr)
{
// clear old extremities.
maxy = 0;
maxx = 0;
miny = (mapHeight*128);
minx = (mapWidth*128);
baseRange = 4 * TILE;
// now find the extremities of our vital structures.
count = 0;
while(count < numBaseStruct)
{
initEnumStruct(FALSE,baseStruct[count],me,me);
structure= enumStruct();
while(structure != NULLOBJECT)
{
if(structure.x < minx)
{
minx = structure.x;
}
if(structure.x > maxx)
{
maxx = structure.x;
}
if(structure.y < miny)
{
miny = structure.y;
}
if(structure.y > maxy)
{
maxy = structure.y;
}
result = distBetweenTwoPoints(baseX, baseY, structure.x, structure.y);
if(result > baseRange){
baseRange = result;
}
structure= enumStruct();
}
count = count + 1;
}
result = 3 * 128;
minx = minx - result;
maxx = maxx + result;
miny = miny - result;
maxy = maxy + result;
baseRange = baseRange + (4 * 128);
}
event repairGrp(repairGrpTr)
{
local bool _droidNeedRepair;
local DROID _droid;
if(repairGroup.members > 0)
{
_droidNeedRepair = false;
InitEnumDroids(me,me);
droid = EnumDroid();
while(droid != NULLOBJECT and _droidNeedRepair == false)
{
initIterateGroup(repairGroup);
_droid = iterateGroup(repairGroup);
while(_droid != NULLOBJECT)
{
if(_droid.action != DACTION_DROIDREPAIR)
{
if(distBetweenTwoPoints(_droid.x,_droid.y,droid.x,droid.y) < (TILE * 3) and droid.health < 90)
{
orderDroid(_droid, DORDER_STOP);
_droidNeedRepair = true;
}
else if(distBetweenTwoPoints(_droid.x,_droid.y,droid.x,droid.y) < (TILE * 6) and droid.health < 90)
{
orderDroidLoc(_droid, DORDER_MOVE, _droid.x,_droid.y);
orderDroidLoc(droid, DORDER_MOVE, _droid.x,_droid.y);
_droidNeedRepair = true;
}
else if(distBetweenTwoPoints(_droid.x,_droid.y,droid.x,droid.y) < (TILE * 25) and droid.health < 90)
{
orderDroidLoc(droid, DORDER_MOVE, _droid.x,_droid.y);
orderDroidLoc(_droid, DORDER_MOVE, droid.x,droid.y);
_droidNeedRepair = true;
}
else if(distBetweenTwoPoints(_droid.x,_droid.y,droid.x,droid.y) > (TILE * 10) and droid.health < 60)
{
orderDroidLoc(_droid, DORDER_MOVE, droid.x,droid.y);
//if(_droid.order == DORDER_RTR)
//{
// orderDroidLoc(droid, DORDER_MOVE, _droid.x,_droid.y);
//}
_droidNeedRepair = true;
}
}
_droid = iterateGroup(repairGroup);
}
droid = EnumDroid();
}
}
}
event droidOrders(droidOrdersTr)
{
local int _droidAtHq,_numDroids,_bestDist,_newDist,_closestRepairDroidX,_closestRepairDroidY;
local DROID _droid,_closestRepairDroid;