/*
Xothello
Auteur :
	Delphine Graeff
	Lopez Edouard
codez sous :
	linux-gentoo-2.6.21
	gcc-4.1.2
compilez avec :
	g++ -Wall ./othello.cpp -o ./xothello

//.c_str() le type 'string' n'est pas connu par printf -> converison en char *.

*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <math.h>
#include <cstdarg>

// CONSTANTES TEXTUELLES
// inclus nos variables textuelles
#include "friendly_user.hpp"

// CONSTANTES NON-TEXTUELLES
#define	FZ					8
#define	NB_CASES			(FZ*FZ-1)
#define	VIDE				-1
#define	BLANC				0
#define	NOIR				1

// CONSTANTES POUR LA PONDÉRATION DES CASES
#define	COIN_FULL			500
#define BORD_IN				0
#define	COIN_OUT			-150
#define	COIN_IN				-250
#define	NOWHERE				30
#define	CENTRE				16
#define	CENT_COIN			10
#define	CENT_BORD			2
#define	OUVERTURE			1

#define	PION_JOUEUR			players[joueur_actif].piece
#define	PION_ADVERSE		players[joueur_actif+1].piece

using namespace std;

// ============================================= VARIABLES =============================================
	int joueur_actif = NOIR, // joueur commencant
		tour, // numéro du tour.
		debug_depth = 3; // profondeur de débuggage
	bool debug = false, // mode débuggage actif ?
		 clear = false; // mode propre
	time_t start = time(&start), cur; // temps en début et fin de partie.

	// initialisation du plateau
	int plateau[FZ][FZ];
	// initialisation du plateau
	int plateau_pondere[FZ][FZ] = {	{COIN_FULL,	COIN_OUT,	NOWHERE,	CENT_COIN,	CENT_COIN,	NOWHERE,	COIN_OUT,	COIN_FULL},
									{COIN_OUT,	COIN_IN,	BORD_IN,	BORD_IN,	BORD_IN,	BORD_IN,	COIN_IN,	COIN_OUT},
									{NOWHERE,	BORD_IN,	CENT_COIN,	CENT_BORD,	CENT_BORD,	CENT_COIN,	BORD_IN,	NOWHERE},
									{CENT_COIN,	BORD_IN,	CENT_BORD,	CENTRE,		CENTRE,		CENT_BORD,	BORD_IN,	CENT_COIN},
									{CENT_COIN,	BORD_IN,	CENT_BORD,	CENTRE,		CENTRE,		CENT_BORD,	BORD_IN,	CENT_COIN},
									{NOWHERE,	BORD_IN,	CENT_COIN,	CENT_BORD,	CENT_BORD,	CENT_COIN,	BORD_IN,	NOWHERE},
									{COIN_OUT,	COIN_IN,	BORD_IN,	BORD_IN,	BORD_IN,	BORD_IN,	COIN_IN,	COIN_OUT},
									{COIN_FULL,	COIN_OUT,	NOWHERE,	CENT_COIN,	CENT_COIN,	NOWHERE,	COIN_OUT,	COIN_FULL}
								};

	// structure contenant les informations liées a un joueur.
	struct player {
		string nom;
		char piece, // caractère symbolisant le pion
			*couleur; // couleur du joueur
		bool verbeux; // intéraction avec le joueur
		int coup, // nombre de coup joués
			ia, // définie l'IA du joueur. 0 = humain, 1 = IA aléatoire
			coups_ligne[(NB_CASES+1/2)-1], // liste des coups possibles pour un joueur
			coups_colonne[(NB_CASES+1/2)-1], // moins de 32
			nb_coups; // nombre de coups possibles
	} p1, p2 ; // tableau des joueurs.

	player players[2] = {p1, p2}; // p1 = blanc; p2 = noir.




// ============================================= FONCTIONS =============================================
// place les pions en début de partie
void create_plateau() {
	for (int i = 0; i<FZ; i++) {
		for (int j = 0; j<FZ; j++){
			plateau[i][j] = VIDE;
		}
	}
	plateau[3][3] = BLANC;	plateau[3][4] = NOIR;
	plateau[4][3] = NOIR;		plateau[4][4] = BLANC;
}

// place les pions en début de partie
void create_plateau_fin_partie() {
	for (int i = 0; i<FZ; i++) {
		for (int j = 0; j<FZ; j++){
			plateau[i][j] = NOIR;
		}
	}
	plateau[0][0] = VIDE;
	plateau[0][7] = BLANC;
	plateau[7][0] = BLANC;
	plateau[7][7] = BLANC;
}


void clear_screen(){
	if (clear){
		printf("\033[2J");
	}
}

// transforme la position numérique en position alphabétique
char lettre(int i) {
	return (char) i+64;
}

// affichage en fonction des parametre passez au programme
void debug_printf(int debug_level, char *message, ...) {
	va_list pointeur_parametres; // [type pointeur] désignant les différents paramètres
	char buffer[1024];

	if (debug && debug_level <= debug_depth) { // nécessite l'execution avec -d
		va_start(pointeur_parametres, message); // fait pointer pointeur_parametres vers le 1er paramètre facultatif
			vsprintf(buffer, message, pointeur_parametres); // concatène message dans buffer et passe à l'élément suivant de la liste de paramètres
		va_end(pointeur_parametres); // fin de l'utilisation de la liste de paramètres
		fprintf(stdout, "%s", buffer); // on affiche le contenu de notre buffer sur la sortie standard
	}
}

// affichage d'INFORMATIONS
void verbose_printf_info(char *message, ...) {
	va_list pointeur_parametres; // [type pointeur] désignant les différents paramètres
	char buffer[1024];

	if (players[joueur_actif].verbeux) { // différencie joueur humain de l'IA
		va_start(pointeur_parametres, message); // fait pointer pointeur_parametres vers le 1er paramètre facultatif
			vsprintf(buffer, message, pointeur_parametres); // concatène message dans buffer et passe à l'élément suivant de la liste de paramètres
		va_end(pointeur_parametres); // fin de l'utilisation de la liste de paramètres
		fprintf(stdout, "%s", buffer); // on affiche le contenu de notre buffer sur la sortie standard
	}
}


// compte les pions du joueur.
int compte(int pion_joueur) {
	int i, j, pion_total = 0;
	for (i=0; i<FZ; i++) {
		for (j=0; j<FZ; j++) {
			if (plateau[i][j]==pion_joueur) {
				pion_total++;
			}
		}
	}
	return pion_total; // nombre de pions du joueur actif
}

//
void duree_partie() {
	time (&cur); // heure courante.
	double	dif = difftime (cur,start); // calcul la != en seconde.
	int
		secondes = (int) dif%60,
		minutes = ((int) dif/60)%60,
		heures = ((int) dif)/3600;

	printf("Durée de la partie: %2hi heures %2hi minutes %2hi secondes.\n\n", heures, minutes, secondes);

}

// fin de partie on détermine le vainqueur.
void vainqueur(void) {
	int total_blanc = compte(BLANC),
		total_noir = compte(NOIR);

	clear_screen();

	verbose_printf_info("\n" L_EQUAL L_EQUAL "\n" L_EQUAL L_EQUAL "\n");
	duree_partie();
	verbose_printf_info(I_TOT_BLANC
						I_TOT_NOIR
						"\t" L_MINUS "\n",
						players[BLANC].nom.c_str(),	total_blanc, players[NOIR].nom.c_str(), total_noir);

 // déclare le vainqueur.
	if (total_blanc > total_noir)
		printf(I_WINNER, players[BLANC].nom.c_str());
	else if (total_blanc < total_noir)
		printf(I_WINNER, players[NOIR].nom.c_str());
	else
		printf(I_EGALITE);

}

//
void quit() {
	char confimation;
	bool quit = false;

	do {
		printf(Q_CONFIRMATION_FIN);
		cin >> confimation;
		switch (confimation) {
			case 'o':
			case 'O':
			case 'y':
			case 'Y':
				quit = true;
				clear_screen();
				vainqueur();
				printf(I_BYE);
				exit(1);
			break;
			case 'n':
			case 'N':
				return;
			break;
			default:
				printf(E_VALEUR);
			break;
		}
	} while (!quit);
}

// change le joueur actif
int change_joueur() {
	return joueur_actif = (joueur_actif+1)%2;
}

// change de ligne régulièrement (voir paramètres)
void retour_chariot_regulier(int tour, string tab = "", int tous_les_x_tours = 4) {
	if (tour%tous_les_x_tours==0)
		printf("\n%s", tab.c_str());
}

// retourne les pions adverses placés sur cet axe
void retournement_axe(int tete_ligne, int tete_colonne, int ligne, int colonne, int distance) {
int retourne_i, retourne_j, // coordonnées du pion retourné
	axe_i = (tete_ligne-ligne)/distance, // coordonnées relative
	axe_j = (tete_colonne-colonne)/distance;

	do {
		retourne_i = ligne + axe_i*distance;
		retourne_j = colonne + axe_j*distance;

		debug_printf(2, I_DEBUG_COUP, axe_i+1, lettre(axe_j+1), distance, retourne_i+1, lettre(retourne_j+1), ligne, lettre(colonne+1));

		verbose_printf_info(I_RETOURNEMENT, retourne_i+1, lettre(retourne_j+1));
		plateau[retourne_i][retourne_j] = joueur_actif; // retourne le pion de la vase <=> met un pion du joueur.
		retour_chariot_regulier(distance--, "\t\t\t\t\t  ");
	} while (distance>0);

	players[joueur_actif].coup++;
}


/*
on va parcourir les 8 axes (partant de la position du pions que l'on veut placer) à la recherche de séquence(s) de pions valide(s) pour un retournement
à savoir: 			{  [NOTRE PION] [PIONS ADVERSES]+ [PION À NOUS]  }
code correspondant:						[OUVERTURE]+	[FERMETURE]
on marque chaque axes en fonctions du type de séquence que l'on trouve:
VIDE = pas de séquence ou alors invalide;
OUVERTURE = séquence incomplète donc non valide;
FERMETURE = on a une une séquence complète donc valide.
*/
bool case_jouable_jouee(int ligne, int colonne, bool retourne = false) {
	int rel_ligne, rel_colonne; // relativement à la case courante.
	int tete_ligne, tete_colonne; // partie mobile du testeur.
	int distance; // distance de la tête de testeur par rapport à la case proposer.
	bool val = false; // valeur de retour <=> on peut jouer le coup ou non. On suppose qu'il n'y a pas de coup possible.
	int adversaire = (joueur_actif+1)%2; // changement de couleur temporaire pour les retournement.

	// case vide obligatoire
	if (plateau[ligne][colonne] == VIDE) {
		for (rel_ligne=-1; rel_ligne<2; rel_ligne++) { // on va parcoucrir les différents axes.
			for (rel_colonne=-1; rel_colonne<2; rel_colonne++) {
				distance = 1; // distance entre la case tester et la case que l'on cherche à valider.
				tete_ligne = ligne + distance*rel_ligne; // coordonnées de la case tester relativement à la case que l'on veut valider.
				tete_colonne = colonne + distance*rel_colonne;

				int axe = VIDE; // axe/direction courante
 // tant que le testeur reste sur le plateau.
				while (tete_ligne >= 0  &&  tete_colonne>=0  && tete_ligne <= FZ  && tete_colonne <= FZ) {
					tete_ligne = ligne + distance*rel_ligne; // coordonnées de la « tete du testeur » relative à la position du pion.
					tete_colonne = colonne + distance*rel_colonne; // renouveller a chaque nouveau cycle

 // Le testeur doit être sur une case différente de celle du pion que l'on propose/essai.
					if ( !(tete_ligne == ligne  &&  tete_colonne == colonne) ) {
 // le pion EST à l'adversaire && on est sur la case attenante à la position tester: on en prend note.
						if (plateau[tete_ligne][tete_colonne] == adversaire  &&  (axe == VIDE  ||  axe == OUVERTURE)) {
							if (axe==VIDE) {
								debug_printf(4, I_OUVERTURE, tete_ligne+1, lettre(tete_colonne)+1);
							}
							else {
								debug_printf(4, I_POURSUITE, tete_ligne+1, lettre(tete_colonne)+1);
							}
							axe = OUVERTURE; // début de séquence valide
						}
 // le pion EST au joueur actif, il faut que le précédent ne nous appartienne pas: on en prend note.
						else if (plateau[tete_ligne][tete_colonne] == joueur_actif  &&  axe == OUVERTURE) {
							debug_printf(4, I_FERMERTURE, tete_ligne+1, lettre(tete_colonne)+1);
							if (retourne) {
								plateau[ligne][colonne] = joueur_actif; // on met le pion du joueur.
								retournement_axe(tete_ligne, tete_colonne, ligne, colonne, distance);
							}
							val = true; // fin de séquence valide => valeur de retour a true
							break;
						}
						else { // on quitte l'axe
							debug_printf(4, I_FIN_RECHERCHE, rel_ligne, rel_colonne, tete_ligne+1, lettre(tete_colonne+1));
							break;
						}
					}
					else {
						debug_printf(4, I_CASE_PROPOSEE, tete_ligne+1, lettre(tete_colonne+1));
						break;
					}
					distance++;
				}
			}
		}
	}
	else
	debug_printf(5, E_CASE_OCCUPEE, ligne+1, lettre(colonne+1));

	return val;
}

// affiche les coordonnées sur le bord du plateau.
void num(int ligne = FZ, int colonne = 0, string tab = " ") {
	int n;

	if ((ligne==0 || ligne==FZ) && colonne==0) { // première || dernière ligne.
		printf(" ");
		for (n=0; n<FZ; n++){
			printf("%s%c", tab.c_str(), lettre(n+1));
		}
		printf("\n");
	}

	// pour les autres lignes, ont doit juste afficher le numéro de la ligne.
	if (colonne==0 && ligne<FZ) // début de ligne.
		printf("%i", ligne+1);

}

// retourne le pion/caractère associé au joueur.
char pion(int i, int j) {
	switch(plateau[i][j]) { // choix du pion.
		case BLANC: return 'O'; // O = Blanc = 0
		case NOIR: return '#'; // 1 = Noir = #
		default: return '_';
 // default: return '@';
	}

}

// dessine le plateau et les pions.
void trace_plateau(void) {
	int i, j;
	char piece;

	printf("\n");
	for (i=0; i<FZ; i++) {
		for (j=0; j<FZ; j++) {
			num(i, j); // on affiche les coordonnées.
			piece = pion(i, j);
			printf("|%c", piece); // affichage de la case et du pion.
		}
		printf("|%i\n", i+1);
	}
	num();
}

// dessine le plateau et les pions.
void trace_plateau_pondere(void) {
	int i, j;

	printf("\n" I_PONDERATION_PLATEAU);
	for (i=0; i<FZ; i++) {
		for (j=0; j<FZ; j++) {
			num(i, j, "    "); // on affiche les coordonnées.
			printf("|%4hi", plateau_pondere[i][j]); // affichage de la case et du pion.
		}
		printf("|%i\n", i+1); // fin de ligne
	}
	num(FZ, 0, "    ");
}


void affiche_tableau_coups_possibles() {
	verbose_printf_info(I_LISTE_COUPS, players[joueur_actif].nom.c_str(), players[joueur_actif].piece);

	for (int i=0; i<players[joueur_actif].nb_coups;i++) { // on parcours les listes de coordonnées de coups possibles
 // on affiche si elle n'est pas vide
		if (players[joueur_actif].coups_ligne[i] != VIDE  &&  players[joueur_actif].coups_colonne[i] != VIDE) {
			verbose_printf_info(I_COUP, i+1, players[joueur_actif].coups_ligne[i]+1, lettre(players[joueur_actif].coups_colonne[i]+1));
			retour_chariot_regulier(i+1, "\t  ");
		}
	}
	verbose_printf_info("\n");
}

// VIDE le tableau des coups possibles.
void vide_tableau_coups_possibles() {
	int i;
	for (i=0; i<players[joueur_actif].nb_coups;i++) { // on parcours les listes de coordonnées de coups possibles
 // on vide la case = -1
		players[joueur_actif].coups_ligne[i] = VIDE;
		players[joueur_actif].coups_colonne[i] = VIDE;
	}
	players[joueur_actif].nb_coups = 0; // nombre de coup pour le joueur actif et le tour courant
}

// REMPLIT le tableau des coups possibles.
int listing_coups_possibles(/*int joueur_tester*/) {
	int i, j;
	vide_tableau_coups_possibles(); // on réinitialise le tableau.
	// indice utiliser de facon à ce que les coordonnées de coups
	// possibles soient groupés ensembles et pas éparpillés dans le tableau.
	// NE PAS LA METTRE AVANT LE VIDAGE CAR IL UTILISE LA VALEUR DU TOUR PRECEDENT
	players[joueur_actif].nb_coups = 0; // nombre de coup pour le joueur actif et le tour courant
	players[(joueur_actif+1)%2].nb_coups = 0; // nombre de coup pour le joueur actif et le tour courant

	debug_printf(4, I_EXISTE_COUP_JOUEUR, players[joueur_actif].nom.c_str(), players[joueur_actif].piece);
	for (i=0; i<FZ;i++) {
		for (j=0; j<FZ;j++) {
			if (case_jouable_jouee(i, j)) {
				players[joueur_actif].coups_ligne[players[joueur_actif].nb_coups] = i;
				players[joueur_actif].coups_colonne[players[joueur_actif].nb_coups] = j;
				players[joueur_actif].nb_coups++;
			}
		}
	}
	debug_printf(4, "\n Existe %i coup(s) pour %s [%c].\n", players[joueur_actif].nb_coups, players[joueur_actif].nom.c_str(), players[joueur_actif].piece);
	return players[joueur_actif].nb_coups;
}

// vérifie si il existe un coup pour le joueur courant
// si les deux joueur ne peuvent plus jouer -> fin de partie.
bool existe_coups_possibles(void) {
	string too = ""; // message plus conviviale;
	bool possible = false; // on suppose qu'aucun coup n'est possible.

	if (listing_coups_possibles() == 0 ) {
		printf(I_PASSE_LA_MAIN, players[joueur_actif].nom.c_str(), players[joueur_actif].piece, too.c_str());
		change_joueur();
		if (listing_coups_possibles() == 0 ) {
			too = "aussi "; // convivialité du message.
			printf(I_PASSE_LA_MAIN, players[joueur_actif].nom.c_str(), players[joueur_actif].piece, too.c_str());
			trace_plateau();
		} else {
			return true;
		}
	} else {
		return true;
	}
	return possible;
}

// choix du coups par le joueur humain
int humain() {
	int coup;
	bool valide = false;

	do { // tant que le joueur saisi un coup INVALIDE on lui redemande de saisir une valeur.
		printf(Q_COUP);
		cin >> coup;
		if (coup == 0) {
			quit();
		} else if (coup == 99){
			printf(A_AIDE);
		} else if (coup <= players[joueur_actif].nb_coups){
			coup--; // décallage affichage/index.
			valide = true;
		} else {
			printf(E_COUP_INVALIDE, players[joueur_actif].nb_coups);
		}
	} while (!valide); // tant que le joueur saisi un coup INVALIDE on lui redemande de saisir une valeur.

	return coup;
}

// IA aléatoire : choisi son coup parmi se possible en faisant
// un random modulé par le nombre de coups possible
int IA_aleatoire() {
	return rand()%players[joueur_actif].nb_coups;
}

int IA_case_ponderee() {
	struct	case_ {
		int	poid, // pondération de la case.
			position; // position dans le tableau des coups possibles
	} coup_actuel, coup_candidat;

	// valeur par défaut
	coup_actuel.position = 0;
	coup_actuel.poid = plateau_pondere[players[joueur_actif].coups_ligne[	coup_actuel.position ]]
										[players[joueur_actif].coups_colonne[ coup_actuel.position ]];

	printf(I_RECHERCHE_COUP_LOURD "\t\t[@] " );

	for (int i=0; i<players[joueur_actif].nb_coups;i++) { // on parcours la liste des coups disponibles
		coup_candidat.position = i; // case
		coup_candidat.poid = plateau_pondere[players[joueur_actif].coups_ligne[i]]
											[players[joueur_actif].coups_colonne[i]];

		printf(I_COUP_POID,	coup_actuel.position,	players[joueur_actif].coups_ligne[coup_actuel.position]+1, 	lettre(players[joueur_actif].coups_colonne[coup_actuel.position]+1),	coup_actuel.poid,
							coup_candidat.position, players[joueur_actif].coups_ligne[i]+1, 					lettre(players[joueur_actif].coups_colonne[i]+1),						coup_candidat.poid);
		retour_chariot_regulier(i+1, "\t\t    ", 2);

		if (coup_candidat.poid > coup_actuel.poid) {
			coup_actuel.position = coup_candidat.position;
			coup_actuel.poid = coup_candidat.poid;
		}
	}
// 	printf("\n>>>>>>>> case: (%i;%i) actuel: %i;", playe %i: (%i;%i)rs[joueur_actif].coups_ligne[i]+1, lettre(players[joueur_actif].coups_colonne[i]+1), coup);
	printf("\n");
	return coup_actuel.position;
}

// questionne le joueur (humain ou IA).
bool demande_coup(void) {
	int coup, // index du coup dans la liste des coups possibles
		ligne, // coordonnées du coup choisi.
		colonne;

	clear_screen();
	printf(I_TOUR, tour, players[joueur_actif].nom.c_str(), PION_JOUEUR);
	trace_plateau();
	if (debug==1 && players[joueur_actif].ia > 0) { // on affiche que lors du debuggage de l'IA
		trace_plateau_pondere();
	}

	affiche_tableau_coups_possibles(); // affiche la liste des coups possibles

	switch(players[joueur_actif].ia) {
		case 0: // cas de joueur humain
			coup = humain();
		break;
		case 1: // cas d'IA aléatoire
			coup = IA_aleatoire();
		break;
		case 2:
			coup = IA_case_ponderee();
		break;
	}

	ligne = players[joueur_actif].coups_ligne[coup];
	colonne = players[joueur_actif].coups_colonne[coup];

	printf(I_CASE_JOUEE, ligne+1, lettre(colonne+1));
		verbose_printf_info(I_DEBUT_RETOURNEMENT);
		verbose_printf_info(I_LISTE_RETOURNEMENT);

	case_jouable_jouee(ligne, colonne, true); // retourne les pions de l'axe.
	verbose_printf_info("\n");

	joueur_actif = change_joueur(); // changement de joueur.
	tour++; // incrémente le numéro du tour.

	return true;
}

// configuration des paramètres de chaque joueurs
void config_joueur(void) {
	verbose_printf_info(I_CONFIG_JOUEURS);

	players[BLANC].piece = 'O';
	players[BLANC].couleur = "Blanc";
	players[NOIR].piece = '#';
	players[NOIR].couleur = "Noir";

	for (int i = 0; i<2; i++) {
		switch(players[i].ia) {
			case 0: // ce n'est pas une IA
				printf(Q_NOM, players[i].couleur, players[i].piece, i);
				cin >> players[i].nom;
				players[joueur_actif].verbeux = true;
				printf(I_JOUEUR_INFO, players[i].nom.c_str(), players[i].piece, players[i].couleur);
			break;
			default:
				players[i].nom = "IA";
				players[joueur_actif].verbeux = debug;
				printf(I_JOUEUR_INFO, players[i].nom.c_str(), players[i].piece, players[i].couleur);
			break;
		}
	}

}

// menu_pre_jeu
void menu_pre_jeu(void) {
	int choix,
		joueur_ia; // pour choisir le joueur IA;
	static int execution = 0; // valeur statique permettant de ne pas réaffichez les infos liées au jeu a chaque début de partie

	players[BLANC].ia = 0; // tous humain, le joueur devient IA en fonction du choix.
	players[NOIR].ia = 0;
	players[BLANC].verbeux = true; // tous humain
	players[NOIR].verbeux = true;
	joueur_ia = rand()%2; // qu'elle couleur prendra le joueur IA

	if (execution==0) { // on affiche les infos sur le jeu seulement lors de la 1ere execution du programme.
		clear_screen(); // on nettoie la console
		cout << M_A_PROPOS;
		execution++;
	}
	cout << M_MENU; // menu de choix de partie.
	cin >> choix;
// 	choix = 3;
	clear_screen(); // on nettoie la console


	switch(choix) {
		case 1:
			printf("\t[@] " CHX_HUMAIN);
			break;
		case 2:
			printf("\t[@] " CHX_IA_ALEA);
			players[joueur_ia].ia = 1; // première IA (randon simple)
		break;
		case 3:
			printf("\t[@] " CHX_IA_PONDEREE);
			players[joueur_ia].ia = 2; // première IA (cases pondérées)
		break;
		case 4:
			printf(A_AIDE);
			menu_pre_jeu();
		break;
		case 0:
			quit();
		break;
		default:
			clear_screen(); // on nettoie la console
			printf(E_VALEUR);
			menu_pre_jeu();
		break;
	}

	config_joueur(); // on configure les variables de chaque joueur (nom + piece)
	time(&start); // retourne l'heure de début.
	while (existe_coups_possibles()) { // tant qu'il existe des coups possibles sur le plateau
		demande_coup();
	}

}

int main(int argc, char *argv[]) {
	srand ( time(NULL) ); // création du seed

	for (int i = 1; i < argc; i++) {
		switch (argv[i][0]) {
			case '-': // l'élément est une option
				switch (argv[i][1]) {
					case 'd':
						debug = true;
						int val;
							if (sscanf(argv[i+1], "%d", &val) != EOF  &&  val > 0) {// Si conversion de la chaine n'échoue pas
								printf(DEBUG_ON DEBUG_LEVEL, val);
								debug_depth = val;
							}
							else {
								printf(DEBUG_DEFAULT_LEVEL);
							}
					break;
					case 'c': // montre la version est quitte
						clear = true;
					break;
					case 'v': // montre la version est quitte
						printf(AP_VERSION);
						exit(1);
					break;
					case 'a': // montre la version est quitte
						printf(AP_AUTEUR AP_REMERCIEMENT);
						exit(1);
					break;
					case 'h': // montre la version est quitte
						printf(A_AIDE);
						exit(1);
					break;
				}
			default :
				break;
		}
	}

	do {
		tour = 1;
		create_plateau();
		menu_pre_jeu();

		vainqueur();
		printf( L_EQUAL L_EQUAL "\n" L_EQUAL L_EQUAL "\n" Q_RECOMMENCER);
	} while (true);
	quit(); // quitte proprement le programme
}


