Images
Turn 350: Greece, Austria
Turn 350: Burkina Faso, Thailand
Turn 500: Greece, Kenia

Frenzy AI

This is an extensely re-worked version of the famous script originally written by Blueorange. In its original version the script had some disadvantages:

  • In the first place it simply ignored diplomacy and threw frenzy armies against the closest human neighbor even when at peace by treaty. This behaviour has already been corrected by Pedrunn (enemy selection, and de-selection considering diplomatic status).
  • The second issue used to be that frenzy armies did not garrison the captured cities. Now they do — and new frenzy armies are selected and targeted.
  • The entire army and target selection logic has been reworked.
  • Re-capturing of cities is somewhat prioritized.

1The Script1

//--------------------------------------------------------------------------
// MoT Mod for CTP2 (Apolyton Edition) by BureauBert
// v1.1
// http://motmod.ctp2.info
//--------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////
// Frenzy AI Mod
// Original code by: Blueorange
// Additional optimization and modification by: Wouter Snijders (aka Locutus)
// Diplomacy adaption and additional optimization by Pedrunn
// Added by BureauBert:
// TaskNumberOne: Recapture and Release Frenzy Armies / Garrison Cities
// Re-worked the entire targeting framework using some new CTP2 AE features
// (GetContinent) and some additional code optimization ;-)
////////////////////////////////////////////////////////////////////////////

///////////////////////////////////
// Global variables
///////////////////////////////////

// declared in main.slc

///////////////////////////////////
// Setup function
///////////////////////////////////

// called from setup.slc

void_f SetupFrenzy() {
        int_t faiSetupCount;
        army_t faiSetupArmy;

        for(faiSetupCount = 0; faiSetupCount < g.max_players; faiSetupCount = faiSetupCount + 1) {
                FAI_FirstArmy[faiSetupCount] = faiSetupArmy;
                FAI_SecondArmy[faiSetupCount] = faiSetupArmy;
                FAI_ThirdArmy[faiSetupCount] = faiSetupArmy;
                FAI_FourthArmy[faiSetupCount] = faiSetupArmy;
               
                FAI_FirstNavy[faiSetupCount] = faiSetupArmy;
                FAI_SecondNavy[faiSetupCount] = faiSetupArmy;
                FAI_ThirdNavy[faiSetupCount] = faiSetupArmy;
                FAI_FourthNavy[faiSetupCount] = faiSetupArmy;

                FAI_AttackSize[faiSetupCount] = 8;        // adjust these parameters as needed
                FAI_ReleaseSize[faiSetupCount] = 4;        // adjust these parameters as needed
               
                FAI_WorstEnemyNum[faiSetupCount] = 0;

                FAI_AttackTarget[faiSetupCount] = faiSetupArmy.location;
                FAI_AttackTargetNeighbor[faiSetupCount] = faiSetupArmy.location;
                FAI_NavyTarget[faiSetupCount] = faiSetupArmy.location;

                FAI_TaskOneFlag[faiSetupCount] = 0;
                FAI_CounterStrikeFlag[faiSetupCount] = 0;
        }                                               
}

///////////////////////////////////
// Army Code
///////////////////////////////////

HandleEvent(StartMovePhase) 'FAI_SelectAndMoveFrenzyArmies' pre {
        int_t faiSelArmies;
        int_t faiSelArmyCount;
        army_t faiSelArmy;
        location_t faiSelArmyLoc;
        int_t faiSelPlayer;
        army_t faiSelEmptyArmy;
        city_t faiSelTmpCity;
        int_t faiSelProceed;
        int_t faiSelArmySize;
        location_t faiSelTargLoc;
        int_t faiSelCount;

        faiSelArmies = player[0].armies;
        faiSelPlayer = player[0].owner;

        if(PlayerCityCount(faiSelPlayer) > 0) {
                for(faiSelArmyCount = 0; faiSelArmyCount < faiSelArmies; faiSelArmyCount = faiSelArmyCount + 1) {
                        if(GetArmyByIndex(faiSelPlayer, faiSelArmyCount, faiSelArmy)) {
                                if(ArmyIsValid(faiSelArmy)) {
                                        faiSelPlayer = faiSelArmy.owner;
                                        faiSelArmyLoc = faiSelArmy.location;
                                        faiSelArmySize = faiSelArmy.size;
                                        faiSelProceed = 10;
                                        // release Frenzy armies if in city or too many have died
                                        if(GetCityByLocation(faiSelArmyLoc, faiSelTmpCity) || faiSelArmySize <= FAI_ReleaseSize[faiSelPlayer]) {
                                                if(faiSelArmy == FAI_FirstArmy[faiSelPlayer]) {
                                                        FAI_FirstArmy[faiSelPlayer] = faiSelEmptyArmy;
                                                }
                                                elseif(faiSelArmy == FAI_SecondArmy[faiSelPlayer]) {
                                                        FAI_SecondArmy[faiSelPlayer] = faiSelEmptyArmy;
                                                }
                                                elseif(faiSelArmy == FAI_ThirdArmy[faiSelPlayer]) {
                                                        FAI_ThirdArmy[faiSelPlayer] = faiSelEmptyArmy;
                                                }
                                                elseif(faiSelArmy == FAI_FourthArmy[faiSelPlayer]) {
                                                        FAI_FourthArmy[faiSelPlayer] = faiSelEmptyArmy;
                                                }
                                        }
                                        // (re-)select Frenzy Armies
                                        if(!IsPrivilegedArmy(faiSelArmy, faiSelPlayer)) {
                                                if(!ArmyIsValid(FAI_FirstArmy[faiSelPlayer])) {
                                                        if(faiSelArmySize >= FAI_AttackSize[faiSelPlayer]) {
                                                                if(IsLandTerrain(faiSelArmyLoc) && CheckGroupage(faiSelArmy) == 1) {
                                                                        FAI_FirstArmy[faiSelPlayer] = faiSelArmy;
                                                                        faiSelProceed = 1;
                                                                }
                                                        }
                                                }
                                                elseif(!ArmyIsValid(FAI_SecondArmy[faiSelPlayer])) {
                                                        if(faiSelArmySize >= FAI_AttackSize[faiSelPlayer]) {
                                                                if(IsLandTerrain(faiSelArmyLoc) && CheckGroupage(faiSelArmy) == 1) {
                                                                        FAI_SecondArmy[faiSelPlayer] = faiSelArmy;
                                                                        faiSelProceed = 1;
                                                                }
                                                        }
                                                }
                                                elseif(!ArmyIsValid(FAI_ThirdArmy[faiSelPlayer])) {
                                                        if(faiSelArmySize >= FAI_AttackSize[faiSelPlayer]) {
                                                                if(IsLandTerrain(faiSelArmyLoc) && CheckGroupage(faiSelArmy) == 1) {
                                                                        FAI_ThirdArmy[faiSelPlayer] = faiSelArmy;
                                                                        faiSelProceed = 1;
                                                                }
                                                        }
                                                }
                                                elseif(!ArmyIsValid(FAI_FourthArmy[faiSelPlayer])) {
                                                        if(faiSelArmySize >= FAI_AttackSize[faiSelPlayer]) {
                                                                if(IsLandTerrain(faiSelArmyLoc) && CheckGroupage(faiSelArmy) == 1) {
                                                                        FAI_FourthArmy[faiSelPlayer] = faiSelArmy;
                                                                        faiSelProceed = 1;
                                                                }
                                                        }
                                                }
                                        }
                                        // If we prepare for an offensive campaign (as opposed to a counter strike),
                                        // be patient and wait for availability of real big armies:
                                        if(faiSelProceed == 1 && FAI_CounterStrikeFlag[faiSelPlayer] == 0) {
                                                FAI_AttackSize[faiSelPlayer] = faiSelArmySize;
                                        }
                                        // Force Frenzy Armies to move
                                        if(FAI_TaskOneFlag[faiSelPlayer] == 1) {
                                                if(faiSelArmy == FAI_FirstArmy[faiSelPlayer]
                                                || faiSelArmy == FAI_SecondArmy[faiSelPlayer]
                                                || faiSelArmy == FAI_ThirdArmy[faiSelPlayer]
                                                || faiSelArmy == FAI_FourthArmy[faiSelPlayer]
                                                ) {
                                                        faiSelProceed = AttackEvaluateLocation(faiSelArmyLoc, faiSelPlayer);
                                                        if(faiSelProceed == 10) {
                                                                Event:DetrenchOrder(faiSelArmy);
                                                                Event:WakeArmy(faiSelArmy);
                                                                // MoveArmyToTarget(faiSelArmy, FAI_AttackTargetNeighbor[faiSelPlayer]);
                                                                MoveArmyToTarget(faiSelArmy, FAI_AttackTarget[faiSelPlayer]);
                                                                // TEST
                                                                //AddCenter(faiSelArmyLoc);
                                                                //AddEffect(faiSelArmyLoc,"SPECEFFECT_EXPLOSION_SPACE_2","SOUND_ID_ALERT");
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
        return CONTINUE;
}

HandleEvent(BeginTurnAllCities) 'FAI_ForceFrenzyArmiesAttack' pre {
        int_t faiSelArmies;
        int_t faiSelArmyCount;
        army_t faiSelArmy;
        int_t faiSelPlayer;
        location_t faiSelArmyLoc;
        location_t faiSelTargLoc;
        int_t faiSelProceed;

        faiSelArmies = player[0].armies;
        faiSelPlayer = player[0].owner;

        if(PlayerCityCount(faiSelPlayer) > 0) {
                for(faiSelArmyCount = 0; faiSelArmyCount < faiSelArmies; faiSelArmyCount = faiSelArmyCount + 1) {
                        if(GetArmyByIndex(faiSelPlayer, faiSelArmyCount, faiSelArmy)) {
                                if(ArmyIsValid(faiSelArmy)) {
                                        faiSelArmyLoc = faiSelArmy.location;
                                        faiSelProceed = 10;
                                        // Force Frenzy Armies to attack
                                        if(FAI_TaskOneFlag[faiSelPlayer] == 1) {
                                                if(faiSelArmy == FAI_FirstArmy[faiSelPlayer]
                                                || faiSelArmy == FAI_SecondArmy[faiSelPlayer]
                                                || faiSelArmy == FAI_ThirdArmy[faiSelPlayer]
                                                || faiSelArmy == FAI_FourthArmy[faiSelPlayer]
                                                ) {
                                                        faiSelProceed = AttackEvaluateLocation(faiSelArmyLoc, faiSelPlayer);
                                                        if(faiSelProceed != 10) {
                                                                if(GetNeighbor(faiSelArmyLoc, faiSelProceed, faiSelTargLoc)) {
                                                                        AttackLocation(faiSelArmy, faiSelProceed, faiSelTargLoc);
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
        return CONTINUE;
}

HandleEvent(NextDiplomaticState) 'FAI_SetWorstEnemy' post {
        int_t        faiDipPlayer;
        int_t        faiDipCounterStrikeTurns;
        int_t        faiDipLowestRegard;
        int_t        faiDipEnemyRegard;
        int_t        faiDipOurCapitalIdx;
        city_t        faiDipOurCapital;
        int_t        faiDipOurContinent;
        int_t        faiDipCheckPlayer;

        faiDipPlayer = player[0].owner;

        if(!IsHumanPlayer(faiDipPlayer) && faiDipPlayer > 0 && Cities(faiDipPlayer) > 0) {
                faiDipCounterStrikeTurns = 10;        // no. of turns since last HotWar attack
                faiDipLowestRegard = 1000;
                faiDipEnemyRegard = 0;
                faiDipOurCapitalIdx = GetCapital(faiDipPlayer);
                if(GetCityByIndex(faiDipPlayer, faiDipOurCapitalIdx, faiDipOurCapital)) {
                        faiDipOurContinent = GetContinent(faiDipOurCapital.location);
                }
                FAI_CounterStrikeFlag[faiDipPlayer] = 0;
                // get lowest effective regard:
                for(faiDipCheckPlayer = 1; faiDipCheckPlayer < g.max_players; faiDipCheckPlayer = faiDipCheckPlayer + 1) {
                        if(IsPlayerAlive(faiDipCheckPlayer)) {
                                faiDipEnemyRegard = GetEffectiveRegard(faiDipPlayer, faiDipCheckPlayer);
                                if(faiDipEnemyRegard < faiDipLowestRegard) {
                                        FAI_WorstEnemyNum[faiDipPlayer] = faiDipCheckPlayer;
                                        faiDipLowestRegard = faiDipEnemyRegard;
                                }
                        }
                }
                // If we are at peace with everyone, good old barbs are our worst enemy:
                if(faiDipLowestRegard > 100) {
                        FAI_WorstEnemyNum[faiDipPlayer] = 0;
                }
                // If we have been recently attacked by our worst enemy prepare for a counter strike:
                if(GetLastHotwarAttack(FAI_WorstEnemyNum[faiDipPlayer], faiDipPlayer) <= faiDipCounterStrikeTurns) {
                        FAI_CounterStrikeFlag[faiDipPlayer] = 1;
                }
        }
}

void_f SetFrenzyLandTarget(int_t thePlayer) {
        int_t                faiTargPlayer;
        int_t                faiTargMinAttackSize;
        int_t                faiTargArmyFound;
        int_t                faiTargOurCapitalIdx;
        city_t                faiTargOurCapital;
        location_t        faiTargOurCapitalLoc;
        int_t                faiTargOurContinent;
        int_t                faiTargFound;
        int_t                faiTargNeighborFound;
        city_t                faiTargCheckCity;
        int_t                faiTargCheckCityOwner;
        int_t                faiTargEnemyRegard;
        location_t        faiTargArmyLoc;
        int_t                faiTargSelRand;
        int_t                faiTargTmpCityIdx;
        city_t                faiTargTmpCity;
        location_t        faiTargTmpCityLoc;
        int_t                faiTargTheirContinent;
        location_t        faiTargLoc;
        int_t                faiTargCycle;
        location_t        faiTargNeighbor;
        location_t        faiTargEmptyLoc;

        faiTargPlayer = thePlayer;

        if(!IsHumanPlayer(faiTargPlayer) && faiTargPlayer > 0 && FAI_On[faiTargPlayer] == 1) {
                faiTargMinAttackSize = 8;        // minimum size of Frenzy Army
                faiTargOurCapitalIdx = GetCapital(faiTargPlayer);
                if(GetCityByIndex(faiTargPlayer, faiTargOurCapitalIdx, faiTargOurCapital)) {
                        faiTargOurCapitalLoc = faiTargOurCapital.location;
                }
                // If we prepare for a counter strike, use any reasonably sized army:
                if(FAI_CounterStrikeFlag[faiTargPlayer] == 1) {
                        FAI_AttackSize[faiTargPlayer] = faiTargMinAttackSize;
                }
                // TARGET SELECTION:
                // if an existing target has been destroyed or already been captured,
                // or we are no longer at war with the target owner: remove flag
                if(FAI_TaskOneFlag[faiTargPlayer] == 1) {
                        faiTargFound = 0;
                        if(GetCityByLocation(FAI_AttackTarget[faiTargPlayer], faiTargCheckCity)) {
                                faiTargCheckCityOwner = faiTargCheckCity.owner;
                                faiTargEnemyRegard = GetEffectiveRegard(faiTargPlayer, faiTargCheckCityOwner);
                                if(faiTargCheckCityOwner != faiTargPlayer && faiTargEnemyRegard < 101) {
                                        faiTargFound = 1;
                                }
                        }
                        if(faiTargFound == 0) {
                                FAI_TaskOneFlag[faiTargPlayer] = 0;
                        }
                }
                // if flag has been removed or no task has been assigned at all: task/re-task task-forces
                if(FAI_TaskOneFlag[faiTargPlayer] == 0) {
                        faiTargArmyFound = 0;
                        if(ArmyIsValid(FAI_FirstArmy[faiTargPlayer])) {
                                faiTargArmyLoc = FAI_FirstArmy[faiTargPlayer].location;
                                faiTargArmyFound = 1;
                        }
                        elseif(ArmyIsValid(FAI_SecondArmy[faiTargPlayer])) {
                                faiTargArmyLoc = FAI_SecondArmy[faiTargPlayer].location;
                                faiTargArmyFound = 1;
                        }
                        elseif(ArmyIsValid(FAI_ThirdArmy[faiTargPlayer])) {
                                faiTargArmyLoc = FAI_ThirdArmy[faiTargPlayer].location;
                                faiTargArmyFound = 1;
                        }
                        elseif(ArmyIsValid(FAI_FourthArmy[faiTargPlayer])) {
                                faiTargArmyLoc = FAI_FourthArmy[faiTargPlayer].location;
                                faiTargArmyFound = 1;
                        }
                        if(faiTargArmyFound == 1) {
                                faiTargOurContinent = GetContinent(faiTargArmyLoc);
                                faiTargSelRand = Random(100);
                                // a 30% chance we first try to target their nearest city:
                                if(0 <= faiTargSelRand <= 29) {
                                        if(PlayerCityCount(FAI_WorstEnemyNum[faiTargPlayer]) > 0) {
                                                faiTargTmpCityIdx = GetNearestCity(faiTargArmyLoc, FAI_WorstEnemyNum[faiTargPlayer]);
                                                if(GetCityByIndex(FAI_WorstEnemyNum[faiTargPlayer], faiTargTmpCityIdx, faiTargTmpCity)) {
                                                        faiTargTmpCityLoc = faiTargTmpCity.location;
                                                        faiTargTheirContinent = GetContinent(faiTargTmpCityLoc);
                                                        if(faiTargOurContinent == faiTargTheirContinent && !IsWater(faiTargTmpCityLoc)) {
                                                                FAI_AttackTarget[faiTargPlayer] = faiTargTmpCityLoc;
                                                                FAI_TaskOneFlag[faiTargPlayer] = 1;
                                                        }
                                                }
                                        }
                                }
                                // a 30% chance we first try to target their most at risk city:
                                elseif(30 <= faiTargSelRand <= 59) {
                                        if(PlayerCityCount(FAI_WorstEnemyNum[faiTargPlayer]) > 0) {
                                                if(GetMostAtRiskCity(FAI_WorstEnemyNum[faiTargPlayer], faiTargPlayer, faiTargTmpCity)) {
                                                        faiTargTmpCityLoc = faiTargTmpCity.location;
                                                        faiTargTheirContinent = GetContinent(faiTargTmpCityLoc);
                                                        if(faiTargOurContinent == faiTargTheirContinent && !IsWater(faiTargTmpCityLoc)) {
                                                                FAI_AttackTarget[faiTargPlayer] = faiTargTmpCityLoc;
                                                                FAI_TaskOneFlag[faiTargPlayer] = 1;
                                                        }
                                                }
                                        }
                                }
                                // a 20% chance we first try to target their largest city
                                elseif(60 <= faiTargSelRand <= 79) {
                                        if(PlayerCityCount(FAI_WorstEnemyNum[faiTargPlayer]) > 0) {
                                                faiTargTmpCityIdx = GetLargestCity(FAI_WorstEnemyNum[faiTargPlayer]);
                                                if(GetCityByIndex(FAI_WorstEnemyNum[faiTargPlayer], faiTargTmpCityIdx, faiTargTmpCity)) {
                                                        faiTargTmpCityLoc = faiTargTmpCity.location;
                                                        faiTargTheirContinent = GetContinent(faiTargTmpCityLoc);
                                                        if(faiTargOurContinent == faiTargTheirContinent && !IsWater(faiTargTmpCityLoc)) {
                                                                FAI_AttackTarget[faiTargPlayer] = faiTargTmpCityLoc;
                                                                FAI_TaskOneFlag[faiTargPlayer] = 1;
                                                        }
                                                }
                                        }
                                }
                                // a 20% chance we first try to target their capital
                                elseif(80 <= faiTargSelRand <= 99) {
                                        if(PlayerCityCount(FAI_WorstEnemyNum[faiTargPlayer]) > 0) {
                                                faiTargTmpCityIdx = GetCapital(FAI_WorstEnemyNum[faiTargPlayer]);
                                                if(GetCityByIndex(FAI_WorstEnemyNum[faiTargPlayer], faiTargTmpCityIdx, faiTargTmpCity)) {
                                                        faiTargTmpCityLoc = faiTargTmpCity.location;
                                                        faiTargTheirContinent = GetContinent(faiTargTmpCityLoc);
                                                        if(faiTargOurContinent == faiTargTheirContinent && !IsWater(faiTargTmpCityLoc)) {
                                                                FAI_AttackTarget[faiTargPlayer] = faiTargTmpCityLoc;
                                                                FAI_TaskOneFlag[faiTargPlayer] = 1;
                                                        }
                                                }
                                        }
                                }
                        }
                }
                // Select neighboring tile - make sure the goal can be reached:
                if(FAI_TaskOneFlag[faiTargPlayer] == 1) {
                        if(!IsAllLandArmyTerrain(FAI_AttackTargetNeighbor[faiTargPlayer])) {
                                faiTargNeighborFound = 0;
                                for(faiTargCycle = 0; faiTargCycle < 8; faiTargCycle = faiTargCycle + 1) {
                                        if(GetNeighbor(FAI_AttackTarget[faiTargPlayer], faiTargCycle, faiTargNeighbor)) {
                                                if(IsAllLandArmyTerrain(faiTargNeighbor)) {
                                                        faiTargCycle = 8;
                                                        faiTargNeighborFound = 1;
                                                        FAI_AttackTargetNeighbor[faiTargPlayer] = faiTargNeighbor;
                                                }
                                        }
                                }
                                if(faiTargNeighborFound == 0) {
                                        FAI_TaskOneFlag[faiTargPlayer] = 0;
                                        FAI_AttackTargetNeighbor[faiTargPlayer] = faiTargEmptyLoc;
                                }
                                // TEST
                                //else {
                                //        AddCenter(FAI_AttackTargetNeighbor[faiTargPlayer]);
                                //        AddEffect(FAI_AttackTargetNeighbor[faiTargPlayer],"SPECEFFECT_UNHAPPINESS_SPACE","SOUND_ID_UNHAPPINESS_SPACE");
                                //}
                        }
                }
        }
}

HandleEvent(EndTurn) 'FAI_SetAttackLandTarget' pre {
        int_t faiSetPlayer;

        faiSetPlayer = player[0].owner;

        if(GetCurrentRound() > 2) {
                SetFrenzyLandTarget(faiSetPlayer);
        }
        return CONTINUE;
}

HandleEvent(MovePathOrder) 'FAI_ArmiesGetBiggerAndBigger' post {
        int_t faiBigPlayer;
       
        faiBigPlayer = army[0].owner;

        if(GetCurrentRound() > 2) {
                if(!IsHumanPlayer(faiBigPlayer) && faiBigPlayer > 0 && FAI_On[faiBigPlayer] == 1) {
                        if(army[0] == FAI_FirstArmy[faiBigPlayer]
                        || army[0] == FAI_SecondArmy[faiBigPlayer]
                        || army[0] == FAI_ThirdArmy[faiBigPlayer]
                        || army[0] == FAI_FourthArmy[faiBigPlayer]) {
                                if(CheckGroupage(army[0]) == 1) {
                                        Event:GroupOrder(army[0]);
                                }
                        }
                }
        }
}

HandleEvent(CaptureCity) 'FAI_TaskOneRecapture' pre {
        int_t recapPlayer;
        city_t recapCity;
        location_t recapCityLoc;
        int_t recapDistance;
        location_t recapAttackTarget;
        int_t recapPlayerCapIdx;
        city_t recapPlayerCap;
        int_t recapTargSel;
        location_t recapArmyLoc;
        int_t recapArmyFound;
        int_t recapArmyContinent;
        int_t recapTargetContinent;
        int_t recapDecisionMaker;
        int_t recapNeighborFound;
        location_t recapEmptyLoc;
        int_t recapTargCycle;
        location_t recapNeighbor;

        recapPlayer = city[0].owner;
        recapCity = city[0];
        recapCityLoc = city[0].location;

        if(GetCurrentRound() > 2) {
                if(!IsHumanPlayer(recapPlayer) && recapPlayer > 0 && FAI_On[recapPlayer] == 1) {
                        recapArmyFound = 0;
                        if(ArmyIsValid(FAI_FirstArmy[recapPlayer])) {
                                recapArmyLoc = FAI_FirstArmy[recapPlayer].location;
                                recapArmyFound = 1;
                        }
                        elseif(ArmyIsValid(FAI_SecondArmy[recapPlayer])) {
                                recapArmyLoc = FAI_SecondArmy[recapPlayer].location;
                                recapArmyFound = 1;
                        }
                        elseif(ArmyIsValid(FAI_ThirdArmy[recapPlayer])) {
                                recapArmyLoc = FAI_ThirdArmy[recapPlayer].location;
                                recapArmyFound = 1;
                        }
                        elseif(ArmyIsValid(FAI_FourthArmy[recapPlayer])) {
                                recapArmyLoc = FAI_FourthArmy[recapPlayer].location;
                                recapArmyFound = 1;
                        }
                        if(recapArmyFound == 1) {
                                recapArmyContinent = GetContinent(recapArmyLoc);
                                recapTargetContinent = GetContinent(recapCityLoc);
                                recapPlayerCapIdx = GetCapital(recapPlayer);
                                if(recapArmyContinent == recapTargetContinent && GetCityByIndex(recapPlayer, recapPlayerCapIdx, recapPlayerCap)) {
                                        // if one of our cities is captured and it's not the capital make it FAI_AttackTarget
                                        // and stay on it as long as needed -- if we already have a task,
                                        // ask the DecisionMaker if it needs to be accomplished :-)
                                        if(recapCity != recapPlayerCap) {
                                                recapDecisionMaker = Random(100);
                                                if(FAI_TaskOneFlag[recapPlayer] == 0
                                                || (FAI_TaskOneFlag[recapPlayer] == 1 && 0 <= recapDecisionMaker <= 49)) {
                                                        if(!IsWater(recapCityLoc)) {
                                                        FAI_AttackTarget[recapPlayer] = recapCityLoc;
                                                                FAI_TaskOneFlag[recapPlayer] = 1;
                                                        }
                                                }
                                        }
                                        // if they take our capital (1.) someone will have to talk to the president
                                        // (has anybody seen him the last two days?), (2.) we will use all available
                                        // Frenzy Forces to get it back (though this will very likely be one of our last
                                        // heroic efforts ...)
                                        if(recapCity == recapPlayerCap) {
                                                if(!IsWater(recapCityLoc)) {
                                                        FAI_AttackTarget[recapPlayer] = recapCityLoc;
                                                        FAI_TaskOneFlag[recapPlayer] = 1;
                                                }
                                        }
                                }
                        }
                        // Select neighboring tile - make sure the goal can be reached:
                        if(FAI_TaskOneFlag[recapPlayer] == 1) {
                                if(!IsAllLandArmyTerrain(FAI_AttackTargetNeighbor[recapPlayer])) {
                                        recapNeighborFound = 0;
                                        for(recapTargCycle = 0; recapTargCycle < 8; recapTargCycle = recapTargCycle + 1) {
                                                if(GetNeighbor(FAI_AttackTarget[recapPlayer], recapTargCycle, recapNeighbor)) {
                                                        if(IsAllLandArmyTerrain(recapNeighbor)) {
                                                                recapTargCycle = 8;
                                                                recapNeighborFound = 1;
                                                                FAI_AttackTargetNeighbor[recapPlayer] = recapNeighbor;
                                                        }
                                                }
                                        }
                                        if(recapNeighborFound == 0) {
                                                FAI_TaskOneFlag[recapPlayer] = 0;
                                                FAI_AttackTargetNeighbor[recapPlayer] = recapEmptyLoc;
                                        }
                                        // TEST
                                        //else {
                                        //        AddCenter(FAI_AttackTargetNeighbor[recapPlayer]);
                                        //        AddEffect(FAI_AttackTargetNeighbor[recapPlayer],"SPECEFFECT_UNHAPPINESS_SPACE","SOUND_ID_UNHAPPINESS_SPACE");
                                        //}
                                }
                        }
                }
        }
        return CONTINUE;
}

HandleEvent(CaptureCity) 'FAI_GarrisonCity' post {
        city_t faiGarrisonCity;
        int_t faiGarrisonPlayer;
        location_t faiGarrisonLoc;
        unit_t faiGarrisonUnit;
        army_t faiGarrisonArmy;
        army_t faiGarrisonEmptyArmy;
        int_t faiGarrisonCount;

        faiGarrisonCity = city[0];
        faiGarrisonPlayer = city[0].owner;
        faiGarrisonLoc = city[0].location;

        if(!IsHumanPlayer(faiGarrisonPlayer)) {
                if(CityIsValid(faiGarrisonCity) && UnitsInCell(faiGarrisonLoc) > 0) {
                        if(GetUnitFromCell(faiGarrisonLoc, 0, faiGarrisonUnit)) {
                                if(GetArmyFromUnit(faiGarrisonUnit, faiGarrisonArmy)) {
                                        if(ArmyIsValid(faiGarrisonArmy)) {
                                                if(faiGarrisonArmy == FAI_FirstArmy[faiGarrisonPlayer]) {
                                                        FAI_FirstArmy[faiGarrisonPlayer] = faiGarrisonEmptyArmy;
                                                }
                                                elseif(faiGarrisonArmy == FAI_SecondArmy[faiGarrisonPlayer]) {
                                                        FAI_SecondArmy[faiGarrisonPlayer] = faiGarrisonEmptyArmy;
                                                }
                                                elseif(faiGarrisonArmy == FAI_ThirdArmy[faiGarrisonPlayer]) {
                                                        FAI_ThirdArmy[faiGarrisonPlayer] = faiGarrisonEmptyArmy;
                                                }
                                                elseif(faiGarrisonArmy == FAI_FourthArmy[faiGarrisonPlayer]) {
                                                        FAI_FourthArmy[faiGarrisonPlayer] = faiGarrisonEmptyArmy;
                                                }
                                                Event:EntrenchOrder(faiGarrisonArmy);
                                                // ExecuteArmyOrders(faiGarrisonArmy, faiGarrisonArmy.location);
                                        }
                                }
                        }
                }
        }
}