//
// License: GPL
// Date: 18.3.2006
// Author: André Schnabel (thefrogs@web.de)
// http://www.masterspace.biz/andreschnabel/
//

// Game.cpp

#include "Game.h"

//
// Game
// Constructor
//
Game::Game(int argc, char **argv)
{
	int i;

	numPlayers = 2;

	for(i=1; i<argc; i++)
	{
		if(!strcmp(argv[i], "-3players"))
			numPlayers = 3;
		if(!strcmp(argv[i], "-4players"))
			numPlayers = 4;
	}

	players = new Player[numPlayers];
}

//
// ~Game
// Destructor
//
Game::~Game()
{
	delete [] players;
}

//
// NEW_ROUND
//
#define NEW_ROUND() \
{ \
	int c, d; \
	players[0].head.x = players[0].head.y = 5; \
	players[1].head.x = players[1].head.y = 20; \
	players[0].dir = DIR_RIGHT; \
	players[1].dir = DIR_LEFT; \
	if(numPlayers >= 3) \
	{ \
		players[2].head.x = players[2].head.y = 30; \
		players[2].dir = DIR_UP; \
	} \
	if(numPlayers == 4) \
	{ \
		players[3].head.x = players[3].head.y = 40; \
		players[3].dir = DIR_RIGHT; \
	} \
	for(c=0; c<MAP_H; c++) \
		for(d=0; d<MAP_W; d++) \
			map[c][d] = TILE_EMPTY; \
}

//
// Init
//
void Game::Init()
{
	InitResMngr("gameFilenames.txt");

	players[0].color = Color::red;
	players[1].color = Color::blue;

	NEW_ROUND();

	players[0].keyNums[DIR_LEFT] = SDLK_LEFT;
	players[0].keyNums[DIR_RIGHT] = SDLK_RIGHT;
	players[0].keyNums[DIR_UP] = SDLK_UP;
	players[0].keyNums[DIR_DOWN] = SDLK_DOWN;

	players[1].keyNums[DIR_LEFT] = SDLK_a;
	players[1].keyNums[DIR_RIGHT] = SDLK_d;
	players[1].keyNums[DIR_UP] = SDLK_w;
	players[1].keyNums[DIR_DOWN] = SDLK_s;

	if(numPlayers >= 3)
	{
		players[2].keyNums[DIR_LEFT] = SDLK_f;
		players[2].keyNums[DIR_RIGHT] = SDLK_h;
		players[2].keyNums[DIR_UP] = SDLK_t;
		players[2].keyNums[DIR_DOWN] = SDLK_g;

		players[2].color = Color::green;
	}

	if(numPlayers == 4)
	{
		players[3].keyNums[DIR_LEFT] = SDLK_j;
		players[3].keyNums[DIR_RIGHT] = SDLK_l;
		players[3].keyNums[DIR_UP] = SDLK_i;
		players[3].keyNums[DIR_DOWN] = SDLK_k;

		players[3].color = Color::magenta;
	}

	gameOver = false;

	lUpdate = framework->GetTicks();

	Mix_VolumeMusic(MIX_MAX_VOLUME / 2);
	framework->PlayMusic(MUS("music"));
}

//
// Quit
//
void Game::Quit()
{
	framework->HaltMusic();
	ReleaseResMngr();
}

//
// Input
//
void Game::Input()
{
	int i;

	if(framework->KeyIsPressed(SDLK_ESCAPE))
		done = true;

	for(i=0; i<numPlayers; i++)
	{
		if(framework->KeyIsPressed(players[i].keyNums[DIR_LEFT]))
		{
			if(players[i].dir != DIR_RIGHT)
				players[i].dir = DIR_LEFT;
		}

		if(framework->KeyIsPressed(players[i].keyNums[DIR_RIGHT]))
		{
			if(players[i].dir != DIR_LEFT)
				players[i].dir = DIR_RIGHT;
		}

		if(framework->KeyIsPressed(players[i].keyNums[DIR_UP]))
		{
			if(players[i].dir != DIR_DOWN)
				players[i].dir = DIR_UP;
		}

		if(framework->KeyIsPressed(players[i].keyNums[DIR_DOWN]))
		{
			if(players[i].dir != DIR_UP)
				players[i].dir = DIR_DOWN;
		}
	}
}

//
// GAME_OVER
//
#define GAME_OVER(pId) \
{ \
	gameOver = players[pId].dead = true; \
	gOvStart = framework->GetTicks(); \
	framework->PlaySound(SND("gameover")); \
}

//
// GAME_RUNNING
//
#define GAME_RUNNING() \
{ \
	int c; \
	gameOver = false; \
	for(c=0; c<numPlayers; c++) players[c].dead = false; \
	NEW_ROUND(); \
}

//
// Update
//
void Game::Update()
{
	int i;
	TileType tileId, thisTile;

	if(gameOver)
	{
		if(framework->GetTicks() - gOvStart > GAME_OVER_TIME)
			GAME_RUNNING();
		return;
	}

	if(framework->GetTicks() - lUpdate > UPDATE_TIME)
	{
		for(i=0; i<numPlayers; i++)
		{
			switch(i)
			{
			case 0:
				tileId = TILE_P1;
				break;
			case 1:
				tileId = TILE_P2;
				break;
			case 2:
				tileId = TILE_P3;
				break;
			case 3:
				tileId = TILE_P4;
				break;
			}

			if(	players[i].head.x < 0 || players[i].head.x >= MAP_W
				|| players[i].head.y < 0 || players[i].head.y >= MAP_H)
			{
				GAME_OVER(i);
				return;
			}

			if((thisTile = map[players[i].head.y][players[i].head.x]) != TILE_EMPTY)
			{
				if(thisTile == tileId)
					players[i].score -= SCORE_ADD;
				else
				{
					switch(thisTile)
					{
					case TILE_P1:
						players[0].score += SCORE_ADD;
						break;
					case TILE_P2:
						players[1].score += SCORE_ADD;
						break;
					case TILE_P3:
						players[2].score += SCORE_ADD;
						break;
					case TILE_P4:
						players[3].score += SCORE_ADD;
						break;
					}
				}

				GAME_OVER(i);
				return;
			}

			map[players[i].head.y][players[i].head.x] = tileId;

			switch(players[i].dir)
			{
			case DIR_LEFT:				
				players[i].head.x--;				
				break;
			case DIR_RIGHT:
				players[i].head.x++;
				break;
			case DIR_UP:
				players[i].head.y--;
				break;
			case DIR_DOWN:
				players[i].head.y++;
				break;
			}
		}

		framework->PlaySound(SND("mov"));
		lUpdate = framework->GetTicks();
	}
}

//
// Draw
//
void Game::Draw()
{
	int i, j;

	framework->Draw(IMG("background"));

	framework->LockScreen();

	for(i=0; i<MAP_H; i++)
	{
		for(j=0; j<MAP_W; j++)
		{
			if(map[i][j] != TILE_EMPTY)
			{
				switch(map[i][j])
				{
				case TILE_P1:
					DrawTile(j * TILE_W + 10, i * TILE_H + 10, players[0].color);
					break;
				case TILE_P2:
					DrawTile(j * TILE_W + 10, i * TILE_H + 10, players[1].color);
					break;
				case TILE_P3:
					DrawTile(j * TILE_W + 10, i * TILE_H + 10, players[2].color);
					break;
				case TILE_P4:
					DrawTile(j * TILE_W + 10, i * TILE_H + 10, players[3].color);
					break;
				}
			}
		}
	}

	framework->UnlockScreen();

	for(i=0; i<numPlayers; i++)
	{
		char msg[MAX_STR_LENGTH];
		sprintf_s(msg, "Player %d Score: %d", i + 1, players[i].score);
		framework->DrawText(msg, 400, i * 20 + 10, FONT("font"), Color::white, true);
	}

	if(gameOver)
	{
		for(i=0; i<numPlayers; i++)
		{
			if(players[i].dead)
			{
				char msg[MAX_STR_LENGTH];
				sprintf_s(msg, "Player %d has lost this round!", i + 1);
				framework->DrawText(msg, 10, 10, FONT("font"), Color::white, true);
			}
		}
	}
}

//
// DrawTile
//
void Game::DrawTile(int x, int y, SDL_Color color)
{
	int i, j;
	Uint32 thisColor = framework->SDLColToUint32Col(color);

	for(i=0; i<TILE_H; i++)
		for(j=0; j<TILE_W; j++)
			framework->SetPixelColor(x + j, y + i, thisColor);
}
