﻿% Auteur:
% Date: 08/12/2010

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%       Vous pouvez tester une partie entre deux joueurs alÃ©atoire de la faÃ§on suivante:
%       lancer_partie.
%       Le nombre de lignes/colonnes du damier va vous Ãªtre demandÃ©. Entrez un nombre pair positif.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

/*
        Permet de lancer une partie.
        Demande le nombre de lignes/colonnes Ã  l'utilisateur.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
lancer_partie :-        init_plateau(5, P),
                        afficher_plateau(P),
                        %joue_partie(0, noir, P, _).

%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Initialise un plateau de jeu.
        N=nombre de (lignes ou colonnes)/2
        Le plateau de jeu doit Ãªtre carrÃ© avec un nombre pair de lignes/colonnes.
        Structure d'une case: [Colonne, Ligne]
        Par exemple, la case [-3, 3] est la case en haut Ã  gauche du plateau et [3, 3] celle en bas Ã  droite.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
init_plateau(N, [N, [[-4,5],[-2,5],[1,5],[3,5], [5,5],[-5,4],[-3,4],[-1,4],[2,4], [4,4],
[-4,3],[-2,3],[1,3],[3,3], [5,3],[-5,2],[-3,2],[-1,2],[2,2], [4,2]],
[[-5,-5],[-3,-5], [-1,-5], [2,-5],[4,-5], [-4,-4], [-2,-4], [1,-4], [3,-4], [5,-4],
[-5,-3],[-3,-3], [-1,-3], [2,-3],[4,-3], [-4,-2], [-2,-2], [1,-2], [3,-2], [5,-2]]  ]).
%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Cette fonction renvoie la valeur de l'indice supÃ©rieur Ã  celui reÃ§u en argument en tenant compte de l'ordre suivant: -3, -2, -1, 1, 2, 3
        voisin_superieur(1, -Y): associe 2 Ã  Y car 2 est le voisin supÃ©rieur de 1.
        voisin_superieur(-X, 2): associe 1 Ã  X car 1 est le voisin infÃ©rieur de 2 puisque 2 est le voisin supÃ©rieur de 1.
        voisin_superieur(1, 2) = true car 2 est aprÃ¨s 1 (attention Ã  voisin_superieur(-1, 1) qui est true Ã©galement).
        voisin_superieur(1, 3) = false car le voisin supÃ©rieur de 1 est 2 et non 3.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
voisin_superieur(_, -1, 1) :- !.
voisin_superieur(N, X, Y) :-    (integer(X),
                                        X < N,
                                        N1 is N*(-1),
                                        (X > N1; X == N1), !,
                                        Y is X + 1);
                                        (integer(Y),
                                        (Y < N; Y == N),
                                        N1 is N*(-1),
                                        Y > N1, !,
                                        X is Y - 1).
%%%%% %%%%% %%%%% %%%%% %%%%%

%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        On peut se dÃ©placer dans tous les sens. Nous avons donc dÃ©cidÃ© d'utiliser les noms des points cardinaux pour plus de simplicitÃ©.
        Cette fonction permet de rÃ©cupÃ©rer les coordonnÃ©es de la case voisine suivant une direction donnÃ©e parmi les points cardinaux:
        - nordEst

        - sudEst

        - sudOuest

        - nordOuest
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
case_voisine(N, [Xd, Yd], sudEst, [Xa, Ya]) :- voisin_superieur(N, Xd, Xa), voisin_superieur(N, Ya, Yd).
case_voisine(N, [Xd, Yd], sudOuest, [Xa, Ya]) :- voisin_superieur(N, Xa, Xd), voisin_superieur(N, Ya, Yd).
case_voisine(N, [Xd, Yd], nordOuest, [Xa, Ya]) :- voisin_superieur(N, Xa, Xd), voisin_superieur(N, Yd, Ya).
case_voisine(N, [Xd, Yd], nordEst, [Xa, Ya]) :- voisin_superieur(N, Xd, Xa), voisin_superieur(N, Yd, Ya).
%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Permet de rÃ©cupÃ©rer la couleur de l'adversaire.
        couleur_adversaire(+C1, -C2): Affecte Ã  C2 la couleur de l'adversaire de C1.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
couleur_adversaire(noir, blanc).
couleur_adversaire(blanc, noir).
%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Permet de rÃ©cupÃ©rer la liste des pions d'un joueur suivant sa couleur.
        pions_joueur(+Couleur, +Plateau, -Pions): Affecte Ã  Pions la liste des pions du joueur dont la couleur est Couleur.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
pions_joueur(noir, [_, X, _], X).
pions_joueur(blanc, [_, _, X], X).
%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Ajoute une liste de pions dans la liste des pions d'un certain joueur suivant sa couleur.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
ajouter_pions(noir, Pions, [N, PN]) :- append(Pions, PN).
ajouter_pions(blanc, Pions, [B, PB]) :- append(Pions, PB).
%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Retire une liste de pions dans la liste des pions d'un certain joueur suivant sa couleur.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
retirer_pions(noir, Pions, [N, PN]) :- delete(Pions, PN).
retirer_pions(blanc, Pions, [B, PB]) :- delete(Pions, PB).
%%%%% %%%%% %%%%% %%%%% %%%%%



%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Affiche le plateau de jeu reÃ§u.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
afficher_plateau([N, PN, PB]) :- N1 is N*(-1), afficher_plateau1(N1, N, [N, PN, PB]).
%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        MÃªme chose que affiche_plateau mais avec des arguments en plus pour savoir quelles sont la ligne et la colonne courante.
        Cette fonction est appelÃ©e par afficher_plateau avec au dÃ©part C=-N et L=N.
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
% Fin de l'affichage.
afficher_plateau1(N, N1, [N, PN, PB]) :-        N1 is N*(-1), !, afficher_case([N, N1], PN, PB), write('\n\n').

% Affichage d'une case en fin de colonne => saut de ligne.
afficher_plateau1(N, L, [N, PN, PB]) :- afficher_case([N, L], PN, PB),
                                                        write('\n'),
                                                        voisin_superieur(N, L1, L), !,
                                                        C1 is N*(-1),
                                                        afficher_plateau1(C1, L1, [N, PN, PB]).
% Affichage d'une case normale.
afficher_plateau1(C, L, [N, PN, PB]) :- afficher_case([C, L], PN, PB),
                                                        voisin_superieur(N, C, C1),
                                                        afficher_plateau1(C1, L, [N, PN, PB]).
%%%%% %%%%% %%%%% %%%%% %%%%%

/*
        Affiche une case du plateau de jeu.
        Pion noir = x
        Pion blanc = o
        Case vide = _
*/
%%%%% %%%%% %%%%% %%%%% %%%%%
afficher_case(C, PN, PB) :-     write(' '),
                                        (member(C, PN) ->
                                        write('|x|');
                                        (member(C, PB) ->
                                                write('|o|');
                                                write('|-|'))).
%%%%% %%%%% %%%%% %%%%% %%%%%

% trace, init_plateau(3, P), afficher_plateau(P).
% trace, init_plateau(3, P), tous_coups_legaux(noir, P, R).
% init_plateau(3, P), joue_partie(noir, P, NP).

joue_partie(_, Couleur, Plateau, NPlateau) :-
        write('Au tour de '),
        write(Couleur),
        write(' de jouer:\n'),
        afficher_plateau(Plateau),
        %get_pion_selectionne(Couleur,Plateau,OldPosition),
        %get_coup_humain(Couleur, Plateau, NewPosition),
        %joue_coup(Couleur, Plateau, OldPosition, NewPosition, NPlateau1),
        %couleur_adversaire(Couleur, CAdverse),
        %joue_partie(0, CAdverse, NPlateau1, NPlateau).
        
        
/***************************************************************************************************************************************
        Récupère au clavier la case dans laquelle veut jouer le joueur humain.
***************************************************************************************************************************************/

%TODO Renvoyer un coup
get_coup_humain(Couleur, Plateau, NewPosition) :-
        write('\nColonne: '),
        read(Colonne),
        write('\nLigne: '),
        read(Ligne), !.

%TODO Renvoyer la position du pion
get_pion_selectionne(Couleur, Plateau, OldPosition) :-
        write('\nColonne: '),
        read(Colonne),
        write('\nLigne: '),
        read(Ligne),
        get_pion_selectionne(Couleur,Plateau,[Colonne,Ligne], !.
        
get_coup_humain(C, P, NewPosition) :-
        write('Mauvaise case\n'),
        get_coup_humain(C, P, NewPosition).

get_coup_humain(C, P, OldPosition) :-
        write('Mauvaise case\n'),
        get_coup_humain(C, P, OldPosition).


/***************************************************************************************************************************************
        Joue un coup donné dans le plateau courant.
***************************************************************************************************************************************/
joue_coup(Couleur, Plateau, OldPosition, NewPosition, NPlateau) :-
        ajouter_pions(Couleur, Plateau, NewPosition, NPlateau1),
        retirer_pions(Couleur, Plateau, OldPosition, NPlateau1).


