/*****************************************************************************
 * $Id: mod_base_pilot.hh,v 1.1 2006/11/24 21:56:57 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Auto-pilot class and AI logic.
 *//*
 * LEGAL:	COPYRIGHT (C) JIM E. BROOKS 2005
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#if COMPILING_MODULE
#ifndef MOD_BASE_PILOT_HH
#define MOD_BASE_PILOT_HH 1

#include "gfx_machine.hh"

class PilotModule;

////////////////////////////////////////////////////////////////////////////////
/// Class for PURSUE AI.
class PursueAI
{
				PREVENT_COPYING(PursueAI)
public:
				PursueAI( void );
				~PursueAI();
	void		Init( Craft* pursuer, Dyna* target );
	bool		IfActive( void ) { return mTarget != NULL; }
	void		SelectTarget( void );
	void		Tick( void ) { mMachine->Tick(); }	// drive state-machine

private:
	void		TransformTarget( void );
	void		TransformTargetOnce( void );
	fp			GetPursuerManeuverability( uint axis );
	void		DoManeuver( uint axis );
	void		DoManeuver( uint axis, Degree degManeuver, Degree degTarget );
	void		Rotate( uint axis, Degree deg );
	fp			CalcAngle( int ia, int ib );
	fp			CalcAngleRoll( void )	{ return CalcAngle( YY, XX ); }
	fp			CalcAnglePitch( void )	{ return CalcAngle( ZZ, YY ); }
	fp			CalcAngleYaw( void )	{ return CalcAngle( ZZ, XX ); }
	fp			ReCalcAngle( void );

public:
	// Methods invoked indirectly by state-machine:
	bool		IfRoll( void );
	bool		IfPitch( void );
	bool		IfYaw( void );
	bool		IfInlineWithTarget( void );
	bool		Roll( void );
	bool		Pitch( void );
	bool		Yaw( void );
	bool		RollWithTarget( void );
	bool		Step( void );
	bool		AdjustSpeed( void );
	bool		Fire( void );
	bool		CheckTarget( void );

private:
	Craft*			mPursuer;				// don't delete!
	Dyna*			mTarget;				// don't delete!
	Machine*		mMachine;
	int				mTickTransformTarget;	// (SM tick) to avoid calling TransformTarget() unnecessarily
	static const Degree mDegAligned[3];		// angle limit when pursuer is considered aligned with target
	static Vector3	mTargetPos;				// position of target in pursuer's local space
	/// For ReCalcAngle() and saving result.
	struct CalcAngleState
	{
		int16	mArgIa;
		int16	mArgIb;
		Degree	mResult;		// resulting angle in degrees
	};
	CalcAngleState	mCalcAngle;
};

////////////////////////////////////////////////////////////////////////////////
/// Pilot class.
/// The pilot class is a state machine that executes fractions of queued maneuvers
/// across multiple frames.
class PilotModule : public Pilot
{
private:
	PREVENT_COPYING(PilotModule)
	typedef Pilot Parent;

public:
	explicit	PilotModule( Craft& owner ) : Pilot(owner) { mProbing = false; }
				~PilotModule() { }
	int			Animate( void );
	bool		IfProbing( void ) { return mProbing; }
	void		SetTarget( Dyna* target ) { mPursueAI.Init( GetOwner(), target ); }
	void		SelectTarget( void ) { mPursueAI.Init( GetOwner(), NULL ); mPursueAI.SelectTarget(); }

	void		SetAnimation( const eAnimation animation );
	void		AddAnimation( const eAnimation animation );

private:
	// Pilot::mOwner is Dyna* but a Craft* was certainly stored in mOwner by constructor.
	Craft*		GetOwner( void ) { return static_cast<Craft*>(&mOwner); }
	void		CommonAnimation( const eAnimation animation );

	bool		mProbing;		///< true if pilot is probing (experimenting with) maneuvers
	PursueAI	mPursueAI;
};

// machine prototypes

bool
PursueIfRoll( Machine* machine );

bool
PursueIfPitch( Machine* machine );

bool
PursueIfYaw( Machine* machine );

bool
PursueIfInlineWithTarget( Machine* machine );

bool
PursueRoll( Machine* machine );

bool
PursuePitch( Machine* machine );

bool
PursueYaw( Machine* machine );

bool
PursueRollWithTarget( Machine* machine );

bool
PursueStep( Machine* machine );

bool
PursueAdjustSpeed( Machine* machine );

bool
PursueFire( Machine* machine );

bool
PursueCheckTarget( Machine* machine );

#endif // MOD_BASE_PILOT_HH
#endif // COMPILING_MODULE
