123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OU_GOD2.CPP
- //Description: God Unit - AI functions
- #include <OGODRES.h>
- #include <ORACERES.h>
- #include <OF_CAMP.h>
- #include <OU_GOD.h>
- //------- 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 ; j<firmPtr->worker_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 --------//
- //
- // <int&> targetXLoc, targetYLoc - reference vars for returning the
- // location of the target.
- //
- // return: <int> 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
|