/* * 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 : OSPY.CPP //Description : Object Spy #include #include #include #include #include #include #include #include #include #include #include #include #include #include //----- Define constants for viewing secret menu ------// #define SECRET_REPORT_COUNT 7 static char* secret_report_str_array[] = { "Kingdoms", "Villages", "Economy", "Trade", "Military", "Technology", "Espionage" }; static char secret_view_mode_array[] = { MODE_NATION, MODE_TOWN, MODE_ECONOMY, MODE_TRADE, MODE_MILITARY, MODE_TECH, MODE_SPY }; static char secret_view_skill_array[] = { 40, 20, 30, 30, 50, 40, 90 }; static Button button_secret_report_array[SECRET_REPORT_COUNT]; static Button button_secret_report_cancel; //--------- Begin of function SpyArray::SpyArray ----------// SpyArray::SpyArray() : DynArrayB(sizeof(Spy), 10) { } //--------- End of function SpyArray::SpyArary ----------// //------- Begin of function SpyArray::~SpyArray ----------// // SpyArray::~SpyArray() { deinit(); } //--------- End of function SpyArray::~SpyArray ----------// //--------- Begin of function SpyArray::init ----------// // void SpyArray::init() { } //---------- End of function SpyArray::init ----------// //--------- Begin of function SpyArray::deinit ----------// // void SpyArray::deinit() { if( size()==0 ) return; //-------- zap the array -----------// zap(); } //---------- End of function SpyArray::deinit ----------// //--------- Begin of function SpyArray::add_spy ----------// // // unitRecno - unit recno of the spy // spySkill - spying skill of the unit // // return: recno of the spy record added // int SpyArray::add_spy(int unitRecno, int spySkill) { Spy spy; Unit* unitPtr = unit_array[unitRecno]; memset( &spy, 0, sizeof(spy) ); spy.spy_place = SPY_MOBILE; spy.spy_place_para = unitRecno; spy.spy_skill = spySkill; spy.spy_loyalty = unitPtr->loyalty; spy.race_id = unitPtr->race_id; spy.name_id = unitPtr->name_id; err_when( unitPtr->race_id < 1 || unitPtr->race_id > MAX_RACE ); err_when( nation_array.is_deleted(unitPtr->nation_recno) ); spy.true_nation_recno = unitPtr->nation_recno; spy.cloaked_nation_recno = unitPtr->nation_recno; //--- spies hold a use right of the name id even though the unit itself will register the usage right of the name already ---// race_res[spy.race_id]->use_name_id(spy.name_id); // the spy will free it up in deinit(). Keep an additional right because when a spy is assigned to a town, the normal program will free up the name id., so we have to keep an additional copy //------- link in the spy_array -------// linkin( &spy ); ((Spy*)get())->spy_recno = recno(); return recno(); } //---------- End of function SpyArray::add_spy ----------// //--------- Begin of function SpyArray::add_spy ----------// // // This overloaded version of add_spy() just add a spy without // setting parameters of the Spy. // // return: recno of the spy record added // int SpyArray::add_spy() { Spy spy; memset( &spy, 0, sizeof(spy) ); linkin( &spy ); ((Spy*)get())->spy_recno = recno(); return recno(); } //---------- End of function SpyArray::add_spy ----------// //--------- Begin of function SpyArray::del_spy ----------// // // spyRecno - recno of the spy to be deleted // void SpyArray::del_spy(int spyRecno) { spy_array[spyRecno]->deinit(); linkout(spyRecno); } //---------- End of function SpyArray::del_spy ----------// //--------- Begin of function SpyArray::next_day ----------// // void SpyArray::next_day() { int spyCount = size(); Spy* spyPtr; for( int i=1 ; i<=spyCount ; i++ ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; spyPtr->next_day(); if( spy_array.is_deleted(i) ) continue; if( nation_array[spyPtr->true_nation_recno]->is_ai() ) spyPtr->process_ai(); } //---------- update Firm::sabotage_level ----------// if( info.game_date%15==0 ) process_sabotage(); } //---------- End of function SpyArray::next_day ----------// //--------- Begin of function SpyArray::find_town_spy ----------// // // Find a spy meeting the specific criteria // // townRecno - town recno of the spy to find // raceId - race id. of the spy to find // spySeq - sequence id. of the spy in spy_array // // return: recno of the spy found // int SpyArray::find_town_spy(int townRecno, int raceId, int spySeq) { int spyCount=size(), matchCount=0; Spy* spyPtr; for( int i=1 ; i<=spyCount ; i++ ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place==SPY_TOWN && spyPtr->spy_place_para==townRecno && spyPtr->race_id==raceId ) { if( ++matchCount == spySeq ) return i; } } return 0; } //---------- End of function SpyArray::find_town_spy ----------// //--------- Begin of function SpyArray::process_sabotage ----------// // void SpyArray::process_sabotage() { Spy* spyPtr; Firm* firmPtr; //-------- reset firms' sabotage_level -------// int i; for( i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firm_array[i]->sabotage_level = 0; } //------- increase firms' sabotage_level -----// for( i=spy_array.size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->action_mode == SPY_SABOTAGE ) { err_when( spyPtr->spy_place != SPY_FIRM ); firmPtr = firm_array[spyPtr->spy_place_para]; firmPtr->sabotage_level += spyPtr->spy_skill/5; if( firmPtr->sabotage_level > 100 ) firmPtr->sabotage_level = 100; } } } //---------- End of function SpyArray::process_sabotage ----------// //--------- Begin of function SpyArray::mobilize_all_spy ----------// // // Mobilize all spies of the specific nation in the specific place. // // spyPlace - place id. of the spy // spyPlacePara - town or firm recno of the spy's staying // nationRecno - recno of the nation which the spy should // be mobilized. // void SpyArray::mobilize_all_spy(int spyPlace, int spyPlacePara, int nationRecno) { Spy* spyPtr; for( int i=size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place == spyPlace && spyPtr->spy_place_para == spyPlacePara && spyPtr->true_nation_recno == nationRecno ) { if( spyPtr->spy_place == SPY_TOWN ) spyPtr->mobilize_town_spy(); else if( spyPtr->spy_place == SPY_FIRM ) spyPtr->mobilize_firm_spy(); } } } //---------- End of function SpyArray::mobilize_all_spy ----------// //--------- Begin of function SpyArray::disp_view_secret_menu ---------// // void SpyArray::disp_view_secret_menu(int spyRecno, int refreshFlag) { if( refreshFlag != INFO_REPAINT ) return; //------------------------------------// vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+42 ); font_san.put_paragraph( INFO_X1+7, INFO_Y1+5, INFO_X2-7, INFO_Y2-5, "Steal which type of secrets?" ); //------------------------------------// int y=INFO_Y1+45; err_when( spy_array.is_deleted(spyRecno) ); Spy* spyPtr = spy_array[spyRecno]; for( int i=0 ; ispy_skill >= secret_view_skill_array[i] ) { button_secret_report_array[i].paint_text( INFO_X1, y, INFO_X2, y+21, secret_report_str_array[i] ); y+=23; } else { button_secret_report_array[i].reset(); } } button_secret_report_cancel.paint_text( INFO_X1, y, INFO_X2, y+22, "Cancel" ); } //----------- End of function SpyArray::disp_view_secret_menu -----------// //--------- Begin of function SpyArray::detect_view_secret_menu ---------// // // spyRecno - recno of the spy to view secret info. // nationRecno - recno of the nation which this spy is going to investigate // int SpyArray::detect_view_secret_menu(int spyRecno, int nationRecno) { //---- detect secret report button ----// int rc=0; for( int i=0 ; i firmRecno - recno of the firm to be updated. // void SpyArray::update_firm_spy_count(int firmRecno) { //---- recalculate Firm::player_spy_count -----// Spy* spyPtr; Firm* firmPtr = firm_array[firmRecno]; firmPtr->player_spy_count = 0; for( int i=spy_array.size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place == SPY_FIRM && spyPtr->spy_place_para == firmRecno && spyPtr->true_nation_recno == nation_array.player_recno ) { firmPtr->player_spy_count++; } } } //----------- End of function SpyArray::update_firm_spy_count -----------// //--------- Begin of function SpyArray::change_cloaked_nation ---------// // // Change the cloak of all the spies in the specific place. // // This function is called when a firm or town change nation. // // spyPlace - spy place // spyPlacePara - spy place para // fromNationRecno - change any spies in the place whose cloaked_nation_recno // toNationRecno is fromNationRecno to toNationRecno. // void SpyArray::change_cloaked_nation(int spyPlace, int spyPlacePara, int fromNationRecno, int toNationRecno) { Spy* spyPtr; for( int i=spy_array.size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->cloaked_nation_recno != fromNationRecno ) continue; if( spyPtr->spy_place != spyPlace ) continue; //--- check if the spy is in the specific firm or town ---// if( spyPlace == SPY_FIRM || spyPlace == SPY_TOWN ) // only check spy_place_para when spyPlace is SPY_TOWN or SPY_FIRM { if( spyPtr->spy_place_para != spyPlacePara ) continue; } if(spyPlace==spyPtr->spy_place && spyPlacePara==spyPtr->spy_place_para && spyPtr->true_nation_recno==toNationRecno) spyPtr->set_action_mode(SPY_IDLE); //----- if the spy is associated with a unit (mobile or firm overseer), we call Unit::spy_chnage_nation() ---// if( spyPlace == SPY_FIRM ) { int firmOverseerRecno = firm_array[spyPtr->spy_place_para]->overseer_recno; if( firmOverseerRecno && unit_array[firmOverseerRecno]->spy_recno == i ) { unit_array[firmOverseerRecno]->spy_change_nation(toNationRecno, COMMAND_AUTO); continue; } } else if( spyPlace == SPY_MOBILE ) { unit_array[spyPtr->spy_place_para]->spy_change_nation(toNationRecno, COMMAND_AUTO); continue; } //---- otherwise, just change the spy cloak ----// spyPtr->cloaked_nation_recno = toNationRecno; } } //----------- End of function SpyArray::change_cloaked_nation -----------// //--------- Begin of function SpyArray::total_spy_skill_level ---------// // // Calculate the combined skill levels of all the spies of the // specific nation in the specific place. // // spyPlace - spy place // spyPlacePara - spy place para // spyNationRecno - nation recno // spyCount - the total no. of spies meeting the criteria. // int SpyArray::total_spy_skill_level(int spyPlace, int spyPlacePara, int spyNationRecno, int& spyCount) { int totalSpyLevel=0; Spy* spyPtr; spyCount = 0; for( int i=spy_array.size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->true_nation_recno != spyNationRecno ) continue; if( spyPtr->spy_place != spyPlace ) continue; if( spyPtr->spy_place_para != spyPlacePara ) continue; spyCount++; totalSpyLevel += spyPtr->spy_skill; } return totalSpyLevel; } //----------- End of function SpyArray::total_spy_skill_level -----------// //-------- Begin of function SpyArray::catch_spy ------// // // spyPlace - either SPY_TOWN or SPY_FIRM // spyPlacePara - town_recno or firm_recno // int SpyArray::catch_spy(int spyPlace, int spyPlacePara) { int nationRecno, totalPop; if( spyPlace == SPY_TOWN ) { Town* townPtr = town_array[spyPlacePara]; nationRecno = townPtr->nation_recno; totalPop = townPtr->population; } else if( spyPlace == SPY_FIRM ) { Firm* firmPtr = firm_array[spyPlacePara]; nationRecno = firmPtr->nation_recno; totalPop = firmPtr->worker_count + (firmPtr->overseer_recno>0); } else err_here(); //--- calculate the total of anti-spy skill in this town ----// int enemySpyCount=0, counterSpySkill=0; Spy* spyPtr; int i; for( i=size() ; i>0 ; i-- ) { if( is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place == spyPlace && spyPtr->spy_place_para == spyPlacePara ) { if( spyPtr->true_nation_recno == nationRecno ) counterSpySkill += spyPtr->spy_skill; else enemySpyCount++; } } //----- if all villagers are enemy spies ----// if( enemySpyCount == totalPop ) return 0; err_when( enemySpyCount > totalPop ); //-------- try to catch enemy spies now ------// for( i=spy_array.size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->action_mode == SPY_IDLE ) // it is very hard to get caught in sleep mode continue; if( spyPtr->spy_place == spyPlace && spyPtr->spy_place_para == spyPlacePara && spyPtr->true_nation_recno != nationRecno ) // doesn't get caught in sleep mode { int escapeChance = 100 + spyPtr->spy_skill - counterSpySkill; escapeChance = max( spyPtr->spy_skill/10, escapeChance ); if( m.random(escapeChance) == 0 ) { spyPtr->get_killed(); // only catch one spy per calling return 1; } } } return 0; } //---------- End of function SpyArray::catch_spy --------// //--------- Begin of function SpyArray::set_action_mode ----------// // // Set all spies in the given place to the specific action mode. // void SpyArray::set_action_mode(int spyPlace, int spyPlacePara, int actionMode) { int spyCount=size(); Spy* spyPtr; for( int i=1 ; i<=spyCount ; i++ ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place==spyPlace && spyPtr->spy_place_para==spyPlacePara ) { spyPtr->set_action_mode(actionMode); } } } //---------- End of function SpyArray::set_action_mode ----------// //--------- Begin of function SpyArray::ai_spy_town_rebel ----------// // // Tell the AI spies in the town that a rebellion is happening. // // When a rebellion happens, all the AI spies in the village will mobilize // and turn its cloak back to a nation that is not at war with the enemy // (and notification flag should be off.) and move to a safe place // (near to one of your towns). Then the spy reaches thedestination, it will // become idle and then the AI processing function on idle spy will be // called and handle the spy. // // townRecno - recno of the town with rebellion happening. // void SpyArray::ai_spy_town_rebel(int townRecno) { int spyCount=size(); Spy* spyPtr; for( int i=1 ; i<=spyCount ; i++ ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place==SPY_TOWN && spyPtr->spy_place_para==townRecno && nation_array[spyPtr->true_nation_recno]->is_ai() ) { //-------- mobilize the spy ----------// int unitRecno = spyPtr->mobilize_town_spy(); //----- think new action for the spy ------// if( unitRecno ) spyPtr->think_mobile_spy_new_action(); } } } //---------- End of function SpyArray::ai_spy_town_rebel ----------// //--------- Begin of function SpyArray::needed_view_secret_skill ----------// // int SpyArray::needed_view_secret_skill(int viewMode) { for( int i=0 ; ispy_recno==0 ) err.run( "SpyArray[] is deleted" ); return spyPtr; } //--------- End of function SpyArray::operator[] ----// #endif