home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freelog 17
/
Freelog017.iso
/
BeOS
/
ababelone
/
Sources
/
DeplacementOrdinateur.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-11-05
|
14KB
|
295 lines
/*
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;
}