//////////////////////////////////////////////////////// // // The Father Code! Pedrunn's AI v0.1 // // This is a SLIC code that teachs the AI how to uses its units. // It works by evaluating and defining the best city target among all // the cities in the game. Meanwhile huge stacks are being formed near // the AI strategic Cities like capital and edges cities. The cities // will only send unit to this armies in case its defense are ok for // the current threat stage which is also defined in this slic. Once // Reached this value the units will move to the one tile near the // Mentioned strategic cities. These armies near strategic cities will // not move until not reachs a good size. Once this size is reached // the Armies attacks the target in which was defined early on. The // may send more then one stack depending on the city protection and // the army attack value! // The Attack only happens in case the AI is faded to win the battle // even if more is needed and is found near the chosen city target. // This makes the AI attacks fulminating and well strategic guided. // //////////////////////////////////////////////////////// int_t PAI_ATTACK_SIZE; // Size for the Attack forces int_t PAI_MAX_DEFENSE; // Minimum number of unit a city must have int_t DoMove; // A unit can only move if = 1 to prevent original AI moves (unimplementd) location_t PAI_ArmyTarget[]; // Target to send Land Attack forces location_t PAI_NavyTarget[]; // Target to send Sea Attack forces army_t PAI_MainArmy[]; // The Army Itself int_t PAI_ArmyOwner[]; // Who owns the Army int_t PAI_ArmyType[]; // 1 for Land, 2 for Sea; 3 for Air; (4 for Undersea?) // If the terrain is Land return true int_f IsLandTerrain(location_t tmpLoc) { int_t TType; TType = TerrainType(tmpLoc); if (TType == TerrainDB(TERRAIN_GRASSLAND) || TType == TerrainDB(TERRAIN_PLAINS) || TType == TerrainDB(TERRAIN_DESERT) || TType == TerrainDB(TERRAIN_TUNDRA) || TType == TerrainDB(TERRAIN_GLACIER) || TType == TerrainDB(TERRAIN_HILL) || TType == TerrainDB(TERRAIN_BROWN_HILL) || TType == TerrainDB(TERRAIN_WHITE_HILL) || TType == TerrainDB(TERRAIN_FOREST) || TType == TerrainDB(TERRAIN_JUNGLE) || TType == TerrainDB(TERRAIN_MOUNTAIN) || TType == TerrainDB(TERRAIN_BROWN_MOUNTAIN) || TType == TerrainDB(TERRAIN_WHITE_MOUNTAIN) || TType == TerrainDB(TERRAIN_SWAMP) || TType == TerrainDB(TERRAIN_DEAD)){ return 1; } return 0; } // Remember to do this! // Function to return true if a battle has victory certain among two stack (CTP2 See combat formula) int_f PAI_IsVictoryCertain() { } // Stolen from BlueO's Frenzy AI // find direction of human assets // Return locaation from 0-7 or return 10 // (Needs to be improved to see how many units around the city there is! // And if the city should be attacked in this turn in cases there are indeed enough units enough the target to launch attack int_f PAI_AttackEvaluateLocation(location_t evalLoc, int_t evalPlayer) { int_t i; city_t tmpCity; unit_t tmpUnit; location_t tmpLoc; for (i=0; i<=7 ; i=i+1) { tmpLoc = evalLoc; GetNeighbor(tmpLoc, i, tmpLoc); if (GetCityByLocation(tmpLoc, tmpCity)) { if(CityIsValid(tmpCity) && PAI_ArmyTarget[evalPlayer] == tmpCity.location) { return i; } } // This was removen to only attack the defined targets // but would be a nice a fix for this, making the AI attack weaker stacks! // elseif (GetUnitsAtLocation(tmpLoc) > 0) { // GetUnitFromCell(tmpLoc, 0, tmpUnit); // if(tmpUnit.valid == 1 // && tmpUnit.owner == tmpCity.owner) { // return i; // } // } } return 10; // no target found } // Function to return the willing to attack a certain city // since it will check how important this city will be for the attacker // (formulas are unbalanced) int_f CheckCityValue(city_t theCity, int_t thePlayer) { int_t c; int_t u; int_t tmpDist; int_t theDist; int_t EmpireDist; int_t CapitalDist; int_t tmpPlayer; int_t IsAttacking; int_t CityValue; city_t tmpCity; city_t NearCity; city_t CapitalCity; city_t checkCity; unit_t tmpUnit; tmpCity = theCity; tmpPlayer = thePlayer; theDist = 99999; // Get Nearest City and Capital for (c = 0; c < tmpPlayer.cities; c = c + 1){ GetCityByIndex(tmpPlayer, c, checkCity); tmpDist = distance(checkCity.location, tmpCity.location); if(tmpDist < theDist) { NearCity = checkCity; theDist = tmpDist; } if(CityHasBuilding(checkCity, "IMPROVE_CAPITOL")) { CapitalCity = checkCity; } } // Distances from the evaluated city to nearestciy and Capital EmpireDist = distance(tmpCity.location, NearCity); CapitalDist = distance(tmpCity.location, CapitalCity); // City Characteristics CityPop = tmpCity.population; CityHap = 60 - (tmpCity.happiness); CityFood = CityFoodDelta(tmpCity); CityGold = tmpCity.netcitygold; if(CityHasBuilding(tmpCity, "IMPROVE_CAPITOL")) { IsCapital = 1; } // Number of units inside the city for (u = 0; u < GetUnitsAtLocation(tmpCity.location); u = u + 1){ GetUnitFromCell(tmpCity.location, u, tmpUnit); if(tmpUnit.valid == 1) { unitrecord[0] = tmpUnit.type; CityAtt = CityAtt + unitrecord[0].attack; CityDef = CityDef + unitrecord[0].defense; CityRan = CityRan + unitrecord[0].ranged; } } // Diplomatic Advisor Interfernce if(GetLastHotWarAttack(tmpCity.owner, tmpPlayer) < 30 || GetLastColdWarAttack(tmpCity.owner, tmpPlayer) < 30) { IsAttacking = 1; } PlayerRegard = 500 - (GetEffectiveRegard(tmpPlayer, tmpCity.owner)); PlayerHate = 200*(EffectiveWarWith(tmpCity.owner, tmpPlayer) + 100*(IsAttacking); PlayerValue = 20*(HasAgreement(tmpCity.owner, tmpPlayer, 33)) + 20*(HasAgreement(tmpCity.owner, tmpPlayer, 34)) + 20*(HasAgreement(tmpCity.owner, tmpPlayer, 35)) + 50*(HasAgreement(tmpCity.owner, tmpPlayer, 36)) + 20*(HasAgreement(tmpCity.owner, tmpPlayer, 37)) + 100*(HasAgreement(tmpCity.owner, tmpPlayer, 38)); // Give the City its value CityValue = (-20)*EmpireDist // Settler Advisor + (-2)*CapitalDist // Settler Advisor + (10)*CityPop // Domestic Advisor + (2)*CityHap // Domestic Advisor + (1)*CityFood // Domestic Advisor + (1)*CityGold // Domestic Advisor + (50)*IsCapital // Domestic Advisor + (1)*PlayerRegard // Diplomatic Advisor + (1)*PlayerHate // Diplomatic Advisor + (1)*PlayerValue // Diplomatic Advisor + (1)*CityAtt/5 // Military Advisor + (1)*CityDef/5 // Military Advisor + (1)*CityRan/5; // Military Advisor // Return the value return CityValue; } // A function to check the size of the continent of location // using if(ContinentSize(tmpLoc1) == ContinentSize(tmpLoc2)) { // We affirm that two locations is the the same continent // note: It round up numbers to pairs int_f ContinentSize(location_t theLoc) { int_t tmpSize1; int_t tmpSize2; int_t sucess; location_t tmpLoc; tmpLoc = theLoc; while(tmpSize < 10000 && sucess == 0) { if(!IsContinentBiggerThan(tmpLoc, tmpSize) sucess = 1; } tmpSize = tmpSize + 2; // pair values to save some time } return tmpSize; } // Remember to do this! int_f IsLandArmy(army_t theArmy) { return 1; } HandleEvent(BeginTurn) 'FindTheTarget' pre { int_t p; int_t c; int_t i; int_t j; int_t a; int_t h; int_t sucess; int_t CityValue; int_t BestValue; int_t IsCityDefense; int_t EnoughArmies; int_t tmpDist; int_t theDist; city_t tmpCity; city_t BestTarget; army_t tmpArmy; army_t saveArmy; if(!IsHumanPlayer(player[0]) && IsPlayerAlive(player[0])) { // Find the best Target! if(player[0].militaryunits > 0 for (p = 1; p < 30; p = p + 1){ if(IsPlayerAlive(p) && p != player[0]) { for (c = 0; c < p.cities; c = c + 1 ){ GetCityByIndex(p, c, tmpCity); // scroll over all cities in the game if(CityIsValid(tmpCity)){ // Checking the city value CityValue = CheckCityValue(tmpCity, player[0]); if(CityValue > BestValue){ // And in case the city has the highes value BestValue = CityValue; // The attack will be there BestTarget = tmpCity; } } } } } PAI_AttackTarget[player[0]] = BestTarget.location; } // Move units outside cities to the Attack Forces and organize armies for(j = 0; j < player[0].armies; j = j + 1){ GetArmyByIndex(player[0], j, tmpArmy); c = 0; if(ArmyIsValid(tmpArmy)) { if(IsLandArmy(tmpArmy)) { // Just works for land units! while(c < player[0].cities && IsCityDefense == 0) { GetCityByIndex(player[0], c, tmpCity); if(CityIsValid(tmpCity) && tmpCity.location == tmpArmy.location){ IsCityDefense = 1; } c = c + 1; } if(IsCityDefense == 0) { // if is a field unit, move it to Attack Forces theDist = 200; sucess = 0; // find an army to send this unit to group for(a = 0; a < PAI_MainArmy.#; a = a + 1) { if(PAI_ArmyOwner[a] == player[0] && ArmyIsValid(PAI_MainArmy[a]) && tmpArmy != PAI_MainArmy[a] && PAI_MainArmy[a] < PAI_ATTACK_SIZE && (12 - PAI_MainArmy[a].size) > (tmpArmy.size) // make sure the army fits ) { tmpDist = distance(tmpArmy.location, PAI_MainArmy[a]); if(ContinentSize(PAI_MainArmy[a].location) == ContinentSize(tmpArmy.location) ) { if(tmpDist < theDist) { theDist = tmpDist; saveArmy = PAI_MainArmy[a] sucess = 1; } } else{ // Is in Another continent, make cross water Invasion code } } } // If army found Send the army to the Attack Force if(ArmyIsValid(saveArmy) // This is redunctant && sucess == 1) { Event: MovePathOrder(tmpArmy, saveArmy.location); } // if no good Attack Force found to add this army else{ // make this Army a Attack Force // storing it in the arrays while(sucess == 0 && h < PAI_MainArmy.#) { if(!ArmyIsValid(PAI_MainArmy[h])) { PAI_MainArmy[h] = tmpArmy; PAI_ArmyType[h] = 1; PAI_ArmyOwner[h]= player[0]; } } if(sucess == 0) { PAI_MainArmy[PAI_MainArmy.#] = tmpArmy; PAI_ArmyType[PAI_MainArmy.#] = 1; PAI_ArmyOwner[PAI_MainArmy.#]= player[0]; } } } else{ // If army is city defense, the units in the city must be ungrouped in case Event: UngroupOrder(tmpArmy); } } else{ // Code for sea units grouping! } } } // Send Attack Force to target // Buildings Handler } } // Make units leave the city if the city is very well protected // Since field units will serve for build attack forces HandleEvent(CreateUnit) 'MoveUnitsOutsideCities' post { int_t i; int_t u; int_t j; int_t sucess; unit_t tmpUnit; army_t tmpArmy; location_t tmpLoc; location_t cityLoc; location_t armyLoc; if(CityIsValid(city[0]) && !IsHumanPlayer(city[0].owner)){ cityLoc = city[0].location; unitrecord[0] = value[0]; if(GetUnitsAtLocation(cityLoc) > PAI_MAX_DEFENSE // if the city is very well defensed && unitrecord[0].attack > 0) { // if a military units was built! while(i < 8 && sucess == 0){ GetNeighbor(cityLoc, i, tmpLoc) // look for a good dircetion it can go if(IsLandTerrain(tmpLoc) && !IsUnderseaCity(city[0])) { // (Just works for land units!) while(u < GetUnitsAtLocation(cityLoc) && sucess == 0) { GetUnitFromCell(cityLoc, u, tmpUnit); GetArmyFromUnit(tmpUnit, tmpArmy); if(tmpUnit.type == unitrecord[0] && IsLandArmy(tmpArmy)) { // (Just works for land units!) DoMove = 1; sucess = 1; Event: MoveToOrder(tmpArmy, i); // And make it leave the City } u = u + 1; } } i = i + 1; } } } }