/*
 *	MacMinado
 *
 *	Created by Victor on 12/25/09.
 *	Copyright (c) 2009 Particular. All rights reserved.
 */

#define	UM		1
#define DOIS	2
#define	TRES	3
#define	QUATRO	4
#define CINCO	5
#define	SEIS	6
#define	SETE	7
#define OITO	8
#define	NOVE	9
#define	MINA	100
#define	VAZIO	0
#define	QUAD	30
#define SUSP	1000
#define INTE	2000

#define	FUNDO	"background.jpg"
#define JUM		"1.jpg"
#define JDOIS	"2.jpg"
#define JTRES	"3.jpg"
#define JQUATRO	"4.jpg"
#define JCINCO	"5.jpg"
#define JSEIS	"6.jpg"
#define JSETE	"7.jpg"
#define JOITO	"8.jpg"
#define JMINA	"mina.jpg"
#define JVAZIO	"vazio.jpg"
#define JSUSP	"suspeito.jpg"
#define JQUAD	"quadrado.jpg"
#define JINT	"int.jpg"

#define	H		600
#define	W		400
#define	OFFSET	20
#define SIZE	36
#define T_H		12
#define T_W		10
//#define	QMINAS	22

#include <time.h>
#include <allegro.h>
#include <jpgalleg.h>

int QMINAS = 10;

void init_all();

void preenche_tela( int **matriz, int **tela );

void preenche_matrizes( int **tela, int **matriz );

void procura_vazios( int x, int y, int **matriz, int **tela );

//0 - nao, 1 - sim
int fim_de_jogo( int **tela );

//Retorna 100 se acertou uma mina, 1 se foi jogada v‡lida, 0 se acabou o jogo
int executa_jogada( int x, int y, int **tela, int **matriz );

int som, svalido;

BITMAP *um, *dois, *tres, *quatro, *cinco, *seis, *sete, *oito, *mina, *quadrado, *vazio, *fundo, *suspeito, *buffer, *inte;
SAMPLE *clique, *ganhou, *explosao;

int main(int argc, const char *argv[])
{
	
	init_all();	
	
	//allegro_message("ESC -> Quit Game\nS -> Enable/Disable sound\nR.M.B./SPACE -> Mark/Unmark mine\nL.M.B. -> Open circle\n\n\n-- by OldSorcerer [old.sorcerer@gmail.com]");
	allegro_message("ESC -> Sair\nS -> Liga/Desliga o som\nR.M.B./Espaco -> Marca/Desmarca mina\nL.M.B. -> Abre casa\n\n\n-- por OldSorcerer [old.sorcerer@gmail.com]");
		
	time_t inicio, final;
	
	int minuto = 0, segundo = 0;
	
	int i;
	
	int fim = 900;
	
	int mx, my;
	
	int **tela = (int**) malloc( sizeof(int*) * T_H );
	
	for (i = 0; i < T_H; i++)
		tela[i] = (int*) malloc( sizeof(int) * T_W );
	
	int **matriz = (int**) malloc( sizeof(int*) * T_H );
	
	for (i = 0; i < T_H; i++)
		matriz[i] = (int*) malloc( sizeof(int) * T_W );
	
	preenche_matrizes( tela, matriz );
	
	preenche_tela( matriz, tela );
		
	inicio = time( 0 );
	
	while ( !key[KEY_ESC] )
	{
		
		if( key[KEY_S] )
		{
			
			rest( 300 );
			
			if( som == 1 )
			{
				som = 0;
				allegro_message("Som foi desligado!");
				//allegro_message("Sound enabled!");
			}
			else
			{
				som = 1;
				allegro_message("Som foi ligado!");
				//allegro_message("Sound disabled!");
			}
			
		}
		
		if( mouse_b & 1 )
		{
			
			//allegro_message("Botao Esquerdo");
			
			mx = mouse_x;
			my = mouse_y;
			
			if( mx > OFFSET && mx < (W - OFFSET) && my > (H - OFFSET - T_H * SIZE) && my < H - OFFSET)
			{
				if( matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] >= 1000 )
				{
					if( matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] >= 2000 )
						matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] -= 2000;
					else
						matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] -= 1000;
				}
				
				if( som )
				{
					if( tela[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] == 100 )
						play_sample(clique, 70, 127, 1000, 0);
				}
				
				fim = executa_jogada( (mx - OFFSET) / SIZE, (my - (H - OFFSET - T_H * SIZE)) / SIZE, tela, matriz );
				
				if( som )
				{
					if( fim == 100 )
						play_sample(explosao, 50, 127, 1000, 0);
				}
				
				preenche_tela(matriz, tela);
			
				rest( 200 );
			}
		}
		
		if( mouse_b & 2 || key[KEY_SPACE] )
		{
			
			//allegro_message("Botao Direito");
			
			mx = mouse_x;
			my = mouse_y;
			
			if( mx > OFFSET && mx < (W - OFFSET) && my > (H - OFFSET - T_H * SIZE) && my < H - OFFSET)
			{
				
				if( tela[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] == 100 )
				{
				
					if( matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] < 1000 )
						matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] += 1000;
					else if( matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] < 2000 )
						matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] += 1000;
					else
						matriz[(my - (H - OFFSET - T_H * SIZE)) / SIZE][(mx - OFFSET) / SIZE] -= 2000;
				
					preenche_tela(matriz, tela);
				
					rest( 200 );
				}
				
			}
			
		}
		
		switch (fim) {
			case 100:				
				allegro_message("Voce perdeu!");
				//allegro_message("You Lose!");
				fim = 1;
				preenche_matrizes(tela, matriz);
				preenche_tela(matriz, tela);
				inicio = time( 0 );
				break;
			case 0:
				final = time( 0 );
				minuto = (int) difftime(final, inicio) / 60;
				segundo = (int) difftime(final, inicio) % 60;
				
				if( som )
					play_sample(ganhou, 80, 127, 1000, 0);
				
				allegro_message("Voce ganhou!\nTempo: %i%i:%i%i\n\nProximo nivel: %i minas", minuto / 10, minuto % 10, segundo / 10, segundo % 10, QMINAS+2);
				//allegro_message("You Win!\nTime: %i%i:%i%i\n\nNext level: %i mines", minuto / 10, minuto % 10, segundo / 10, segundo % 10, QMINAS+2);
				QMINAS += 2;
				fim = 1;
				preenche_matrizes(tela, matriz);
				preenche_tela(matriz, tela);
				inicio = time( 0 );
				break;
			default:
				break;
		}
		
	}
	
	return 0;
}
END_OF_MAIN();

void init_all()
{

	allegro_init();
	jpgalleg_init();
	
	install_keyboard();
	install_mouse();
	
	set_color_depth(32);
	
	if (set_gfx_mode(GFX_QUARTZ_WINDOW, W, H, 0, 0)) {
		//allegro_message("Error trying to set a %dx%dx32 screen:\n%s\n", H, W, allegro_error);
		allegro_message("Erro criando uma janela %dx%dx32:\n%s\n", H, W, allegro_error);
	}
	
	if( !install_sound( DIGI_AUTODETECT, MIDI_AUTODETECT, NULL ) )
	{
		som = 1;
	    svalido = 1;
	}
	else
	{
		//allegro_message("Error trying to set sounds! Game will be muted!\n%s", allegro_error);
		allegro_message("Erro habilitando placa de som! O jogo n‹o ter‡ sons!\n%s", allegro_error);
		som = 0;
		svalido = 0;
	}
	
	buffer = create_bitmap(W, H);
	um = load_jpg( JUM, NULL );
	dois = load_jpg( JDOIS, NULL );
	tres = load_jpg( JTRES, NULL );
	quatro = load_jpg( JQUATRO, NULL );
	cinco = load_jpg( JCINCO, NULL );
	seis = load_jpg( JSEIS, NULL );
	sete = load_jpg( JSETE, NULL );
	oito = load_jpg( JOITO, NULL );
	mina = load_jpg( JMINA, NULL );
	suspeito = load_jpg( JSUSP, NULL );
	vazio = load_jpg( JVAZIO, NULL );
	quadrado = load_jpg( JQUAD, NULL );
	fundo = load_jpg( FUNDO, NULL );
	inte = load_jpg( JINT, NULL );
	
	if(svalido)
	{
		explosao = load_sample( "explosao.wav" );
		clique = load_sample( "clique.wav" );
		ganhou = load_sample( "ganhou.wav" );
	}
	
}	

void preenche_tela( int **matriz, int **tela )
{
	
	int x = OFFSET, y = H - OFFSET - SIZE * T_H;
	int a = 0, b = 0;
	int resultado;
	
	BITMAP *tile;
	
	show_mouse( NULL );
	
	clear_to_color(buffer, 0);
	
	draw_sprite( buffer, fundo, 0, 0 );
	
	for(a = 0; a < T_H; a++)
	{
		for(b = 0; b < T_W; b++)
		{
			
			resultado = matriz[a][b] + tela[a][b];
			
			if(resultado > SUSP )
			{
				if( resultado < INTE )
					resultado = SUSP;
				else
					resultado = INTE;
			}
			
			switch (resultado) {
				case UM:
					tile = um;
					break;
				case DOIS:
					tile = dois;
					break;
				case TRES:
					tile = tres;
					break;
				case QUATRO:
					tile = quatro;
					break;
				case CINCO:
					tile = cinco;
					break;
				case SEIS:
					tile = seis;
					break;
				case SETE:
					tile = sete;
					break;
				case OITO:
					tile = oito;
					break;
				case VAZIO:
					tile = vazio;
					break;
				case MINA:
					tile = mina;
					break;
				case SUSP:
					tile = suspeito;
					break;
				case INTE:
					tile = inte;
					break;
				default:
					tile = quadrado;
					break;
			}
			
			draw_sprite(buffer, tile, x, y);
			
			x += SIZE;
			
		}
		
		x = OFFSET;
		y += SIZE;
		
	}
	
	draw_sprite( screen, buffer, 0, 0 );
	
	rest(10);
	
	show_mouse(screen);
			
}

void preenche_matrizes( int **tela, int **matriz )
{
	
	int a, b, c;
	
	for (a = 0; a < T_H; a++) 
	{
		for (b = 0; b < T_W; b++) 
		{
		
			tela[a][b] = 100;
			matriz[a][b] = VAZIO;
			
		}
	}
	
	srand(time(NULL));
	
	for( a = 0; a < QMINAS; a++ )
	{
		
		b = rand() % T_H;
		c = rand() % T_W;
		
		while ( matriz[b][c] != VAZIO )
		{
			
			b = rand() % T_H;
			c = rand() % T_W;
			
		}
		
		matriz[b][c] = MINA;
		
	}
	
	
	for( a = 0; a < T_H; a++ )
	{
		for( b = 0; b < T_W; b++ )
		{
			
			if( matriz[a][b] >= MINA )
			{

				if( (a - 1) >= 0 && (b - 1) >= 0 )
					matriz[a-1][b-1] += 1;
				
			
				if( (a - 1) >= 0 )
					matriz[a-1][b] += 1;
				

				if( (a - 1) >= 0 && (b + 1) < T_W )
					matriz[a-1][b+1] += 1;


				if( (b - 1) >= 0 )
					matriz[a][b-1] += 1;
				
				
				if( (b + 1) < T_W )
					matriz[a][b+1] += 1;
				

				if( (a + 1) < T_H && (b - 1) >= 0 )
					matriz[a+1][b-1] += 1;
				

				if( (a + 1) < T_H )
					matriz[a+1][b] += 1;
				

				if( (a + 1) < T_H && (b + 1) < T_W )
					matriz[a+1][b+1] += 1;
				
			}
		}
	}
	
	
	for( a = 0; a < T_H; a++ )
	{
		for( b = 0; b < T_W; b++ )
		{
			if( matriz[a][b] > MINA )
				matriz[a][b] = MINA;
			
			if( matriz[a][b] == VAZIO )
				matriz[a][b] = QUAD;
		}
	}
	
}

int executa_jogada(int x, int y, int **tela, int **matriz)
{
	int a, b;
	
	if (matriz[y][x] == MINA)
	{
		for( a = 0; a < T_H; a++ )
		{
			for( b = 0; b < T_W; b++ )
			{
				if(matriz[a][b] == MINA || matriz[a][b] == MINA + 1000)
				{
					matriz[a][b] = MINA;
					tela[a][b] = 0;
				}
			}
		}
		
		preenche_tela(matriz, tela);
		return 100;
	}
	
	if(matriz[y][x] != QUAD)
	{
		tela[y][x] = 0;
		
	}
	else
	{
		matriz[y][x] = VAZIO;
		procura_vazios(x, y, matriz, tela);
	}
	
	preenche_tela(matriz, tela);
	
	if( fim_de_jogo( tela ) )
		return 0;
	else
		return 1;
	
}

void procura_vazios(int x, int y, int **matriz, int **tela)
{
	int *p;
	
	tela[y][x] = 0;
	
	if( matriz[y][x] >= 1000 )
	{
		if( matriz[y][x] >= 2000 )
			matriz[y][x] -= 2000;
		else
			matriz[y][x] -= 1000;
	}
	
	if( x - 1 >= 0 && y - 1 >= 0 )
	{
		p = &(matriz[y-1][x-1]);
		
		if( tela[y-1][x-1] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y-1][x-1] = VAZIO;
			procura_vazios( x-1, y-1, matriz, tela );
		}
		else
		{
			tela[y-1][x-1] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
	if( x - 1 >= 0 && y >= 0 )
	{
		p = &(matriz[y][x-1]);
		if( tela[y][x-1] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y][x-1] = VAZIO;
			procura_vazios( x-1, y, matriz, tela );
		}
		else
		{
			tela[y][x-1] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
	if( x - 1 >= 0 && y + 1 < T_H )
	{
		p = &(matriz[y+1][x-1]);
		if( tela[y+1][x-1] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y+1][x-1] = VAZIO;
			procura_vazios( x-1, y+1, matriz, tela );
		}
		else
		{
			tela[y+1][x-1] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
	if( x >= 0 && y - 1 >= 0 )
	{
		p = &(matriz[y-1][x]);
		if( tela[y-1][x] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y-1][x] = VAZIO;
			procura_vazios( x, y-1, matriz, tela );
		}
		else
		{
			tela[y-1][x] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
	if( x >= 0 && y + 1 < T_H )
	{
		p = &(matriz[y+1][x]);
		if( tela[y+1][x] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y+1][x] = VAZIO;
			procura_vazios( x, y+1, matriz, tela );
		}
		else
		{
			tela[y+1][x] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
	if( x + 1 < T_W && y + 1 < T_H )
	{
		p = &(matriz[y+1][x+1]);
		if( tela[y+1][x+1] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y+1][x+1] = VAZIO;
			procura_vazios( x+1, y+1, matriz, tela );
		}
		else
		{
			tela[y+1][x+1] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
	if( x + 1 < T_W && y >= 0 )
	{
		p = &(matriz[y][x+1]);
		if( tela[y][x+1] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y][x+1] = VAZIO;
			procura_vazios( x+1, y, matriz, tela );
		}
		else
		{
			tela[y][x+1] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
	if( x + 1 < T_W && y - 1 >= 0 )
	{
		p = &(matriz[y-1][x+1]);
		if( tela[y-1][x+1] != 0 && ( *p == QUAD || *p == QUAD+1000 || *p == QUAD+2000) )
		{
			matriz[y-1][x+1] = VAZIO;
			procura_vazios( x+1, y-1, matriz, tela );
		}
		else
		{
			tela[y-1][x+1] = 0;
			if( *p >= 1000 )
			{
				if( *p >= 2000 )
					*p -= 2000;
				else
					*p -= 1000;
			}
		}
	}
	
}

int fim_de_jogo(int **tela)
{
	int a, b, count = 0;
	
	for( a = 0; a < T_H; a++ )
	{
		for( b = 0; b < T_W; b++ )
		{
			if( tela[a][b] == 100 )
				count++;
		}
	}
	
	if( count == QMINAS )
		return 1;
	else
		return 0;
}





