OFIRMAI.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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 : OFIRMAI.CPP
  21. //Description : AI functions for the class Firm
  22. #include <OF_INN.h>
  23. #include <OF_MINE.h>
  24. #include <OF_FACT.h>
  25. #include <OF_CAMP.h>
  26. #include <OF_MARK.h>
  27. #include <OUNITRES.h>
  28. #include <OTALKRES.h>
  29. #include <ONATION.h>
  30. //--------- Begin of function Firm::process_common_ai --------//
  31. //
  32. // AI processing functions common for all firm types.
  33. //
  34. void Firm::process_common_ai()
  35. {
  36. if( info.game_date%30==firm_recno%30 )
  37. think_repair();
  38. //------ think about closing this firm ------//
  39. if( !should_close_flag )
  40. {
  41. if( ai_should_close() )
  42. {
  43. should_close_flag = 1;
  44. nation_array[nation_recno]->firm_should_close_array[firm_id-1]++;
  45. }
  46. }
  47. }
  48. //--------- End of function Firm::process_common_ai --------//
  49. //------- Begin of function Firm::think_repair -----------//
  50. //
  51. void Firm::think_repair()
  52. {
  53. Nation* ownNation = nation_array[nation_recno];
  54. //----- check if the damage is serious enough -----//
  55. if( hit_points >=
  56. max_hit_points * (70+ownNation->pref_repair_concern/4) / 100 ) // 70% to 95%
  57. {
  58. return;
  59. }
  60. //--- if it's no too heavily damaged, it is just that the AI has a high concern on this ---//
  61. if( hit_points >= max_hit_points * 80 / 100 )
  62. {
  63. if( ownNation->total_jobless_population < 15 )
  64. return;
  65. }
  66. //------- queue assigning a construction worker now ------//
  67. ownNation->add_action(loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_CONSTRUCTION_WORKER, firm_id);
  68. }
  69. //--------- End of function Firm::think_repair -----------//
  70. //------- Begin of function Firm::ai_del_firm -----------//
  71. //
  72. // Delete the firm no matter what status this firm is in.
  73. //
  74. void Firm::ai_del_firm()
  75. {
  76. if( under_construction )
  77. {
  78. cancel_construction(COMMAND_PLAYER);
  79. }
  80. else
  81. {
  82. if( can_sell() )
  83. sell_firm(COMMAND_AI);
  84. else
  85. destruct_firm(COMMAND_AI);
  86. }
  87. }
  88. //--------- End of function Firm::ai_del_firm -----------//
  89. //------- Begin of function Firm::ai_should_close -----------//
  90. //
  91. // This is function is for derived class to overload.
  92. //
  93. int Firm::ai_should_close()
  94. {
  95. return 0;
  96. }
  97. //--------- End of function Firm::ai_should_close -----------//
  98. //------- Begin of function Firm::think_hire_inn_unit -------//
  99. //
  100. int Firm::think_hire_inn_unit()
  101. {
  102. if( !nation_array[nation_recno]->ai_should_hire_unit(30) ) // 30 - importance rating
  103. return 0;
  104. //---- one firm only hire one foreign race worker ----//
  105. int i, foreignRaceCount=0;
  106. int majorityRace = majority_race();
  107. if( majorityRace )
  108. {
  109. for( i=0 ; i<worker_count ; i++ )
  110. {
  111. if( worker_array[i].race_id != majorityRace )
  112. foreignRaceCount++;
  113. }
  114. }
  115. //-------- try to get skilled workers from inns --------//
  116. Nation* nationPtr = nation_array[nation_recno];
  117. FirmInn* firmInn, *bestInn=NULL;
  118. int curRating, bestRating=0, bestInnUnitId=0;
  119. int prefTownHarmony = nationPtr->pref_town_harmony;
  120. for( i=0 ; i<nationPtr->ai_inn_count ; i++ )
  121. {
  122. firmInn = (FirmInn*) firm_array[ nationPtr->ai_inn_array[i] ];
  123. if( firmInn->region_id != region_id )
  124. continue;
  125. InnUnit* innUnit = firmInn->inn_unit_array;
  126. for( int j=0 ; j<firmInn->inn_unit_count ; j++, innUnit++ )
  127. {
  128. if( innUnit->skill.skill_id != firm_skill_id )
  129. continue;
  130. //-------------------------------------------//
  131. // Rating of a unit to be hired is based on:
  132. //
  133. // -distance between the inn and this firm.
  134. // -whether the unit is racially homogenous to the majority of the firm workers
  135. //
  136. //-------------------------------------------//
  137. curRating = world.distance_rating( center_x, center_y,
  138. firmInn->center_x, firmInn->center_y );
  139. curRating += innUnit->skill.skill_level;
  140. if( majorityRace == unit_res[innUnit->unit_id]->race_id )
  141. {
  142. curRating += prefTownHarmony;
  143. }
  144. else
  145. {
  146. //----------------------------------------------------//
  147. // Don't pick this unit if it isn't racially homogenous
  148. // to the villagers, and its pref_town_harmony is higher
  149. // than its skill level. (This means if its skill level
  150. // is low, its chance of being selected is lower.
  151. //----------------------------------------------------//
  152. if( majorityRace )
  153. {
  154. if( foreignRaceCount>0 || prefTownHarmony > innUnit->skill.skill_level-50 )
  155. continue;
  156. }
  157. }
  158. if( curRating > bestRating )
  159. {
  160. bestRating = curRating;
  161. bestInn = firmInn;
  162. bestInnUnitId = j+1;
  163. }
  164. }
  165. }
  166. //-----------------------------------------//
  167. if( bestInn )
  168. {
  169. int unitRecno = bestInn->hire(bestInnUnitId);
  170. if( unitRecno )
  171. {
  172. unit_array[unitRecno]->assign(loc_x1, loc_y1);
  173. return 1;
  174. }
  175. }
  176. return 0;
  177. }
  178. //--------- End of function Firm::think_hire_inn_unit -------//
  179. //------- Begin of function Firm::being_attacked -----------//
  180. //
  181. void Firm::being_attacked(int attackerUnitRecno)
  182. {
  183. last_attacked_date = info.game_date;
  184. if( nation_recno && firm_ai )
  185. {
  186. if( unit_array[attackerUnitRecno]->nation_recno == nation_recno ) // this can happen when the unit has just changed nation
  187. return;
  188. nation_array[nation_recno]->ai_defend(attackerUnitRecno);
  189. }
  190. }
  191. //--------- End of function Firm::being_attacked -----------//
  192. //------- Begin of function Firm::ai_recruit_worker -----------//
  193. //
  194. int Firm::ai_recruit_worker()
  195. {
  196. if( worker_count == MAX_WORKER )
  197. return 0;
  198. Nation* nationPtr = nation_array[nation_recno];
  199. Town* townPtr;
  200. for( int i=0; i<linked_town_count ; i++ )
  201. {
  202. if( linked_town_enable_array[i] != LINK_EE )
  203. continue;
  204. townPtr = town_array[ linked_town_array[i] ];
  205. //-- only recruit workers from towns of other nations if we don't have labor ourselves
  206. if( townPtr->nation_recno != nation_recno &&
  207. nationPtr->total_jobless_population > MAX_WORKER )
  208. {
  209. continue;
  210. }
  211. if( townPtr->jobless_population > 0 )
  212. return 0; // don't order units to move into it as they will be recruited from the town automatically
  213. }
  214. //---- order workers to move into the firm ----//
  215. nationPtr->add_action(loc_x1, loc_y1, -1, -1, ACTION_AI_ASSIGN_WORKER, firm_id, MAX_WORKER-worker_count);
  216. return 1;
  217. }
  218. //--------- End of function Firm::ai_recruit_worker -----------//
  219. //------- Begin of function Firm::ai_build_neighbor_firm -----------//
  220. //
  221. int Firm::ai_build_neighbor_firm(int firmId)
  222. {
  223. short buildXLoc, buildYLoc;
  224. Nation* nationPtr = nation_array[nation_recno];
  225. if( !nationPtr->find_best_firm_loc(firmId, loc_x1, loc_y1, buildXLoc, buildYLoc) )
  226. {
  227. no_neighbor_space = 1;
  228. return 0;
  229. }
  230. nationPtr->add_action(buildXLoc, buildYLoc, loc_x1, loc_y1, ACTION_AI_BUILD_FIRM, firmId);
  231. return 1;
  232. }
  233. //--------- End of function Firm::ai_build_neighbor_firm -----------//
  234. //--------- Begin of function Firm::ai_update_link_status ---------//
  235. //
  236. // Updating link status of this firm with towns.
  237. //
  238. void Firm::ai_update_link_status()
  239. {
  240. err_when( firm_id == FIRM_CAMP ); // FirmCamp has its own ai_update_link_status(), this version shouldn't be called.
  241. if( !worker_array ) // if this firm does not need any workers.
  242. return;
  243. if( is_worker_full() ) // if this firm already has all the workers it needs.
  244. return;
  245. //------------------------------------------------//
  246. Nation* ownNation = nation_array[nation_recno];
  247. int i, rc;
  248. for( i=0 ; i<linked_town_count ; i++ )
  249. {
  250. Town* townPtr = town_array[linked_town_array[i]];
  251. //--- enable link to hire people from the town ---//
  252. rc = townPtr->nation_recno==0 || // either it's an independent town or it's friendly or allied to our nation
  253. ownNation->get_relation_status(townPtr->nation_recno) >= NATION_FRIENDLY;
  254. toggle_town_link( i+1, rc, COMMAND_AI );
  255. }
  256. }
  257. //----------- End of function Firm::ai_update_link_status ----------//
  258. //------- Begin of function Firm::think_build_factory -----------//
  259. //
  260. int Firm::think_build_factory(int rawId)
  261. {
  262. if( no_neighbor_space ) // if there is no space in the neighbor area for building a new firm.
  263. return 0;
  264. Nation* nationPtr = nation_array[nation_recno];
  265. //--- check whether the AI can build a new firm next this firm ---//
  266. if( !nationPtr->can_ai_build(FIRM_FACTORY) )
  267. return 0;
  268. //---------------------------------------------------//
  269. int factoryCount=0;
  270. FirmFactory* firmPtr;
  271. Firm* firmMarket;
  272. for(int i=0; i<linked_firm_count; i++)
  273. {
  274. err_when(!linked_firm_array[i] || firm_array.is_deleted(linked_firm_array[i]));
  275. firmPtr = (FirmFactory*) firm_array[linked_firm_array[i]];
  276. if(firmPtr->firm_id!=FIRM_FACTORY)
  277. continue;
  278. if( firmPtr->nation_recno != nation_recno )
  279. continue;
  280. if( firmPtr->product_raw_id != rawId )
  281. continue;
  282. //--- if one of own factories still has not recruited enough workers ---//
  283. if( firmPtr->worker_count < MAX_WORKER )
  284. return 0;
  285. //---------------------------------------------------//
  286. //
  287. // If this factory has a medium to high level of stock,
  288. // this means the bottleneck is not at the factories,
  289. // building more factories won't solve the problem.
  290. //
  291. //---------------------------------------------------//
  292. if( firmPtr->stock_qty > firmPtr->max_stock_qty * 0.1 )
  293. return 0;
  294. //---------------------------------------------------//
  295. //
  296. // Check if this factory is just outputing goods to
  297. // a market and it is actually not overcapacity.
  298. //
  299. //---------------------------------------------------//
  300. for( int j=firmPtr->linked_firm_count-1 ; j>=0 ; j-- )
  301. {
  302. if( firmPtr->linked_firm_enable_array[j] != LINK_EE )
  303. continue;
  304. firmMarket = firm_array[ firmPtr->linked_firm_array[j] ];
  305. if( firmMarket->firm_id != FIRM_MARKET )
  306. continue;
  307. //--- if this factory is producing enough goods to the market place, then it means it is still quite efficient
  308. MarketGoods *marketGoods = ((FirmMarket*)firmMarket)->market_product_array[rawId-1];
  309. if( marketGoods && marketGoods->stock_qty > 100 )
  310. return 0;
  311. }
  312. //----------------------------------------------//
  313. factoryCount++;
  314. }
  315. //---- don't build additional factory if we don't have enough peasants ---//
  316. if( factoryCount>=1 && !nationPtr->ai_has_enough_food() )
  317. return 0;
  318. //-- if there isn't much raw reserve left, don't build new factories --//
  319. if( firm_id == FIRM_MINE )
  320. {
  321. if( ((FirmMine*)this)->reserve_qty < 1000 && factoryCount>=1 )
  322. return 0;
  323. }
  324. //--- only build additional factories if we have a surplus of labor ---//
  325. if( nationPtr->total_jobless_population < factoryCount * MAX_WORKER )
  326. return 0;
  327. //--- only when we have checked it three times and all say it needs a factory, we then build a factory ---//
  328. if( ++ai_should_build_factory_count >= 3 )
  329. {
  330. short buildXLoc, buildYLoc;
  331. if( !nationPtr->find_best_firm_loc(FIRM_FACTORY, loc_x1, loc_y1, buildXLoc, buildYLoc) )
  332. {
  333. no_neighbor_space = 1;
  334. return 0;
  335. }
  336. nationPtr->add_action(buildXLoc, buildYLoc, loc_x1, loc_y1, ACTION_AI_BUILD_FIRM, FIRM_FACTORY);
  337. ai_should_build_factory_count = 0;
  338. }
  339. return 1;
  340. }
  341. //--------- End of function Firm::think_build_factory -----------//
  342. //------- Begin of function Firm::think_capture -----------//
  343. //
  344. int Firm::think_capture()
  345. {
  346. Nation* nationPtr;
  347. int i;
  348. for( i=nation_array.size() ; i>0 ; i-- )
  349. {
  350. if( nation_array.is_deleted(i) )
  351. continue;
  352. nationPtr = nation_array[i];
  353. if( nationPtr->is_ai() && can_worker_capture(i) )
  354. break;
  355. }
  356. if( i==0 )
  357. return 0;
  358. //------- capture the firm --------//
  359. capture_firm(i);
  360. //------ order troops to attack nearby enemy camps -----//
  361. Firm *firmPtr, *bestTarget=NULL;
  362. int curDistance, minDistance=0x1000;
  363. for( i=firm_array.size() ; i>0 ; i-- )
  364. {
  365. if( firm_array.is_deleted(i) )
  366. continue;
  367. firmPtr = firm_array[i];
  368. //----- only attack enemy camps -----//
  369. if( firmPtr->nation_recno != nation_recno ||
  370. firmPtr->firm_id != FIRM_CAMP )
  371. {
  372. continue;
  373. }
  374. curDistance = m.points_distance(center_x, center_y,
  375. firmPtr->center_x, firmPtr->center_y );
  376. //--- only attack camps within 15 location distance to this firm ---//
  377. if( curDistance < 15 && curDistance < minDistance )
  378. {
  379. minDistance = curDistance;
  380. bestTarget = firmPtr;
  381. }
  382. }
  383. if( bestTarget )
  384. {
  385. int useAllCamp = nationPtr->pref_military_courage > 60 || m.random(3)==0;
  386. nationPtr->ai_attack_target( bestTarget->loc_x1, bestTarget->loc_y1,
  387. ((FirmCamp*)bestTarget)->total_combat_level(), 0, 0, 0, 0, useAllCamp );
  388. }
  389. return 1;
  390. }
  391. //--------- End of function Firm::think_capture -----------//
  392. //------- Begin of function Firm::think_linked_town_change_nation ------//
  393. //
  394. // This function is called by Town::set_nation() when a town linked
  395. // to this firm has changed nation.
  396. //
  397. // <int> linkedTownRecno - the recno of the town that has changed nation.
  398. // <int> oldNationRecno - the old nation recno of the town
  399. // <int> newNationRecno - the new nation recno of the town
  400. //
  401. void Firm::think_linked_town_change_nation(int linkedTownRecno, int oldNationRecno, int newNationRecno)
  402. {
  403. }
  404. //-------- End of function Firm::think_linked_town_change_nation ------//
  405. //--------- Begin of function Firm::ai_firm_captured --------//
  406. //
  407. // This is function is called when the AI's firm is just
  408. // about to be captured.
  409. //
  410. void Firm::ai_firm_captured(int capturerNationRecno)
  411. {
  412. Nation* ownNation = nation_array[nation_recno];
  413. if( !ownNation->is_ai() ) //**BUGHERE
  414. return;
  415. if( ownNation->get_relation(capturerNationRecno)->status >= NATION_FRIENDLY )
  416. ownNation->ai_end_treaty(capturerNationRecno);
  417. talk_res.ai_send_talk_msg(capturerNationRecno, nation_recno, TALK_DECLARE_WAR);
  418. }
  419. //--------- End of function Firm::ai_firm_captured --------//