// C Source File
// Created 9/4/2004; 2:41:32 PM

#include "MainHeader.h"


//VARIABLES



//FUNCTIONS
void phys_DoPhys();
void phys_MarioPhys();
void phys_DoParticles();
void phys_DoEnemies();
short getEnemyType(short PosX, short PosY);
short getEnemyDirection(short PosX, short PosY);






//MAIN SUB INCHARGE OF PHYSICS
void phys_DoPhys()
{
	//skip physics, when mario is in the middle of transforming
	//from one state to another
	if(Mario.Transition)
		return;
	
	//Make mario do his thang..
	phys_MarioPhys();
	
	//Make the partices move and such
	phys_DoParticles();
	
	//Make the enemies do their job
	phys_DoEnemies();
}


//HANDS MARIOS OWN PHSYICS
void phys_MarioPhys()
{
	//no physics, at this point of level completion
	if(LevelComplete>2) return;
	
	//marios y composition increase because of gravity, unless on a vine
	if(!Mario.OnVine) Mario.YCmp++;
	
	//if mario is jumping, move his jdir
	if(Mario.IsJumping)
	{
		Mario.x+=Mario.JDir2;
		if(!_keytest(RR_2ND))
			Mario.YCmp++;
	}
		
	if(Mario.YCmp>4)
	{
		if(!Mario.Swimming)
			Mario.YCmp=10;
		else
			Mario.YCmp=4;
	}

	//mario falls at his ycmp, unless on a vine
	if(!Mario.OnVine || Mario.OnFlagpole) Mario.y+=Mario.YCmp;

	
	//lower marios invunerability, if he has any
	if(Mario.Invincible)
		Mario.Invincible--;
		
	//if mario is airborn, no momentum
	if(Mario.Airborn)
		Mario.Momentum=0;
}

//THE PHYSICS BEHING MARIO JUMPING
void phys_MarioJump(short Dir)
{
	Mario.IsJumping=true;
	Mario.YCmp=-12;
	Mario.JDir=Mario.Direction;
	Mario.JDir2=Dir;
	Mario.Momentum=0;
}



//THE PHYSICS FOR THE PARTICLES...
void phys_DoParticles()
{
	short x, PType, PYCmp; //looping variable
	
	//loops for all 12 particles
	for(x=0;x<Max_Particles;x++)
	{
		PType=Particle[x][p_Type];
		
		//only do active particles
		if(PType!=-1)
		{
		
			//if its a score type
			if(PType==p_Score)
			{
				//increase its life..
				Particle[x][p_Life]--;
				
				//if its life is <0 then kill the particle
				if(Particle[x][p_Life]<0)
					Particle[x][p_Type]=-1;
					
				//move it up
				Particle[x][p_Y]--;
			}
			
			//if its a shroom...
			if(PType==p_Shroom)
			{
				//increase its life..
				Particle[x][p_Life]++;
				
				//if its greater than 3, than kill the particle
				if(Particle[x][p_Life]<17)
					Particle[x][p_Y]--;
					
				//move it based on its x and ycmp, if its over 16
				if(Particle[x][p_Life]>16)
				{
					//make sure it doesnt overflow
					Particle[x][p_Life]=17;
					
					//give it gravity...
					//Particle[x][p_YCmp]--;
					
					//move it
					//Particle[x][p_X]+=Particle[x][p_Dir];
					//Particle[x][p_Y]-=Particle[x][p_YCmp];
				}
				
				//if the particle is off screen, kill it
				//if(Particle[x][p_X]<Mario.x-16*7)
				//	Particle[x][p_Type]=-1;
					
				//if(Particle[x][p_X]>Mario.x+16*7)
				//	Particle[x][p_Type]=-1;
			}
			
			
			//if its a super star...
			if(PType==p_Star)
			{
				//increase its life..
				Particle[x][p_Life]++;
				
				//if its greater than 3, than kill the particle
				if(Particle[x][p_Life]<17)
					Particle[x][p_Y]--;
					
				//move it based on its x and ycmp, if its over 16
				if(Particle[x][p_Life]>16)
				{
					//make sure it doesnt overflow
					Particle[x][p_Life]=17;
					
					/*//give it gravity...
					Particle[x][p_YCmp]--;
					
					//move it
					Particle[x][p_X]+=Particle[x][p_Dir];
					Particle[x][p_Y]-=Particle[x][p_YCmp];*/
				}
				
				//if the particle is off screen, kill it
				/*if(Particle[x][p_X]<Mario.x-16*7)
					Particle[x][p_Type]=-1;
					
				if(Particle[x][p_X]>Mario.x+16*7)
					Particle[x][p_Type]=-1;*/
			}
			
			
			//if its a fire ball or bricl...
			if(PType==p_Fire || PType==p_Brick || PType==p_Shroom || PType==p_Star || PType==p_Hammer)
			{
				//if its an underage shroom, exit
				if((PType==p_Shroom || PType==p_Star) && Particle[x][p_Life]<17)
					continue;
					
				//increses the Y Component
				PYCmp= Particle[x][p_YCmp]+=1;
				
				//moves makes it "fall" at the ycmp
				Particle[x][p_Y]+=PYCmp;
				
				//move based on its x comp
				Particle[x][p_X]+=Particle[x][p_Dir];
				
				//if the particle is off screen..
				if(Particle[x][p_Y]>(17*16))
					Particle[x][p_Type]=-1;
				if(Particle[x][p_X]>Mario.x+160 || Particle[x][p_X]<Mario.x-160)
					Particle[x][p_Type]=-1;
			}//end if fire ball
			
			
			//if its an explosion...
			if(PType==p_Explosion)
			{
				//increase its life..
				Particle[x][p_Life]++;
				
				//if its greater than 3, than kill the particle
				if(Particle[x][p_Life]>3)
					Particle[x][p_Type]=-1;
			}
			

			//if its a flower...
			if(PType==p_Flower)
			{
				//increase its life..
				Particle[x][p_Life]++;
				
				//if its greater than 3, than kill the particle
				if(Particle[x][p_Life]<16)
					Particle[x][p_Y]--;
			}
			
			//if its a coin-spin
			if(PType==p_SpinCoin)
			{
				//increases its life..
				short PLife=Particle[x][p_Life]++;
				
				//if its life is under 16..
				if(PLife<8)
					//then move it up
					Particle[x][p_Y]-=4;
				
				//if its over 16..
				if(PLife>8)
					//then move it down
					Particle[x][p_Y]+=4;
					
				//if its greater than 32, kill it
				if(PLife>16)
				{
					//kill it
					Particle[x][p_Type]=-1;
					
					//spawn a 200 score
					SpawnScore(Particle[x][p_X]-3, Particle[x][p_Y], 200);	
				}
			}
			
		}//end if active particle
	}//next x
}

//PHYSICS FOR ENEMIES
void phys_DoEnemies()
{
	short x, Type; //looping variable
	
	//loops for all 12 particles
	for(x=0;x<Max_Enemies;x++)
	{
		Type = Enemy[x][e_Type];
		
		//only do active particles
		if(Type!=-1 && Enemy[x][e_Ani]!=es_Dead)
		{
			//if the particle is off screen, kill it
			/*if(Enemy[x][e_X]<Mario.x-16*15)
				{Enemy[x][e_Type]=-1; continue;}
				
			if(Enemy[x][e_X]>Mario.x+16*15)
				{Enemy[x][e_Type]=-1; continue;}
				
			if(Enemy[x][e_Y]>16*16)
				{Enemy[x][e_Type]=-1; continue;}*/
					
			//if its a goomba, beetle, spiney, koopa, or shell, just move it its dir / ycmp
			if(Type==eGoomba || Type==eBuzzy || Type==eSpiny || Type==eShell || Type==eBuzzyShell || Type==eKoopa)
			{
				//give it gravity...
				Enemy[x][e_YCmp]--;
				
				//move it
				Enemy[x][e_X]+=Enemy[x][e_Dir]*2;
				Enemy[x][e_Y]-=Enemy[x][e_YCmp];
			}
			
			//if its a smashed gooma
			if(Type==eStompedGoomba)
			{
				//if the enemy disapears, remove it
				if(Enemy[x][e_Life]-- <0)
					Enemy[x][e_Type]=-1;
			}
			
			//if its an air cheep cheep
			if(Type==eAirCheep)
			{
				short MX=(int)((Mario.x+23)/16)-1, CX=(int)((Enemy[x][e_X])/16)-1, EDir=Enemy[x][e_Dir];
				
				//if mario is to the right of it, then start it
				if(MX>CX+3 && EDir>0)
					Enemy[x][e_Ani]=1;
				else if(MX<CX+1 && MX>CX-6 && EDir<0)
					Enemy[x][e_Ani]=1;
					
				//if the enemy is ready to start moving
				if(Enemy[x][e_Ani]==1)
				{
					//give it gravity...
					Enemy[x][e_YCmp]--;
					
					//move it
					Enemy[x][e_X]+=EDir*3;
					Enemy[x][e_Y]-=Enemy[x][e_YCmp];
				}
			}
			
			//if its a cheep cheep or bullet bill, just move it
			if(Type==eBullet || Type==eCheep)
			{
				//move it
				Enemy[x][e_X]+=Enemy[x][e_Dir];
			}
			
			//if its a koopa paratroopa
			if(Type==eAirKoopa)
			{
				//increase its life
				short ELife=Enemy[x][e_Life]++;
				
				//prevent it from being too big
				if(ELife>30)
					Enemy[x][e_Life]=-30;
				
				ELife=Enemy[x][e_Life];
				
				//move em'
				if(ELife<0)
					Enemy[x][e_Y]--;
				else if(ELife>0)
				  Enemy[x][e_Y]++;
			}
			
			//if its podobo
			if(Type==ePodobo)
			{
				//increase its life
				short ELife=Enemy[x][e_Life]++;
				
				//prevent it from being too big
				if(ELife>30)
					Enemy[x][e_Life]=-30;
					
				ELife=Enemy[x][e_Life];
				
				//move em'
				if(ELife<0)
				{
					Enemy[x][e_Y]-=3;
					Enemy[x][e_Dir]=-1;
				}
				else if(ELife>0)
				{
					Enemy[x][e_Y]+=3;
					Enemy[x][e_Dir]=1;
				}
			}
			
			//if its pirahana plant
			if(Type==ePlant)
			{
				//increase its life
				Enemy[x][e_Life]++;
				
				//prevent it from being too big
				if(Enemy[x][e_Life]>86)
					Enemy[x][e_Life]=0;
					
				short Life = Enemy[x][e_Life];
				
				//if its less then 24, move up
				if(Life<24)
					Enemy[x][e_Y]--;
				if(Life>44 && Life<69)
					Enemy[x][e_Y]++;
					
				//if mario is near by, hide it
				short MX=(int)((Mario.x+23)/16)-1, PX=(int)((Enemy[x][e_X])/16)-1;
				//printf_xy(1,20,"%d",MX);
				//printf_xy(1,28,"%d",PX);
				
				if(Life>69 && ((MX==PX) || (MX==PX+1) || (MX==PX+2) || (MX==PX+3)))
					Enemy[x][e_Life]=84;
			}
			
			//if its a cannon
			if(Type==eCannon)
			{
				//increase its life
				Enemy[x][e_Life]++;
				
				//prevent it from being too big
				if(Enemy[x][e_Life]>80)
					Enemy[x][e_Life]=0;
					
				short Life = Enemy[x][e_Life];
				
				//if 0 spawn bullet
				if(Life==0)
				{
					//marios xpos and cannons xpos
					short MX=(int)((Mario.x+23)/16)-1, CX=(int)((Enemy[x][e_X])/16)-1, Dir=0, y, E=0;
					
					//if mario is to the left, spwn bullet bill
					if(MX<CX+1 && MX>CX-10)
						Dir=-5;
					else if(MX>CX+1 && MX<CX+11) //or right
						Dir=5;
					else
						Dir=0;
						
					if(Dir!=0)
					{
						//loop thru to find an unused enemey "-1"
						for(y=Max_Enemies-1;y>=0;y--)
						{
							if(Enemy[y][e_Type]==-1)
								E=y;
						}//next x
						
						//sets up the enemy
						Enemy[E][e_Type]=eBullet;
						Enemy[E][e_X]=Enemy[x][e_X];
						Enemy[E][e_Y]=Enemy[x][e_Y];
						Enemy[E][e_Dir]=Dir;
						Enemy[E][e_Ani]=0;
						
						//printf_xy(0,20,"%d",E);
						//printf_xy(0,20,"%d",E);
						
					}//end if dir!=0
				}//end if life==0
			}//end if cannon
			
			//if its a bloober
			if(Type==eSquid)
			{
				//increase its life
				Enemy[x][e_Life]++;
				
				//let the life loop
				if(Enemy[x][e_Life]>30)
				{
					Enemy[x][e_Life]=0;
				}
					
					
				short Life=Enemy[x][e_Life];
				
				//if the life is less than 10, bloober sinks
				if(Life<15)
					Enemy[x][e_Y]+=2;
				
				//if its between 10 and 15, charge bloober
				if(Life>=10 && Life<15)
					Enemy[x][e_Dir]=1;
					
				//if his life IS 15, then choose a direction to shoot him off in
				if(Life==15)
				{
					short Rnd=random(3);
					short MX=(int)((Mario.x+23)/16)-1, BX=(int)((Enemy[x][e_X])/16)-1, Dir=0;
					
					//if mario is to the left or right
					if(MX<BX+1 && MX>BX-5)
						Dir=-2;
					else if(MX>BX+1 && MX<BX+6) //or right
						Dir=2;
					else
						Dir=(random(2)-1)*2;
						
					if(Rnd<2)
						Enemy[x][e_Ani]=Dir; //rand dir
					else
						Enemy[x][e_Ani]=-Dir; //rand dir
						
					Enemy[x][e_Dir]=-1; //enemy is now big
				}
				
				//if life is over 15, move by dir \ up
				if(Life>15)
				{
					Enemy[x][e_X]+=Enemy[x][e_Ani];
					Enemy[x][e_Y]-=2;
				}
			}//end if bloober
			
			
			//if its a lakutu
			if(Type==eLakutu)
			{
				//increase its life
				Enemy[x][e_Life]++;
				
				//if lakutus lifeis over 20, loop it
				if(Enemy[x][e_Life]>30)
					Enemy[x][e_Life]=0;
					
				short Life=Enemy[x][e_Life];
				
				short MX=(int)((Mario.x+23)/16)-1, LX=(int)((Enemy[x][e_X])/16)-1, Dir=0, y, E=0;
				
				//if he is ducking (between 10 & 15)
				if(Life>=10 && Life<15)
					Enemy[x][e_Ani]=1;
				else if(Life<15)
					Enemy[x][e_Ani]=0;
				
				//if it is 15, then randomly make him duck \ appear
				if(Life==15)
					Enemy[x][e_Ani]=random(2);
				
				//if its 25, he is not ducking
				if(Life==25)
					Enemy[x][e_Ani]=0;
				
				//if life is over 20, amke sure lakutu is facing mario
				if(Life>20)
				{
					//if mario is to the left or right
					if(MX<LX+1)
						Dir=-5;
					else if(MX>LX+1) //or right
						Dir=5;
					else
						while(Dir==0)
							Dir=(random(2)-1)*5;

					//save laukutus dir
					Enemy[x][e_Dir]=Dir;
				}
				
				//if life is 0, then he has to drop a spiney egg
				if(Life==0)
				{
					//loop thru to find an unused enemey "-1"
					for(y=Max_Enemies-1;y>=0;y--)
					{
						if(Enemy[y][e_Type]==-1)
							E=y;
					}//next x
					
					//sets up the enemy
					Enemy[E][e_Type]=eSpinyEgg;
					Enemy[E][e_X]=Enemy[x][e_X];
					Enemy[E][e_Y]=Enemy[x][e_Y];
					Enemy[E][e_Dir]=0;
					Enemy[E][e_YCmp]=0;
					Enemy[E][e_Life]=100;
				}
					
				//move lakutu
				Enemy[x][e_X]+=Enemy[x][e_Dir];
			}//end if lakutu
			
			
			//if its a spiney egg
			if(Type==eSpinyEgg)
			{
				//inc its ycmp, not more than 8 tho
				if(Enemy[x][e_YCmp]++>6)
					Enemy[x][e_YCmp]=6;
					
				//move em down
				Enemy[x][e_Y]+=Enemy[x][e_YCmp];
				
				short MX=(int)((Mario.x+23)/16)-1, EX=(int)((Enemy[x][e_X])/16)-1, Dir=2;
				
				//if mario is to the left or right
				if(MX<EX+1)
					Dir=-1;
				else if(MX>EX+1) //or right
					Dir=1;
					
				//Save the dir
				Enemy[x][e_Dir]=Dir;
			}//end if spiny egg
			
			//if its a hammer bro
			if(Type==eHammer)
			{
				//inc its life, not more than 8 tho
				if(Enemy[x][e_Life]++>41)
					Enemy[x][e_Life]=0;
				
				//inc its ycmp, not more than 6 tho
				if(Enemy[x][e_YCmp]++>6)
					Enemy[x][e_YCmp]=6;
					
				short Life=Enemy[x][e_Life];
				
				//if its a multiple of 6, throw a hammer
				if(Life%8==0)
				{
					//show arm up animation
					Enemy[x][e_Ani]=1;
					
					//spawn a hammer
					short P=0, z;
	
					//loop thru particles to find a free one
					for(z=0;z<Max_Particles;z++)
						if(Particle[z][p_Type]==-1)
						{
							P=z;
							z=Max_Particles+1;
						}
					
					//sets up the particle
					Particle[P][p_Type]=p_Hammer;
					Particle[P][p_X]=Enemy[x][e_X];
					Particle[P][p_Y]=Enemy[x][e_Y]-16;
					Particle[P][p_Dir]=Enemy[x][e_Dir]*4;
					Particle[P][p_YCmp]=-5;
					Particle[12][p_Life]=20;
				}
				else
					Enemy[x][e_Ani]=0;
				
				//if life IS 41, then make em' jump
				if(Life==41)
					Enemy[x][e_YCmp]=-10;
					
				short MX=(int)((Mario.x+23)/16)-1, EX=(int)((Enemy[x][e_X])/16)-1, Dir=2;
				
				//if mario is to the left or right
				if(MX<EX+1)
					Dir=-1;
				else if(MX>EX+1) //or right
					Dir=1;
				
				//make sure he is always facing mario
				Enemy[x][e_Dir]=Dir;
				
				//move em
				Enemy[x][e_Y]+=Enemy[x][e_YCmp];
				
				//if the life is less than 10 move left
				if(Life<10)
					Enemy[x][e_X]--;
				
				//if greater than 31, move right
				if(Life>32)
					Enemy[x][e_X]++;
					
				//if mario is 
			}//end if hammer bro
			
		}//end if active enemy
		
		//if its a dead enemy, just ycmp and xcmp until off screen...
		if(Enemy[x][e_Ani]==es_Dead)
		{
				//give it gravity...
				Enemy[x][e_YCmp]--;
				
				//move it
				Enemy[x][e_X]+=Enemy[x][e_Dir]*2;
				Enemy[x][e_Y]-=Enemy[x][e_YCmp];
		}
	}//next x
}




//THE PHYSICS FOR SHOOTING A FIRE BALL
void phys_ShootBall()
{
	short FireBall;
	
	//it must determine which particle slot to store the fire ball..
	if(Particle[8][p_Type]==-1)
		FireBall=8;
	else if(Particle[9][p_Type]==-1)
	  FireBall=9;
	else
	  return;
	
	//sets up the fire ball..
	Particle[FireBall][p_X]=Mario.x;
	Particle[FireBall][p_Y]=Mario.y;
	Particle[FireBall][p_Type]=p_Fire; //its a fire ball
	Particle[FireBall][p_YCmp]=0;
	if(Mario.Direction==RIGHT) //which way to shoot the fire ball?
		Particle[FireBall][p_Dir]=5;
	else
		Particle[FireBall][p_Dir]=-5;
}

//SPAWNING AN ENEMY
void phys_SpawnEnemy(short PosX, short PosY)
{
	short Type; //looping variable
	static short E=0;
	
	//the next enemy
	E++;
	if(E>Max_Enemies-1)
		E=0;
	
	//loop thru to find an unused enemey "-1"
	//for(x=Max_Enemies-1;x>=0;x--)
	//{
	//	if(Enemy[x][e_Type]==-1)
	//		E=x;
	//}//next x
	
	//sets up the enemy
	Enemy[E][e_Type]=getEnemyType(PosX, PosY);
	Enemy[E][e_X]=PosX*16;
	Enemy[E][e_Y]=PosY*16;
	Enemy[E][e_Dir]=getEnemyDirection(PosX, PosY);
	Enemy[E][e_YCmp]=0;
	Enemy[E][e_Life]=0;
	Enemy[E][e_Ani]=0;
	
	//removes the enemy from the map
	Map[PosY][PosX]=0;
	
	//special cases
	Type=Enemy[E][e_Type];
	
	//if its a pirhana plant
	if(Type==ePlant)
	{
		Enemy[E][e_X]+=8;
		Enemy[E][e_Y]+=16;
	}
	
	//if its a bullet bill, make it go faster
	if(Type==eBullet)
		Enemy[E][e_Dir]*=5;

	//if its a air cheep cheep
	if(Type==eAirCheep)
	{
		Enemy[E][e_YCmp]=11;
		Enemy[E][e_Dir]*=3;
	}
		
	
	//if its a cannon, replace the map tile with a static cannon
	if(Type==eCannon)
		Map[PosY][PosX]=55;
	
}

//RETURN THE ENEMY TYPE BASED ON ITS ID
short getEnemyType(short PosX, short PosY)
{
	short Type = Map[PosY][PosX]-1;
	
	if(Type==101 || Type==102)
		return eGoomba;
	else if(Type==103 || Type==104)
		return eKoopa;
	else if(Type==105 || Type==106)
		return eBuzzy;
	else if(Type==107 || Type==108)
		return eSpiny;
	else if(Type==109)
		return eHammer;
	else if(Type==110)
		return ePlant;
	else if(Type==111 || Type==112)
		return eAirKoopa;
	else if(Type==113 || Type==114)
		return eBullet;
	else if(Type==115 || Type==116)
		return eAirCheep;
	else if(Type==117)
		return eLakutu;
	else if(Type==118)
		return eSquid;
	else if(Type==119)
		return eCheep;
	else if(Type==120)
		return ePodobo;
	else if(Type==121)
		return eCannon;
	else if(Type==122)
		return eFlameCW315;
	else if(Type==123)
		return eFlameCW225;
	else if(Type==124)
		return eFlameCW135;
	else if(Type==125)
		return eFlameCCW45;
	else if(Type==126)
		return eFlameCCW315;
	else if(Type==127)
		return eFlameCCW225;
	else if(Type==128)
		return eFlameCCW135;
		
		
	//else garbadge
	return -1;
}


//RETURN THE SPAWN DIRECTION OF THE ENEMY
short getEnemyDirection(short PosX, short PosY)
{
	short Type = Map[PosY][PosX]-1;
	
	//if its a left facing enemy
	if(Type==101 || Type==103 || Type==105 || Type==107 || Type==109 || Type==110 || Type==111 || Type==113
	|| Type==115 || Type==117 || Type==118 || Type==119 || Type==120 || Type==121 || Type==122 || Type==123
	|| Type==124 || Type==121)
		return -1;
	else return 1;
}