CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

DRIVE.CPP (93452B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/DRIVE.CPP 1     3/03/97 10:24a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : DRIVE.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : April 22, 1994                                               *
     28  *                                                                                             *
     29  *                  Last Update : October 31, 1996 [JLB]                                       *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   DriveClass::AI -- Processes unit movement and rotation.                                   *
     34  *   DriveClass::Approach_Target -- Handles approaching the target in order to attack it.      *
     35  *   DriveClass::Assign_Destination -- Set the unit's NavCom.                                  *
     36  *   DriveClass::Class_Of -- Fetches a reference to the class type for this object.            *
     37  *   DriveClass::Debug_Dump -- Displays status information to monochrome screen.               *
     38  *   DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction.              *
     39  *   DriveClass::DriveClass -- Constructor for drive class object.                             *
     40  *   DriveClass::Fixup_Path -- Adds smooth start path to normal movement path.                 *
     41  *   DriveClass::Force_Track -- Forces the unit to use the indicated track.                    *
     42  *   DriveClass::Lay_Track -- Handles track laying logic for the unit.                         *
     43  *   DriveClass::Limbo -- Prepares vehicle and then limbos it.                                 *
     44  *   DriveClass::Mark_Track -- Marks the midpoint of the track as occupied.                    *
     45  *   DriveClass::Ok_To_Move -- Checks to see if this object can begin moving.                  *
     46  *   DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell.          *
     47  *   DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target.  *
     48  *   DriveClass::Response_Move -- Voice feedback when ordering the unit to move.               *
     49  *   DriveClass::Response_Select -- Voice feedback when selecting the unit.                    *
     50  *   DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell.                   *
     51  *   DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic.        *
     52  *   DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell.                  *
     53  *   DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops.           *
     54  *   DriveClass::Teleport_To -- Teleport object to specified location.                         *
     55  *   DriveClass::While_Moving -- Processes unit movement.                                      *
     56  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     57 
     58 #include	"function.h"
     59 
     60 
     61 #ifdef NEVER
     62 void test(void)
     63 {
     64 	enum nums {one, two, three};
     65 
     66    nums x;
     67    nums *ptr;
     68 
     69    ptr = &x;
     70 }
     71 #endif
     72 
     73 
     74 /***********************************************************************************************
     75  * DriveClass::Response_Select -- Voice feedback when selecting the unit.                      *
     76  *                                                                                             *
     77  *    This is the voice to play when the unit is selected.                                     *
     78  *                                                                                             *
     79  * INPUT:   none                                                                               *
     80  *                                                                                             *
     81  * OUTPUT:  none                                                                               *
     82  *                                                                                             *
     83  * WARNINGS:   none                                                                            *
     84  *                                                                                             *
     85  * HISTORY:                                                                                    *
     86  *   12/30/1994 JLB : Created.                                                                 *
     87  *=============================================================================================*/
     88 void DriveClass::Response_Select(void)
     89 {
     90 	assert(IsActive);
     91 
     92 	static VocType _response[] = {
     93 		VOC_VEHIC,
     94 		VOC_REPORT,
     95 		VOC_YESSIR,
     96 		VOC_YESSIR,
     97 		VOC_YESSIR,
     98 		VOC_AWAIT
     99 	};
    100 	VocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];
    101 	if (AllowVoice) {
    102 		Sound_Effect(response, fixed(1), -(ID+1));
    103 	}
    104 }
    105 
    106 
    107 /***********************************************************************************************
    108  * DriveClass::Response_Move -- Voice feedback when ordering the unit to move.                 *
    109  *                                                                                             *
    110  *    This plays the audio feedback when ordering this unit to move to a new destination.      *
    111  *                                                                                             *
    112  * INPUT:   none                                                                               *
    113  *                                                                                             *
    114  * OUTPUT:  none                                                                               *
    115  *                                                                                             *
    116  * WARNINGS:   none                                                                            *
    117  *                                                                                             *
    118  * HISTORY:                                                                                    *
    119  *   12/30/1994 JLB : Created.                                                                 *
    120  *=============================================================================================*/
    121 void DriveClass::Response_Move(void)
    122 {
    123 	assert(IsActive);
    124 
    125 	static VocType _response[] = {
    126 		VOC_ACKNOWL,
    127 		VOC_AFFIRM,
    128 	};
    129 	VocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];
    130 	if (AllowVoice) {
    131 		Sound_Effect(response, fixed(1), -(ID+1));
    132 	}
    133 }
    134 
    135 
    136 /***********************************************************************************************
    137  * DriveClass::Response_Attack -- Voice feedback when ordering the unit to attack a target.    *
    138  *                                                                                             *
    139  *    This plays the audio feedback when ordering this unit to attack.                         *
    140  *                                                                                             *
    141  * INPUT:   none                                                                               *
    142  *                                                                                             *
    143  * OUTPUT:  none                                                                               *
    144  *                                                                                             *
    145  * WARNINGS:   none                                                                            *
    146  *                                                                                             *
    147  * HISTORY:                                                                                    *
    148  *   12/30/1994 JLB : Created.                                                                 *
    149  *=============================================================================================*/
    150 void DriveClass::Response_Attack(void)
    151 {
    152 	assert(IsActive);
    153 
    154 	static VocType _response[] = {
    155 		VOC_AFFIRM,
    156 		VOC_ACKNOWL
    157 	};
    158 	VocType response = _response[Sim_Random_Pick(0, ARRAY_SIZE(_response)-1)];
    159 	if (AllowVoice) {
    160 		Sound_Effect(response, fixed(1), -(ID+1));
    161 	}
    162 }
    163 
    164 
    165 /***********************************************************************************************
    166  * DriveClass::Scatter -- Causes the unit to travel to a nearby safe cell.                     *
    167  *                                                                                             *
    168  *    This routine is called when the unit discovers that it should get out of the "hot seat"  *
    169  *    and move to an adjacent cell. Since the safety of the adjacent cell is not determined    *
    170  *    before the move begins, it will appear that the unit is just scattering (which it        *
    171  *    should).                                                                                 *
    172  *                                                                                             *
    173  * INPUT:   threat   -- The coordinate of the source of the threat. The unit will try to move  *
    174  *                      roughly away from the threat.                                          *
    175  *                                                                                             *
    176  *          forced   -- The threat is real and a serious effort to scatter should be made.     *
    177  *                                                                                             *
    178  *          nokidding-- The scatter should affect the player's infantry even if it otherwise   *
    179  *                      wouldn't have.                                                         *
    180  *                                                                                             *
    181  * OUTPUT:  none                                                                               *
    182  *                                                                                             *
    183  * WARNINGS:   none                                                                            *
    184  *                                                                                             *
    185  * HISTORY:                                                                                    *
    186  *   09/25/1994 JLB : Created.                                                                 *
    187  *   09/27/1995 JLB : Revised to never scatter if already moving.                              *
    188  *   07/09/1996 JLB : Moved to DriveClass so that ships will scatter too.                      *
    189  *   08/02/1996 JLB : Added the "nokidding" parameter.                                         *
    190  *=============================================================================================*/
    191 void DriveClass::Scatter(COORDINATE threat, bool forced, bool nokidding)
    192 {
    193 	assert(IsActive);
    194 
    195 	/*
    196 	**	Certain missions prevent scattering regardless of whether it would be
    197 	**	a good idea or not.
    198 	*/
    199 	if (MissionControl[Mission].IsParalyzed) return;
    200 
    201 	if ((What_Am_I() != RTTI_UNIT || !((UnitClass *)this)->IsDumping) && (!Target_Legal(NavCom) || (nokidding && !IsRotating))) {
    202 		if (!Target_Legal(TarCom) || forced || Random_Pick(1, 4) == 1) {
    203 			FacingType	toface;
    204 			FacingType	newface;
    205 			CELL			newcell;
    206 
    207 			if (threat != 0) {
    208 				toface = Dir_Facing(Direction8(threat, Coord));
    209 				toface = toface + FacingType(Random_Pick(0, 2)-1);
    210 			} else {
    211 				toface = Dir_Facing(PrimaryFacing.Current());
    212 				toface = toface + FacingType(Random_Pick(0, 2)-1);
    213 			}
    214 
    215 			for (FacingType face = FACING_N; face < FACING_COUNT; face++) {
    216 				newface = toface + face;
    217 				newcell = Adjacent_Cell(Coord_Cell(Coord), newface);
    218 
    219 				if (Map.In_Radar(newcell) && Can_Enter_Cell(newcell) == MOVE_OK) {
    220 					Assign_Destination(::As_Target(newcell));
    221 				}
    222 			}
    223 		}
    224 	}
    225 }
    226 
    227 
    228 /***********************************************************************************************
    229  * DriveClass::Limbo -- Prepares vehicle and then limbos it.                                   *
    230  *                                                                                             *
    231  *    This routine removes the occupation bits for the vehicle and also handles cleaning up    *
    232  *    any vehicle reservation bits. After this, it then proceeds with limboing the unit.       *
    233  *                                                                                             *
    234  * INPUT:   none                                                                               *
    235  *                                                                                             *
    236  * OUTPUT:  bool; Was the vehicle limboed?                                                     *
    237  *                                                                                             *
    238  * WARNINGS:   none                                                                            *
    239  *                                                                                             *
    240  * HISTORY:                                                                                    *
    241  *   12/22/1994 JLB : Created.                                                                 *
    242  *=============================================================================================*/
    243 bool DriveClass::Limbo(void)
    244 {
    245 	if (!IsInLimbo) {
    246 		Stop_Driver();
    247 		TrackNumber = -1;
    248 	}
    249 	return(FootClass::Limbo());
    250 }
    251 
    252 
    253 /***********************************************************************************************
    254  * DriveClass::Stop_Driver -- Handles removing occupation bits when driving stops.             *
    255  *                                                                                             *
    256  *    This routine will remove the "reservation" flag (if present) when the vehicle is         *
    257  *    required to stop movement.                                                               *
    258  *                                                                                             *
    259  * INPUT:   none                                                                               *
    260  *                                                                                             *
    261  * OUTPUT:  bool; Was the vehicle stopped?                                                     *
    262  *                                                                                             *
    263  * WARNINGS:   none                                                                            *
    264  *                                                                                             *
    265  * HISTORY:                                                                                    *
    266  *   12/22/1994 JLB : Created.                                                                 *
    267  *=============================================================================================*/
    268 bool DriveClass::Stop_Driver(void)
    269 {
    270 	assert(IsActive);
    271 
    272 	/*
    273 	** We only need to do something if the vehicle is actually going
    274 	** somewhere.
    275 	*/
    276 	if (Head_To_Coord()) {
    277 
    278 		/*
    279 		** Safe off whether the vehicle is down or not so we know whether
    280 		** we have to put it back down.
    281 		*/
    282 		int temp = IsDown;
    283 
    284 		/*
    285 		** If the vehicle is down, pick it up so it doesn't interfere with
    286 		** our flags.
    287 		*/
    288 		if (temp) {
    289 			Mark(MARK_UP);
    290 		}
    291 
    292 		/*
    293 		** Call the drive class function which will let us release the
    294 		** reserved track.
    295 		*/
    296 		Mark_Track(Head_To_Coord(), MARK_UP);
    297 
    298 		/*
    299 		** If it was down it should be down when we are done.
    300 		*/
    301 		if (temp) {
    302 			Mark(MARK_DOWN);
    303 		}
    304 	}
    305 	return(FootClass::Stop_Driver());
    306 }
    307 
    308 
    309 /***********************************************************************************************
    310  * DriveClass::Do_Turn -- Tries to turn the vehicle to the specified direction.                *
    311  *                                                                                             *
    312  *    This routine will set the vehicle to rotate to the direction specified. For tracked      *
    313  *    vehicles, it is just a simple rotation. For wheeled vehicles, it performs a series       *
    314  *    of short drives (three point turn) to face the desired direction.                        *
    315  *                                                                                             *
    316  * INPUT:   dir   -- The direction that this vehicle should face.                              *
    317  *                                                                                             *
    318  * OUTPUT:  none                                                                               *
    319  *                                                                                             *
    320  * WARNINGS:   none                                                                            *
    321  *                                                                                             *
    322  * HISTORY:                                                                                    *
    323  *   05/29/1995 JLB : Created.                                                                 *
    324  *=============================================================================================*/
    325 void DriveClass::Do_Turn(DirType dir)
    326 {
    327 	assert(IsActive);
    328 
    329 	if (dir != PrimaryFacing) {
    330 
    331 #ifdef TOFIX
    332 		/*
    333 		**	Special rotation track is needed for units that
    334 		**	cannot rotate in place.
    335 		*/
    336 		if (Special.IsThreePoint && TrackNumber == -1 && Techno_Type_Class()->Speed == SPEED_WHEEL) {
    337 			int			facediff;	// Signed difference between current and desired facing.
    338 			FacingType	face;			// Current facing (ordinal value).
    339 
    340 			facediff = PrimaryFacing.Difference(dir) >> 5;
    341 			facediff = Bound(facediff, -2, 2);
    342 			if (facediff) {
    343 				face = Dir_Facing(PrimaryFacing);
    344 
    345 				IsOnShortTrack = true;
    346 				Force_Track(face*FACING_COUNT + (face + facediff), Coord);
    347 
    348 				Path[0] = FACING_NONE;
    349 				Set_Speed(0xFF);		// Full speed.
    350 			}
    351 		} else {
    352 			PrimaryFacing.Set_Desired(dir);
    353 		}
    354 #else
    355 			PrimaryFacing.Set_Desired(dir);
    356 //			IsRotating = true;
    357 #endif
    358 	}
    359 }
    360 
    361 
    362 /***********************************************************************************************
    363  * DriveClass::Teleport_To -- Teleport object to specified location.                           *
    364  *                                                                                             *
    365  *    This will teleport the object to the specified location or as close as possible to it    *
    366  *    if the destination is blocked.                                                           *
    367  *                                                                                             *
    368  * INPUT:   cell  -- The desired destination cell to teleport to.                              *
    369  *                                                                                             *
    370  * OUTPUT:  bool; Was the teleport successful?                                                 *
    371  *                                                                                             *
    372  * WARNINGS:   All current activity of this object will be terminated by the teleport. It will *
    373  *             arrive at the destination in static guard mode.                                 *
    374  *                                                                                             *
    375  * HISTORY:                                                                                    *
    376  *   10/21/1996 JLB : Created.                                                                 *
    377  *   10/31/1996 JLB : Handles flag teleport case.                                              *
    378  *=============================================================================================*/
    379 bool DriveClass::Teleport_To(CELL cell)
    380 {
    381 	/*
    382 	**	All cargo gets destroyed.
    383 	*/
    384 	if (Rule.IsChronoKill) {
    385 		Kill_Cargo(NULL);
    386 	}
    387 
    388 	Stop_Driver();
    389 	Force_Track(-1, 0);
    390 	PrimaryFacing.Set_Current(PrimaryFacing.Desired());
    391 	Transmit_Message(RADIO_OVER_OUT);
    392 	Assign_Destination(TARGET_NONE);
    393 	Assign_Target(TARGET_NONE);
    394 	Assign_Mission(MISSION_NONE);
    395 	Commence();
    396 	Mark(MARK_UP);
    397 
    398 	/*
    399 	**	A teleported unit will drop the flag right where it's at.
    400 	*/
    401 	if (What_Am_I() == RTTI_UNIT && ((UnitClass *)this)->Flagged != HOUSE_NONE) {
    402 		HouseClass::As_Pointer(((UnitClass *)this)->Flagged)->Flag_Attach(Coord_Cell(Coord));
    403 	}
    404 
    405 	if (Can_Enter_Cell(cell) != MOVE_OK) {
    406 		cell = Map.Nearby_Location(cell, Techno_Type_Class()->Speed);
    407 	}
    408 	Coord = Cell_Coord(cell);
    409 	Mark(MARK_DOWN);
    410 	Look(false);
    411 	Per_Cell_Process(PCP_END);
    412 	return(true);
    413 }
    414 
    415 
    416 /***********************************************************************************************
    417  * DriveClass::Force_Track -- Forces the unit to use the indicated track.                      *
    418  *                                                                                             *
    419  *    This override (nuclear bomb) style routine is to be used when a unit needs to start      *
    420  *    on a movement track but is outside the normal movement system. This occurs when a        *
    421  *    harvester starts driving off of a refinery.                                              *
    422  *                                                                                             *
    423  * INPUT:   track -- The track number to start on.                                             *
    424  *                                                                                             *
    425  *          coord -- The coordinate that the unit will end up at when the movement track       *
    426  *                   is completed.                                                             *
    427  *                                                                                             *
    428  * OUTPUT:  none                                                                               *
    429  *                                                                                             *
    430  * WARNINGS:   none                                                                            *
    431  *                                                                                             *
    432  * HISTORY:                                                                                    *
    433  *   03/17/1995 JLB : Created.                                                                 *
    434  *=============================================================================================*/
    435 void DriveClass::Force_Track(int track, COORDINATE coord)
    436 {
    437 	assert(IsActive);
    438 
    439 	TrackNumber = track;
    440 	TrackIndex = 0;
    441 	if (coord != 0) {
    442 		Start_Driver(coord);
    443 	}
    444 }
    445 
    446 
    447 /***********************************************************************************************
    448  * DriveClass::DriveClass -- Constructor for drive class object.                               *
    449  *                                                                                             *
    450  *    This will initialize the drive class to its default state. It is called as a result      *
    451  *    of creating a unit.                                                                      *
    452  *                                                                                             *
    453  * INPUT:   classid  -- The unit's ID class. It is passed on to the foot class constructor.    *
    454  *                                                                                             *
    455  * OUTPUT:  none                                                                               *
    456  *                                                                                             *
    457  * WARNINGS:   none                                                                            *
    458  *                                                                                             *
    459  * HISTORY:                                                                                    *
    460  *   07/13/1994 JLB : Created.                                                                 *
    461  *=============================================================================================*/
    462 DriveClass::DriveClass(RTTIType rtti, int id, HousesType house) :
    463 	FootClass(rtti, id, house),
    464 	IsMoebius(false),
    465 	IsHarvesting(false),
    466 	IsTurretLockedDown(false),
    467 	IsOnShortTrack(false),
    468 	SpeedAccum(0),
    469 	MoebiusCountDown(0),
    470 	MoebiusCell(0),
    471 	TrackNumber(-1),
    472 	TrackIndex(0)
    473 {
    474 }
    475 
    476 
    477 #ifdef CHEAT_KEYS
    478 /***********************************************************************************************
    479  * DriveClass::Debug_Dump -- Displays status information to monochrome screen.                 *
    480  *                                                                                             *
    481  *    This debug utility function will display the status of the drive class to the mono       *
    482  *    screen. It is through this information that bugs can be tracked down.                    *
    483  *                                                                                             *
    484  * INPUT:   none                                                                               *
    485  *                                                                                             *
    486  * OUTPUT:  none                                                                               *
    487  *                                                                                             *
    488  * WARNINGS:   none                                                                            *
    489  *                                                                                             *
    490  * HISTORY:                                                                                    *
    491  *   05/31/1994 JLB : Created.                                                                 *
    492  *=============================================================================================*/
    493 void DriveClass::Debug_Dump(MonoClass * mono) const
    494 {
    495 	assert(IsActive);
    496 
    497 	mono->Fill_Attrib(66, 14, 12, 1, IsMoebius ? MonoClass::INVERSE : MonoClass::NORMAL);
    498 	FootClass::Debug_Dump(mono);
    499 }
    500 #endif
    501 
    502 
    503 /***********************************************************************************************
    504  * DriveClass::Smooth_Turn -- Handles the low level coord calc for smooth turn logic.          *
    505  *                                                                                             *
    506  *    This routine calculates the new coordinate value needed for the                          *
    507  *    smooth turn logic. The adjustment and flag values must be                                *
    508  *    determined prior to entering this routine.                                               *
    509  *                                                                                             *
    510  * INPUT:   adj      -- The adjustment coordinate as lifted from the                           *
    511  *                      correct smooth turn table.                                             *
    512  *                                                                                             *
    513  *          dir      -- Pointer to dir for possible modification                               *
    514  *                      according to the flag bits.                                            *
    515  *                                                                                             *
    516  * OUTPUT:  Returns with the coordinate the unit should positioned to.                         *
    517  *                                                                                             *
    518  * WARNINGS:   none                                                                            *
    519  *                                                                                             *
    520  * HISTORY:                                                                                    *
    521  *   03/14/1994 JLB : Created.                                                                 *
    522  *   07/13/1994 JLB : Converted to member function.                                            *
    523  *=============================================================================================*/
    524 COORDINATE DriveClass::Smooth_Turn(COORDINATE adj, DirType & dir)
    525 {
    526 	assert(IsActive);
    527 
    528 	DirType workdir = dir;
    529 	int x,y;
    530 	int temp;
    531 	TrackControlType flags = TrackControl[TrackNumber].Flag;
    532 
    533 	x = Coord_X(adj);
    534 	y = Coord_Y(adj);
    535 
    536 	if (flags & F_T) {
    537 		temp	= x;
    538 		x		= y;
    539 		y 		= temp;
    540 		workdir = (DirType)(DIR_W - workdir);
    541 	}
    542 
    543 	if (flags & F_X) {
    544 		x 		 = -x;
    545 		workdir = (DirType)-workdir;
    546 	}
    547 
    548 	if (flags & F_Y) {
    549 		y = -y;
    550 		workdir = (DirType)(DIR_S - workdir);
    551 	}
    552 
    553 	dir = workdir;
    554 
    555 	return(XY_Coord( (LEPTON)(Coord_X(Head_To_Coord()) + x), (LEPTON)(Coord_Y(Head_To_Coord()) + y)));
    556 }
    557 
    558 
    559 /***********************************************************************************************
    560  * DriveClass::Assign_Destination -- Set the unit's NavCom.                                    *
    561  *                                                                                             *
    562  *    This routine is used to set the unit's navigation computer to the                        *
    563  *    specified target. Once the navigation computer is set, the unit                          *
    564  *    will start planning and moving toward the destination.                                   *
    565  *                                                                                             *
    566  * INPUT:   target   -- The destination target for the unit to head to.                        *
    567  *                                                                                             *
    568  * OUTPUT:  none                                                                               *
    569  *                                                                                             *
    570  * WARNINGS:   none                                                                            *
    571  *                                                                                             *
    572  * HISTORY:                                                                                    *
    573  *   09/07/1992 JLB : Created.                                                                 *
    574  *   04/15/1994 JLB : Converted to member function.                                            *
    575  *=============================================================================================*/
    576 void DriveClass::Assign_Destination(TARGET target)
    577 {
    578 	assert(IsActive);
    579 
    580 	/*
    581 	**	Abort early if there is anything wrong with the parameters
    582 	**	or the unit already is assigned the specified destination.
    583 	*/
    584 	if (target == NavCom) return;
    585 
    586 	/*
    587 	**	For harvesting type vehicles, it might go into a dock and unload procedure
    588 	**	when the harvester is full and an empty refinery is selected as a target.
    589 	*/
    590 	BuildingClass * b = As_Building(target);
    591 
    592 	/*
    593 	**	If the player clicked on refinery but it is not busy, then assign
    594 	**	it to unload at the refinery.
    595 	*/
    596 	if (b != NULL && *b == STRUCT_REFINERY && What_Am_I() == RTTI_UNIT && ((UnitTypeClass *)Techno_Type_Class())->IsToHarvest) {
    597 		if (Contact_With_Whom() != b && !b->In_Radio_Contact()) {
    598 			/*
    599 			**	Establish radio contact protocol. If the facility responds correctly,
    600 			**	then remain in radio contact and proceed toward the desired destination.
    601 			*/
    602 			if (Transmit_Message(RADIO_HELLO, b) == RADIO_ROGER) {
    603 				if (Mission != MISSION_ENTER && Mission != MISSION_HARVEST) {
    604 					Assign_Mission(MISSION_ENTER);
    605 					target = TARGET_NONE;
    606 				} else {
    607 //					target = TARGET_NONE;
    608 				}
    609 			} else {
    610 //				target = TARGET_NONE;
    611 			}
    612 		} else {
    613 //			target = TARGET_NONE;
    614 		}
    615 	}
    616 
    617 	/*
    618 	**	Set the unit's navigation computer.
    619 	*/
    620 	FootClass::Assign_Destination(target);
    621 
    622 	Path[0] = FACING_NONE;			// Force recalculation of path.
    623 	if (!IsDriving && Mission != MISSION_UNLOAD) {
    624 		Start_Of_Move();
    625 	}
    626 }
    627 
    628 
    629 /***********************************************************************************************
    630  * DriveClass::While_Moving -- Processes unit movement.                                        *
    631  *                                                                                             *
    632  *    This routine is used to process movement for the units as they move.                     *
    633  *    It is called many times for each cell's worth of movement.   This                        *
    634  *    routine only applies after the next cell HeadTo has been determined.                     *
    635  *                                                                                             *
    636  * INPUT:   none                                                                               *
    637  *                                                                                             *
    638  * OUTPUT:  true/false; Should this routine be called again?                                   *
    639  *                                                                                             *
    640  * WARNINGS:   none                                                                            *
    641  *                                                                                             *
    642  * HISTORY:                                                                                    *
    643  *   02/02/1992 JLB : Created.                                                                 *
    644  *   04/15/1994 JLB : Converted to member function.                                            *
    645  *=============================================================================================*/
    646 bool DriveClass::While_Moving(void)
    647 {
    648 	assert(IsActive);
    649 
    650 	/*
    651 	**	Perform quick legality checks.
    652 	*/
    653 	if (!IsDriving || TrackNumber == -1 || (IsRotating && !Techno_Type_Class()->IsTurretEquipped)) {
    654 		SpeedAccum = 0;		// Kludge?  No speed should accumulate if movement is on hold.
    655 		return(false);
    656 	}
    657 
    658 	/*
    659 	**	If enough movement has accumulated so that the unit can
    660 	**	visibly move on the map, then process accordingly.
    661 	** Slow the unit down if he's carrying a flag.
    662 	*/
    663 	MPHType maxspeed = MPHType(min(Techno_Type_Class()->MaxSpeed * SpeedBias * House->GroundspeedBias, (int)MPH_LIGHT_SPEED));
    664 	if (IsFormationMove) maxspeed = FormationMaxSpeed;
    665 
    666 	int actual;			// Working movement addition value.
    667 	if (((UnitClass *)this)->Flagged != HOUSE_NONE) {
    668 		actual = SpeedAccum + ((int)maxspeed/2) * fixed(Speed, 256);
    669 	} else {
    670 		actual = SpeedAccum + maxspeed * fixed(Speed, 256);
    671 	}
    672 
    673 	if (actual > PIXEL_LEPTON_W) {
    674 		TurnTrackType	const * track;	// Track control pointer.
    675 		TrackType		const	* ptr;		// Pointer to coord offset values.
    676 		int				tracknum;		// The track number being processed.
    677 		FacingType		nextface;		// Next facing queued in path.
    678 		bool				adj;				// Is a turn coming up?
    679 
    680 		track = &TrackControl[TrackNumber];
    681 		if (IsOnShortTrack) {
    682 			tracknum = track->StartTrack;
    683 		} else {
    684 			tracknum = track->Track;
    685 		}
    686 		ptr = RawTracks[tracknum-1].Track;
    687 		nextface = Path[0];
    688 
    689 		/*
    690 		**	Determine if there is a turn coming up. If there is
    691 		**	a turn, then track jumping might occur.
    692 		*/
    693 		adj = false;
    694 		if (nextface != FACING_NONE && Dir_Facing(track->Facing) != nextface) {
    695 			adj = true;
    696 		}
    697 
    698 		/*
    699 		**	Skip ahead the number of track steps required (limited only
    700 		**	by track length). Set the unit to the new position and
    701 		**	flag the unit accordingly.
    702 		*/
    703 		Mark(MARK_UP);
    704 		while (actual > PIXEL_LEPTON_W) {
    705 			COORDINATE		offset;
    706 			DirType	dir;
    707 
    708 			actual -= PIXEL_LEPTON_W;
    709 
    710 			offset = ptr[TrackIndex].Offset;
    711 			if (offset || !TrackIndex) {
    712 				dir = ptr[TrackIndex].Facing;
    713 				Coord = Smooth_Turn(offset, dir);
    714 
    715 				PrimaryFacing.Set(dir);
    716 
    717 				/*
    718 				**	See if "per cell" processing is necessary.
    719 				*/
    720 				if (TrackIndex && RawTracks[tracknum-1].Cell == TrackIndex) {
    721 					Mark(MARK_DOWN);
    722 					Per_Cell_Process(PCP_DURING);
    723 					if (!IsActive) {
    724 						return(false);
    725 					}
    726 					Mark(MARK_UP);
    727 				}
    728 
    729 				/*
    730 				**	The unit could "jump tracks". Check to see if the unit should
    731 				**	do so.
    732 				*/
    733 				if (/**this != UNIT_GUNBOAT &&*/ nextface != FACING_NONE && adj && RawTracks[tracknum-1].Jump == TrackIndex && TrackIndex) {
    734 					TurnTrackType const * newtrack;		// Proposed jump-to track.
    735 					int	tnum;
    736 
    737 					tnum = (int)(Dir_Facing(track->Facing) * FACING_COUNT) + (int)nextface;
    738 					newtrack = &TrackControl[tnum];
    739 					if (newtrack->Track && RawTracks[newtrack->Track-1].Entry) {
    740 						COORDINATE	c = Head_To_Coord();
    741 						int oldspeed = Speed;
    742 
    743 						c = Adjacent_Cell(c, nextface);
    744 
    745 						switch (Can_Enter_Cell(Coord_Cell(c), nextface)) {
    746 							case MOVE_OK:
    747 								IsOnShortTrack = false;		// Shouldn't be necessary, but...
    748 								TrackNumber = tnum;
    749 								track = newtrack;
    750 
    751 								tracknum = track->Track;
    752 								TrackIndex = RawTracks[tracknum-1].Entry-1;	// Anticipate increment.
    753 								ptr = RawTracks[tracknum-1].Track;
    754 								adj = false;
    755 
    756 								Stop_Driver();
    757 								IsDriving = true;
    758 								Per_Cell_Process(PCP_END);
    759 								IsDriving = false;
    760 								if (!IsActive) return(false);
    761 								if (Start_Driver(c)) {
    762 									Set_Speed(oldspeed);
    763 									memcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);
    764 									Path[CONQUER_PATH_MAX-1] = FACING_NONE;
    765 								} else {
    766 									Path[0] = FACING_NONE;
    767 									TrackNumber = -1;
    768 									actual = 0;
    769 								}
    770 								break;
    771 
    772 							case MOVE_CLOAK:
    773 								Map[c].Shimmer();
    774 								break;
    775 
    776 							case MOVE_TEMP:
    777 #ifdef TOFIX
    778 								if (*this == UNIT_HARVESTER || !House->IsHuman) {
    779 #else
    780 								if (!House->IsHuman) {
    781 #endif
    782 									Map[c].Incoming(0, true, true);
    783 								}
    784 								break;
    785 						}
    786 					}
    787 				}
    788 				TrackIndex++;
    789 
    790 			} else {
    791 				actual = 0;
    792 				Coord = Head_To_Coord();
    793 				Stop_Driver();
    794 				TrackNumber = -1;
    795 				TrackIndex = NULL;
    796 
    797 				/*
    798 				**	Perform "per cell" activities.
    799 				*/
    800 				Mark(MARK_DOWN);
    801 				Per_Cell_Process(PCP_END);
    802 				if (!IsActive) return(false);
    803 				Mark(MARK_UP);
    804 
    805 				break;
    806 			}
    807 		}
    808 		if (IsActive) {
    809 			Mark(MARK_DOWN);
    810 		}
    811 	}
    812 
    813 	/*
    814 	**	Replace any remainder back into the unit's movement
    815 	**	accumulator to be processed next pass.
    816 	*/
    817 	SpeedAccum = actual;
    818 	return(true);
    819 }
    820 
    821 
    822 /***********************************************************************************************
    823  * DriveClass::Per_Cell_Process -- Handles when unit finishes movement into a cell.            *
    824  *                                                                                             *
    825  *    This routine is called when a unit has mostly or completely                              *
    826  *    entered a cell. The unit might be in the middle of a movement track                      *
    827  *    when this routine is called. It's primary purpose is to perform                          *
    828  *    sighting and other "per cell" activities.                                                *
    829  *                                                                                             *
    830  * INPUT:   why   -- Specifies the circumstances under which this routine was called.          *
    831  *                                                                                             *
    832  * OUTPUT:  none                                                                               *
    833  *                                                                                             *
    834  * WARNINGS:   none                                                                            *
    835  *                                                                                             *
    836  * HISTORY:                                                                                    *
    837  *   11/03/1993 JLB : Created.                                                                 *
    838  *   03/30/1994 JLB : Revamped for track system.                                               *
    839  *   04/15/1994 JLB : Converted to member function.                                            *
    840  *   06/18/1994 JLB : Converted to virtual function.                                           *
    841  *   06/18/1994 JLB : Distinguishes between center and near-center conditions.                 *
    842  *=============================================================================================*/
    843 void DriveClass::Per_Cell_Process(PCPType why)
    844 {
    845 	assert(IsActive);
    846 
    847 	if (why == PCP_END) {
    848 		CELL	cell = Coord_Cell(Coord);
    849 
    850 		/*
    851 		**	Check to see if it has reached its destination. If so, then clear the NavCom
    852 		**	regardless of the remaining path list.
    853 		*/
    854 		if (As_Cell(NavCom) == cell) {
    855 			IsTurretLockedDown = false;
    856 			NavCom = TARGET_NONE;
    857 			Path[0] = FACING_NONE;
    858 		}
    859 
    860 		Lay_Track();
    861 	}
    862 
    863 	FootClass::Per_Cell_Process(why);
    864 }
    865 
    866 
    867 /***********************************************************************************************
    868  * DriveClass::Start_Of_Move -- Tries to get a unit to advance toward cell.                    *
    869  *                                                                                             *
    870  *    This will try to start a unit advancing toward the cell it is                            *
    871  *    facing. It will check for and handle legality and reserving of the                       *
    872  *    necessary cell.                                                                          *
    873  *                                                                                             *
    874  * INPUT:   none                                                                               *
    875  *                                                                                             *
    876  * OUTPUT:  true/false; Should this routine be called again because                            *
    877  *                      initial start operation is temporarily delayed?                        *
    878  *                                                                                             *
    879  * WARNINGS:   none                                                                            *
    880  *                                                                                             *
    881  * HISTORY:                                                                                    *
    882  *   02/02/1992 JLB : Created.                                                                 *
    883  *   10/18/1993 JLB : This should be called repeatedly until HeadTo is not NULL.               *
    884  *   03/16/1994 JLB : Revamped for track logic.                                                *
    885  *   04/15/1994 JLB : Converted to member function.                                            *
    886  *   06/19/1995 JLB : Fixed so that it won't fire on ground unnecessarily.                     *
    887  *   07/13/1995 JLB : Handles bumping into cloaked objects.                                    *
    888  *   09/22/1995 JLB : Breaks out of hopeless hunt mode.                                        *
    889  *   07/10/1996 JLB : Sets scan limit if necessary.                                            *
    890  *=============================================================================================*/
    891 bool DriveClass::Start_Of_Move(void)
    892 {
    893 	assert(IsActive);
    894 
    895 	FacingType		facing;				// Direction movement will commence.
    896 	DirType			dir;				// Desired actual facing toward destination.
    897 	int				facediff;			// Difference between current and desired facing.
    898 	int				speed;				// Speed of unit.
    899 	CELL				destcell;			// Cell of destination.
    900 	LandType			ground;				// Ground unit is entering.
    901 	COORDINATE				dest;					// Destination coordinate.
    902 
    903 	facing = Path[0];
    904 
    905 	if (!Target_Legal(NavCom) && facing == FACING_NONE) {
    906 		IsTurretLockedDown = false;
    907 		Stop_Driver();
    908 		if (Mission == MISSION_MOVE) {
    909 			Enter_Idle_Mode();
    910 		}
    911 		return(false);		// Why is it calling this routine!?!
    912 	}
    913 
    914 	/*
    915 	**	Reduce the path length if the target is a unit and the
    916 	**	range to the unit is less than the precalculated path steps.
    917 	*/
    918 	if (facing != FACING_NONE) {
    919 		int	dist;
    920 
    921 		if (Is_Target_Vessel(NavCom) || Is_Target_Unit(NavCom) || Is_Target_Infantry(NavCom)) {
    922 			dist = Lepton_To_Cell((LEPTON)Distance(NavCom));
    923 
    924 			if (dist < ARRAY_SIZE(Path)) {
    925 				Path[dist] = FACING_NONE;
    926 				facing = Path[0];		// Maybe needed.
    927 			}
    928 		}
    929 	}
    930 
    931 	/*
    932 	**	If the path is invalid at this point, then generate one. If
    933 	**	generating a new path fails, then abort NavCom.
    934 	*/
    935 	if (facing == FACING_NONE) {
    936 
    937 		/*
    938 		**	If after a path search, there is still no valid path, then set the
    939 		**	NavCom to null and let the script take care of assigning a new
    940 		**	navigation target.
    941 		*/
    942 		if (PathDelay != 0) {
    943 			return(false);
    944 		}
    945 
    946 		if (!Basic_Path()) {
    947 
    948 			/*
    949 			**	If the unit is close enough to the target then just stop
    950 			**	driving now. This prevents the fidgeting that would occur
    951 			**	if they mindlessly kept trying to get to the exact location
    952 			**	desired. This is quite necessary since it is typical to move
    953 			**	several units with the same mouse click.
    954 			*/
    955 			if (!Is_On_Priority_Mission() && Distance(NavCom) < Rule.CloseEnoughDistance && (Mission == MISSION_MOVE || Mission == MISSION_GUARD_AREA)) {
    956 				Assign_Destination(TARGET_NONE);
    957 				if (!IsActive) return(false);
    958 			} else {
    959 				/*
    960 				**	If a basic path could not be found, but the immediate move destination is
    961 				**	blocked by a friendly temporary blockage, then cause that blockage
    962 				**	to scatter.
    963 				*/
    964 				CELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), PrimaryFacing.Current());
    965 				if (Map.In_Radar(cell)) {
    966 					MoveType ok = Can_Enter_Cell(cell);
    967 					if (ok == MOVE_TEMP) {
    968 						CellClass * cellptr = &Map[cell];
    969 						TechnoClass * blockage = cellptr->Cell_Techno();
    970 						if (blockage && House->Is_Ally(blockage)) {
    971 
    972 							/*
    973 							**	If the target can be told to get out of the way, only bother
    974 							**	to do so if we aren't very close to the target and this
    975 							**	object can just say "good enough" and stop here.
    976 							*/
    977 							if (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {
    978 								Assign_Destination(TARGET_NONE);
    979 								return(false);
    980 							} else {
    981 								cellptr->Incoming(0, true, false);
    982 //								cellptr->Incoming(0, true, true);
    983 							}
    984 						}
    985 					}
    986 				}
    987 
    988 				if (TryTryAgain > 0) {
    989 					TryTryAgain--;
    990 				} else {
    991 					Assign_Destination(TARGET_NONE);
    992 					if (!IsActive) return(false);
    993 					if (IsNewNavCom) Sound_Effect(VOC_SCOLD);
    994 					IsNewNavCom = false;
    995 				}
    996 			}
    997 
    998 			/*
    999 			**	Since the path was blocked, check to make sure that it was completely
   1000 			**	blocked. If so and it has a valid TarCom and it is out of range of the
   1001 			**	TarCom, then give this unit a range limit so that it might not pick
   1002 			**	a "can't reach" target again.
   1003 			*/
   1004 			if (!Target_Legal(NavCom) && Target_Legal(TarCom) && !In_Range(TarCom)) {
   1005 				IsScanLimited = true;
   1006 				if (Team.Is_Valid()) Team->Scan_Limit();
   1007 				Assign_Target(TARGET_NONE);
   1008 			}
   1009 
   1010 			/*
   1011 			**	Stop the movement, for now, and let the subsequent logic in later game
   1012 			**	frames resume movement as appropriate.
   1013 			*/
   1014 			Stop_Driver();
   1015 			TrackNumber = -1;
   1016 			IsTurretLockedDown = false;
   1017 			return(false);
   1018 		}
   1019 
   1020 		/*
   1021 		**	If a basic path could be found, but the immediate move destination is
   1022 		**	blocked by a friendly temporary blockage, then cause that blockage
   1023 		**	to scatter.
   1024 		*/
   1025 		CELL cell = Adjacent_Cell(Coord_Cell(Center_Coord()), Path[0]);
   1026 		if (Map.In_Radar(cell)) {
   1027 			MoveType ok = Can_Enter_Cell(cell);
   1028 			if (ok == MOVE_TEMP) {
   1029 				CellClass * cellptr = &Map[cell];
   1030 				TechnoClass * blockage = cellptr->Cell_Techno();
   1031 				if (blockage && House->Is_Ally(blockage)) {
   1032 
   1033 					/*
   1034 					**	If the target can be told to get out of the way, only bother
   1035 					**	to do so if we aren't very close to the target and this
   1036 					**	object can just say "good enough" and stop here.
   1037 					*/
   1038 					if (Distance(NavCom) < Rule.CloseEnoughDistance && !In_Radio_Contact()) {
   1039 						Assign_Destination(TARGET_NONE);
   1040 						return(false);
   1041 					} else {
   1042 						cellptr->Incoming(0, true, false);
   1043 //						cellptr->Incoming(0, true, true);
   1044 					}
   1045 				}
   1046 			}
   1047 		}
   1048 
   1049 		TryTryAgain = PATH_RETRY;
   1050 		facing = Path[0];
   1051 	}
   1052 
   1053 	/*
   1054 	**	Determine the coordinate of the next cell to move into.
   1055 	*/
   1056 	dest = Adjacent_Cell(Coord, facing);
   1057 	dir = Facing_Dir(facing);
   1058 
   1059 	/*
   1060 	**	Set the facing correctly if it isn't already correct. This
   1061 	**	means starting a rotation track if necessary.
   1062 	*/
   1063 	facediff = PrimaryFacing.Difference(dir);
   1064 	if (facediff) {
   1065 
   1066 		/*
   1067 		**	Request a change of facing.
   1068 		*/
   1069 		Do_Turn(dir);
   1070 		return(true);
   1071 
   1072 	} else {
   1073 
   1074 		/* NOTE:  Beyond this point, actual track assignment can begin.
   1075 		**
   1076 		**	If the cell to move into is impassable (probably for some unexpected
   1077 		**	reason), then abort the path list and set the speed to zero. The
   1078 		** next time this routine is called, a new path will be generated.
   1079 		*/
   1080 		destcell = Coord_Cell(dest);
   1081 		Mark(MARK_UP);
   1082 		MoveType cando = Can_Enter_Cell(destcell, facing);
   1083 		Mark(MARK_DOWN);
   1084 
   1085 		if (cando != MOVE_OK) {
   1086 
   1087 			if (Mission == MISSION_MOVE /*KO&& House->IsHuman */&& Distance(NavCom) < Rule.CloseEnoughDistance) {
   1088 				Assign_Destination(TARGET_NONE);
   1089 				if (!IsActive) return(false);//BG
   1090 			}
   1091 
   1092 			/*
   1093 			**	If a temporary friendly object is blocking the path, then cause it to
   1094 			**	get out of the way.
   1095 			*/
   1096 			if (cando == MOVE_TEMP) {
   1097 				Map[destcell].Incoming(0, true, true);
   1098 			}
   1099 
   1100 			/*
   1101 			**	If a cloaked object is blocking, then shimmer the cell.
   1102 			*/
   1103 			if (cando == MOVE_CLOAK) {
   1104 				Map[destcell].Shimmer();
   1105 			}
   1106 
   1107 			Stop_Driver();
   1108 			if (cando != MOVE_MOVING_BLOCK) {
   1109 			 	Path[0] = FACING_NONE;		// Path is blocked!
   1110 			}
   1111 
   1112 			/*
   1113 			** If blocked by a moving block then just exit start of move and
   1114 			** try again next tick.
   1115 			*/
   1116 			if (cando == MOVE_DESTROYABLE) {
   1117 				if (Map[destcell].Cell_Object()) {
   1118 					if (!House->Is_Ally(Map[destcell].Cell_Object())) {
   1119 						Override_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);
   1120 					}
   1121 				} else {
   1122 					if (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {
   1123 						Override_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);
   1124 					}
   1125 				}
   1126 			} else {
   1127 				if (IsNewNavCom) Sound_Effect(VOC_SCOLD);
   1128 			}
   1129 			IsNewNavCom = false;
   1130 			TrackNumber = -1;
   1131 			return(true);
   1132 		}
   1133 
   1134 		/*
   1135 		**	Determine the speed that the unit can travel to the desired square.
   1136 		*/
   1137 		ground = Map[destcell].Land_Type();
   1138 		speed = Ground[ground].Cost[Techno_Type_Class()->Speed] * 255;
   1139 
   1140 		/* change speed if it's related to a team move */
   1141 		if (IsFormationMove) speed = Ground[ground].Cost[FormationSpeed] * 255;
   1142 		if (!speed) speed = 128;
   1143 
   1144 #ifdef NEVER
   1145 		/*
   1146 		**	Set the jiggle flag if the terrain would cause the unit
   1147 		**	to jiggle when travelled over.
   1148 		*/
   1149 		BaseF &= ~BASEF_JIGGLE;
   1150 		if (Ground[ground].Jiggle) {
   1151 			BaseF |= BASEF_JIGGLE;
   1152 		}
   1153 #endif
   1154 
   1155 		/*
   1156 		**	A damaged unit has a reduced speed.
   1157 		*/
   1158 		if (Health_Ratio() <= Rule.ConditionYellow /*(Techno_Type_Class()->MaxStrength>>1) > Strength*/) {
   1159 			speed -= (speed/4);	// Three quarters speed.
   1160 		}
   1161 		if ((speed != Speed)/* || !SpeedAdd*/) {
   1162 			Set_Speed(speed);		// Full speed.
   1163 		}
   1164 
   1165 		/*
   1166 		**	Reserve the destination cell so that it won't become
   1167 		**	occupied AS this unit is moving into it.
   1168 		*/
   1169 		if (cando != MOVE_OK) {
   1170 		 	Path[0] = FACING_NONE;		// Path is blocked!
   1171 			TrackNumber = -1;
   1172 		 	dest = NULL;
   1173 		} else {
   1174 
   1175 			Overrun_Square(Coord_Cell(dest), true);
   1176 
   1177 			/*
   1178 			**	Determine which track to use (based on recorded path).
   1179 			*/
   1180 			FacingType nextface = Path[1];
   1181 			if (nextface == FACING_NONE) nextface = facing;
   1182 
   1183 			IsOnShortTrack = false;
   1184 			TrackNumber = facing * FACING_COUNT + (int)nextface;
   1185 			if (TrackControl[TrackNumber].Track == 0) {
   1186 				Path[0] = FACING_NONE;
   1187 				TrackNumber = -1;
   1188 				return(true);
   1189 			} else {
   1190 				if (TrackControl[TrackNumber].Flag & F_D) {
   1191 					/*
   1192 					**	If the middle cell of a two cell track contains a crate,
   1193 					**	the check for goodies before movement starts.
   1194 					*/
   1195 					if (!Map[destcell].Goodie_Check(this)) {
   1196 						cando = MOVE_NO;
   1197 						if (!IsActive) return(false);
   1198 					} else {
   1199 						if (!IsActive) return(false);
   1200 						dest = Adjacent_Cell(dest, nextface);
   1201 						destcell = Coord_Cell(dest);
   1202 						cando = Can_Enter_Cell(destcell);
   1203 					}
   1204 					if (!IsActive) return(false);
   1205 
   1206 					if (cando != MOVE_OK) {
   1207 
   1208 						/*
   1209 						**	If a temporary friendly object is blocking the path, then cause it to
   1210 						**	get out of the way.
   1211 						*/
   1212 						if (cando == MOVE_TEMP) {
   1213 							Map[destcell].Incoming(0, true, true);
   1214 						}
   1215 
   1216 						/*
   1217 						**	If a cloaked object is blocking, then shimmer the cell.
   1218 						*/
   1219 						if (cando == MOVE_CLOAK) {
   1220 							Map[destcell].Shimmer();
   1221 						}
   1222 
   1223 						Path[0] = FACING_NONE;		// Path is blocked!
   1224 						TrackNumber = -1;
   1225 						dest = NULL;
   1226 						if (cando == MOVE_DESTROYABLE) {
   1227 
   1228 							if (Map[destcell].Cell_Object()) {
   1229 								if (!House->Is_Ally(Map[destcell].Cell_Object())) {
   1230 									Override_Mission(MISSION_ATTACK, Map[destcell].Cell_Object()->As_Target(), TARGET_NONE);
   1231 								}
   1232 							} else {
   1233 								if (Map[destcell].Overlay != OVERLAY_NONE && OverlayTypeClass::As_Reference(Map[destcell].Overlay).IsWall) {
   1234 									Override_Mission(MISSION_ATTACK, ::As_Target(destcell), TARGET_NONE);
   1235 								}
   1236 							}
   1237 							IsNewNavCom = false;
   1238 							TrackIndex = 0;
   1239 							return(true);
   1240 						}
   1241 					} else {
   1242 						memcpy((char*)&Path[0], (char*)&Path[2], CONQUER_PATH_MAX-2);
   1243 						Path[CONQUER_PATH_MAX-2] = FACING_NONE;
   1244 						IsPlanningToLook = true;
   1245 					}
   1246 				} else {
   1247 					memcpy((char*)&Path[0], (char*)&Path[1], CONQUER_PATH_MAX-1);
   1248 				}
   1249 				Path[CONQUER_PATH_MAX-1] = FACING_NONE;
   1250 			}
   1251 		}
   1252 
   1253 		IsNewNavCom = false;
   1254 		TrackIndex = 0;
   1255 		if (!Start_Driver(dest)) {
   1256 			TrackNumber = -1;
   1257 			Path[0] = FACING_NONE;
   1258 			Set_Speed(0);
   1259 		}
   1260 	}
   1261 	return(false);
   1262 }
   1263 
   1264 
   1265 /***********************************************************************************************
   1266  * DriveClass::AI -- Processes unit movement and rotation.                                     *
   1267  *                                                                                             *
   1268  *    This routine is used to process unit movement and rotation. It                           *
   1269  *    functions autonomously from the script system. Thus, once a unit                         *
   1270  *    is give rotation command or movement path, it will follow this                           *
   1271  *    until specifically instructed to stop. The advantage of this                             *
   1272  *    method is that it allows smooth movement of units, faster game                           *
   1273  *    execution, and reduced script complexity (since actual movement                          *
   1274  *    dynamics need not be controlled directly by the scripts).                                *
   1275  *                                                                                             *
   1276  * INPUT:   none                                                                               *
   1277  *                                                                                             *
   1278  * OUTPUT:  none                                                                               *
   1279  *                                                                                             *
   1280  * WARNINGS:   This routine relies on the process control bits for the                         *
   1281  *             specified unit (for speed reasons). Thus, only setting                          *
   1282  *             movement, rotation, or path list will the unit perform                          *
   1283  *             any physics.                                                                    *
   1284  *                                                                                             *
   1285  * HISTORY:                                                                                    *
   1286  *   09/26/1993 JLB : Created.                                                                 *
   1287  *   04/15/1994 JLB : Converted to member function.                                            *
   1288  *=============================================================================================*/
   1289 void DriveClass::AI(void)
   1290 {
   1291 	assert(IsActive);
   1292 
   1293 	FootClass::AI();
   1294 	if (!IsActive || Height > 0) return;
   1295 
   1296 	/*
   1297 	** Is this a unit that's been teleported using the chronosphere, and if so,
   1298 	** has his timer expired such that he needs to teleport back?
   1299 	*/
   1300 	if (IsMoebius) {
   1301 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   1302 	 if (What_Am_I() != RTTI_UNIT || ((UnitClass *)this)->Class->Type != UNIT_CHRONOTANK) {
   1303 #endif
   1304 		if (MoebiusCountDown == 0) {
   1305 			IsMoebius = false;
   1306 			Teleport_To(MoebiusCell);
   1307 			MoebiusCell = 0;
   1308 		}
   1309 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
   1310 	 }
   1311 #endif
   1312 	}
   1313 
   1314 	/*
   1315 	**	If the unit is following a track, then continue
   1316 	**	to do so -- mindlessly.
   1317 	*/
   1318 	if (TrackNumber != -1) {
   1319 
   1320 		/*
   1321 		**	Perform the movement accumulation.
   1322 		*/
   1323 		While_Moving();
   1324 		if (!IsActive) return;
   1325 		if (TrackNumber == -1 && (Target_Legal(NavCom) || Path[0] != FACING_NONE) && (What_Am_I() != RTTI_UNIT || !((UnitClass*)this)->IsDumping)) {
   1326 			Start_Of_Move();
   1327 			if (!IsActive) return;
   1328 			While_Moving();
   1329 			if (!IsActive) return;
   1330 		}
   1331 
   1332 	} else {
   1333 
   1334 		/*
   1335 		**	For tracked units that are rotating in place, perform the rotation now.
   1336 		*/
   1337 #ifdef TOFIX
   1338 		if ((Class->Speed == SPEED_FLOAT || Class->Speed == SPEED_HOVER || Class->Speed == SPEED_TRACK || (Class->Speed == SPEED_WHEEL && !Special.IsThreePoint)) && PrimaryFacing.Is_Rotating()) {
   1339 			if (PrimaryFacing.Rotation_Adjust(Class->ROT)) {
   1340 				Mark(MARK_CHANGE);
   1341 			}
   1342 #else
   1343 		if (PrimaryFacing.Is_Rotating()) {
   1344 			Mark(MARK_CHANGE_REDRAW);
   1345 			if (PrimaryFacing.Rotation_Adjust(Techno_Type_Class()->ROT * House->GroundspeedBias)) {
   1346 				Mark(MARK_CHANGE_REDRAW);
   1347 			}
   1348 #endif
   1349 			if (!IsRotating) {
   1350 				Per_Cell_Process(PCP_ROTATION);
   1351 				if (!IsActive) return;
   1352 			}
   1353 
   1354 		} else {
   1355 
   1356 			/*
   1357 			**	The unit has no track to follow, but if there
   1358 			**	is a navigation target or a remaining path,
   1359 			**	then start on a new track.
   1360 			*/
   1361 			if ((Mission != MISSION_GUARD || Target_Legal(NavCom)) && Mission != MISSION_UNLOAD) {
   1362 				if (Target_Legal(NavCom) || Path[0] != FACING_NONE) {
   1363 
   1364 					/*
   1365 					**	Double check to make sure that the movement destination is
   1366 					**	in a zone that this unit can travel to. If not, then abort
   1367 					**	the navigation target. Exception is to allow units to leave
   1368 					**	impassable cells regardless of zone checks.
   1369 					*/
   1370 					LandType land = LAND_NONE;
   1371 					if (What_Am_I() == RTTI_INFANTRY || What_Am_I() == RTTI_UNIT) {
   1372 						land = Map[Center_Coord()].Land_Type();
   1373 					}
   1374 					if (IsLocked && Mission != MISSION_ENTER && Target_Legal(NavCom) && !Is_In_Same_Zone(As_Cell(NavCom)) &&
   1375 						land != LAND_ROCK && land != LAND_WATER && land != LAND_RIVER && !Team) {
   1376 						Stop_Driver();
   1377 						Assign_Destination(TARGET_NONE);
   1378 					} else {
   1379 						Start_Of_Move();
   1380 						if (!IsActive) return;
   1381 						While_Moving();
   1382 						if (!IsActive) return;
   1383 					}
   1384 				} else {
   1385 					Stop_Driver();
   1386 				}
   1387 			}
   1388 		}
   1389 	}
   1390 }
   1391 
   1392 
   1393 /***********************************************************************************************
   1394  * DriveClass::Fixup_Path -- Adds smooth start path to normal movement path.                   *
   1395  *                                                                                             *
   1396  *    This routine modifies the path of the specified unit so that it                          *
   1397  *    will not start out with a rotation. This is necessary for those                          *
   1398  *    vehicles that have difficulty with rotating in place. Typically,                         *
   1399  *    this includes wheeled vehicles.                                                          *
   1400  *                                                                                             *
   1401  * INPUT:   unit  -- Pointer to the unit to adjust.                                            *
   1402  *                                                                                             *
   1403  *          path  -- Pointer to path structure.                                                *
   1404  *                                                                                             *
   1405  * OUTPUT:  none                                                                               *
   1406  *                                                                                             *
   1407  * WARNINGS:   Only units that require a fixup get modified. The                               *
   1408  *             modification only occurs, if there is a legal path to                           *
   1409  *             do so.                                                                          *
   1410  *                                                                                             *
   1411  * HISTORY:                                                                                    *
   1412  *   04/03/1994 JLB : Created.                                                                 *
   1413  *   04/06/1994 JLB : Uses path structure.                                                     *
   1414  *   04/10/1994 JLB : Diagonal smooth turn added.                                              *
   1415  *   04/15/1994 JLB : Converted to member function.                                            *
   1416  *=============================================================================================*/
   1417 void DriveClass::Fixup_Path(PathType * path)
   1418 {
   1419 	assert(IsActive);
   1420 
   1421 	FacingType stage[6]={FACING_N,FACING_N,FACING_N,FACING_N,FACING_N,FACING_N};		// Prefix path elements.
   1422 	int	facediff;		// The facing difference value (0..4 | 0..-4).
   1423 	static FacingType _path[4][6] = {
   1424 		{(FacingType)2,(FacingType)0,(FacingType)2,(FacingType)0,(FacingType)0,(FacingType)0},
   1425 		{(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},
   1426 		{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},
   1427 		{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}
   1428 	};
   1429 	static FacingType _dpath[4][6] = {
   1430 		{(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0,(FacingType)0},
   1431 		{(FacingType)3,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)0,(FacingType)0},
   1432 		{(FacingType)4,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0},
   1433 		{(FacingType)5,(FacingType)0,(FacingType)2,(FacingType)2,(FacingType)1,(FacingType)0}
   1434 	};
   1435 
   1436 	int			index;
   1437 	int			counter;			// Path addition
   1438 	FacingType	* ptr;				// Path list pointer.
   1439 	FacingType	* ptr2;			// Copy of new path list pointer.
   1440 	FacingType	nextpath;		// Next path value.
   1441 	CELL			cell;				// Working cell value.
   1442 	bool			ok;
   1443 
   1444 	/*
   1445 	**	Verify that the unit is valid and there is a path problem to resolve.
   1446 	*/
   1447 	if (!path || path->Command[0] == FACING_NONE) {
   1448 		return;
   1449 	}
   1450 
   1451 	/*
   1452 	**	Only wheeled vehicles need a path fixup -- to avoid 3 point turns.
   1453 	*/
   1454 #ifdef TOFIX
   1455 	if (!Special.IsThreePoint || Class->Speed != SPEED_WHEEL) {
   1456 #else
   1457 	if (What_Am_I() == RTTI_UNIT || What_Am_I() == RTTI_VESSEL) {
   1458 //	if (What_Am_I() == RTTI_UNIT) {
   1459 #endif
   1460 		return;
   1461 	}
   1462 
   1463 	/*
   1464 	**	If the original path starts in the same direction as the unit, then
   1465 	**	there is no problem to resolve -- abort.
   1466 	*/
   1467 	facediff = PrimaryFacing.Difference((DirType)(path->Command[0]<<5)) >> 5;
   1468 
   1469 	if (!facediff) return;
   1470 
   1471 	if (Dir_Facing(PrimaryFacing) & FACING_NE) {
   1472 		ptr = &_dpath[(FacingType)ABS((int)facediff)-FACING_NE][1];			// Pointer to path adjust list.
   1473  		counter = (int)_dpath[(FacingType)ABS((int)facediff)-FACING_NE][0];		// Number of path adjusts.
   1474 	} else {
   1475 		ptr = &_path[(FacingType)ABS((int)facediff)-FACING_NE][1];			// Pointer to path adjust list.
   1476  		counter = (int)_path[(FacingType)ABS((int)facediff)-FACING_NE][0];		// Number of path adjusts.
   1477 	}
   1478 	ptr2 = ptr;
   1479 
   1480 	ok = true;										// Presume adjustment is all ok.
   1481 	cell = Coord_Cell(Coord);	// Starting cell.
   1482 	nextpath = Dir_Facing(PrimaryFacing);	// Starting path.
   1483 	for (index = 0; index < counter; index++) {
   1484 
   1485 		/*
   1486 		**	Determine next path element and add it to the
   1487 		**	working path list.
   1488 		*/
   1489 		if (facediff > 0) {
   1490 			nextpath = nextpath + *ptr++;
   1491 		} else {
   1492 			nextpath = nextpath - *ptr++;
   1493 		}
   1494 		stage[index] = nextpath;
   1495 		cell = Adjacent_Cell(cell, nextpath);
   1496 		//cell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));
   1497 
   1498 		/*
   1499 		**	If it can't enter this cell, then abort the path
   1500 		**	building operation without adjusting the unit's
   1501 		**	path.
   1502 		*/
   1503 		if (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {
   1504 			ok = false;
   1505 			break;
   1506 		}
   1507 	}
   1508 
   1509 	/*
   1510 	**	If veering to the left was not successful, then try veering
   1511 	**	to the right. This only makes sense if the vehicle is trying
   1512 	**	to turn 180 degrees.
   1513 	*/
   1514 	if (!ok && ABS(facediff) == 4) {
   1515 		ptr = ptr2;											// Pointer to path adjust list.
   1516 		facediff = -facediff;
   1517 		ok = true;											// Presume adjustment is all ok.
   1518 		cell = Coord_Cell(Coord);						// Starting cell.
   1519 		nextpath = Dir_Facing(PrimaryFacing);		// Starting path.
   1520 		for (index = 0; index < counter; index++) {
   1521 
   1522 			/*
   1523 			**	Determine next path element and add it to the
   1524 			**	working path list.
   1525 			*/
   1526 			if (facediff > 0) {
   1527 				nextpath = nextpath + *ptr++;
   1528 			} else {
   1529 				nextpath = nextpath - *ptr++;
   1530 			}
   1531 			stage[index] = nextpath;
   1532 			cell = Coord_Cell(Adjacent_Cell(Cell_Coord(cell), nextpath));
   1533 
   1534 			/*
   1535 			**	If it can't enter this cell, then abort the path
   1536 			**	building operation without adjusting the unit's
   1537 			**	path.
   1538 			*/
   1539 			if (Can_Enter_Cell(cell, nextpath) != MOVE_OK) {
   1540 				ok = false;
   1541 				break;
   1542 			}
   1543 		}
   1544 	}
   1545 
   1546 	/*
   1547 	**	If a legal path addition was created, then install it in place
   1548 	**	of the first path value. The initial path entry is to be replaced
   1549 	**	with a sequence of path entries that create smooth turning.
   1550 	*/
   1551 	if (ok) {
   1552 		if (path->Length <= 1) {
   1553 			memmove((char *)&stage[0], (char*)path->Command, max(counter, 1));
   1554 			path->Length = counter;
   1555 		} else {
   1556 
   1557 			/*
   1558 			**	Optimize the transition path step from the smooth turn
   1559 			**	first part as it joins with the rest of the normal
   1560 			**	path. The normal prefix path steps are NOT to be optimized.
   1561 			*/
   1562 			if (counter) {
   1563 				counter--;
   1564 				path->Command[0] = stage[counter];
   1565 				Optimize_Moves(path, MOVE_OK);
   1566 			}
   1567 
   1568 			/*
   1569 			**	If there is more than one prefix path element, then
   1570 			**	insert the rest now.
   1571 			*/
   1572 			if (counter) {
   1573 				memmove((char*)&path->Command[0], (char*)&path->Command[counter], 40-counter);
   1574 				memmove((char*)&stage[0], (char*)&path->Command[0], counter);
   1575 				path->Length += counter;
   1576 			}
   1577 		}
   1578 		path->Command[path->Length] = FACING_NONE;
   1579 	}
   1580 }
   1581 
   1582 
   1583 /***********************************************************************************************
   1584  * DriveClass::Lay_Track -- Handles track laying logic for the unit.                           *
   1585  *                                                                                             *
   1586  *    This routine handles the track laying for the unit. This entails examining the unit's    *
   1587  *    current location as well as the direction and whether this unit is allowed to lay        *
   1588  *    tracks in the first place.                                                               *
   1589  *                                                                                             *
   1590  * INPUT:   none                                                                               *
   1591  *                                                                                             *
   1592  * OUTPUT:  none                                                                               *
   1593  *                                                                                             *
   1594  * WARNINGS:   none                                                                            *
   1595  *                                                                                             *
   1596  * HISTORY:                                                                                    *
   1597  *   05/28/1994 JLB : Created.                                                                 *
   1598  *=============================================================================================*/
   1599 void DriveClass::Lay_Track(void)
   1600 {
   1601 	assert(IsActive);
   1602 
   1603 #ifdef NEVER
   1604 	static IconCommandType * _trackdirs[8] = {
   1605 		TrackN_S,
   1606 		TrackNE_SW,
   1607 		TrackE_W,
   1608 		TrackNW_SE,
   1609 		TrackN_S,
   1610 		TrackNE_SW,
   1611 		TrackE_W,
   1612 		TrackNW_SE
   1613 	};
   1614 
   1615 	if (!(ClassF & CLASSF_TRACKS)) return;
   1616 
   1617 	Icon_Install(Coord_Cell(Coord), _trackdirs[Facing_To_8(BodyFacing)]);
   1618 #endif
   1619 }
   1620 
   1621 
   1622 /***********************************************************************************************
   1623  * DriveClass::Mark_Track -- Marks the midpoint of the track as occupied.                      *
   1624  *                                                                                             *
   1625  *    This routine will ensure that the midpoint (if any) of the track that the unit is        *
   1626  *    following, will be marked according to the mark type specified.                          *
   1627  *                                                                                             *
   1628  * INPUT:   headto   -- The head to coordinate.                                                *
   1629  *                                                                                             *
   1630  *          type     -- The type of marking to perform.                                        *
   1631  *                                                                                             *
   1632  * OUTPUT:  none                                                                               *
   1633  *                                                                                             *
   1634  * WARNINGS:   none                                                                            *
   1635  *                                                                                             *
   1636  * HISTORY:                                                                                    *
   1637  *   07/30/1995 JLB : Created.                                                                 *
   1638  *=============================================================================================*/
   1639 void DriveClass::Mark_Track(COORDINATE headto, MarkType type)
   1640 {
   1641 	assert(IsActive);
   1642 
   1643 	int value;
   1644 
   1645 	if (type == MARK_UP) {
   1646 		value = false;
   1647 	} else {
   1648 		value = true;
   1649 	}
   1650 
   1651 	if (headto) {
   1652 		if (!IsOnShortTrack && TrackNumber != -1) {
   1653 
   1654 			/*
   1655 			** If we have not passed the per cell process point we need
   1656 			** to deal with it.
   1657 			*/
   1658 			int tracknum = TrackControl[TrackNumber].Track;
   1659 			if (tracknum) {
   1660 				TrackType const * ptr = RawTracks[tracknum - 1].Track;
   1661 				int cellidx = RawTracks[tracknum - 1].Cell;
   1662 				if (cellidx > -1) {
   1663 					DirType dir = ptr[cellidx].Facing;
   1664 
   1665 					if (TrackIndex < cellidx && cellidx != -1) {
   1666 						COORDINATE offset = Smooth_Turn(ptr[cellidx].Offset, dir);
   1667 						Map[offset].Flag.Occupy.Vehicle = value;
   1668 					}
   1669 				}
   1670 			}
   1671 		}
   1672 		Map[headto].Flag.Occupy.Vehicle = value;
   1673 	}
   1674 }
   1675 
   1676 
   1677 /***********************************************************************************************
   1678  * DriveClass::Ok_To_Move -- Checks to see if this object can begin moving.                    *
   1679  *                                                                                             *
   1680  *    This routine is used to verify that this object is allowed to move. Some objects can     *
   1681  *    be temporarily occupied and thus cannot move until the situation permits.                *
   1682  *                                                                                             *
   1683  * INPUT:   direction   -- The direction that movement would be desired.                       *
   1684  *                                                                                             *
   1685  * OUTPUT:  Can the unit move in the direction specified?                                      *
   1686  *                                                                                             *
   1687  * WARNINGS:   none                                                                            *
   1688  *                                                                                             *
   1689  * HISTORY:                                                                                    *
   1690  *   07/29/1995 JLB : Created.                                                                 *
   1691  *=============================================================================================*/
   1692 bool DriveClass::Ok_To_Move(DirType ) const
   1693 {
   1694 	assert(IsActive);
   1695 
   1696 	return true;
   1697 }
   1698 
   1699 
   1700 /***************************************************************************
   1701 **	Smooth turn track tables. These are coordinate offsets from the center
   1702 **	of the destination cell. These are the raw tracks that are modified
   1703 **	by negating the X and Y portions as necessary. Also for reverse travelling
   1704 **	direction, the track list can be processed backward.
   1705 **
   1706 **	Track 1 = N
   1707 **	Track 2 = NE
   1708 **	Track 3 = N->NE 45 deg (double path consumption)
   1709 **	Track 4 = N->E 90 deg (double path consumption)
   1710 **	Track 5 = NE->SE 90 deg (double path consumption)
   1711 ** Track 6 = NE->N 45 deg (double path consumption)
   1712 **	Track 7 = N->NE (facing change only)
   1713 **	Track 8 = NE->E (facing change only)
   1714 **	Track 9 = N->E (facing change only)
   1715 **	Track 10= NE->SE (facing change only)
   1716 **	Track 11= back up into refinery
   1717 **	Track 12= drive out of refinery
   1718 */
   1719 //#pragma warn -ias
   1720 DriveClass::TrackType const DriveClass::Track1[24] = {
   1721 	{0x00F50000L,(DirType)0},
   1722 	{0x00EA0000L,(DirType)0},
   1723 	{0x00DF0000L,(DirType)0},
   1724 	{0x00D40000L,(DirType)0},
   1725 	{0x00C90000L,(DirType)0},
   1726 	{0x00BE0000L,(DirType)0},
   1727 	{0x00B30000L,(DirType)0},
   1728 	{0x00A80000L,(DirType)0},
   1729 	{0x009D0000L,(DirType)0},
   1730 	{0x00920000L,(DirType)0},
   1731 	{0x00870000L,(DirType)0},
   1732 	{0x007C0000L,(DirType)0},		// Track jump check here.
   1733 	{0x00710000L,(DirType)0},
   1734 	{0x00660000L,(DirType)0},
   1735 	{0x005B0000L,(DirType)0},
   1736 	{0x00500000L,(DirType)0},
   1737 	{0x00450000L,(DirType)0},
   1738 	{0x003A0000L,(DirType)0},
   1739 	{0x002F0000L,(DirType)0},
   1740 	{0x00240000L,(DirType)0},
   1741 	{0x00190000L,(DirType)0},
   1742 	{0x000E0000L,(DirType)0},
   1743 	{0x00030000L,(DirType)0},
   1744 	{0x00000000L,(DirType)0}
   1745 };
   1746 
   1747 DriveClass::TrackType const DriveClass::Track2[] = {
   1748 	{0x00F8FF08L,(DirType)32},
   1749 	{0x00F0FF10L,(DirType)32},
   1750 	{0x00E8FF18L,(DirType)32},
   1751 	{0x00E0FF20L,(DirType)32},
   1752 	{0x00D8FF28L,(DirType)32},
   1753 	{0x00D0FF30L,(DirType)32},
   1754 	{0x00C8FF38L,(DirType)32},
   1755 	{0x00C0FF40L,(DirType)32},
   1756 	{0x00B8FF48L,(DirType)32},
   1757 	{0x00B0FF50L,(DirType)32},
   1758 	{0x00A8FF58L,(DirType)32},
   1759 	{0x00A0FF60L,(DirType)32},
   1760 	{0x0098FF68L,(DirType)32},
   1761 	{0x0090FF70L,(DirType)32},
   1762 	{0x0088FF78L,(DirType)32},
   1763 	{0x0080FF80L,(DirType)32},		// Track jump check here.
   1764 	{0x0078FF88L,(DirType)32},
   1765 	{0x0070FF90L,(DirType)32},
   1766 	{0x0068FF98L,(DirType)32},
   1767 	{0x0060FFA0L,(DirType)32},
   1768 	{0x0058FFA8L,(DirType)32},
   1769 	{0x0050FFB0L,(DirType)32},
   1770 	{0x0048FFB8L,(DirType)32},
   1771 	{0x0040FFC0L,(DirType)32},
   1772 	{0x0038FFC8L,(DirType)32},
   1773 	{0x0030FFD0L,(DirType)32},
   1774 	{0x0028FFD8L,(DirType)32},
   1775 	{0x0020FFE0L,(DirType)32},
   1776 	{0x0018FFE8L,(DirType)32},
   1777 	{0x0010FFF0L,(DirType)32},
   1778 	{0x0008FFF8L,(DirType)32},
   1779 	{0x00000000L,(DirType)32}
   1780 };
   1781 
   1782 DriveClass::TrackType const DriveClass::Track3[] = {
   1783 	{0x01F5FF00L,(DirType)0},
   1784 	{0x01EAFF00L,(DirType)0},
   1785 	{0x01DFFF00L,(DirType)0},
   1786 	{0x01D4FF00L,(DirType)0},
   1787 	{0x01C9FF00L,(DirType)0},
   1788 	{0x01BEFF00L,(DirType)0},
   1789 	{0x01B3FF00L,(DirType)0},
   1790 	{0x01A8FF00L,(DirType)0},
   1791 	{0x019DFF00L,(DirType)0},
   1792 	{0x0192FF00L,(DirType)0},
   1793 	{0x0187FF00L,(DirType)0},
   1794 	{0x0180FF00L,(DirType)0},
   1795 	{0x0175FF00L,(DirType)0},		// Jump entry point here.
   1796 	{0x016BFF00L,(DirType)0},
   1797 	{0x0160FF02L,(DirType)1},
   1798 	{0x0155FF04L,(DirType)3},
   1799 	{0x014CFF06L,(DirType)4},
   1800 	{0x0141FF08L,(DirType)5},
   1801 	{0x0137FF0BL,(DirType)7},
   1802 	{0x012EFF0FL,(DirType)8},
   1803 	{0x0124FF13L,(DirType)9},
   1804 	{0x011AFF17L,(DirType)11},
   1805 	{0x0110FF1BL,(DirType)12},
   1806 	{0x0107FF1FL,(DirType)13},		// Center cell processing here.
   1807 	{0x00FCFF24L,(DirType)15},
   1808 	{0x00F3FF28L,(DirType)16},
   1809 	{0x00ECFF2CL,(DirType)17},
   1810 	{0x00E0FF32L,(DirType)19},
   1811 	{0x00D7FF36L,(DirType)20},
   1812 	{0x00CFFF3DL,(DirType)21},
   1813 	{0x00C6FF42L,(DirType)23},
   1814 	{0x00BAFF49L,(DirType)24},
   1815 	{0x00B0FF4DL,(DirType)25},
   1816 	{0x00A8FF58L,(DirType)27},
   1817 	{0x00A0FF60L,(DirType)28},
   1818 	{0x0098FF68L,(DirType)29},
   1819 	{0x0090FF70L,(DirType)31},
   1820 	{0x0088FF78L,(DirType)32},
   1821 	{0x0080FF80L,(DirType)32},		// Track jump check here.
   1822 	{0x0078FF88L,(DirType)32},
   1823 	{0x0070FF90L,(DirType)32},
   1824 	{0x0068FF98L,(DirType)32},
   1825 	{0x0060FFA0L,(DirType)32},
   1826 	{0x0058FFA8L,(DirType)32},
   1827 	{0x0050FFB0L,(DirType)32},
   1828 	{0x0048FFB8L,(DirType)32},
   1829 	{0x0040FFC0L,(DirType)32},
   1830 	{0x0038FFC8L,(DirType)32},
   1831 	{0x0030FFD0L,(DirType)32},
   1832 	{0x0028FFD8L,(DirType)32},
   1833 	{0x0020FFE0L,(DirType)32},
   1834 	{0x0018FFE8L,(DirType)32},
   1835 	{0x0010FFF0L,(DirType)32},
   1836 	{0x0008FFF8L,(DirType)32},
   1837 	{0x00000000L,(DirType)32}
   1838 };
   1839 
   1840 DriveClass::TrackType const DriveClass::Track4[] = {
   1841 	{0x00F5FF00L,(DirType)0},
   1842 	{0x00EBFF00L,(DirType)0},
   1843 	{0x00E0FF00L,(DirType)0},
   1844 	{0x00D5FF00L,(DirType)0},
   1845 	{0x00CBFF01L,(DirType)0},
   1846 	{0x00C0FF03L,(DirType)0},
   1847 	{0x00B5FF05L,(DirType)1},
   1848 	{0x00ABFF07L,(DirType)1},
   1849 	{0x00A0FF0AL,(DirType)2},
   1850 	{0x0095FF0DL,(DirType)3},
   1851 	{0x008BFF10L,(DirType)4},
   1852 	{0x0080FF14L,(DirType)5},		// Track entry here.
   1853 	{0x0075FF18L,(DirType)8},
   1854 	{0x006DFF1CL,(DirType)12},
   1855 	{0x0063FF22L,(DirType)16},
   1856 	{0x005AFF25L,(DirType)20},
   1857 	{0x0052FF2BL,(DirType)23},
   1858 	{0x0048FF32L,(DirType)27},
   1859 	{0x0040FF37L,(DirType)32},
   1860 	{0x0038FF3DL,(DirType)36},
   1861 	{0x0030FF46L,(DirType)39},
   1862 	{0x002BFF4FL,(DirType)43},
   1863 	{0x0024FF58L,(DirType)47},
   1864 	{0x0020FF60L,(DirType)51},
   1865 	{0x001BFF6DL,(DirType)54},
   1866 	{0x0017FF79L,(DirType)57},
   1867 	{0x0014FF82L,(DirType)60},		// Track jump here.
   1868 	{0x0011FF8FL,(DirType)62},
   1869 	{0x000DFF98L,(DirType)63},
   1870 	{0x0009FFA2L,(DirType)64},
   1871 	{0x0006FFACL,(DirType)64},
   1872 	{0x0004FFB5L,(DirType)66},
   1873 	{0x0003FFC0L,(DirType)64},
   1874 	{0x0002FFCBL,(DirType)64},
   1875 	{0x0001FFD5L,(DirType)64},
   1876 	{0x0000FFE0L,(DirType)64},
   1877 	{0x0000FFEBL,(DirType)64},
   1878 	{0x0000FFF5L,(DirType)64},
   1879 	{0x00000000L,(DirType)64}
   1880 };
   1881 
   1882 DriveClass::TrackType const DriveClass::Track5[] = {
   1883 	{0xFFF8FE08L,(DirType)32},
   1884 	{0xFFF0FE10L,(DirType)32},
   1885 	{0xFFE8FE18L,(DirType)32},
   1886 	{0xFFE0FE20L,(DirType)32},
   1887 	{0xFFD8FE28L,(DirType)32},
   1888 	{0xFFD0FE30L,(DirType)32},
   1889 	{0xFFC8FE38L,(DirType)32},
   1890 	{0xFFC0FE40L,(DirType)32},
   1891 	{0xFFB8FE48L,(DirType)32},
   1892 	{0xFFB0FE50L,(DirType)32},
   1893 	{0xFFA8FE58L,(DirType)32},
   1894 	{0xFFA0FE60L,(DirType)32},
   1895 	{0xFF98FE68L,(DirType)32},
   1896 	{0xFF90FE70L,(DirType)32},
   1897 	{0xFF88FE78L,(DirType)32},
   1898 	{0xFF80FE80L,(DirType)32},		// Track entry here.
   1899 	{0xFF78FE88L,(DirType)32},
   1900 	{0xFF71FE90L,(DirType)32},
   1901 	{0xFF6AFE97L,(DirType)32},
   1902 	{0xFF62FE9FL,(DirType)32},
   1903 	{0xFF5AFEA8L,(DirType)32},
   1904 	{0xFF53FEB0L,(DirType)35},
   1905 	{0xFF4BFEB7L,(DirType)38},
   1906 	{0xFF44FEBEL,(DirType)41},
   1907 	{0xFF3EFEC4L,(DirType)44},
   1908 	{0xFF39FECEL,(DirType)47},
   1909 	{0xFF34FED8L,(DirType)50},
   1910 	{0xFF30FEE0L,(DirType)53},
   1911 	{0xFF2DFEEBL,(DirType)56},
   1912 	{0xFF2CFEF5L,(DirType)59},
   1913 	{0xFF2BFF00L,(DirType)62},
   1914 	{0xFF2CFF0BL,(DirType)66},
   1915 	{0xFF2DFF15L,(DirType)69},
   1916 	{0xFF30FF1FL,(DirType)72},
   1917 	{0xFF34FF28L,(DirType)75},
   1918 	{0xFF39FF30L,(DirType)78},
   1919 	{0xFF3EFF3AL,(DirType)81},
   1920 	{0xFF44FF44L,(DirType)84},
   1921 	{0xFF4BFF4BL,(DirType)87},
   1922 	{0xFF53FF50L,(DirType)90},
   1923 	{0xFF5AFF58L,(DirType)93},
   1924 	{0xFF62FF60L,(DirType)96},
   1925 	{0xFF6AFF68L,(DirType)96},
   1926 	{0xFF71FF70L,(DirType)96},
   1927 	{0xFF78FF78L,(DirType)96},
   1928 	{0xFF80FF80L,(DirType)96},		// Track jump check here.
   1929 	{0xFF88FF88L,(DirType)96},
   1930 	{0xFF90FF90L,(DirType)96},
   1931 	{0xFF98FF98L,(DirType)96},
   1932 	{0xFFA0FFA0L,(DirType)96},
   1933 	{0xFFA8FFA8L,(DirType)96},
   1934 	{0xFFB0FFB0L,(DirType)96},
   1935 	{0xFFB8FFB8L,(DirType)96},
   1936 	{0xFFC0FFC0L,(DirType)96},
   1937 	{0xFFC8FFC8L,(DirType)96},
   1938 	{0xFFD0FFD0L,(DirType)96},
   1939 	{0xFFD8FFD8L,(DirType)96},
   1940 	{0xFFE0FFE0L,(DirType)96},
   1941 	{0xFFE8FFE8L,(DirType)96},
   1942 	{0xFFF0FFF0L,(DirType)96},
   1943 	{0xFFF8FFF8L,(DirType)96},
   1944 	{0x00000000L,(DirType)96}
   1945 };
   1946 
   1947 DriveClass::TrackType const DriveClass::Track6[] = {
   1948 	{0x0100FE00L,(DirType)32},
   1949 	{0x00F8FE08L,(DirType)32},
   1950 	{0x00F0FE10L,(DirType)32},
   1951 	{0x00E8FE18L,(DirType)32},
   1952 	{0x00E0FE20L,(DirType)32},
   1953 	{0x00D8FE28L,(DirType)32},
   1954 	{0x00D0FE30L,(DirType)32},
   1955 	{0x00C8FE38L,(DirType)32},
   1956 	{0x00C0FE40L,(DirType)32},
   1957 	{0x00B8FE48L,(DirType)32},
   1958 	{0x00B0FE50L,(DirType)32},
   1959 	{0x00A8FE58L,(DirType)32},
   1960 	{0x00A0FE60L,(DirType)32},
   1961 	{0x0098FE68L,(DirType)32},
   1962 	{0x0090FE70L,(DirType)32},
   1963 	{0x0088FE78L,(DirType)32},
   1964 	{0x0080FE80L,(DirType)32},		// Jump entry point here.
   1965 	{0x0078FE88L,(DirType)32},
   1966 	{0x0070FE90L,(DirType)32},
   1967 	{0x0068FE98L,(DirType)32},
   1968 	{0x0060FEA0L,(DirType)32},
   1969 	{0x0058FEA8L,(DirType)32},
   1970 	{0x0055FEAEL,(DirType)32},
   1971 	{0x004EFEB8L,(DirType)35},
   1972 	{0x0048FEC0L,(DirType)37},
   1973 	{0x0042FEC9L,(DirType)40},
   1974 	{0x003BFED2L,(DirType)43},
   1975 	{0x0037FEDAL,(DirType)45},
   1976 	{0x0032FEE3L,(DirType)48},
   1977 	{0x002BFEEBL,(DirType)51},
   1978 	{0x0026FEF5L,(DirType)53},
   1979 	{0x0022FEFEL,(DirType)56},
   1980 	{0x001CFF08L,(DirType)59},
   1981 	{0x0019FF12L,(DirType)61},
   1982 	{0x0015FF1BL,(DirType)64},
   1983 	{0x0011FF26L,(DirType)64},
   1984 	{0x000EFF30L,(DirType)64},
   1985 	{0x000BFF39L,(DirType)64},
   1986 	{0x0009FF43L,(DirType)64},
   1987 	{0x0007FF4EL,(DirType)64},
   1988 	{0x0005FF57L,(DirType)64},
   1989 	{0x0003FF62L,(DirType)64},
   1990 	{0x0001FF6DL,(DirType)64},
   1991 	{0x0000FF77L,(DirType)64},
   1992 	{0x0000FF80L,(DirType)64},		// Track jump check here.
   1993 	{0x0000FF8BL,(DirType)64},
   1994 	{0x0000FF95L,(DirType)64},
   1995 	{0x0000FFA0L,(DirType)64},
   1996 	{0x0000FFABL,(DirType)64},
   1997 	{0x0000FFB5L,(DirType)64},
   1998 	{0x0000FFC0L,(DirType)64},
   1999 	{0x0000FFCBL,(DirType)64},
   2000 	{0x0000FFD5L,(DirType)64},
   2001 	{0x0000FFE0L,(DirType)64},
   2002 	{0x0000FFEBL,(DirType)64},
   2003 	{0x0000FFF5L,(DirType)64},
   2004 	{0x00000000L,(DirType)64}
   2005 };
   2006 
   2007 DriveClass::TrackType const DriveClass::Track7[] = {
   2008 	{0x0006FFFFL,(DirType)0},
   2009 	{0x000CFFFEL,(DirType)4},
   2010 	{0x0011FFFCL,(DirType)8},
   2011 	{0x0018FFFAL,(DirType)12},
   2012 	{0x001FFFF6L,(DirType)16},
   2013 	{0x0024FFF3L,(DirType)19},
   2014 	{0x002BFFF0L,(DirType)22},
   2015 	{0x0030FFFDL,(DirType)23},
   2016 	{0x0035FFEBL,(DirType)24},
   2017 	{0x0038FFE8L,(DirType)25},
   2018 	{0x003CFFE6L,(DirType)26},
   2019 	{0x0040FFE3L,(DirType)27},
   2020 	{0x0043FFE0L,(DirType)28},
   2021 	{0x0046FFDDL,(DirType)29},
   2022 	{0x0043FFDFL,(DirType)30},
   2023 	{0x0040FFE1L,(DirType)30},
   2024 	{0x003CFFE3L,(DirType)30},
   2025 	{0x0038FFE5L,(DirType)30},
   2026 	{0x0035FFE7L,(DirType)31},
   2027 	{0x0030FFE9L,(DirType)31},
   2028 	{0x002BFFEBL,(DirType)31},
   2029 	{0x0024FFEDL,(DirType)31},
   2030 	{0x001FFFF1L,(DirType)31},
   2031 	{0x0018FFF4L,(DirType)32},
   2032 	{0x0011FFF7L,(DirType)32},
   2033 	{0x000CFFFAL,(DirType)32},
   2034 	{0x0006FFFDL,(DirType)32},
   2035 	{0x00000000L,(DirType)32}
   2036 };
   2037 
   2038 DriveClass::TrackType const DriveClass::Track8[] = {
   2039 	{0x0003FFFCL,(DirType)32},
   2040 	{0x0006FFF7L,(DirType)36},
   2041 	{0x000AFFF1L,(DirType)40},
   2042 	{0x000CFFEBL,(DirType)44},
   2043 	{0x000DFFE4L,(DirType)46},
   2044 	{0x000EFFDCL,(DirType)48},
   2045 	{0x000FFFD5L,(DirType)50},
   2046 	{0x0010FFD0L,(DirType)52},
   2047 	{0x0011FFC9L,(DirType)54},
   2048 	{0x0012FFC2L,(DirType)56},
   2049 	{0x0011FFC0L,(DirType)58},
   2050 	{0x0010FFC2L,(DirType)60},
   2051 	{0x000EFFC9L,(DirType)62},
   2052 	{0x000CFFCFL,(DirType)64},
   2053 	{0x000AFFD5L,(DirType)64},
   2054 	{0x0008FFDAL,(DirType)64},
   2055 	{0x0006FFE2L,(DirType)64},
   2056 	{0x0004FFE9L,(DirType)64},
   2057 	{0x0002FFEFL,(DirType)64},
   2058 	{0x0001FFF5L,(DirType)64},
   2059 	{0x0000FFF9L,(DirType)64},
   2060 	{0x00000000L,(DirType)64}
   2061 };
   2062 
   2063 DriveClass::TrackType const DriveClass::Track9[] = {
   2064 	{0xFFF50002L,(DirType)0},
   2065 	{0xFFEB0004L,(DirType)2},
   2066 	{0xFFE00006L,(DirType)4},
   2067 	{0xFFD50009L,(DirType)6},
   2068 	{0xFFCE000CL,(DirType)9},
   2069 	{0xFFC8000FL,(DirType)11},
   2070 	{0xFFC00012L,(DirType)13},
   2071 	{0xFFB80015L,(DirType)16},
   2072 	{0xFFC00012L,(DirType)18},
   2073 	{0xFFC8000EL,(DirType)20},
   2074 	{0xFFCE000AL,(DirType)22},
   2075 	{0xFFD50004L,(DirType)24},
   2076 	{0xFFDE0000L,(DirType)26},
   2077 	{0xFFE9FFF8L,(DirType)28},
   2078 	{0xFFEEFFF2L,(DirType)30},
   2079 	{0xFFF5FFEBL,(DirType)32},
   2080 	{0xFFFDFFE1L,(DirType)34},
   2081 	{0x0002FFD8L,(DirType)36},
   2082 	{0x0007FFD2L,(DirType)39},
   2083 	{0x000BFFCBL,(DirType)41},
   2084 	{0x0010FFC5L,(DirType)43},
   2085 	{0x0013FFBEL,(DirType)45},
   2086 	{0x0015FFB7L,(DirType)48},
   2087 	{0x0013FFBEL,(DirType)50},
   2088 	{0x0011FFC5L,(DirType)52},
   2089 	{0x000BFFCCL,(DirType)54},
   2090 	{0x0008FFD4L,(DirType)56},
   2091 	{0x0005FFDFL,(DirType)58},
   2092 	{0x0003FFEBL,(DirType)62},
   2093 	{0x0001FFF5L,(DirType)64},
   2094 	{0x00000000L,(DirType)64}
   2095 };
   2096 
   2097 DriveClass::TrackType const DriveClass::Track10[] = {
   2098 	{0xFFF6000BL,(DirType)32},
   2099 	{0xFFF00015L,(DirType)37},
   2100 	{0xFFEB0020L,(DirType)42},
   2101 	{0xFFE9002BL,(DirType)47},
   2102 	{0xFFE50032L,(DirType)52},
   2103 	{0xFFE30038L,(DirType)57},
   2104 	{0xFFE00040L,(DirType)60},
   2105 	{0xFFE20038L,(DirType)62},
   2106 	{0xFFE40032L,(DirType)64},
   2107 	{0xFFE5002AL,(DirType)68},
   2108 	{0xFFE6001EL,(DirType)70},
   2109 	{0xFFE70015L,(DirType)72},
   2110 	{0xFFE8000BL,(DirType)74},
   2111 	{0xFFE90000L,(DirType)76},
   2112 	{0xFFE8FFF5L,(DirType)78},
   2113 	{0xFFE7FFEBL,(DirType)80},
   2114 	{0xFFE6FFE0L,(DirType)82},
   2115 	{0xFFE5FFD5L,(DirType)84},
   2116 	{0xFFE4FFCEL,(DirType)86},
   2117 	{0xFFE2FFC5L,(DirType)88},
   2118 	{0xFFE0FFC0L,(DirType)90},
   2119 	{0xFFE3FFC5L,(DirType)92},
   2120 	{0xFFE5FFCEL,(DirType)94},
   2121 	{0xFFE9FFD5L,(DirType)95},
   2122 	{0xFFEBFFE0L,(DirType)96},
   2123 	{0xFFF0FFEBL,(DirType)96},
   2124 	{0xFFF6FFF5L,(DirType)96},
   2125 	{0x00000000L,(DirType)96}
   2126 };
   2127 
   2128 DriveClass::TrackType const DriveClass::Track11[] = {
   2129 	{0x01000000L,DIR_SW},
   2130 	{0x00F30008L,DIR_SW},
   2131 	{0x00E50010L,DIR_SW_X1},
   2132 	{0x00D60018L,DIR_SW_X1},
   2133 	{0x00C80020L,DIR_SW_X1},
   2134 	{0x00B90028L,DIR_SW_X1},
   2135 	{0x00AB0030L,DIR_SW_X2},
   2136 	{0x009C0038L,DIR_SW_X2},
   2137 	{0x008D0040L,DIR_SW_X2},
   2138 	{0x007F0048L,DIR_SW_X2},
   2139 	{0x00710050L,DIR_SW_X2},
   2140 	{0x00640058L,DIR_SW_X2},
   2141 	{0x00550060L,DIR_SW_X2},
   2142 
   2143 	{0x00000000L,DIR_SW_X2}
   2144 };
   2145 
   2146 DriveClass::TrackType const DriveClass::Track12[] = {
   2147 	{0xFF550060L,DIR_SW_X2},
   2148 	{0xFF640058L,DIR_SW_X2},
   2149 	{0xFF710050L,DIR_SW_X2},
   2150 	{0xFF7F0048L,DIR_SW_X2},
   2151 	{0xFF8D0040L,DIR_SW_X2},
   2152 	{0xFF9C0038L,DIR_SW_X2},
   2153 	{0xFFAB0030L,DIR_SW_X2},
   2154 	{0xFFB90028L,DIR_SW_X1},
   2155 	{0xFFC80020L,DIR_SW_X1},
   2156 	{0xFFD60018L,DIR_SW_X1},
   2157 	{0xFFE50010L,DIR_SW_X1},
   2158 	{0xFFF30008L,DIR_SW},
   2159 
   2160 	{0x00000000L,DIR_SW}
   2161 };
   2162 
   2163 #if(1)
   2164 /*
   2165 **	Drive out of weapon's factory.
   2166 */
   2167 DriveClass::TrackType const DriveClass::Track13[] = {
   2168 	{XYP_COORD(0,-35),DIR_S},
   2169 	{XYP_COORD(0,-34),DIR_S},
   2170 	{XYP_COORD(0,-33),DIR_S},
   2171 	{XYP_COORD(0,-32),DIR_S},
   2172 	{XYP_COORD(0,-31),DIR_S},
   2173 	{XYP_COORD(0,-30),DIR_S},
   2174 	{XYP_COORD(0,-29),DIR_S},
   2175 	{XYP_COORD(0,-28),DIR_S},
   2176 	{XYP_COORD(0,-27),DIR_S},
   2177 	{XYP_COORD(0,-26),DIR_S},
   2178 	{XYP_COORD(0,-25),DIR_S},
   2179 	{XYP_COORD(0,-24),DIR_S},
   2180 	{XYP_COORD(0,-23),DIR_S},
   2181 	{XYP_COORD(0,-22),DIR_S},
   2182 	{XYP_COORD(0,-21),DIR_S},
   2183 	{XYP_COORD(0,-20),DIR_S},
   2184 	{XYP_COORD(0,-19),DIR_S},
   2185 	{XYP_COORD(0,-18),DIR_S},
   2186 	{XYP_COORD(0,-17),DIR_S},
   2187 	{XYP_COORD(0,-16),DIR_S},
   2188 	{XYP_COORD(0,-15),DIR_S},
   2189 	{XYP_COORD(0,-14),DIR_S},
   2190 	{XYP_COORD(0,-13),DIR_S},
   2191 	{XYP_COORD(0,-12),DIR_S},
   2192 	{XYP_COORD(0,-11),DIR_S},
   2193 	{XYP_COORD(0,-10),DIR_S},
   2194 	{XYP_COORD(0,-9),DIR_S},
   2195 	{XYP_COORD(0,-8),DIR_S},
   2196 	{XYP_COORD(0,-7),DIR_S},
   2197 	{XYP_COORD(0,-6),DIR_S},
   2198 	{XYP_COORD(0,-5),DIR_S},
   2199 	{XYP_COORD(0,-4),DIR_S},
   2200 	{XYP_COORD(0,-3),DIR_S},
   2201 	{XYP_COORD(0,-2),DIR_S},
   2202 	{XYP_COORD(0,-1),DIR_S},
   2203 
   2204 	{0x00000000L,DIR_S}
   2205 };
   2206 #else
   2207 /*
   2208 **	Drive out of weapon's factory.
   2209 */
   2210 DriveClass::TrackType const DriveClass::Track13[] = {
   2211 	{XYP_COORD(10,-21),(DirType)(DIR_SW-10)},
   2212 	{XYP_COORD(10,-21),(DirType)(DIR_SW-10)},
   2213 	{XYP_COORD(10,-20),(DirType)(DIR_SW-10)},
   2214 	{XYP_COORD(10,-20),(DirType)(DIR_SW-10)},
   2215 	{XYP_COORD(9,-18),(DirType)(DIR_SW-10)},
   2216 	{XYP_COORD(9,-18),(DirType)(DIR_SW-10)},
   2217 	{XYP_COORD(9,-17),(DirType)(DIR_SW-10)},
   2218 	{XYP_COORD(8,-16),(DirType)(DIR_SW-10)},
   2219 	{XYP_COORD(8,-15),(DirType)(DIR_SW-10)},
   2220 	{XYP_COORD(7,-14),(DirType)(DIR_SW-10)},
   2221 	{XYP_COORD(7,-13),(DirType)(DIR_SW-10)},
   2222 	{XYP_COORD(6,-12),(DirType)(DIR_SW-10)},
   2223 	{XYP_COORD(6,-11),(DirType)(DIR_SW-10)},
   2224 	{XYP_COORD(5,-10),(DirType)(DIR_SW-10)},
   2225 	{XYP_COORD(5,-9),(DirType)(DIR_SW-10)},
   2226 	{XYP_COORD(4,-8),(DirType)(DIR_SW-10)},
   2227 	{XYP_COORD(4,-7),(DirType)(DIR_SW-10)},
   2228 	{XYP_COORD(3,-6),(DirType)(DIR_SW-10)},
   2229 	{XYP_COORD(3,-5),(DirType)(DIR_SW-9)},
   2230 	{XYP_COORD(2,-4),(DirType)(DIR_SW-7)},
   2231 	{XYP_COORD(2,-3),(DirType)(DIR_SW-5)},
   2232 	{XYP_COORD(1,-2),(DirType)(DIR_SW-3)},
   2233 	{XYP_COORD(1,-1),(DirType)(DIR_SW-1)},
   2234 
   2235 	{0x00000000L,DIR_SW}
   2236 };
   2237 #endif
   2238 
   2239 /*
   2240 **	There are a limited basic number of tracks that a vehicle can follow. These
   2241 **	are they. Each track can be interpreted differently but this is controlled
   2242 **	by the TrackControl structure elaborated elsewhere.
   2243 */
   2244 DriveClass::RawTrackType const DriveClass::RawTracks[13] = {
   2245 	{Track1, -1, 0, -1},
   2246 	{Track2, -1, 0, -1},
   2247 	{Track3, 37, 12, 22},
   2248 	{Track4, 26, 11, 19},
   2249 	{Track5, 45, 15, 31},
   2250 	{Track6, 44, 16, 27},
   2251 	{Track7, -1, 0, -1},
   2252 	{Track8, -1, 0, -1},
   2253 	{Track9, -1, 0, -1},
   2254 	{Track10, -1, 0, -1},
   2255 	{Track11, -1, 0, -1},
   2256 	{Track12, -1, 0, -1},
   2257 	{Track13, -1, 0, -1}
   2258 };
   2259 
   2260 
   2261 /***************************************************************************
   2262 **	Smooth turning control table. Given two directions in a path list, this
   2263 **	table determines which track to use and what modifying operations need
   2264 **	be performed on the track data.
   2265 */
   2266 DriveClass::TurnTrackType const DriveClass::TrackControl[67] = {
   2267 	{1,	0,		DIR_N,	F_},																//	0-0
   2268 	{3,	7,		DIR_NE,	F_D},																//	0-1 (raw chart)
   2269 	{4,	9,		DIR_E,	F_D},																//	0-2 (raw chart)
   2270 	{0,	0,		DIR_SE,	F_},																//	0-3 !
   2271 	{0,	0,		DIR_S,	F_},																//	0-4 !
   2272 	{0,	0,		DIR_SW,	F_},																//	0-5 !
   2273 	{4,	9,		DIR_W,	(DriveClass::TrackControlType)(F_X|F_D)},				//	0-6
   2274 	{3,	7,		DIR_NW,	(DriveClass::TrackControlType)(F_X|F_D)},				//	0-7
   2275 	{6,	8,		DIR_N,	(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},	//	1-0
   2276 	{2,	0,		DIR_NE,	F_},																//	1-1 (raw chart)
   2277 	{6,	8,		DIR_E,	F_D},																//	1-2 (raw chart)
   2278 	{5,	10,	DIR_SE,	F_D},																//	1-3 (raw chart)
   2279 	{0,	0,		DIR_S,	F_},																//	1-4 !
   2280 	{0,	0,		DIR_SW,	F_},																//	1-5 !
   2281 	{0,	0,		DIR_W,	F_},																//	1-6 !
   2282 	{5,	10,	DIR_NW,	(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},	//	1-7
   2283 	{4,	9,		DIR_N,	(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},	//	2-0
   2284 	{3,	7,		DIR_NE,	(DriveClass::TrackControlType)(F_T|F_X|F_Y|F_D)},	//	2-1
   2285 	{1,	0,		DIR_E,	(DriveClass::TrackControlType)(F_T|F_X)},				//	2-2
   2286 	{3,	7,		DIR_SE,	(DriveClass::TrackControlType)(F_T|F_X|F_D)},		//	2-3
   2287 	{4,	9,		DIR_S,	(DriveClass::TrackControlType)(F_T|F_X|F_D)},		//	2-4
   2288 	{0,	0,		DIR_SW,	F_},																//	2-5 !
   2289 	{0,	0,		DIR_W,	F_},																//	2-6 !
   2290 	{0,	0,		DIR_NW,	F_},																//	2-7 !
   2291 	{0,	0,		DIR_N,	F_},																//	3-0 !
   2292 	{5,	10,	DIR_NE,	(DriveClass::TrackControlType)(F_Y|F_D)},				//	3-1
   2293 	{6,	8,		DIR_E,	(DriveClass::TrackControlType)(F_Y|F_D)},				//	3-2
   2294 	{2,	0,		DIR_SE,	F_Y},																//	3-3
   2295 	{6,	8,		DIR_S,	(DriveClass::TrackControlType)(F_T|F_X|F_D)},		//	3-4
   2296 	{5,	10,	DIR_SW,	(DriveClass::TrackControlType)(F_T|F_X|F_D)},		//	3-5
   2297 	{0,	0,		DIR_W,	F_},																//	3-6 !
   2298 	{0,	0,		DIR_NW,	F_},																//	3-7 !
   2299 	{0,	0,		DIR_N,	F_},																//	4-0 !
   2300 	{0,	0,		DIR_NE,	F_},																//	4-1 !
   2301 	{4,	9,		DIR_E,	(DriveClass::TrackControlType)(F_Y|F_D)},				//	4-2
   2302 	{3,	7,		DIR_SE,	(DriveClass::TrackControlType)(F_Y|F_D)},				//	4-3
   2303 	{1,	0,		DIR_S,	F_Y},																//	4-4
   2304 	{3,	7,		DIR_SW,	(DriveClass::TrackControlType)(F_X|F_Y|F_D)},		//	4-5
   2305 	{4,	9,		DIR_W,	(DriveClass::TrackControlType)(F_X|F_Y|F_D)},		//	4-6
   2306 	{0,	0,		DIR_NW,	F_},																//	4-7 !
   2307 	{0,	0,		DIR_N,	F_},																//	5-0 !
   2308 	{0,	0,		DIR_NE,	F_},																//	5-1 !
   2309 	{0,	0,		DIR_E,	F_},																//	5-2 !
   2310 	{5,	10,	DIR_SE,	(DriveClass::TrackControlType)(F_T|F_D)},				//	5-3
   2311 	{6,	8,		DIR_S,	(DriveClass::TrackControlType)(F_T|F_D)},				//	5-4
   2312 	{2,	0,		DIR_SW,	F_T},																//	5-5
   2313 	{6,	8,		DIR_W,	(DriveClass::TrackControlType)(F_X|F_Y|F_D)},		//	5-6
   2314 	{5,	10,	DIR_NW,	(DriveClass::TrackControlType)(F_X|F_Y|F_D)},		//	5-7
   2315 	{4,	9,		DIR_N,	(DriveClass::TrackControlType)(F_T|F_Y|F_D)},		//	6-0
   2316 	{0,	0,		DIR_NE,	F_},																//	6-1 !
   2317 	{0,	0,		DIR_E,	F_},																//	6-2 !
   2318 	{0,	0,		DIR_SE,	F_},																//	6-3 !
   2319 	{4,	9,		DIR_S,	(DriveClass::TrackControlType)(F_T|F_D)},				//	6-4
   2320 	{3,	7,		DIR_SW,	(DriveClass::TrackControlType)(F_T|F_D)},				//	6-5
   2321 	{1,	0,		DIR_W,	F_T},																//	6-6
   2322 	{3,	7,		DIR_NW,	(DriveClass::TrackControlType)(F_T|F_Y|F_D)},		//	6-7
   2323 	{6,	8,		DIR_N,	(DriveClass::TrackControlType)(F_T|F_Y|F_D)},		//	7-0
   2324 	{5,	10,	DIR_NE,	(DriveClass::TrackControlType)(F_T|F_Y|F_D)},		//	7-1
   2325 	{0,	0,		DIR_E,	F_},																//	7-2 !
   2326 	{0,	0,		DIR_SE,	F_},																//	7-3 !
   2327 	{0,	0,		DIR_S,	F_},																//	7-4 !
   2328 	{5,	10,	DIR_SW,	(DriveClass::TrackControlType)(F_X|F_D)},				//	7-5
   2329 	{6,	8,		DIR_W,	(DriveClass::TrackControlType)(F_X|F_D)},				//	7-6
   2330 	{2,	0,		DIR_NW,	F_X},																//	7-7
   2331 
   2332 	{11,	11,	DIR_SW,	F_},																// Backup harvester into refinery.
   2333 	{12,	12,	DIR_SW_X2,	F_},															// Drive back into refinery.
   2334 	{13,	13,	DIR_SW,	F_}																// Drive out of weapons factory.
   2335 };
   2336 
   2337 
   2338