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 : OUNITS.CPP
22 //Description : Object Unit(Ship) functions
23 //Owner : Alex
24
25 #include <OU_MARI.h>
26 #include <OTERRAIN.h>
27 #include <ONATION.h>
28
29 #ifdef NO_DEBUG_UNIT
30 #undef err_when
31 #undef err_here
32 #undef err_if
33 #undef err_else
34 #undef err_now
35 #define err_when(cond)
36 #define err_here()
37 #define err_if(cond)
38 #define err_else
39 #define err_now(msg)
40 #undef DEBUG
41 #endif
42
43 //--------- Begin of function Unit::assign_to_ship ---------//
44 // assigns units to ship
45 //
46 // <int> destX, destY - the location for the ship to load the unit
47 // <short> shipRecno - the recno of the ship
48 // <int> miscNo - used to cal the offset location (default: 0)
49 //
assign_to_ship(int destX,int destY,short shipRecno,int miscNo)50 void Unit::assign_to_ship(int destX, int destY, short shipRecno, int miscNo)
51 {
52 err_when(destX<0 || destX>=MAX_WORLD_X_LOC || destY<0 || destY>=MAX_WORLD_Y_LOC || shipRecno<=0);
53 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
54
55 //----------------------------------------------------------------//
56 // return if the unit is dead
57 //----------------------------------------------------------------//
58 if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
59 return;
60
61 if(unit_array.is_deleted(shipRecno))
62 return;
63
64 #ifdef DEBUG
65 int debugShipXLoc = unit_array[shipRecno]->next_x_loc();
66 int debugShipYLoc = unit_array[shipRecno]->next_y_loc();
67 err_when(terrain_res[world.get_loc(debugShipXLoc, debugShipYLoc)->terrain_id]->average_type!=TERRAIN_OCEAN);
68 int debugCheckXLoc, debugCheckYLoc;
69 #endif
70
71 //----------------------------------------------------------------//
72 // action_mode2: checking for equal action or idle action
73 //----------------------------------------------------------------//
74 if(action_mode2==ACTION_ASSIGN_TO_SHIP && action_para2==shipRecno && action_x_loc2==destX && action_y_loc2==destY)
75 {
76 if(cur_action!=SPRITE_IDLE)
77 return;
78 }
79 else
80 {
81 //----------------------------------------------------------------//
82 // action_mode2: store new order
83 //----------------------------------------------------------------//
84 action_mode2 = ACTION_ASSIGN_TO_SHIP;
85 action_para2 = shipRecno;
86 action_x_loc2 = destX;
87 action_y_loc2 = destY;
88 }
89
90 //----- order the sprite to stop as soon as possible -----//
91 stop(); // new order
92
93 Unit *shipPtr = unit_array[shipRecno];
94 int shipXLoc = shipPtr->next_x_loc();
95 int shipYLoc = shipPtr->next_y_loc();
96 bool resultXYLocWritten = false;
97 int resultXLoc, resultYLoc;
98 int xShift, yShift;
99 if(!miscNo)
100 {
101 //-------- find a suitable location since no offset location is given ---------//
102 if(abs(shipXLoc-action_x_loc2)<=1 && abs(shipYLoc-action_y_loc2)<=1)
103 {
104 int checkXLoc, checkYLoc;
105 Location *locPtr = world.get_loc(next_x_loc(), next_y_loc());
106 uint8_t regionId = locPtr->region_id;
107 for(int i=2; i<=9; i++)
108 {
109 misc.cal_move_around_a_point(i, 3, 3, xShift, yShift);
110 checkXLoc = shipXLoc+xShift;
111 checkYLoc = shipYLoc+yShift;
112 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
113 continue;
114
115 locPtr = world.get_loc(checkXLoc, checkYLoc);
116 if(locPtr->region_id!=regionId)
117 continue;
118
119 resultXYLocWritten = true;
120 resultXLoc = checkXLoc;
121 resultYLoc = checkYLoc;
122
123 #ifdef DEBUG
124 debugCheckXLoc = checkXLoc;
125 debugCheckYLoc = checkYLoc;
126 #endif
127 break;
128 }
129 }
130 else
131 {
132 resultXYLocWritten = true;
133 resultXLoc = action_x_loc2;
134 resultYLoc = action_y_loc2;
135 }
136
137 err_when(!resultXYLocWritten);
138 err_when(resultXLoc<0 || resultXLoc>=MAX_WORLD_X_LOC || resultYLoc<0 || resultYLoc>=MAX_WORLD_Y_LOC);
139 }
140 else
141 {
142 //------------ offset location is given, move there directly ----------//
143 misc.cal_move_around_a_point(miscNo, MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC, xShift, yShift);
144 resultXLoc = destX+xShift;
145 resultYLoc = destY+yShift;
146 err_when(resultXLoc<0 || resultXLoc>=MAX_WORLD_X_LOC || resultYLoc<0 || resultYLoc>=MAX_WORLD_Y_LOC);
147 }
148
149 //--------- start searching ----------//
150 int curXLoc = next_x_loc();
151 int curYLoc = next_y_loc();
152 if((curXLoc!=destX || curYLoc!=destY) && (abs(shipXLoc-curXLoc)>1 || abs(shipYLoc-curYLoc)>1))
153 search(resultXLoc, resultYLoc, 1);
154
155 //-------- set action parameters ----------//
156 action_mode = ACTION_ASSIGN_TO_SHIP;
157 action_para = shipRecno;
158 action_x_loc = destX;
159 action_y_loc = destY;
160 }
161 //----------- End of function Unit::assign_to_ship -----------//
162
163
164 //--------- Begin of function Unit::process_assign_to_ship ---------//
165 // process unit action of assigning units to ship
166 //
process_assign_to_ship()167 void Unit::process_assign_to_ship()
168 {
169 err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
170
171 //---------------------------------------------------------------------------//
172 // clear unit's action if situation is changed
173 //---------------------------------------------------------------------------//
174 UnitMarine *shipPtr;
175 if(unit_array.is_deleted(action_para2))
176 {
177 stop2();
178 return; // stop the unit as the ship is deleted
179 }
180 else
181 {
182 shipPtr = (UnitMarine*) unit_array[action_para2];
183 if(shipPtr->nation_recno != nation_recno)
184 {
185 stop2();
186 return; // stop the unit as the ship's nation_recno != the unit's nation_recno
187 }
188 }
189
190 if(shipPtr->action_mode2!=ACTION_SHIP_TO_BEACH)
191 {
192 stop2(); // the ship has changed its action
193 return;
194 }
195
196 int curXLoc = next_x_loc();
197 int curYLoc = next_y_loc();
198 int shipXLoc = shipPtr->next_x_loc();
199 int shipYLoc = shipPtr->next_y_loc();
200
201 if(shipPtr->cur_x==shipPtr->next_x && shipPtr->cur_y==shipPtr->next_y &&
202 abs(shipXLoc-curXLoc)<=1 && abs(shipYLoc-curYLoc)<=1)
203 {
204 //----------- assign the unit now -----------//
205 if(abs(cur_x-next_x)<sprite_info->speed && abs(cur_y-next_y)<sprite_info->speed)
206 {
207 if(ai_action_id)
208 nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
209
210 stop2();
211 set_dir(curXLoc, curYLoc, shipXLoc, shipYLoc);
212 shipPtr->load_unit(sprite_recno);
213 return;
214 }
215 }
216 else if(cur_action==SPRITE_IDLE)
217 set_dir(curXLoc, curYLoc, shipPtr->move_to_x_loc, shipPtr->move_to_y_loc);
218
219 //---------------------------------------------------------------------------//
220 // update location to embark
221 //---------------------------------------------------------------------------//
222 int shipActionXLoc = shipPtr->action_x_loc2;
223 int shipActionYLoc = shipPtr->action_y_loc2;
224 if(abs(shipActionXLoc-action_x_loc2)>1 || abs(shipActionYLoc-action_y_loc2)>1)
225 {
226 if(shipActionXLoc!=action_x_loc2 || shipActionYLoc!=action_y_loc2)
227 {
228 Location *unitLocPtr = world.get_loc(curXLoc, curYLoc);
229 Location *shipActionLocPtr = world.get_loc(shipActionXLoc, shipActionYLoc);
230 if(unitLocPtr->region_id != shipActionLocPtr->region_id)
231 {
232 stop2();
233 return;
234 }
235
236 assign_to_ship(shipActionXLoc, shipActionYLoc, action_para2);
237 return;
238 }
239 }
240 }
241 //----------- End of function Unit::process_assign_to_ship -----------//
242
243
244 //--------- Begin of function Unit::ship_to_beach ---------//
245 // <int> destX, destY - the location in land planned for LAND_UNIT to embark
246 // <int&> finalDestX, finalDestY - reference to final location used to embark
247 //
248 // This function is only for ship
249 // move the ship to the coast
250 //
251 //
ship_to_beach(int destX,int destY,int & finalDestX,int & finalDestY)252 void Unit::ship_to_beach(int destX, int destY, int& finalDestX, int& finalDestY)
253 {
254 err_when(unit_res[unit_id]->unit_class!=UNIT_CLASS_SHIP);
255 err_when(destX<0 || destX>=MAX_WORLD_X_LOC || destY<0 || destY>=MAX_WORLD_Y_LOC);
256 err_when(terrain_res[world.get_loc(destX, destY)->terrain_id]->average_type == TERRAIN_OCEAN);
257
258 //----------------------------------------------------------------//
259 // change to move_to if the unit is dead
260 //----------------------------------------------------------------//
261 if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
262 {
263 move_to(destX, destY, 1);
264 finalDestX = finalDestY = -1;
265 return;
266 }
267
268 //----------------------------------------------------------------//
269 // change to move_to if the ship cannot carry units
270 //----------------------------------------------------------------//
271 if(unit_res[unit_id]->carry_unit_capacity<=0)
272 {
273 move_to(destX, destY, 1);
274 finalDestX = finalDestY = -1;
275 return;
276 }
277
278 //----------------------------------------------------------------//
279 // calculate new destination
280 //----------------------------------------------------------------//
281 #ifdef DEBUG
282 UnitMarine *debugShipPtr = (UnitMarine*) this; //****** for testing
283 #endif
284
285 int curXLoc = next_x_loc();
286 int curYLoc = next_y_loc();
287 int resultXLoc, resultYLoc;
288
289 stop();
290 err_when(cur_action==SPRITE_MOVE && cur_x==move_to_x_loc*ZOOM_LOC_WIDTH && cur_y==move_to_y_loc*ZOOM_LOC_HEIGHT);
291
292 if(abs(destX-curXLoc)>1 || abs(destY-curYLoc)>1)
293 {
294 //-----------------------------------------------------------------------------//
295 // get a suitable location in the territory as a reference location
296 //-----------------------------------------------------------------------------//
297 Location *locPtr = world.get_loc(destX, destY);
298 uint8_t regionId = locPtr->region_id;
299 int xStep = curXLoc-destX;
300 int yStep = curYLoc-destY;
301 int absXStep = abs(xStep);
302 int absYStep = abs(yStep);
303 int count = (absXStep>=absYStep) ? absXStep : absYStep;
304 int x, y;
305 long int sameTerr = 0;
306
307 for(long int i=1; i<=count; i++)
308 {
309 x = destX + int((i*xStep)/count);
310 y = destY + int((i*yStep)/count);
311
312 locPtr = world.get_loc(x, y);
313 if(locPtr->region_id==regionId)
314 {
315 if(locPtr->walkable())
316 sameTerr = i;
317 }
318 }
319
320 if(sameTerr)
321 {
322 resultXLoc = destX + int((sameTerr*xStep)/count);
323 resultYLoc = destY + int((sameTerr*yStep)/count);
324 }
325 else
326 {
327 resultXLoc = destX;
328 resultYLoc = destY;
329 }
330
331 //------------------------------------------------------------------------------//
332 // find the path from the ship location in the ocean to the reference location
333 // in the territory
334 //------------------------------------------------------------------------------//
335 if(!ship_to_beach_path_edit(resultXLoc, resultYLoc, regionId))
336 {
337 finalDestX = finalDestY = -1;
338 return; // calling move_to() instead
339 }
340 }
341 else
342 {
343 resultXLoc = destX;
344 resultYLoc = destY;
345 }
346
347 err_when(cur_action==SPRITE_MOVE && cur_x==next_x && cur_y==next_y &&
348 cur_x==move_to_x_loc*ZOOM_LOC_WIDTH && cur_y==move_to_y_loc*ZOOM_LOC_HEIGHT);
349 err_when(result_node_array==NULL && result_path_dist);
350
351 action_mode = action_mode2 = ACTION_SHIP_TO_BEACH;
352 action_para = action_para2 = 0;
353 finalDestX = action_x_loc = action_x_loc2 = resultXLoc;
354 finalDestY = action_y_loc = action_y_loc2 = resultYLoc;
355 }
356 //----------- End of function Unit::ship_to_beach -----------//
357
358
359 //--------- Begin of function Unit::ship_to_beach_path_edit ---------//
360 // find a path to the beach
361 //
362 // <int&> resultXLoc - reference to return final x location the ship move to
363 // <int&> resultYLoc - reference to return final y location the ship move to
364 // <UCHAR> regionId - region id of the destination location
365 //
366 // return 1 if normal execution
367 // return 0 if calling move_to() instead
368 //
ship_to_beach_path_edit(int & resultXLoc,int & resultYLoc,uint8_t regionId)369 int Unit::ship_to_beach_path_edit(int& resultXLoc, int& resultYLoc, uint8_t regionId)
370 {
371 int curXLoc = next_x_loc();
372 int curYLoc = next_y_loc();
373 if(abs(curXLoc-resultXLoc)<=1 && abs(curYLoc-resultYLoc)<=1)
374 return 1;
375
376 //--------------- find a path to land area -------------------//
377 UnitMarine *shipPtr = (UnitMarine*) this;
378 int result = search(resultXLoc, resultYLoc, 1, SEARCH_MODE_TO_LAND_FOR_SHIP, regionId);
379 if(!result)
380 return 1;
381
382 //----------- update cur location --------//
383 curXLoc = next_x_loc();
384 curYLoc = next_y_loc();
385 err_when(shipPtr->extra_move_in_beach!=NO_EXTRA_MOVE);
386
387 //------------------------------------------------------------------------------//
388 // edit the result path to get a location for embarking
389 //------------------------------------------------------------------------------//
390 err_when(result_node_array==NULL && result_node_count);
391
392 if(result_node_array && result_node_count)
393 {
394 err_when(result_node_count<2);
395 ResultNode *curNodePtr = result_node_array;
396 ResultNode *nextNodePtr = curNodePtr + 1;
397 int moveScale = move_step_magn();
398 int nodeCount = result_node_count;
399 Location *locPtr;
400 int i, j, found, pathDist;
401
402 int preXLoc, preYLoc;
403 int checkXLoc = curXLoc;
404 int checkYLoc = curYLoc;
405 int hasMoveStep = 0;
406 if(checkXLoc!=curNodePtr->node_x || checkYLoc!=curNodePtr->node_y)
407 {
408 err_when(abs(checkXLoc-curNodePtr->node_x)>moveScale || abs(checkYLoc-curNodePtr->node_y)>moveScale);
409 hasMoveStep += moveScale;
410 checkXLoc = curNodePtr->node_x;
411 checkYLoc = curNodePtr->node_y;
412 }
413
414 //-----------------------------------------------------------------//
415 // find the pair of points that one is in ocean and one in land
416 //-----------------------------------------------------------------//
417 err_when(terrain_res[world.get_loc(curNodePtr->node_x, curNodePtr->node_y)->terrain_id]->average_type!=TERRAIN_OCEAN);
418 int vecX, vecY, xMagn, yMagn, magn;
419
420 #ifdef DEBUG
421 int debugLoop1=0, debugLoop2=0;
422 #endif
423 for(pathDist=0, found=0, i=1; i<nodeCount; ++i, curNodePtr++, nextNodePtr++)
424 {
425 #ifdef DEBUG
426 err_when(++debugLoop1>10000);
427 #endif
428
429 vecX = nextNodePtr->node_x - curNodePtr->node_x;
430 vecY = nextNodePtr->node_y - curNodePtr->node_y;
431 magn = ((xMagn=abs(vecX)) > (yMagn=abs(vecY))) ? xMagn : yMagn;
432 if(xMagn) { vecX /= xMagn; vecX *= moveScale; }
433 if(yMagn) { vecY /= yMagn; vecY *= moveScale; }
434 err_when(abs(vecX)>moveScale && abs(vecY)>moveScale);
435
436 //------------- check each location bewteen editNode1 and editNode2 -------------//
437 for(j=0; j<magn; j+=moveScale)
438 {
439 #ifdef DEBUG
440 err_when(++debugLoop2>10000);
441 #endif
442
443 preXLoc = checkXLoc;
444 preYLoc = checkYLoc;
445 checkXLoc += vecX;
446 checkYLoc += vecY;
447
448 locPtr = world.get_loc(checkXLoc, checkYLoc);
449 if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN) // found
450 {
451 found++;
452 break;
453 }
454 }
455
456 if(found)
457 {
458 //------------ a soln is found ---------------//
459 if(!j) // end node should be curNodePtr pointed at
460 {
461 pathDist -= hasMoveStep;
462 result_node_count = i;
463 result_path_dist = pathDist;
464 }
465 else
466 {
467 nextNodePtr->node_x = checkXLoc;
468 nextNodePtr->node_y = checkYLoc;
469
470 if(i==1) // first editing
471 {
472 ResultNode *firstNodePtr = result_node_array;
473 if(cur_x==firstNodePtr->node_x*ZOOM_LOC_WIDTH && cur_y==firstNodePtr->node_y*ZOOM_LOC_HEIGHT)
474 {
475 go_x = checkXLoc * ZOOM_LOC_WIDTH;
476 go_y = checkYLoc * ZOOM_LOC_HEIGHT;
477 }
478 }
479
480 pathDist += (j+moveScale);
481 pathDist -= hasMoveStep;
482 result_node_count = i+1;
483 result_path_dist = pathDist;
484 }
485
486 move_to_x_loc = preXLoc;
487 move_to_y_loc = preYLoc;
488 locPtr = world.get_loc((preXLoc+checkXLoc)/2, (preYLoc+checkYLoc)/2);
489 if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN)
490 {
491 resultXLoc = (preXLoc+checkXLoc)/2;
492 resultYLoc = (preYLoc+checkYLoc)/2;
493 }
494 else
495 {
496 resultXLoc = checkXLoc;
497 resultYLoc = checkYLoc;
498 }
499 break;
500 }
501 else
502 pathDist += magn;
503 }
504
505 if(!found)
506 {
507 ResultNode *endNodePtr = result_node_array + result_node_count - 1;
508 if(abs(endNodePtr->node_x-resultXLoc)>1 || abs(endNodePtr->node_y-resultYLoc)>1)
509 {
510 move_to(resultXLoc, resultYLoc, -1);
511 return 0;
512 }
513 }
514 }
515 else
516 {
517 //------------- scan for the surrounding for a land location -----------//
518 int xShift, yShift, checkXLoc, checkYLoc;
519 Location *locPtr;
520 for(int i=2; i<=9; ++i)
521 {
522 misc.cal_move_around_a_point(i, 3, 3, xShift, yShift);
523 checkXLoc = curXLoc + xShift;
524 checkYLoc = curYLoc + yShift;
525 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
526 continue;
527
528 locPtr = world.get_loc(checkXLoc, checkYLoc);
529 if(locPtr->region_id!=regionId)
530 continue;
531
532 if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN && locPtr->can_move(UNIT_LAND))
533 {
534 resultXLoc = checkXLoc;
535 resultYLoc = checkYLoc;
536 return 1;
537 }
538 }
539
540 return 0;
541 }
542
543 return 1;
544 }
545 //----------- End of function Unit::ship_to_beach_path_edit -----------//
546
547
548 //--------- Begin of function Unit::process_ship_to_beach ---------//
549 // process unit action SHIP_TO_BEACH
550 //
process_ship_to_beach()551 void Unit::process_ship_to_beach()
552 {
553 //----- action_mode never clear, in_beach to skip idle checking
554 if(cur_action==SPRITE_IDLE)
555 {
556 int shipXLoc = next_x_loc();
557 int shipYLoc = next_y_loc();
558 if(shipXLoc==move_to_x_loc && shipYLoc==move_to_y_loc)
559 {
560 if(abs(move_to_x_loc-action_x_loc2)<=2 && abs(move_to_y_loc-action_y_loc2)<=2)
561 {
562 UnitMarine *shipPtr = (UnitMarine*) this;
563 //------------------------------------------------------------------------------//
564 // determine whether extra_move is required
565 //------------------------------------------------------------------------------//
566 switch(shipPtr->extra_move_in_beach)
567 {
568 case NO_EXTRA_MOVE:
569 if(abs(shipXLoc-action_x_loc2)>1 || abs(shipYLoc-action_y_loc2)>1)
570 {
571 err_when(abs(shipXLoc-action_x_loc2)>2 || abs(shipYLoc-action_y_loc2)>2);
572 err_when(result_node_array);
573
574 shipPtr->extra_move();
575 }
576 else
577 {
578 //shipPtr->in_beach = 1;
579 shipPtr->extra_move_in_beach = NO_EXTRA_MOVE;
580
581 //#### trevor 23/10 #####//
582 if(ai_action_id)
583 nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
584 //#### trevor 23/10 #####//
585 }
586 break;
587
588 case EXTRA_MOVING_IN:
589 case EXTRA_MOVING_OUT:
590 //err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE);
591 break;
592
593 //#### trevor 23/10 #####//
594
595 case EXTRA_MOVE_FINISH:
596 if(ai_action_id)
597 nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
598 break;
599
600 //#### trevor 23/10 #####//
601
602 default: err_here();
603 break;
604 }
605 }
606 }
607 else
608 reset_action_para();
609 }
610 else if(cur_action==SPRITE_TURN && is_dir_correct())
611 set_move();
612 }
613 //----------- End of function Unit::process_ship_to_beach -----------//
614
615
616 //--------- Begin of function Unit::ship_leave_beach ---------//
ship_leave_beach(int shipOldXLoc,int shipOldYLoc)617 void Unit::ship_leave_beach(int shipOldXLoc, int shipOldYLoc)
618 {
619 err_when(cur_x!=next_x || cur_y!=next_y);
620
621 UnitMarine *shipPtr = (UnitMarine*) this;
622 err_when(!shipPtr->in_beach && shipPtr->extra_move_in_beach==EXTRA_MOVE_FINISH);
623
624 //--------------------------------------------------------------------------------//
625 // scan for location to leave the beach
626 //--------------------------------------------------------------------------------//
627 int curXLoc = next_x_loc();
628 int curYLoc = next_y_loc();
629 int xShift, yShift, checkXLoc, checkYLoc, found=0;
630 Location *locPtr;
631
632 //------------- find a location to leave the beach ------------//
633 for(int i=2; i<=9; i++)
634 {
635 misc.cal_move_around_a_point(i, 3, 3, xShift, yShift);
636 checkXLoc = curXLoc + xShift;
637 checkYLoc = curYLoc + yShift;
638
639 if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
640 continue;
641
642 if(checkXLoc%2 || checkYLoc%2)
643 continue;
644
645 locPtr = world.get_loc(checkXLoc, checkYLoc);
646 if(terrain_res[locPtr->terrain_id]->average_type==TERRAIN_OCEAN &&
647 locPtr->can_move(mobile_type))
648 {
649 found++;
650 break;
651 }
652 }
653
654 if(!found)
655 return; // no suitable location, wait until finding suitable location
656
657 //---------------- leave now --------------------//
658 set_dir(shipOldXLoc, shipOldYLoc, checkXLoc, checkYLoc);
659 set_ship_extra_move();
660 go_x = checkXLoc*ZOOM_LOC_WIDTH;
661 go_y = checkYLoc*ZOOM_LOC_HEIGHT;
662 err_when(cur_x==go_x && cur_y==go_y);
663 }
664 //----------- End of function Unit::ship_leave_beach -----------//