<pre>
/*
File: critter.h
Uploaded by richprillinger on Tue Nov 27 14:50:35 PST 2001
*/

// Critter.h: interface for the cCritter class.
//
//////////////////////////////////////////////////////////////////////

#ifndef CRITTER_H
#define CRITTER_H
#include "randomizer.h"
#include "realbox.h"
#include "realpixelconverter.h"
#include "vectortransformation.h"
class cGraphics;

#define USEBOUNCINESS //Compile switch used in critter.cpp, critterwall.cpp, realbox.cpp.

	/* We don't actually need to include the headers for the next four classes as
		we only mention them as pointers.  In general, we only include a header in a header if
		we absolutely have to.  Here we can get by with forward class declarations that simply
		say such and such a class exists.  Of course we will need to include the headers in the
		critter.cpp which is where we actually use the properties of these classes. Note, though,
that we could have included the headers for sprite, listener and force if we wanted to. */
class cBiota; //For the *_powner member.
class cSprite; //For the *_psprite member.
class cListener; //For *_plistener member.
class cForce; //For _forcearray member.
class cDistanceAndDirection; /* Return type of the distanceAndDirection function.  This
	class is defined in metric.h, but we definitely can't include metric.h because
	metric.h includes critter.h. */
class CPopView; //Used as an argument to sniff.
class cGame; //For the return type of the pgame() method.
class cGrahics; //For the draw method.

class cCritter : public CObject
{
DECLARE_SERIAL(cCritter);
public:
//constant statics
	//The MF_ statics are mutation flags used in the mutate methods.
	static const int MF_NUDGE;
	static const int MF_POSITION;
	static const int MF_VELOCITY;
	static const int MF_ALL; //MF_POSITION | MF_VELOCITY
	//Wrapflag values
	static const int BOUNCE;
	static const int WRAP;
	//special density used for player or other immovable critter.
	static const Real INFINITEDENSITY;
	//Attitudelock values say whether we should lock attitude to the _tangent argument
	static const int ATTITUDE_TO_DIRECTION_LOCK_OFF;
	static const int ATTITUDE_TO_DIRECTION_LOCK_ON;
//statics
	//Motion variable statics
	static Real MINSPEED;  //Used in randomizing critter speed.
	static Real MAXSPEED; /* Used in randomizing and in move(dt). Can be increased over 
		course of the program. */
	static Real MINTWITCHTHRESHOLDSPEED; //Default for _mintwitchthresholdspeed
	//Personal variable statics
	static Real DENSITY; //Default density.
	static Real MUTATIONSTRENGTH; //Default argument to mutate method.
	static Real MINRADIUS; //Used in randomizing
	static Real MAXRADIUS;
	static Real BULLETRADIUS; //Gets set to cGame::BULLETRADIUS in cGame constructor.
	static Real PLAYERRADIUS; 
	static Real LISTENERACCELERATION; //Default for _listeneracceleration

	static int STARTHEALTH; //Default is 1.
	static BOOL STARTWRAPFLAG;
	static Real SAFEWAIT; /* Time in seconds of invulnerability, use at start up and after
		damage, this gives critters a breathing room so they don't get damaged twice in a
		row by same bullet. */
	static Real FIXEDLIFETIME;
protected:
//Personal variables.
	Real _age;
	Real _lasthit_age; //Age at last hit (or age at birth), use to time invulnerability.
	BOOL _oldrecentlydamaged; /* update() sets to the prior value of recentlyDamaged() for use
		in knowing when you might need to update the dipslay list of a sprite. */ 
	int _health;
	BOOL _shieldflag;
	BOOL _usefixedlifetime;
	Real _fixedlifetime;
	int _score;
	UINT _personality; /* Use for making critters have different behaviors,
		cCritteArmedRobot uses it for whether to dodge left or right. */
	int _value; //Used as score value in games
	int _newlevelscorestep; //Step size between score levels that are rewarded.
	int _newlevelreward; //Health reward for new score level.
	/* The _density and _absorberflag are primarily used by the player.
		In standard critters they are by default 1.0 and FALSE.  The reason for them is that
		we want the cCritterPlayer not to be wildly buffeted about, so that you 
		can bull your way through a crowd.  One way is to assign the cCritterPlayer a
		very large mass so that it's hardly affected by collisions, this is done by
		default by setting the player's _density to INFINITEDENSITY.  An alternate
		way to make a cCritter able to bull through crowds is to set _absorberflag to TRUE.
		This has the effect in cCritter::collide to throw away whatever change in velocity
		the critter gets from the collision.  This steadily siphons velocity out of the
		system, so that eventually everthing comes to a halt, which is, in a way, kind of
		a nice effect. */
	Real _defaultprismdz; /* We copy this into the psprite's _prismdz field in setSprite.  
		If we are in 3D and if the sprite is, for instance, a polygon that makes use of 
		the _prismdz field, then _prismdz will determine the z-thickness of the sprite. */
	Real _density; //View your density as 1 normally, but INFINITEDENSITY for player.
	Real _mass; //Use fixMass() helper to maintain _mass = _density * radius()^3.
	Real _absorberflag; //Don't change your own velocity after a collision.
	Real _mutationstrength; /* Number between 0.0 and 1.0 controlling how different
		a spawned copy will be. */
//Motion variables.
	int _wrapflag;
	int _outcode;
	cRealBox _movebox;
	cRealBox _dragbox;
	BOOL _fixedflag; //Refuse to move.
	cVector _position;
	cVector _oldposition; //This is used by the cCritterWall::collide method.
	cVector _oldtangent; //This is used by the cCritter::fixNormalAndBinormal method.
	cVector _wrapposition1, _wrapposition2, _wrapposition3; //Use for showing wrap
	cVector _velocity;
	Real _speed;
	cVector _tangent; /* We always keep _velocity = _speed * _tangent.  It's
		useful to have _tangent around even when _speed goes to 0 and _velocity
		is zero, this way we know what direction to start back up in. */
	cVector _normal; /* We will also maintain a _normal and _binormal vector to fully express the
		motion of the critter through space. */
	cVector _binormal;
	cMatrix _attitude; /* The attitude expresses the way that the critter holds itself, 
		by default it will have the columns _tangent, _normal, _binormal, _position.
		But we can let it do be something different if _attitudelock is NOLOCK spin the critter. */
	cSpin _spin; /* A containter to hold the spinangle in radians per second, the spinaxis which is
		the axis to spin around (z by default), and a spinaxistype to speed up the computations by
		flagging when spinaxis is simply the x, y, or z axis.  This is only used
		if cCritter::_attitudelock is ATTITUDE_TO_DIRECTION_LOCK_OFF. */
	Real _maxspeed;
	Real _maxspeedstandard;/* In case  _maxspeed might be temporarily increased, for
		instance if the critter is allowed to move extra fast while fleeing or chasing another. */
	Real _mintwitchthresholdspeed; /* If we have ATTITUDE_TO_DIRECTION_LOCK_ON, and we have some
		critters barely bouncing on a "floor" it looks bad if they keep twitching their orientation up
		and down.  So in cCritter::updateAttitude, we don't actually change the _attitudeMatrix to
		match the motionMatrix() if the speed is less than _mintwitchtriggerspeed. Default
		value is cCritter::MINTWITCHTHRESHOLDSPEED */
	Real _bounciness; /* ranges from 0.0 to 1.0.  Determines how elastically you bounce off of walls
		or off of other critters.  1.0 is perfect bounce, 0.0 is don't bounce at all. */
	cVector _acceleration; /* _acceleration gets reset during every cycle, using the
		_forcearray and possibly the _plistener to change it. */
	Real _listeneracceleration; /* This is the acceleration used by listeners such as
		cListenerCar and cListenerSpaceship that "drive" the critter around. If you
		have a strong gravitational force, for instance, you may want to make sure
		_listeneracceleration is large enough to overcome the force. We keep 
		the _listeneracceleration field in cCritter instead of cListener so we can 
		change listeners and still have	the same _listeneracceleration.*/
	int _attitudelock; /* Shall I make the sprite always point in my _tangent? Or in the
		reverse direction?  Possible values are ATTITUDE_TO_DIRECTION_LOCK_OFF, 
		ATTITUDE_TO_DIRECTION_LOCK_ON,  ATTITUDE_TO_DIRECTION_LOCK_REVERSE */
//Dummyindex for nonserializable pointer reference.
	int _targetindex; //This is a dummy used only inside the Serialize methods.
//Class members that use Serialize calls.
	cSprite *_psprite;
	cListener *_plistener;
	CTypedPtrArray<CObArray, cForce*> _forcearray;
//Nonserialized helpers.
	int _metrickey; // Index in the _powner cBiota's _metric, can be used to lookup metric values.
	cBiota *_powner; /* Used in makeServiceRequest and in other places.  It allows the
		critter to be aware of all the other critters. */
//Nonserializable pointer.
	cCritter *_ptarget;/* In case you are following or dragging or watching or aimed at
		someone else, use this field to track them. */
//Nonpublic helper methods.
	void synchSpeedAndDirectionToVelocity(); /* Enforces _speed*_tangent = _velocity and avoids
		having _speed less than SMALL_REAL */
	void fixNormalAndBinormal(); /* This is easy in 2D, subtler in 3D.  In 3D, we compares _olddirection
		to _tangent and guess the direction of the normal as being this difference. We call this from
		inside ::move on every update.  It also orthonormolizes _tangent, _normal, and _binormal. */
	void initialize(); /* This factors out common constructor work that we want to call in both
		the cCritter() and the cCritter(cGame *powner) constructors. */
public:
//Constructor stuff
	cCritter();
	cCritter(cGame *powner); /* Does normal construction, randomizes position in powner->border(), and
		adds to powner. */
	cCritter(cCritter *pcritter); //copy constructor
	virtual ~cCritter(); /* deletes _psprite and calls cBiota::removeReferencesTo(this).  The
		destructor is virtual so that child critter destructors can do extra cleanup before this
		baseclass destructor gets automatically called. */
//Mutators
	virtual void copy(cCritter *pcritter);  /* Helper function for copy 
		constructor, also good for cloning. */
	void setOwner(cBiota* powner){_powner = powner;} //Used in Add and CBiota::Serialize
	void setValue(int value){_value = value;}
	//The velocity, direction, and speed mutators always keep _velocity = _speed * _tangent.
	void setVelocity(const cVector &velocity);
	void addVelocity(const cVector velocitychange){setVelocity(_velocity + velocitychange);}
	void setTangent(const cVector &direction);
	void rotate(const cSpin &spin); //cSpin is a way to express general 3D angles.
	void yaw(Real turnangle); //Rotate around _binormal. 
	void roll(Real turnangle); //Rotate around _tangent
	void pitch(Real turnangle); //Rotate around _normal
	void orthonormalize(); //Make sure _tangent, _normal, _binormal are orthogonal units.
	void setSpeed(Real speed);
	void setAcceleration(const cVector &acceleration){_acceleration = acceleration;}
	void addAcceleration(const cVector &acceleration){_acceleration += acceleration;}
	void setSpin(cVector3 spinvector){_spin = cSpin(spinvector);}
	void setSpin(Real spinangle, cVector3 spinaxis = cVector::ZAXIS){_spin = cSpin(spinangle, spinaxis);}
	void rotateAttitude(Real angle);//{_attitude *= cMatrix::rotation(angle);}
	void rotateAttitude(cSpin &spin);//{_attitude *= cMatrix::rotation(spin);}
	void setAttitude(const cMatrix &attitude); /* This changes the orientation aspect of _attitude,
		but NOT the _positoin aspect, that is, it leaves the last column alone. */
	void resetAttitude(); /* Assume the identity orientation. */
	void setAttitudeTangent(const cVector &tangent); /* points _attitude in tangent
		direction.  If _attitudelocked is set to ATTITUDE_TO_DIRECTION_LOCK_ON,
		we move _tangent to match. */
	void copyMotionMatrixToAttitudeMatrix(); 
	void copyAttitudeMatrixToMotionMatrix(); 
	BOOL lookAt(const cVector &targetpos); /* Aim attitudeTangent at targetpos, and try and preverse
		attitudeNormal while you're at it. Return FALSE if the targetpos is right on top of you,
		preventing you from looking at it, else return TRUE. */
	BOOL lookAtProportional(const cVector &targetpos, Real proportion); /* Proportion is between 0.0 and
		1.0 specifying how far towards targetpos you turn to look. */
	void setMaxspeed(Real maxspeed){_maxspeed = _maxspeedstandard = maxspeed;} // Initialization
	void setMinTwitchThresholdSpeed(Real twitchspeed){_mintwitchthresholdspeed = twitchspeed;}
	void setBounciness(Real bounciness){CLAMP(bounciness, 0.0, 1.0); _bounciness = bounciness;}
	void setTempMaxspeed(Real maxspeed){_maxspeed = maxspeed;} 
	void restoreMaxspeed(){_maxspeed = _maxspeedstandard;}
	int setRadius(Real radius);
	void setSprite(cSprite *psprite);
	int setMoveBox(const cRealBox &box);
	void setDragBox(const cRealBox &box){_dragbox = box;}
	virtual void setWrapflag(int wrapflag); //We have a kludge overload for cCritterWall
	void setDefaultPrismDz(Real prismdz); //Sets _defaultprismdz and the current _psprite->_prismdz.
	void setDensity(Real density){_density = density; fixMass();}
	void setAbsorberflag(BOOL flag){_absorberflag = flag; _absorberflag?_bounciness=0.0:_bounciness=1.0;}
		/* This method is only used in the Player menu, _absorberflag is becoming replaced by
		 _bounciness. */
	void setFixedflag(BOOL flag){_fixedflag = flag;}
	void setMutationStrength(Real mutationstrength){_mutationstrength = mutationstrength;}
	virtual void setTarget(cCritter *pcritter){_ptarget = pcritter;} /* Comes in handy
		sometimes, though more often I'll use a cForceObject. */
	void setMetricKey(int i){_metrickey = i;}
	void setShield(BOOL shield){_shieldflag = shield;}
	void setNewlevelreward(int healthgain){_newlevelreward = healthgain;}
	void setNewlevelscorestep(int pointspread){_newlevelscorestep = pointspread;}
	virtual void reset(); //can overload to do special things.
	virtual void setAge(Real age){_age = age; _lasthit_age = _age - cCritter::SAFEWAIT;}
		//overlaoded by cCritterArmedRobot.
	void setAttitudeLock(int lockmode){_attitudelock = lockmode;}
	virtual void addScore(int scorechange); 
	void setHealth(int health){_health = health; if(_health<0)_health=0;} /* We can add
		health points at certain score levels. */ 
	void setUseFixedLifetime(BOOL yesno){_usefixedlifetime = yesno;}
	void setFixedLifetime(Real lifetime){_fixedlifetime = lifetime;}
	void addForce(cForce *pforce);
	void clearForcearray();
	void copyForcearray(cCritter *pcritter); /* This helper method will empty the existing
		force array and copy all of the forces in the pcritter force array.  */
	virtual void copyPhysicsForces(cCritter *pcritter); /* A more modest kind of force copying.
		Here we don't wipeout the existing forces in the caller, and we only copy the "physics"
		forces like cForceGravity and cForceDrag from pcritter.  We don't copy "behavioral"
		forces like cForceAccelerateTowards or cForceEvadeClass forces.  We give our cForce an
		BOOL isGlobalPhysicsForce() to tell us which kind an instance is.  We need this
		method so that bullets can copy the physics of their shooters but not their
		behavioral forces.  */
	void fixMass();
//Randomizing mutators
	void randomizePosition( const cRealBox &startbox);
	void randomizePosition(){randomizePosition(_movebox);}
	void randomizeRadius(Real minradius, Real maxradius)
		{setRadius(cRandomizer::pinstance()->randomReal(minradius, maxradius));}
	void randomizeVelocity(Real speed, BOOL is3D=FALSE);
	void randomizeVelocity(Real minspeed, Real maxspeed, BOOL is3D=FALSE);
	void randomizeVelocity(BOOL is3D=FALSE){randomizeVelocity(MINSPEED, _maxspeed, is3D);}
	void randomizeSpin(Real minspeed, Real maxspeed);
	virtual void mutate(int mutationflags, Real mutationstrength); /* Mutate flagged position,
		velocity  and sprite properties by an amount specified in mutationstrength. */
	void mutate(int mutationflags) {mutate(mutationflags, _mutationstrength);}
		//Uses the member _mutationstrength, which defaults to 0.6.
	void randomize(int mutationflags){mutate(mutationflags, 1.0);} //1.0 is maximum.
//Accessors
	virtual BOOL isWall(){return FALSE;}
	int value()const{return _value;}
	cVector position() const {return _position;}
	cVector oldposition() const {return _oldposition;}
	cVector velocity() const {return _velocity;}
	cVector tangent() const {return _tangent;}
	cVector normal() const{return _normal;}
	cVector binormal() const{return _binormal;}
	cPlane plane()const{return cPlane(_position, _binormal);}
	cMatrix attitude(){return _attitude;} 
	cVector attitudeTangent()const {return _attitude.column(0);}
	cVector attitudeNormal()const {return _attitude.column(1);}
	cVector attitudeBinormal()const{return _attitude.column(2);}
	cVector acceleration() const {return _acceleration;}
	Real listeneracceleration()const{return _listeneracceleration;}
	void setListenerAcceleration(Real la){_listeneracceleration = la;}
	cSpin spin()const{return _spin;}
	Real speed()const {return _speed;}
	Real maxspeed()const {return _maxspeed;}
	Real maxspeedstandard()const {return _maxspeedstandard;}
	Real minTwitchThresholdSpeed(){return _mintwitchthresholdspeed;}
	Real bounciness(){return _bounciness;}
	cSprite* psprite() const{return _psprite;}
	int attitudelock() const{return _attitudelock;}
	int wrapflag()const {return _wrapflag;}
	Real defaultprismdz()const{return _defaultprismdz;}
	Real density()const{return _density;}
	BOOL absorberflag()const{return _absorberflag;}
	BOOL fixedflag()const{return _fixedflag;}
	Real radius() const;
	Real mass()const{return _mass;} //We use _fixMass to maintain as _density * radius()^3.
	cRealBox moveBox()const{return _movebox;}
	cRealBox dragBox()const{return _dragbox;}
	cRealBox realBox(); //Smallest box holding the sprite.
	Real mutationStrength()const{return _mutationstrength;}
	cCritter* clone(); /* Returns a pointer to a cCritter of the same child class
		type, with the same info in it. */
	cBiota* powner()const;
	virtual cGame* pgame()const; /*Normally this will just return _powner->pgame(), but in the
		case of a cCritterViewer associated with a CPopView we use a different path to the cGame.*/
	cCritter* ptarget()const{return _ptarget;}
	cCritter* pplayer(); /* return pgame()->pplayer(), in other words the player of 
		the game that this critter belongs to. */
	int metrickey()const{return _metrickey;}
	unsigned long personality()const{return _personality;}
	BOOL shield()const{return _shieldflag;}
	cListener* plistener()const{return _plistener;}
	CTypedPtrArray<CObArray, cForce*>* pforcearray(){return &_forcearray;}
	virtual cCritter* volunteer(){return this;} /* This  accessor is used to specify
		whether the critter is willing to be dragged in cGame::onLButtonDown. If you ever
		want a non-draggable critter child class, overload to volunteer(){return NULL;} */
	int score()const{return _score;}
	int health()const{return _health;}
	BOOL usefixedlifetime(){return _usefixedlifetime;}
	Real fixedlifetime(){return _fixedlifetime;}
	Real age()const{return _age;}
	BOOL recentlyDamaged(){return (_age - _lasthit_age) < SAFEWAIT;}
	BOOL in3DWorld(); //Tells you if the owner game has a z-Thickness.
// Serialize methods
	virtual void Serialize(CArchive &ar);
	virtual void fixPointerRefs(); /* This is for fixing things like 
		_ptarget after serialization */
// Service request methods 
	/* The point of these is that if a critter is do something that affects the set
		of critters as a whole, we want it to let the cBiota* _powner do it, so that
		all critter changes are coordinated.  So critter just passes this request to
		its _powner, and later _powner calls cBiota::processServiceRequests. */
	void makeServiceRequest(CString request);
	void add_me(cBiota *powner){setOwner(powner); makeServiceRequest("add_me");}
	void delete_me(){_health = 0; makeServiceRequest("delete_me");}
	void spawn(){makeServiceRequest("spawn");}
	void zap(){makeServiceRequest("zap");}
	void replicate(){makeServiceRequest("replicate");}
//Motion methods
	virtual int moveTo(const cVector &newposition, BOOL treatascontinuousmotion = FALSE);
		 /* Do the move, and then clamp against _movebox, return outcode of clamp. */
//	virtual int moveToX(Real x){return moveTo(cVector(x, _position.y(), _position.z()));}
//	virtual int moveToY(Real y){return moveTo(cVector(_position.x(), y, _position.z()));}
	virtual int moveToZ(Real z){return moveTo(cVector(_position.x(), _position.y(), z));}
		/* These could be useful  in setting critter positions.  The moveToZ does
			nothing in the two dimensional case where THREEDVECTORS isn't #defined in 
			vectortransformation.h. I use moveToZ in cGamePickNPop::seedCritters. */
	virtual int moveToProportional(const cVector &newposition, Real proportion,
		BOOL treatascontinuousmotion = FALSE); /* Proportion
		between 0.0 and 1.0 is how much of the way you want to move towards newposition. */
	virtual int dragTo(const cVector &newposition, Real dt); /* Move and clamp against _dragbox,
		return outcode. In addition, use dt to set critter velocity to match the drag velocity.
		I make it virtual so cCritterWall can overload to NOT change the velocity.  */
	virtual int clamp(); //Clamp against _movebox
	virtual int clamp(const cRealBox &border); //Clamp against border
	virtual void addvelocityandcheckedges(Real dt); /* do _position += dt*_velocity, and clamp,
		wrap, or bounce the  new position off the _movebox.  Set _outcode to tell
		which edges. Called by move(). Need the dt to figure out a velocity bounce. */
//Distance and touch methods. 
	//The first three methods implementation depends whether USEMETRIC is #defined in metric.h
	virtual cVector directionTo(cCritter *pcritter);//Use  cMetricCritter or compute directly
	Real distanceTo(cCritter *pcritter); //Uses cBiota's cMetricCritter or computes directly
	Real distanceTo(const cLine &testline){return testline.distanceTo(_position);} //Computes directly
	cDistanceAndDirection distanceAndDirectionTo(cCritter *pcritter); //ditto
	Real distanceTo(const cVector &vpoint); //Brute force.
	virtual BOOL touch(const cVector &vpoint);//Brute force.
	virtual BOOL touch(const cLine &sightline); /* In 3D, clicking the screen really picks a line
		of sight rather than a particualr point in space. */
	virtual BOOL touch(cCritter *pcritter); /* TRUE if pcritter is different from this and the 
		distance between the centers is less than the sum of the radii. Uses cBiota's
		cMetricCritter or just does the brute force distance checks. */
	virtual BOOL contains(cCritter *pcritter); /* TRUE if the disk of pcritter is inside
		the disk of the caller. */
	virtual COLORREF sniff(const cVector &snifflocation, CPopView *pview); /* Can be used in
		update to check the current screen's pixel color at locations you're interested in. */
	virtual BOOL collide(cCritter *pcritter); 
//Game methods
	virtual void die(){delete_me();} /* Can be overloaded to add dying behavior.  But should
		eventually produce a call to delete_me. */
	virtual void cCritter::dieOfOldAge(){delete_me();} 	/* dieOfOldAge is called in the update
		method if(_usefixedlifetime && _age > _fixedlifetime).  We distinguish between die()
		and dieOfOldAge(); we use die() because when a critter dies	of unnatural causes by having
		its _health go to 0 by maybe getting shot or eaten.  It's more likely that I overload die() to
		do something dramatic than that I overlaod dieOfOldAge(). */
	virtual int damage(int hitstrength); /* Deducts hitstrength from _health, calls die
		if this is below zero, returns _value as a reward to the damager. */
//Listen methods
	void setListener(cListener *plistener);
	virtual void feellistener(Real dt); /* Listen to the _powner->_pgame->_pcontroller if you have
		 a _plistener. Can overload to do special stuff. */ 
//Force methods
	virtual void feelforce(); /* Do _acceleration = (sum of _forcearray[i]->force(this))/mass().
		feelforce is virtual because you might possibly want to select which forces you feel,
		depending on the situation, like whether you're currently pursuing or fleeing. */
//Drawing methods.
	virtual	void updateAttitude(Real dt, BOOL forceattitudeupdate = FALSE); /* This keeps the
		graphical attitude matrix of the critter in synch with its motionmatrix.  To prevent
		a too-busy look, we normally don't do the update if the _speed is less than
		_mintwitchthresholdspeed. But if we are controlling the critter with arrow key calls to,
		e.g. the yaw, pitch and roll methods, we do want to force the update of the appearance,
		and then you set the forceattitudeupdate argument to TRUE. */
	virtual void draw(cGraphics *pgraphics, int drawflags=0);
		/* Calls _psprite->draw.  Has to be virtual because some child critters draw stuff
			 (like guns) on top	of sprite. */
	virtual void drawHighlight(cGraphics *pgraphics, Real highlightratio); /* Draw a highlighted XOR line
		, normally a circle around the sprite with a size = highlightratio * radius(). */
//Animation methods
	virtual void animate(Real dt); //Calls _psprite->animate(dt). Can overload to setAimVector.
	virtual void update(Real dt, CPopView *pview); /* Call force to set the _acceleration to zero or
		to the quantity determined by _pforce. hild classes may add extra
		things to _acceleration and do other things as well. */ 
	int move(Real dt); /* You really should NOT change the delicately constructed move method,
		which is why its not virtual. Instead change the update(dt, CPopView *pview) method to
		alter motions if you need to, though presently none of our update overloads uses dt. */
};
#endif //CRITTER_H

</pre>

