#include "globals.h"
#include "gameutils.h"
#include "deepblue.h"


#define	maxcoups  haut * larg
typedef  Coords CoordIndex[maxcoups+1]; /* portage : 1 de trop pour ne pas avoir a reajuster */
typedef short ScoreIndex[maxcoups+1]; /* idem */

short prof;

Grille	valeur;
short	depth;

/*attribue les coefficients de chaque case */
void CalculeValeur()  
{
	short i, j;

	for (i = 1 ; i <= larg ; i++)
		for (j = 1 ; j <= haut ; j++)
			valeur[i][j] = 3;
			
	valeur[1][1] = 20;
	valeur[larg][1] = 20;
	valeur[larg][haut] = 20;
	valeur[1][haut] = 20;
	for (i = 3 ; i<= larg - 2 ; i++)
		valeur[i][1] = 7;
	for (i = 3 ; i<= larg - 2 ; i++)
		valeur[i][haut] = 7;
	for (j = 3 ; j<= haut - 2 ; j++)
		valeur[1][j] = 7;
	for (j = 3 ; j<= haut - 2 ; j++)
		valeur[larg][j] = 7;
	valeur[2][2] = 0;
	valeur[2][haut - 1] = 0;
	valeur[larg - 1][2] = 0;
	valeur[larg - 1][haut - 1] = 0;
	valeur[3][3] = 8;
	valeur[3][haut - 2] = 8;
	valeur[larg - 2][3] = 8;
	valeur[larg - 2][haut - 2] = 8;
	valeur[larg / 2][haut / 2 - 1] = 5;
	valeur[larg / 2 + 1][haut / 2 - 1] = 5;
	valeur[larg / 2 - 1][haut / 2] = 5;
	valeur[larg / 2 - 1][haut / 2 + 1] = 5;
	valeur[larg / 2 + 2][haut / 2] = 5;
	valeur[larg / 2 + 2][haut / 2 + 1] = 5;
	valeur[larg / 2][haut / 2 + 2] = 5;
	valeur[larg / 2 + 1][haut / 2 + 2] = 5;
/* toutes les cases du tableau prennent une valeur, independamment de la taille du tableau */
/* neanmoins, ces coefficients sont appropries a un tableau de 8x8 (taille standard) */
}


short coupsJouables (short couleur, CoordIndex *positions) /* retourne le nb de coups jouables */
{
	Coords test;
	short coupsj, i, j;
	
	coupsj = 0;
	for (j = 1 ; j <= haut ; j++)
		for (i = 1 ; i <= larg ;i++) {
			test.h = i;
			test.v = j;
			if (canPlay(test, couleur)) {
				coupsj++;
				(*positions)[coupsj] = test; /* on remplit egalement la liste des coups jouables */
			}
		}
	return coupsj;
}


short heuristique (short gentil)  /* evalue l'etat du tableau */
{
	short i, j;
	short score;

	score = 0;
	for (j = 1 ; j <= haut ; j++)
		for (i = 1 ; i <= larg ;i++)
			if (tableau[i][j] == gentil)
				score += valeur[i][j];
			else
				score -= valeur[i][j];
	return score;
}

/* cette fonction determine la valeur et la case a remonter dans l'arborescence */
short determine (short couleur, ScoreIndex index, short quantite, short *bonindex)
{
	short i, result;
	
	if (couleur == coulact)
		result = -32000;
	else
		result = 32000;
		
	for (i = 1 ; i <= quantite ; i++) {
		if (((couleur == coulact) && (index[i] > result)) || ((couleur == -coulact) && (index[i] < result))) {
			result = index[i];
			*bonindex = i;
		}
	}
	return result;
}

short MinMax (short couleur, Coords *bonnecase)  /* fonction recursive d'exploration de l'arbre */
{
	Grille backup;
	short nb, i;
	CoordIndex liste;
	ScoreIndex coups;
	short result=0;

	if (prof == depth)              /* si on a atteint la profondeur souhaitˇe, on evalue l'etat du tableau */
		result = heuristique (coulact);
	else {
		nb = coupsJouables (couleur, &liste);
		if (nb > 0)                /* Si on peut jouer, on joue tous les coups possibles */
			for (i = 1 ; i <= nb; i++) {
				copieTableau(&tableau, &backup);
				Joue(liste[i], couleur);
				prof++;
				coups[i] = MinMax(-couleur, bonnecase);
				copieTableau(&backup, &tableau);
				prof--;
			} else {                               /* si il n'y a pas de coup possible, on passe au tour suivant */
				prof++;
				coups[1] = MinMax(-couleur, bonnecase);
				nb = 1;
				prof--;
			}
			result = determine(couleur, coups, nb, &i);   /* La valeur a remonter est donnee par Determine */
			*bonnecase = liste[i];               /* On recupere les coordonnees correspondant a la valeur remontee */
	}
	return result;
}

void IA (Coords * result)  /* procedure principale de l'intelligence artificielle */
{
	prof = 0;
	CalculeValeur();  /* Attribue les coefficients utilises pour calculer l'heuristique */
	MinMax(coulact, result); /* appel de MinMax (la valeur de retour est ignoree) */
}
