OAI_MARI.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  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_MARI.CPP
  21. //Description: AI functions on sea exploration, trading
  22. #include <OTOWN.h>
  23. #include <OREGIONS.h>
  24. #include <OU_MARI.h>
  25. #include <OUNITRES.h>
  26. #include <OSITE.h>
  27. #include <OF_HARB.h>
  28. #include <OF_CAMP.h>
  29. #include <ONATION.h>
  30. //--------- Begin of function Nation::think_marine --------//
  31. //
  32. void Nation::think_marine()
  33. {
  34. if( pref_use_marine < 50 ) // don't use marine at all
  35. return;
  36. if( !ai_should_spend(20+pref_use_marine/2) ) // 20 to 70 importance rating
  37. return;
  38. //--- think over building harbor network ---//
  39. think_build_harbor_network();
  40. if( ai_harbor_count == 0 )
  41. return;
  42. //------ think about sea attack enemies -------//
  43. if( m.random(3)==0 ) // 33% chance
  44. {
  45. if( think_sea_attack_enemy() )
  46. return;
  47. }
  48. //---- check if it is safe for sea travel now ----//
  49. if( !ai_is_sea_travel_safe() )
  50. return;
  51. //----- think over moving between regions -----//
  52. think_move_between_region();
  53. // think_move_to_region_with_mine();
  54. }
  55. //---------- End of function Nation::think_marine --------//
  56. //----- Begin of function Nation::think_build_harbor_network ----//
  57. //
  58. // Think about thinking a harbor network so that we have harbors
  59. // from every region to any other regions.
  60. //
  61. int Nation::think_build_harbor_network()
  62. {
  63. //--- only build one harbor at a time, to avoid double building ---//
  64. if( is_action_exist( ACTION_AI_BUILD_FIRM, FIRM_HARBOR ) )
  65. return 0;
  66. //--------------------------------------------//
  67. RegionStat* regionStat = region_array.region_stat_array;
  68. RegionPath* regionPath;
  69. for( int i=0 ; i<region_array.region_stat_count ; i++, regionStat++ )
  70. {
  71. //--- only build on those regions that this nation has base towns ---//
  72. if( !regionStat->base_town_nation_count_array[nation_recno-1] )
  73. continue;
  74. if( regionStat->harbor_nation_count_array[nation_recno-1] > 0 ) // if we already have a harbor in this region
  75. continue;
  76. err_when( regionStat->harbor_nation_count_array[nation_recno-1] > 1 ); // this shouldn't happen if the AI works properly
  77. //-----------------------------------------------------------------------//
  78. //
  79. // Scan thru all regions which this region can be connected to thru sea.
  80. // If one of them is worth our landing, then builld a harbor in this
  81. // region so we can sail to that region.
  82. //
  83. //-----------------------------------------------------------------------//
  84. regionPath = regionStat->reachable_region_array;
  85. for( int j=0 ; j<regionStat->reachable_region_count ; j++, regionPath++ )
  86. {
  87. err_when( regionPath->land_region_stat_id == i+1 ); // pointing back to its own
  88. //--------------------------------------//
  89. if( ai_harbor_count == 0 && // if we have already built one harbor, then we should continue to build others asa single harbor isn't useful
  90. ai_should_sail_to_rating(regionPath->land_region_stat_id) <= 0 )
  91. {
  92. continue;
  93. }
  94. //--------- build a harbor now ---------//
  95. if( ai_build_harbor( regionStat->region_id, regionPath->sea_region_id ) )
  96. return 1;
  97. }
  98. }
  99. return 0;
  100. }
  101. //----- End of function Nation::think_build_harbor_network ----//
  102. //----- Begin of function Nation::ai_should_sail_to_rating ----//
  103. //
  104. int Nation::ai_should_sail_to_rating(int regionStatId)
  105. {
  106. RegionStat* regionStat = region_array.get_region_stat2(regionStatId);
  107. int curRating;
  108. curRating = regionStat->raw_count * 100
  109. + regionStat->independent_town_count * 20
  110. + regionStat->nation_presence_count * 30;
  111. /*
  112. - (regionStat->total_town_count - regionStat->town_nation_count_array[nation_recno-1] ) * 10 // towns of other nations
  113. - (regionStat->total_firm_count - regionStat->firm_nation_count_array[nation_recno-1] ) * 5 // firms of other nations
  114. - (regionStat->total_unit_count - regionStat->unit_nation_count_array[nation_recno-1] ) * 2 // units of other nations
  115. - regionStat->independent_unit_count * 2; // monsters or rebel units
  116. */
  117. return curRating > 0;
  118. }
  119. //----- End of function Nation::ai_should_sail_to_rating ----//
  120. //--------- Begin of function Nation::ai_build_harbor --------//
  121. //
  122. // Build a harbor across the given land and sea region id.
  123. //
  124. // <int> landRegionId - the land region id.
  125. // <int> seaRegionId - the sea region id.
  126. //
  127. // return: <int> 1 - a suitable location is found and the
  128. // building action has been queued.
  129. // 0 - not suitable location is found.
  130. //
  131. int Nation::ai_build_harbor(int landRegionId, int seaRegionId)
  132. {
  133. #define ADEQUATE_ENEMY_HARBOR_DISTANCE 10
  134. //---- randomly pick a base town of this nation ----//
  135. Town* townPtr;
  136. int townSeq = m.random(ai_town_count);
  137. int i;
  138. for( i=0 ; i<ai_town_count ; i++ )
  139. {
  140. if( ++townSeq >= ai_town_count )
  141. townSeq=0;
  142. townPtr = town_array[ ai_town_array[townSeq] ];
  143. if( townPtr->is_base_town && landRegionId==townPtr->region_id )
  144. break;
  145. }
  146. if( i==ai_town_count ) // not found
  147. return 0;
  148. int homeXLoc = townPtr->center_x;
  149. int homeYLoc = townPtr->center_y;
  150. //---- scan out from the town and find the nearest suitable location to build the harbor ----//
  151. int xOffset, yOffset;
  152. int xLoc, yLoc, bestXLoc= -1, bestYLoc= -1, maxEnemyDistance=0;
  153. Location* locPtr;
  154. for( i=2 ; i<MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC ; i++ )
  155. {
  156. m.cal_move_around_a_point(i, MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC, xOffset, yOffset);
  157. xLoc = homeXLoc + xOffset;
  158. yLoc = homeYLoc + yOffset;
  159. xLoc = max(0, xLoc);
  160. xLoc = min(MAX_WORLD_X_LOC-1, xLoc);
  161. yLoc = max(0, yLoc);
  162. yLoc = min(MAX_WORLD_Y_LOC-1, yLoc);
  163. locPtr = world.get_loc(xLoc, yLoc);
  164. if( !locPtr->can_build_whole_harbor() )
  165. continue;
  166. if( !world.is_adjacent_region(xLoc, yLoc, seaRegionId) )
  167. continue;
  168. if( !world.can_build_firm(xLoc, yLoc, FIRM_HARBOR) )
  169. continue;
  170. //--------------------------------------//
  171. int enemyDistance = closest_enemy_firm_distance(FIRM_HARBOR, xLoc, yLoc);
  172. if( enemyDistance > maxEnemyDistance )
  173. {
  174. maxEnemyDistance = enemyDistance;
  175. bestXLoc = xLoc;
  176. bestYLoc = yLoc;
  177. if( enemyDistance >= ADEQUATE_ENEMY_HARBOR_DISTANCE )
  178. break;
  179. }
  180. }
  181. //--------------------------------//
  182. if( bestXLoc >= 0 )
  183. {
  184. add_action(xLoc, yLoc, homeXLoc, homeYLoc, ACTION_AI_BUILD_FIRM, FIRM_HARBOR);
  185. return 1;
  186. }
  187. return 0;
  188. }
  189. //---------- End of function Nation::ai_build_harbor --------//
  190. //--------- Begin of function Nation::closest_enemy_firm_distance --------//
  191. //
  192. // Return how close is the cloeset enemy harbor to the given location.
  193. //
  194. // <int> firmId - firm id.
  195. // <int> xLoc, yLoc - the given location
  196. //
  197. int Nation::closest_enemy_firm_distance(int firmId, int xLoc, int yLoc)
  198. {
  199. int curDistance, minDistance=0x7FFF;
  200. for( int i=firm_array.size() ; i>0 ; i-- )
  201. {
  202. if( firm_array.is_deleted(i) )
  203. continue;
  204. Firm* firmPtr = firm_array[i];
  205. if( firmPtr->firm_id != firmId ||
  206. firmPtr->nation_recno == nation_recno ) // belonging to own nation, not enemy nation
  207. {
  208. continue;
  209. }
  210. curDistance = m.points_distance(firmPtr->center_x, firmPtr->center_y, xLoc, yLoc);
  211. if( curDistance < minDistance )
  212. minDistance = curDistance;
  213. }
  214. return minDistance;
  215. }
  216. //---------- End of function Nation::closest_enemy_firm_distance --------//
  217. //------ Begin of function Nation::think_move_between_region ------//
  218. //
  219. int Nation::think_move_between_region()
  220. {
  221. if( think_move_people_between_region() )
  222. return 1;
  223. if( think_move_troop_between_region() )
  224. return 1;
  225. return 0;
  226. }
  227. //------ End of function Nation::think_move_between_region -------//
  228. //------ Begin of function Nation::think_move_troop_between_region ------//
  229. //
  230. // Thing about moving units between regions
  231. //
  232. int Nation::think_move_troop_between_region()
  233. {
  234. //----- find the region with the least population -----//
  235. int campCount, maxCampCount=0, minCampCount=0x1000;
  236. int maxRegionId=0, minRegionId=0;
  237. RegionStat* regionStat = region_array.region_stat_array;
  238. int curRating, minRegionRating=0;
  239. int i;
  240. for( i=0 ; i<region_array.region_stat_count ; i++, regionStat++ )
  241. {
  242. if( regionStat->nation_presence_count==0 &&
  243. regionStat->independent_town_count==0 &&
  244. regionStat->raw_count==0 )
  245. {
  246. continue;
  247. }
  248. campCount = regionStat->camp_nation_count_array[nation_recno-1];
  249. if( campCount > maxCampCount )
  250. {
  251. maxCampCount = campCount;
  252. maxRegionId = regionStat->region_id;
  253. }
  254. if( campCount <= minCampCount )
  255. {
  256. curRating = ai_should_sail_to_rating(i+1);
  257. if( campCount < minCampCount || curRating >= minRegionRating )
  258. {
  259. minCampCount = campCount;
  260. minRegionId = regionStat->region_id;
  261. minRegionRating = curRating;
  262. }
  263. }
  264. }
  265. if( !maxRegionId || !minRegionId || maxRegionId==minRegionId )
  266. return 0;
  267. //----- only move if the difference is big enough ------//
  268. int minJoblessPop = region_array.get_region_stat(minRegionId)->nation_jobless_population_array[nation_recno-1];
  269. int maxJoblessPop = region_array.get_region_stat(maxRegionId)->nation_jobless_population_array[nation_recno-1];
  270. if( pref_use_marine < 90 ) // if > 90, it will ignore all these and move anyway
  271. {
  272. if( minCampCount==0 )
  273. {
  274. if( maxJoblessPop - minJoblessPop < 200 - pref_use_marine ) // 150 to 200 (pref_use_marine is always >= 50, if it is < 50, marine functions are not called at all
  275. return 0;
  276. }
  277. else
  278. {
  279. if( maxJoblessPop - minJoblessPop < 150 - pref_use_marine ) // 100 to 150 (pref_use_marine is always >= 50, if it is < 50, marine functions are not called at all
  280. return 0;
  281. }
  282. }
  283. else
  284. {
  285. if( maxJoblessPop < 20 ) // don't move if we only have a few jobless people
  286. return 0;
  287. }
  288. //------------ see if we have any camps in the region -----------//
  289. int destRegionId = minRegionId;
  290. Firm* firmPtr;
  291. for( i=ai_camp_count-1 ; i>=0 ; i-- )
  292. {
  293. firmPtr = firm_array[ai_camp_array[i]];
  294. if( firmPtr->region_id == destRegionId &&
  295. !firmPtr->under_construction ) // if it's under construction there may be unit waiting outside of the camp
  296. {
  297. //--- if there is one, must move the troop close to it ---//
  298. return ai_patrol_to_region(firmPtr->center_x, firmPtr->center_y, SEA_ACTION_NONE);
  299. }
  300. }
  301. //----- if we don't have any camps in the region, build one ----//
  302. int xLoc=0, yLoc=0;
  303. FirmInfo* firmInfo = firm_res[FIRM_CAMP];
  304. if(world.locate_space_random(xLoc, yLoc, MAX_WORLD_X_LOC-1,
  305. MAX_WORLD_Y_LOC-1, firmInfo->loc_width, firmInfo->loc_height,
  306. MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC, destRegionId, 1))
  307. {
  308. return ai_patrol_to_region(xLoc, yLoc, SEA_ACTION_BUILD_CAMP);
  309. }
  310. return 0;
  311. }
  312. //------ End of function Nation::think_move_troop_between_region -------//
  313. //------ Begin of function Nation::think_move_people_between_region ------//
  314. //
  315. // Thing about moving units between regions
  316. //
  317. int Nation::think_move_people_between_region()
  318. {
  319. //----- find the region with the least population -----//
  320. int joblessPop, maxJoblessPop=0, minJoblessPop=0x1000;
  321. int maxRegionId=0, minRegionId=0;
  322. RegionStat* regionStat = region_array.region_stat_array;
  323. int i;
  324. for( i=0 ; i<region_array.region_stat_count ; i++, regionStat++ )
  325. {
  326. //--- only move to regions in which we have camps ---//
  327. if( regionStat->camp_nation_count_array[nation_recno-1] == 0 )
  328. continue;
  329. joblessPop = regionStat->nation_jobless_population_array[nation_recno-1];
  330. if( joblessPop > maxJoblessPop )
  331. {
  332. maxJoblessPop = joblessPop;
  333. maxRegionId = regionStat->region_id;
  334. }
  335. if( joblessPop < minJoblessPop )
  336. {
  337. minJoblessPop = joblessPop;
  338. minRegionId = regionStat->region_id;
  339. }
  340. }
  341. if( !maxRegionId || !minRegionId || maxRegionId==minRegionId )
  342. return 0;
  343. //----- only move if the difference is big enough ------//
  344. if( pref_use_marine < 90 ) // if > 90, it will ignore all these and move anyway
  345. {
  346. if( maxJoblessPop - minJoblessPop < 150 - pref_use_marine ) // 100 to 150 (pref_use_marine is always >= 50, if it is < 50, marine functions are not called at all
  347. return 0;
  348. }
  349. else
  350. {
  351. if( maxJoblessPop < 20 ) // don't move if we only have a few jobless people
  352. return 0;
  353. }
  354. //------------ see if we have any towns in the region -----------//
  355. int destRegionId = minRegionId;
  356. Town* townPtr;
  357. for( i=ai_town_count-1 ; i>=0 ; i-- )
  358. {
  359. townPtr = town_array[ai_town_array[i]];
  360. if( townPtr->region_id == destRegionId )
  361. {
  362. //--- if there is one, must move the people to it ---//
  363. return ai_settle_to_region(townPtr->center_x, townPtr->center_y, SEA_ACTION_NONE);
  364. }
  365. }
  366. //----- if we don't have any towns in the region, settle one ----//
  367. int xLoc=0, yLoc=0;
  368. if(world.locate_space_random(xLoc, yLoc, MAX_WORLD_X_LOC-1,
  369. MAX_WORLD_Y_LOC-1, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT,
  370. MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC, destRegionId, 1))
  371. {
  372. return ai_settle_to_region(xLoc, yLoc, SEA_ACTION_SETTLE);
  373. }
  374. return 0;
  375. }
  376. //------ End of function Nation::think_move_people_between_region -------//
  377. //------ Begin of function Nation::ai_is_sea_travel_safe ------//
  378. //
  379. // return: <int> 1 - it's safe for sea travel
  380. // 0 - it's not safe for sea travel
  381. //
  382. int Nation::ai_is_sea_travel_safe()
  383. {
  384. //--- count the no. of battle ships owned by each nation ---//
  385. Unit* unitPtr;
  386. short nationShipCountArray[MAX_NATION];
  387. memset( nationShipCountArray, 0, sizeof(nationShipCountArray) );
  388. int i;
  389. for( i=unit_array.size() ; i>0 ; i-- )
  390. {
  391. if( unit_array.is_deleted(i) )
  392. continue;
  393. unitPtr = unit_array[i];
  394. if( unitPtr->unit_id != UNIT_CARAVEL &&
  395. unitPtr->unit_id != UNIT_GALLEON )
  396. {
  397. continue;
  398. }
  399. err_when( unitPtr->nation_recno < 1 || unitPtr->nation_recno > MAX_NATION );
  400. nationShipCountArray[unitPtr->nation_recno-1]++;
  401. }
  402. //--- compare the no. of ships of ours and those of the human players ---//
  403. int ourBattleShipCount = nationShipCountArray[nation_recno-1];
  404. int nationRecno = m.random(nation_array.size())+1;
  405. for( i=nation_array.size() ; i>0 ; i-- )
  406. {
  407. if( ++nationRecno > nation_array.size() )
  408. nationRecno = 1;
  409. if( nation_array.is_deleted(nationRecno) )
  410. continue;
  411. if( get_relation(nationRecno)->status != NATION_HOSTILE ) // only check enemies
  412. continue;
  413. if( nation_array[nationRecno]->is_ai() ) // only check human players
  414. continue;
  415. //-- if enemy has battle ships, it is not safe for sea travel, destroy them first ---//
  416. if( nationShipCountArray[nationRecno-1] > 0 )
  417. {
  418. //--- if enemy ships significantly outnumber ours, don't do any sea travel ---//
  419. if( nationShipCountArray[nationRecno-1] - ourBattleShipCount >
  420. pref_military_courage/3 ) // 0 to 3
  421. {
  422. return 0;
  423. }
  424. }
  425. }
  426. return 1;
  427. }
  428. //----- End of function Nation::ai_is_sea_travel_safe -----//
  429. //------ Begin of function Nation::max_human_battle_ship_count ------//
  430. //
  431. // return: <int> the number of ships owned by the human player who
  432. // is strongest on sea power.
  433. //
  434. int Nation::max_human_battle_ship_count()
  435. {
  436. //--- count the no. of battle ships owned by each nation ---//
  437. Unit* unitPtr;
  438. short nationShipCountArray[MAX_NATION];
  439. memset( nationShipCountArray, 0, sizeof(nationShipCountArray) );
  440. int i;
  441. for( i=unit_array.size() ; i>0 ; i-- )
  442. {
  443. if( unit_array.is_deleted(i) )
  444. continue;
  445. unitPtr = unit_array[i];
  446. if( unitPtr->unit_id != UNIT_CARAVEL &&
  447. unitPtr->unit_id != UNIT_GALLEON )
  448. {
  449. continue;
  450. }
  451. err_when( unitPtr->nation_recno < 1 || unitPtr->nation_recno > MAX_NATION );
  452. nationShipCountArray[unitPtr->nation_recno-1]++;
  453. }
  454. //--- compare the no. of ships of ours and those of the human players ---//
  455. int maxShipCount=0;
  456. for( i=nation_array.size() ; i>0 ; i-- )
  457. {
  458. if( nation_array.is_deleted(i) )
  459. continue;
  460. if( nation_array[i]->is_ai() ) // only check human players
  461. continue;
  462. //-- if enemy has battle ships, it is not safe for sea travel, destroy them first ---//
  463. if( nationShipCountArray[i-1] > maxShipCount )
  464. {
  465. maxShipCount = nationShipCountArray[i-1];
  466. }
  467. }
  468. return maxShipCount;
  469. }
  470. //----- End of function Nation::max_human_battle_ship_count -----//
  471. //------ Begin of function Nation::think_sea_attack_enemy ------//
  472. //
  473. // Think about attacking enemy harbors and ships.
  474. //
  475. int Nation::think_sea_attack_enemy()
  476. {
  477. if( total_ship_combat_level < 700 - (pref_military_courage + pref_use_marine)*2 ) // 300 to 700
  478. return 0;
  479. //-----------------------------------------//
  480. int totalFirm = firm_array.size();
  481. int firmRecno = m.random(totalFirm)+1;
  482. Firm* firmPtr;
  483. for( int i=0 ; i<totalFirm ; i++ )
  484. {
  485. if( ++firmRecno > totalFirm )
  486. firmRecno = 1;
  487. if( firm_array.is_deleted(firmRecno) )
  488. continue;
  489. firmPtr = firm_array[firmRecno];
  490. if( firmPtr->firm_id != FIRM_HARBOR )
  491. continue;
  492. if( get_relation_status(firmPtr->nation_recno) != NATION_HOSTILE )
  493. continue;
  494. //--- if the AI has more powerful fleets than the enemy ---//
  495. if( total_ship_combat_level >
  496. nation_array[firmPtr->nation_recno]->total_ship_combat_level )
  497. {
  498. ai_sea_attack_target(firmPtr->center_x, firmPtr->center_y);
  499. return 1;
  500. }
  501. }
  502. return 0;
  503. }
  504. //----- End of function Nation::think_sea_attack_enemy -----//