OAI_MAIN.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  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 : OAI_MAIN.CPP
  21. //Description: AI - main functions
  22. #include <OSYS.h>
  23. #include <ONATION.h>
  24. #include <OWORLD.h>
  25. #include <OGAME.h>
  26. #include <OSPY.h>
  27. #include <OCONFIG.h>
  28. #include <OUNIT.h>
  29. #include <OFIRM.h>
  30. #include <OTOWN.h>
  31. #include <OTALKRES.h>
  32. #include <OF_MINE.h>
  33. #include <OINFO.h>
  34. #include <OLOG.h>
  35. //--------- Begin of function Nation::Nation --------//
  36. Nation::Nation() : action_array( sizeof(ActionNode), 30 )
  37. {
  38. ai_town_array = NULL;
  39. }
  40. //---------- End of function Nation::Nation --------//
  41. //--------- Begin of function Nation::~Nation --------//
  42. Nation::~Nation()
  43. {
  44. err_when( nation_recno ); // deinit() must be called first before this destructor is called
  45. }
  46. //---------- End of function Nation::~Nation --------//
  47. //--------- Begin of function Nation::init --------//
  48. void Nation::init(int nationType, int raceId, int colorSchemeId, DWORD playerId)
  49. {
  50. NationBase::init(nationType, raceId, colorSchemeId, playerId);
  51. //----- init other AI vars -----//
  52. last_action_id = 0;
  53. ai_capture_enemy_town_recno = 0;
  54. ai_capture_enemy_town_start_attack_date = 0;
  55. ai_last_defend_action_date = 0;
  56. memset( firm_should_close_array, 0, sizeof(firm_should_close_array) );
  57. ai_base_town_count = 0;
  58. attack_camp_count = 0;
  59. //------ init AI info arrays -----//
  60. init_all_ai_info();
  61. //----- init AI personality ----//
  62. init_personalty();
  63. }
  64. //---------- End of function Nation::init --------//
  65. //--------- Begin of function Nation::deinit --------//
  66. void Nation::deinit()
  67. {
  68. NationBase::deinit();
  69. deinit_all_ai_info();
  70. }
  71. //---------- End of function Nation::deinit --------//
  72. //--------- Begin of function Nation::init_all_ai_info --------//
  73. void Nation::init_all_ai_info()
  74. {
  75. err_when( ai_town_array );
  76. init_ai_info(&ai_town_array, ai_town_count, ai_town_size, AI_TOWN_INIT_SIZE);
  77. init_ai_info(&ai_base_array, ai_base_count, ai_base_size, AI_BASE_INIT_SIZE);
  78. init_ai_info(&ai_mine_array, ai_mine_count, ai_mine_size, AI_MINE_INIT_SIZE);
  79. init_ai_info(&ai_factory_array, ai_factory_count, ai_factory_size, AI_FACTORY_INIT_SIZE);
  80. init_ai_info(&ai_market_array, ai_market_count, ai_market_size, AI_MARKET_INIT_SIZE);
  81. init_ai_info(&ai_inn_array, ai_inn_count, ai_inn_size, AI_INN_INIT_SIZE);
  82. init_ai_info(&ai_camp_array, ai_camp_count, ai_camp_size, AI_CAMP_INIT_SIZE);
  83. init_ai_info(&ai_research_array, ai_research_count, ai_research_size, AI_RESEARCH_INIT_SIZE);
  84. init_ai_info(&ai_war_array, ai_war_count, ai_war_size, AI_WAR_INIT_SIZE);
  85. init_ai_info(&ai_harbor_array, ai_harbor_count, ai_harbor_size, AI_HARBOR_INIT_SIZE);
  86. init_ai_info(&ai_caravan_array, ai_caravan_count, ai_caravan_size, AI_CARAVAN_INIT_SIZE);
  87. init_ai_info(&ai_ship_array, ai_ship_count, ai_ship_size, AI_SHIP_INIT_SIZE);
  88. init_ai_info(&ai_general_array, ai_general_count, ai_general_size, AI_GENERAL_INIT_SIZE);
  89. }
  90. //---------- End of function Nation::init_all_ai_info --------//
  91. //--------- Begin of function Nation::init_ai_info --------//
  92. //
  93. // <short**> aiInfoArrayPtr - poniter to the AI info array.
  94. // <short&> aiInfoCount - the count of the AI info array.
  95. // <short&> aiInfoSize - the size of the AI info array.
  96. // <int> arrayInitSize - the init size of the array.
  97. //
  98. void Nation::init_ai_info(short** aiInfoArrayPtr, short& aiInfoCount, short& aiInfoSize, int arrayInitSize )
  99. {
  100. *aiInfoArrayPtr = (short*) mem_add( sizeof(short) * arrayInitSize );
  101. memset( *aiInfoArrayPtr, 0, sizeof(short) * arrayInitSize );
  102. aiInfoCount = 0;
  103. aiInfoSize = arrayInitSize;
  104. }
  105. //---------- End of function Nation::init_ai_info --------//
  106. //--------- Begin of function Nation::deinit_all_ai_info --------//
  107. void Nation::deinit_all_ai_info()
  108. {
  109. err_when( !ai_town_array );
  110. //------- debug checking -------//
  111. #ifdef DEBUG
  112. if( !sys.signal_exit_flag )
  113. {
  114. err_when( ai_town_count > 0 );
  115. err_when( ai_base_town_count > 0 );
  116. err_when( ai_base_count > 0 );
  117. err_when( ai_mine_count > 0 );
  118. err_when( ai_factory_count > 0 );
  119. err_when( ai_market_count > 0 );
  120. err_when( ai_inn_count > 0 );
  121. err_when( ai_camp_count > 0 );
  122. err_when( ai_research_count > 0 );
  123. err_when( ai_war_count > 0 );
  124. err_when( ai_harbor_count > 0 );
  125. err_when( ai_caravan_count > 0 );
  126. err_when( ai_ship_count > 0 );
  127. err_when( ai_general_count > 0 );
  128. }
  129. #endif
  130. //------- release array from memory -------//
  131. mem_del(ai_town_array);
  132. mem_del(ai_base_array);
  133. mem_del(ai_mine_array);
  134. mem_del(ai_factory_array);
  135. mem_del(ai_market_array);
  136. mem_del(ai_inn_array);
  137. mem_del(ai_camp_array);
  138. mem_del(ai_research_array);
  139. mem_del(ai_war_array);
  140. mem_del(ai_harbor_array);
  141. mem_del(ai_caravan_array);
  142. mem_del(ai_ship_array);
  143. mem_del(ai_general_array);
  144. }
  145. //---------- End of function Nation::deinit_all_ai_info --------//
  146. //--------- Begin of function Nation::init_personalty --------//
  147. void Nation::init_personalty()
  148. {
  149. pref_force_projection = m.random(101);
  150. pref_military_development = m.random(101);
  151. pref_economic_development = 100-pref_military_development;
  152. pref_inc_pop_by_capture = m.random(101);
  153. pref_inc_pop_by_growth = 100-pref_inc_pop_by_capture;
  154. pref_peacefulness = m.random(101);
  155. pref_military_courage = m.random(101);
  156. pref_territorial_cohesiveness = m.random(101);
  157. pref_trading_tendency = m.random(101);
  158. pref_allying_tendency = m.random(101);
  159. pref_honesty = m.random(101);
  160. pref_town_harmony = m.random(101);
  161. pref_loyalty_concern = m.random(101);
  162. pref_forgiveness = m.random(101);
  163. pref_collect_tax = m.random(101);
  164. pref_hire_unit = m.random(101);
  165. pref_use_weapon = m.random(101);
  166. pref_keep_general = m.random(101);
  167. pref_keep_skilled_unit = m.random(101);
  168. pref_diplomacy_retry = m.random(101);
  169. pref_attack_monster = m.random(101);
  170. pref_spy = m.random(101);
  171. pref_counter_spy = m.random(101);
  172. pref_cash_reserve = m.random(101);
  173. pref_food_reserve = m.random(101);
  174. pref_use_marine = m.random(101);
  175. pref_unit_chase_distance = 15+m.random(15);
  176. pref_repair_concern = m.random(101);
  177. pref_scout = m.random(101);
  178. }
  179. //---------- End of function Nation::init_personalty --------//
  180. //--------- Begin of function Nation::process_ai --------//
  181. void Nation::process_ai()
  182. {
  183. //-*********** simulate aat ************-//
  184. #ifdef DEBUG
  185. if(debug_sim_game_type)
  186. return;
  187. #endif
  188. //-*********** simulate aat ************-//
  189. if( config.disable_ai_flag || game.game_mode == GAME_TEST )
  190. return;
  191. //---- if the king has just been killed ----//
  192. int nationRecno = nation_recno;
  193. if( !king_unit_recno )
  194. {
  195. if( think_succeed_king() )
  196. return;
  197. if( think_surrender() )
  198. return;
  199. defeated();
  200. return;
  201. }
  202. //-------- process main AI actions ---------//
  203. process_ai_main();
  204. if( nation_array.is_deleted(nationRecno) ) // the nation can have surrendered
  205. return;
  206. //------ process queued diplomatic messges first --------//
  207. // ##### begin Gilbert 4/10 ######//
  208. if( (info.game_date-nation_recno)%3 == 0 )
  209. {
  210. LOG_MSG("begin process_action(0,ACTION_AI_PROCESS_TALK_MSG)");
  211. process_action(0, ACTION_AI_PROCESS_TALK_MSG);
  212. LOG_MSG("end process_action(0,ACTION_AI_PROCESS_TALK_MSG)");
  213. LOG_MSG(m.get_random_seed());
  214. if( nation_array.is_deleted(nationRecno) ) // the nation can have surrendered
  215. return;
  216. }
  217. // ##### end Gilbert 4/10 ######//
  218. //--------- process queued actions ----------//
  219. // ##### begin Gilbert 4/10 ######//
  220. if( (info.game_date-nation_recno)%3 == 0 )
  221. {
  222. LOG_MSG("begin process_action()");
  223. process_action();
  224. LOG_MSG("end process_action()");
  225. LOG_MSG(m.get_random_seed());
  226. if( nation_array.is_deleted(nationRecno) ) // the nation can have surrendered
  227. return;
  228. }
  229. // ##### end Gilbert 4/10 ######//
  230. //--- process action that are on-going and need continous checking ---//
  231. process_on_going_action();
  232. //--------- cheat ---------//
  233. //
  234. // In tutorial mode only so that your opponent won't surrender
  235. // and you won't go to the end game screen.
  236. //
  237. //-------------------------//
  238. if( game.game_mode == GAME_TUTORIAL )
  239. {
  240. if( cash < 100 )
  241. add_cheat( (float)200+m.random(500) );
  242. if( food < 100 )
  243. food += 1000;
  244. }
  245. //----- think about updating relationship with other nations -----//
  246. if( info.game_date%360 == nation_recno%360 )
  247. ai_improve_relation();
  248. //------ think about surrendering -------//
  249. if( info.game_date%60 == nation_recno%60 )
  250. {
  251. if( think_surrender() )
  252. return;
  253. if( think_unite_against_big_enemy() )
  254. return;
  255. }
  256. }
  257. //---------- End of function Nation::process_ai --------//
  258. //--------- Begin of function Nation::process_on_going_action --------//
  259. //
  260. // Process action that are on-going and need continous checking.
  261. //
  262. void Nation::process_on_going_action()
  263. {
  264. //--- if the nation is in the process of trying to capture an enemy town ---//
  265. if( ai_capture_enemy_town_recno )
  266. {
  267. if( info.game_date%5 == nation_recno%5 )
  268. think_capturing_enemy_town();
  269. }
  270. //----- if the nation is in the process of attacking a target ----//
  271. if( attack_camp_count > 0 )
  272. ai_attack_target_execute(1);
  273. }
  274. //---------- End of function Nation::process_on_going_action --------//
  275. //------- Begin of function Nation::process_ai_main --------//
  276. //
  277. void Nation::process_ai_main()
  278. {
  279. #if defined(DEBUG) && defined(ENABLE_LOG)
  280. String debugStr;
  281. debugStr = "Nation ";
  282. debugStr += nation_recno;
  283. #endif
  284. static short intervalDaysArray[] = { 90, 30, 15, 15 };
  285. int intervalDays = intervalDaysArray[config.ai_aggressiveness-OPTION_LOW];
  286. if( game.game_mode == GAME_TUTORIAL )
  287. intervalDays = 120;
  288. switch( (info.game_date-nation_recno*4) % intervalDays )
  289. {
  290. case 0:
  291. #if defined(DEBUG) && defined(ENABLE_LOG)
  292. debugStr += " think_build_firm";
  293. #endif
  294. think_build_firm();
  295. break;
  296. case 1:
  297. #if defined(DEBUG) && defined(ENABLE_LOG)
  298. debugStr += " think_trading";
  299. #endif
  300. think_trading();
  301. break;
  302. case 2:
  303. #if defined(DEBUG) && defined(ENABLE_LOG)
  304. debugStr += " think_capture";
  305. #endif
  306. think_capture();
  307. break;
  308. case 3:
  309. #if defined(DEBUG) && defined(ENABLE_LOG)
  310. debugStr += " think_explore";
  311. #endif
  312. think_explore();
  313. break;
  314. case 4: // think about expanding its military force
  315. #if defined(DEBUG) && defined(ENABLE_LOG)
  316. debugStr += " think_military";
  317. #endif
  318. think_military();
  319. break;
  320. case 5:
  321. #if defined(DEBUG) && defined(ENABLE_LOG)
  322. debugStr += " think_secret_attack";
  323. #endif
  324. think_secret_attack();
  325. break;
  326. case 6:
  327. #if defined(DEBUG) && defined(ENABLE_LOG)
  328. debugStr += " think_attack_monster";
  329. #endif
  330. think_attack_monster();
  331. break;
  332. case 7:
  333. #if defined(DEBUG) && defined(ENABLE_LOG)
  334. debugStr += " think_diplomacy";
  335. #endif
  336. think_diplomacy();
  337. break;
  338. case 8:
  339. #if defined(DEBUG) && defined(ENABLE_LOG)
  340. debugStr += " think_marine";
  341. #endif
  342. think_marine();
  343. break;
  344. case 9:
  345. #if defined(DEBUG) && defined(ENABLE_LOG)
  346. debugStr += " think_grand_plan";
  347. #endif
  348. think_grand_plan();
  349. break;
  350. case 10:
  351. #if defined(DEBUG) && defined(ENABLE_LOG)
  352. debugStr += " think_reduce_expense";
  353. #endif
  354. think_reduce_expense();
  355. break;
  356. case 11:
  357. #if defined(DEBUG) && defined(ENABLE_LOG)
  358. debugStr += " think_town";
  359. #endif
  360. think_town();
  361. break;
  362. }
  363. LOG_MSG(debugStr);
  364. LOG_MSG(m.get_random_seed());
  365. }
  366. //---------- End of function Nation::process_ai_main --------//
  367. //--------- Begin of function Nation::think_explore --------//
  368. void Nation::think_explore()
  369. {
  370. }
  371. //---------- End of function Nation::think_explore --------//
  372. //-------- Begin of function Nation::think_succeed_king --------//
  373. //
  374. // return: <int> 1 - a unit succeed the king
  375. // 0 - no unit available for succeeding the king,
  376. // the nation is defeated.
  377. //
  378. int Nation::think_succeed_king()
  379. {
  380. int i, curRating, bestRating=0;
  381. Unit *unitPtr, *bestUnitPtr=NULL;
  382. Firm *firmPtr, *bestFirmPtr=NULL;
  383. int bestWorkerId=0;
  384. //---- try to find the best successor from mobile units ----//
  385. for( i=unit_array.size() ; i>0 ; i-- )
  386. {
  387. if( unit_array.is_deleted(i) )
  388. continue;
  389. unitPtr = unit_array[i];
  390. if( unitPtr->nation_recno != nation_recno || !unitPtr->race_id )
  391. continue;
  392. if( !unitPtr->is_visible() && unitPtr->unit_mode != UNIT_MODE_OVERSEE )
  393. continue;
  394. err_when( unitPtr->skill.combat_level<= 0 );
  395. curRating = 0;
  396. if( unitPtr->race_id == race_id )
  397. curRating += 50;
  398. if( unitPtr->rank_id == RANK_GENERAL )
  399. curRating += 50;
  400. if( unitPtr->skill.skill_id == SKILL_LEADING )
  401. curRating += unitPtr->skill.skill_level;
  402. if( curRating > bestRating )
  403. {
  404. bestRating = curRating;
  405. bestUnitPtr = unitPtr;
  406. }
  407. }
  408. //---- try to find the best successor from military camps ----//
  409. for( i=firm_array.size() ; i>0 ; i-- )
  410. {
  411. if( firm_array.is_deleted(i) )
  412. continue;
  413. firmPtr = firm_array[i];
  414. if( firmPtr->nation_recno != nation_recno )
  415. continue;
  416. //------ only military camps -------//
  417. if( firmPtr->firm_id == FIRM_CAMP )
  418. {
  419. Worker* workerPtr = firmPtr->worker_array;
  420. for(int j=1 ; j<=firmPtr->worker_count ; j++, workerPtr++ )
  421. {
  422. if( !workerPtr->race_id )
  423. continue;
  424. curRating = 0;
  425. if( workerPtr->race_id == race_id )
  426. curRating += 50;
  427. if( workerPtr->rank_id == RANK_GENERAL )
  428. curRating += 50;
  429. if( workerPtr->skill_id == SKILL_LEADING )
  430. curRating += workerPtr->skill_level;
  431. if( curRating > bestRating )
  432. {
  433. bestRating = curRating;
  434. bestUnitPtr = NULL;
  435. bestFirmPtr = firmPtr;
  436. bestWorkerId = j;
  437. }
  438. }
  439. }
  440. }
  441. //------- if the best successor is a mobile unit -------//
  442. if( bestUnitPtr )
  443. {
  444. //-- if the unit is in a command base or seat of power, mobilize it --//
  445. if( !bestUnitPtr->is_visible() )
  446. {
  447. err_when( bestUnitPtr->unit_mode != UNIT_MODE_OVERSEE );
  448. firm_array[bestUnitPtr->unit_mode_para]->mobilize_overseer();
  449. err_when( bestUnitPtr->skill.combat_level<= 0 );
  450. }
  451. //---------- succeed the king -------------//
  452. if( bestUnitPtr->is_visible() ) // it may still be not visible if there is no space for the unit to be mobilized
  453. {
  454. if( bestUnitPtr->spy_recno && bestUnitPtr->true_nation_recno() == nation_recno ) // if this is a spy and he's our spy
  455. spy_array[bestUnitPtr->spy_recno]->drop_spy_identity(); // revert the spy to a normal unit
  456. succeed_king( bestUnitPtr->sprite_recno );
  457. return 1;
  458. }
  459. }
  460. //------- if the best successor is a soldier in a camp -------//
  461. if( bestFirmPtr )
  462. {
  463. int unitRecno = bestFirmPtr->mobilize_worker(bestWorkerId, COMMAND_AI);
  464. if( unitRecno )
  465. {
  466. succeed_king( unitRecno );
  467. return 1;
  468. }
  469. }
  470. //--- if stil not found here, then try to locate the sucessor from villages ---//
  471. Town* townPtr;
  472. for( i=town_array.size() ; i>0 ; i-- )
  473. {
  474. if( town_array.is_deleted(i) )
  475. continue;
  476. townPtr = town_array[i];
  477. if( townPtr->nation_recno != nation_recno )
  478. continue;
  479. if( townPtr->recruitable_race_pop(race_id, 0) > 0 ) // if this town has people with the same race as the original king
  480. {
  481. int unitRecno = townPtr->mobilize_town_people(race_id, 1, 0); // 1-dec pop, 0-don't mobilize spies
  482. if( unitRecno )
  483. {
  484. succeed_king( unitRecno );
  485. return 1;
  486. }
  487. }
  488. }
  489. return 0;
  490. }
  491. //---------- End of function Nation::think_succeed_king ---------//
  492. //--------- Begin of function Nation::ai_improve_relation --------//
  493. //
  494. // This function is called once every year.
  495. //
  496. void Nation::ai_improve_relation()
  497. {
  498. NationRelation* nationRelation;
  499. for( int i=nation_array.size() ; i>0 ; i-- )
  500. {
  501. if( nation_array.is_deleted(i) )
  502. continue;
  503. nationRelation = get_relation(i);
  504. if( nationRelation->status == NATION_HOSTILE )
  505. continue;
  506. //--- It improves the AI relation with nations that have trade with us. ---//
  507. change_ai_relation_level( i, trade_rating(i) / 10 );
  508. //--- decrease the started_war_on_us_count once per year, gradually forgiving other nations' wrong doing ---//
  509. if( nationRelation->started_war_on_us_count > 0
  510. && m.random(5-pref_forgiveness/20) > 0 )
  511. {
  512. nationRelation->started_war_on_us_count--;
  513. }
  514. }
  515. }
  516. //---------- End of function Nation::ai_improve_relation --------//