/*
File: gameworms.cpp
Uploaded by leegong on Tue Nov 13 14:43:36 PST 2001
*/

// gameworms.cpp: implementation of the generic cGameWorms class.
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "gameworms.h"
//#include "critterarmed.h" /* Lee added 11-11-01 */
#include "critterwall.h" /* Lee added 11-04-01 */
#include "listener.h"
#include "spriteicon.h"
#include "spritemultiicon.h"
#include "pop.h" //for playSound
#include "popview.h"
#include "force.h"
#include "spritebubble.h"

IMPLEMENT_SERIAL(cGameWorms, cGame, 0);
IMPLEMENT_SERIAL(cCritterMazeWall, cCritterWall, 0); /* Lee added 11-04-01 */
IMPLEMENT_SERIAL(cCritterWormsPlayer, cCritter, 0); //ArmedPlayer, 0); /* Lee added 11-11-01 */
IMPLEMENT_SERIAL(cCritterPlayerWormsSeg, cCritter, 0); /* Lee added 11-11-01 */
IMPLEMENT_SERIAL(cCritterWormsSeg, cCritter, 0); /* Lee added 11-11-01 */
IMPLEMENT_SERIAL(cCritterWormsEnemyHead, cCritter, 0); /* Lee added 11-11-01 */
//IMPLEMENT_SERIAL(cCritterWormsRival, cCritterArmedRobot, 0); /* 11-6 Joe */
//IMPLEMENT_SERIAL(cCritterWormsPlayerBullet, cCritterBullet, 0);  /* 11-6 Joe */
//IMPLEMENT_SERIAL(cCritterWormsRivalBullet, cCritterBullet, 0);  /* 11-6 Joe */

//Defines
#define PLAYERSPRITELOOP
//#define NOWALLS
	/* We have the option of havin the cCritterWormsPlayer either use
	an "animated" cSpriteLoop or use a directionally-sensitive cSpriteDirectional.
	Comment the #define PLAYERSPRITELOOP in for the cSpriteLoop,
	comment it out for the	cSpriteDirectional. */

//==============================cGameWorms
int cGameWorms::PLAYERHEALTH = 5; 
int cGameWorms::WORMCOUNT = 3; //1; /* Lee added 11-04-01 */
static int randomLow = -4;          /* 11-12 Joe */
static int randomHigh = 4;          /* 11-12 Joe */

cGameWorms::cGameWorms(): //The constructor gets called only once, at first start.
	_rivalcount(3)
{	
	_menuflags &= ~cGame::MENU_SHIELD; //We don't use the shield control in this game.
//Usually we set _seedcount.
	_playerseedcount = 6; //The number of cCritterPlayerWormsSeg that I plan to add. /* Lee added 11-11-01 */
	_seedcount = 6; //The number of cCritterWormsSeg that I plan to add.
//	_seedcount2 = 6; //The number of cCritterWormsSeg that I plan to add.
//	_seedcount3 = 6; //The number of cCritterWormsSeg that I plan to add.
// Add more _seedcount variables, one for each enemy..? probably not /* Lee added 11-11-01 */
//Fix your statics
	cCritter::MAXSPEED = 10.0; //5.0; //4.0; /* Customary to set critter speed, usually the   /* 11-5 Joe */
		/*bigger the world the higher the speed you want. */
//Set the cursor tools.
	/*_arrayHCURSOR has only the _hCursorArrow inherited from cGame. 
		 Add a Shooting cursor and a Dragging cursor for fun. */
	/* Can Probably remove all of these */ /* Lee added 11-11-01 */
	_arrayHCURSOR.Add(((CPopApp*)::AfxGetApp())->_hCursorPlay); 
//	_arrayHCURSOR.Add(((CPopApp*)::AfxGetApp())->_hCursorDragger); 
	_arrayHCURSOR.Add(((CPopApp*)::AfxGetApp())->_hCursorPin);
//	_arrayHCURSOR.Add(((CPopApp*)::AfxGetApp())->_hCursorReplicate); 
//	_arrayHCURSOR.Add(((CPopApp*)::AfxGetApp())->_hCursorZap); 
//Set your world shape _border.set(width, height) /* Lee added 11-04-01 */
	_border.set(38.0, 29.0), //Standard is (14.4, 9.6), can override here..
//Set the backgroudn bitmap
	setBackgroundBitmap(IDB_BACKGROUND); /*  Sets the cSpriteBackground for the background bitmap.
		Note that you must call this after the _border has its size fully initialized. So each
		cGame child with a different border should call this again in its constructor. */
//Set wrap with setWrapflag(cCritter::WRAP) or cCritter::BOUNCE.
	cCritterWall::THICKNESS = 0.4; /* Lee added 11-04-01 */
	setWrapflag(cCritter::BOUNCE); /* Lee added 11-04-01 */
//Make a player   
   initiatePlayer();                                                       /* 11-5 Joe */
	// setPlayer(new cCritterWormsPlayer);                                  /* 11-5 joe */
//Possibly make and add any permanent critters here.
//#define DEBUGWALL /* Lee added 11-04-01 */
#ifndef NOWALLS
   initiateMap1();
#endif
}

void cGameWorms::initiateMap1()
{
#ifndef DEBUGWALL /* Lee added 11-04-01 */
	add(new cCritterMazeWall( cVector(-16.5, 12),	cVector(-13.5, 12))); // 1 
	add(new cCritterMazeWall( cVector(-16.5, 12),	cVector(-16.5, 6))); // 2
	add(new cCritterMazeWall( cVector(-16.5, 3),	cVector(-13.5, 3))); // 3
	add(new cCritterMazeWall( cVector(-13.5, 3),	cVector(-13.5, 6))); // 4
	add(new cCritterMazeWall( cVector(-13.5, 6),	cVector(-10.5, 6))); // 5
	add(new cCritterMazeWall( cVector(-13.5, 9),	cVector(-10.5, 9))); // 6 
	add(new cCritterMazeWall( cVector(-10.5, 9),	cVector(-10.5, 12))); // 7
	add(new cCritterMazeWall( cVector(-10.5, 12),	cVector(-7.5, 12))); // 8
	add(new cCritterMazeWall( cVector(-7.5, 9),	cVector(-7.5, 3))); // 9
	add(new cCritterMazeWall( cVector(-7.5, 6),	cVector(-1.5, 6))); // 10
	add(new cCritterMazeWall( cVector(-4.5, 12),	cVector(-4.5, 9))); // 11 
	add(new cCritterMazeWall( cVector(-4.5, 9),	cVector(1.5, 9))); // 12
	add(new cCritterMazeWall( cVector(-1.5, 12),	cVector(4.5, 12))); // 13
	add(new cCritterMazeWall( cVector(-4.5, 3),	cVector(1.5, 3))); // 14
	add(new cCritterMazeWall( cVector(1.5, 3),	cVector(1.5, 0))); // 15
	add(new cCritterMazeWall( cVector(-1.5, 0),	cVector(-1.5, .4))); // 16 
	add(new cCritterMazeWall( cVector(-4.5, 0),	cVector(-4.5, -3))); // 17
	add(new cCritterMazeWall( cVector(-4.5, -3),	cVector(1.5, -3))); // 18
	add(new cCritterMazeWall( cVector(-7.5, 0),	cVector(-13.5, 0))); // 19
	add(new cCritterMazeWall( cVector(-10.5, 3),	cVector(-10.5, -3))); // 20
	add(new cCritterMazeWall( cVector(-16.5, 0),	cVector(-16.5, -6))); // 21 
	add(new cCritterMazeWall( cVector(-16.5, -3),	cVector(-13.5, -3))); // 22
	add(new cCritterMazeWall( cVector(-16.5, -9),	cVector(-10.5, -9))); // 23
	add(new cCritterMazeWall( cVector(-13.5, -9),	cVector(-13.5, -6))); // 24
	add(new cCritterMazeWall( cVector(-16.5, -12),	cVector(-13.5, -12))); // 25
	add(new cCritterMazeWall( cVector(-10.5, -12),	cVector(-7.5, -12))); // 26 
	add(new cCritterMazeWall( cVector(-7.5, -12),	cVector(-7.5, -9))); // 27
	add(new cCritterMazeWall( cVector(-10.5, -6),	cVector(-4.5, -6))); // 28
	add(new cCritterMazeWall( cVector(-7.5, -6),	cVector(-7.5, -3))); // 29
	add(new cCritterMazeWall( cVector(-1.5, -6),	cVector(-1.5, -9))); // 30
	add(new cCritterMazeWall( cVector(-1.5, -9),	cVector(-4.5, -9))); // 31 
	add(new cCritterMazeWall( cVector(-4.5, -9),	cVector(-4.5, -12))); // 32
	add(new cCritterMazeWall( cVector(-1.5, -12),	cVector(4.5, -12))); // 33
	add(new cCritterMazeWall( cVector(1.5, -12),	cVector(1.5, -6))); // 34
	add(new cCritterMazeWall( cVector(4.5, -9),	cVector(4.5, -8.6))); // 35
	add(new cCritterMazeWall( cVector(7.5, -12),	cVector(16.5, -12))); // 36 
	add(new cCritterMazeWall( cVector(10.5, -12),	cVector(10.5, -9))); // 37
	add(new cCritterMazeWall( cVector(7.5, -9),	cVector(7.5, -3))); // 38
	add(new cCritterMazeWall( cVector(13.5, -9),	cVector(16.5, -9))); // 39
	add(new cCritterMazeWall( cVector(13.5, -6),	cVector(16.5, -6))); // 40
	add(new cCritterMazeWall( cVector(16.5, -6),	cVector(16.5, -3))); // 41 
	add(new cCritterMazeWall( cVector(10.5, -3),	cVector(13.5, -3))); // 42
	add(new cCritterMazeWall( cVector(13.5, -3),	cVector(13.5, 0))); // 43
	add(new cCritterMazeWall( cVector(13.5, 0),	cVector(16.5, 0))); // 44
	add(new cCritterMazeWall( cVector(4.5, -3),	cVector(4.5, 0))); // 45
	add(new cCritterMazeWall( cVector(4.5, 0),	cVector(7.5, 0))); // 46 
	add(new cCritterMazeWall( cVector(7.5, 0),	cVector(7.5, 3))); // 47
	add(new cCritterMazeWall( cVector(10.5, 0),	cVector(10.5, 3))); // 48
	add(new cCritterMazeWall( cVector(10.5, 3),	cVector(16.5, 3))); // 49
	add(new cCritterMazeWall( cVector(10.5, 6),	cVector(16.5, 6))); // 50
	add(new cCritterMazeWall( cVector(13.5, 6),	cVector(13.5, 9))); // 51 
	add(new cCritterMazeWall( cVector(16.5, 9),	cVector(16.5, 12))); // 52
	add(new cCritterMazeWall( cVector(16.5, 12),	cVector(10.5, 12))); // 53
	add(new cCritterMazeWall( cVector(10.5, 9),	cVector(7.5, 9))); // 54
	add(new cCritterMazeWall( cVector(7.5, 9),	cVector(7.5, 12))); // 55
	add(new cCritterMazeWall( cVector(7.5, 6),	cVector(1.5, 6))); // 56 
	add(new cCritterMazeWall( cVector(4.5, 9),	cVector(4.5, 3))); // 57
	add(new cCritterMazeWall( cVector(4.5, -6),	cVector(10.5, -6))); // 58
#else /* Lee added 11-04-01 */
//	_seedcount = 0; /* Lee added 11-04-01 */
#endif //DEBUGWALL /* Lee added 11-04-01 */
}

void cGameWorms::seedCritters()
{
	pbiota()->purgeNonPlayerNonWallCritters(); 
		/* Clean out any old non-player non-wall critters. Although we don't have 
			walls yet, you might want to put some in. */
  
   //cCritter * pprop_prior; /* This is a special trick for the   
	cCritterWormsBase * pprop_prior; /* This is a special trick for the                 /* 11-12 Joe SnakeClass 
		follow-the-leader thing we'll set up in the next loop.  Not standard. */   
   Real randomX;        /* 11-12 Joe */
   Real randomY;        /* 11-12 Joe */
	for (int k=0; k < cGameWorms::WORMCOUNT; k++)
   {
      cCritterWormsSnake * snake = new cCritterWormsSnake( this );            /* 11-12 Joe  SnakeClass*/

      randomX = cRandomizer::pinstance()->randomReal( randomLow, randomHigh );        /* 11-12 Joe */
      randomY = cRandomizer::pinstance()->randomReal( randomLow, randomHigh );        /* 11-12 Joe */

		for (int i = 0; i < _seedcount - 1; i++)           /* 11-5 Joe */
		// To keep the number of segments <= _seedcount, adding a segment w/o incrementing i
		// during the first loop of the iteration.
		{
			if (i==0)
			{                                               /* 11-5 Joe */
				// pprop_prior = new cCritterWormsEnemyHead();    /* 11-5 Joe */           /* 11-12 Joe */
				pprop_prior = new cCritterWormsEnemyHead( pplayer() );    /* 11-5 Joe */
				add( pprop_prior );                          /* 11-5 Joe */
            pprop_prior->setMoveBox( cRealBox2( cVector( -19, -14.5 ), cVector( 19, 14.5 ) ) );      /* 11-12 Joe */
            pprop_prior->moveTo( cVector( (k+1)*randomX, (k+1)*randomY ) );                                             /* 11-12 Joe */
            pprop_prior->setSnake( snake );              /* 11-12 Joe SnakeClass*/
            snake ->setHead( pprop_prior );              /* 11-12 Joe SnakeClass*/
			}                                               /* 11-5 Joe */
			cCritterWormsSeg *pprop = new cCritterWormsSeg(pprop_prior); /* Lee added 11-11-01 */
			add(pprop);
         pprop->setMoveBox( cRealBox2( cVector( -19, -14.5 ), cVector( 19, 14.5 ) ) );      /* 11-12 Joe */
         pprop->moveTo( cVector( (k+1)*randomX, (k+1)*randomY ) );                            /* 11-12 Joe */
         pprop->setSnake( snake );                       /* 11-12 Joe SnakeClass*/
			//pprop->randomize(cCritter::MF_POSITION);
			pprop_prior = pprop;
		}
      snake->setTail( pprop_prior );                     /* 11-12 Joe SnakeClass*/
   }
}

/*                                        11-5 Joe                      */
/* It is used to setup a player and its tail, or body segments */
void cGameWorms::initiatePlayer()
{
   cCritterWormsPlayer * newPlayer = new cCritterWormsPlayer;
   //cCritter * pprop_prior
   cCritterWormsBase *pprop_prior;                             /* 11-12 Joe SnakeClass*/
   cCritterWormsSnake * snake = new cCritterWormsSnake( this );      /* 11-12 Joe SnakeClass*/

   newPlayer->setSnake( snake );                /* 11-12 Joe SnakeClass*/
   snake->setHead( newPlayer );                 /* 11-12 Joe SnakeClass*/
   newPlayer->setMoveBox( cRealBox2( cVector( -100, -100 ), cVector( 100, 100 ) ) );      /* 11-12 Joe */
   newPlayer->moveTo( cVector( -17, 14 ) );                                             /* 11-12 Joe */

   for (int i = 0; i < _playerseedcount - 1; i++) /* Lee added 11-11-01 */
      // To keep the number of segments <= _seedcount, adding a segment w/o incrementing i
      // during the first loop of the iteration.
	{
		if (i==0)
			pprop_prior = newPlayer;
		cCritterPlayerWormsSeg *pprop = new cCritterPlayerWormsSeg(pprop_prior); /* Lee added 11-11-01 */
		add(pprop);
      pprop->setMoveBox( cRealBox2( cVector( -100, -100 ), cVector( 100, 100 ) ) );      /* 11-12 Joe */
      pprop->moveTo( cVector( -17, 14 ) );                                             /* 11-12 Joe */
      pprop ->setSnake( snake );             /* 11-12 Joe SnakeClass*/
		//pprop->randomize(cCritter::MF_POSITION);
		pprop_prior = pprop;
	}

	setPlayer(newPlayer);
   snake->setTail( pprop_prior );            /* 11-12 Joe SnakeClass*/
}


/* cGameWorms::reset does not get called at first startup, is called only when you start a
	 new round or 	level of the game.*/
void cGameWorms::reset() 
{
   initiatePlayer();                                              /* 11-5 Joe */
	cGame::reset(); //Calls pplayer()->reset() and seedCritters().
	//Soemtimes reset other parameters here.
}

/* This gets called at startup and when you begin a new game.  This is the
place to set the background or the kind of cursor you want to use. */
void cGameWorms::initializeView(CPopView *pview)
{
	cGame::initializeView(pview); //Always call baseclass
	pview->setCursor(((CPopApp*)::AfxGetApp())->_hCursorPlay);
			 //Use the shoot cursor
	pview->setUseBackgroundBitmap(TRUE);
			//TRUE if you want the background, FALSE if not.
}

CString cGameWorms::statusMessage()
{
	CString cStrStatusBar = cGame::statusMessage(); //Get the standard message
		//Add to it or change it.
	return cStrStatusBar;
}

BOOL cGameWorms::collide(cCritter *pcriti, cCritter *pcritj)
{
	/* For now we just copy cGame.  But we may sometimes want to take that
	code and edit it so as to make sure that certain kinds of pcritj get
	to call pcritj->collide(pcriti) instead of the (normal) other way
	around.*/
		//*
   BOOL collide = cGame::collide(pcriti, pcritj);              //* 11-12 Joe */
   if( collide )                                               //* 11-12 Joe */
   {
      	if (pcriti->IsKindOf(RUNTIME_CLASS(cCritterWormsEnemyHead))) /* Lee added 11-11-01 */
      	{	// Stops worm heads from being pushed around by other segments
      			return FALSE;
      	}
      if (pcriti->IsKindOf(RUNTIME_CLASS(cCritterWormsPlayer))) ///* Lee added 11-11-01 */
      {	// Stops worm heads from being pushed around by other segments
	      if (pcriti->IsKindOf(RUNTIME_CLASS(cCritterPlayerWormsSeg)))
		      return FALSE;
      }
      if (pcriti->IsKindOf(RUNTIME_CLASS(cCritterWormsSeg))) ///* Lee added 11-11-01 */
      {	// Stops worm heads from being pushed around by other segments
	      return FALSE;
      }
      if (pcriti->IsKindOf(RUNTIME_CLASS(cCritterPlayerWormsSeg))) ///* Lee added 11-11-01 */
      {	// Stops worm heads from being pushed around by other segments
	      return FALSE;
      }
      //*//* Lee added 11-11-01 */
/*
      if (pcriti->IsKindOf(RUNTIME_CLASS(cCritterWormsPlayer))) 
      {
         cCritterWormsPlayer * player = (cCritterWormsPlayer * )pcriti;
	      if (pcritj->IsKindOf(RUNTIME_CLASS(cCritterWormsSeg)))
	      {
            cCritterWormsSeg * seg = (cCritterWormsSeg *)pcritj;
            seg->getSnake()->eatenTail();
            player->getSnake()->growSnake();
            //pcritj->die();
		      //return FALSE;
	      }
      }*/
   }
   return collide;                  /* 11-12 Joe */
	//return cGame::collide(pcriti, pcritj);
}

void cGameWorms::adjustGameParameters()
{
// (1) End the game if the player is dead
	if (!health()  && !_gameover) //Player's been killed and game's not over.
	{
		_gameover = TRUE;
		pplayer()->addScore(_scorecorrection); // So user can reach _maxscore 
		((CPopApp*)::AfxGetApp())->playSound("Tada",
			SND_RESOURCE|SND_ASYNC);
		return; 
	}
// (2) Perhaps do this to reseed the screen if rivals are gone.
	int othercrittercount = pbiota()->count(RUNTIME_CLASS(cCritter)) -
		pbiota()->count(RUNTIME_CLASS(cCritterWall)) - /* Lee added 11-11-01 */
		pbiota()->count(RUNTIME_CLASS(cCritterPlayerWormsSeg)) - 1; /* Lee added 11-11-01 */

	/***** possibly add to level here, maybe increase snake intel? *****/ /* Lee added 11-11-01 */
		//Number of critters minus bullets minus player equals other critters.
	if (!othercrittercount) //Player is alone with bullets
		seedCritters();
// (3) Maybe check some other conditions.
}

void cGameWorms::Serialize(CArchive& ar)
{
	cGame::Serialize(ar);
	if (ar.IsStoring()) // Save any extra variables
		ar << _rivalcount ; //Line of form ar << ...
	else //Load any extra variables 
		ar >> _rivalcount; //Line of form ar >> ...
}

//====================cCritterWormsPlayer
cCritterWormsPlayer::cCritterWormsPlayer()
{
   cCritterWormsBase::cCritterWormsBase();              /* 11-12 Joe SnakeClass*/
		//Set the listener
	setListener(new cListenerArrow());              /* 11-12 Joe */
//   setListener( new cListenerFly() );
      //Set the bullet
		//Set other variables, perhaps including sprite.

	setHealth(cGameWorms::PLAYERHEALTH);
		/* Maybe add some forces like gravity; the player will ignore them, but the
			bullets it shoots will use them. */
   setMaxspeed( cCritter::MAXSPEED );                                                     /* 11-12 Joe */
	//Let's test out a cSpriteDirectional or a cSpriteLoop
	//Swith on the 
	/*
#ifdef PLAYERSPRITELOOP
	cSpriteLoop *pmultisprite = new cSpriteLoop(); //OR Cycle through changes
#else //The not PLAYERSPRITELOOP case we do a directional sprite.
	cSpriteDirectional *pmultisprite = new cSpriteDirectional(); //Change with direction
#endif //End PLAYERSPRITELOOP switch.

	cPolygon *ppolygon = new cPolygon(8);
	ppolygon->setVertex(4, cVector(0, 0)); //Puts a dent in the "back" side.
	ppolygon->setFillColor(cColorStyle::CN_GREEN);
	ppolygon->setDotted(TRUE);
	ppolygon->setDotRadiusWeight(0.3);
	ppolygon->pdotcolorstyle()->setFillColor(cColorStyle::CN_BLUE);
	pmultisprite->add(ppolygon);

	ppolygon = new cPolygon(8);
	ppolygon->setVertex(4, cVector(0, 0)); 
	ppolygon->setFillColor(cColorStyle::CN_YELLOW);
	ppolygon->setDotted(TRUE);
	ppolygon->setDotRadiusWeight(0.3);
	ppolygon->pdotcolorstyle()->setFillColor(cColorStyle::CN_BLUE);
	pmultisprite->add(ppolygon);

	ppolygon = new cPolygon(8);
	ppolygon->setVertex(4, cVector(0, 0)); 
	ppolygon->setFillColor(cColorStyle::CN_RED);
	ppolygon->setDotted(TRUE);
	ppolygon->setDotRadiusWeight(0.3);
	ppolygon->pdotcolorstyle()->setFillColor(cColorStyle::CN_BLUE);
	pmultisprite->add(ppolygon);

	ppolygon = new cPolygon(8);
	ppolygon->setVertex(4, cVector(0, 0)); 
	ppolygon->setFillColor(cColorStyle::CN_PURPLE);
	ppolygon->setDotted(TRUE);
	ppolygon->setDotRadiusWeight(0.3);
	ppolygon->pdotcolorstyle()->setFillColor(cColorStyle::CN_BLUE);
	pmultisprite->add(ppolygon);
*/
//	setSprite(pmultisprite);
   setSprite( new cSpriteIcon(IDB_UFO) );
	setRadius(2.5*cCritter::MINRADIUS);
}

void cCritterWormsPlayer::reset()
{
   /* the player is no longer an armed player     /*  11-5 Joe */
	// cCritterArmedPlayer::reset(); */
		//Perhaps use setHealth to restore the health to a high value.
	setHealth(cGameWorms::PLAYERHEALTH);
}

BOOL cCritterWormsPlayer::collide(cCritter *pcritter)
{
	BOOL collideflag = cCritter::collide(pcritter);
		//May sometimes do more stuff here if collideflag is TRUE.
   if( collideflag )
   {
      if (pcritter->IsKindOf(RUNTIME_CLASS(cCritterWormsSeg)))
      {
         cCritterWormsSeg * seg = (cCritterWormsSeg *)pcritter;
         seg->getSnake()->eatenTail();
         getSnake()->growSnake();
         //pcritj->die();
	      //return FALSE;
      }
   }
	return collideflag;
}

void cCritterWormsPlayer::update(Real dt, CPopView *pview)
{
   // Again the player is no longer armed   /* 11-5 Joe */
	 //cCritter::update(dt, pview);//Always call this first
}
/*
int cCritterWormsPlayer::damage(int hitstrength)
{
	//Let's have the bullets be like food.
	addScore(hitstrength);
	return 0;
}*/

//==================== cCritterWormsSeg ====================

//cCritterWormsSeg::cCritterWormsSeg(cCritter *pcritter) /* Lee added 11-11-01 */
cCritterWormsSeg::cCritterWormsSeg(cCritterWormsBase *pcritter) /* Lee added 11-11-01 */
{
   setPrevious( pcritter );                 /* 11-12 Joe SnakeClass*/
//   setMaxspeed( cCritter::MAXSPEED + 1.5 );                                                     /* 11-12 Joe */
		//Set the health and value.  Make a sprite and use setSprite to install it.
		//For instance you might use a random sprite.
	setSprite(cGame::RANDOMSPRITE(cGame::ST_BUBBLES));//ST_SIMPLEPOLYGONS)); /* Lee added 11-11-01 */
		//Use addForce to add forces.
		//Randomize velocity if you like.
	//randomize(cCritter::MF_VELOCITY); /* Lee added 11-11-01 */
		//Set a particular radius ifyou like.
    //setRadius(0.5);
	setRadius( 0.7 );		/* 11-6 Joe */
		//Add some forces
		//Just for kicks lets add a spring force.
	if (pcritter)
		addForce(new cForceObjectLinkRod(pcritter,		// changed to LinkRod force 11/12/01 -Rich
			1.0));//,		// distance between critters	/* Lee added 11-11-01 */
		//addForce(new cForceObjectSpringRod(pcritter,
      //   1.0,    // want to distance between critters   /* Lee added 11-11-01 */
      // radius()+pcritter->radius(), //rodlength
		//	1000 )); // 3.0)); //spring force   /* 11-5 Joe Cheng */
}
/*
int cCritterWormsSeg::damage(int hitstrength) /* Lee added 11-11-01 *//*
{
	if (psprite()->IsKindOf(RUNTIME_CLASS(cPolygon)))/* I have to check this
		because if I try and cast a non-cPolygon sprite, the program will crash. 
	{
		cPolygon *ppolygon = (cPolygon*)psprite();
		if (ppolygon->vertCount() == 3) //Down to three verts
			ppolygon->changeVertexcount(7); //Jump to 10
		else
			ppolygon->changeVertexcount(-1);
	}
	return 0; 
}*/

BOOL cCritterWormsSeg::collide(cCritter *pcritter)
{
	BOOL collideflag = cCritter::collide(pcritter);
		//May sometimes do more stuff here if collideflag is TRUE.

	return collideflag;
}

void cCritterWormsSeg::update(Real dt, CPopView *pview)
{
	cCritter::update(dt, pview); //Always call this first
}

//==================== cCritterPlayerWormsSeg ====================

//cCritterPlayerWormsSeg::cCritterPlayerWormsSeg(cCritter *pcritter)
cCritterPlayerWormsSeg::cCritterPlayerWormsSeg(cCritterWormsBase *pcritter)
{  
   setPrevious( pcritter );                 /* 11-12 Joe SnakeClass*/
//   setMaxspeed( cCritter::MAXSPEED + 2.5 );                                                     /* 11-12 Joe */
		//Set the health and value.  Make a sprite and use setSprite to install it.
		//For instance you might use a random sprite.
	setSprite(cGame::RANDOMSPRITE(cGame::ST_BUBBLES));
		//Use addForce to add forces.
		//Randomize velocity if you like.
//	randomize(cCritter::MF_VELOCITY);
		//Set a particular radius ifyou like.
    //setRadius(0.5);
	setRadius( 0.7 );		/* 11-6 Joe */
		//Add some forces
		//Just for kicks lets add a spring force.
	if (pcritter)
      //addForce(new cForceObjectLinkRod(pcritter,		// changed to LinkRod force 11/12/01 -Rich
		//	1.0));//,		// distance between critters	/* Lee added 11-11-01 */
		addForce(new cForceObjectSpringRod(pcritter,
         0.7,    // want to distance between critters   /* 11-5 joe cheng  */
      // radius()+pcritter->radius(), //rodlength
			1000 )); // 3.0)); //spring force   /* 11-5 Joe Cheng */
}
/*
int cCritterPlayerWormsSeg::damage(int hitstrength) /* Lee added 11-11-01 *//*
{
	if (psprite()->IsKindOf(RUNTIME_CLASS(cPolygon)))/* I have to check this
		because if I try and cast a non-cPolygon sprite, the program will crash. *//*
	{
		cPolygon *ppolygon = (cPolygon*)psprite();
		if (ppolygon->vertCount() == 3) //Down to three verts
			ppolygon->changeVertexcount(7); //Jump to 10
		else
			ppolygon->changeVertexcount(-1);
	}
	return 0; 
}*/

BOOL cCritterPlayerWormsSeg::collide(cCritter *pcritter) /* Lee added 11-11-01 */
{
	//BOOL collideflag = cCritter::collide(pcritter);
		//May sometimes do more stuff here if collideflag is TRUE.
	//return collideflag;
   return false;
}

void cCritterPlayerWormsSeg::update(Real dt, CPopView *pview) /* Lee added 11-11-01 */
{
	cCritter::update(dt, pview); //Always call this first
}

//===================cCritterMazeWall /* Lee added 11-04-01 */
cCritterMazeWall::cCritterMazeWall(const cVector &enda, const cVector &endb,
	 Real thickness):
cCritterWall(enda, endb, thickness)
{
	setFixedflag(TRUE);
}

//===================cCritterWormsEnemyHead        /* 11-5 Joe */
cCritterWormsEnemyHead::cCritterWormsEnemyHead( cCritter * pcritter )
//cCritterWormsEnemyHead::cCritterWormsEnemyHead()
{
//   addForce( new cForceObjectAccelerateTowards( pcritter, 10 ) );     /* 11-12 Joe */
   setSprite( new cSpriteIcon(IDB_FACE) );
	//randomize(cCritter::MF_VELOCITY); /* Lee added 11-11-01 */
   setRadius( 1.0 );
}

BOOL cCritterWormsEnemyHead::collide( cCritter * pcritter )
{
	BOOL collideflag = cCritter::collide(pcritter);
		//May sometimes do more stuff here if collideflag is TRUE.
   if( collideflag )
   {
      if (pcritter->IsKindOf(RUNTIME_CLASS(cCritterPlayerWormsSeg)))
      {
         cCritterPlayerWormsSeg * seg = (cCritterPlayerWormsSeg *)pcritter;
         seg->getSnake()->eatenTail();
         getSnake()->growSnake();
         //pcritj->die();
	      //return FALSE;
      }
   }
	return collideflag;
}

//====================cCritterWorms                /* 11-12 Joe SnakeClass */
void cCritterWormsSnake::eatenTail()
{
   cCritterWormsBase * oldTail;

   oldTail = _pTail;
   
   _pTail = _pTail->getPrevious();
   
   oldTail->die();
}

/* 11-12 Joe */
void cCritterWormsSnake::growSnake()
{
   if (_pHead->IsKindOf(RUNTIME_CLASS(cCritterWormsPlayer)))
   {
      cCritterPlayerWormsSeg * newSeg = new cCritterPlayerWormsSeg( _pTail );
      newSeg->setMoveBox( cRealBox2( cVector( -19, -14.5 ), cVector( 19, 14.5 ) ) );
      newSeg->moveTo( _pTail->position() );
      _pGame->add( newSeg );
      newSeg->setSnake( this );
      _pTail = newSeg;
   }
   if (_pHead->IsKindOf(RUNTIME_CLASS(cCritterWormsEnemyHead)))
   {
      cCritterWormsSeg * newSeg = new cCritterWormsSeg( _pTail );
      _pGame->add( newSeg );
      newSeg->setSnake( this );
      _pTail = newSeg;
   }
}