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 : OUNITM.CPP
22 //Description : Object Unit movement
23 //Owner : Alex
24
25 #include <ALL.h>
26 #include <OWORLD.h>
27 #include <OF_HARB.h>
28 #include <OGAME.h>
29 #include <ONATION.h>
30 #include <OU_MARI.h>
31 #include <OSPATH.h>
32 #include <OSPREUSE.h>
33 #include <OSERES.h>
34 #include <OLOG.h>
35 #include <OEFFECT.h>
36
37 #ifdef NO_DEBUG_UNIT
38 #undef err_when
39 #undef err_here
40 #undef err_if
41 #undef err_else
42 #undef err_now
43 #define err_when(cond)
44 #define err_here()
45 #define err_if(cond)
46 #define err_else
47 #define err_now(msg)
48 #undef DEBUG
49 #endif
50
51 //-*********** simulate aat ************-//
52 #ifdef DEBUG
53 #include <OSYS.h>
54 #endif
55 //-*********** simulate aat ************-//
56
57 //--- Define no. of pixels per direction move (N, NE, E, SE, S, SW, W, NW) ---//
58
59 static short move_x_pixel_array[] = { 0, ZOOM_LOC_WIDTH, ZOOM_LOC_WIDTH, ZOOM_LOC_WIDTH, 0, -ZOOM_LOC_WIDTH, -ZOOM_LOC_WIDTH, -ZOOM_LOC_WIDTH };
60 static short move_y_pixel_array[] = { -ZOOM_LOC_HEIGHT, -ZOOM_LOC_HEIGHT, 0, ZOOM_LOC_HEIGHT, ZOOM_LOC_HEIGHT, ZOOM_LOC_HEIGHT, 0, -ZOOM_LOC_HEIGHT };
61
62 static short cycle_wait_unit_index;
63 static short *cycle_wait_unit_array;
64 static short cycle_wait_unit_array_def_size;
65 static short cycle_wait_unit_array_multipler;
66
67
68 static char move_action_call_flag=0; // avoid calling move_to_my_loc() if this function is called from move_to() chain
69
70
71 //--------- Begin of function Unit::reset_action_para ---------//
72 // reset action parameters when action is finished or cancelled
73 // for action_mode
74 //
reset_action_para()75 void Unit::reset_action_para()
76 {
77 action_mode = ACTION_STOP;
78 action_x_loc = action_y_loc = -1;
79 action_para = 0;
80 }
81 //----------- End of function Unit::reset_action_para -----------//
82
83
84 //--------- Begin of function Unit::reset_action_para2 ---------//
85 // reset action parameters when action is finished or cancelled
86 //
87 // <int> keepMode - use to keep action
88 //
reset_action_para2(int keepMode)89 void Unit::reset_action_para2(int keepMode)
90 {
91 if(keepMode!=KEEP_DEFENSE_MODE || !in_any_defense_mode())
92 {
93 action_mode2 = ACTION_STOP;
94 action_para2 = 0;
95 action_x_loc2 = action_y_loc2 = -1;
96 }
97 else
98 {
99 switch(unit_mode)
100 {
101 case UNIT_MODE_DEFEND_TOWN:
102 if(action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET)
103 defend_town_detect_target();
104 break;
105
106 case UNIT_MODE_REBEL:
107 if(action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET)
108 defense_detect_target();
109 break;
110
111 case UNIT_MODE_MONSTER:
112 if(action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET)
113 monster_defend_detect_target();
114 break;
115 }
116 }
117 }
118 //----------- End of function Unit::reset_action_para2 -----------//
119
120
121 //--------- Begin of function Unit::reset_action_misc_para ---------//
122 // reset miscellaneous action parameters
123 //
reset_action_misc_para()124 void Unit::reset_action_misc_para()
125 {
126 action_misc = ACTION_MISC_STOP;
127 action_misc_para = 0;
128 }
129 //----------- End of function Unit::reset_action_misc_para -----------//
130
131
132 //--------- Begin of function Unit::stop ---------//
133 // stop unit action
134 //
135 // [int] preserveAction - preserve the current action or not.
136 // (default: 0)
137 //
stop(int preserveAction)138 void Unit::stop(int preserveAction)
139 {
140 //------------- reset vars ------------//
141 if(action_mode2!=ACTION_MOVE)
142 reset_way_point_array();
143
144 reset_path();
145 err_when(result_node_array!=NULL);
146
147 //-------------- keep action or not --------------//
148 switch(preserveAction)
149 {
150 case 0: case KEEP_DEFENSE_MODE:
151 reset_action_para();
152 range_attack_x_loc = range_attack_y_loc = -1; // should set here or reset for attack
153 break;
154
155 case KEEP_PRESERVE_ACTION:
156 break;
157
158 /*case 3: err_when(action_mode!=ACTION_ATTACK_UNIT);
159 go_x = next_x; // combine move_to_attack() into move_to()
160 go_y = next_y;
161 move_to_x_loc = next_x_loc();
162 move_to_y_loc = next_y_loc();
163 return;*/
164 }
165
166 waiting_term = 0; // for idle_detect_attack(), oscillate between 0 and 1
167 err_when(cur_dir<0 || cur_dir>MAX_SPRITE_DIR_TYPE);
168 err_when(final_dir<0 || final_dir>MAX_SPRITE_DIR_TYPE);
169 UnitMarine *shipPtr;
170
171 //----------------- update parameters ----------------//
172 switch( cur_action )
173 {
174 //----- if the unit is moving right now, ask it to stop as soon as possible -----//
175
176 case SPRITE_READY_TO_MOVE:
177 set_idle();
178 break;
179
180 case SPRITE_TURN:
181 case SPRITE_WAIT:
182 go_x = next_x;
183 go_y = next_y;
184 move_to_x_loc = next_x_loc();
185 move_to_y_loc = next_y_loc();
186 final_dir = cur_dir;
187 turn_delay = 0;
188 set_idle();
189 break;
190
191 case SPRITE_SHIP_EXTRA_MOVE:
192 shipPtr = (UnitMarine*) this;
193 switch(shipPtr->extra_move_in_beach)
194 {
195 case NO_EXTRA_MOVE:
196 if(cur_x==next_x && cur_y==next_y)
197 {
198 go_x = next_x;
199 go_y = next_y;
200 move_to_x_loc = next_x_loc();
201 move_to_y_loc = next_y_loc();
202 set_idle();
203 return;
204 }
205 break;
206
207 case EXTRA_MOVING_IN:
208 if(cur_x==next_x && cur_y==next_y && (cur_x!=go_x || cur_y!=go_y))
209 {
210 shipPtr->extra_move_in_beach = NO_EXTRA_MOVE; // not yet move although location is chosed
211 err_when(next_x_loc()%2 || next_y_loc()%2); // in even location
212 }
213 else
214 err_when(next_x_loc()%2==0 && next_y_loc()%2==0); // in even location
215 break;
216
217 case EXTRA_MOVING_OUT:
218 if(cur_x==next_x && cur_y==next_y && (cur_x!=go_x || cur_y!=go_y))
219 {
220 shipPtr->extra_move_in_beach = EXTRA_MOVE_FINISH; // not yet move although location is chosed
221 err_when(next_x_loc()%2==0 && next_y_loc()%2==0); // not in even location
222 }
223 else
224 err_when(next_x_loc()%2 || next_y_loc()%2); // in even location
225 break;
226
227
228 case EXTRA_MOVE_FINISH:
229 break;
230 }
231
232 go_x = next_x;
233 go_y = next_y;
234 move_to_x_loc = next_x_loc();
235 move_to_y_loc = next_y_loc();
236 break;
237
238 case SPRITE_MOVE:
239 go_x = next_x;
240 go_y = next_y;
241 move_to_x_loc = next_x_loc();
242 move_to_y_loc = next_y_loc();
243 if(cur_x==next_x && cur_y==next_y)
244 set_idle();
245 break;
246
247 //--- if its current action is SPRITE_ATTACK, stop immediately ---//
248
249 case SPRITE_ATTACK:
250 set_next(cur_x, cur_y, 0, 1); //********** BUGHERE
251 go_x = next_x;
252 go_y = next_y;
253 move_to_x_loc = next_x_loc();
254 move_to_y_loc = next_y_loc();
255 set_idle();
256
257 #ifdef DEBUG
258 char h, w, blocked=0;
259 short x, y;
260
261 for(h=0, y=next_y_loc(); h<sprite_info->loc_height&&!blocked; h++, y++)
262 {
263 for(w=0, x=next_x_loc(); w<sprite_info->loc_width&&!blocked; w++, x++)
264 err_when(world.get_unit_recno(x, y, mobile_type) != sprite_recno);
265 }
266 #endif
267 cur_frame = 1;
268 break;
269 }
270 }
271 //----------- End of function Unit::stop -----------//
272
273
274 //--------- Begin of function Unit::stop2 ---------//
275 // stop unit action
276 //
277 // preserverAction can be
278 // 0, KEEP_PRESERVE_ACTION, KEEP_DEFENSE_MODE (default 0)
279 //
stop2(int preserveAction)280 void Unit::stop2(int preserveAction)
281 {
282 stop(preserveAction);
283 reset_action_para2(preserveAction);
284
285 //----------------------------------------------------------//
286 // set the original location of the attacking target when
287 // the attack() function is called, action_x_loc2 & action_y_loc2
288 // will change when the unit move, but these two will not.
289 //----------------------------------------------------------//
290
291 //##### begin trevor 13/10 #####//
292
293 force_move_flag = 0;
294 ai_no_suitable_action = 0;
295
296 if( preserveAction==0 )
297 {
298 original_action_mode = 0;
299 ai_original_target_x_loc = -1;
300
301 if( ai_action_id )
302 nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
303 }
304
305 //##### end trevor 13/10 #####//
306 }
307 //----------- End of function Unit::stop2 -----------//
308
309 //######## begin trevor 26/4 ###########//
310
311 //--------- Begin of function Unit::set_search_tries ---------//
312 // used to limit the number of nodes in searching
313 //
314 // <int> tries - number of nodes used in searhcing
315 //
set_search_tries(int tries)316 void Unit::set_search_tries(int tries)
317 {
318 unit_search_tries = tries;
319 unit_search_tries_flag++;
320 }
321 //----------- End of function Unit::set_search_tries -----------//
322
323
324 //--------- Begin of function Unit::reset_search_tries ---------//
325 // reset the number of node to default value
326 //
reset_search_tries()327 void Unit::reset_search_tries()
328 {
329 unit_search_tries = 0; // 0 for reset
330 unit_search_tries_flag = 0;
331 }
332 //----------- End of function Unit::reset_search_tries -----------//
333
334 //######## end trevor 26/4 ###########//
335
336 //-------- Begin of function Unit::abort_searching --------//
337 //
338 // <int> reuseSetNext - condition flag for updating parameters
339 // of path_reuse
340 //
abort_searching(int reuseSetNext)341 void Unit::abort_searching(int reuseSetNext)
342 {
343 if(reuseSetNext) // to avoid error in path-reuse
344 seek_path_reuse.set_next_cur_path_num();
345
346 if(unit_search_tries_flag)
347 reset_search_tries();
348 }
349 //-------- End of function Unit::abort_searching ---------//
350
351
352 //--------- Begin of function Unit::enable_force_move ---------//
enable_force_move()353 void Unit::enable_force_move()
354 {
355 force_move_flag = 1;
356 }
357 //-------- End of function Unit::enable_force_move ---------//
358
359
360 //--------- Begin of function Unit::disable_force_move ---------//
disable_force_move()361 void Unit::disable_force_move()
362 {
363 force_move_flag = 0;
364 }
365 //-------- End of function Unit::disable_force_move ---------//
366
367
368 //--------- Begin of function Unit::move_to ---------//
369 // Main function for action_mode = ACTION_MOVE
370 //
371 // Order the unit to move to a specific location following the shortest path.
372 //
373 // <int> destX - x location of the destination
374 // <int> destY - y location of the destination
375 // [int] preserveAction - preserve the current action or not (default: 0)
376 // [short] searchMode - the search mode used (default: SEARCH_MODE_IN_A_GROUP)
377 // [short] miscNo - = target record no if search_mode=SEARCH_MODE_TO_ATTACK
378 // = firm ID if search_mode=SEARCH_MODE_TO_FIRM (default: 0)
379 // [short] numOfPath - num of path, used in path reuse, (default: 1)
380 // [short] reuseMode - path reuse mode (default: GENERAL_GROUP_MOVEMENT)
381 // [short] pathReuseStatus - path reuse status (default: 0)
382 //
move_to(int destX,int destY,int preserveAction,short searchMode,short miscNo,short numOfPath,short reuseMode,short pathReuseStatus)383 void Unit::move_to(int destX, int destY, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus)
384 {
385 err_when(destX<0 || destX>=MAX_WORLD_X_LOC || destY<0 || destY>=MAX_WORLD_Y_LOC);
386
387 if(!seek_path.total_node_avail)
388 {
389 //-------- insufficient nodes for searching, return now ----------//
390 stop(KEEP_PRESERVE_ACTION);
391 action_mode = action_mode2 = ACTION_MOVE;
392 action_para = action_para2 = 0;
393 action_x_loc = action_x_loc2 = destX;
394 action_y_loc = action_y_loc2 = destY;
395 return; // for later searching
396 }
397
398 //int useClosestNode = (seek_path.total_node_avail>=MIN_BACKGROUND_NODE_USED_UP);
399
400 //---------- reset way point array since new action is assigned --------//
401 if(way_point_count)
402 {
403 ResultNode *nodePtr = way_point_array;
404 if(nodePtr->node_x!=destX || nodePtr->node_y!=destY)
405 reset_way_point_array();
406 }
407
408 //----------------------------------------------------------------//
409 // calculate new destination if trying to move to different territory
410 //----------------------------------------------------------------//
411 int curXLoc = next_x_loc();
412 int curYLoc = next_y_loc();
413 Location *locPtr = world.get_loc(curXLoc, curYLoc);
414 Location *destLocPtr = world.get_loc(destX, destY);
415 int destXLoc = destX;
416 int destYLoc = destY;
417
418 if(locPtr->region_id!=destLocPtr->region_id && mobile_type!=UNIT_AIR) // different territory
419 different_territory_destination(destXLoc, destYLoc);
420
421 //----------------------------------------------------------------//
422 // for path_reuse initialization
423 //----------------------------------------------------------------//
424 if(numOfPath!=1 && pathReuseStatus==REUSE_PATH_INITIAL) // for path-reuse only
425 {
426 search(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
427 return;
428 }
429
430 //----------------------------------------------------------------//
431 // return if the unit is dead
432 //----------------------------------------------------------------//
433 if(is_unit_dead())
434 {
435 abort_searching(searchMode==SEARCH_MODE_REUSE && numOfPath>1);
436 return;
437 }
438
439 //-----------------------------------------------------------------------------------//
440 // The codes here is used to check for equal action in movement.
441 //
442 // mainly checked by action_mode2. If previous action is ACTION_MOVE, action_mode2,
443 // action_para2, action_x_loc2 and action_x_loc2 need to be kept for this checking.
444 //
445 // If calling from unit_array.move_to(), action_mode is set to ACTION_MOVE, action_para
446 // is set to 0 while action_x_loc and action_y_loc are kept as original value for checking.
447 // Meanwhile, action_mode2, action_para2, action_x_loc2 and action_y_loc2 are kept if
448 // the condition is fulfilled (action_mode2==ACTION_MOVE)
449 //-----------------------------------------------------------------------------------//
450 if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
451 {
452 //------ previous action is ACTION_MOVE -------//
453 err_when(action_para2 || action_para);
454 if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
455 {
456 //-------- equal order --------//
457 action_x_loc = action_x_loc2;
458 action_y_loc = action_y_loc2;
459
460 if(cur_action!=SPRITE_IDLE)
461 {
462 //-------- the old order is processing --------//
463 abort_searching(searchMode==SEARCH_MODE_REUSE && numOfPath>1);
464
465 if(result_node_array==NULL) // cannot move
466 {
467 err_when(result_path_dist);
468 if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
469 {
470 if(cur_action!=SPRITE_SHIP_EXTRA_MOVE)
471 {
472 err_when(result_node_count || result_node_recno);
473 if(cur_x!=next_x || cur_y!=next_y)
474 set_move();
475 else
476 set_idle();
477 }
478 //else keep extra_moving
479 }
480 else
481 {
482 err_when(result_node_count || result_node_recno);
483 if(cur_x!=next_x || cur_y!=next_y)
484 set_move();
485 else
486 set_idle();
487 }
488 }
489
490 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
491 return;
492 }//else action is hold due to some problems, re-activiate again
493 }
494 }//else, new order or searching is required
495
496 move_action_call_flag++; // set flag to avoid calling move_to_my_loc()
497 seek_path_reuse.set_status(PATH_WAIT);
498 err_when(seek_path_reuse.get_reuse_path_status()==REUSE_PATH_INCOMPLETE_SEARCH);
499
500 action_mode2 = ACTION_MOVE;
501 action_para2 = 0;
502
503 int enoughNode = search(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
504 move_action_call_flag = 0; // clear the flag
505
506 //----------------------------------------------------------------//
507 // store new order in action parameters
508 //----------------------------------------------------------------//
509 action_mode = ACTION_MOVE;
510 action_para = 0;
511
512 if(!enoughNode || (searchMode==SEARCH_MODE_REUSE && seek_path_reuse.get_reuse_path_status()==REUSE_PATH_INCOMPLETE_SEARCH))
513 {
514 action_x_loc = action_x_loc2 = destXLoc;
515 action_y_loc = action_y_loc2 = destYLoc;
516 }
517 else // enough node for search
518 {
519 action_x_loc = action_x_loc2 = move_to_x_loc;
520 action_y_loc = action_y_loc2 = move_to_y_loc;
521 }
522
523 #ifdef DEBUG
524 if(result_node_array && result_node_count)
525 {
526 ResultNode *debugPtr = result_node_array + result_node_count - 1;
527 err_when(debugPtr->node_x != move_to_x_loc || debugPtr->node_y != move_to_y_loc);
528 }
529 else
530 {
531 UnitInfo* unitInfo = unit_res[unit_id];
532
533 if( unitInfo->unit_class == UNIT_CLASS_SHIP )
534 {
535 UnitMarine *shipPtr = (UnitMarine*) this;
536 if(shipPtr->extra_move_in_beach==NO_EXTRA_MOVE)
537 err_when(curXLoc!=move_to_x_loc || curYLoc!=move_to_y_loc);
538 }
539 else
540 {
541 err_when(curXLoc!=move_to_x_loc || curYLoc!=move_to_y_loc);
542 }
543 }
544 #endif
545 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
546 err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
547 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
548 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
549 err_when(action_mode2==ACTION_MOVE && (action_x_loc2==-1 || action_y_loc2==-1));
550 }
551 //----------- End of function Unit::move_to -----------//
552
553
554 //--------- Begin of function Unit::search ---------//
555 // This function is only used to find the shorest path for
556 // searching. Action parameters should not be changed in
557 // this function.
558 //
559 // <int> destX - x coordinate of destination
560 // <int> destY - y coordinate of destination
561 // <int> preserveAction - used to keep action in calling stop()
562 // <short> searchMode - search mode being used
563 // <short> miscNo - see move_to()
564 // <short> numOfPath - num of path
565 // <short> reuseMode - path reuse mode being used
566 // <short> pathReuseStatus - path reuse status
567 //
568 // return 1 for normal operation process
569 // return 0 otherwise or there is not enough node for searching
570 //
search(int destXLoc,int destYLoc,int preserveAction,short searchMode,short miscNo,short numOfPath,short reuseMode,short pathReuseStatus)571 int Unit::search(int destXLoc, int destYLoc, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus)
572 {
573 #ifdef DEBUG
574 err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
575 err_when(searchMode==SEARCH_MODE_TO_FIRM && miscNo!=FIRM_HARBOR && mobile_type!=UNIT_AIR &&
576 world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(destXLoc, destYLoc)->region_id);
577 err_when(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE);
578 #else
579 if(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC || hit_points<=0 ||
580 action_mode==ACTION_DIE || cur_action==SPRITE_DIE || searchMode<=0 || searchMode>MAX_SEARCH_MODE_TYPE)
581 {
582 stop2(KEEP_DEFENSE_MODE); //-********** BUGHERE, err_handling for retailed version
583 return 1;
584 }
585 #endif
586
587 //----------------------------------------------------------------//
588 // for path_reuse initialization
589 //----------------------------------------------------------------//
590 if(numOfPath!=1 && pathReuseStatus==REUSE_PATH_INITIAL) // for path-reuse only
591 {
592 seek_path_reuse.seek(next_x_loc(), next_y_loc(), move_to_x_loc, move_to_y_loc, sprite_info->loc_width,
593 unit_group_id, mobile_type, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
594 return 1;
595 }
596
597 int result=0;
598 if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP)
599 {
600 UnitMarine *shipPtr = (UnitMarine*) this;
601 switch(shipPtr->extra_move_in_beach)
602 {
603 case NO_EXTRA_MOVE:
604 result = searching(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
605 break;
606
607 case EXTRA_MOVING_IN:
608 err_when(next_x_loc()%2==0 && next_y_loc()%2==0);
609 if(pathReuseStatus==REUSE_PATH_SEARCH || pathReuseStatus==REUSE_PATH_FIRST_SEEK)
610 seek_path_reuse.set_next_cur_path_num();
611 return 0;
612
613 case EXTRA_MOVING_OUT:
614 err_when(next_x_loc()%2 || next_y_loc()%2);
615 if(pathReuseStatus==REUSE_PATH_SEARCH || pathReuseStatus==REUSE_PATH_FIRST_SEEK)
616 seek_path_reuse.set_next_cur_path_num();
617 return 0;
618
619 case EXTRA_MOVE_FINISH:
620 err_when(next_x_loc()%2==0 && next_y_loc()%2==0);
621 if(pathReuseStatus==REUSE_PATH_SEARCH || pathReuseStatus==REUSE_PATH_FIRST_SEEK)
622 seek_path_reuse.set_next_cur_path_num();
623
624 ship_leave_beach(next_x_loc(), next_y_loc());
625 break;
626
627 default: err_here();
628 break;
629 }
630 }
631 else
632 result = searching(destXLoc, destYLoc, preserveAction, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
633
634 if(way_point_count && !result_node_array) // can move no more
635 reset_way_point_array();
636
637 if(!result)
638 return 0; // not enough node or extra_move_in_beach!=NO_EXTRA_MOVE
639 else
640 return 1;
641 }
642 //----------- End of function Unit::search -----------//
643
644
645 //--------- Begin of function Unit::select_search_sub_mode ---------//
646 // select searching sub_mode
647 //
648 // <int> sx - start location x
649 // <int> sy - start location y
650 // <int> dx - x coordinate of destination
651 // <int> dy - y coordinate of destination
652 // <short> nationRecno - nation recno of the unit
653 // <short> searchMode - search mode being used
654 //
select_search_sub_mode(int sx,int sy,int dx,int dy,short nationRecno,short searchMode)655 void Unit::select_search_sub_mode(int sx, int sy, int dx, int dy, short nationRecno, short searchMode)
656 {
657 //seek_path.set_sub_mode(); // cancel the selection
658 //return;
659
660 err_when(mobile_type!=UNIT_LAND);
661
662 if(!nation_recno || ignore_power_nation)
663 {
664 seek_path.set_sub_mode(); // always using normal mode for independent unit
665 seek_path_reuse.set_sub_mode();
666 return;
667 }
668
669 //--------------------------------------------------------------------------------//
670 // Checking for starting location and destination to determine sub_mode used
671 // N - not hostile, H - hostile
672 // 1) N -> N, using normal mode
673 // 2) N -> H, H -> N, H -> H, using sub_mode SEARCH_SUB_MODE_PASSABLE
674 //--------------------------------------------------------------------------------//
675 Location *startLocPtr = world.get_loc(sx, sy);
676 Location *destLocPtr = world.get_loc(dx, dy);
677 Nation *nationPtr = nation_array[nationRecno];
678 int subModeOn = 1;
679
680 if((startLocPtr->power_nation_recno && !nationPtr->get_relation_passable(startLocPtr->power_nation_recno)) ||
681 (destLocPtr->power_nation_recno && !nationPtr->get_relation_passable(destLocPtr->power_nation_recno)))
682 subModeOn = 0;
683
684 if(subModeOn) // true only when both start and end locations are passable for this nation
685 {
686 seek_path.set_nation_passable(nationPtr->relation_passable_array);
687 seek_path.set_sub_mode(SEARCH_SUB_MODE_PASSABLE);
688 }
689 else
690 seek_path.set_sub_mode(); //----- normal sub mode, normal searching
691
692 //----------- set sub_mode of path-reuse if more than one unit are selected -----------//
693 if(subModeOn && searchMode==SEARCH_MODE_REUSE)
694 {
695 seek_path_reuse.set_nation_passable(nationPtr->relation_passable_array);
696 seek_path_reuse.set_sub_mode(SEARCH_SUB_MODE_PASSABLE);
697 }
698 else
699 seek_path_reuse.set_sub_mode();
700 }
701 //----------- End of function Unit::select_search_sub_mode -----------//
702
703
704 //--------- Begin of function Unit::searching ---------//
searching(int destXLoc,int destYLoc,int preserveAction,short searchMode,short miscNo,short numOfPath,short reuseMode,short pathReuseStatus)705 int Unit::searching(int destXLoc, int destYLoc, int preserveAction, short searchMode, short miscNo, short numOfPath, short reuseMode, short pathReuseStatus)
706 {
707 stop(preserveAction); // stop the unit as soon as possible
708
709 int startXLocLoc=next_x_loc(); // next location the sprite is moving towards
710 int startYLocLoc=next_y_loc();
711 int totalAvailableNode = seek_path.total_node_avail;
712
713 if(!avail_node_enough_for_search(startXLocLoc, startYLocLoc, destXLoc, destYLoc))
714 {
715 abort_searching(searchMode==4 && numOfPath>1);
716 return 0; // not enough node for searching
717 }
718
719 //stop(preserveAction); // stop the unit as soon as possible
720
721 //---------------------------------------------------------------------------//
722 // adjust the destination for unit size
723 //---------------------------------------------------------------------------//
724 /*err_when(sprite_info->loc_width!=sprite_info->loc_height);
725 if(sprite_info->loc_width>1) // not size 1x1
726 {
727 destXLoc = move_to_x_loc = MIN(destXLoc, MAX_WORLD_X_LOC-sprite_info->loc_width);
728 destYLoc = move_to_y_loc = MIN(destYLoc, MAX_WORLD_Y_LOC-sprite_info->loc_height);
729 }
730 else
731 {*/
732 move_to_x_loc = destXLoc;
733 move_to_y_loc = destYLoc;
734 //}
735
736 //------------------------------------------------------------//
737 // fast checking for destination == current location
738 //------------------------------------------------------------//
739 //if(startXLocLoc==move_to_x_loc && startYLocLoc==move_to_y_loc) // already here
740 if(startXLocLoc==destXLoc && startYLocLoc==destYLoc) // already here
741 {
742 if(cur_x!=next_x || cur_y!=next_y)
743 set_move();
744 else
745 set_idle();
746
747 err_when(move_to_x_loc!=startXLocLoc || move_to_y_loc!=startYLocLoc);
748 err_when(result_node_array!=NULL);
749
750 abort_searching(searchMode==SEARCH_MODE_REUSE && numOfPath>1);
751 return 1;
752 }
753
754 //------------------------ find the shortest path --------------------------//
755 //
756 // Note: seek() will never return PATH_SEEKING as the maxTries==max_node in
757 // calling seek()
758 //
759 // decide the searching to use according to the unit size
760 // assume the unit size is always 1x1, 2x2, 3x3 and so on
761 // i.e. sprite_info->loc_width == sprite_info->loc_height
762 //--------------------------------------------------------------------------//
763
764 result_node_recno = result_node_count = 0;
765 err_when(result_node_array!=NULL);
766
767 seek_path.set_nation_recno(nation_recno);
768
769 int seekResult;
770 #ifdef DEBUG
771 unsigned long seekPathStartTime = misc.get_time();
772 #endif
773 /*switch(sprite_info->loc_width)
774 {
775 case 1:*/
776 if(searchMode!=SEARCH_MODE_REUSE || numOfPath==1) // no need to call path_reuse
777 {
778 if(mobile_type==UNIT_LAND)
779 select_search_sub_mode(startXLocLoc, startYLocLoc, destXLoc, destYLoc, nation_recno, searchMode);
780 seekResult = seek_path.seek(startXLocLoc, startYLocLoc, destXLoc, destYLoc, unit_group_id,
781 mobile_type, searchMode, miscNo, numOfPath, unit_search_tries);
782
783 result_node_array = seek_path.get_result(result_node_count, result_path_dist);
784 seek_path.set_sub_mode(); // reset sub_mode searching
785 }
786 else // use path_reuse
787 {
788 err_when(reuseMode!=GENERAL_GROUP_MOVEMENT);
789 seekResult = seek_path_reuse.seek(startXLocLoc, startYLocLoc, destXLoc, destYLoc, 1, unit_group_id,
790 mobile_type, searchMode, miscNo, numOfPath, reuseMode, pathReuseStatus);
791 result_node_array = seek_path_reuse.get_result(result_node_count, result_path_dist);
792 }
793 #ifdef DEBUG
794 seek_path_profile_time = misc.get_time() - seekPathStartTime;
795 #endif
796 /* break;
797
798 default: err_here();
799 break;
800 }*/
801
802 if(seekResult==PATH_IMPOSSIBLE)
803 {
804 reset_path();
805 err_when(result_node_array || result_node_count);
806 }
807
808 //####### begin trevor 15/10 ########//
809
810 //-----------------------------------------------------------------------//
811 // update ignore_power_nation,seek_path_fail_count
812 //-----------------------------------------------------------------------//
813
814 if(ai_unit)
815 {
816 //----- set seek_path_fail_count ------//
817
818 if( seekResult==PATH_IMPOSSIBLE ||
819 (seekResult==PATH_NODE_USED_UP && // if all the nodes have been used up and the number of nodes original available is >= VALID_BACKGROUND_SEARCH_NODE
820 totalAvailableNode >= VALID_BACKGROUND_SEARCH_NODE) )
821 {
822 if( seek_path_fail_count < 100 ) // prevent numeric overflow
823 seek_path_fail_count++;
824 }
825 else
826 seek_path_fail_count=0;
827
828 //------- set ignore_power_nation -------//
829
830 if( seekResult==PATH_IMPOSSIBLE )
831 {
832 switch(ignore_power_nation)
833 {
834 case 0: ignore_power_nation = 1;
835 break;
836 case 1: ignore_power_nation = 2;
837 break;
838 case 2: break;
839 default: err_here();
840 break;
841 }
842 }
843 else
844 {
845 if( ignore_power_nation==1 )
846 ignore_power_nation = 0;
847 }
848 }
849
850 //######## end trevor 15/10 ########//
851
852 //-----------------------------------------------------------------------//
853 // if closest node is returned, the destination should not be the real
854 // location to go to. Thus, move_to_?_loc should be adjusted
855 //-----------------------------------------------------------------------//
856 if(result_node_array && result_node_count)
857 {
858 ResultNode* lastNode = result_node_array + result_node_count - 1;
859 move_to_x_loc = lastNode->node_x; // adjust move_to_?_loc
860 move_to_y_loc = lastNode->node_y;
861
862 result_node_recno = 1; // skip the first node which is the current location
863 if(cur_action != SPRITE_MOVE) // check if the unit is moving right now, wait until it reaches the nearest complete tile.
864 {
865 err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE && (cur_x!=next_x || cur_y!=next_y));
866 #ifdef DEBUG
867 int moveToXLoc = move_to_x_loc;
868 int moveToYLoc = move_to_y_loc;
869 #endif
870
871 ResultNode *nextNode = result_node_array + 1;
872 //set_dir(next_x_loc(), next_y_loc(), nextNode->node_x, nextNode->node_y);
873 set_dir(startXLocLoc, startYLocLoc, nextNode->node_x, nextNode->node_y);
874
875 next_move();
876
877 #ifdef DEBUG
878 err_when(move_action_call_flag && (moveToXLoc!=move_to_x_loc || moveToYLoc!=move_to_y_loc));
879 #endif
880 }
881 }
882 else // stay in the current location
883 {
884 err_when(result_node_array!=NULL);
885
886 move_to_x_loc = startXLocLoc; // adjust move_to_?_loc
887 move_to_y_loc = startYLocLoc;
888 err_when(move_to_x_loc!=startXLocLoc || move_to_y_loc!=startYLocLoc);
889
890 if(cur_x!=next_x || cur_y!=next_y)
891 set_move();
892 else
893 set_idle();
894 }
895
896 err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
897 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
898 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
899
900 //-------------------------------------------------------//
901 // PATH_NODE_USED_UP happens when:
902 // Exceed the object's MAX's node limitation, the closest path
903 // is returned. Get to the closest path first and continue
904 // to seek the path in the background.
905 //-------------------------------------------------------//
906
907 return 1;
908 }
909 //----------- End of function Unit::searching -----------//
910
911
912 //--------- Begin of function Unit::move_to_firm_surround ---------//
913 // order unit to move to firm surrounding
914 //
915 // <int> destXLoc, destYLoc - destination
916 // <int> width - unit width
917 // <int> height - unit height
918 // <int> miscNo - the firm id (default 0)
919 // <int> readyDist - similar to that in set_move_to_surround()
920 // (default 0)
921 //
922 // Note: the firm should exist in the location (destXloc, destYLoc)
923 // this function can be called by unit with size 1x1, 2x2,
924 //
move_to_firm_surround(int destXLoc,int destYLoc,int width,int height,int miscNo,int readyDist)925 void Unit::move_to_firm_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
926 {
927 err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
928
929 //----------------------------------------------------------------//
930 // calculate new destination if trying to move to different territory
931 //----------------------------------------------------------------//
932 Location *locPtr = world.get_loc(destXLoc, destYLoc);
933 if(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP && miscNo==FIRM_HARBOR)
934 {
935 err_when(!locPtr->is_firm());
936 Firm *firmPtr = firm_array[locPtr->firm_recno()];
937 FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
938 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=harborPtr->sea_region_id)
939 {
940 move_to(destXLoc, destYLoc);
941 return;
942 }
943 }
944 else
945 {
946 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
947 {
948 move_to(destXLoc, destYLoc);
949 return;
950 }
951 }
952
953 //----------------------------------------------------------------//
954 // return if the unit is dead
955 //----------------------------------------------------------------//
956 if(is_unit_dead())
957 return;
958
959 //----------------------------------------------------------------//
960 // check for equal actions
961 //----------------------------------------------------------------//
962 if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
963 {
964 //------ previous action is ACTION_MOVE -------//
965 err_when(action_para2 || action_para);
966 if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
967 {
968 //-------- equal order --------//
969 action_x_loc = action_x_loc2;
970 action_y_loc = action_y_loc2;
971
972 if(cur_action!=SPRITE_IDLE)
973 {
974 //-------- the old order is processing --------//
975 if(result_node_array==NULL) // cannot move
976 {
977 err_when(result_node_count || result_node_recno);
978 set_idle();
979 }
980
981 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
982 return;
983 }//else action is hold due to some problems, re-activiate again
984 }
985 }//else, new order or searching is required
986
987 int destX = MAX(0, ((width>1) ? destXLoc : destXLoc - width + 1));
988 int destY = MAX(0, ((height>1) ? destYLoc : destYLoc - height + 1));
989
990 FirmInfo *firmInfo = firm_res[miscNo];
991 stop();
992 set_move_to_surround(destX, destY, firmInfo->loc_width, firmInfo->loc_height, BUILDING_TYPE_FIRM_MOVE_TO, miscNo);
993
994 //----------------------------------------------------------------//
995 // store new order in action parameters
996 //----------------------------------------------------------------//
997 action_mode = action_mode2 = ACTION_MOVE;
998 action_para = action_para2 = 0;
999 action_x_loc = action_x_loc2 = move_to_x_loc;
1000 action_y_loc = action_y_loc2 = move_to_y_loc;
1001
1002 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
1003 err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
1004 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
1005 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
1006
1007 #ifdef DEBUG
1008 if(unit_res[unit_id]->unit_class!=UNIT_CLASS_SHIP || ((UnitMarine*)this)->extra_move_in_beach==NO_EXTRA_MOVE)
1009 err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
1010 #endif
1011 }
1012 //----------- End of function Unit::move_to_firm_surround -----------//
1013
1014
1015 //--------- Begin of function Unit::move_to_town_surround ---------//
1016 // move to town surrounding
1017 //
1018 // <int> destXLoc, destYLoc - destination
1019 // <int> width - unit width
1020 // <int> height - unit height
1021 // <int> miscNo - reserved (default 0)
1022 // <int> readyDist - similar to that in set_move_to_surround()
1023 // (default 0)
1024 //
1025 // Note: assume the town exists
1026 // this function can be called by unit with size 1x1, 2x2,
1027 //
move_to_town_surround(int destXLoc,int destYLoc,int width,int height,int miscNo,int readyDist)1028 void Unit::move_to_town_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
1029 {
1030 err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
1031
1032 //----------------------------------------------------------------//
1033 // calculate new destination if trying to move to different territory
1034 //----------------------------------------------------------------//
1035 Location *locPtr = world.get_loc(destXLoc, destYLoc);
1036 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
1037 {
1038 move_to(destXLoc, destYLoc);
1039 return;
1040 }
1041
1042 //----------------------------------------------------------------//
1043 // return if the unit is dead
1044 //----------------------------------------------------------------//
1045 if(is_unit_dead())
1046 return;
1047
1048 //----------------------------------------------------------------//
1049 // check for equal actions
1050 //----------------------------------------------------------------//
1051 if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
1052 {
1053 //------ previous action is ACTION_MOVE -------//
1054 err_when(action_para2 || action_para);
1055 if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
1056 {
1057 //-------- equal order --------//
1058 action_x_loc = action_x_loc2;
1059 action_y_loc = action_y_loc2;
1060
1061 if(cur_action!=SPRITE_IDLE)
1062 {
1063 //-------- the old order is processing --------//
1064 if(result_node_array==NULL) // cannot move
1065 {
1066 err_when(result_node_count || result_node_recno);
1067 set_idle();
1068 }
1069
1070 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
1071 return;
1072 }//else action is hold due to some problems, re-activiate again
1073 }
1074 }//else, new order or searching is required
1075
1076 int destX = MAX(0, ((width>1) ? destXLoc : destXLoc - width + 1));
1077 int destY = MAX(0, ((height>1) ? destYLoc : destYLoc - height + 1));
1078
1079 stop();
1080 set_move_to_surround(destX, destY, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, BUILDING_TYPE_TOWN_MOVE_TO);
1081
1082 //----------------------------------------------------------------//
1083 // store new order in action parameters
1084 //----------------------------------------------------------------//
1085 action_mode = action_mode2 = ACTION_MOVE;
1086 action_para = action_para2 = 0;
1087 action_x_loc = action_x_loc2 = move_to_x_loc;
1088 action_y_loc = action_y_loc2 = move_to_y_loc;
1089
1090 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
1091 err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
1092 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
1093 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
1094 err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
1095 }
1096 //----------- End of function Unit::move_to_town_surround -----------//
1097
1098
1099 //--------- Begin of function Unit::move_to_wall_surround ---------//
1100 // move to wall surrounding
1101 //
1102 // <int> destXLoc, destYLoc - destination
1103 // <int> width - unit width
1104 // <int> height - unit height
1105 // <int> miscNo - reserved (default 0)
1106 // <int> readyDist - similar to that in set_move_to_surround()
1107 // (default 0)
1108 //
1109 // Note: assume the wall exists
1110 // this function can be called by unit with size 1x1, 2x2,
1111 //
move_to_wall_surround(int destXLoc,int destYLoc,int width,int height,int miscNo,int readyDist)1112 void Unit::move_to_wall_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
1113 {
1114 err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
1115
1116 //----------------------------------------------------------------//
1117 // calculate new destination if trying to move to different territory
1118 //----------------------------------------------------------------//
1119 Location *locPtr = world.get_loc(destXLoc, destYLoc);
1120 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
1121 {
1122 move_to(destXLoc, destYLoc);
1123 return;
1124 }
1125
1126 //----------------------------------------------------------------//
1127 // return if the unit is dead
1128 //----------------------------------------------------------------//
1129 if(is_unit_dead())
1130 return;
1131
1132 //----------------------------------------------------------------//
1133 // check for equal actions
1134 //----------------------------------------------------------------//
1135 if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
1136 {
1137 //------ previous action is ACTION_MOVE -------//
1138 err_when(action_para2 || action_para);
1139 if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
1140 {
1141 //-------- equal order --------//
1142 action_x_loc = action_x_loc2;
1143 action_y_loc = action_y_loc2;
1144
1145 if(cur_action!=SPRITE_IDLE)
1146 {
1147 //-------- the old order is processing --------//
1148 if(result_node_array==NULL) // cannot move
1149 {
1150 err_when(result_node_count || result_node_recno);
1151 set_idle();
1152 }
1153
1154 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
1155 return;
1156 }//else action is hold due to some problems, re-activiate again
1157 }
1158 }//else, new order or searching is required
1159
1160 int destX = MAX(0, ((width>1) ? destXLoc : destXLoc - width + 1));
1161 int destY = MAX(0, ((height>1) ? destYLoc : destYLoc - height + 1));
1162
1163 stop();
1164 set_move_to_surround(destX, destY, 1, 1, BUILDING_TYPE_WALL);
1165
1166 //----------------------------------------------------------------//
1167 // store new order in action parameters
1168 //----------------------------------------------------------------//
1169 action_mode = action_mode2 = ACTION_MOVE;
1170 action_para = action_para2 = 0;
1171 action_x_loc = action_x_loc2 = move_to_x_loc;
1172 action_y_loc = action_y_loc2 = move_to_y_loc;
1173
1174 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
1175 err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
1176 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
1177 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
1178 err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
1179 }
1180 //----------- End of function Unit::move_to_wall_surround -----------//
1181
1182
1183 //--------- Begin of function Unit::move_to_unit_surround ---------//
1184 // move to unit surrounding
1185 //
1186 // <int> destXLoc, destYLoc - destination
1187 // <int> width - unit width
1188 // <int> height - unit height
1189 // <int> miscNo - vehicle unit_recno (default 0)
1190 // <int> readyDist - similar to that in set_move_to_surround()
1191 // (default 0)
1192 //
1193 // Note: assume the vehicle exists
1194 // this function can be called by unit with size 1x1, 2x2,
1195 //
move_to_unit_surround(int destXLoc,int destYLoc,int width,int height,int miscNo,int readyDist)1196 void Unit::move_to_unit_surround(int destXLoc, int destYLoc, int width, int height, int miscNo, int readyDist)
1197 {
1198 err_when(destXLoc<0 || destXLoc>=MAX_WORLD_X_LOC || destYLoc<0 || destYLoc>=MAX_WORLD_Y_LOC);
1199
1200 //----------------------------------------------------------------//
1201 // calculate new destination if trying to move to different territory
1202 //----------------------------------------------------------------//
1203 Location *locPtr = world.get_loc(destXLoc, destYLoc);
1204 if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=locPtr->region_id)
1205 {
1206 move_to(destXLoc, destYLoc);
1207 return;
1208 }
1209
1210 //----------------------------------------------------------------//
1211 // return if the unit is dead
1212 //----------------------------------------------------------------//
1213 if(is_unit_dead())
1214 return;
1215
1216 //----------------------------------------------------------------//
1217 // check for equal actions
1218 //----------------------------------------------------------------//
1219 if(action_mode2==ACTION_MOVE && action_mode==ACTION_MOVE)
1220 {
1221 //------ previous action is ACTION_MOVE -------//
1222 err_when(action_para2 || action_para);
1223 if(action_x_loc2==destXLoc && action_y_loc2==destYLoc)
1224 {
1225 //-------- equal order --------//
1226 action_x_loc = action_x_loc2;
1227 action_y_loc = action_y_loc2;
1228
1229 if(cur_action!=SPRITE_IDLE)
1230 {
1231 //-------- the old order is processing --------//
1232 if(result_node_array==NULL) // cannot move
1233 {
1234 err_when(result_node_count || result_node_recno);
1235 set_idle();
1236 }
1237
1238 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
1239 return;
1240 }//else action is hold due to some problems, re-activiate again
1241 }
1242 }//else, new order or searching is required
1243
1244 int destX = MAX(0, ((width>1) ? destXLoc : destXLoc - width + 1));
1245 int destY = MAX(0, ((height>1) ? destYLoc : destYLoc - height + 1));
1246
1247 err_when(unit_array.is_deleted(miscNo));
1248 Unit *unitPtr = unit_array[miscNo];
1249 SpriteInfo *spriteInfo = unitPtr->sprite_info;
1250 stop();
1251 set_move_to_surround(destX, destY, spriteInfo->loc_width, spriteInfo->loc_height, BUILDING_TYPE_VEHICLE);
1252
1253 //----------------------------------------------------------------//
1254 // store new order in action parameters
1255 //----------------------------------------------------------------//
1256 action_mode = action_mode2 = ACTION_MOVE;
1257 action_para = action_para2 = 0;
1258 action_x_loc = action_x_loc2 = move_to_x_loc;
1259 action_y_loc = action_y_loc2 = move_to_y_loc;
1260
1261 err_when(action_mode==ACTION_MOVE && (action_x_loc==-1 || action_y_loc==-1));
1262 err_when(move_to_x_loc<0 || move_to_x_loc>=MAX_WORLD_X_LOC || move_to_y_loc<0 || move_to_y_loc>=MAX_WORLD_Y_LOC);
1263 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
1264 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
1265 err_when(result_node_array==NULL && (next_x!=go_x || next_y!=go_y));
1266 }
1267 //----------- End of function Unit::move_to_unit_surround -----------//
1268
1269
1270 //--------- Begin of function Unit::different_territory_destination ---------//
1271 // calculate a reachable destination if the unit is ordered to move to unreachable
1272 // location on different territory
1273 //
1274 // <int&> destX, destY - reference to return destination
1275 //
different_territory_destination(int & destX,int & destY)1276 void Unit::different_territory_destination(int& destX, int& destY)
1277 {
1278 int curXLoc = next_x_loc();
1279 int curYLoc = next_y_loc();
1280
1281 Location *locPtr = world.get_loc(curXLoc, curYLoc);
1282 int regionId = locPtr->region_id;
1283 int xStep = destX-curXLoc;
1284 int yStep = destY-curYLoc;
1285 int absXStep = abs(xStep);
1286 int absYStep = abs(yStep);
1287 int count = (absXStep>=absYStep) ? absXStep : absYStep;
1288 int x, y;
1289 long int sameTerr = 0;
1290
1291 //------------------------------------------------------------------------------//
1292 // draw a line from the unit location to the destination, find the last location
1293 // with the same region id.
1294 //------------------------------------------------------------------------------//
1295 for(long int i=1; i<=count; i++)
1296 {
1297 x = curXLoc + int((i*xStep)/count);
1298 y = curYLoc + int((i*yStep)/count);
1299
1300 locPtr = world.get_loc(x, y);
1301 if(locPtr->region_id==regionId)
1302 sameTerr = i;
1303 }
1304
1305 if(sameTerr)
1306 {
1307 destX = curXLoc + int((sameTerr*xStep)/count);
1308 destY = curYLoc + int((sameTerr*yStep)/count);
1309 }
1310 else
1311 {
1312 destX = curXLoc;
1313 destY = curYLoc;
1314 }
1315 }
1316 //----------- End of function Unit::different_territory_destination -----------//
1317
1318
1319 //--------- Begin of function Unit::next_move ---------//
1320 //
1321 // If there is unprocessed node(s) in the result_node_array,
1322 // then next unprocessed node will be set to be the next location
1323 // to move to. (i.e. go_? = location of the unprocessed node)
1324 //
next_move()1325 void Unit::next_move()
1326 {
1327 if(result_node_array == NULL || !result_node_count || !result_node_recno)
1328 return;
1329
1330 if( ++result_node_recno > result_node_count )
1331 {
1332 //------------ all nodes are visited --------------//
1333 err_when(cur_x!=next_x || cur_y!=next_y);
1334 err_when(next_x_loc()!=move_to_x_loc || next_y_loc()!=move_to_y_loc);
1335
1336 mem_del(result_node_array);
1337 result_node_array = NULL;
1338 set_idle();
1339
1340 if(action_mode2==ACTION_MOVE) //--------- used to terminate action_mode==ACTION_MOVE
1341 {
1342 force_move_flag = 0;
1343
1344 //------- reset ACTION_MOVE parameters ------//
1345 reset_action_para();
1346 if(move_to_x_loc==action_x_loc2 && move_to_y_loc==action_y_loc2)
1347 reset_action_para2();
1348 }
1349 return;
1350 }
1351
1352 //---- order the unit to move to the next checkpoint following the path ----//
1353
1354 ResultNode* resultNode = result_node_array+result_node_recno-1;
1355 #ifdef DEBUG
1356 err_when(cur_x==move_to_x_loc*ZOOM_LOC_WIDTH && cur_y==move_to_y_loc*ZOOM_LOC_HEIGHT);
1357 err_when(!resultNode);
1358 #endif
1359
1360 sprite_move( resultNode->node_x*ZOOM_LOC_WIDTH, resultNode->node_y*ZOOM_LOC_HEIGHT );
1361
1362 err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
1363 }
1364 //----------- End of function Unit::next_move -----------//
1365
1366
1367 //--------- Begin of function Unit::reset_path ---------//
1368 // Cancel all movement.
1369 //
reset_path()1370 void Unit::reset_path()
1371 {
1372 if( result_node_array )
1373 {
1374 mem_del(result_node_array);
1375 result_node_array = NULL;
1376 }
1377
1378 result_path_dist = result_node_count = result_node_recno = 0;
1379 }
1380 //----------- End of function Unit::reset_path -----------//
1381
1382
1383 //--------- Begin of function Unit::pre_process ---------//
1384 // process unit's action
1385 //
pre_process()1386 void Unit::pre_process()
1387 {
1388 //-*********** simulate aat ************-//
1389 #ifdef DEBUG
1390 if(debug_sim_game_type==2)
1391 {
1392 if(hit_points!=max_hit_points)
1393 hit_points = max_hit_points;
1394
1395 Nation *nationPtr = nation_array[nation_recno];
1396 if(nationPtr->cash<4000)
1397 nationPtr->cash += 10000;
1398
1399 if(nationPtr->food<4000)
1400 nationPtr->food += 10000;
1401 }
1402 #endif
1403 //-*********** simulate aat ************-//
1404
1405 #if defined(DEBUG) && defined(ENABLE_LOG)
1406 String logStr;
1407 logStr = " begin unit ";
1408 logStr += sprite_recno;
1409 // ########## begin Gilbert 6/9 #######//
1410 logStr += " nation=";
1411 logStr += nation_recno;
1412 logStr += "(";
1413 logStr += true_nation_recno();
1414 logStr += ")";
1415 // ########## end Gilbert 6/9 #######//
1416 logStr += " pre_process(), action_mode=";
1417 logStr += action_mode;
1418 logStr += " action_mode2=";
1419 logStr += action_mode2;
1420 LOG_MSG(logStr);
1421
1422 logStr = "action_para=";
1423 logStr += action_para;
1424 logStr += " action_para2=";
1425 logStr += action_para2;
1426 logStr += " cur_action=";
1427 logStr += cur_action;
1428 logStr += " cur_x/y=";
1429 logStr += cur_x;
1430 logStr += "/";
1431 logStr += cur_y;
1432 logStr += " next_x/y=";
1433 logStr += next_x;
1434 logStr += "/";
1435 logStr += next_y;
1436
1437 LOG_MSG(logStr);
1438 #endif
1439
1440 //------ if all the hit points are lost, die now ------//
1441 if(hit_points <= 0 && action_mode != ACTION_DIE)
1442 {
1443 set_die();
1444
1445 if(ai_action_id)
1446 nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
1447
1448 return;
1449 }
1450
1451 #ifdef DEBUG
1452 int debugActionMode = action_mode;
1453 int debugActionPatra = action_para;
1454 int debugCurAction = cur_action;
1455 #endif
1456
1457 if( config.fog_of_war )
1458 {
1459 if( is_own() ||
1460 (nation_recno && nation_array[nation_recno]->is_allied_with_player) )
1461 {
1462 world.visit(next_x_loc(), next_y_loc(), next_x_loc()+sprite_info->loc_width-1,
1463 next_y_loc()+sprite_info->loc_height-1, unit_res[unit_id]->visual_range,
1464 unit_res[unit_id]->visual_extend);
1465 }
1466 }
1467
1468 //--------- process action corresponding to action_mode ----------//
1469
1470 #ifdef DEBUG
1471 unsigned long startTime;
1472 #endif
1473
1474 switch(action_mode)
1475 {
1476 case ACTION_ATTACK_UNIT:
1477
1478 #ifdef DEBUG
1479 startTime = misc.get_time();
1480 #endif
1481
1482 //------------------------------------------------------------------//
1483 // if unit is in defense mode, check situation to follow the target
1484 // or return back to camp
1485 //------------------------------------------------------------------//
1486 if(action_mode!=action_mode2)
1487 {
1488 if(action_mode2==ACTION_AUTO_DEFENSE_ATTACK_TARGET)
1489 {
1490 if(!defense_follow_target()) // false if abort attacking
1491 break; // cancel attack and go back to military camp
1492 }
1493 else if(action_mode2==ACTION_DEFEND_TOWN_ATTACK_TARGET)
1494 {
1495 if(!defend_town_follow_target())
1496 break;
1497 }
1498 else if(action_mode2==ACTION_MONSTER_DEFEND_ATTACK_TARGET)
1499 {
1500 if(!monster_defend_follow_target())
1501 break;
1502 }
1503 else
1504 err_here();
1505 }
1506
1507 process_attack_unit();
1508
1509 #ifdef DEBUG
1510 unit_attack_profile_time += misc.get_time() - startTime;
1511 #endif
1512 break;
1513
1514 case ACTION_ATTACK_FIRM:
1515 process_attack_firm();
1516 break;
1517
1518 case ACTION_ATTACK_TOWN:
1519 process_attack_town();
1520 break;
1521
1522 case ACTION_ATTACK_WALL:
1523 process_attack_wall();
1524 break;
1525
1526 case ACTION_ASSIGN_TO_FIRM:
1527 case ACTION_ASSIGN_TO_TOWN:
1528 case ACTION_ASSIGN_TO_VEHICLE:
1529 #ifdef DEBUG
1530 startTime = misc.get_time();
1531 #endif
1532 process_assign();
1533 #ifdef DEBUG
1534 unit_assign_profile_time += misc.get_time() - startTime;
1535 #endif
1536 break;
1537
1538 case ACTION_ASSIGN_TO_SHIP:
1539 process_assign_to_ship();
1540 break;
1541
1542 case ACTION_BUILD_FIRM:
1543 process_build_firm();
1544 break;
1545
1546 case ACTION_BURN:
1547 process_burn();
1548 break;
1549
1550 case ACTION_SETTLE:
1551 process_settle();
1552 break;
1553
1554 case ACTION_SHIP_TO_BEACH:
1555 process_ship_to_beach();
1556 break;
1557
1558 case ACTION_GO_CAST_POWER:
1559 process_go_cast_power();
1560 break;
1561 }
1562
1563 //-****** don't add code here, the unit may be removed after the above function call*******-//
1564
1565 // ###### begin Gilbert 20/6 ########//
1566 #ifdef DEBUG
1567 // do not read data member
1568 LOG_MSG( " end Unit::pre_process()" );
1569 LOG_MSG( misc.get_random_seed() );
1570 #endif
1571 // ###### end Gilbert 20/6 ########//
1572
1573 }
1574 //----------- End of function Unit::pre_process -----------//
1575
1576
1577 //--------- Begin of function Unit::process_die ---------//
1578 // process unit die
1579 //
1580 // return 1 if die frame is counting
1581 // return 0 otherwise
1582 //
process_die()1583 int Unit::process_die()
1584 {
1585 //-*********** simulate aat ************-//
1586 #ifdef DEBUG
1587 if(debug_sim_game_type)
1588 {
1589 cur_action = SPRITE_IDLE;
1590 hit_points = max_hit_points;
1591 stop2();
1592 return 0;
1593 }
1594 #endif
1595 //-*********** simulate aat ************-//
1596
1597 //--------- voice ------------//
1598 se_res.sound(cur_x_loc(), cur_y_loc(), cur_frame, 'S',sprite_id,"DIE");
1599
1600 // ####### begin Gilbert 14/7 ###########//
1601 //------------- add die effect on first frame --------- //
1602 if( cur_frame == 1 && unit_res[unit_id]->die_effect_id)
1603 {
1604 Effect::create(unit_res[unit_id]->die_effect_id, cur_x, cur_y,
1605 SPRITE_DIE, cur_dir, mobile_type == UNIT_AIR ? 8 : 2, 0);
1606 }
1607 // ####### end Gilbert 14/7 ###########//
1608
1609 //--------- next frame ---------//
1610 if( ++cur_frame > sprite_info->die.frame_count )
1611 return 1;
1612
1613 return 0;
1614 }
1615 //----------- End of function Unit::process_die -----------//
1616
1617
1618 //--------- Begin of function Unit::process_rebel ---------//
1619 //
1620 // Unit::process_rebel() is in OREBEL.CPP
1621 //
1622 //----------- End of function Unit::process_rebel ---------//
1623
1624
1625 //--------- Begin of function Unit::avail_node_enough_for_search --------//
1626 // decide whether the available number of nodes enough for a valid path searching
1627 //
1628 // <short> x1, y1 - start location
1629 // <short> x2, y2 - end location
1630 //
1631 // return 1 if num of nodes is enough
1632 // return 0 otherwise
1633 //
avail_node_enough_for_search(short x1,short y1,short x2,short y2)1634 int Unit::avail_node_enough_for_search(short x1, short y1, short x2, short y2)
1635 {
1636 short dispX = abs(x1-x2);
1637 short dispY = abs(y1-y2);
1638
1639 short majDist = dispX>dispY ? dispX : dispY;
1640 short minDist = abs(dispX-dispY);
1641
1642 int nodeRequire = MIN(VALID_BACKGROUND_SEARCH_NODE, majDist<<5); // *32
1643 int totalNode = seek_path.total_node_avail;
1644 if(totalNode < nodeRequire)
1645 {
1646 if(totalNode>=MIN_BACKGROUND_NODE_USED_UP)
1647 seek_path.total_node_avail = MIN_BACKGROUND_NODE_USED_UP-1;
1648
1649 return 0;
1650 }
1651
1652 return 1;
1653 }
1654 //----------- End of function Unit::avail_node_enough_for_search -----------//
1655
1656
1657 //--------- Begin of function Unit::process_move --------//
1658 // process unit movement
1659 //
process_move()1660 void Unit::process_move()
1661 {
1662 //----- if the sprite has reach the destintion ----//
1663
1664 //--------------------------------------------------------//
1665 // if the unit reach its destination, then
1666 // cur_? == next_? == go_?
1667 //--------------------------------------------------------//
1668 err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
1669
1670 if(cur_x==go_x && cur_y==go_y)
1671 {
1672 if(result_node_array)
1673 {
1674 next_move();
1675 if( cur_action != SPRITE_MOVE ) // if next_move() is not successful, the movement has been stopped
1676 return;
1677
1678 //---------------------------------------------------------------------------//
1679 // If (1) the unit is blocked at cur_? == go_? and go_? != destination and
1680 // (2) a new path is generated if calling the previous next_move(),
1681 // then cur_? still equal to go_?.
1682 //
1683 // The following Sprite::process_move() call will set the unit to SPRITE_IDLE
1684 // since cur_? == go_?. Thus, the unit terminates its move although it has not
1685 // reached its destination.
1686 //
1687 // (note: if it has reached its destination, cur_? == go_? and cur_action =
1688 // SPRITE_IDLE)
1689 //
1690 // if the unit is still moving and cur_? == go_?, call next_move() again to reset
1691 // the go_?.
1692 //---------------------------------------------------------------------------//
1693 if(cur_action==SPRITE_MOVE && cur_x==go_x && cur_y==go_y)
1694 next_move();
1695 }
1696 }
1697
1698 err_when(result_node_array && result_node_count==result_node_recno &&
1699 (result_node_array[result_node_count-1].node_x!=go_x>>ZOOM_X_SHIFT_COUNT ||
1700 result_node_array[result_node_count-1].node_y!=go_y>>ZOOM_Y_SHIFT_COUNT));
1701
1702 //--------- process the move, update sprite position ---------//
1703 //--------------------------------------------------------//
1704 // if the unit is moving, cur_?!=go_? and
1705 // if next_? != cur_?, the direction from cur_? to next_?
1706 // should equal to that from cur_? to go_?
1707 //--------------------------------------------------------//
1708 err_when((cur_x%ZOOM_LOC_WIDTH==0 && cur_y%ZOOM_LOC_HEIGHT==0) && (cur_x!=next_x || cur_y!=next_y) &&
1709 ((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, next_x, next_y))));
1710
1711 #ifdef DEBUG
1712 int debugCurX = cur_x;
1713 int debugCurY = cur_y;
1714 int debugNextX = next_x;
1715 int debugNextY = next_y;
1716 int debugGoX = go_x;
1717 int debugGoY = go_y;
1718 #endif
1719 err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));
1720 err_when(result_path_dist && result_node_array==NULL);
1721
1722 Sprite::process_move();
1723
1724 err_when( cur_x < 0 || cur_y < 0 || cur_x >= ZOOM_X_PIXELS || cur_y >= ZOOM_Y_PIXELS );
1725 if(cur_x==go_x && cur_y==go_y && cur_action==SPRITE_IDLE) // the sprite has reached its destination
1726 {
1727 move_to_x_loc = next_x_loc();
1728 move_to_y_loc = next_y_loc();
1729 }
1730
1731 //--------------------------------------------------------//
1732 // after Sprite::process_move(), if the unit is blocked, its
1733 // cur_action is set to SPRITE_WAIT. Otherwise, its cur_action
1734 // is still SPRITE_MOVE. Then cur_? != next_? if the unit
1735 // has not reached its destination.
1736 //--------------------------------------------------------//
1737 err_when(cur_action==SPRITE_MOVE && (cur_x!=go_x || cur_y!=go_y) && (cur_x==next_x && cur_y==next_y));
1738 }
1739 //---------- End of function Unit::process_move ----------//
1740
1741
1742 //--------- Begin of function Unit::process_wait ---------//
1743 // process unit's waiting
1744 //
process_wait()1745 void Unit::process_wait()
1746 {
1747 err_when((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=final_dir);
1748 if(!match_dir())
1749 return;
1750
1751 //-----------------------------------------------------//
1752 // If the unit is moving to the destination and was
1753 // blocked by something. If it is now no longer blocked,
1754 // continue the movement.
1755 //-----------------------------------------------------//
1756 //
1757 // When this funciton is called:
1758 //
1759 // (next_x, next_y)==(cur_x, cur_y), it's the location of the sprite.
1760 //
1761 //-----------------------------------------------------//
1762
1763 //--- find out the next location which the sprite should be moving towards ---//
1764
1765 //-----------------------------------------------------//
1766 // If the unit is waiting,
1767 // go_? != cur_?
1768 // go_? != next_?
1769 //
1770 // If the unit is not under swapping, the next_?_loc()
1771 // is always the move_to_?_loc. Thus, the unit is ordered
1772 // to stop.
1773 //-----------------------------------------------------//
1774 err_when( (go_x>>ZOOM_X_SHIFT_COUNT!=move_to_x_loc || go_y>>ZOOM_Y_SHIFT_COUNT!=move_to_y_loc) &&
1775 ( (cur_x==go_x && cur_y==go_y) || (cur_x!=next_x || cur_y!=next_y) ) );
1776
1777 if(next_x_loc()==move_to_x_loc && next_y_loc()==move_to_y_loc && !swapping)
1778 {
1779 terminate_move();
1780 return; // terminate since already in destination
1781 }
1782
1783 int stepMagn = move_step_magn();
1784 int nextX = cur_x+stepMagn*move_x_pixel_array[final_dir];
1785 int nextY = cur_y+stepMagn*move_y_pixel_array[final_dir];
1786
1787 /*short w, h, blocked=0;
1788 short x, y, blockedX, blockedY;
1789 Location* locPtr;
1790
1791 //---------- check whether the unit is blocked -----------//
1792 for(h=0, y=nextY>>ZOOM_Y_SHIFT_COUNT; h<sprite_info->loc_height && !blocked; h++, y++)
1793 {
1794 for(w=0, x=nextX>>ZOOM_X_SHIFT_COUNT; w<sprite_info->loc_width && !blocked; w++, x++)
1795 {
1796 locPtr = world.get_loc(x, y);
1797 blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
1798 locPtr->unit_recno(mobile_type)!=sprite_recno) );
1799
1800 if(blocked)
1801 {
1802 blockedX = x;
1803 blockedY = y;
1804 }
1805 }
1806 }*/
1807 short x = nextX>>ZOOM_X_SHIFT_COUNT;
1808 short y = nextY>>ZOOM_Y_SHIFT_COUNT;
1809 Location *locPtr = world.get_loc(x, y);
1810 short blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
1811 locPtr->unit_recno(mobile_type)!=sprite_recno) );
1812
1813 if(!blocked || move_action_call_flag)
1814 {
1815 //--------- not blocked, continue to move --------//
1816 waiting_term = 0;
1817 set_move();
1818 cur_frame = 1;
1819 set_next(nextX, nextY, -stepMagn, 1);
1820 }
1821 else
1822 {
1823 //------- blocked, call handle_blocked_move() ------//
1824 //locPtr = world.get_loc(blockedX, blockedY);
1825 err_when(cur_x!=next_x || cur_y!=next_y);
1826 handle_blocked_move(locPtr);
1827 }
1828
1829 err_when(cur_action==SPRITE_MOVE && (cur_x!=go_x || cur_y!=go_y) && (cur_x==next_x && cur_y==next_y));
1830 err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
1831 }
1832 //----------- End of function Unit::process_wait -----------//
1833
1834
1835 //--------- Begin of function Unit::set_next --------//
1836 // set the next coordinates to move to
1837 //
1838 // <int> newNextX, newNextY - next coordinate to move to
1839 // <int> para - used to count the result_path_dist
1840 // <int> blockedChecked - whether the next location specified is checked to be
1841 // non-blocked. 1 checked for non-blocked, 0 for not checked
1842 //
set_next(int newNextX,int newNextY,int para,int blockedChecked)1843 void Unit::set_next(int newNextX, int newNextY, int para, int blockedChecked)
1844 {
1845 int curNextXLoc = next_x_loc();
1846 int curNextYLoc = next_y_loc();
1847 int newNextXLoc = newNextX >> ZOOM_X_SHIFT_COUNT;
1848 int newNextYLoc = newNextY >> ZOOM_Y_SHIFT_COUNT;
1849
1850 #ifdef DEBUG
1851 int debugStepMagn = move_step_magn();
1852 err_when(abs(curNextXLoc-newNextXLoc)>debugStepMagn || abs(curNextYLoc-newNextYLoc)>debugStepMagn);
1853 #endif
1854
1855 if(curNextXLoc!=newNextXLoc || curNextYLoc!=newNextYLoc)
1856 {
1857 if(!match_dir())
1858 {
1859 set_wait();
1860 return;
1861 }
1862 }
1863
1864 //short w, h, blocked=0;
1865 //short x, y, blockedX, blockedY;
1866 short w, h, blocked=0;
1867 short x, y;
1868
1869 #ifdef DEBUG
1870 for(h=0, y=curNextYLoc; h<sprite_info->loc_height; h++, y++)
1871 for(w=0, x=curNextXLoc; w<sprite_info->loc_width; w++, x++)
1872 err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno ); // it must be 0 to put the sprite in this location
1873 #endif
1874
1875 if( curNextXLoc != newNextXLoc || curNextYLoc != newNextYLoc )
1876 {
1877 //------- if the next location is blocked ----------//
1878
1879 Location* locPtr;
1880 if(!blockedChecked)
1881 {
1882 /*for(h=0, y=newNextYLoc; h<sprite_info->loc_height && !blocked; h++, y++)
1883 {
1884 for(w=0, x=newNextXLoc; w<sprite_info->loc_width && !blocked; w++, x++)
1885 {
1886 locPtr = world.get_loc(x, y);
1887 blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
1888 locPtr->unit_recno(mobile_type)!=sprite_recno) );
1889
1890 if(blocked)
1891 {
1892 blockedX = x;
1893 blockedY = y;
1894 }
1895 }
1896 }*/
1897 x = newNextXLoc;
1898 y = newNextYLoc;
1899 locPtr = world.get_loc(x, y);
1900 blocked = ( (!locPtr->is_accessible(mobile_type)) || (locPtr->has_unit(mobile_type) &&
1901 locPtr->unit_recno(mobile_type)!=sprite_recno) );
1902 }//else, then blockedChecked = 0
1903
1904 //--- no change to next_x & next_y if the new next location is blocked ---//
1905
1906 if(blocked)
1907 {
1908 set_cur(next_x, next_y); // align the sprite to 32x32 location when it stops
1909
1910 //------ avoid infinitely looping in calling handle_blocked_move() ------//
1911 if(blocked_by_member || move_action_call_flag)
1912 {
1913 set_wait();
1914 blocked_by_member = 0;
1915 }
1916 else
1917 {
1918 locPtr = world.get_loc(x, y);
1919 handle_blocked_move(locPtr);
1920 }
1921
1922 #ifdef DEBUG
1923 for(h=0, y=next_y_loc(); h<sprite_info->loc_height; h++, y++)
1924 {
1925 for(w=0, x=next_x_loc(); w<sprite_info->loc_width; w++, x++)
1926 err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno ); // it must be 0 to put the sprite in this location
1927 }
1928 #endif
1929 }
1930 else
1931 {
1932 err_when(mobile_type!=UNIT_LAND && (abs(para)!=2 || result_path_dist%2));
1933 if(para)
1934 {
1935 #ifdef DEBUG
1936 int count=0, ii;
1937 int dist;
1938 int curXLoc = next_x_loc();
1939 int curYLoc = next_y_loc();
1940 ResultNode *curNode = result_node_array + result_node_recno -1;
1941 ResultNode *nextNode;
1942
1943 dist = misc.points_distance(curXLoc, curYLoc, curNode->node_x, curNode->node_y);
1944 if(result_node_recno>1)
1945 count += dist;
1946 else
1947 count -= dist;
1948
1949 for(ii=result_node_recno, nextNode=curNode+1; ii<result_node_count; ii++, curNode++, nextNode++)
1950 {
1951 dist = misc.points_distance(nextNode->node_x, nextNode->node_y, curNode->node_x, curNode->node_y);
1952 count += dist;
1953 }
1954
1955 err_when(result_path_dist!=count);
1956 #endif
1957
1958 //----------------------------------------------------------------------------//
1959 // calculate the result_path_dist as the unit move from one tile to another
1960 //----------------------------------------------------------------------------//
1961 result_path_dist += para;
1962 }
1963
1964 next_x = newNextX;
1965 next_y = newNextY;
1966
1967 swapping = blocked_by_member = 0;
1968
1969 //---- move sprite_recno to the next location ------//
1970
1971 for(h=0, y=curNextYLoc; h<sprite_info->loc_height; h++, y++)
1972 {
1973 for(w=0, x=curNextXLoc; w<sprite_info->loc_width; w++, x++)
1974 world.set_unit_recno(x, y, mobile_type, 0);
1975 }
1976
1977 for(h=0, y=next_y_loc(); h<sprite_info->loc_height; h++, y++)
1978 {
1979 for(w=0, x=next_x_loc(); w<sprite_info->loc_width; w++, x++)
1980 world.set_unit_recno(x, y, mobile_type, sprite_recno);
1981 }
1982
1983 //--------- explore land ----------//
1984
1985 // ###### begin Gilbert 24/5 ######//
1986 if( !config.explore_whole_map && is_own() )
1987 // ###### end Gilbert 24/5 ######//
1988 {
1989 int xLoc1 = MAX(0,newNextXLoc-EXPLORE_RANGE);
1990 int yLoc1 = MAX(0,newNextYLoc-EXPLORE_RANGE);
1991 int xLoc2 = MIN(MAX_WORLD_X_LOC-1, newNextXLoc+EXPLORE_RANGE);
1992 int yLoc2 = MIN(MAX_WORLD_Y_LOC-1, newNextYLoc+EXPLORE_RANGE);
1993 int exploreWidth = move_step_magn()-1;
1994
1995 if( newNextYLoc < curNextYLoc ) // if move upwards, explore upper area
1996 world.explore(xLoc1, yLoc1, xLoc2, yLoc1+exploreWidth);
1997
1998 else if( newNextYLoc > curNextYLoc ) // if move downwards, explore lower area
1999 world.explore(xLoc1, yLoc2-exploreWidth, xLoc2, yLoc2);
2000
2001 if( newNextXLoc < curNextXLoc ) // if move towards left, explore left area
2002 world.explore(xLoc1, yLoc1, xLoc1+exploreWidth, yLoc2);
2003
2004 else if( newNextXLoc > curNextXLoc ) // if move towards right, explore right area
2005 world.explore(xLoc2-exploreWidth, yLoc1, xLoc2, yLoc2);
2006 }
2007 }
2008 }
2009
2010 err_when(cur_x!=next_x && cur_y!=next_y && // is not blocked
2011 (check_unit_dir1=get_dir(cur_x, cur_y, next_x, next_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, go_x, go_y)));
2012 }
2013 //---------- End of function Unit::set_next ----------//
2014
2015
2016 //------ Begin of function Unit::blocked_move_new_handle -------//
2017 /*int Unit::blocked_move_new_handle()
2018 {
2019 //------------------------------------------------------------------//
2020 // new handling for blocked move
2021 //------------------------------------------------------------------//
2022 static int counter = 0;
2023 int checkXLoc1, checkYLoc1, checkXLoc2, checkYLoc2;
2024 int curXLoc = next_x_loc(), curYLoc = next_y_loc();
2025 Location *locPtr;
2026
2027 counter++;
2028 switch(final_dir)
2029 {
2030 case DIR_N:
2031 checkXLoc1 = MIN(curXLoc+1, MAX_WORLD_X_LOC-1);
2032 checkYLoc1 = checkYLoc2 = MAX(curYLoc-1, 0);
2033 checkXLoc2 = MAX(curXLoc-1, 0);
2034 break;
2035
2036 case DIR_NE:
2037 checkXLoc1 = MIN(curXLoc+1, MAX_WORLD_X_LOC-1);
2038 checkYLoc1 = curYLoc;
2039 checkXLoc2 = curXLoc;
2040 checkYLoc2 = MAX(curYLoc-1, 0);
2041 break;
2042
2043 case DIR_E:
2044 checkXLoc1 = checkXLoc2 = MIN(curXLoc+1, MAX_WORLD_X_LOC-1);
2045 checkYLoc1 = MIN(curYLoc+1, MAX_WORLD_Y_LOC-1);
2046 checkYLoc2 = MAX(curYLoc-1, 0);
2047 break;
2048
2049 case DIR_SE:
2050 checkXLoc1 = curXLoc;
2051 checkYLoc1 = MIN(curYLoc+1, MAX_WORLD_Y_LOC-1);
2052 checkXLoc2 = MIN(curXLoc+1, MAX_WORLD_X_LOC-1);
2053 checkYLoc2 = curYLoc;
2054 break;
2055
2056 case DIR_S:
2057 checkXLoc1 = MAX(curXLoc-1, 0);
2058 checkYLoc1 = checkYLoc2 = MIN(curYLoc+1, MAX_WORLD_Y_LOC-1);
2059 checkXLoc2 = MIN(curXLoc+1, MAX_WORLD_X_LOC-1);
2060 break;
2061
2062 case DIR_SW:
2063 checkXLoc1 = MAX(curXLoc-1, 0);
2064 checkYLoc1 = curYLoc;
2065 checkXLoc2 = curXLoc;
2066 checkYLoc2 = MIN(curYLoc, MAX_WORLD_Y_LOC-1);
2067 break;
2068
2069 case DIR_W:
2070 checkXLoc1 = checkXLoc2 = MAX(curXLoc-1, 0);
2071 checkYLoc1 = MAX(curYLoc-1, 0);
2072 checkYLoc2 = MIN(curYLoc+1, MAX_WORLD_Y_LOC-1);
2073 break;
2074
2075 case DIR_NW:
2076 checkXLoc1 = curXLoc;
2077 checkYLoc1 = MAX(curYLoc-1, 0);
2078 checkXLoc2 = MAX(curXLoc-1, 0);
2079 checkYLoc2 = curYLoc;
2080 break;
2081 }
2082
2083 locPtr = world.get_loc(checkXLoc1, checkYLoc1);
2084 if(locPtr->can_move(mobile_type))
2085 set_path_to(checkXLoc1, checkYLoc1);
2086 else
2087 {
2088 locPtr = world.get_loc(checkXLoc2, checkYLoc2);
2089 if(locPtr->can_move(mobile_type))
2090 set_path_to(checkXLoc2, checkYLoc2);
2091 else
2092 return 0;
2093 }
2094
2095 return 1;
2096 }*/
2097 //------- End of function Unit::blocked_move_new_handle --------//
2098
2099
2100 //------ Begin of function Unit::set_path_to -------//
2101 /*void Unit::set_path_to(int destXLoc, int destYLoc)
2102 {
2103 //reset_path();
2104 terminate_move();
2105 result_node_array = (ResultNode*) mem_add(2*sizeof(ResultNode));
2106 ResultNode *curNodePtr = result_node_array;
2107 curNodePtr->node_x = next_x_loc();
2108 curNodePtr->node_y = next_y_loc();
2109 curNodePtr++;
2110 curNodePtr->node_x = destXLoc;
2111 curNodePtr->node_y = destYLoc;
2112
2113 result_node_count = 2;
2114 result_node_recno = 1;
2115 result_path_dist = 1;
2116 move_to_x_loc = destXLoc;
2117 move_to_y_loc = destYLoc;
2118 go_x = destXLoc*ZOOM_LOC_WIDTH;
2119 go_y = destYLoc*ZOOM_LOC_HEIGHT;
2120
2121 //set_dir(cur_x, cur_y, go_x, go_y);
2122 //set_wait();
2123 next_move();
2124 }*/
2125 //------- End of function Unit::set_path_to --------//
2126
2127
2128 //------ Begin of function Unit::handle_blocked_move -------//
2129 // Note: it assumes the given location is blocked, it makes no
2130 // further attempt to verify it.
2131 //
2132 // <Location*> blockedLoc - blocked location
2133 //
2134 // return : <int> 1 - handled successfully
2135 // 0 - cannot be handled, the movement must be terminated
2136 //
handle_blocked_move(Location * blockedLoc)2137 void Unit::handle_blocked_move(Location* blockedLoc)
2138 {
2139 //--- check if the tile we are moving at is blocked by a building ---//
2140 if(blockedLoc->is_firm() || blockedLoc->is_town() || blockedLoc->is_wall())
2141 {
2142 //------------------------------------------------//
2143 // firm/town/wall is on the blocked location
2144 //------------------------------------------------//
2145 reset_path();
2146 search_or_stop(move_to_x_loc, move_to_y_loc, 1);
2147 //search(move_to_x_loc, move_to_y_loc, 1);
2148 return;
2149 }
2150
2151 if(next_x_loc()==move_to_x_loc && next_y_loc()==move_to_y_loc && !swapping)
2152 {
2153 terminate_move(); // terminate since already reaching destination
2154 return;
2155 }
2156
2157 if(!blockedLoc->is_accessible(mobile_type))
2158 {
2159 terminate_move(); // the location is not accessible
2160 err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
2161 return;
2162 }
2163
2164 //-----------------------------------------------------------------------------------//
2165 // there is another sprite on the move_to location, check the combination of both sizes
2166 //-----------------------------------------------------------------------------------//
2167 blocked_by_member = 1;
2168 err_when(!blockedLoc->unit_recno(mobile_type));
2169
2170 Unit* unitPtr = unit_array[blockedLoc->unit_recno(mobile_type)];
2171 //if(unitPtr->sprite_info->loc_width>1 || sprite_info->loc_width>1)
2172 //{
2173 // set_wait();
2174 // return;
2175 //}
2176 //else
2177 handle_blocked_move_s11(unitPtr); //------ both units size 1x1
2178
2179 err_when(cur_x==go_x && cur_y==go_y && (cur_x!=next_x || cur_y!=next_y));
2180 return;
2181 }
2182 //------- End of function Unit::handle_blocked_move --------//
2183
2184
2185 //------ Begin of function Unit::handle_blocked_by_idle_unit ---------//
2186 // handle the case blocked by idle unit
2187 //
2188 // <Unit*> unitPtr - the unit blocking this unit
2189 //
handle_blocked_by_idle_unit(Unit * unitPtr)2190 void Unit::handle_blocked_by_idle_unit(Unit *unitPtr)
2191 {
2192 #define TEST_DIMENSION 10
2193 #define TEST_LIMIT TEST_DIMENSION*TEST_DIMENSION
2194
2195 char notLandUnit = (mobile_type!=UNIT_LAND);
2196 int unitXLoc = unitPtr->next_x_loc();
2197 int unitYLoc = unitPtr->next_y_loc();
2198 int xShift, yShift;
2199 int checkXLoc, checkYLoc;
2200 Location *locPtr;
2201
2202 int xSign = misc.random(2) ? 1 : -1;
2203 int ySign = misc.random(2) ? 1 : -1;
2204
2205 for(int i=2; i<=TEST_LIMIT; i++)
2206 {
2207 misc.cal_move_around_a_point(i, TEST_DIMENSION, TEST_DIMENSION, xShift, yShift);
2208 xShift *= xSign;
2209 yShift *= ySign;
2210
2211 if(notLandUnit)
2212 {
2213 checkXLoc = unitXLoc + xShift*2;
2214 checkYLoc = unitYLoc + yShift*2;
2215 }
2216 else
2217 {
2218 checkXLoc = unitXLoc + xShift;
2219 checkYLoc = unitYLoc + yShift;
2220 }
2221
2222 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
2223 continue;
2224
2225 locPtr = world.get_loc(checkXLoc , checkYLoc);
2226 if(!locPtr->can_move(unitPtr->mobile_type))
2227 continue;
2228
2229 if(on_my_path(checkXLoc, checkYLoc))
2230 continue;
2231
2232 unitPtr->move_to(checkXLoc, checkYLoc);
2233 set_wait();
2234 return;
2235 }
2236
2237 stop(KEEP_DEFENSE_MODE);
2238
2239 //--------------------------------------------------------------------------------//
2240 // improved version!!!
2241 //--------------------------------------------------------------------------------//
2242 /*int testResult = 0, worstCase=0;
2243 int worstXLoc=-1, worstYLoc=-1;
2244 int startCount, endCount;
2245 int i, j;
2246
2247 for(j=0; j<2; j++)
2248 {
2249 //----------- set the startCount and endCount ------------//
2250 if(j==0)
2251 {
2252 startCount = 2;
2253 endCount = 9;
2254 }
2255 else
2256 {
2257 startCount = 10;
2258 endCount = TEST_LIMIT;
2259 }
2260
2261 for(i=startCount; i<=endCount; i++)
2262 {
2263 misc.cal_move_around_a_point(i, TEST_DIMENSION, TEST_DIMENSION, xShift, yShift);
2264 if(notLandUnit)
2265 {
2266 checkXLoc = unitXLoc + xShift*2;
2267 checkYLoc = unitYLoc + yShift*2;
2268 }
2269 else
2270 {
2271 checkXLoc = unitXLoc + xShift;
2272 checkYLoc = unitYLoc + yShift;
2273 }
2274
2275 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
2276 continue;
2277
2278 locPtr = world.get_loc(checkXLoc , checkYLoc);
2279 if(!locPtr->can_move(unitPtr->mobile_type))
2280 continue;
2281
2282 //-------------------------------------------------------------------//
2283 // a possible location
2284 //-------------------------------------------------------------------//
2285 testResult = on_my_path(checkXLoc, checkYLoc);
2286 if(testResult)
2287 {
2288 if(j==0 && !worstCase)
2289 {
2290 worstCase++;
2291 worstXLoc = checkXLoc;
2292 worstYLoc = checkYLoc;
2293 }
2294 continue;
2295 }
2296
2297 unitPtr->move_to(checkXLoc, checkYLoc):
2298 set_wait();
2299 return;
2300 }
2301 }
2302
2303 //-------------------------------------------------------------------//
2304 if(worstCase)
2305 {
2306 unitPtr->move_to(worstXLoc, worstYLoc);
2307 set_wait();
2308 }
2309 else
2310 stop(KEEP_DEFENSE_MODE);*/
2311 }
2312 //------- End of function Unit::handle_blocked_by_idle_unit --------//
2313
2314
2315 //------ Begin of function Unit::on_my_path ---------//
2316 // This function is used to check whether a location
2317 // (checkXLoc, checkYLoc) is on the unit path, result_node_array.
2318 //
2319 // return 1 if true
2320 // return 0 otherwise
2321 //
on_my_path(short checkXLoc,short checkYLoc)2322 int Unit::on_my_path(short checkXLoc, short checkYLoc)
2323 {
2324 err_when(result_node_count<2);
2325 ResultNode* curNodePtr = result_node_array+result_node_recno-2;
2326 ResultNode* nextNodePtr = curNodePtr+1;
2327
2328 for(int i=result_node_recno-1; i<result_node_count; i++, curNodePtr++, nextNodePtr++)
2329 {
2330 if((curNodePtr->node_x-checkXLoc)*(checkYLoc-nextNodePtr->node_y)==
2331 (curNodePtr->node_y-checkYLoc)*(checkXLoc-nextNodePtr->node_x)) // point of division
2332 return 1;
2333 }
2334
2335 return 0;
2336 }
2337 //------- End of function Unit::on_my_path --------//
2338
2339
2340 //------ Begin of function Unit::handle_blocked_wait ---------//
2341 //
2342 // this function is worked for unit size 1x1 only to handle case that
2343 // blocked by waiting unit
2344 //
2345 // <Unit*> unitPtr - unit blocking this unit
2346 //
handle_blocked_wait(Unit * unitPtr)2347 void Unit::handle_blocked_wait(Unit* unitPtr)
2348 {
2349 err_when(sprite_info->loc_width>1 || unitPtr->sprite_info->loc_width>1);
2350
2351 int stepMagn = move_step_magn();
2352 short cycleWait = 0;
2353 Location *locPtr;
2354
2355 if(is_dir_correct())
2356 {
2357 Unit *blockedUnitPtr = unitPtr;
2358 SpriteInfo *unitSpriteInfo = unitPtr->sprite_info;
2359 int nextX, nextY, loop = 0, i;
2360 short blocked=0;
2361
2362 //---------------------------------------------------------------//
2363 // construct a cycle_waiting array to store the sprite_recno of
2364 // those units in cycle_waiting in order to prevent forever looping
2365 // in the checking
2366 //---------------------------------------------------------------//
2367 int arraySize = 20;
2368 cycle_wait_unit_array_def_size = arraySize;
2369 cycle_wait_unit_index = 0;
2370 cycle_wait_unit_array_multipler = 1;
2371 cycle_wait_unit_array = (short*)mem_add(sizeof(short)*cycle_wait_unit_array_def_size);
2372 memset(cycle_wait_unit_array, 0, sizeof(short)*cycle_wait_unit_array_def_size);
2373
2374 //---------------------------------------------------------------//
2375 // don't handle the case blocked by size 2x2 unit in this moment
2376 //---------------------------------------------------------------//
2377 while(!cycleWait && blockedUnitPtr->cur_action==SPRITE_WAIT)
2378 {
2379 if(unitSpriteInfo->loc_width>1)
2380 break; // don't handle unit size > 1
2381
2382 if(!blockedUnitPtr->is_dir_correct())
2383 break;
2384
2385 //----------------------------------------------------------------------------------------//
2386 // cur_x, cur_y of unit pointed by blockedUnitPtr should be exactly inside a tile
2387 //----------------------------------------------------------------------------------------//
2388 nextX = blockedUnitPtr->cur_x+stepMagn*move_x_pixel_array[blockedUnitPtr->final_dir];
2389 nextY = blockedUnitPtr->cur_y+stepMagn*move_y_pixel_array[blockedUnitPtr->final_dir];
2390
2391 //---------- calculate location blocked unit attempts to move to ---------//
2392 nextX >>= ZOOM_X_SHIFT_COUNT;
2393 nextY >>= ZOOM_Y_SHIFT_COUNT;
2394
2395 locPtr = world.get_loc(nextX, nextY);
2396 blocked = locPtr->has_unit(mobile_type);
2397
2398 //---------------- the unit is also waiting ---------------//
2399 if(blocked && (blockedUnitPtr->move_to_x_loc!=blockedUnitPtr->cur_x_loc() ||
2400 blockedUnitPtr->move_to_y_loc!=blockedUnitPtr->cur_y_loc()))
2401 {
2402 if(locPtr->unit_recno(mobile_type) == sprite_recno)
2403 cycleWait = 1;
2404 else
2405 {
2406 for(i=0; i<cycle_wait_unit_index; i++)
2407 {
2408 //---------- checking for forever loop ----------------//
2409 if(cycle_wait_unit_array[i] == blockedUnitPtr->sprite_recno)
2410 {
2411 loop = 1;
2412 break;
2413 }
2414 }
2415
2416 if(loop)
2417 break;
2418
2419 //------------------------------------------------------//
2420 // resize array if required size is larger than arraySize
2421 //------------------------------------------------------//
2422 if(cycle_wait_unit_index >= arraySize)
2423 {
2424 cycle_wait_unit_array_multipler++;
2425 arraySize = cycle_wait_unit_array_def_size*cycle_wait_unit_array_multipler;
2426 cycle_wait_unit_array = (short*) mem_resize(cycle_wait_unit_array, sizeof(short)*arraySize);
2427 }
2428 else
2429 {
2430 //-------- store recno of next blocked unit ----------//
2431 cycle_wait_unit_array[cycle_wait_unit_index++] = blockedUnitPtr->sprite_recno;
2432 locPtr = world.get_loc(nextX, nextY);
2433 err_when(blockedUnitPtr->mobile_type!=mobile_type);
2434 blockedUnitPtr = unit_array[locPtr->unit_recno(mobile_type)];
2435 unitSpriteInfo = blockedUnitPtr->sprite_info;
2436 }
2437 }
2438 }
2439 else
2440 break;
2441 }
2442
2443 //---------- deinit data structure -------//
2444 mem_del(cycle_wait_unit_array);
2445 cycle_wait_unit_array = NULL;
2446 }
2447
2448 if(cycleWait)
2449 {
2450 //----------------------------------------------------------------------//
2451 // shift the recno of all the unit in the cycle
2452 //----------------------------------------------------------------------//
2453 err_when(!is_dir_correct());
2454
2455 short backupSpriteRecno;
2456 world.set_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type, 0); // empty the firt node in the cycle
2457 cycle_wait_shift_recno(this, unitPtr); // shift all the unit in the cycle
2458 backupSpriteRecno = world.get_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type);
2459 world.set_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type, sprite_recno);
2460 set_next(unitPtr->cur_x, unitPtr->cur_y, -stepMagn, 1);
2461 set_move();
2462 world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, sprite_recno);
2463 world.set_unit_recno(cur_x_loc(), cur_y_loc(), mobile_type, backupSpriteRecno);
2464 swapping = 1;
2465 }
2466 else // not in a cycle
2467 {
2468 set_wait();
2469
2470 //if(waiting_term>=MAX_WAITING_TERM_SAME)
2471 if(waiting_term>=MAX_WAITING_TERM_SAME*move_step_magn())
2472 {
2473 //-----------------------------------------------------------------//
2474 // codes used to speed up frame rate
2475 //-----------------------------------------------------------------//
2476 locPtr = world.get_loc(move_to_x_loc, move_to_y_loc);
2477 if(!locPtr->can_move(mobile_type) && action_mode2!=ACTION_MOVE)
2478 stop(KEEP_PRESERVE_ACTION); // let reactivate..() call searching later
2479 else
2480 search_or_wait();
2481
2482 waiting_term = 0;
2483 }
2484 }
2485 }
2486 //-------- End of function Unit::handle_blocked_wait ---------//
2487
2488
2489 //------ Begin of function Unit::cycle_wait_shift_recno ---------//
2490 // copy recno of curUnit to location where nextUnit on
2491 //
2492 // <Unit*> curUnit -
2493 // <Unit*> nextUnit -
2494 //
cycle_wait_shift_recno(Unit * curUnit,Unit * nextUnit)2495 void Unit::cycle_wait_shift_recno(Unit* curUnit, Unit* nextUnit)
2496 {
2497 err_when(!curUnit->is_dir_correct() || !nextUnit->is_dir_correct());
2498
2499 int stepMagn = move_step_magn();
2500 Unit *blockedUnitPtr;
2501 Location *locPtr;
2502
2503 //----------- find the next location ------------//
2504 int nextX = nextUnit->cur_x+stepMagn*move_x_pixel_array[nextUnit->final_dir];
2505 int nextY = nextUnit->cur_y+stepMagn*move_y_pixel_array[nextUnit->final_dir];
2506
2507 nextX >>= ZOOM_X_SHIFT_COUNT;
2508 nextY >>= ZOOM_Y_SHIFT_COUNT;
2509
2510 if(nextX != cur_x_loc() || nextY != cur_y_loc())
2511 {
2512 locPtr = world.get_loc(nextX, nextY);
2513 blockedUnitPtr = unit_array[locPtr->unit_recno(nextUnit->mobile_type)];
2514 }
2515 else
2516 blockedUnitPtr = this;
2517
2518 err_when(!blockedUnitPtr);
2519
2520 if(blockedUnitPtr != this)
2521 {
2522 cycle_wait_shift_recno(nextUnit, blockedUnitPtr);
2523 nextUnit->set_next(blockedUnitPtr->cur_x, blockedUnitPtr->cur_y, -stepMagn, 1);
2524 nextUnit->set_move();
2525 world.set_unit_recno(blockedUnitPtr->cur_x_loc(), blockedUnitPtr->cur_y_loc(), nextUnit->mobile_type, nextUnit->sprite_recno);
2526 world.set_unit_recno(nextUnit->cur_x_loc(), nextUnit->cur_y_loc(), nextUnit->mobile_type, 0);
2527 nextUnit->swapping = 1;
2528 }
2529 else // the cycle shift is ended
2530 {
2531 err_when(blockedUnitPtr != this);
2532 err_when(nextUnit->cur_x!=nextUnit->next_x || nextUnit->cur_y!=nextUnit->next_y);
2533 err_when(nextUnit->cur_action != SPRITE_WAIT);
2534
2535 nextUnit->set_next(cur_x, cur_y, -stepMagn, 1);
2536 nextUnit->set_move();
2537 world.set_unit_recno(cur_x_loc(), cur_y_loc(), nextUnit->mobile_type, nextUnit->sprite_recno);
2538 world.set_unit_recno(nextUnit->cur_x_loc(), nextUnit->cur_y_loc(), nextUnit->mobile_type, 0);
2539
2540 nextUnit->swapping = 1;
2541 }
2542 }
2543 //-------- End of function Unit::cycle_wait_shift_recno ---------//
2544
2545
2546 //------ Begin of function Unit::opposite_direction_blocked ---------//
2547 // the two units are oppositely blocked, handle swapping
2548 //
opposite_direction_blocked(short vecX,short vecY,short unitPtrVecX,short unitPtrVecY,Unit * unitPtr)2549 void Unit::opposite_direction_blocked(short vecX, short vecY, short unitPtrVecX, short unitPtrVecY, Unit* unitPtr)
2550 {
2551 //---------------------------------------------------------------------------//
2552 // processing swapping only when both units are exactly in the tiles
2553 //---------------------------------------------------------------------------//
2554 if(unitPtr->cur_action!=SPRITE_IDLE)
2555 {
2556 if(unitPtr->move_to_x_loc!=move_to_x_loc || unitPtr->move_to_y_loc!=move_to_y_loc)
2557 {
2558 int stepMagn = move_step_magn();
2559
2560 world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, 0);
2561 err_when(!is_dir_correct());
2562 set_next(unitPtr->cur_x, unitPtr->cur_y, -stepMagn, -1);
2563
2564 world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, unitPtr->sprite_recno);
2565 world.set_unit_recno(cur_x_loc(), cur_y_loc(), unitPtr->mobile_type, 0);
2566 err_when(!unitPtr->is_dir_correct());
2567 unitPtr->set_next(cur_x, cur_y, -stepMagn, 1);
2568
2569 world.set_unit_recno(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), mobile_type, sprite_recno);
2570 world.set_unit_recno(cur_x_loc(), cur_y_loc(), unitPtr->mobile_type, unitPtr->sprite_recno);
2571
2572 set_move();
2573 unitPtr->set_move();
2574
2575 swapping = 1;
2576 unitPtr->swapping = 1;
2577
2578 #ifdef DEBUG
2579 ResultNode* curNode;
2580 curNode = result_node_array + result_node_count - 1;
2581 err_when(curNode->node_x!=move_to_x_loc || curNode->node_y!=move_to_y_loc);
2582 curNode = unitPtr->result_node_array + unitPtr->result_node_count - 1;
2583 err_when(curNode->node_x!=unitPtr->move_to_x_loc || curNode->node_y!=unitPtr->move_to_y_loc);
2584 #endif
2585 }
2586 else
2587 terminate_move();
2588 }
2589 else
2590 {
2591 //----------------------------------------------------------------------//
2592 // If the unit pointed by unitPtr (unit B) has the same unit_id, rank_id
2593 // and both are in the same group, this unit will order the other unit to
2594 // move to its location and this unit will occupy the location of the unit B.
2595 //
2596 // If the above condition is not fulfilled, swapping is processed.
2597 //----------------------------------------------------------------------//
2598 if(unit_id!=unitPtr->unit_id || rank_id!=unitPtr->rank_id || unit_group_id!=unitPtr->unit_group_id)
2599 {
2600 if(unitPtr->move_to_x_loc!=move_to_x_loc || unitPtr->move_to_y_loc!=move_to_y_loc)
2601 {
2602 //----------------- process swapping ---------------//
2603 set_wait();
2604 unitPtr->set_dir(unitPtr->next_x, unitPtr->next_y, next_x, next_y);
2605 set_dir(next_x, next_y, unitPtr->next_x, unitPtr->next_y);
2606
2607 err_when(unitPtr->result_node_array!=NULL);
2608
2609 unitPtr->result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*2);
2610 ResultNode* nodePtr = unitPtr->result_node_array;
2611
2612 err_when(next_x_loc()!= cur_x_loc() || next_y_loc()!=cur_y_loc());
2613 nodePtr->node_x = next_x_loc();
2614 nodePtr->node_y = next_y_loc();
2615 nodePtr++;
2616 nodePtr->node_x = unitPtr->next_x_loc();
2617 nodePtr->node_y = unitPtr->next_y_loc();
2618 unitPtr->result_node_count = 2;
2619 unitPtr->result_node_recno = 1;
2620
2621 unitPtr->set_wait();
2622 unitPtr->go_x = next_x;
2623 unitPtr->go_y = next_y;
2624
2625 unitPtr->result_path_dist = 2;
2626
2627 err_when((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=final_dir);
2628 swapping = 1;
2629 unitPtr->swapping = 1;
2630 }
2631 else
2632 terminate_move();
2633 }
2634 else
2635 {
2636 //------------ process move_to_my_loc or terminate the movement -----------//
2637 if(unitPtr->move_to_x_loc!=move_to_x_loc || unitPtr->move_to_y_loc!=move_to_y_loc)
2638 move_to_my_loc(unitPtr);
2639 else
2640 terminate_move();
2641 }
2642
2643 #ifdef DEBUG
2644 ResultNode* curNode;
2645 if(result_node_array!=NULL)
2646 {
2647 curNode = result_node_array + result_node_count - 1;
2648 err_when(curNode->node_x!=move_to_x_loc || curNode->node_y!=move_to_y_loc);
2649 }
2650 if(unitPtr->result_node_array!=NULL)
2651 {
2652 curNode = unitPtr->result_node_array + unitPtr->result_node_count - 1;
2653 err_when(curNode->node_x!=unitPtr->move_to_x_loc || curNode->node_y!=unitPtr->move_to_y_loc);
2654 }
2655 #endif
2656 }
2657 }
2658 //-------- End of function Unit::opposite_direction_blocked ---------//
2659
2660
2661 //------ Begin of function Unit::terminate_move -------//
2662 //
2663 // When the sprite has finished moving the next tile in
2664 // the path. If the following tile is blocked and the whole
2665 // movement need to be terminated, this function is called.
2666 //
2667 // When SPRITE_IDLE:
2668 //
2669 // (next_x, next_y) must be == (cur_x, cur_y), it's the location of the sprite.
2670 //
terminate_move()2671 void Unit::terminate_move()
2672 {
2673 #ifdef DEBUG
2674 err_when( next_x != cur_x || next_y != cur_y );
2675 short h, y;
2676 for(h=0, y=cur_y_loc(); h<sprite_info->loc_height; h++, y++)
2677 for(short w=0, x=cur_x_loc(); w<sprite_info->loc_width; w++, x++)
2678 err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno );
2679 #endif
2680
2681 go_x = next_x;
2682 go_y = next_y;
2683
2684 move_to_x_loc = next_x_loc();
2685 move_to_y_loc = next_y_loc();
2686
2687 #ifdef DEBUG
2688 char blocked=0;
2689 for(h=0, y=next_y_loc(); h<sprite_info->loc_height&&!blocked; h++, y++)
2690 for(short w=0, x=next_x_loc(); w<sprite_info->loc_width&&!blocked; w++, x++)
2691 blocked = world.get_unit_recno(x,y,mobile_type) != sprite_recno;
2692 err_when(blocked);
2693 #endif
2694
2695 cur_frame = 1;
2696
2697 reset_path();
2698 set_idle();
2699
2700 err_when(result_node_array!=NULL);
2701 }
2702 //------- End of function Unit::terminate_move --------//
2703
2704
2705 //------------- Begin of function Unit::move_to_my_loc --------------//
2706 //
2707 // This function is used as this unit Unit A is blocked by another
2708 // IDLE unit Unit B. Then Unit A will move to the location of Unit B
2709 // and Unit B will move to the location of Unit A want to move to.
2710 //
2711 // Note: action_?_loc2 of both units can be different from their
2712 // move_to_?_loc
2713 //
move_to_my_loc(Unit * unitPtr)2714 void Unit::move_to_my_loc(Unit* unitPtr)
2715 {
2716 int unitDestX, unitDestY;
2717 if(unitPtr->action_mode2==ACTION_MOVE)
2718 {
2719 unitDestX = unitPtr->action_x_loc2;
2720 unitDestY = unitPtr->action_y_loc2;
2721 err_when(unitDestX==-1 || unitDestY==-1);
2722 }
2723 else
2724 {
2725 unitDestX = unitPtr->move_to_x_loc;
2726 unitDestY = unitPtr->move_to_y_loc;
2727 }
2728
2729 //--------------- init parameters ---------------//
2730 int unitCurX = unitPtr->next_x_loc();
2731 int unitCurY = unitPtr->next_y_loc();
2732 int destX = action_x_loc2;
2733 int destY = action_y_loc2;
2734 int curX = next_x_loc();
2735 int curY = next_y_loc();
2736 int moveScale = move_step_magn();
2737 err_when(curX != cur_x_loc() || curY != cur_y_loc());
2738 err_when(mobile_type!=unitPtr->mobile_type);
2739
2740 //------------------------------------------------------------------//
2741 // setting for unit pointed by unitPtr
2742 //------------------------------------------------------------------//
2743 if(result_node_array==NULL) //************BUGHERE
2744 {
2745 err_when(unitPtr->cur_action!=SPRITE_IDLE);
2746 unitPtr->move_to(destX, destY, 1); // unit pointed by unitPtr is idle before calling searching
2747 err_when(unitPtr->cur_action!=SPRITE_DIE && unitPtr->action_mode2!=ACTION_MOVE);
2748 }
2749 else
2750 {
2751 err_when(result_node_recno<1 || unitPtr->result_node_array!=NULL);
2752 ResultNode* resultNode = result_node_array+result_node_recno-1;
2753 if(go_x == unitPtr->next_x && go_y == unitPtr->next_y)
2754 {
2755 //------ Unit B is in one of the node of the result_node_array ---//
2756 unitPtr->result_node_count = result_node_count-result_node_recno+1; // at least there are 2 nodes
2757 unitPtr->result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*(unitPtr->result_node_count));
2758 memcpy(unitPtr->result_node_array, resultNode, sizeof(ResultNode)*(unitPtr->result_node_count));
2759 }
2760 else
2761 {
2762 //----- Unit B is in the middle of two nodes in the result_node_array -----//
2763 unitPtr->result_node_count = result_node_count-result_node_recno+2;
2764 unitPtr->result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*(unitPtr->result_node_count));
2765 ResultNode* curNode = unitPtr->result_node_array;
2766 curNode->node_x = unitCurX;
2767 curNode->node_y = unitCurY;
2768 curNode++;
2769 memcpy(curNode, resultNode, sizeof(ResultNode)*(unitPtr->result_node_count-1));
2770 }
2771 err_when(unitPtr->result_node_count<2);
2772
2773 //--------------- set unit action ---------------//
2774 if(unitPtr->action_mode2==ACTION_STOP || unitPtr->action_mode2==ACTION_MOVE) // unitPtr is idle now
2775 {
2776 //---------- activate unit pointed by unitPtr now ------------//
2777 unitPtr->action_mode = unitPtr->action_mode2 = ACTION_MOVE;
2778 unitPtr->action_para = unitPtr->action_para2 = 0;
2779 if(destX!=-1 && destY!=-1)
2780 {
2781 unitPtr->action_x_loc = unitPtr->action_x_loc2 = destX;
2782 unitPtr->action_y_loc = unitPtr->action_y_loc2 = destY;
2783 }
2784 else
2785 {
2786 ResultNode *lastNodePtr = unitPtr->result_node_array + unitPtr->result_node_count - 1;
2787 unitPtr->action_x_loc = unitPtr->action_x_loc2 = lastNodePtr->node_x;
2788 unitPtr->action_y_loc = unitPtr->action_y_loc2 = lastNodePtr->node_y;
2789 }
2790 }
2791
2792 //----------------- set unit movement parameters -----------------//
2793 unitPtr->result_node_recno = 1;
2794 unitPtr->result_path_dist = result_path_dist-moveScale;
2795 unitPtr->move_to_x_loc = move_to_x_loc;
2796 unitPtr->move_to_y_loc = move_to_y_loc;
2797 err_when( next_x != cur_x || next_y != cur_y );
2798 unitPtr->next_move();
2799
2800 #ifdef DEBUG
2801 if(unitPtr->result_node_array!=NULL)
2802 {
2803 ResultNode* curNode1 = unitPtr->result_node_array + unitPtr->result_node_recno - 1;
2804 err_when(curNode1->node_x!=unitPtr->go_x>>ZOOM_X_SHIFT_COUNT || curNode1->node_y!=unitPtr->go_y>>ZOOM_Y_SHIFT_COUNT);
2805 }
2806 #endif
2807 }
2808
2809 //------------------------------------------------------------------//
2810 // setting for this unit
2811 //------------------------------------------------------------------//
2812 int shouldWait = 0;
2813 if(next_x==unitPtr->cur_x && next_y==unitPtr->cur_y)
2814 {
2815 reset_path();
2816 result_path_dist = 0;
2817 }
2818 else
2819 {
2820 terminate_move();
2821 shouldWait++;
2822 result_path_dist = moveScale;
2823 }
2824
2825 go_x = unitPtr->cur_x;
2826 go_y = unitPtr->cur_y;
2827 move_to_x_loc = unitCurX;
2828 move_to_y_loc = unitCurY;
2829
2830 if(action_mode2==ACTION_MOVE)
2831 {
2832 action_x_loc = action_x_loc2 = unitDestX;
2833 action_y_loc = action_y_loc2 = unitDestY;
2834 }
2835
2836 //---------- note: the cur_dir is already the correct direction ---------------//
2837 err_when(result_node_array!=NULL);
2838 result_node_array = (ResultNode*)mem_add(sizeof(ResultNode)*2);
2839 ResultNode* nodePtr = result_node_array;
2840 nodePtr->node_x = curX;
2841 nodePtr->node_y = curY;
2842 nodePtr++;
2843 nodePtr->node_x = unitCurX;
2844 nodePtr->node_y = unitCurY;
2845 result_node_count = 2;
2846 result_node_recno = 2;
2847 if(shouldWait)
2848 set_wait(); // wait for the blocking unit to move first
2849
2850 #ifdef DEBUG
2851 if(result_node_array!=NULL)
2852 {
2853 ResultNode* curNode2 = result_node_array + result_node_recno - 1;
2854 err_when(curNode2->node_x!=go_x>>ZOOM_X_SHIFT_COUNT || curNode2->node_y!=go_y>>ZOOM_Y_SHIFT_COUNT);
2855 }
2856 #endif
2857
2858 err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
2859 err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
2860 err_when(unitPtr->cur_action==SPRITE_IDLE && (unitPtr->move_to_x_loc!=unitPtr->next_x_loc() ||
2861 unitPtr->move_to_y_loc!=unitPtr->next_y_loc()));
2862 }
2863 //----------------- End of function Unit::move_to_my_loc ----------------//
2864
2865 //###### begin trevor 25/6 #######//
2866
2867 /*
2868 //------------- Begin of function Unit::change_relation --------------//
2869 void Unit::change_relation(short nation1, short nation2, int relationType)
2870 {
2871 if(!nation1 || !nation2 || nation1==nation2)
2872 return; // return if either is neutral nation or same nation
2873
2874 nation_array[nation1]->set_relation_status(nation2, relationType);
2875 }
2876 //----------------- End of function Unit::change_relation ----------------//
2877 */
2878
2879 //####### end trevor 25/6 ########//
2880
2881
2882 //------------- Begin of function Unit::set_idle --------------//
2883 // set parameters for unit idle
2884 //
set_idle()2885 void Unit::set_idle()
2886 {
2887 /*err_when(unit_res[unit_id]->unit_class==UNIT_CLASS_SHIP &&
2888 (((UnitMarine*)this)->extra_move_in_beach==EXTRA_MOVING_IN ||
2889 ((UnitMarine*)this)->extra_move_in_beach==EXTRA_MOVING_OUT));*/
2890 err_when(cur_x<0);
2891 err_when(move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc());
2892 err_when(cur_x!=next_x || cur_y!=next_y || next_x!=go_x || next_y!=go_y);
2893 err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT);
2894
2895 err_when(result_path_dist || result_node_array);
2896 err_when(cur_dir<0 || cur_dir>MAX_SPRITE_DIR_TYPE);
2897 final_dir = cur_dir;
2898 turn_delay = 0;
2899 cur_action = SPRITE_IDLE;
2900 }
2901 //----------------- End of function Unit::set_idle ----------------//
2902
2903
2904 //------------- Begin of function Unit::set_ready --------------//
2905 // set parameters for unit ready to move
2906 //
set_ready()2907 void Unit::set_ready()
2908 {
2909 err_when(cur_x<0);
2910 err_when(move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc());
2911 err_when(cur_x!=next_x || cur_y!=next_y || next_x!=go_x || next_y!=go_y);
2912 err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT);
2913
2914 err_when(cur_dir<0 || cur_dir>MAX_SPRITE_DIR_TYPE);
2915 final_dir = cur_dir;
2916 turn_delay = 0;
2917 cur_action = SPRITE_READY_TO_MOVE;
2918 }
2919 //----------------- End of function Unit::set_ready ----------------//
2920
2921
2922 //------------- Begin of function Unit::set_move --------------//
2923 // set parameters for unit movement
2924 //
set_move()2925 void Unit::set_move()
2926 {
2927 err_when(cur_x<0);
2928 err_when(cur_dir!=final_dir);
2929 cur_action = SPRITE_MOVE;
2930 }
2931 //----------------- End of function Unit::set_move ----------------//
2932
2933
2934 //------------- Begin of function Unit::set_wait --------------//
2935 // Set the unit to waiting status.
2936 // When SPRITE_WAIT:
2937 // (next_x, next_y) must be == (cur_x, cur_y), it's the location of the sprite.
2938 //
set_wait()2939 void Unit::set_wait()
2940 {
2941 err_when(cur_x<0);
2942
2943 #ifdef DEBUG
2944 err_when(go_x==cur_x && go_y==cur_y);
2945 err_when( next_x != cur_x || next_y != cur_y );
2946
2947 short w, h, x, y;
2948 for(h=0, y=cur_y_loc(); h<sprite_info->loc_height; h++, y++)
2949 for(w=0, x=cur_x_loc(); w<sprite_info->loc_width; w++, x++)
2950 err_when( world.get_unit_recno(x, y, mobile_type) != sprite_recno );
2951 err_when((check_unit_dir1=get_dir(cur_x, cur_y, go_x, go_y))!=final_dir);
2952 #endif
2953
2954 cur_action = SPRITE_WAIT;
2955 cur_frame = 1;
2956 waiting_term++;
2957 }
2958 //----------------- End of function Unit::set_wait ----------------//
2959
2960
2961 //------------- Begin of function Unit::set_attack --------------//
2962 // set parameters for unit attack
2963 //
set_attack()2964 void Unit::set_attack()
2965 {
2966 err_when(cur_x<0);
2967 err_when(next_x!=cur_x || next_y!=cur_y);
2968 err_when(cur_dir<0 || cur_dir>=MAX_SPRITE_DIR_TYPE || turn_delay);
2969 final_dir = cur_dir;
2970 turn_delay = 0;
2971 cur_action = SPRITE_ATTACK;
2972 }
2973 //----------------- End of function Unit::set_attack ----------------//
2974
2975
2976 //------------- Begin of function Unit::set_turn --------------//
2977 // set parameters for unit turning
2978 //
set_turn()2979 void Unit::set_turn()
2980 {
2981 err_when(cur_x<0);
2982 err_when(next_x!=cur_x || next_y!=cur_y);
2983 cur_action = SPRITE_TURN;
2984 }
2985 //----------------- End of function Unit::set_turn ----------------//
2986
2987
2988 //------------- Begin of function Unit::set_ship_extra_move --------------//
2989 // set parameters for ship extra moving in inlet
2990 //
set_ship_extra_move()2991 void Unit::set_ship_extra_move()
2992 {
2993 err_when(cur_x<0);
2994 cur_action = SPRITE_SHIP_EXTRA_MOVE;
2995 }
2996 //----------------- End of function Unit::set_ship_extra_move ----------------//
2997
2998
2999 //------------- Begin of function Unit::set_die --------------//
3000 // set parameters for unit die
3001 //
set_die()3002 void Unit::set_die()
3003 {
3004 if( action_mode == ACTION_DIE )
3005 return;
3006
3007 err_when(hit_points>0);
3008
3009 action_mode = ACTION_DIE;
3010 cur_action = SPRITE_DIE;
3011 cur_frame = 1;
3012
3013 //##### begin trevor 19/7 #####//
3014
3015 //---- if this unit is led by a leader, only mobile units has leader_unit_recno assigned to a leader -----//
3016
3017 if( leader_unit_recno && !unit_array.is_deleted(leader_unit_recno) ) // the leader unit may have been killed at the same time
3018 {
3019 unit_array[leader_unit_recno]->del_team_member(sprite_recno);
3020 leader_unit_recno = 0;
3021 }
3022
3023 //##### end trevor 19/7 #####//
3024 }
3025 //----------------- End of function Unit::set_die ----------------//
3026
3027