OAI_ACT2.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  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_ACT.CPP
  21. //Description: AI - action progressing functions
  22. #include <ALL.h>
  23. #include <OBOX.h>
  24. #include <OSYS.h>
  25. #include <OSPY.h>
  26. #include <OINFO.h>
  27. #include <OUNIT.h>
  28. #include <OFIRM.h>
  29. #include <ONATION.h>
  30. //-------- Begin of function Nation::ai_build_firm -------//
  31. //
  32. // action_x_loc, action_y_loc - location of the building site.
  33. // ref_x_loc, ref_y_loc - location of the town which the base
  34. // should be built next to.
  35. // action_para - firm id.
  36. // action_para2 - firm race id. (for FirmBase only)
  37. //
  38. int Nation::ai_build_firm(ActionNode* actionNode)
  39. {
  40. if(!seek_path.total_node_avail)
  41. return 0;
  42. err_when( actionNode->action_x_loc < 0 || actionNode->action_y_loc < 0 ); // they must be given when this function is called
  43. //-------- determine the skill id. needed -------//
  44. int firmId = actionNode->action_para;
  45. int raceId = actionNode->action_para2;
  46. int skillId = firm_res[firmId]->firm_skill_id;
  47. if( !skillId ) // if the firm does not have a specific skill (e.g. Inn), use the general SKILL_CONSTRUCTION
  48. skillId = SKILL_CONSTRUCTION; // for military camps, use construction workers instead of generals for facilitating migration of military camps
  49. //---- if there are camps that should be closed available now, transfer soldiers there to the new camp, ask a construction worker to build the camp so we can transfer the whole troop to the new camp ---//
  50. if( firmId==FIRM_CAMP &&
  51. ai_has_should_close_camp( world.get_region_id( actionNode->action_x_loc, actionNode->action_y_loc ) ) )
  52. {
  53. skillId = SKILL_CONSTRUCTION; // for military camps, use construction workers instead of generals for facilitating migration of military camps
  54. }
  55. //------------- get a skilled unit --------------//
  56. Unit* skilledUnit = get_skilled_unit(skillId, raceId, actionNode);
  57. if( !skilledUnit )
  58. return 0;
  59. //--- a unit with the specific skill is not found, try to find a construction unit instead ---//
  60. if( skillId != SKILL_CONSTRUCTION )
  61. {
  62. Unit* skilledUnit = get_skilled_unit(skillId, raceId, actionNode);
  63. if( !skilledUnit )
  64. return 0;
  65. }
  66. //------- build the firm now ---------//
  67. skilledUnit->build_firm(actionNode->action_x_loc, actionNode->action_y_loc, firmId, COMMAND_AI);
  68. if(skilledUnit->action_x_loc==actionNode->action_x_loc && skilledUnit->action_y_loc==actionNode->action_y_loc)
  69. {
  70. err_when( skilledUnit->nation_recno==0 );
  71. skilledUnit->ai_action_id = actionNode->action_id;
  72. actionNode->unit_recno = skilledUnit->sprite_recno;
  73. return 1;
  74. }
  75. else
  76. {
  77. skilledUnit->stop2();
  78. return 0;
  79. }
  80. }
  81. //-------- End of function Nation::ai_build_firm -------//
  82. //----- Begin of function Nation::ai_assign_overseer -----//
  83. //
  84. // action_x_loc, action_y_loc - location of the firm to which the overseer should be assigned.
  85. // ref_x_loc, ref_y_loc - not used
  86. // action_para - firm id.
  87. // [action_para2] - race id of the overseer
  88. // (if not given, the majority race will be used.)
  89. //
  90. int Nation::ai_assign_overseer(ActionNode* actionNode)
  91. {
  92. //---------------------------------------------------------------------------//
  93. // cancel action if the firm is deleted, has incorrect firm_id or nation is
  94. // changed
  95. //---------------------------------------------------------------------------//
  96. int firmId = actionNode->action_para;
  97. err_when( !firmId );
  98. if(!check_firm_ready(actionNode->action_x_loc, actionNode->action_y_loc, firmId)) // return 0 to cancel action
  99. return -1; // -1 means remove the current action immediately
  100. if(!seek_path.total_node_avail)
  101. return 0;
  102. //-------- get the poisnter to the firm -------//
  103. Location* locPtr = world.get_loc(actionNode->action_x_loc, actionNode->action_y_loc);
  104. err_when(!locPtr->is_firm());
  105. Firm* firmPtr = firm_array[ locPtr->firm_recno() ];
  106. //-------- get a skilled unit --------//
  107. int raceId; // the race of the needed unit
  108. if( actionNode->action_para2 )
  109. {
  110. raceId = actionNode->action_para2;
  111. }
  112. else
  113. {
  114. if( firmPtr->firm_id == FIRM_BASE ) // for seat of power, the race must be specific
  115. raceId = firm_res.get_build(firmPtr->firm_build_id)->race_id;
  116. else
  117. raceId = firmPtr->majority_race();
  118. }
  119. Unit* skilledUnit = get_skilled_unit(SKILL_LEADING, raceId, actionNode);
  120. if( !skilledUnit )
  121. return 0;
  122. //---------------------------------------------------------------------------//
  123. FirmInfo* firmInfo = firm_res[firmId];
  124. err_when( !firmInfo->need_overseer );
  125. if(skilledUnit->rank_id==RANK_SOLDIER)
  126. skilledUnit->set_rank(RANK_GENERAL);
  127. skilledUnit->assign(actionNode->action_x_loc, actionNode->action_y_loc);
  128. skilledUnit->ai_action_id = actionNode->action_id;
  129. err_when( skilledUnit->nation_recno != nation_recno );
  130. actionNode->unit_recno = skilledUnit->sprite_recno;
  131. return 1;
  132. }
  133. //----- End of function Nation::ai_assign_overseer -----//
  134. //----- Begin of function Nation::ai_assign_construction_worker -----//
  135. //
  136. // action_x_loc, action_y_loc - location of the firm to which the overseer should be assigned.
  137. // ref_x_loc, ref_y_loc - not used
  138. //
  139. int Nation::ai_assign_construction_worker(ActionNode* actionNode)
  140. {
  141. //---------------------------------------------------------------------------//
  142. // cancel action if the firm is deleted, has incorrect firm_id or nation is
  143. // changed
  144. //---------------------------------------------------------------------------//
  145. if(!check_firm_ready(actionNode->action_x_loc, actionNode->action_y_loc)) // return 0 to cancel action
  146. return -1; // -1 means remove the current action immediately
  147. if(!seek_path.total_node_avail)
  148. return 0;
  149. //-------- get the poisnter to the firm -------//
  150. Location* locPtr = world.get_loc(actionNode->action_x_loc, actionNode->action_y_loc);
  151. err_when(!locPtr->is_firm());
  152. Firm* firmPtr = firm_array[ locPtr->firm_recno() ];
  153. if( firmPtr->builder_recno ) // if the firm already has a construction worker
  154. return -1;
  155. //-------- get a skilled unit --------//
  156. Unit* skilledUnit = get_skilled_unit(SKILL_CONSTRUCTION, 0, actionNode);
  157. if( !skilledUnit )
  158. return 0;
  159. //------------------------------------------------------------------//
  160. skilledUnit->assign(actionNode->action_x_loc, actionNode->action_y_loc);
  161. skilledUnit->ai_action_id = actionNode->action_id;
  162. err_when( skilledUnit->nation_recno != nation_recno );
  163. actionNode->unit_recno = skilledUnit->sprite_recno;
  164. return 1;
  165. }
  166. //----- End of function Nation::ai_assign_construction_worker -----//
  167. //----- Begin of function Nation::ai_assign_worker -----//
  168. //
  169. // action_x_loc, action_y_loc - location of the firm to which the overseer should be assigned.
  170. // ref_x_loc, ref_y_loc - not used
  171. // action_para - firm id.
  172. // [action_para2] - race id of the overseer
  173. // (if not given, the majority race will be used.)
  174. //
  175. int Nation::ai_assign_worker(ActionNode* actionNode)
  176. {
  177. //---------------------------------------------------------------------------//
  178. // cancel action if the firm is deleted, has incorrect firm_id or nation is
  179. // changed
  180. //---------------------------------------------------------------------------//
  181. int firmId = actionNode->action_para;
  182. err_when( !firmId );
  183. if(!check_firm_ready(actionNode->action_x_loc, actionNode->action_y_loc, firmId)) // return 0 to cancel action
  184. return -1; // -1 means remove the current action immediately
  185. if(!seek_path.total_node_avail)
  186. return 0;
  187. //---------------------------------------------------------------------------//
  188. // cancel this action if the firm already has enough workers
  189. //---------------------------------------------------------------------------//
  190. Location* locPtr = world.get_loc(actionNode->action_x_loc, actionNode->action_y_loc);
  191. err_when(!locPtr->is_firm());
  192. Firm* firmPtr = firm_array[locPtr->firm_recno()];
  193. err_when( firmPtr->firm_id != firmId );
  194. err_when( !firm_res[firmPtr->firm_id]->need_worker );
  195. if(firmPtr->worker_count>=MAX_WORKER)
  196. return -1;
  197. if( MAX_WORKER - firmPtr->worker_count < actionNode->instance_count ) // if the firm now has more workers, reduce the number needed to be assigned to the firm
  198. {
  199. err_when( actionNode->processing_instance_count >= actionNode->instance_count );
  200. actionNode->instance_count = max( actionNode->processing_instance_count+1, MAX_WORKER - firmPtr->worker_count );
  201. }
  202. //---------------------------------------------------------------------------//
  203. // firm exists and belongs to our nation. Assign worker to firm
  204. //---------------------------------------------------------------------------//
  205. int unitRecno=0;
  206. Unit* unitPtr = NULL;
  207. //----------- use a trained unit --------//
  208. if( actionNode->unit_recno )
  209. unitPtr = unit_array[actionNode->unit_recno];
  210. //------ recruit on job worker ----------//
  211. if( !unitPtr && firmPtr->firm_id != FIRM_BASE ) // seat of power shouldn't call this function at all, as it doesn't handle the racial issue.
  212. {
  213. unitRecno = recruit_on_job_worker(firmPtr, actionNode->action_para2);
  214. if( unitRecno )
  215. unitPtr = unit_array[unitRecno];
  216. }
  217. //------- train a unit --------------//
  218. if( !unitPtr &&
  219. firmPtr->firm_id == FIRM_CAMP &&
  220. ai_should_spend( 20+pref_military_development/2 ) ) // 50 to 70
  221. {
  222. int trainTownRecno;
  223. if( train_unit( firmPtr->firm_skill_id, firmPtr->majority_race(),
  224. actionNode->action_x_loc, actionNode->action_y_loc,
  225. trainTownRecno, actionNode->action_id ) )
  226. {
  227. actionNode->next_retry_date = info.game_date + TOTAL_TRAIN_DAYS + 1;
  228. actionNode->retry_count++;
  229. return 0; // training in process
  230. }
  231. }
  232. //-------- recruit a unit ----------//
  233. if( !unitPtr )
  234. {
  235. unitRecno = recruit_jobless_worker(firmPtr, actionNode->action_para2);
  236. if( unitRecno )
  237. unitPtr = unit_array[unitRecno];
  238. }
  239. if( !unitPtr )
  240. return 0;
  241. //---------------------------------------------------------------------------//
  242. FirmInfo* firmInfo = firm_res[firmId];
  243. if( !world.get_loc(actionNode->action_x_loc, actionNode->action_y_loc)->is_firm() ) // firm exists, so assign
  244. return -1;
  245. err_when( unitPtr->rank_id != RANK_SOLDIER );
  246. unitPtr->assign(actionNode->action_x_loc, actionNode->action_y_loc);
  247. unitPtr->ai_action_id = actionNode->action_id;
  248. err_when( unitPtr->nation_recno != nation_recno );
  249. return 1;
  250. }
  251. //----- End of function Nation::ai_assign_worker -----//
  252. //----- Begin of function Nation::ai_settle_to_other_town -----//
  253. //
  254. // action_x_loc, action_y_loc - location of the destination town.
  255. // ref_x_loc, ref_y_loc - location of the origin town.
  256. //
  257. int Nation::ai_settle_to_other_town(ActionNode* actionNode)
  258. {
  259. if(!seek_path.total_node_avail)
  260. return 0;
  261. //------- check if both towns are ready first --------//
  262. if(!check_town_ready(actionNode->action_x_loc, actionNode->action_y_loc) ||
  263. !check_town_ready(actionNode->ref_x_loc, actionNode->ref_y_loc))
  264. {
  265. return -1;
  266. }
  267. //----------------------------------------------------//
  268. // stop if no jobless population
  269. //----------------------------------------------------//
  270. Location* locPtr = world.get_loc(actionNode->ref_x_loc, actionNode->ref_y_loc);
  271. err_when(!locPtr->is_town() || town_array.is_deleted(locPtr->town_recno()));
  272. Town* townPtr = town_array[locPtr->town_recno()]; // point to the old town
  273. int raceId = townPtr->pick_random_race(0, 1); // 0-don't pick has job unit, 1-pick spies
  274. if( !raceId )
  275. return -1;
  276. //---- if cannot recruit because the loyalty is too low ---//
  277. if( !townPtr->can_recruit(raceId) && townPtr->has_linked_own_camp )
  278. {
  279. int minRecruitLoyalty = MIN_RECRUIT_LOYALTY + townPtr->recruit_dec_loyalty(raceId, 0);
  280. //--- if cannot recruit because of low loyalty, reward the town people now ---//
  281. if( townPtr->race_loyalty_array[raceId-1] < minRecruitLoyalty )
  282. {
  283. if( cash > 0 && townPtr->accumulated_reward_penalty==0 )
  284. {
  285. townPtr->reward(COMMAND_AI);
  286. }
  287. if( !townPtr->can_recruit(raceId) ) // if still cannot be recruited, return 0 now
  288. return 0;
  289. }
  290. return 0;
  291. }
  292. //------------------------------------------------------//
  293. // recruit
  294. //------------------------------------------------------//
  295. int unitRecno = townPtr->recruit(-1, raceId, COMMAND_AI);
  296. if( !unitRecno )
  297. return 0;
  298. //---------------------------------------------------------------------------//
  299. // since it is not an important action, no need to add processing action
  300. //---------------------------------------------------------------------------//
  301. Unit* unitPtr = unit_array[unitRecno];
  302. unitPtr->assign(actionNode->action_x_loc, actionNode->action_y_loc); // assign to the town
  303. unitPtr->ai_action_id = actionNode->action_id;
  304. err_when( unitPtr->nation_recno==0 );
  305. return 1;
  306. }
  307. //----- End of function Nation::ai_settle_to_other_town -----//
  308. //--------- Begin of function Nation::ai_scout ----------//
  309. //
  310. // action_x_loc, action_y_loc - location of the destination town.
  311. // ref_x_loc, ref_y_loc - location of the origin town.
  312. //
  313. int Nation::ai_scout(ActionNode* actionNode)
  314. {
  315. if(!seek_path.total_node_avail)
  316. return 0;
  317. //------- check if both towns are ready first --------//
  318. if(!check_town_ready(actionNode->action_x_loc, actionNode->action_y_loc) ||
  319. !check_town_ready(actionNode->ref_x_loc, actionNode->ref_y_loc))
  320. {
  321. return -1;
  322. }
  323. //----------------------------------------------------//
  324. // stop if no jobless population
  325. //----------------------------------------------------//
  326. Location* locPtr = world.get_loc(actionNode->ref_x_loc, actionNode->ref_y_loc);
  327. err_when(!locPtr->is_town() || town_array.is_deleted(locPtr->town_recno()));
  328. Town* townPtr = town_array[locPtr->town_recno()]; // point to the old town
  329. int raceId = townPtr->pick_random_race(0, 1); // 0-don't pick has job unit, 1-pick spies
  330. if( !raceId )
  331. return -1;
  332. //---- if cannot recruit because the loyalty is too low ---//
  333. if( !townPtr->can_recruit(raceId) && townPtr->has_linked_own_camp )
  334. return 0;
  335. //------------------------------------------------------//
  336. // recruit
  337. //------------------------------------------------------//
  338. int unitRecno = townPtr->recruit(-1, raceId, COMMAND_AI);
  339. if( !unitRecno )
  340. return 0;
  341. //---------------------------------------------------------------------------//
  342. // since it is not an important action, no need to add processing action
  343. //---------------------------------------------------------------------------//
  344. Unit* unitPtr = unit_array[unitRecno];
  345. short selectedArray[1];
  346. selectedArray[0] = unitRecno;
  347. //-- must use unit_array.move_to() instead of unit.move_to() because the destination may be reachable, it can be in a different region --//
  348. unit_array.move_to( actionNode->action_x_loc, actionNode->action_y_loc, 0, selectedArray, 1, COMMAND_AI );
  349. unitPtr->ai_action_id = actionNode->action_id;
  350. err_when( unitPtr->nation_recno==0 );
  351. return 1;
  352. }
  353. //-------- End of function Nation::ai_scout ----------//