/*============================================================*/
/*============================================================*/
/*==														==*/
/*==				Play Handling Core Routines				==*/
/*==														==*/
/*============================================================*/
/*============================================================*/


/*========================================================  Includes  */

#include "AppleTalkDDP.h"
#include "Globals.h"
#include "UnivUtilities.h"
#include "PlayCore.h"
#include "NetOpponent.h"
#include "SoundUtils.h"
#include "MainWindow.h"
#include "PlayUtils.h"
#include "RenderQD.h"
#include "Replay.h"
#include "CommonPerson.h"
#include "Human.h"
#include "Dynamics.h"
#include "Render.h"
#include "Ball.h"


/*========================================================  Functions  */
/*========================================================  DoCommandKey  */

void DoCommandKey (void)

{
	#define			kNoThanksButton	1
	short			response;
	Boolean			dummyBool;
	
	if (BitTst(&theKeyMap, kQKeyMap))			/* is -Q- key held down? */
	{
		quitting = TRUE;
		primaryMode = kIdleMode;
		if (netGameInSession)
			dummyBool = SendModalMessage(kAbortGameMessage);
	}
	
	if (BitTst(&theKeyMap, kEKeyMap))			/* is -E- key held down? */
	{
		if ((whichGame == kTournament) && (!gameIsOver))
		{
			timePaused = Ticks;
			
			FlushSoundQueues();
			StopCrowdSound();
			TurnSMSOff();
			InitCursor();
			FlushEvents(everyEvent, kRemoveAllEvents);
			CenterAlert(rAbortGameAlertID);
			
			response = Alert(rAbortGameAlertID, kNilPointer);
			
			TurnSMSOn();
			RefreshMainWindow();
			ResumeCrowdSound();
			UpdatePlayerScore();
			UpdateOpponentScore();
			timePaused = Ticks - timePaused;
			baseTime += timePaused / 60;
			RedrawWholeScreen();
			HideCursor();
			
			if (response == kNoThanksButton)
			{
				return;
			}
			else
			{
				playerWonTheGame = kOpponentWon;
				UpdateStats();
				UpdateWorldRecords();
				primaryMode = kIdleMode;
			}
		}
		else
		{
			primaryMode = kIdleMode;
			if (netGameInSession)
			{
				dummyBool = SendModalMessage(kAbortGameMessage);
			}
		}
	}
}


/*========================================================  DoPausing  */

void DoPausing (void)

{
	if (!netGameInSession)
	{
		pausing = TRUE;
		timePaused = Ticks;
	}
}


/*========================================================  UnPauseGame  */

void UnPauseGame (void)

{
	TurnSMSOn();
	
	HideMenuBar((GrafPtr)mainWndo);
	EraseMenuBarRect();
	RefreshMainWindow();
	
	ResumeCrowdSound();
	
	UpdatePlayerScore();
	UpdateOpponentScore();
	
	timePaused = Ticks - timePaused;
	baseTime += timePaused / 60;
	
	RedrawWholeScreen();
	
	HideCursor();
}


/*========================================================  DoSpecial  */

void DoSpecial (void)

{
	Point		theMouse;
	
	GetMouse(&theMouse);
	LocalToGlobal(&theMouse);
	theMouse.h -= displayHCenter;
	theMouse.v -= displayVCenter;
	
	theBall.xPos = theMouse.h * 128;
	theBall.zPos = -theMouse.v * 128;
	theBall.xVel = 0;
	theBall.zVel = 0;
}


/*========================================================  DoSoundToggle  */

void DoSoundToggle (void)

{
	soundOn = !soundOn;
	if (soundOn)
	{
		StartCrowdSound();
	}
	else
	{
		StopCrowdSound();
	}
	while (BitTst(&theKeyMap, kSKeyMap))
		GetKeys(theKeyMap);
}


/*========================================================  CheckAbortiveInput  */

void CheckAbortiveInput (void)

{
	Boolean			confirmed;
	
	GetKeys(theKeyMap);
	if (BitTst(&theKeyMap, kCommandKeyMap))
		DoCommandKey();
	if (BitTst(&theKeyMap, kTabKeyMap))
		DoPausing();
	if (BitTst(&theKeyMap, kSKeyMap))
		DoSoundToggle();
	if ((replayOnR) && (BitTst(&theKeyMap, kRKeyMap)))
	{
		if (netGameInSession)
		{
			confirmed = SendModalMessage(kInstantReplayMessage);
		}
		DoInstantReplay();
	}
	if (BitTst(&theKeyMap, kOptionKeyMap) && BitTst(&theKeyMap, kZKeyMap))
		DoSpecial();
}


/*========================================================  HandleTimerEtc  */

void HandleTimerEtc (void)

{
	if (replaySomething)
	{
		replayFlag++;
		if (replayFlag == 0)
			DoInstantReplay();
	}
	
	theDoor.stateChanged = FALSE;
	
	if ((netGameInSession) && (!imTheMaster))
		return;
	
	timeElapsed = (Ticks / 60) - baseTime;			/* get seconds elapsed */
}


/*========================================================  RunGameOverGame  */

void RunGameOverGame (void)

{
	long		waitTil, endWhen, pauseTime;
	short		starsWinked, lightNumber;
	Boolean		dummyBool;
	
	lightNumber = 0;
	waitTil = Ticks + kTickDelay;
	endWhen = Ticks + kHooplaTime;
	
	while ((!pausing) && (primaryMode == kPlayMode))
	{
		DetermineFrameRate();
		
		if (playerWonTheGame == kPlayerWon)
		{
			HandlePerson(&thePlayer);
			if (theOpponent.mode == kBeamingOut)
				HandlePerson(&theOpponent);
		}
		else if (playerWonTheGame == kOpponentWon)
		{
			HandlePerson(&theOpponent);
			if (thePlayer.mode == kBeamingOut)
				HandlePerson(&thePlayer);
		}
		
		if (waitTil > endWhen)
		{
			if (playerWonTheGame == kPlayerWon)
			{
				if (thePlayer.mode == kInStasis)
				{
					primaryMode = kIdleMode;
				}
				else if (thePlayer.mode == kInArena)
				{
					StartPersonBeamOut(&thePlayer);
				}
				else
					HandlePerson(&thePlayer);
			}
			else if (playerWonTheGame == kOpponentWon)
			{
				if (theOpponent.mode == kInStasis)
				{
					primaryMode = kIdleMode;
				}
				else if (theOpponent.mode == kInArena)
				{
					StartPersonBeamOut(&theOpponent);
				}
				else
					HandlePerson(&theOpponent);
			}
		}
		
		HandleBoardCursor();
		HandleCollisions();
		HandleCrowdSound();
		HandleIncidentalQueue();
		
		CheckAbortiveInput();
		if (enableBackground)
			dummyBool = GetOSEvent(everyEvent, &theEvent);
		HideCursor();
		
		starsWinked = 0;
		while (Ticks < waitTil)
		{
			CheckAbortiveInput();
			
			if (starsWinked < 3)
			{
				TwinkleAStar();
				starsWinked++;
			}
		}
		waitTil = Ticks + kTickDelay;
		
		if (replaySomething)
			AmassReplayData();
		HandlePreGraphics();
		RenderScene();
		HandlePostGraphics();
		
		pauseTime = Ticks;
		HandleTimerEtc();
		pauseTime = Ticks - pauseTime;
		waitTil += pauseTime;
		endWhen += pauseTime;
	}
}


/*========================================================  RunNetGameOverGame  */

void RunNetGameOverGame (void)

{
	long		waitTil, endWhen;
	short		starsWinked;
	Boolean		dummyBool;
	
	waitTil = Ticks + kTickDelay;
	endWhen = Ticks + kHooplaTime;
	
	while ((!pausing) && (primaryMode == kPlayMode))
	{
		DetermineFrameRate();
		
		if (imTheMaster)
		{
			if (playerWonTheGame == kPlayerWon)
			{
				HandlePerson(&thePlayer);
				ReceiveMessage();				/* get user input from slave */
				if (theOpponent.mode == kBeamingOut)
				{
					HandlePerson(&theOpponent);
				}
			}
			else if (playerWonTheGame == kOpponentWon)
			{
				ReceiveMessage();				/* get user input from slave */
				HandlePerson(&theOpponent);
				if (thePlayer.mode == kBeamingOut)
					HandlePerson(&thePlayer);
			}
			
			if (waitTil > endWhen)
			{
				if (playerWonTheGame == kPlayerWon)
				{
					if (thePlayer.mode == kInStasis)
					{
						dummyBool = SendModalMessage(kEndGameMessage);
						primaryMode = kIdleMode;
					}
					else if (thePlayer.mode == kInArena)
					{
						StartPersonBeamOut(&thePlayer);
					}
					else
						HandlePerson(&thePlayer);
				}
				else if (playerWonTheGame == kOpponentWon)
				{
					if (theOpponent.mode == kInStasis)
					{
						dummyBool = SendModalMessage(kEndGameMessage);
						primaryMode = kIdleMode;
					}
					else if (theOpponent.mode == kInArena)
					{
						StartPersonBeamOut(&theOpponent);
					}
					else
						HandlePerson(&theOpponent);
				}
			}
			
			HandleBoardCursor();
			HandleCollisions();
		}
		else
		{
			PrepareNetHumanInput();
			PrepareStandardMessage();
			SendMessage();
		}
		
		HandleCrowdSound();
		HandleIncidentalQueue();
		
		CheckAbortiveInput();
		if (enableBackground)
			dummyBool = GetOSEvent(everyEvent, &theEvent);
		HideCursor();
		
		starsWinked = 0;
		while (Ticks < waitTil)
		{
			CheckAbortiveInput();
			
			if (starsWinked < 3)
			{
				TwinkleAStar();
				starsWinked++;
			}
		}
		waitTil = Ticks + kTickDelay;
		
		if (imTheMaster)
		{
			if (replaySomething)
				AmassReplayData();
			HandlePreGraphics();
			if (primaryMode == kPlayMode)
			{
				PrepareStandardMessage();
				SendMessage();					/* send a "frame" to slave */
			}
			wasLastSound = 0;
			lastSoundPriority = 0;
		}
		else
		{
			ReceiveMessage();
			HandleBoardCursor();
			if (replaySomething)
				AmassReplayData();
			HandlePreGraphics();
			if ((wasLastSound > 0) && (wasLastSound <= kLastIncidentalSounds))
			{
				PlaySoundSMS(wasLastSound);
			}
			wasLastSound = 0;
			lastSoundPriority = 0;
		}
	
		RenderScene();
		HandlePostGraphics();
		HandleTimerEtc();
	}
}


/*========================================================  RunNetGame  */

void RunNetGame (void)

{
	long		waitTil;
	short		starsWinked;
	Boolean		dummyBool;
	
	waitTil = Ticks + kTickDelay;
	
	while ((!pausing) && (primaryMode == kPlayMode) && (!gameIsOver))
	{
		DetermineFrameRate();
		
		if (imTheMaster)
		{
			HandlePerson(&thePlayer);
			HandleBoardCursor();
			ReceiveMessage();					/* get user input from slave */
			HandlePerson(&theOpponent);
			HandleBall();
			HandleCollisions();
		}
		else
		{
			PrepareNetHumanInput();
			PrepareStandardMessage();
			SendMessage();						/* send user input to master */
		}
		
		HandleCrowdSound();
		HandleIncidentalQueue();
		
		CheckAbortiveInput();
		if (enableBackground)
			dummyBool = GetOSEvent(everyEvent, &theEvent);
		HideCursor();
		
		starsWinked = 0;
		while (Ticks < waitTil)
		{
			CheckAbortiveInput();
			
			if (starsWinked < 3)
			{
				TwinkleAStar();
				starsWinked++;
			}
		}
		waitTil = Ticks + kTickDelay;
		
		if (imTheMaster)
		{
			if (replaySomething)
				AmassReplayData();
			HandlePreGraphics();
			if (primaryMode == kPlayMode)
			{
				PrepareStandardMessage();
				SendMessage();					/* send a "frame" to slave */
			}
			wasLastSound = 0;
			lastSoundPriority = 0;
		}
		else
		{
			ReceiveMessage();					/* receive a "frame" from master */
			if (whosGotBall == kPlayerHasBall)
			{
				thePlayer.loopsBallHeld--;
				if (thePlayer.loopsBallHeld < 0)
					thePlayer.loopsBallHeld = 0;
				UpdateBallTimers(&thePlayer);
			}
			else if (whosGotBall == kOpponentHasBall)
			{
				theOpponent.loopsBallHeld--;
				if (theOpponent.loopsBallHeld < 0)
					theOpponent.loopsBallHeld = 0;
				UpdateBallTimers(&theOpponent);
			}
			HandleBoardCursor();
			if (replaySomething)
				AmassReplayData();
			HandlePreGraphics();
			if ((wasLastSound > 0) && (wasLastSound <= kLastIncidentalSounds))
			{
				PlaySoundSMS(wasLastSound);
			}
			wasLastSound = 0;
			lastSoundPriority = 0;
		}
		RenderScene();
		HandlePostGraphics();
		HandleTimerEtc();
	}
	
	if (gameIsOver)
	{
		if (imTheMaster)
		{
			dummyBool = SendModalMessage(kGameIsOverMessage);
			dummyBool = WhatsTheGamesOutcome();
		}
		RunNetGameOverGame();
	}
}


/*========================================================  RunBoardinGame  */

void RunBoardinGame (void)

{
	long		waitTil;
	short		starsWinked;
	Boolean		dummyBool;
	
	waitTil = Ticks + kTickDelay;
	
	while ((!pausing) && (primaryMode == kPlayMode))
	{
		DetermineFrameRate();
		
		HandlePerson(&thePlayer);
		HandleBoardCursor();
		
		if (thePlayer.justHitWall > 0)
			thePlayer.justHitWall--;
		
		CheckAbortiveInput();
		if (enableBackground)
			dummyBool = GetOSEvent(everyEvent, &theEvent);
		HideCursor();
		
		starsWinked = 0;
		while (Ticks < waitTil)
		{
			CheckAbortiveInput();
			
			if (starsWinked < 3)
			{
				TwinkleAStar();
				starsWinked++;
			}
		}
		waitTil = Ticks + kTickDelay;
		
		if (replaySomething)
			AmassReplayData();
		HandlePreGraphics();
		RenderScene();
		HandlePostGraphics();
		
		HandleTimerEtc();
	}
}


/*========================================================  RunScorinGame  */

void RunScorinGame (void)

{
	long		waitTil;
	short		starsWinked;
	Boolean		dummyBool;
	
	waitTil = Ticks + kTickDelay;
	
	while ((!pausing) && (primaryMode == kPlayMode))
	{
		DetermineFrameRate();
		
		HandlePerson(&thePlayer);
		HandleBoardCursor();
		HandleBall();
		
		HandleCollisions();
		
		CheckAbortiveInput();
		if (enableBackground)
			dummyBool = GetOSEvent(everyEvent, &theEvent);
		HideCursor();
		
		starsWinked = 0;
		while (Ticks < waitTil)
		{
			CheckAbortiveInput();
			
			if (starsWinked < 3)
			{
				TwinkleAStar();
				starsWinked++;
			}
		}
		waitTil = Ticks + kTickDelay;
		
		if (replaySomething)
			AmassReplayData();
		HandlePreGraphics();
		RenderScene();
		HandlePostGraphics();
		
		HandleTimerEtc();
	}
}


/*========================================================  RunStandardGame  */

void RunStandardGame (void)

{
	long		waitTil;
	short		starsWinked;
	Boolean		dummyBool;
	
	waitTil = Ticks + kTickDelay;
	
	while ((!pausing) && (primaryMode == kPlayMode) && (!gameIsOver))
	{
		DetermineFrameRate();
		
		HandlePerson(&thePlayer);
		HandleBoardCursor();
		HandlePerson(&theOpponent);
		HandleBall();
		HandleCollisions();
		HandleCrowdSound();
		HandleIncidentalQueue();
		
		CheckAbortiveInput();
		if (enableBackground)
			dummyBool = GetOSEvent(everyEvent, &theEvent);
		HideCursor();
		
		starsWinked = 0;
		while (Ticks < waitTil)
		{
			CheckAbortiveInput();
			
			if (starsWinked < 3)
			{
				TwinkleAStar();
				starsWinked++;
			}
		}
		waitTil = Ticks + kTickDelay;
		
		if (replaySomething)
			AmassReplayData();
		HandlePreGraphics();
		RenderScene();
		HandlePostGraphics();
		
		HandleTimerEtc();
	}
	
	if (gameIsOver)
		RunGameOverGame();
}


/*========================================================  PlayGame  */

void PlayGame (void)

{
	if (newGame)
		PrepareNewGame();
	else
		UnPauseGame();
	
	if (netGameInSession)
	{
		RunNetGame();
	}
	else
	{
		switch (whichGame)
		{
			case kPracticeBoardin:
				RunBoardinGame();
				break;
			case kPracticeScoring:
				RunScorinGame();
				break;
			case kStandardGame:
			case kTournament:
				RunStandardGame();
				break;
			default:
				break;
		}
	}
	
	FlushSoundQueues();
	StopCrowdSound();
	TurnSMSOff();
	RedrawWholeScreen();
	ShowMenuBar((GrafPtr)mainWndo);
	FixVisRegion();
	InitCursor();
	FlushEvents(everyEvent, kRemoveAllEvents);
	
	if (primaryMode != kPlayMode)
		DoEndGame();
}


