OUNITI.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  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 : OUNITI.CPP
  21. //Description : Object Unit idle processing
  22. //Owner : Alex
  23. #include <ALL.h>
  24. #include <OWORLD.h>
  25. #include <OU_MARI.h>
  26. #include <ONATION.h>
  27. #include <OF_MONS.h>
  28. #include <OTOWN.h>
  29. #include <OSPY.h>
  30. #include <OREBEL.h>
  31. #include <OSYS.h>
  32. #include <OU_GOD.h>
  33. #ifdef NO_DEBUG_UNIT
  34. #undef err_when
  35. #undef err_here
  36. #undef err_if
  37. #undef err_else
  38. #undef err_now
  39. #define err_when(cond)
  40. #define err_here()
  41. #define err_if(cond)
  42. #define err_else
  43. #define err_now(msg)
  44. #undef DEBUG
  45. #endif
  46. //-------------- define static variables -----------//
  47. static char idle_detect_has_unit;
  48. static char idle_detect_has_firm;
  49. static char idle_detect_has_town;
  50. static char idle_detect_has_wall;
  51. static short idle_detect_target_unit_recno;
  52. static short idle_detect_target_firm_recno;
  53. static short idle_detect_target_town_recno;
  54. static short idle_detect_target_wall_x1;
  55. static short idle_detect_target_wall_y1;
  56. static int idle_detect_default_mode;
  57. static int help_mode;
  58. static short help_attack_target_recno;
  59. //--------- Begin of function Unit::process_idle ---------//
  60. // process actions for idle units
  61. //
  62. void Unit::process_idle()
  63. {
  64. err_when(result_path_dist || result_node_array);
  65. //---- if the unit is defending the town ----//
  66. switch( unit_mode )
  67. {
  68. case UNIT_MODE_REBEL:
  69. if(action_mode2==ACTION_STOP)
  70. {
  71. process_rebel(); // redirect to process_rebel for rebel units
  72. return;
  73. }
  74. break;
  75. case UNIT_MODE_MONSTER:
  76. if(action_mode2==ACTION_STOP)
  77. {
  78. if(unit_mode_para)
  79. {
  80. if(!firm_array.is_deleted(unit_mode_para))
  81. {
  82. //-------- return to monster firm -----------//
  83. FirmMonster *monsterFirmPtr = (FirmMonster*) firm_array[unit_mode_para];
  84. assign(monsterFirmPtr->loc_x1, monsterFirmPtr->loc_y1);
  85. return;
  86. }
  87. else
  88. unit_mode_para = 0;
  89. }
  90. }
  91. break;
  92. }
  93. //------------- process way point ------------//
  94. if(action_mode==ACTION_STOP && action_mode2==ACTION_STOP && way_point_count)
  95. {
  96. err_when(way_point_count < 0);
  97. if(way_point_count==1)
  98. reset_way_point_array();
  99. else
  100. process_way_point();
  101. return;
  102. }
  103. //-------- randomize direction --------//
  104. err_when(result_node_array!=NULL);
  105. //-------------------------------------------------------//
  106. // when the unit is idle, the following should be always true
  107. // move_to_x_loc == next_x_loc()
  108. // move_to_y_loc == next_y_loc()
  109. //-------------------------------------------------------//
  110. err_when(move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc());
  111. //move_to_x_loc = next_x_loc(); //***************BUGHERE
  112. //move_to_y_loc = next_y_loc();
  113. err_when(next_x!=cur_x || next_y!=cur_y);
  114. if(match_dir())
  115. {
  116. if(!is_guarding() && race_id ) // only these units can move
  117. {
  118. if(!m.random(150)) // change direction randomly
  119. set_dir(m.random(8));
  120. }
  121. }
  122. else
  123. return;
  124. err_when(turn_delay);
  125. //------- call Sprite::process_idle() -------//
  126. Sprite::process_idle();
  127. //-*********************** simulate ship movment ***************************-//
  128. /*if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
  129. {
  130. unit_group_id = 1;
  131. if(cur_action==SPRITE_IDLE)
  132. {
  133. if(m.random(50))
  134. return;
  135. }
  136. else if(cur_action!=SPRITE_READY_TO_MOVE)
  137. {
  138. if(m.random(30)==0)
  139. return;
  140. }
  141. int xOffset = m.random(30)*(m.random(2) ? 1 : -1);
  142. int yOffset = m.random(30)*(m.random(2) ? 1 : -1);
  143. int curXLoc = next_x_loc();
  144. int curYLoc = next_y_loc();
  145. int destXLoc = curXLoc+xOffset;
  146. int destYLoc = curYLoc+yOffset;
  147. if(destXLoc<0) destXLoc = 0;
  148. else if(destXLoc>=MAX_WORLD_X_LOC) destXLoc = MAX_WORLD_X_LOC-1;
  149. if(destYLoc<0) destYLoc = 0;
  150. else if(destYLoc>=MAX_WORLD_Y_LOC) destYLoc = MAX_WORLD_Y_LOC-1;
  151. Location *locPtr = world.get_loc(destXLoc, destYLoc);
  152. int tempX, tempY;
  153. if(terrain_res[locPtr->terrain_id]->average_type==TERRAIN_OCEAN)
  154. move_to(destXLoc, destYLoc);
  155. else
  156. ship_to_beach(destXLoc, destYLoc, tempX, tempY);
  157. Nation *nationPtr = nation_array[nation_recno];
  158. if(nationPtr->cash<5000)
  159. nationPtr->cash += 10000;
  160. if(nationPtr->food<5000)
  161. nationPtr->food += 10000;
  162. if(hit_points<max_hit_points)
  163. hit_points = max_hit_points;
  164. return;
  165. }
  166. */
  167. //-*********************** simulate ship movment ***************************-//
  168. //---------------------------------------------------------------------------//
  169. // reset idle blocked attacking unit. If the previous condition is totally
  170. // blocked for attacking target, try again now
  171. // Note: reset blocked_edge is essentail for idle unit to reactivate attack
  172. // action
  173. //---------------------------------------------------------------------------//
  174. if(action_mode>=ACTION_ATTACK_UNIT && action_mode<=ACTION_ATTACK_WALL)
  175. {
  176. if(unit_array.idle_blocked_unit_reset_count && *(long*)blocked_edge)
  177. {
  178. unit_array.idle_blocked_unit_reset_count = 0;
  179. memset(blocked_edge, 0, sizeof(char)*4);
  180. err_when(blocked_edge[0] || blocked_edge[1] || blocked_edge[2] || blocked_edge[3]);
  181. }
  182. }
  183. err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
  184. err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
  185. //--------- reactivate action -----------//
  186. if(reactivate_idle_action())
  187. {
  188. err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
  189. err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
  190. return; // true if an action is reactivated
  191. }
  192. //-**************** simulate aat ********************-//
  193. #ifdef DEBUG
  194. if(debug_sim_game_type==2)
  195. {
  196. //int curXLoc = next_x_loc();
  197. //int curYLoc = next_y_loc();
  198. //int destXLoc, destYLoc;
  199. if(m.random(30))
  200. move_to(m.random(MAX_WORLD_X_LOC), m.random(MAX_WORLD_Y_LOC));
  201. Nation *nationPtr = nation_array[nation_recno];
  202. if(nationPtr->cash<2000)
  203. nationPtr->cash += 8000;
  204. if(nationPtr->food<2000)
  205. nationPtr->food += 8000;
  206. return;
  207. }
  208. #endif
  209. //-**************** simulate aat ********************-//
  210. err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
  211. err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
  212. //----------- for ai unit idle -----------//
  213. if( action_mode != ACTION_STOP || action_mode2 != ACTION_STOP ) // only detect attack when the unit is really idle
  214. return;
  215. if( !can_attack() )
  216. return; // cannot attack
  217. err_when(!can_attack());
  218. err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
  219. err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
  220. //--- only detect attack if in aggressive mode or the unit is a monster ---//
  221. UnitInfo* unitInfo = unit_res[unit_id];
  222. if( unitInfo->unit_class == UNIT_CLASS_MONSTER || aggressive_mode )
  223. {
  224. //----------- detect target to attack -----------//
  225. if( idle_detect_attack() )
  226. {
  227. err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
  228. err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
  229. return; // target detected
  230. }
  231. err_when(action_mode==ACTION_STOP && cur_action==SPRITE_ATTACK);
  232. err_when(action_mode==ACTION_ATTACK_UNIT && action_para==0);
  233. }
  234. //------------------------------------------------------------------//
  235. // wander around for monster
  236. //------------------------------------------------------------------//
  237. if( unitInfo->unit_class == UNIT_CLASS_MONSTER )
  238. {
  239. if(m.random(500)==0)
  240. {
  241. #define WANDER_DIST 20
  242. int xOffset = m.random(WANDER_DIST)-WANDER_DIST/2;
  243. int yOffset = m.random(WANDER_DIST)-WANDER_DIST/2;
  244. int destX = next_x_loc()+xOffset;
  245. int destY = next_y_loc()+yOffset;
  246. if(destX<0) destX = 0;
  247. else if(destX>=MAX_WORLD_X_LOC) destX = MAX_WORLD_X_LOC-1;
  248. if(destY<0) destY = 0;
  249. else if(destY>=MAX_WORLD_Y_LOC) destY = MAX_WORLD_Y_LOC-1;
  250. move_to(destX, destY);
  251. }
  252. }
  253. }
  254. //----------- End of function Unit::process_idle -----------//
  255. //--------- Begin of function Unit::reactivate_idle_action --------//
  256. // resume actions for idle units
  257. //
  258. // return 1 if an action is reactivated
  259. // return 0 otherwise
  260. //
  261. int Unit::reactivate_idle_action()
  262. {
  263. if(action_mode2==ACTION_STOP)
  264. return 0; // return for no idle action
  265. if(!is_dir_correct())
  266. return 1; // cheating for turning the direction
  267. //------------------- declare parameters ----------------------//
  268. Location *locPtr;
  269. Firm *firmPtr;
  270. FirmInfo *firmInfo;
  271. Unit *unitPtr;
  272. UnitMarine *shipPtr;
  273. SpriteInfo *spriteInfo;
  274. int canMove = 1;
  275. int returnFlag = 0;
  276. int curXLoc = move_to_x_loc;
  277. int curYLoc = move_to_y_loc;
  278. int dummyX, dummyY;
  279. int hasSearch = 0;
  280. int validSearch = seek_path.is_valid_searching();
  281. seek_path.set_status(PATH_WAIT);
  282. err_when(seek_path.path_status==PATH_NODE_USED_UP);
  283. switch(action_mode2)
  284. {
  285. case ACTION_STOP:
  286. case ACTION_DIE:
  287. return 0; // do nothing
  288. case ACTION_ATTACK_UNIT:
  289. if(unit_array.is_deleted(action_para2))
  290. stop2();
  291. else
  292. {
  293. unitPtr = unit_array[action_para2];
  294. spriteInfo = unitPtr->sprite_info;
  295. if(space_for_attack(action_x_loc2, action_y_loc2, unitPtr->mobile_type, spriteInfo->loc_width, spriteInfo->loc_height))
  296. {
  297. //------ there should be place for this unit to attack the target, attempts to attack it ------//
  298. attack_unit(action_para2, 0, 0, 0); // last 0 for not reset blocked_edge
  299. hasSearch++;
  300. returnFlag = 1;
  301. break;
  302. }
  303. }
  304. break;
  305. case ACTION_ATTACK_FIRM:
  306. locPtr = world.get_loc(action_x_loc2, action_y_loc2);
  307. if(!locPtr->is_firm())
  308. stop2(); // stop since target is already destroyed
  309. else
  310. {
  311. firmPtr = firm_array[action_para2];
  312. firmInfo = firm_res[firmPtr->firm_id];
  313. if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, firmInfo->loc_width, firmInfo->loc_height))
  314. {
  315. //-------- attack target since space is found for this unit to move to ---------//
  316. attack_firm(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
  317. hasSearch++;
  318. returnFlag = 1;
  319. break;
  320. }
  321. }
  322. break;
  323. case ACTION_ATTACK_TOWN:
  324. locPtr = world.get_loc(action_x_loc2, action_y_loc2);
  325. if(!locPtr->is_town())
  326. stop2(); // stop since target is deleted
  327. else if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
  328. {
  329. //---------- attack target --------//
  330. attack_town(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
  331. hasSearch++;
  332. returnFlag = 1;
  333. break;
  334. }
  335. break;
  336. case ACTION_ATTACK_WALL:
  337. locPtr = world.get_loc(action_x_loc2, action_y_loc2);
  338. if(!locPtr->is_wall())
  339. stop2(); // stop since target doesn't exist
  340. else if(space_for_attack(action_x_loc2, action_y_loc2, UNIT_LAND, 1, 1))
  341. {
  342. //----------- attack target -----------//
  343. attack_wall(action_x_loc2, action_y_loc2, 0, 0, 0); // last 0 for not reset blocked_edge
  344. hasSearch++;
  345. returnFlag = 1;
  346. break;
  347. }
  348. break;
  349. case ACTION_ASSIGN_TO_FIRM:
  350. case ACTION_ASSIGN_TO_TOWN:
  351. case ACTION_ASSIGN_TO_VEHICLE:
  352. //---------- resume assign actions -------------//
  353. err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
  354. assign(action_x_loc2, action_y_loc2);
  355. hasSearch++;
  356. waiting_term = 0;
  357. returnFlag = 1;
  358. break;
  359. case ACTION_ASSIGN_TO_SHIP:
  360. //------------ try to assign to marine ------------//
  361. err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
  362. assign_to_ship(action_x_loc2, action_y_loc2, action_para2);
  363. hasSearch++;
  364. waiting_term = 0;
  365. returnFlag = 1;
  366. break;
  367. case ACTION_BUILD_FIRM:
  368. //-------------- build again ----------------//
  369. err_when(action_x_loc2==-1 || action_y_loc2==-1 || !action_para2);
  370. build_firm(action_x_loc2, action_y_loc2, action_para2, COMMAND_AUTO);
  371. hasSearch++;
  372. waiting_term = 0;
  373. returnFlag = 1;
  374. break;
  375. case ACTION_SETTLE:
  376. //------------- try again to settle -----------//
  377. err_when(action_x_loc2==-1 || action_y_loc2==-1 || action_para2);
  378. settle(action_x_loc2, action_y_loc2);
  379. hasSearch++;
  380. waiting_term = 0;
  381. returnFlag = 1;
  382. break;
  383. case ACTION_BURN:
  384. //---------------- resume burn action -----------------//
  385. err_when(action_x_loc2==-1 || action_y_loc2==-1 || action_para2);
  386. burn(action_x_loc2, action_y_loc2, COMMAND_AUTO);
  387. hasSearch++;
  388. waiting_term = 0;
  389. returnFlag = 1;
  390. break;
  391. case ACTION_MOVE:
  392. //if(!avail_node_enough_for_search())
  393. //{
  394. // returnFlag = 1;
  395. // break;
  396. //}
  397. if(move_to_x_loc!=action_x_loc2 || move_to_y_loc!=action_y_loc2)
  398. {
  399. //------- move since the unit has not reached its destination --------//
  400. move_to(action_x_loc2, action_y_loc2, 1);
  401. hasSearch++;
  402. returnFlag = 1;
  403. break;
  404. }
  405. waiting_term = 0;
  406. break;
  407. case ACTION_AUTO_DEFENSE_ATTACK_TARGET:
  408. if(unit_search_node_used<500) // limit the no. of nods to reactivate idle process
  409. {
  410. //---------- resume action -----------//
  411. process_auto_defense_attack_target();
  412. hasSearch++;
  413. }
  414. returnFlag = 1;
  415. break;
  416. case ACTION_AUTO_DEFENSE_DETECT_TARGET:
  417. process_auto_defense_detect_target();
  418. returnFlag = 1;
  419. break;
  420. case ACTION_AUTO_DEFENSE_BACK_CAMP:
  421. process_auto_defense_back_camp();
  422. hasSearch++;
  423. returnFlag = 1;
  424. break;
  425. case ACTION_DEFEND_TOWN_ATTACK_TARGET:
  426. process_defend_town_attack_target();
  427. hasSearch++;
  428. returnFlag = 1;
  429. break;
  430. case ACTION_DEFEND_TOWN_DETECT_TARGET:
  431. process_defend_town_detect_target();
  432. returnFlag = 1;
  433. break;
  434. case ACTION_DEFEND_TOWN_BACK_TOWN:
  435. process_defend_town_back_town();
  436. hasSearch++;
  437. returnFlag = 1;
  438. break;
  439. case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
  440. process_monster_defend_attack_target();
  441. hasSearch++;
  442. returnFlag = 1;
  443. break;
  444. case ACTION_MONSTER_DEFEND_DETECT_TARGET:
  445. process_monster_defend_detect_target();
  446. returnFlag = 1;
  447. break;
  448. case ACTION_MONSTER_DEFEND_BACK_FIRM:
  449. process_monster_defend_back_firm();
  450. hasSearch++;
  451. returnFlag = 1;
  452. break;
  453. case ACTION_SHIP_TO_BEACH:
  454. shipPtr = (UnitMarine*) this;
  455. if(!shipPtr->in_beach || shipPtr->extra_move_in_beach==EXTRA_MOVE_FINISH)
  456. {
  457. //----------- the ship has not reached inlet, so move again --------------//
  458. ship_to_beach(action_x_loc2, action_y_loc2, dummyX, dummyY);
  459. hasSearch++;
  460. }
  461. returnFlag = 1;
  462. break;
  463. case ACTION_GO_CAST_POWER:
  464. go_cast_power(action_x_loc2, action_y_loc2, ((UnitGod*)this)->cast_power_type, COMMAND_AUTO);
  465. returnFlag = 1;
  466. break;
  467. default: err_here();
  468. break;
  469. }
  470. if(validSearch && hasSearch && seek_path.path_status==PATH_NODE_USED_UP &&
  471. next_x_loc()==move_to_x_loc && next_y_loc()==move_to_y_loc)
  472. {
  473. //-------------------------------------------------------------------------//
  474. // abort actions since the unit trys to move and move no more.
  475. //-------------------------------------------------------------------------//
  476. stop2(KEEP_DEFENSE_MODE);
  477. return 1;
  478. }
  479. int abort=0;
  480. if(returnFlag)
  481. {
  482. if(curXLoc==move_to_x_loc && curYLoc==move_to_y_loc && seek_path.path_status==PATH_NODE_USED_UP)
  483. {
  484. //---------------------------------------------------------------------------------//
  485. // insufficient nodes for searching
  486. //---------------------------------------------------------------------------------//
  487. if(action_mode2==ACTION_ASSIGN_TO_SHIP || action_mode2==ACTION_SHIP_TO_BEACH || in_any_defense_mode())
  488. return 1;
  489. //------- number of nodes is not enough to find the destination -------//
  490. if(action_misc!=ACTION_MISC_STOP)
  491. {
  492. if(action_misc==ACTION_MISC_PRE_SEARCH_NODE_USED_UP)
  493. {
  494. if(action_misc_para<20)
  495. {
  496. action_misc_para++;
  497. return 0;
  498. }
  499. else
  500. action_misc_para++;
  501. }
  502. abort++; // assume destination unreachable, abort action
  503. }
  504. else
  505. {
  506. action_misc = ACTION_MISC_PRE_SEARCH_NODE_USED_UP;
  507. action_misc_para = 0;
  508. }
  509. }
  510. else // action resumed, return true
  511. return 1;
  512. }
  513. if(!returnFlag || abort)
  514. {
  515. stop2(KEEP_DEFENSE_MODE);
  516. }
  517. return 0;
  518. }
  519. //----------- End of function Unit::reactivate_idle_action -----------//
  520. //--------- Begin of function Unit::idle_detect_attack --------//
  521. // detect target for idle units
  522. //
  523. // [int] startLoc - (default = 0), used to select region of the square
  524. // for checking
  525. // [int] dimensionInput - (default = 0), the detected size is calculated as
  526. // 2*dimensionInput+1. this unit is located in
  527. // the center of the square.
  528. // [char] defenseMode - true for defensive mode on.
  529. //
  530. // return 1 if any target is detected
  531. // return 0 otherwise
  532. //
  533. int Unit::idle_detect_attack(int startLoc, int dimensionInput, char defenseMode)
  534. {
  535. err_when(attack_count==0);
  536. //---------------------------------------------------//
  537. // Set detectDelay.
  538. //
  539. // The larger its value, the less CPU time it will takes,
  540. // but it will also take longer to detect enemies.
  541. //---------------------------------------------------//
  542. int detectDelay = 1+unit_array.packed_size()/10;
  543. Location *locPtr;
  544. Unit *unitPtr;
  545. //Unit *unitPtr, *targetUnitPtr;
  546. //Firm *firmPtr, *targetFirmPtr;
  547. //Town *townPtr, *targetTownPtr;
  548. //int targetWallXLoc, targetWallYLoc;
  549. //char hasUnit=0, hasFirm=0, hasTown=0, hasWall=0;
  550. char targetMobileType;
  551. int dimension, countLimit;
  552. short targetRecno, i;
  553. int xOffset, yOffset, checkXLoc, checkYLoc;
  554. idle_detect_default_mode = (!startLoc && !dimensionInput && !defenseMode); //----- true when all zero
  555. idle_detect_has_unit = idle_detect_has_firm = idle_detect_has_town = idle_detect_has_wall = 0;
  556. help_mode = HELP_NOTHING;
  557. err_when(idle_detect_default_mode!=0 && idle_detect_default_mode!=1);
  558. //-----------------------------------------------------------------------------------------------//
  559. // adjust waiting_term for default_mode
  560. //-----------------------------------------------------------------------------------------------//
  561. int lowestBit = (++waiting_term)%detectDelay;
  562. if(action_mode2==ACTION_STOP)
  563. {
  564. err_when(action_mode!=ACTION_STOP);
  565. waiting_term = lowestBit;
  566. }
  567. (dimension = (dimensionInput ? dimensionInput : ATTACK_DETECT_DISTANCE)<<1)++;
  568. countLimit = dimension*dimension;
  569. i = startLoc ? startLoc : 1+lowestBit;
  570. int incAmount = (idle_detect_default_mode) ? detectDelay : 1;
  571. //-----------------------------------------------------------------------------------------------//
  572. // check the location around the unit
  573. //
  574. // The priority to choose target is (value of targetType)
  575. // 1) Unit, 2) firm, 3) wall
  576. //-----------------------------------------------------------------------------------------------//
  577. err_when(defenseMode && action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET &&
  578. action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET && action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET);
  579. err_when(incAmount<1 || incAmount>100000);
  580. for(; i<=countLimit; i+=incAmount) // 1 is the self location
  581. {
  582. m.cal_move_around_a_point(i, dimension, dimension, xOffset, yOffset);
  583. checkXLoc = move_to_x_loc+xOffset;
  584. checkYLoc = move_to_y_loc+yOffset;
  585. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  586. continue;
  587. //------------------ verify location ---------------//
  588. locPtr = world.get_loc(checkXLoc, checkYLoc);
  589. if(defenseMode && action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET)
  590. {
  591. if(action_mode2==ACTION_AUTO_DEFENSE_DETECT_TARGET)
  592. if(locPtr->power_nation_recno!=nation_recno && locPtr->power_nation_recno)
  593. continue; // skip this location because it is not neutral nation or our nation
  594. }
  595. //----------------------------------------------------------------------------//
  596. // checking the target type
  597. //----------------------------------------------------------------------------//
  598. if((targetMobileType=locPtr->has_any_unit(i==1 ? mobile_type : UNIT_LAND)) &&
  599. (targetRecno=locPtr->unit_recno(targetMobileType)) && !unit_array.is_deleted(targetRecno))
  600. {
  601. //=================== is unit ======================//
  602. if(idle_detect_has_unit || (action_para==targetRecno && action_mode==ACTION_ATTACK_UNIT &&
  603. checkXLoc==action_x_loc && checkYLoc==action_y_loc))
  604. continue; // same target as before
  605. unitPtr = unit_array[targetRecno];
  606. if(nation_recno && unitPtr->nation_recno==nation_recno && help_mode!=HELP_ATTACK_UNIT)
  607. idle_detect_helper_attack(targetRecno); // help our troop
  608. else if((help_mode==HELP_ATTACK_UNIT && help_attack_target_recno==targetRecno) ||
  609. (unitPtr->nation_recno!=nation_recno && idle_detect_unit_checking(targetRecno)))
  610. {
  611. idle_detect_target_unit_recno = targetRecno;
  612. idle_detect_has_unit++;
  613. break; // break with highest priority
  614. }
  615. }
  616. else if(locPtr->is_firm() && (targetRecno = locPtr->firm_recno()))
  617. {
  618. //=============== is firm ===============//
  619. if(idle_detect_has_firm || (action_para==targetRecno && action_mode==ACTION_ATTACK_FIRM &&
  620. action_x_loc==checkXLoc && action_y_loc==checkYLoc))
  621. continue; // same target as before
  622. if(idle_detect_firm_checking(targetRecno))
  623. {
  624. idle_detect_target_firm_recno = targetRecno;
  625. idle_detect_has_firm++;
  626. }
  627. }
  628. /*else if(locPtr->is_town() && (targetRecno = locPtr->town_recno()))
  629. {
  630. //=============== is town ===========//
  631. if(idle_detect_has_town || (action_para==targetRecno && action_mode==ACTION_ATTACK_TOWN &&
  632. action_x_loc==checkXLoc && action_y_loc==checkYLoc))
  633. continue; // same target as before
  634. if(idle_detect_town_checking(targetRecno))
  635. {
  636. idle_detect_target_town_recno = targetRecno;
  637. idle_detect_has_town++;
  638. }
  639. }
  640. else if(locPtr->is_wall())
  641. {
  642. //================ is wall ==============//
  643. if(idle_detect_has_wall || (action_mode==ACTION_ATTACK_WALL && action_para==targetRecno &&
  644. action_x_loc==checkXLoc && action_y_loc==checkYLoc))
  645. continue; // same target as before
  646. if(idle_detect_wall_checking(checkXLoc, checkYLoc))
  647. {
  648. idle_detect_target_wall_x1 = checkXLoc;
  649. idle_detect_target_wall_y1 = checkYLoc;
  650. idle_detect_has_wall++;
  651. }
  652. }*/
  653. //if(hasUnit && hasFirm && hasTown && hasWall)
  654. //if(hasUnit && hasFirm && hasWall)
  655. // break; // there is target for attacking
  656. }
  657. return idle_detect_choose_target(defenseMode);
  658. }
  659. //----------- End of function Unit::idle_detect_attack -----------//
  660. //--------- Begin of function Unit::idle_detect_unit_checking --------//
  661. // check whether to attack the unit with recno = targetRecno
  662. //
  663. // <short> targetRecno - recno of unit being checked
  664. //
  665. // return 1 if situation is suitable for attacking
  666. // return 0 otherwise
  667. //
  668. int Unit::idle_detect_unit_checking(short targetRecno)
  669. {
  670. Unit *targetUnitPtr = unit_array[targetRecno];
  671. if(targetUnitPtr->unit_id == UNIT_CARAVAN)
  672. return 0;
  673. //###### trevor 15/10 #######//
  674. //-------------------------------------------//
  675. // If the target is moving, don't attack it.
  676. // Only attack when the unit stands still or
  677. // is attacking.
  678. //-------------------------------------------//
  679. if( targetUnitPtr->cur_action != SPRITE_ATTACK &&
  680. targetUnitPtr->cur_action != SPRITE_IDLE )
  681. {
  682. return 0;
  683. }
  684. //-------------------------------------------//
  685. // If the target is a spy of our own and the
  686. // notification flag is set to 0, then don't
  687. // attack.
  688. //-------------------------------------------//
  689. if( targetUnitPtr->spy_recno ) // if the target unit is our spy, don't attack
  690. {
  691. Spy* spyPtr = spy_array[targetUnitPtr->spy_recno];
  692. if( spyPtr->true_nation_recno == nation_recno &&
  693. spyPtr->notify_cloaked_nation_flag == 0 )
  694. {
  695. return 0;
  696. }
  697. }
  698. if( spy_recno ) // if this unit is our spy, don't attack own units
  699. {
  700. Spy* spyPtr = spy_array[spy_recno];
  701. if( spyPtr->true_nation_recno == targetUnitPtr->nation_recno &&
  702. spyPtr->notify_cloaked_nation_flag == 0 )
  703. {
  704. return 0;
  705. }
  706. }
  707. //###### trevor 15/10 #######//
  708. SpriteInfo *spriteInfo = targetUnitPtr->sprite_info;
  709. Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
  710. short targetNationRecno = targetUnitPtr->nation_recno;
  711. //-------------------------------------------------------------------//
  712. // checking nation relationship
  713. //-------------------------------------------------------------------//
  714. if(nation_recno)
  715. {
  716. if(targetNationRecno)
  717. {
  718. //------- don't attack own units and non-hostile units -------//
  719. err_when(targetNationRecno==nation_recno);
  720. //--------------------------------------------------------------//
  721. // if the unit is hostile, only attack if should_attack flag to
  722. // that nation is true or the unit is attacking somebody or something.
  723. //--------------------------------------------------------------//
  724. NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
  725. if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
  726. return 0;
  727. }
  728. else if(!targetUnitPtr->independent_nation_can_attack(nation_recno))
  729. return 0;
  730. }
  731. else if(!independent_nation_can_attack(targetNationRecno)) // independent unit
  732. return 0;
  733. //---------------------------------------------//
  734. if(space_for_attack(targetUnitPtr->next_x_loc(), targetUnitPtr->next_y_loc(), targetUnitPtr->mobile_type,
  735. spriteInfo->loc_width, spriteInfo->loc_height))
  736. return 1;
  737. else
  738. return 0;
  739. }
  740. //----------- End of function Unit::idle_detect_unit_checking -----------//
  741. //--------- Begin of function Unit::idle_detect_firm_checking --------//
  742. // check whether to attack the firm
  743. //
  744. // <short> targetRecno - recno of the firm being checked
  745. //
  746. // return 1 if situation is suitable
  747. // return 0 otherwise
  748. //
  749. int Unit::idle_detect_firm_checking(short targetRecno)
  750. {
  751. Firm *firmPtr = firm_array[targetRecno];
  752. //------------ code to select firm for attacking -----------//
  753. switch(firmPtr->firm_id)
  754. {
  755. case FIRM_CAMP:case FIRM_BASE: case FIRM_WAR_FACTORY:
  756. break;
  757. default: return 0;
  758. }
  759. Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
  760. short targetNationRecno = firmPtr->nation_recno;
  761. char targetMobileType = mobile_type==UNIT_SEA ? UNIT_SEA : UNIT_LAND;
  762. //-------------------------------------------------------------------------------//
  763. // checking nation relationship
  764. //-------------------------------------------------------------------------------//
  765. if(nation_recno)
  766. {
  767. if(targetNationRecno)
  768. {
  769. //------- don't attack own units and non-hostile units -------//
  770. if( targetNationRecno==nation_recno )
  771. return 0;
  772. //--------------------------------------------------------------//
  773. // if the unit is hostile, only attack if should_attack flag to
  774. // that nation is true or the unit is attacking somebody or something.
  775. //--------------------------------------------------------------//
  776. NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
  777. if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
  778. return 0;
  779. }
  780. else // independent firm
  781. {
  782. FirmMonster *monsterFirmPtr = (FirmMonster*) firm_array[targetRecno];
  783. if(!monsterFirmPtr->is_hostile_nation(nation_recno))
  784. return 0;
  785. }
  786. }
  787. else if(!independent_nation_can_attack(targetNationRecno)) // independent town
  788. return 0;
  789. FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
  790. if(space_for_attack(firmPtr->loc_x1, firmPtr->loc_y1, UNIT_LAND, firmInfo->loc_width, firmInfo->loc_height))
  791. return 1;
  792. else
  793. return 0;
  794. }
  795. //----------- End of function Unit::idle_detect_firm_checking -----------//
  796. //--------- Begin of function Unit::idle_detect_town_checking --------//
  797. // check town to attack
  798. //
  799. // <short> targetRecno - recno of town
  800. //
  801. // return 1 if situation is suitable for attacking
  802. // return 0 otherwise
  803. //
  804. int Unit::idle_detect_town_checking(short targetRecno)
  805. {
  806. Town *townPtr = town_array[targetRecno];
  807. Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
  808. short targetNationRecno = townPtr->nation_recno;
  809. //-------------------------------------------------------------------------------//
  810. // checking nation relationship
  811. //-------------------------------------------------------------------------------//
  812. if(nation_recno)
  813. {
  814. if(targetNationRecno)
  815. {
  816. //------- don't attack own units and non-hostile units -------//
  817. if( targetNationRecno==nation_recno )
  818. return 0;
  819. //--------------------------------------------------------------//
  820. // if the unit is hostile, only attack if should_attack flag to
  821. // that nation is true or the unit is attacking somebody or something.
  822. //--------------------------------------------------------------//
  823. NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
  824. if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
  825. return 0;
  826. }
  827. else if(!townPtr->is_hostile_nation(nation_recno))
  828. return 0; // false if the indepentent unit don't want to attack us
  829. }
  830. else if(!independent_nation_can_attack(targetNationRecno)) // independent town
  831. return 0;
  832. if(space_for_attack(townPtr->loc_x1, townPtr->loc_y1, UNIT_LAND, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
  833. return 1;
  834. else
  835. return 0;
  836. }
  837. //----------- End of function Unit::idle_detect_town_checking -----------//
  838. //--------- Begin of function Unit::idle_detect_wall_checking --------//
  839. // check wall to attack
  840. //
  841. // <int> targetXLoc - wall x location
  842. // <int> targetYLoc - wall y location
  843. //
  844. // return 1 if situation is suitable for attacking
  845. // return 0 otherwise
  846. //
  847. int Unit::idle_detect_wall_checking(int targetXLoc, int targetYLoc)
  848. {
  849. Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
  850. Nation *nationPtr = nation_recno ? nation_array[nation_recno] : NULL;
  851. short targetNationRecno = locPtr->wall_nation_recno();
  852. //-------------------------------------------------------------------------------//
  853. // checking nation relationship
  854. //-------------------------------------------------------------------------------//
  855. if(nation_recno)
  856. {
  857. if(targetNationRecno)
  858. {
  859. //------- don't attack own units and non-hostile units -------//
  860. if( targetNationRecno==nation_recno )
  861. return 0;
  862. //--------------------------------------------------------------//
  863. // if the unit is hostile, only attack if should_attack flag to
  864. // that nation is true or the unit is attacking somebody or something.
  865. //--------------------------------------------------------------//
  866. NationRelation* nationRelation = nationPtr->get_relation(targetNationRecno);
  867. if( nationRelation->status != NATION_HOSTILE || !nationRelation->should_attack )
  868. return 0;
  869. }
  870. else
  871. return 0;
  872. }
  873. else if(!independent_nation_can_attack(targetNationRecno)) // independent town
  874. return 0;
  875. if(space_for_attack(targetXLoc, targetYLoc, UNIT_LAND, 1, 1))
  876. return 1;
  877. else
  878. return 0;
  879. }
  880. //----------- End of function Unit::idle_detect_wall_checking -----------//
  881. //--------- Begin of function Unit::idle_detect_choose_target --------//
  882. //
  883. // <char> defenseMode - indicate whether defensive mode is on
  884. //
  885. int Unit::idle_detect_choose_target(char defenseMode)
  886. {
  887. //-----------------------------------------------------------------------------------------------//
  888. // Decision making for choosing target to attack
  889. //-----------------------------------------------------------------------------------------------//
  890. if(defenseMode)
  891. {
  892. if(action_mode2==ACTION_AUTO_DEFENSE_DETECT_TARGET)
  893. {
  894. //----------- defense units allow to attack units and firms -----------//
  895. err_when(!in_auto_defense_mode());
  896. if(idle_detect_has_unit)
  897. defense_attack_unit(idle_detect_target_unit_recno);
  898. else if(idle_detect_has_firm)
  899. {
  900. Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
  901. defense_attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
  902. }
  903. /*else if(idle_detect_has_town)
  904. {
  905. TownPtr *targetTownPtr = town_array[idle_detect_target_town_recno];
  906. defense_attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
  907. }
  908. else if(idle_detect_has_wall)
  909. defense_attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
  910. else
  911. return 0;
  912. return 1;
  913. }
  914. else if(action_mode2==ACTION_DEFEND_TOWN_DETECT_TARGET)
  915. {
  916. //----------- town units only attack units ------------//
  917. err_when(!in_defend_town_mode());
  918. if(idle_detect_has_unit)
  919. defend_town_attack_unit(idle_detect_target_unit_recno);
  920. else
  921. return 0;
  922. return 1;
  923. }
  924. else if(action_mode2==ACTION_MONSTER_DEFEND_DETECT_TARGET)
  925. {
  926. //---------- monsters can attack units and firms -----------//
  927. err_when(!in_monster_defend_mode());
  928. if(idle_detect_has_unit)
  929. monster_defend_attack_unit(idle_detect_target_unit_recno);
  930. else if(idle_detect_has_firm)
  931. {
  932. Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
  933. monster_defend_attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
  934. }
  935. /*else if(idle_detect_has_town)
  936. {
  937. Town *targetTownPtr = town_array[idle_detect_target_town_recno];
  938. monster_defend_attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
  939. }
  940. else if(idle_detect_has_wall)
  941. monster_defend_attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
  942. else
  943. return 0;
  944. return 1;
  945. }
  946. else
  947. err_here();
  948. }
  949. else // default mode
  950. {
  951. //#### begin trevor 9/10 ####//
  952. int rc = 0;
  953. if(idle_detect_has_unit)
  954. {
  955. attack_unit(idle_detect_target_unit_recno);
  956. //--- set the original position of the target, so the unit won't chase too far away ---//
  957. Unit* unitPtr = unit_array[idle_detect_target_unit_recno];
  958. original_target_x_loc = unitPtr->next_x_loc();
  959. original_target_y_loc = unitPtr->next_y_loc();
  960. rc = 1;
  961. }
  962. else if(help_mode==HELP_ATTACK_UNIT)
  963. {
  964. attack_unit(help_attack_target_recno);
  965. //--- set the original position of the target, so the unit won't chase too far away ---//
  966. Unit* unitPtr = unit_array[help_attack_target_recno];
  967. original_target_x_loc = unitPtr->next_x_loc();
  968. original_target_y_loc = unitPtr->next_y_loc();
  969. rc = 1;
  970. }
  971. else if(idle_detect_has_firm)
  972. {
  973. Firm *targetFirmPtr = firm_array[idle_detect_target_firm_recno];
  974. attack_firm(targetFirmPtr->loc_x1, targetFirmPtr->loc_y1);
  975. }
  976. /*else if(idle_detect_has_town)
  977. {
  978. Town *targetTownPtr = town_array[idle_detect_target_town_recno];
  979. attack_town(targetTownPtr->loc_x1, targetTownPtr->loc_y1);
  980. }
  981. else if(idle_detect_has_wall)
  982. attack_wall(idle_detect_target_wall_x1, idle_detect_target_wall_y1);*/
  983. else
  984. return 0;
  985. //---- set original action vars ----//
  986. if( rc && original_action_mode==0 )
  987. {
  988. original_action_mode = ACTION_MOVE;
  989. original_action_para = 0;
  990. original_action_x_loc = next_x_loc();
  991. original_action_y_loc = next_y_loc();
  992. }
  993. return 1;
  994. //#### end trevor 9/10 ####//
  995. }
  996. return 0;
  997. }
  998. //----------- End of function Unit::idle_detect_choose_target -----------//
  999. //--------- Begin of function Unit::idle_detect_helper_attack --------//
  1000. // check the action_mode of the unit being checked, which has same nation
  1001. // recno as this unit. If the unit attacks other unit, this unit help to
  1002. // attack the same target.
  1003. //
  1004. // <short> unitRecno - recno of the unit of nation recno same as this unit
  1005. //
  1006. void Unit::idle_detect_helper_attack(short unitRecno)
  1007. {
  1008. #define HELP_DISTANCE 15
  1009. Unit *unitPtr = unit_array[unitRecno];
  1010. if(unitPtr->unit_id == UNIT_CARAVAN)
  1011. return;
  1012. //char actionMode;
  1013. short actionPara;
  1014. //short actionXLoc, actionYLoc;
  1015. char isUnit = 0;
  1016. //------------- is the unit attacking other unit ------------//
  1017. switch(unitPtr->action_mode2)
  1018. {
  1019. case ACTION_ATTACK_UNIT:
  1020. actionPara = unitPtr->action_para2;
  1021. isUnit++;
  1022. break;
  1023. default:
  1024. switch(unitPtr->action_mode)
  1025. {
  1026. case ACTION_ATTACK_UNIT:
  1027. actionPara = unitPtr->action_para;
  1028. isUnit++;
  1029. break;
  1030. }
  1031. }
  1032. if(isUnit && !unit_array.is_deleted(actionPara))
  1033. {
  1034. Unit *targetUnit = unit_array[actionPara];
  1035. if(targetUnit->nation_recno==nation_recno)
  1036. return;
  1037. if(m.points_distance(next_x_loc(), next_y_loc(), targetUnit->next_x_loc(), targetUnit->next_y_loc())<HELP_DISTANCE)
  1038. {
  1039. if(idle_detect_unit_checking(actionPara))
  1040. {
  1041. help_attack_target_recno = actionPara;
  1042. help_mode = HELP_ATTACK_UNIT;
  1043. }
  1044. memset(blocked_edge, 0, sizeof(blocked_edge));
  1045. }
  1046. }
  1047. }
  1048. //----------- End of function Unit::idle_detect_helper_attack -----------//