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