OAI_MAR3.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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_MAR3.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::ai_settle_to_region ------//
  31. //
  32. // <int> destXLoc, destYLoc - the location of the destination to settle.
  33. // <int> seaActionId - SEA_ACTION_???
  34. //
  35. int Nation::ai_settle_to_region(int destXLoc, int destYLoc, int seaActionId)
  36. {
  37. #define SETTLE_REGION_UNIT_COUNT 9 // no. of units to move to settle on a new region each time
  38. //---- think about which town to recruit the people -----//
  39. int destRegionId = world.get_region_id(destXLoc, destYLoc);
  40. int curRating, bestRating=0, seaRegionId;
  41. Town *townPtr, *bestTown=NULL;
  42. for( int i=0 ; i<ai_town_count ; i++ )
  43. {
  44. townPtr = town_array[ ai_town_array[i] ];
  45. if( townPtr->has_linked_own_camp==0 ) // if there is no command base linked to this town, we cannot recruit any peasants from it
  46. continue;
  47. if( townPtr->jobless_population < SETTLE_REGION_UNIT_COUNT ) // don't get peasant from this town if the jobless population is less than 20
  48. continue;
  49. //--- only send units from this region if we have a harbor in that region ---//
  50. // ###### patch begin Gilbert 16/3 #######//
  51. // region_stat_id of a region may be zero
  52. if(
  53. //#ifdef AMPLUS
  54. region_array[townPtr->region_id]->region_stat_id == 0 ||
  55. //#endif
  56. region_array.get_region_stat(townPtr->region_id)->harbor_nation_count_array[nation_recno-1] == 0 )
  57. // ###### patch end Gilbert 16/3 #######//
  58. continue;
  59. curRating = world.distance_rating(destXLoc, destYLoc, townPtr->center_x, townPtr->center_y);
  60. curRating += townPtr->jobless_population;
  61. curRating += townPtr->average_loyalty(); // select a town with high loyalty
  62. if( curRating <= bestRating )
  63. continue;
  64. //------- see if we have ships ready currently -----//
  65. seaRegionId = region_array.get_sea_path_region_id(townPtr->region_id, destRegionId);
  66. if( !ai_find_transport_ship(seaRegionId, townPtr->center_x, townPtr->center_y, 0) ) // 0-don't have to find the best, return immediately whenever a suitable one is found
  67. continue;
  68. bestRating = curRating;
  69. bestTown = townPtr;
  70. }
  71. if( !bestTown )
  72. return 0;
  73. //------- try to recruit 9 units from one of our towns --------//
  74. short recruitedUnitArray[SETTLE_REGION_UNIT_COUNT];
  75. int recruitedCount=0;
  76. int raceId = bestTown->majority_race();
  77. int unitRecno;
  78. int loopCount=0;
  79. while( recruitedCount < SETTLE_REGION_UNIT_COUNT )
  80. {
  81. err_when( ++loopCount > 100 );
  82. if( bestTown->recruitable_race_pop( raceId, 1 ) )
  83. {
  84. unitRecno = bestTown->recruit(-1, raceId, COMMAND_AI);
  85. if( !unitRecno ) // no space for new unit
  86. break;
  87. err_when( unit_array.is_deleted(unitRecno) );
  88. err_when( !unit_array[unitRecno]->is_visible() );
  89. recruitedUnitArray[recruitedCount++] = unitRecno;
  90. }
  91. else
  92. {
  93. raceId = bestTown->pick_random_race(0, 1); // 0-recruitable only, 1-will also pick spies
  94. if( !raceId )
  95. break;
  96. }
  97. }
  98. //--- if due to some reasons that the no. of units recruited is less than half of what we need, do not continue to sea travel.
  99. if( recruitedCount < SETTLE_REGION_UNIT_COUNT/2 )
  100. return 0;
  101. int actionRecno = add_action( destXLoc, destYLoc, 0, 0, ACTION_AI_SEA_TRAVEL, seaActionId,
  102. recruitedCount, 0, 0, recruitedUnitArray );
  103. if( actionRecno ) // must process it immediately otherwise the recruited units will do something else
  104. return process_action(actionRecno);
  105. else
  106. return 0;
  107. }
  108. //------ End of function Nation::ai_settle_to_region -------//
  109. //------ Begin of function Nation::ai_patrol_to_region ------//
  110. //
  111. // Look for a military camp for moving all of its soldiers to
  112. // a new region and set up a new military camp to host the soldiers.
  113. //
  114. // <int> destXLoc, destYLoc - the location of the destination to set up
  115. // a military camp.
  116. // <int> seaActionId - SEA_ACTION_???
  117. //
  118. int Nation::ai_patrol_to_region(int destXLoc, int destYLoc, int seaActionId)
  119. {
  120. #define SETTLE_REGION_UNIT_COUNT 9 // no. of units to move to settle on a new region each time
  121. //---- think about which town to recruit the people -----//
  122. int destRegionId = world.get_region_id(destXLoc, destYLoc);
  123. int curRating, bestRating=0, seaRegionId;
  124. int kingRecno = nation_array[nation_recno]->king_unit_recno;
  125. FirmCamp *firmCamp, *bestCamp=NULL;
  126. for( int i=0 ; i<ai_camp_count ; i++ )
  127. {
  128. firmCamp = (FirmCamp*) firm_array[ ai_camp_array[i] ];
  129. if( !(firmCamp->overseer_recno && firmCamp->worker_count==MAX_WORKER) ) // only when the camp is filled with workers
  130. continue;
  131. if( firmCamp->ai_capture_town_recno ) // the base is trying to capture an independent town
  132. continue;
  133. if( firmCamp->is_attack_camp )
  134. continue;
  135. if( firmCamp->overseer_recno == kingRecno ) // if the king oversees this firm
  136. continue;
  137. //--- only send units from this region if we have a harbor in that region ---//
  138. // ####### patch begin Gilbert 16/3 ########//
  139. if(
  140. //#ifdef AMPLUS
  141. region_array[firmCamp->region_id]->region_stat_id == 0 ||
  142. //#endif
  143. region_array.get_region_stat(firmCamp->region_id)->harbor_nation_count_array[nation_recno-1] == 0 )
  144. continue;
  145. // ####### patch end Gilbert 16/3 ########//
  146. curRating = world.distance_rating(destXLoc, destYLoc, firmCamp->center_x, firmCamp->center_y);
  147. if( curRating <= bestRating )
  148. continue;
  149. //------- see if we have ships ready currently -----//
  150. seaRegionId = region_array.get_sea_path_region_id(firmCamp->region_id, destRegionId);
  151. if( !ai_find_transport_ship(seaRegionId, firmCamp->center_x, firmCamp->center_y, 0) ) // 0-don't have to find the best, return immediately whenever a suitable one is found
  152. continue;
  153. bestRating = curRating;
  154. bestCamp = firmCamp;
  155. }
  156. if( !bestCamp )
  157. return 0;
  158. //----- patrol the camp troop ajnd assign it to a ship -----//
  159. bestCamp->patrol();
  160. if( bestCamp->patrol_unit_count > 0 ) // there could be chances that there are no some for mobilizing the units
  161. {
  162. int actionRecno = add_action( destXLoc, destYLoc, 0, 0, ACTION_AI_SEA_TRAVEL, seaActionId,
  163. bestCamp->patrol_unit_count, 0, 0, bestCamp->patrol_unit_array );
  164. if( actionRecno ) // must process it immediately otherwise the recruited units will do something else
  165. return process_action(actionRecno);
  166. }
  167. return 0;
  168. }
  169. //------ End of function Nation::ai_patrol_to_region -------//
  170. //------- Begin of function Nation::has_trade_ship -----------//
  171. //
  172. // Whether this nation already has a trade ship travelling between
  173. // the two given harbors.
  174. //
  175. // return: <int> recno of the ship.
  176. // 0 - if there isn't any yet.
  177. //
  178. int Nation::has_trade_ship(int firmRecno1, int firmRecno2)
  179. {
  180. UnitMarine* unitMarine;
  181. for( int i=ai_ship_count-1 ; i>=0 ; i-- )
  182. {
  183. unitMarine = (UnitMarine*) unit_array[ ai_ship_array[i] ];
  184. err_when( unit_res[ unitMarine->unit_id ]->unit_class != UNIT_CLASS_SHIP );
  185. if( unitMarine->stop_defined_num < 2 )
  186. continue;
  187. if( ( unitMarine->stop_array[0].firm_recno == firmRecno1 &&
  188. unitMarine->stop_array[1].firm_recno == firmRecno2 ) ||
  189. ( unitMarine->stop_array[1].firm_recno == firmRecno1 &&
  190. unitMarine->stop_array[0].firm_recno == firmRecno2 ) )
  191. {
  192. return unitMarine->sprite_recno;
  193. }
  194. }
  195. return 0;
  196. }
  197. //--------- End of function Nation::has_trade_ship -----------//
  198. //------ Begin of function Nation::think_move_to_region_with_mine ------//
  199. //
  200. // Think about moving to a region with mines and settle a town next to
  201. // the mine.
  202. //
  203. int Nation::think_move_to_region_with_mine()
  204. {
  205. if( total_jobless_population < 30 )
  206. return 0;
  207. //---------------------------------------------------//
  208. int curRating, bestRating=0, bestRegionId=0;
  209. RegionStat* regionStat = region_array.region_stat_array;
  210. int i;
  211. for( i=0 ; i<region_array.region_stat_count ; i++, regionStat++ )
  212. {
  213. if( regionStat->town_nation_count_array[nation_recno-1] > 0 ) // if we already have towns there
  214. continue;
  215. if( regionStat->raw_count==0 )
  216. continue;
  217. //-- if we have already build one camp there, just waiting for sending a few peasants there, then process it first --//
  218. if( regionStat->camp_nation_count_array[nation_recno-1] > 0 )
  219. {
  220. bestRegionId = regionStat->region_id;
  221. break;
  222. }
  223. //-----------------------------------------------//
  224. curRating = regionStat->raw_count*3 - regionStat->nation_presence_count;
  225. if( curRating > bestRating )
  226. {
  227. bestRating = curRating;
  228. bestRegionId = regionStat->region_id;
  229. }
  230. }
  231. if( !bestRegionId )
  232. return 0;
  233. //----- select the raw site to acquire -----//
  234. Site* sitePtr;
  235. for( i=site_array.size() ; i>0 ; i-- )
  236. {
  237. if( site_array.is_deleted(i) )
  238. continue;
  239. sitePtr = site_array[i];
  240. if( sitePtr->region_id == bestRegionId )
  241. break;
  242. }
  243. if( i==0 )
  244. return 0;
  245. //----- decide the location of the settlement -----//
  246. return ai_build_camp_town_next_to( sitePtr->map_x_loc-1, sitePtr->map_y_loc-1,
  247. sitePtr->map_x_loc+1, sitePtr->map_y_loc+1 );
  248. }
  249. //------ End of function Nation::think_move_to_region_with_mine -------//
  250. //------ Begin of function Nation::ai_build_camp_town_next_to ------//
  251. //
  252. // Build a new camp and settle a new town next to the given location.
  253. //
  254. // <int> xLoc1, yLoc1, xLoc2, yLoc2 - the location that the new camp
  255. // and town should be built next to.
  256. //
  257. int Nation::ai_build_camp_town_next_to(int xLoc1, int yLoc1, int xLoc2, int yLoc2)
  258. {
  259. //---- first see if we already have a camp in the region ---//
  260. int regionId = world.get_region_id(xLoc1, yLoc1);
  261. // ##### patch begin Gilbert 16/3 #######//
  262. //#ifdef AMPLUS
  263. if( region_array[regionId]->region_stat_id == 0)
  264. return 0;
  265. //#endif
  266. // ##### patch end Gilbert 16/3 #######//
  267. if( region_array.get_region_stat(regionId)->camp_nation_count_array[nation_recno-1] == 0 )
  268. {
  269. //--- if we don't have one yet, build one next to the destination ---//
  270. if( !world.locate_space( xLoc1, yLoc1, xLoc2, yLoc2,
  271. 3, 3, UNIT_LAND, regionId, 1 ) ) // 1-locating the space for building
  272. {
  273. return 0;
  274. }
  275. if( !world.can_build_firm( xLoc1, yLoc1, FIRM_CAMP ) )
  276. return 0;
  277. return ai_patrol_to_region(xLoc1, yLoc1, SEA_ACTION_BUILD_CAMP);
  278. }
  279. else //-- if there's already a camp there, then set people there to settle --//
  280. {
  281. FirmCamp* firmCamp;
  282. for( int i=0 ; i<ai_camp_count ; i++ )
  283. {
  284. firmCamp = (FirmCamp*) firm_array[ ai_camp_array[i] ];
  285. if( firmCamp->region_id != regionId )
  286. continue;
  287. xLoc1 = firmCamp->loc_x1;
  288. yLoc1 = firmCamp->loc_y1;
  289. xLoc2 = firmCamp->loc_x2;
  290. yLoc2 = firmCamp->loc_y2;
  291. if( world.locate_space( xLoc1, yLoc1, xLoc2, yLoc2,
  292. STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, UNIT_LAND, regionId, 1 ) ) // 1-locating the space for building
  293. {
  294. if( world.can_build_town( xLoc1, yLoc1 ) )
  295. return ai_settle_to_region(xLoc1, yLoc1, SEA_ACTION_SETTLE);
  296. }
  297. }
  298. }
  299. return 0;
  300. }
  301. //------ End of function Nation::ai_build_camp_town_next_to -------//
  302. //------ Begin of function Nation::ai_sea_attack_target ------//
  303. //
  304. // <int> targetXLoc, targetYLoc - the location of the target.
  305. //
  306. int Nation::ai_sea_attack_target(int targetXLoc, int targetYLoc)
  307. {
  308. UnitMarine* unitMarine;
  309. int targetRegionId = world.get_region_id(targetXLoc, targetYLoc);
  310. int rc = 0;
  311. for( int i=0 ; i<ai_ship_count ; i++ )
  312. {
  313. unitMarine = (UnitMarine*) unit_array[ ai_ship_array[i] ];
  314. if( unitMarine->attack_count==0 )
  315. continue;
  316. if( !unitMarine->is_ai_all_stop() )
  317. continue;
  318. //----- if the ship is in the harbor now -----//
  319. if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR )
  320. {
  321. FirmHarbor* firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para];
  322. if( firmHarbor->sea_region_id != targetRegionId )
  323. continue;
  324. firmHarbor->sail_ship(unitMarine->sprite_recno, COMMAND_AI);
  325. }
  326. if( !unitMarine->is_visible() ) // no space in the sea for placing the ship
  327. continue;
  328. if( unitMarine->region_id() != targetRegionId )
  329. continue;
  330. //------ order the ship to attack the target ------//
  331. unitMarine->attack_unit( targetXLoc, targetYLoc );
  332. rc = 1;
  333. }
  334. return rc;
  335. }
  336. //-------- End of function Nation::ai_sea_attack_target -------//