OSPY2.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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 : OSPY2.CPP
  21. //Description : Spy AI functions
  22. #include <OINFO.h>
  23. #include <OFIRM.h>
  24. #include <OTOWN.h>
  25. #include <ONATION.h>
  26. #include <OSPY.h>
  27. //--------- Begin of function Spy::process_ai ----------//
  28. //
  29. void Spy::process_ai()
  30. {
  31. if( spy_recno%30 == info.game_date%30 ) // think about changing actions once 30 days
  32. think_reward();
  33. switch( spy_place )
  34. {
  35. case SPY_TOWN:
  36. if( spy_recno%30 == info.game_date%30 )
  37. think_town_spy();
  38. break;
  39. case SPY_FIRM:
  40. if( spy_recno%30 == info.game_date%30 )
  41. think_firm_spy();
  42. break;
  43. case SPY_MOBILE:
  44. if( spy_recno%5 == info.game_date%5 )
  45. think_mobile_spy();
  46. break;
  47. }
  48. }
  49. //---------- End of function Spy::process_ai ----------//
  50. //--------- Begin of function Spy::think_town_spy ----------//
  51. //
  52. void Spy::think_town_spy()
  53. {
  54. Town* townPtr = town_array[spy_place_para];
  55. if( townPtr->nation_recno == true_nation_recno ) // anti-spy
  56. return;
  57. //------ if it's an independent town ------//
  58. if( townPtr->nation_recno == 0 )
  59. {
  60. set_action_mode(SPY_SOW_DISSENT);
  61. //--- if the resistance has already drop low enough, the spy no longer needs to be in the town ---//
  62. if( townPtr->race_loyalty_array[race_id-1] < MIN_INDEPENDENT_DEFEND_LOYALTY )
  63. {
  64. mobilize_town_spy();
  65. }
  66. }
  67. else
  68. {
  69. //-------------- if it's a nation town -------------//
  70. //
  71. // Set to sleep mode in most time so the spying skill can increase
  72. // gradually, when the loyalty level of the village falls to near
  73. // rebel level, set all of your spies in the village to sow dissent
  74. // mode and cause rebellion in the enemy village.
  75. //
  76. //--------------------------------------------------//
  77. Nation* trueNation = nation_array[true_nation_recno];
  78. if( townPtr->average_loyalty() < 50 - trueNation->pref_loyalty_concern/10 ) // pref_loyalty_concern actually does apply to here, we just use a preference var so that the decision making process will vary between nations
  79. {
  80. set_action_mode(SPY_SOW_DISSENT);
  81. }
  82. else
  83. {
  84. if( m.random(5)==0 ) // 20% chance of sowing dissents.
  85. set_action_mode(SPY_SOW_DISSENT);
  86. else
  87. set_action_mode(SPY_IDLE);
  88. }
  89. }
  90. }
  91. //---------- End of function Spy::think_town_spy ----------//
  92. //--------- Begin of function Spy::think_firm_spy ----------//
  93. //
  94. void Spy::think_firm_spy()
  95. {
  96. Firm* firmPtr = firm_array[spy_place_para];
  97. if( firmPtr->nation_recno == true_nation_recno ) // anti-spy
  98. return;
  99. //-------- try to capturing the firm --------//
  100. if( capture_firm() )
  101. return;
  102. //-------- think about bribing ---------//
  103. if( think_bribe() )
  104. return;
  105. //-------- think about assassinating ---------//
  106. if( think_assassinate() )
  107. return;
  108. //------ think about changing spy mode ----//
  109. else if( m.random(3)==0 ) // 1/10 chance to set it to idle to prevent from being caught
  110. {
  111. set_action_mode(SPY_IDLE);
  112. }
  113. else if( m.random(2)==0 &&
  114. can_sabotage() && firmPtr->is_operating() && firmPtr->productivity >= 20 )
  115. {
  116. set_action_mode(SPY_SABOTAGE);
  117. }
  118. else
  119. {
  120. set_action_mode(SPY_SOW_DISSENT);
  121. }
  122. }
  123. //---------- End of function Spy::think_firm_spy ----------//
  124. //--------- Begin of function Spy::think_bribe ----------//
  125. //
  126. int Spy::think_bribe()
  127. {
  128. Firm* firmPtr = firm_array[spy_place_para];
  129. //--- only bribe enemies in military camps ---//
  130. if( firmPtr->firm_id != FIRM_CAMP )
  131. return 0;
  132. //----- only if there is an overseer in the camp -----//
  133. if( !firmPtr->overseer_recno )
  134. return 0;
  135. //---- see if the overseer can be bribe (kings and your own spies can't be bribed) ----//
  136. if( !firmPtr->can_spy_bribe(0, true_nation_recno ) ) // 0-bribe the overseer
  137. return 0;
  138. //------ first check our financial status ------//
  139. Nation* ownNation = nation_array[true_nation_recno];
  140. Unit* overseerUnit = unit_array[firmPtr->overseer_recno];
  141. if( spy_skill < min(50, overseerUnit->skill.skill_level) ||
  142. !ownNation->ai_should_spend(30) )
  143. {
  144. return 0;
  145. }
  146. //----- think about how important is this firm -----//
  147. int firmImportance = 0;
  148. Town* townPtr;
  149. for( int i=firmPtr->linked_town_count-1 ; i>=0 ; i-- )
  150. {
  151. townPtr = town_array[ firmPtr->linked_town_array[i] ];
  152. if( townPtr->nation_recno == firmPtr->nation_recno )
  153. firmImportance += townPtr->population * 2;
  154. else
  155. firmImportance += townPtr->population;
  156. }
  157. //------- think about which one to bribe -------//
  158. //-- first get the succeedChange if the bribe amount is zero --//
  159. int succeedChange = firmPtr->spy_bribe_succeed_chance( 0, spy_recno, 0 ); // first 0 - $0 bribe amount, 3rd 0 - bribe the overseer
  160. //-- then based on it, figure out how much we have to offer to bribe successfully --//
  161. int bribeAmount = MAX_BRIBE_AMOUNT * (100-succeedChange) / 100;
  162. bribeAmount = max(100, bribeAmount);
  163. //--- only bribe when the nation has enough money ---//
  164. if( !ownNation->ai_should_spend(30, (float)bribeAmount) )
  165. return 0;
  166. //------- try to bribe the commander ----//
  167. int newSpyRecno = firmPtr->spy_bribe(bribeAmount, spy_recno, 0);
  168. if( !newSpyRecno ) // bribing failed
  169. return 1; // return 1 as the spy has been killed
  170. Spy* newSpy = spy_array[newSpyRecno];
  171. err_when( newSpy->true_nation_recno != true_nation_recno );
  172. err_when( newSpy->spy_place != SPY_FIRM );
  173. if( newSpy->capture_firm() ) // try to capture the firm now
  174. {
  175. err_when( firm_array[newSpy->spy_place_para]->nation_recno != true_nation_recno );
  176. newSpy->drop_spy_identity(); // drop the spy identity of the newly bribed spy if the capture is successful, this will save the spying costs
  177. }
  178. return 1;
  179. }
  180. //---------- End of function Spy::think_bribe ----------//
  181. //--------- Begin of function Spy::think_reward ----------//
  182. //
  183. // Think about rewarding this spy.
  184. //
  185. int Spy::think_reward()
  186. {
  187. Nation* ownNation = nation_array[true_nation_recno];
  188. //----------------------------------------------------------//
  189. // The need to secure high loyalty on this unit is based on:
  190. // -its skill
  191. // -its combat level
  192. // -soldiers commanded by this unit
  193. //----------------------------------------------------------//
  194. int neededLoyalty = spy_skill * (100+ownNation->pref_loyalty_concern) / 100;
  195. neededLoyalty = max( UNIT_BETRAY_LOYALTY+10, neededLoyalty ); // 10 points above the betray loyalty level to prevent betrayal
  196. neededLoyalty = min( 100, neededLoyalty );
  197. //------- if the loyalty is already high enough ------//
  198. if( spy_loyalty >= neededLoyalty )
  199. return 0;
  200. //---------- see how many cash & profit we have now ---------//
  201. int rewardNeedRating = neededLoyalty - spy_loyalty;
  202. if( spy_loyalty < UNIT_BETRAY_LOYALTY+5 )
  203. rewardNeedRating += 50;
  204. if( ownNation->ai_should_spend(rewardNeedRating) )
  205. {
  206. reward(COMMAND_AI);
  207. return 1;
  208. }
  209. return 0;
  210. }
  211. //---------- End of function Spy::think_reward ----------//
  212. //--------- Begin of function Spy::think_mobile_spy ----------//
  213. //
  214. int Spy::think_mobile_spy()
  215. {
  216. Unit* unitPtr = unit_array[spy_place_para];
  217. //--- if the spy is on the ship, nothing can be done ---//
  218. if( !unitPtr->is_visible() )
  219. return 0;
  220. //---- if the spy has stopped and there is no new action ----//
  221. if( unitPtr->is_ai_all_stop() &&
  222. (!notify_cloaked_nation_flag || cloaked_nation_recno==0) )
  223. {
  224. return think_mobile_spy_new_action();
  225. }
  226. return 0;
  227. }
  228. //---------- End of function Spy::think_mobile_spy ----------//
  229. //-------- Begin of function Spy::think_mobile_spy_new_action --------//
  230. //
  231. int Spy::think_mobile_spy_new_action()
  232. {
  233. Nation* trueNation = nation_array[true_nation_recno];
  234. err_when( spy_place != SPY_MOBILE );
  235. int spyRegionId = unit_array[spy_place_para]->region_id();
  236. //----- try to sneak into an enemy camp ------//
  237. int firmRecno = trueNation->think_assign_spy_target_camp(race_id, spyRegionId);
  238. if( firmRecno )
  239. {
  240. Firm* firmPtr = firm_array[firmRecno];
  241. return add_assign_spy_action( firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->nation_recno );
  242. }
  243. //--- try to sneak into an enemy town or an independent town ---//
  244. int townRecno = trueNation->think_assign_spy_target_town(race_id, spyRegionId);
  245. if( townRecno )
  246. {
  247. Town* townPtr = town_array[townRecno];
  248. return add_assign_spy_action( townPtr->loc_x1, townPtr->loc_y1, townPtr->nation_recno );
  249. }
  250. //------ think if we should drop the spy identity -------//
  251. int dropIdentity = 0;
  252. //-------- if we already have too many spies --------//
  253. if( trueNation->total_spy_count > trueNation->total_population * (10+trueNation->pref_spy/5) / 100 ) // 10% to 30%
  254. {
  255. dropIdentity = 1;
  256. }
  257. //--- the expense of spies should not be too large ---//
  258. else if( trueNation->expense_365days(EXPENSE_SPY) >
  259. trueNation->expense_365days() * (50+trueNation->pref_counter_spy) / 400 )
  260. {
  261. dropIdentity = 1;
  262. }
  263. else //------- try to assign to one of our own towns -------//
  264. {
  265. int townRecno = trueNation->think_assign_spy_own_town(race_id, spyRegionId);
  266. if( townRecno )
  267. {
  268. Town* townPtr = town_array[townRecno];
  269. return add_assign_spy_action( townPtr->loc_x1, townPtr->loc_y1, townPtr->nation_recno );
  270. }
  271. else
  272. {
  273. dropIdentity = 1;
  274. }
  275. }
  276. //---------- drop spy identity now --------//
  277. if( dropIdentity )
  278. {
  279. drop_spy_identity();
  280. return 1;
  281. }
  282. return 0;
  283. }
  284. //---------- End of function Spy::think_mobile_spy_new_action --------//
  285. //-------- Begin of function Spy::add_assign_spy_action --------//
  286. //
  287. int Spy::add_assign_spy_action(int destXLoc, int destYLoc, int cloakedNationRecno)
  288. {
  289. err_when( spy_place != SPY_MOBILE );
  290. err_when( unit_array.is_deleted(spy_place_para) );
  291. return nation_array[true_nation_recno]->add_action( destXLoc, destYLoc,
  292. -1, -1, ACTION_AI_ASSIGN_SPY, cloakedNationRecno, 1, spy_place_para );
  293. }
  294. //---------- End of function Spy::add_assign_spy_action --------//
  295. //--------- Begin of function Spy::ai_spy_being_attacked ----------//
  296. //
  297. // This function is called when this spy is under attack.
  298. //
  299. // <int> attackerUnitRecno - recno of the attacker unit.
  300. //
  301. int Spy::ai_spy_being_attacked(int attackerUnitRecno)
  302. {
  303. err_when( spy_place != SPY_MOBILE );
  304. Unit* attackerUnit = unit_array[attackerUnitRecno];
  305. Unit* spyUnit = unit_array[spy_place_para];
  306. Nation* trueNation = nation_array[true_nation_recno];
  307. //----- if we are attacking our own units -----//
  308. if( attackerUnit->true_nation_recno() == true_nation_recno )
  309. {
  310. if( spy_skill > 50-trueNation->pref_spy/10 ||
  311. spyUnit->hit_points < spyUnit->max_hit_points * (100-trueNation->pref_military_courage/2) / 100 )
  312. {
  313. change_cloaked_nation( true_nation_recno );
  314. return 1;
  315. }
  316. }
  317. else
  318. {
  319. //---- if this unit is attacking units of other nations -----//
  320. //
  321. // If the nation this spy cloaked into is at war with the spy's
  322. // true nation and the nation which the spy is currently attacking
  323. // is not at war with the spy's true nation, then change
  324. // the spy's cloak to the non-hostile nation.
  325. //
  326. //-----------------------------------------------------------//
  327. if( trueNation->get_relation_status(attackerUnit->nation_recno) != NATION_HOSTILE &&
  328. trueNation->get_relation_status(cloaked_nation_recno) == NATION_HOSTILE )
  329. {
  330. if( spy_skill > 50-trueNation->pref_spy/10 ||
  331. spyUnit->hit_points < spyUnit->max_hit_points * (100-trueNation->pref_military_courage/2) / 100 )
  332. {
  333. change_cloaked_nation( true_nation_recno );
  334. return 1;
  335. }
  336. }
  337. }
  338. return 0;
  339. }
  340. //---------- End of function Spy::ai_spy_being_attacked ----------//
  341. //--------- Begin of function Spy::think_assassinate ----------//
  342. //
  343. int Spy::think_assassinate()
  344. {
  345. Firm* firmPtr = firm_array[spy_place_para];
  346. //--- only bribe enemies in military camps ---//
  347. if( firmPtr->firm_id != FIRM_CAMP )
  348. return 0;
  349. //----- only if there is an overseer in the camp -----//
  350. if( !firmPtr->overseer_recno )
  351. return 0;
  352. //---- get the attack and defense rating ----//
  353. int attackRating, defenseRating, otherDefenderCount;
  354. if( !get_assassinate_rating(firmPtr->overseer_recno, attackRating, defenseRating, otherDefenderCount) ) // return 0 if assassination is not possible
  355. return 0;
  356. Nation* trueNation = nation_array[true_nation_recno];
  357. if( attackRating + m.random(20+trueNation->pref_spy/2) > defenseRating ) // the random number is to increase the chance of attempting assassination
  358. {
  359. assassinate(firmPtr->overseer_recno, COMMAND_AI);
  360. return 1;
  361. }
  362. return 0;
  363. }
  364. //---------- End of function Spy::think_assassinate ----------//