OSPYA.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OSPY.CPP
  21. //Description : Object Spy
  22. #include <OPOWER.h>
  23. #include <OGAME.h>
  24. #include <ODATE.h>
  25. #include <ONEWS.h>
  26. #include <OFONT.h>
  27. #include <OUNIT.h>
  28. #include <OWORLD.h>
  29. #include <OBUTTON.h>
  30. #include <OFIRM.h>
  31. #include <OTOWN.h>
  32. #include <ONATION.h>
  33. #include <ORACERES.h>
  34. #include <OSYS.h>
  35. #include <OSPY.h>
  36. //----- Define constants for viewing secret menu ------//
  37. #define SECRET_REPORT_COUNT 7
  38. static char* secret_report_str_array[] = { "Kingdoms", "Villages", "Economy", "Trade", "Military", "Technology", "Espionage" };
  39. static char secret_view_mode_array[] = { MODE_NATION, MODE_TOWN, MODE_ECONOMY, MODE_TRADE, MODE_MILITARY, MODE_TECH, MODE_SPY };
  40. static char secret_view_skill_array[] = { 40, 20, 30, 30, 50, 40, 90 };
  41. static Button button_secret_report_array[SECRET_REPORT_COUNT];
  42. static Button button_secret_report_cancel;
  43. //--------- Begin of function SpyArray::SpyArray ----------//
  44. SpyArray::SpyArray() : DynArrayB(sizeof(Spy), 10)
  45. {
  46. }
  47. //--------- End of function SpyArray::SpyArary ----------//
  48. //------- Begin of function SpyArray::~SpyArray ----------//
  49. //
  50. SpyArray::~SpyArray()
  51. {
  52. deinit();
  53. }
  54. //--------- End of function SpyArray::~SpyArray ----------//
  55. //--------- Begin of function SpyArray::init ----------//
  56. //
  57. void SpyArray::init()
  58. {
  59. }
  60. //---------- End of function SpyArray::init ----------//
  61. //--------- Begin of function SpyArray::deinit ----------//
  62. //
  63. void SpyArray::deinit()
  64. {
  65. if( size()==0 )
  66. return;
  67. //-------- zap the array -----------//
  68. zap();
  69. }
  70. //---------- End of function SpyArray::deinit ----------//
  71. //--------- Begin of function SpyArray::add_spy ----------//
  72. //
  73. // <int> unitRecno - unit recno of the spy
  74. // <int> spySkill - spying skill of the unit
  75. //
  76. // return: <int> recno of the spy record added
  77. //
  78. int SpyArray::add_spy(int unitRecno, int spySkill)
  79. {
  80. Spy spy;
  81. Unit* unitPtr = unit_array[unitRecno];
  82. memset( &spy, 0, sizeof(spy) );
  83. spy.spy_place = SPY_MOBILE;
  84. spy.spy_place_para = unitRecno;
  85. spy.spy_skill = spySkill;
  86. spy.spy_loyalty = unitPtr->loyalty;
  87. spy.race_id = unitPtr->race_id;
  88. spy.name_id = unitPtr->name_id;
  89. err_when( unitPtr->race_id < 1 || unitPtr->race_id > MAX_RACE );
  90. err_when( nation_array.is_deleted(unitPtr->nation_recno) );
  91. spy.true_nation_recno = unitPtr->nation_recno;
  92. spy.cloaked_nation_recno = unitPtr->nation_recno;
  93. //--- spies hold a use right of the name id even though the unit itself will register the usage right of the name already ---//
  94. 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
  95. //------- link in the spy_array -------//
  96. linkin( &spy );
  97. ((Spy*)get())->spy_recno = recno();
  98. return recno();
  99. }
  100. //---------- End of function SpyArray::add_spy ----------//
  101. //--------- Begin of function SpyArray::add_spy ----------//
  102. //
  103. // This overloaded version of add_spy() just add a spy without
  104. // setting parameters of the Spy.
  105. //
  106. // return: <int> recno of the spy record added
  107. //
  108. int SpyArray::add_spy()
  109. {
  110. Spy spy;
  111. memset( &spy, 0, sizeof(spy) );
  112. linkin( &spy );
  113. ((Spy*)get())->spy_recno = recno();
  114. return recno();
  115. }
  116. //---------- End of function SpyArray::add_spy ----------//
  117. //--------- Begin of function SpyArray::del_spy ----------//
  118. //
  119. // <int> spyRecno - recno of the spy to be deleted
  120. //
  121. void SpyArray::del_spy(int spyRecno)
  122. {
  123. spy_array[spyRecno]->deinit();
  124. linkout(spyRecno);
  125. }
  126. //---------- End of function SpyArray::del_spy ----------//
  127. //--------- Begin of function SpyArray::next_day ----------//
  128. //
  129. void SpyArray::next_day()
  130. {
  131. int spyCount = size();
  132. Spy* spyPtr;
  133. for( int i=1 ; i<=spyCount ; i++ )
  134. {
  135. if( spy_array.is_deleted(i) )
  136. continue;
  137. spyPtr = spy_array[i];
  138. spyPtr->next_day();
  139. if( spy_array.is_deleted(i) )
  140. continue;
  141. if( nation_array[spyPtr->true_nation_recno]->is_ai() )
  142. spyPtr->process_ai();
  143. }
  144. //---------- update Firm::sabotage_level ----------//
  145. if( info.game_date%15==0 )
  146. process_sabotage();
  147. }
  148. //---------- End of function SpyArray::next_day ----------//
  149. //--------- Begin of function SpyArray::find_town_spy ----------//
  150. //
  151. // Find a spy meeting the specific criteria
  152. //
  153. // <int> townRecno - town recno of the spy to find
  154. // <int> raceId - race id. of the spy to find
  155. // <int> spySeq - sequence id. of the spy in spy_array
  156. //
  157. // return: <int> recno of the spy found
  158. //
  159. int SpyArray::find_town_spy(int townRecno, int raceId, int spySeq)
  160. {
  161. int spyCount=size(), matchCount=0;
  162. Spy* spyPtr;
  163. for( int i=1 ; i<=spyCount ; i++ )
  164. {
  165. if( spy_array.is_deleted(i) )
  166. continue;
  167. spyPtr = spy_array[i];
  168. if( spyPtr->spy_place==SPY_TOWN &&
  169. spyPtr->spy_place_para==townRecno &&
  170. spyPtr->race_id==raceId )
  171. {
  172. if( ++matchCount == spySeq )
  173. return i;
  174. }
  175. }
  176. return 0;
  177. }
  178. //---------- End of function SpyArray::find_town_spy ----------//
  179. //--------- Begin of function SpyArray::process_sabotage ----------//
  180. //
  181. void SpyArray::process_sabotage()
  182. {
  183. Spy* spyPtr;
  184. Firm* firmPtr;
  185. //-------- reset firms' sabotage_level -------//
  186. int i;
  187. for( i=firm_array.size() ; i>0 ; i-- )
  188. {
  189. if( firm_array.is_deleted(i) )
  190. continue;
  191. firm_array[i]->sabotage_level = 0;
  192. }
  193. //------- increase firms' sabotage_level -----//
  194. for( i=spy_array.size() ; i>0 ; i-- )
  195. {
  196. if( spy_array.is_deleted(i) )
  197. continue;
  198. spyPtr = spy_array[i];
  199. if( spyPtr->action_mode == SPY_SABOTAGE )
  200. {
  201. err_when( spyPtr->spy_place != SPY_FIRM );
  202. firmPtr = firm_array[spyPtr->spy_place_para];
  203. firmPtr->sabotage_level += spyPtr->spy_skill/5;
  204. if( firmPtr->sabotage_level > 100 )
  205. firmPtr->sabotage_level = 100;
  206. }
  207. }
  208. }
  209. //---------- End of function SpyArray::process_sabotage ----------//
  210. //--------- Begin of function SpyArray::mobilize_all_spy ----------//
  211. //
  212. // Mobilize all spies of the specific nation in the specific place.
  213. //
  214. // <int> spyPlace - place id. of the spy
  215. // <int> spyPlacePara - town or firm recno of the spy's staying
  216. // <int> nationRecno - recno of the nation which the spy should
  217. // be mobilized.
  218. //
  219. void SpyArray::mobilize_all_spy(int spyPlace, int spyPlacePara, int nationRecno)
  220. {
  221. Spy* spyPtr;
  222. for( int i=size() ; i>0 ; i-- )
  223. {
  224. if( spy_array.is_deleted(i) )
  225. continue;
  226. spyPtr = spy_array[i];
  227. if( spyPtr->spy_place == spyPlace &&
  228. spyPtr->spy_place_para == spyPlacePara &&
  229. spyPtr->true_nation_recno == nationRecno )
  230. {
  231. if( spyPtr->spy_place == SPY_TOWN )
  232. spyPtr->mobilize_town_spy();
  233. else if( spyPtr->spy_place == SPY_FIRM )
  234. spyPtr->mobilize_firm_spy();
  235. }
  236. }
  237. }
  238. //---------- End of function SpyArray::mobilize_all_spy ----------//
  239. //--------- Begin of function SpyArray::disp_view_secret_menu ---------//
  240. //
  241. void SpyArray::disp_view_secret_menu(int spyRecno, int refreshFlag)
  242. {
  243. if( refreshFlag != INFO_REPAINT )
  244. return;
  245. //------------------------------------//
  246. vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+42 );
  247. font_san.put_paragraph( INFO_X1+7, INFO_Y1+5, INFO_X2-7, INFO_Y2-5,
  248. "Steal which type of secrets?" );
  249. //------------------------------------//
  250. int y=INFO_Y1+45;
  251. err_when( spy_array.is_deleted(spyRecno) );
  252. Spy* spyPtr = spy_array[spyRecno];
  253. for( int i=0 ; i<SECRET_REPORT_COUNT ; i++ )
  254. {
  255. if( spyPtr->spy_skill >= secret_view_skill_array[i] )
  256. {
  257. button_secret_report_array[i].paint_text( INFO_X1, y, INFO_X2, y+21, secret_report_str_array[i] );
  258. y+=23;
  259. }
  260. else
  261. {
  262. button_secret_report_array[i].reset();
  263. }
  264. }
  265. button_secret_report_cancel.paint_text( INFO_X1, y, INFO_X2, y+22, "Cancel" );
  266. }
  267. //----------- End of function SpyArray::disp_view_secret_menu -----------//
  268. //--------- Begin of function SpyArray::detect_view_secret_menu ---------//
  269. //
  270. // <int> spyRecno - recno of the spy to view secret info.
  271. // <int> nationRecno - recno of the nation which this spy is going to investigate
  272. //
  273. int SpyArray::detect_view_secret_menu(int spyRecno, int nationRecno)
  274. {
  275. //---- detect secret report button ----//
  276. int rc=0;
  277. for( int i=0 ; i<SECRET_REPORT_COUNT ; i++ )
  278. {
  279. if( button_secret_report_array[i].detect() )
  280. {
  281. sys.set_view_mode( secret_view_mode_array[i], nationRecno, spyRecno );
  282. rc=1;
  283. break;
  284. }
  285. }
  286. //-------- detect cancel button --------//
  287. if( button_secret_report_cancel.detect() )
  288. rc = 1;
  289. return rc;
  290. }
  291. //----------- End of function SpyArray::detect_view_secret_menu -----------//
  292. //--------- Begin of function SpyArray::update_firm_spy_count ---------//
  293. //
  294. // Update the player_spy_count of this firm. This function is called
  295. // when the firm change its nation.
  296. //
  297. // <int> firmRecno - recno of the firm to be updated.
  298. //
  299. void SpyArray::update_firm_spy_count(int firmRecno)
  300. {
  301. //---- recalculate Firm::player_spy_count -----//
  302. Spy* spyPtr;
  303. Firm* firmPtr = firm_array[firmRecno];
  304. firmPtr->player_spy_count = 0;
  305. for( int i=spy_array.size() ; i>0 ; i-- )
  306. {
  307. if( spy_array.is_deleted(i) )
  308. continue;
  309. spyPtr = spy_array[i];
  310. if( spyPtr->spy_place == SPY_FIRM &&
  311. spyPtr->spy_place_para == firmRecno &&
  312. spyPtr->true_nation_recno == nation_array.player_recno )
  313. {
  314. firmPtr->player_spy_count++;
  315. }
  316. }
  317. }
  318. //----------- End of function SpyArray::update_firm_spy_count -----------//
  319. //--------- Begin of function SpyArray::change_cloaked_nation ---------//
  320. //
  321. // Change the cloak of all the spies in the specific place.
  322. //
  323. // This function is called when a firm or town change nation.
  324. //
  325. // <int> spyPlace - spy place
  326. // <int> spyPlacePara - spy place para
  327. // <int> fromNationRecno - change any spies in the place whose cloaked_nation_recno
  328. // <int> toNationRecno is fromNationRecno to toNationRecno.
  329. //
  330. void SpyArray::change_cloaked_nation(int spyPlace, int spyPlacePara, int fromNationRecno, int toNationRecno)
  331. {
  332. Spy* spyPtr;
  333. for( int i=spy_array.size() ; i>0 ; i-- )
  334. {
  335. if( spy_array.is_deleted(i) )
  336. continue;
  337. spyPtr = spy_array[i];
  338. if( spyPtr->cloaked_nation_recno != fromNationRecno )
  339. continue;
  340. if( spyPtr->spy_place != spyPlace )
  341. continue;
  342. //--- check if the spy is in the specific firm or town ---//
  343. if( spyPlace == SPY_FIRM || spyPlace == SPY_TOWN ) // only check spy_place_para when spyPlace is SPY_TOWN or SPY_FIRM
  344. {
  345. if( spyPtr->spy_place_para != spyPlacePara )
  346. continue;
  347. }
  348. if(spyPlace==spyPtr->spy_place && spyPlacePara==spyPtr->spy_place_para &&
  349. spyPtr->true_nation_recno==toNationRecno)
  350. spyPtr->set_action_mode(SPY_IDLE);
  351. //----- if the spy is associated with a unit (mobile or firm overseer), we call Unit::spy_chnage_nation() ---//
  352. if( spyPlace == SPY_FIRM )
  353. {
  354. int firmOverseerRecno = firm_array[spyPtr->spy_place_para]->overseer_recno;
  355. if( firmOverseerRecno && unit_array[firmOverseerRecno]->spy_recno == i )
  356. {
  357. unit_array[firmOverseerRecno]->spy_change_nation(toNationRecno, COMMAND_AUTO);
  358. continue;
  359. }
  360. }
  361. else if( spyPlace == SPY_MOBILE )
  362. {
  363. unit_array[spyPtr->spy_place_para]->spy_change_nation(toNationRecno, COMMAND_AUTO);
  364. continue;
  365. }
  366. //---- otherwise, just change the spy cloak ----//
  367. spyPtr->cloaked_nation_recno = toNationRecno;
  368. }
  369. }
  370. //----------- End of function SpyArray::change_cloaked_nation -----------//
  371. //--------- Begin of function SpyArray::total_spy_skill_level ---------//
  372. //
  373. // Calculate the combined skill levels of all the spies of the
  374. // specific nation in the specific place.
  375. //
  376. // <int> spyPlace - spy place
  377. // <int> spyPlacePara - spy place para
  378. // <int> spyNationRecno - nation recno
  379. // <int&> spyCount - the total no. of spies meeting the criteria.
  380. //
  381. int SpyArray::total_spy_skill_level(int spyPlace, int spyPlacePara, int spyNationRecno, int& spyCount)
  382. {
  383. int totalSpyLevel=0;
  384. Spy* spyPtr;
  385. spyCount = 0;
  386. for( int i=spy_array.size() ; i>0 ; i-- )
  387. {
  388. if( spy_array.is_deleted(i) )
  389. continue;
  390. spyPtr = spy_array[i];
  391. if( spyPtr->true_nation_recno != spyNationRecno )
  392. continue;
  393. if( spyPtr->spy_place != spyPlace )
  394. continue;
  395. if( spyPtr->spy_place_para != spyPlacePara )
  396. continue;
  397. spyCount++;
  398. totalSpyLevel += spyPtr->spy_skill;
  399. }
  400. return totalSpyLevel;
  401. }
  402. //----------- End of function SpyArray::total_spy_skill_level -----------//
  403. //-------- Begin of function SpyArray::catch_spy ------//
  404. //
  405. // <int> spyPlace - either SPY_TOWN or SPY_FIRM
  406. // <int> spyPlacePara - town_recno or firm_recno
  407. //
  408. int SpyArray::catch_spy(int spyPlace, int spyPlacePara)
  409. {
  410. int nationRecno, totalPop;
  411. if( spyPlace == SPY_TOWN )
  412. {
  413. Town* townPtr = town_array[spyPlacePara];
  414. nationRecno = townPtr->nation_recno;
  415. totalPop = townPtr->population;
  416. }
  417. else if( spyPlace == SPY_FIRM )
  418. {
  419. Firm* firmPtr = firm_array[spyPlacePara];
  420. nationRecno = firmPtr->nation_recno;
  421. totalPop = firmPtr->worker_count + (firmPtr->overseer_recno>0);
  422. }
  423. else
  424. err_here();
  425. //--- calculate the total of anti-spy skill in this town ----//
  426. int enemySpyCount=0, counterSpySkill=0;
  427. Spy* spyPtr;
  428. int i;
  429. for( i=size() ; i>0 ; i-- )
  430. {
  431. if( is_deleted(i) )
  432. continue;
  433. spyPtr = spy_array[i];
  434. if( spyPtr->spy_place == spyPlace &&
  435. spyPtr->spy_place_para == spyPlacePara )
  436. {
  437. if( spyPtr->true_nation_recno == nationRecno )
  438. counterSpySkill += spyPtr->spy_skill;
  439. else
  440. enemySpyCount++;
  441. }
  442. }
  443. //----- if all villagers are enemy spies ----//
  444. if( enemySpyCount == totalPop )
  445. return 0;
  446. err_when( enemySpyCount > totalPop );
  447. //-------- try to catch enemy spies now ------//
  448. for( i=spy_array.size() ; i>0 ; i-- )
  449. {
  450. if( spy_array.is_deleted(i) )
  451. continue;
  452. spyPtr = spy_array[i];
  453. if( spyPtr->action_mode == SPY_IDLE ) // it is very hard to get caught in sleep mode
  454. continue;
  455. if( spyPtr->spy_place == spyPlace &&
  456. spyPtr->spy_place_para == spyPlacePara &&
  457. spyPtr->true_nation_recno != nationRecno ) // doesn't get caught in sleep mode
  458. {
  459. int escapeChance = 100 + spyPtr->spy_skill - counterSpySkill;
  460. escapeChance = max( spyPtr->spy_skill/10, escapeChance );
  461. if( m.random(escapeChance) == 0 )
  462. {
  463. spyPtr->get_killed(); // only catch one spy per calling
  464. return 1;
  465. }
  466. }
  467. }
  468. return 0;
  469. }
  470. //---------- End of function SpyArray::catch_spy --------//
  471. //--------- Begin of function SpyArray::set_action_mode ----------//
  472. //
  473. // Set all spies in the given place to the specific action mode.
  474. //
  475. void SpyArray::set_action_mode(int spyPlace, int spyPlacePara, int actionMode)
  476. {
  477. int spyCount=size();
  478. Spy* spyPtr;
  479. for( int i=1 ; i<=spyCount ; i++ )
  480. {
  481. if( spy_array.is_deleted(i) )
  482. continue;
  483. spyPtr = spy_array[i];
  484. if( spyPtr->spy_place==spyPlace &&
  485. spyPtr->spy_place_para==spyPlacePara )
  486. {
  487. spyPtr->set_action_mode(actionMode);
  488. }
  489. }
  490. }
  491. //---------- End of function SpyArray::set_action_mode ----------//
  492. //--------- Begin of function SpyArray::ai_spy_town_rebel ----------//
  493. //
  494. // Tell the AI spies in the town that a rebellion is happening.
  495. //
  496. // When a rebellion happens, all the AI spies in the village will mobilize
  497. // and turn its cloak back to a nation that is not at war with the enemy
  498. // (and notification flag should be off.) and move to a safe place
  499. // (near to one of your towns). Then the spy reaches thedestination, it will
  500. // become idle and then the AI processing function on idle spy will be
  501. // called and handle the spy.
  502. //
  503. // <int> townRecno - recno of the town with rebellion happening.
  504. //
  505. void SpyArray::ai_spy_town_rebel(int townRecno)
  506. {
  507. int spyCount=size();
  508. Spy* spyPtr;
  509. for( int i=1 ; i<=spyCount ; i++ )
  510. {
  511. if( spy_array.is_deleted(i) )
  512. continue;
  513. spyPtr = spy_array[i];
  514. if( spyPtr->spy_place==SPY_TOWN &&
  515. spyPtr->spy_place_para==townRecno &&
  516. nation_array[spyPtr->true_nation_recno]->is_ai() )
  517. {
  518. //-------- mobilize the spy ----------//
  519. int unitRecno = spyPtr->mobilize_town_spy();
  520. //----- think new action for the spy ------//
  521. if( unitRecno )
  522. spyPtr->think_mobile_spy_new_action();
  523. }
  524. }
  525. }
  526. //---------- End of function SpyArray::ai_spy_town_rebel ----------//
  527. //--------- Begin of function SpyArray::needed_view_secret_skill ----------//
  528. //
  529. int SpyArray::needed_view_secret_skill(int viewMode)
  530. {
  531. for( int i=0 ; i<SECRET_REPORT_COUNT ; i++ )
  532. {
  533. if( secret_view_mode_array[i] == viewMode )
  534. return secret_view_skill_array[i];
  535. }
  536. return 0;
  537. }
  538. //---------- End of function SpyArray::needed_view_secret_skill ----------//
  539. #ifdef DEBUG
  540. //------- Begin of function SpyArray::operator[] -----//
  541. Spy* SpyArray::operator[](int recNo)
  542. {
  543. Spy* spyPtr = (Spy*) get(recNo);
  544. if( !spyPtr || spyPtr->spy_recno==0 )
  545. err.run( "SpyArray[] is deleted" );
  546. return spyPtr;
  547. }
  548. //--------- End of function SpyArray::operator[] ----//
  549. #endif