home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (C) 2000 by Hervé PHILIPPE <rv@bemail.org>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include "DeplacementOrdinateur.h"
-
- /////////////////////////////////////
- // VARIABLE "m_TableauPonderation" //
- /////////////////////////////////////------------------------------------------
- // Variable membre en "static" qui définit la pondération du tableau interne --
- //-----------------------------------------------------------------------------
- int16 DeplacementOrdinateur::m_TableauPonderation[11][11] = {
- { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
- { 0, 0, 0, 0, 1, 900, 900, 900, 900, 900, 1},
- { 0, 0, 0, 1, 900,1000,1000,1000,1000, 900, 1},
- { 0, 0, 1, 900,1000,1001,1001,1001,1000, 900, 1},
- { 0, 1, 900,1000,1001,1004,1004,1001,1000, 900, 1},
- { 1, 900,1000,1001,1004,1014,1004,1001,1000, 900, 1},
- { 1, 900,1000,1001,1004,1004,1001,1000, 900, 1, 0},
- { 1, 900,1000,1001,1001,1001,1000, 900, 1, 0, 0},
- { 1, 900,1000,1000,1000,1000, 900, 1, 0, 0, 0},
- { 1, 900, 900, 900, 900, 900, 1, 0, 0, 0, 0},
- { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}};
-
- /////////////////////////////////////////////
- // CONSTRUCTEUR de "DeplacementOrdinateur" //
- /////////////////////////////////////////////-----------------------------------
- // Construit l'objet "Deplacement" hérité et initialise les variables membres --
- //------------------------------------------------------------------------------
- DeplacementOrdinateur::DeplacementOrdinateur(PlateauDeJeuInterne* plateau_de_jeu_interne, PlateauDeJeuGraphique* plateau_de_jeu_graphique, int8 couleur, uint8 profondeur_max)
- // 4 PARAMETRES : ENTREE/SORTIE (modification par la suite) ENTREE/SORTIE (modification par la suite) ENTREE ENTREE
- : Deplacement(plateau_de_jeu_interne, plateau_de_jeu_graphique, couleur, true)
- {
- m_ProfondeurMax = profondeur_max;
- }
-
- //////////////////////
- // FONCTION "Jouer" //
- //////////////////////---------------------------------------------------------
- // Joue un coup automatiquement (de la part du joueur de type "ordinateur"). --
- // Le déplacement peut être réaliste ou non --
- //-----------------------------------------------------------------------------
- void // AUCUNE VALEUR DE RETOUR
- DeplacementOrdinateur::Jouer(bool faire_glisser_les_boules)
- // AUCUN PARAMETRE
- {
- if (CalculerMeilleurCoupPossible() != COUP_IMPOSSIBLE) {
- RestaurerMeilleurCoup();
- if (m_NombreBoulesSelectionnees == 1)
- DeplacerBoulesPoussee(faire_glisser_les_boules);
- else
- DeplacerBoulesLaterales(faire_glisser_les_boules);
- }
- // Sinon, l'ordinateur passe son tour !!!!
- }
-
- /////////////////////////////////////////////
- // FONCTION "CalculerMeilleurCoupPossible" //
- /////////////////////////////////////////////--------------------------------------------
- // Renvoie le meilleur coup possible pour une profondeur donnée --
- // REMARQUE : cette fonction et la fonction "CalculerCoup" sont récursives entre elles --
- //---------------------------------------------------------------------------------------
- int16 // VALEUR DE RETOUR
- DeplacementOrdinateur::CalculerMeilleurCoupPossible(uint8 profondeur)
- // 1 PARAMETRE : ENTREE
- {
- // Création et initialisation éventuelle des variables locales
- int8 i, j, k, min, max;
- int8 nombre_boules_joueur;
- int8 nombre_boules_adversaire;
- bool deplacement_avec_2_boules;
- bool direction_possible;
- int16 meilleur_coup = COUP_IMPOSSIBLE;
- PlateauDeJeuInterne* ancien_plateau_interne = new PlateauDeJeuInterne();
- PlateauDeJeuInterne* nouveau_plateau_interne = new PlateauDeJeuInterne();
-
- // Initialisation des variables "min" et "max" définissant les bornes de la boucle
- // Numéro de la première boule de la couleur du joueur (minimum inclu)
- min = 1 + m_CouleurCourante * m_PlateauInterne->NombreBoulesCouleur();
- // Numéro de la dernière boule de la couleur du joueur (maximum NON inclu)
- max = min + m_PlateauInterne->NombreBoulesCouleur();
-
- m_Direction = -1;
- // Boucle pour tester si le déplacement d'une boule de la bonne couleur est possible
- for (i = min; i < max; i++) {
- m_PremiereBouleSelectionnee = i;
- // Calculer tous les déplacements possibles
- for (j = 0; j < 6; j++) {
- m_NombreBoulesSelectionnees = 1;
- // Si la direction n°i correspond à un déplacement possible pour la boule sélectionnée
- direction_possible = DirectionPousseePossible(j, &nombre_boules_joueur, &nombre_boules_adversaire);
- if (direction_possible == true) {
- m_Direction = j;
- // Une poussée possible
- CalculerCoup(meilleur_coup, ancien_plateau_interne, nouveau_plateau_interne, profondeur, nombre_boules_joueur, nombre_boules_adversaire);
- }
- if (j < 3 && nombre_boules_joueur > 1) {
- m_DirectionLaterale = j;
- if (nombre_boules_joueur > 2)
- m_NombreBoulesSelectionnees = 3;
- else
- m_NombreBoulesSelectionnees = 2;
- for (k = 0; k < 6; k++) {
- if (k%3 != j) {
- direction_possible = DirectionLateralePossible(k, &deplacement_avec_2_boules);
- m_Direction = k;
- if (direction_possible == true || deplacement_avec_2_boules == true) {
- if (m_NombreBoulesSelectionnees == 3)
- m_NombreBoulesSelectionnees = 2;
- // Un déplacement latéral possible avec 2 boules
- CalculerCoup(meilleur_coup, ancien_plateau_interne, nouveau_plateau_interne, profondeur);
- if (nombre_boules_joueur > 2)
- m_NombreBoulesSelectionnees = 3;
- if (direction_possible == true && m_NombreBoulesSelectionnees == 3) {
- // Un déplacement latéral possible avec 3 boules
- CalculerCoup(meilleur_coup, ancien_plateau_interne, nouveau_plateau_interne, profondeur);
- }
- }
- }
- }
- }
- }
- }
- delete ancien_plateau_interne;
- delete nouveau_plateau_interne;
- return meilleur_coup;
- }
-
- /////////////////////////////
- // FONCTION "CalculerCoup" //
- /////////////////////////////-----------------------------------------------------
- // Calcule un coup possible --
- // REMARQUE : cette fonction et la fonction "CalculerMeilleurCoupPossible" sont --
- // récursives entre elles --
- //--------------------------------------------------------------------------------
- void // AUCUNE VALEUR DE RETOUR
- DeplacementOrdinateur::CalculerCoup(int16& meilleur_coup, PlateauDeJeuInterne* ancien_plateau_interne, PlateauDeJeuInterne* nouveau_plateau_interne, uint8 profondeur, int8 nombre_boules_joueur, int8 nombre_boules_adversaire)
- // 6 PARAMETRES : ENTREE/SORTIE (@) ENTREE/SORTIE ENTREE/SORTIE ENTREE ENTREE ENTREE
- {
- int8 premiere_boule_selectionnee;
- int8 direction;
- int8 nombre_boules_selectionnees;
- int8 direction_laterale;
- int16 coup;
- int16 coup_temp;
- int8 couleur_courante;
-
- if (profondeur == m_ProfondeurMax)
- if (m_NombreBoulesSelectionnees > 1)
- coup = CalculerValeurCoupLateral();
- else
- coup = CalculerValeurCoupPoussee(nombre_boules_joueur, nombre_boules_adversaire);
- else {
- *nouveau_plateau_interne = *m_PlateauInterne;
- *ancien_plateau_interne = *m_PlateauInterne;
- *m_PlateauInterne = *nouveau_plateau_interne;
- premiere_boule_selectionnee = m_PremiereBouleSelectionnee;
- nombre_boules_selectionnees = m_NombreBoulesSelectionnees;
- direction = m_Direction;
- direction_laterale = m_DirectionLaterale;
- if (m_NombreBoulesSelectionnees > 1)
- coup = CalculerValeurCoupLateral(true);
- else
- coup = CalculerValeurCoupPoussee(nombre_boules_joueur, nombre_boules_adversaire, true);
-
- couleur_courante = m_CouleurCourante;
- m_CouleurCourante = m_PlateauInterne->JoueurSuivant(m_CouleurCourante);
- coup_temp = CalculerMeilleurCoupPossible(profondeur+1);
- ///////////ATTENTION////////
- coup -= coup_temp; ////ATTENTION : - par -, ça fait +, donc c'est valable
- ///////////ATTENTION//////// pour 2 joueurs. Pour 3 joueurs, il faut utiliser la fonction
- // "NombreJoueurs" de la classe "PlateauDeJeu", pour savoir si on doit additionner ou
- // soustraire
- m_CouleurCourante = couleur_courante;
-
- *m_PlateauInterne = *ancien_plateau_interne;
- m_PremiereBouleSelectionnee = premiere_boule_selectionnee;
- m_NombreBoulesSelectionnees = nombre_boules_selectionnees;
- m_Direction = direction;
- m_DirectionLaterale = direction_laterale;
- }
- if (coup > meilleur_coup) {
- if (profondeur == 1)
- SauvegarderMeilleurCoup();
- meilleur_coup = coup;
- }
- }
-
- //////////////////////////////////////////
- // FONCTION "CalculerValeurCoupPoussee" //
- //////////////////////////////////////////-------------------------------------------
- // Renvoie la valeur d'un coup pour un déplacement en poussée (pour un déplacement --
- // virtuel ou non) --
- //-----------------------------------------------------------------------------------
- int16 // VALEUR DE RETOUR
- DeplacementOrdinateur::CalculerValeurCoupPoussee(int8 nombre_boules_joueur, int8 nombre_boules_adversaire, bool deplacement_virtuel)
- // 3 PARAMETRES : ENTREE ENTREE ENTREE
- {
- // Création et initialisation éventuelle des variables locales
- int8 i;
- int16 valeur_coup = 0;
- Coordonnees coord_boule = m_PlateauInterne->CoordonneesBoule(m_PremiereBouleSelectionnee);
-
- valeur_coup -= m_TableauPonderation[coord_boule.x][coord_boule.y];
- for (i = 0; i < nombre_boules_joueur; i++)
- if (deplacement_virtuel == true)
- coord_boule = m_PlateauInterne->DeplacerBoule(coord_boule, m_Direction); // Se positionner sur la case suivante
- else
- coord_boule = m_PlateauInterne->CoordonneesSuivantes(coord_boule, m_Direction); // Se positionner sur la case suivante
- valeur_coup += m_TableauPonderation[coord_boule.x][coord_boule.y];
-
- if (nombre_boules_adversaire != 0) {
- valeur_coup += m_TableauPonderation[coord_boule.x][coord_boule.y];
- for (i = 0; i < nombre_boules_adversaire; i++)
- if (deplacement_virtuel == true)
- coord_boule = m_PlateauInterne->DeplacerBoule(coord_boule, m_Direction); // Se positionner sur la case suivante
- else
- coord_boule = m_PlateauInterne->CoordonneesSuivantes(coord_boule, m_Direction); // Se positionner sur la case suivante
- valeur_coup -= m_TableauPonderation[coord_boule.x][coord_boule.y];
- }
- return valeur_coup;
- }
-
- //////////////////////////////////////////
- // FONCTION "CalculerValeurCoupLateral" //
- //////////////////////////////////////////----------------------------------------
- // Renvoie la valeur d'un coup pour un déplacement latéral (pour un déplacement --
- // virtuel ou non) --
- //--------------------------------------------------------------------------------
- int16 // VALEUR DE RETOUR
- DeplacementOrdinateur::CalculerValeurCoupLateral(bool deplacement_virtuel)
- // 1 PARAMETRE : ENTREE
- {
- // Création et initialisation éventuelle des variables locales
- int8 i;
- int16 valeur_coup = 0;
- Coordonnees coord_boule = m_PlateauInterne->CoordonneesBoule(m_PremiereBouleSelectionnee);
- Coordonnees coord_boule_deplacee;
-
- for (i = 0; i < m_NombreBoulesSelectionnees; i++) {
- if (deplacement_virtuel == true)
- coord_boule_deplacee = m_PlateauInterne->DeplacerBoule(coord_boule, m_Direction); // Se positionner sur la case suivante
- else
- coord_boule_deplacee = m_PlateauInterne->CoordonneesSuivantes(coord_boule, m_Direction); // Se positionner sur la case suivante
- valeur_coup += m_TableauPonderation[coord_boule_deplacee.x][coord_boule_deplacee.y];
- valeur_coup -= m_TableauPonderation[coord_boule.x][coord_boule.y];
- coord_boule = m_PlateauInterne->CoordonneesSuivantes(coord_boule, m_DirectionLaterale); // Se positionner sur la case suivante
- }
- return valeur_coup;
- }
-
- ////////////////////////////////////////
- // FONCTION "SauvegarderMeilleurCoup" //
- ////////////////////////////////////////----------------------
- // Sauvegarde le meilleur coup dans des variables réservées --
- //------------------------------------------------------------
- void // AUCUNE VALEUR DE RETOUR
- DeplacementOrdinateur::SauvegarderMeilleurCoup()
- // AUCUN PARAMETRE
- {
- m_PremiereBouleSelectionnee_MeilleurCoup = m_PremiereBouleSelectionnee;
- m_Direction_MeilleurCoup = m_Direction;
- m_NombreBoulesSelectionnees_MeilleurCoup = m_NombreBoulesSelectionnees;
- m_DirectionLaterale_MeilleurCoup = m_DirectionLaterale;
- }
-
- //////////////////////////////////////
- // FONCTION "RestaurerMeilleurCoup" //
- //////////////////////////////////////--------------------------
- // Restaure le meilleur coup à partir des variables réservées --
- //--------------------------------------------------------------
- void // AUCUNE VALEUR DE RETOUR
- DeplacementOrdinateur::RestaurerMeilleurCoup()
- // AUCUN PARAMETRE
- {
- m_PremiereBouleSelectionnee = m_PremiereBouleSelectionnee_MeilleurCoup;
- m_Direction = m_Direction_MeilleurCoup;
- m_NombreBoulesSelectionnees = m_NombreBoulesSelectionnees_MeilleurCoup;
- m_DirectionLaterale = m_DirectionLaterale_MeilleurCoup;
- }
-