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 -----------//