OTOWNIND.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  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 : OTOWNINDP.CPP
  21. //Description : Independent town thining
  22. #include <OWORLD.h>
  23. #include <OUNIT.h>
  24. #include <ONEWS.h>
  25. #include <OCONFIG.h>
  26. #include <ORACERES.h>
  27. #include <OGODRES.h>
  28. #include <OTECHRES.h>
  29. #include <OREGIONS.h>
  30. #include <OFIRM.h>
  31. #include <ONATION.h>
  32. #include <OINFO.h>
  33. #include <OTOWN.h>
  34. #include <OLOG.h>
  35. //------- Begin of function Town::think_independent_town --------//
  36. //
  37. // Independent town thinking.
  38. //
  39. void Town::think_independent_town()
  40. {
  41. if( rebel_recno ) // if this is a rebel town, its AI will be executed in Rebel::think_town_action()
  42. return;
  43. #if defined(DEBUG) && defined(ENABLE_LOG)
  44. String logStr;
  45. logStr = "begin Town::think_independent_town, town_recno=";
  46. logStr += town_recno;
  47. LOG_MSG(logStr);
  48. #endif
  49. //---- think about toggling town links ----//
  50. if( info.game_date%15 == town_recno%15 )
  51. {
  52. LOG_MSG(" Town::think_independent_set_link");
  53. think_independent_set_link();
  54. LOG_MSG(m.get_random_seed() );
  55. }
  56. //---- think about independent units join existing nations ----//
  57. if( info.game_date%60 == town_recno%60 )
  58. {
  59. LOG_MSG(" Town::think_independent_unit_join_nation");
  60. think_independent_unit_join_nation();
  61. LOG_MSG(m.get_random_seed() );
  62. }
  63. //----- think about form a new nation -----//
  64. if( info.game_date%365 == town_recno%365 )
  65. {
  66. LOG_MSG(" Town::think_independent_form_new_nation");
  67. think_independent_form_new_nation();
  68. LOG_MSG(m.get_random_seed() );
  69. }
  70. LOG_MSG("end Town::think_independent_town");
  71. LOG_MSG(m.get_random_seed());
  72. }
  73. //-------- End of function Town::think_independent_town ---------//
  74. //------- Begin of function Town::think_independent_set_link --------//
  75. //
  76. // Independent town thinking.
  77. //
  78. void Town::think_independent_set_link()
  79. {
  80. //---- think about working for foreign firms ------//
  81. int linkStatus;
  82. Firm* firmPtr;
  83. for(int i=0; i<linked_firm_count; i++)
  84. {
  85. firmPtr = firm_array[linked_firm_array[i]];
  86. if( firmPtr->firm_id == FIRM_CAMP ) // a town cannot change its status with a military camp
  87. continue;
  88. //---- think about the link status ----//
  89. linkStatus = 0;
  90. if( firmPtr->nation_recno == 0 ) // if the firm is also an independent firm
  91. linkStatus = 1;
  92. if( average_resistance(firmPtr->nation_recno) <= INDEPENDENT_LINK_RESISTANCE )
  93. linkStatus = 1;
  94. //---- set the link status -------//
  95. toggle_firm_link( i+1, linkStatus, COMMAND_AI );
  96. }
  97. ai_link_checked = 1;
  98. }
  99. //-------- End of function Town::think_independent_set_link ---------//
  100. //------ Begin of function Town::think_independent_form_new_nation ------//
  101. //
  102. // Independent town thinking.
  103. //
  104. int Town::think_independent_form_new_nation()
  105. {
  106. if( m.random(10) > 0 ) // 1/10 chance to set up a new nation.
  107. return 0;
  108. //-------- check if the town is big enough -------//
  109. if( population < 30 )
  110. return 0;
  111. //---- don't form if the world is already densely populated ----//
  112. if( nation_array.all_nation_population > 60 * MAX_NATION )
  113. return 0;
  114. //----------------------------------------------//
  115. if( !nation_array.can_form_new_ai_nation() )
  116. return 0;
  117. //----------------------------------------------//
  118. return form_new_nation();
  119. }
  120. //------ End of function Town::think_independent_form_new_nation ------//
  121. //--------- Begin of function Town::form_new_nation ---------//
  122. //
  123. // This independent town forms a new nation.
  124. //
  125. // Return: <int>
  126. //
  127. int Town::form_new_nation()
  128. {
  129. err_when( nation_recno );
  130. if( !nation_array.can_form_new_ai_nation() )
  131. return 0;
  132. //----- determine the race with most population -----//
  133. int maxPop=0, raceId=0;
  134. int i;
  135. for( i=0 ; i<MAX_RACE ; i++ )
  136. {
  137. if( race_pop_array[i] > maxPop )
  138. {
  139. maxPop = race_pop_array[i];
  140. raceId = i+1;
  141. }
  142. }
  143. err_when( !raceId );
  144. //---- create the king of the new nation ----//
  145. int unitId = race_res[raceId]->basic_unit_id;
  146. int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
  147. SpriteInfo* spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
  148. if( !world.locate_space( xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height ) )
  149. return 0;
  150. //--------- create a new nation ---------//
  151. int nationRecno = nation_array.new_nation( NATION_AI, raceId, nation_array.random_unused_color() );
  152. err_when( !nationRecno );
  153. //-------- create the king --------//
  154. int kingUnitRecno = unit_array.add_unit( unitId, nationRecno, RANK_KING, 100, xLoc, yLoc );
  155. Unit* kingUnit = unit_array[kingUnitRecno];
  156. kingUnit->skill.skill_id = SKILL_LEADING;
  157. kingUnit->skill.skill_level = 50+m.random(51);
  158. kingUnit->set_combat_level(70+m.random(31));
  159. nation_array[nationRecno]->set_king(kingUnitRecno, 1); // 1-this is the first king of the nation
  160. dec_pop(raceId, 0); // 0-the unit doesn't have a job
  161. //------ set the nation of the rebel town -----//
  162. err_when( rebel_recno ); // rebel has its own function in Rebel, this shouldn't be called
  163. set_nation(nationRecno); // set the town at last because set_nation() will delete the Town object
  164. //------ increase the loyalty of the town -----//
  165. for( i=0 ; i<MAX_RACE ; i++ )
  166. race_loyalty_array[i] = (float) 70 + m.random(20); // 70 to 90 initial loyalty
  167. //--------- add news ----------//
  168. news_array.new_nation(nationRecno);
  169. //--- random extra beginning advantages -----//
  170. int mobileCount;
  171. Nation* nationPtr = nation_array[nationRecno];
  172. switch( m.random(10) )
  173. {
  174. case 1: // knowledge of weapon in the beginning.
  175. tech_res[ m.random(tech_res.tech_count)+1 ]->set_nation_tech_level(nationRecno, 1);
  176. break;
  177. case 2: // random additional cash
  178. nationPtr->cash += m.random(5000);
  179. break;
  180. case 3: // random additional food
  181. nationPtr->food += m.random(5000);
  182. break;
  183. case 4: // random additional skilled units
  184. mobileCount = m.random(5)+1;
  185. for( i=0 ; i<mobileCount && recruitable_race_pop(raceId,0)>0 ; i++ ) // 0-don't recruit spies
  186. {
  187. int unitRecno = mobilize_town_people(raceId, 1, 0); // 1-dec pop, 0-don't mobilize spies
  188. if( unitRecno )
  189. {
  190. Unit* unitPtr = unit_array[unitRecno];
  191. //------- randomly set a skill -------//
  192. int skillId = m.random(MAX_TRAINABLE_SKILL)+1;
  193. int loopCount=0; // no spying skill
  194. while( skillId==SKILL_SPYING ) // no spy skill as skill_id can't be set as SKILL_SPY, for spies, spy_recno must be set instead
  195. {
  196. if( ++skillId > MAX_TRAINABLE_SKILL )
  197. skillId = 1;
  198. err_when( ++loopCount > 100 );
  199. }
  200. unitPtr->skill.skill_id = skillId;
  201. unitPtr->skill.skill_level = 50 + m.random(50);
  202. unitPtr->set_combat_level( 50 + m.random(50) );
  203. }
  204. else
  205. break;
  206. }
  207. break;
  208. }
  209. return nationRecno;
  210. }
  211. //----------- End of function Town::form_new_nation ---------//
  212. //---- Begin of function Town::think_independent_unit_join_nation ----//
  213. //
  214. // Think having independent units joining existing nations.
  215. //
  216. int Town::think_independent_unit_join_nation()
  217. {
  218. if( jobless_population==0 )
  219. return 0;
  220. independent_unit_join_nation_min_rating -= 2; // make it easier to join nation everytime it's called
  221. // -2 each time, adding of 30 after a unit has been recruited and calling it once every 2 months make it a normal rate of joining once a year per town
  222. //------ think about which nation to turn towards -----//
  223. int i, bestNationRecno=0, curRating, raceId, bestRaceId=0;
  224. int bestRating=independent_unit_join_nation_min_rating;
  225. Nation *nationPtr;
  226. // ###### patch begin Gilbert 16/3 ########//
  227. // #ifdef AMPLUS
  228. if( region_array[region_id]->region_stat_id == 0)
  229. return 0;
  230. // #endif
  231. // ###### patch end Gilbert 16/3 ########//
  232. RegionStat* regionStat = region_array.get_region_stat(region_id);
  233. for( i=nation_array.size() ; i>0 ; i-- )
  234. {
  235. if( nation_array.is_deleted(i) )
  236. continue;
  237. nationPtr = nation_array[i];
  238. if( !nationPtr->race_id )
  239. continue;
  240. if( nationPtr->cash <= 0 )
  241. continue;
  242. if( info.game_date < nationPtr->last_independent_unit_join_date + 90 ) // don't join too frequently, at most 3 months a unit
  243. continue;
  244. //--- only join the nation if the nation has town in the town's region ---//
  245. if( regionStat->town_nation_count_array[i-1] == 0 )
  246. continue;
  247. //----- calculate the rating of the nation -----//
  248. curRating = (int) nationPtr->reputation + nationPtr->overall_rating;
  249. if( recruitable_race_pop(nationPtr->race_id, 0) > 0 ) // 0-don't count spies
  250. {
  251. curRating += 30;
  252. raceId = nationPtr->race_id;
  253. }
  254. else
  255. raceId = 0;
  256. if( curRating > bestRating )
  257. {
  258. bestRating = curRating;
  259. bestNationRecno = i;
  260. bestRaceId = raceId;
  261. }
  262. }
  263. //--------------------------------------------//
  264. if( !bestNationRecno )
  265. return 0;
  266. if( !bestRaceId )
  267. bestRaceId = pick_random_race(0, 0); // 0-only pick jobless unit, 0-don't pick spy units
  268. if( !bestRaceId )
  269. return 0;
  270. if( !independent_unit_join_nation(bestRaceId, bestNationRecno) )
  271. return 0;
  272. //--- set a new value to independent_unit_join_nation_min_rating ---//
  273. independent_unit_join_nation_min_rating = bestRating + 100 + m.random(30); // reset it to a higher rating
  274. if( independent_unit_join_nation_min_rating < 100 )
  275. independent_unit_join_nation_min_rating = 100;
  276. return 1;
  277. }
  278. //----- End of function Town::think_independent_unit_join_nation -----//
  279. //---- Begin of function Town::independent_unit_join_nation ----//
  280. //
  281. // <int> raceId - race id. of the unit
  282. // <int> toNationRecno - recno of the nation the unit should turn toward
  283. //
  284. int Town::independent_unit_join_nation(int raceId, int toNationRecno)
  285. {
  286. //----- mobilize a villager ----//
  287. int unitRecno = mobilize_town_people(raceId, 1, 0); // 1-dec population after mobilizing the unit, 0-don't mobilize spies
  288. if( !unitRecno )
  289. return 0;
  290. Unit* unitPtr = unit_array[unitRecno];
  291. //----- set the skills of the unit -----//
  292. int skillId, skillLevel, combatLevel;
  293. switch( m.random(3) )
  294. {
  295. case 0: // leaders
  296. skillId = SKILL_LEADING;
  297. if( m.random(3)==0 )
  298. skillLevel = m.random(100);
  299. else
  300. skillLevel = m.random(50);
  301. combatLevel = skillLevel + m.random(40) - 20;
  302. combatLevel = min(combatLevel, 100);
  303. combatLevel = max(combatLevel, 10);
  304. break;
  305. case 1: // peasants
  306. skillId = 0;
  307. skillLevel = 0;
  308. combatLevel = 10 + m.random(10);
  309. break;
  310. case 2: // skilled units
  311. skillId = m.random(MAX_TRAINABLE_SKILL)+1;
  312. {
  313. int loopCount=0; // no spying skill
  314. while( skillId==SKILL_SPYING )
  315. {
  316. if( ++skillId > MAX_TRAINABLE_SKILL )
  317. skillId = 1;
  318. err_when( ++loopCount > 100 );
  319. }
  320. }
  321. skillLevel = 10+m.random(80);
  322. combatLevel = 10+m.random(30);
  323. break;
  324. }
  325. //--------------------------------------//
  326. unitPtr->skill.skill_id = skillId;
  327. unitPtr->skill.skill_level = skillLevel;
  328. unitPtr->set_combat_level( combatLevel );
  329. //------ change nation now --------//
  330. if( !unitPtr->betray(toNationRecno) )
  331. return 0;
  332. //---- the unit moves close to the newly joined nation ----//
  333. unitPtr->ai_move_to_nearby_town();
  334. //-------- set last_independent_unit_join_date --------//
  335. nation_array[toNationRecno]->last_independent_unit_join_date = info.game_date;
  336. return 1;
  337. }
  338. //----- End of function Town::independent_unit_join_nation -----//