home *** CD-ROM | disk | FTP | other *** search
- //==============================================================================
- // Scn19ap2: AI Scenario Script for scenario 19a player 2
- //==============================================================================
- /*
- AI owner: Mike Kidd
- Scenario owner: Jeff Brown
- Handed off to: Greg Street
-
- Overview:
- The player lands on an open plain, with the goal of destroying the CP-owned
- wonder. He starts with a sizeable myth army, and must build up sufficient
- forces to break into the well-defended city.
-
- The CP will build up and maintain land armies and a navy. The land army will
- be predominately Cav with some infantry. At the time of launching each attack,
- the CP will randomly choose land or water (2/3 land) and send in an appropriate
- attack wave.
-
- There will be a special invocation of Earthquake if the CP survives to reach
- age 4. A pegasus will do a fly-over of the HP's town, and the CP will
- invoke Earthquake on the TC at that time. The pegasus will then fly off, and
- the CP will refrain from sending any attacks for the next 4 minutes.
-
- Difficulty: 7/17/2002
-
-
- */
- //==============================================================================
-
-
- include "scn lib.xs";
-
-
- // *****************************************************************************
- //
- // Globals
- //
- // *****************************************************************************
-
- // Attack routes and queries
- // TODO
-
- int queryP1Units = -1;
- int queryP1Buildings = -1;
-
-
- // Army control
- int lastAttackPlan = -1; // Used to find "my army" for god power position info
- int lastNavyPlan = -1;
- int nextAttackTime = 300000; // Will be adjusted for the wakeup time
- int attackInterval = 240000; // Attack every 4:00
- float attackSize = 8;
- float attackSizeMultiplier = 1.2;
- int maxAttackSize = 12;
- int reserveSize = 12;
-
- // TODO:ships
- int hippikonMaintainID = -1; // Plan for maintaining population of hippikon units
- int hippikonMaintainQty = 4; // How many to maintain
- int hippikonMaintainDelay = 60; // How many seconds between training units
-
- int prodromosMaintainID = -1;
- int prodromosMaintainQty = 4;
- int prodromosMaintainDelay = 60;
-
- int hypaspistMaintainID = -1;
- int hypaspistMaintainQty = 2;
- int hypaspistMaintainDelay = 40;
-
- int hopliteMaintainID = -1;
- int hopliteMaintainQty = 2;
- int hopliteMaintainDelay = 40;
-
- int petrobolosMaintainID = -1;
- int petrobolosMaintainQty = 2;
- int petrobolosMaintainDelay = 90;
-
-
- // Cinematic blocks
- const string cbAttackGather = "1491";
- const string cbNavyGather = "1492";
- const string cbHypaspistGather = "1493";
- const string cbHippikonGather = "1494";
- const string cbHopliteGather = "1495";
- const string cbProdromosGather = "1496";
- const string cbSiegeGather = "1497";
- const string cbTownLocation = "1498";
- const string cbAnimalMagnet = "1499";
- const string cbEarthquake = "1500";
-
-
- // Misc.
- int age2Time = 0; //
- int age3Time = 0; // We start in 3rd age
- int age4Time = 720000; // Go to 4th age in 12 min
- int startTime = -1; // Time of the wakeup() function...will be added to the age times.
-
-
-
- // *****************************************************************************
- //
- // FUNCTIONS
- //
- // *****************************************************************************
-
-
- // Called by trigger when the cinematics are done
- void wakeup(int parm=-1)
- {
- static bool alreadyRun = false;
- aiEcho("Wakeup running at "+timeString()+".");
- if (alreadyRun == true)
- return;
- alreadyRun = true;
-
- startTime = xsGetTime();
- age2Time = age2Time + startTime;
- xsEnableRule("goToAge3");
- age3Time = age3Time + startTime; // Adjust for delay in wakeup.
- age4Time = age4Time + startTime;
- nextAttackTime = nextAttackTime + startTime;
-
- // Init maintain plans
- maintainUnit(cUnitTypePegasus, 1, kbGetBlockPosition(cbTownLocation), 10);
- // TODO: add ships
- hippikonMaintainID = maintainUnit(cUnitTypeHippikon, hippikonMaintainQty, kbGetBlockPosition(cbHippikonGather), hippikonMaintainDelay);
- hopliteMaintainID = maintainUnit(cUnitTypeHoplite, hopliteMaintainQty, kbGetBlockPosition(cbHopliteGather), hopliteMaintainDelay);
-
-
-
- xsEnableRule("useAnimalMagnet");
- xsEnableRule("usePestilence");
- xsEnableRule("scout");
- xsEnableRule("attackGenerator");
- }
-
-
- // Used to delete units that are being replaced by a new type.
- void deleteObsoleteUnits(int unitType=cUnitTypeUnit, int player=2, vector center=vector(-1,-1,-1), float radius = 20.0, float percent=1.00)
- {
- // Make query
- int query = -1;
- int count = -1;
-
- query = kbUnitQueryCreate("Unit deletion query");
- if ( configQuery(query, unitType, -1, cUnitStateAlive, player, center, false, radius) == false)
- return;
- kbUnitQueryResetResults(query);
- count = kbUnitQueryExecute(query);
-
- // Iterate list, deleting percentage indicated
- float remainder=0.0; // Used to handle percentages, when this gets >= 1, it's time to delete a unit.
-
- for (i=0; <count)
- {
- remainder = remainder + percent;
- if (remainder >= 1.0) // time to delete one
- {
- aiTaskUnitDelete(kbUnitQueryGetResult(query,i));
- remainder = remainder - 1.0;
- }
- }
- }
-
-
- void age2EventHandler(int bogus=-1)
- {
- xsEnableRule("goToAge3");
- xsEnableRule("getAge2UnitUpgrades");
- xsEnableRule("getAge2ArmoryUpgrades");
-
-
- }
-
-
-
- void age3EventHandler(int bogus=-1)
- {
- xsEnableRule("useBronze");
- xsEnableRule("goToAge4");
- xsEnableRule("getAge3UnitUpgrades");
- xsEnableRule("getAge3ArmoryUpgrades");
-
- // TODO: Add hero defense...
- // mythMaintainID = maintainUnit(mythUnit, mythMaintainQty, kbGetBlockPosition(cbMythGather), mythMaintainDelay);
- hypaspistMaintainID = maintainUnit(cUnitTypeHypaspist, hypaspistMaintainQty, kbGetBlockPosition(cbHypaspistGather), hypaspistMaintainDelay);
- prodromosMaintainID = maintainUnit(cUnitTypeProdromos, prodromosMaintainQty, kbGetBlockPosition(cbProdromosGather), prodromosMaintainDelay);
- petrobolosMaintainID = maintainUnit(cUnitTypePetrobolos, petrobolosMaintainQty, kbGetBlockPosition(cbSiegeGather), petrobolosMaintainDelay);
- }
-
-
-
- void age4EventHandler(int bogus=-1)
- {
- xsEnableRule("getAge4UnitUpgrades");
- xsEnableRule("getAge4ArmoryUpgrades");
- xsEnableRule("useEarthquake");
-
- }
-
-
-
-
- void attack(int size=0)
- {
- int attackID=aiPlanCreate("Attack at "+timeString(true)+" ", cPlanAttack);
- if (attackID < 0)
- return;
-
- if (aiPlanSetVariableInt(attackID, cAttackPlanPlayerID, 0, 1) == false)
- return;
-
- if (aiPlanSetNumberVariableValues(attackID, cAttackPlanTargetTypeID, 2, true) == false)
- return;
-
- aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
- aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding);
-
- // aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeLeft);
-
- aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint, 0, kbGetBlockPosition(cbAttackGather));
- aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 10.0);
- aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbAttackGather));
- aiPlanAddUnitType(attackID, cUnitTypeMilitary, 1, size-1, size-1);
-
- // aiPlanSetNumberVariableValues(attackID, cAttackPlanQueryID, 2);
- // aiPlanSetVariableInt(attackID, cAttackPlanQueryID, 0, queryP1Farms);
- // aiPlanSetVariableInt(attackID, cAttackPlanQueryID, 1, queryP1Units);
-
- // aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbAttackGather));
- aiPlanSetRequiresAllNeedUnits(attackID, true);
- aiPlanSetActive(attackID);
- aiEcho("Activating attack plan "+attackID+" with appx "+size+" units.");
- lastAttackPlan = attackID; // update the global vars
-
- }
-
-
-
-
- void main()
- {
- aiEcho("Starting Scn19ap2.xs");
-
- kbAreaCalculate(1200.0);
- aiRandSetSeed();
- kbSetTownLocation(kbGetBlockPosition(cbTownLocation));
-
- aiSetAgeEventHandler(cAge2, "age2EventHandler");
- aiSetAgeEventHandler(cAge3, "age3EventHandler");
- aiSetAgeEventHandler(cAge4, "age4EventHandler");
-
- // Init attack routes
- // routeLeft = attackRoute("Left Attack Route",cbAttackGather, cbRouteLeft1, cbRouteLeft2);
-
- // Initialize the target queries
- queryP1Units = kbUnitQueryCreate("Player 1 Units");
- configQuery(queryP1Units, cUnitTypeUnit, -1, cUnitStateAlive, 1);
-
- queryP1Buildings = kbUnitQueryCreate("Player 1 Buildings");
- configQuery(queryP1Buildings, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding, 1);
-
-
- switch(aiGetWorldDifficulty())
- { // ignores 0 (easiest), uses initial values in that case.
- case 1: // medium
- {
- nextAttackTime = 300000; // 5 minutes
- attackSize = 6.0;
- maxAttackSize = 12.0;
- attackSizeMultiplier = 1.2;
- attackInterval = 240000; // 4 minutes
- reserveSize = 20;
- age4Time = 8*60*1000;
- break;
- }
- case 2: // difficult/hard
- {
- nextAttackTime = 240000; // 3 minutes
- attackSize = 8.0;
- maxAttackSize = 30.0;
- attackSizeMultiplier = 1.2;
- attackInterval = 180000; // 3 minutes
- reserveSize = 35;
- age4Time = 6*60*1000;
- break;
- }
- case 3: // hardest/nightmare
- {
- nextAttackTime = 30000; // 30 sec
- attackSize = 10.0;
- maxAttackSize = 50.0;
- attackSizeMultiplier = 1.3;
- attackInterval = 120000; // 2 minutes
- reserveSize = 60;
- age4Time = 6*60*1000;
- break;
- }
- }
- hippikonMaintainQty = (reserveSize+1) / 3;
- prodromosMaintainQty = (reserveSize+1) / 3;
- hypaspistMaintainQty = (reserveSize+3) / 6;
- hopliteMaintainQty = (reserveSize+3) / 6;
-
- aiEcho("Difficulty = "+aiGetWorldDifficulty());
- }
-
-
-
-
-
- // *****************************************************************************
- //
- // RULES
- //
- // *****************************************************************************
-
- rule scout
- inactive
- minInterval 5
- {
- // just set up an explore plan
- int exploreID = aiPlanCreate("Explore", cPlanExplore);
- if(exploreID >= 0)
- {
- aiPlanSetVariableFloat( exploreID, cExplorePlanLOSMultiplier, 0, 4.0 );
- aiPlanAddUnitType(exploreID, cUnitTypePegasus, 1, 1, 1);
- aiPlanSetDesiredPriority(exploreID, 90);
- aiPlanSetInitialPosition(exploreID, kbGetBlockPosition(cbAttackGather));
- aiPlanSetActive(exploreID);
- }
-
- int explore2ID = aiPlanCreate("Water explore", cPlanExplore);
- if(explore2ID >= 0)
- {
- aiPlanSetVariableFloat( explore2ID, cExplorePlanLOSMultiplier, 0, 4.0 );
- aiPlanAddUnitType(explore2ID, cUnitTypeHippocampus, 1, 1, 1);
- aiPlanSetDesiredPriority(explore2ID, 90);
- aiPlanSetInitialPosition(explore2ID, kbGetBlockPosition(cbNavyGather));
- aiPlanSetActive(explore2ID);
- }
-
- xsDisableSelf();
- }
-
- rule goToAge2
- inactive
- minInterval 10
- {
- if ( xsGetTime() < age2Time)
- return;
- // researchTech(cTechAge2Ptah);
- xsDisableSelf();
- }
-
-
-
- rule goToAge3
- inactive
- mininterval 20
- {
- if ( xsGetTime() < age3Time )
- return;
- researchTech(cTechAge3Dionysos);
- xsDisableSelf();
- }
-
-
- rule goToAge4
- inactive
- mininterval 20
- {
- if ( xsGetTime() < age4Time )
- return;
- if (aiGetWorldDifficulty() != 0)
- researchTech(cTechAge4Artemis);
- xsDisableSelf();
- }
-
-
-
- rule getAge2UnitUpgrades
- inactive
- minInterval 20
- {
- if ( xsGetTime() < (age2Time + age2Time + age3Time)/3 )
- return; // Wait till 1/3 to age3
- researchTech(cTechMediumCavalry);
- researchTech(cTechMediumInfantry);
- xsDisableSelf();
- }
-
- rule getAge2ArmoryUpgrades
- inactive
- minInterval 20
- {
- if ( xsGetTime() < (age2Time + age3Time + age3Time)/3 )
- return; // Wait till 2/3 to age3
- aiEcho("Getting age 2 armory upgrades");
- researchTech(cTechCopperWeapons);
- researchTech(cTechCopperMail);
- researchTech(cTechCopperShields);
- xsDisableSelf();
- }
-
- rule getAge3UnitUpgrades
- inactive
- minInterval 20
- {
- if ( xsGetTime() < (age3Time+180000) )
- return;
- researchTech(cTechHeavyCavalry);
- researchTech(cTechHeavyInfantry);
- xsDisableSelf();
- }
-
- rule getAge3ArmoryUpgrades
- inactive
- minInterval 20
- {
- if ( xsGetTime() < (age3Time+300000) )
- return;
- researchTech(cTechBronzeWeapons);
- researchTech(cTechBronzeMail);
- researchTech(cTechBronzeShields);
- xsDisableSelf();
- }
-
- rule getAge4UnitUpgrades
- inactive
- minInterval 20
- {
- if ( xsGetTime() < (age4Time+300000) )
- return;
- researchTech(cTechChampionCavalry);
- researchTech(cTechChampionInfantry);
- xsDisableSelf();
- }
-
- rule getAge4ArmoryUpgrades
- inactive
- minInterval 20
- {
- if ( xsGetTime() < (age4Time+600000) )
- return;
- researchTech(cTechIronWeapons);
- researchTech(cTechIronMail);
- researchTech(cTechIronShields);
- xsDisableSelf();
- }
-
-
-
- rule attackGenerator
- minInterval 10
- inactive
- {
- // aiEcho("attack check running, next time is "+nextAttackTime);
- if ( xsGetTime() < nextAttackTime )
- return;
-
- attack(attackSize);
- nextAttackTime = xsGetTime() + attackInterval;
- attackSize = attackSize * attackSizeMultiplier;
- if (attackSize > maxAttackSize)
- attackSize = maxAttackSize;
- aiEcho("Next attack size will be "+attackSize+".");
- }
-
-
-
- rule useAnimalMagnetism
- minInterval 5
- inactive
- {
- vector aimHere = kbGetBlockPosition(cbAnimalMagnet);
-
-
- if (aiCastGodPowerAtPosition(cTechAnimalMagnetism, aimHere) == true)
- {
- xsDisableSelf();
- aiEcho("Invoking animal magnetism at "+aimHere);
- }
- else
- aiEcho("Couldn't do animal magnetism at "+aimHere);
- }
-
-
-
-
- rule usePestilence // Look for 2 military buildings near my army
- minInterval 5
- inactive
- {
- int targetUnit = -1;
- int attackArmyID = -1;
-
- if (lastAttackPlan < 0)
- return;
- vector pVec = aiPlanGetLocation(lastAttackPlan);
- if (xsVectorGetX(pVec)<0)
- return;
-
- static int tempQuery = -1;
- if (tempQuery < 0)
- { // Doesn't exist, set it up
- tempQuery = kbUnitQueryCreate("usePestilence");
-
- if ( configQuery(tempQuery, cUnitTypeMilitaryBuilding, -1, cUnitStateAliveOrBuilding, 1, pVec, true, 50) == false)
- return;
- }
- else
- kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
-
- kbUnitQueryResetResults(tempQuery);
- int targetCount = kbUnitQueryExecute(tempQuery);
-
- if (targetCount < 2)
- return;
- // targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2); // grab middle farm
-
-
- aiEcho("Using Pestilence");
- if ( aiCastGodPowerAtPosition(cTechPestilence, pVec) == true)
- xsDisableSelf();
- else
- aiEcho("Pestilence failed at "+pVec);
- }
-
-
- rule useBronze // Look for 8 military units near my army
- minInterval 5
- inactive
- {
- int targetUnit = -1;
- int attackArmyID = -1;
-
- if (lastAttackPlan < 0)
- return;
- vector pVec = aiPlanGetLocation(lastAttackPlan);
- if (xsVectorGetX(pVec)<0)
- return;
-
- static int tempQuery = -1;
- if (tempQuery < 0)
- { // Doesn't exist, set it up
- tempQuery = kbUnitQueryCreate("useBronze");
-
- if ( configQuery(tempQuery, cUnitTypeMilitary, -1, cUnitStateAlive, 1, pVec, true, 50) == false)
- return;
- }
- else
- kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
-
- kbUnitQueryResetResults(tempQuery);
- int targetCount = kbUnitQueryExecute(tempQuery);
-
- if (targetCount < 8)
- return;
- // targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2); // grab middle farm
-
- // confirm that we have at least 10 miltary units there
- static int query2 = -1;
- if (query2 < 0)
- {
- query2 = kbUnitQueryCreate("useBronze2");
- configQuery(query2, cUnitTypeMilitary, -1, cUnitStateAlive, 2, pVec, true, 25);
- }
- else
- kbUnitQuerySetPosition(query2, pVec); // Because pVec changes as army moves
- kbUnitQuerySetPosition(query2, pVec);
- kbUnitQueryResetResults(query2);
- targetCount = kbUnitQueryExecute(query2);
- if (targetCount < 10)
- return;
-
-
- aiEcho("Using Bronze");
- if ( aiCastGodPowerAtPosition(cTechBronze, kbUnitGetPosition(kbUnitQueryGetResult(query2, targetCount/2))) == true)
- xsDisableSelf();
- else
- aiEcho("Bronze failed on "+kbUnitQueryGetResult(query2, targetCount/2));
- }
-
- /*
- rule useEarthquake // Look for 12 buildings near my army
- minInterval 5
- inactive
- {
- int targetUnit = -1;
- int attackArmyID = -1;
-
- if (lastAttackPlan < 0)
- return;
- vector pVec = aiPlanGetLocation(lastAttackPlan);
- if (xsVectorGetX(pVec)<0)
- return;
-
- static int tempQuery = -1;
- if (tempQuery < 0)
- { // Doesn't exist, set it up
- tempQuery = kbUnitQueryCreate("useEarthQuake");
-
- if ( configQuery(tempQuery, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding, 1, pVec, true, 50) == false)
- return;
- }
- else
- kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
-
- kbUnitQueryResetResults(tempQuery);
- int targetCount = kbUnitQueryExecute(tempQuery);
-
- if (targetCount < 12)
- return;
- targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2); // grab middle building
-
-
- aiEcho("Using Earthquake");
- if ( aiCastGodPowerAtPosition(cTechEarthquake, pVec) == true)
- xsDisableSelf();
- else
- aiEcho("Earthquake failed at "+pVec);
- }
- */
-
- rule useEarthquake // Ultra-hacked variant...grab pegasus, send to HP TC, do quake there.
- minInterval 5
- inactive
- {
- static int lastPegasusMove = -20000;
- static int pegQuery = -1;
- static int pegUnit = -1;
-
- // Make sure pegasus is en route
- if ( (xsGetTime()-20000) > lastPegasusMove ) // Move it again if last move was > 20 sec ago
- {
- if (pegQuery < 0)
- {
- pegQuery = kbUnitQueryCreate("Pegasus");
- configQuery(pegQuery, cUnitTypePegasus, -1, cUnitStateAlive, 2);
- }
- kbUnitQueryResetResults(pegQuery);
- if ( kbUnitQueryExecute(pegQuery) > 0 )
- pegUnit = kbUnitQueryGetResult(pegQuery, 0);
- else
- return;
- aiTaskUnitMove(pegUnit, kbGetBlockPosition(cbEarthquake));
- lastPegasusMove = xsGetTime();
- }
-
- // See if it's there
- vector pegVec = kbUnitGetPosition(pegUnit);
- if ( xsVectorGetX(pegVec) < 0)
- return;
- float dx = xsVectorGetX(pegVec) - xsVectorGetX(kbGetBlockPosition(cbEarthquake));
- float dz = xsVectorGetZ(pegVec) - xsVectorGetZ(kbGetBlockPosition(cbEarthquake));
- if (dx > 10.0)
- return;
- if (dx < -10.0)
- return;
- if (dz > 10.0)
- return;
- if (dz < -10.0)
- return;
-
- // Pegasus is close enough for LOS
- aiCastGodPowerAtPosition(cTechEarthquake, kbGetBlockPosition(cbEarthquake));
- xsDisableSelf();
- aiTaskUnitMove(pegUnit, kbGetBlockPosition(cbTownLocation)); // Bug out!
-
- // Prevent attacks for 4 minutes
- nextAttackTime = xsGetTime() + 4*60*1000;
- }
-
-
-
-
-