/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OU_GOD2.CPP //Description: God Unit - AI functions #include #include #include #include //------- Begin of function UnitGod::process_ai --------// void UnitGod::process_ai() { if( !is_ai_all_stop() ) return; if( info.game_date%7 != sprite_recno%7 ) return; switch( god_id ) { case GOD_NORMAN: think_dragon(); break; case GOD_MAYA: think_maya_god(); break; case GOD_GREEK: think_phoenix(); break; case GOD_VIKING: think_viking_god(); break; case GOD_PERSIAN: think_persian_god(); break; case GOD_CHINESE: think_chinese_dragon(); break; case GOD_JAPANESE: think_japanese_god(); break; #if(MAX_RACE > 7) case GOD_EGYPTIAN: think_egyptian_god(); break; case GOD_INDIAN: think_indian_god(); break; case GOD_ZULU: think_zulu_god(); break; #endif } } //------- End of function UnitGod::process_ai --------// //------- Begin of function UnitGod::think_dragon --------// void UnitGod::think_dragon() { int targetXLoc, targetYLoc; if( think_god_attack_target(targetXLoc, targetYLoc) ) attack_firm( targetXLoc, targetYLoc ); } //------- End of function UnitGod::think_dragon --------// //------- Begin of function UnitGod::think_chinese_dragon --------// void UnitGod::think_chinese_dragon() { int targetXLoc, targetYLoc; if( think_god_attack_target(targetXLoc, targetYLoc) ) attack_firm( targetXLoc, targetYLoc ); } //------- End of function UnitGod::think_chinese_dragon --------// //------- Begin of function UnitGod::think_phoenix --------// void UnitGod::think_phoenix() { int xLoc = m.random(MAX_WORLD_X_LOC); int yLoc = m.random(MAX_WORLD_Y_LOC); move_to( xLoc, yLoc ); } //------- End of function UnitGod::think_phoenix --------// //------- Begin of function UnitGod::think_viking_god --------// void UnitGod::think_viking_god() { int targetXLoc, targetYLoc; if( think_god_attack_target(targetXLoc, targetYLoc) ) { go_cast_power(targetXLoc+1, targetYLoc+1, 2, COMMAND_AI); // 2 - cast power type } } //------- End of function UnitGod::think_viking_god --------// //------- Begin of function UnitGod::think_persian_god --------// void UnitGod::think_persian_god() { //------- there is no action, now think a new one ------// Nation* ownNation = nation_array[nation_recno]; Firm* firmPtr; int curRating, bestRating=0; int targetXLoc, targetYLoc; for( int i=ownNation->ai_camp_count-1 ; i>=0 ; i-- ) { firmPtr = firm_array[ ownNation->ai_camp_array[i] ]; //----- calculate the injured rating of the camp ----// Worker* workerPtr = firmPtr->worker_array; int totalHitPoints = 0; int totalMaxHitPoints = 0; for( int j=0 ; jworker_count ; j++, workerPtr++ ) { totalHitPoints += workerPtr->hit_points; totalMaxHitPoints += workerPtr->max_hit_points(); } if( !totalMaxHitPoints ) continue; curRating = 100 * (totalMaxHitPoints-totalHitPoints) / totalMaxHitPoints; //---- if the king is the commander of this camp -----// if( firmPtr->overseer_recno && unit_array[firmPtr->overseer_recno]->rank_id == RANK_KING ) { curRating += 20; } if( curRating > bestRating ) { bestRating = curRating; targetXLoc = firmPtr->center_x; targetYLoc = firmPtr->center_y; } } //-------------------------------------// if( bestRating ) { go_cast_power(targetXLoc, targetYLoc, 1, COMMAND_AI); // 1 - cast power type } } //------- End of function UnitGod::think_persian_god --------// //------- Begin of function UnitGod::think_japanese_god --------// void UnitGod::think_japanese_god() { //------- there is no action, now think a new one ------// Nation* ownNation = nation_array[nation_recno]; int curRating, bestRating=0; int targetXLoc, targetYLoc; //------ think firm target --------// if( m.random(2)==0 ) { for( int i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; Firm* firmPtr = firm_array[i]; //------- only cast on camps ---------// if( firmPtr->firm_id != FIRM_CAMP ) continue; //------ only cast on hostile and tense nations ------// if( ownNation->get_relation(firmPtr->nation_recno)->status > NATION_TENSE ) continue; //------ calculate the rating of the firm -------// curRating = ((FirmCamp*)firmPtr)->total_combat_level()/10; if( curRating > bestRating ) { bestRating = curRating; targetXLoc = firmPtr->center_x; targetYLoc = firmPtr->center_y; } } } else { //------ think town target --------// for( int i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; Town* townPtr = town_array[i]; //------ only cast on hostile and tense nations ------// if( townPtr->nation_recno && ownNation->get_relation(townPtr->nation_recno)->status > NATION_TENSE ) continue; //------ calculate the rating of the firm -------// curRating = townPtr->population + (100-townPtr->average_loyalty()); if( curRating > bestRating ) { bestRating = curRating; targetXLoc = townPtr->center_x; targetYLoc = townPtr->center_y; } } } //-------------------------------------// if( bestRating ) { go_cast_power(targetXLoc, targetYLoc, 1, COMMAND_AI); // 1 - cast power type } } //------- End of function UnitGod::think_japanese_god --------// //------- Begin of function UnitGod::think_god_attack_target --------// // // targetXLoc, targetYLoc - reference vars for returning the // location of the target. // // return: 1 - target selected // 0 - no target selected // int UnitGod::think_god_attack_target(int& targetXLoc, int& targetYLoc) { Firm* firmPtr; Nation* ownNation = nation_array[nation_recno]; int curXLoc=next_x_loc(), curYLoc=next_y_loc(); int totalFirm = firm_array.size(); int firmRecno = m.random(totalFirm)+1; int i; for( i=totalFirm ; i>0 ; i-- ) { if( ++firmRecno > totalFirm ) firmRecno = 1; if( firm_array.is_deleted(firmRecno) ) continue; firmPtr = firm_array[firmRecno]; if( firmPtr->firm_id == FIRM_MONSTER ) continue; //-------- only attack enemies ----------// if( ownNation->get_relation(firmPtr->nation_recno)->status != NATION_HOSTILE ) continue; //---- only attack enemy base and camp ----// if( firmPtr->firm_id != FIRM_BASE && firmPtr->firm_id != FIRM_CAMP ) { continue; } //------- attack now --------// targetXLoc = firmPtr->loc_x1; targetYLoc = firmPtr->loc_y1; return 1; } //----- if there is no enemy to attack, attack Fryhtans ----// for( i=totalFirm ; i>0 ; i-- ) { if( ++firmRecno > totalFirm ) firmRecno = 1; if( firm_array.is_deleted(firmRecno) ) continue; firmPtr = firm_array[firmRecno]; if( firmPtr->firm_id == FIRM_MONSTER ) { targetXLoc = firmPtr->loc_x1; targetYLoc = firmPtr->loc_y1; return 1; } } //---------------------------------------------------// return 0; } //------- End of function UnitGod::think_god_attack_target --------// //------- Begin of function UnitGod::think_maya_god --------// void UnitGod::think_maya_god() { //------- there is no action, now think a new one ------// Nation* ownNation = nation_array[nation_recno]; Firm* firmPtr; int curRating, bestRating=0; int targetXLoc, targetYLoc; for( int i=ownNation->ai_camp_count-1 ; i>=0 ; i-- ) { firmPtr = firm_array[ ownNation->ai_camp_array[i] ]; curRating = 0; if( firmPtr->overseer_recno ) { Unit* unitPtr = unit_array[firmPtr->overseer_recno]; if( unitPtr->race_id == RACE_MAYA && unitPtr->skill.combat_level < 100 ) curRating += 10; } Worker* workerPtr = firmPtr->worker_array; for( int j=firmPtr->worker_count-1 ; j>=0 ; j--, workerPtr++ ) { if( workerPtr->race_id == RACE_MAYA && workerPtr->combat_level < 100 ) curRating += 5; } if( curRating > bestRating ) { bestRating = curRating; targetXLoc = firmPtr->center_x; targetYLoc = firmPtr->center_y; } } //-------------------------------------// if( bestRating ) { go_cast_power(targetXLoc, targetYLoc, 1, COMMAND_AI); // 1 - cast power type } } //------- End of function UnitGod::think_maya_god --------// #ifdef AMPLUS //------- Begin of function UnitGod::think_egyptian_god --------// void UnitGod::think_egyptian_god() { Nation* ownNation = nation_array[nation_recno]; int curRating, bestRating=0; int targetXLoc, targetYLoc; for( int i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; Town* townPtr = town_array[i]; //------ only cast on own nations ------// if( townPtr->nation_recno != nation_recno ) continue; //------ calculate the rating of the firm -------// if( townPtr->population > MAX_TOWN_GROWTH_POPULATION - 5 ) continue; // maximize the total loyalty gain. curRating = 5 * townPtr->average_loyalty(); // calc rating on the number of people if( townPtr->population >= MAX_TOWN_GROWTH_POPULATION/2 ) curRating -= (townPtr->population - MAX_TOWN_GROWTH_POPULATION/2) * 300 / MAX_TOWN_GROWTH_POPULATION; else curRating -= (MAX_TOWN_GROWTH_POPULATION/2 - townPtr->population) * 300 / MAX_TOWN_GROWTH_POPULATION; if( curRating > bestRating ) { bestRating = curRating; targetXLoc = townPtr->center_x; targetYLoc = townPtr->center_y; } } //-------------------------------------// if( bestRating ) { go_cast_power(targetXLoc, targetYLoc, 1, COMMAND_AI); // 1 - cast power type } } //------- End of function UnitGod::think_egyptian_god --------// //------- Begin of function UnitGod::think_indian_god --------// void UnitGod::think_indian_god() { Nation* ownNation = nation_array[nation_recno]; // see if any unit near by int castRadius = 2; int leftLocX = next_x_loc() - castRadius; if(leftLocX < 0) leftLocX = 0; int rightLocX = next_x_loc() + castRadius; if(rightLocX >= MAX_WORLD_X_LOC) rightLocX = MAX_WORLD_X_LOC-1; int topLocY = next_y_loc() - castRadius; if(topLocY < 0) topLocY = 0; int bottomLocY = next_y_loc() + castRadius; if(bottomLocY >= MAX_WORLD_Y_LOC) bottomLocY = MAX_WORLD_Y_LOC-1; int curRating = 0; int xLoc, yLoc; for( yLoc = topLocY; yLoc <= bottomLocY; ++yLoc) { for( xLoc = leftLocX; xLoc <= rightLocX; ++xLoc ) { Location *locPtr = world.get_loc(xLoc, yLoc); int unitRecno; Unit *unitPtr; if( locPtr->has_unit(UNIT_LAND) && (unitRecno = locPtr->unit_recno(UNIT_LAND)) && !unit_array.is_deleted(unitRecno) && (unitPtr = unit_array[unitRecno]) && unitPtr->nation_recno // don't affect indepedent unit && unitPtr->nation_recno != nation_recno && (unitPtr->loyalty >= 20 && unitPtr->loyalty <= 60 || unitPtr->loyalty <= 80 && unitPtr->target_loyalty < 30) ) { switch( ownNation->get_relation(unitPtr->nation_recno)->status ) { case NATION_HOSTILE: curRating += 3; break; case NATION_TENSE: case NATION_NEUTRAL: // curRating += 0; // unchange break; case NATION_FRIENDLY: curRating -= 1; // actually friendly humans are not affected break; case NATION_ALLIANCE: curRating -= 1; // actually allied humans are not affected break; default: err_here(); } } } } if( curRating > 1 ) { // if enemy unit come near, cast go_cast_power(next_x_loc(), next_y_loc(), 1, COMMAND_AI); // 1 - cast power type } else { // find any unit suitable, go to that area first int bestUnitCost = 20000; for( int unitRecno = unit_array.size(); unitRecno > 0; --unitRecno ) { Unit *unitPtr; if( !unit_array.is_deleted(unitRecno) && (unitPtr = unit_array[unitRecno]) && unitPtr->is_visible() && unitPtr->mobile_type == UNIT_LAND && unitPtr->nation_recno // don't affect indepedent unit && unitPtr->nation_recno != nation_recno && (unitPtr->loyalty >= 20 && unitPtr->loyalty <= 60 || unitPtr->loyalty <= 80 && unitPtr->target_loyalty < 30) && ownNation->get_relation(unitPtr->nation_recno)->status == NATION_HOSTILE ) { int cost = m.points_distance(next_x_loc(), next_y_loc(), unitPtr->next_x_loc(), unitPtr->next_y_loc()); if( cost < bestUnitCost ) { bestUnitCost = cost; xLoc = unitPtr->next_x_loc(); yLoc = unitPtr->next_y_loc(); } } } if( bestUnitCost < 100 ) { if( m.points_distance(next_x_loc(), next_y_loc(), xLoc, yLoc) <= god_res[god_id]->cast_power_range ) go_cast_power(xLoc, yLoc, 1, COMMAND_AI); // 1 - cast power type else move_to( xLoc, yLoc ); } else if( m.random(4) == 0 ) { // move to a near random location xLoc = next_x_loc() + m.random(100) - 50; if( xLoc < 0 ) xLoc = 0; if( xLoc >= MAX_WORLD_X_LOC) xLoc = MAX_WORLD_X_LOC-1; yLoc = next_y_loc() + m.random(100) - 50; if( yLoc < 0 ) yLoc = 0; if( yLoc >= MAX_WORLD_Y_LOC) yLoc = MAX_WORLD_Y_LOC-1; move_to( xLoc, yLoc ); } } } //------- End of function UnitGod::think_indian_god --------// //------- Begin of function UnitGod::think_zulu_god --------// void UnitGod::think_zulu_god() { //------- there is no action, now think a new one ------// Nation* ownNation = nation_array[nation_recno]; Firm* firmPtr; int curRating, bestRating=0; int targetXLoc, targetYLoc; for( int i=ownNation->ai_camp_count-1 ; i>=0 ; i-- ) { firmPtr = firm_array[ ownNation->ai_camp_array[i] ]; curRating = 0; Unit* unitPtr; if( firmPtr->overseer_recno && (unitPtr = unit_array[firmPtr->overseer_recno]) && unitPtr->race_id == RACE_ZULU // only consider ZULU leader && unitPtr->skill.skill_level <= 70) { if( unitPtr->rank_id == RANK_KING ) curRating += 5000; // weak king need leadership very much if( unitPtr->skill.skill_level >= 40 ) curRating += 5000 - (unitPtr->skill.skill_level - 40) * 60; // strong leader need not be enhanced else curRating += 5000 - (40 - unitPtr->skill.skill_level) * 80; // don't add weak leader // calculat the benefits to his soldiers Worker* workerPtr = firmPtr->worker_array; for( int j=firmPtr->worker_count-1 ; j>=0 ; j--, workerPtr++ ) { if( workerPtr->race_id == RACE_ZULU ) curRating += (unitPtr->skill.combat_level - workerPtr->combat_level)*2; else curRating += unitPtr->skill.combat_level - workerPtr->combat_level; } if( curRating > bestRating ) { bestRating = curRating; targetXLoc = firmPtr->center_x; targetYLoc = firmPtr->center_y; } } } //-------------------------------------// if( bestRating ) { go_cast_power(targetXLoc, targetYLoc, 1, COMMAND_AI); // 1 - cast power type } } //------- End of function UnitGod::think_zulu_god --------// #endif