add winrate test

This commit is contained in:
Mylloon 2022-12-04 21:05:28 +01:00
parent f278a49f66
commit 68c7f2824a
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
5 changed files with 121 additions and 31 deletions

View file

@ -47,8 +47,9 @@ typedef struct jeu Jeu;
Jeu *nouvelle_partie(void);
/* Lance et joue une partie */
void deroulement_partie(Jeu *jeu, const enum PLAYER_TYPE noir,
const enum PLAYER_TYPE blanc, const Test_Data *test);
enum CASE deroulement_partie(Jeu *jeu, const enum PLAYER_TYPE noir,
const enum PLAYER_TYPE blanc,
const Test_Data *test);
/* Coups possibles d'un joueur */
struct coups {

View file

@ -5,17 +5,25 @@
struct test_data {
int test;
int profondeur;
int profondeur_minimax;
int profondeur_alphabeta;
};
typedef struct test_data Test_Data;
/* Initialise un Test_Data */
Test_Data *nouveau_test_data(int test, int profondeur);
Test_Data *nouveau_test_data(int test, int profondeur_minimax,
int profondeur_alphabeta);
/* Libère un Test_Data de la mémoire */
void free_test_data(Test_Data *test_data);
/* Run the tests */
/* Lance les différents tests */
void run_tests(void);
/* Test par rapport à la vitesse d'éxécution */
void speed_test(int profondeur_max_minimax, int profondeur_max_alphabeta);
/* Test par rapport à qui gagne */
void winrate_test(int profondeur_max_minimax, int profondeur_max_alphabeta);
#endif

View file

@ -38,9 +38,9 @@ Jeu *nouvelle_partie(void) {
return jeu;
}
void deroulement_partie(Jeu *jeu, const enum PLAYER_TYPE type_noir,
const enum PLAYER_TYPE type_blanc,
const Test_Data *test) {
enum CASE deroulement_partie(Jeu *jeu, const enum PLAYER_TYPE type_noir,
const enum PLAYER_TYPE type_blanc,
const Test_Data *test) {
Joueur *tour = jeu->j1->couleur == NOIR ? jeu->j1 : jeu->j2;
while (!partie_finie(jeu)) {
@ -66,11 +66,12 @@ void deroulement_partie(Jeu *jeu, const enum PLAYER_TYPE type_noir,
action_joueur_humain(jeu, tour->couleur);
break;
case MINIMAX:
action_joueur_minimax(jeu, tour->couleur, test->profondeur);
action_joueur_minimax(jeu, tour->couleur,
test->profondeur_minimax);
break;
case ALPHABETA:
action_joueur_alphabeta(jeu, tour->couleur,
test->profondeur);
test->profondeur_alphabeta);
break;
default:
fprintf(stderr, "Erreur: Joueur noir non supporté.");
@ -87,11 +88,12 @@ void deroulement_partie(Jeu *jeu, const enum PLAYER_TYPE type_noir,
action_joueur_humain(jeu, tour->couleur);
break;
case MINIMAX:
action_joueur_minimax(jeu, tour->couleur, test->profondeur);
action_joueur_minimax(jeu, tour->couleur,
test->profondeur_minimax);
break;
case ALPHABETA:
action_joueur_alphabeta(jeu, tour->couleur,
test->profondeur);
test->profondeur_alphabeta);
break;
default:
fprintf(stderr, "Erreur: Joueur blanc non supporté.");
@ -110,17 +112,24 @@ void deroulement_partie(Jeu *jeu, const enum PLAYER_TYPE type_noir,
if (!test->test) {
affiche_plateau(jeu->plateau);
}
int resultat[3];
if (selection_gagnant(jeu, resultat)) {
int resultat[3];
if (selection_gagnant(jeu, resultat)) {
Joueur *gagnant = jeu->j1->couleur == resultat[0] ? jeu->j1 : jeu->j2;
if (!test->test) {
printf("Fin de partie ! Le joueur %s a gagné %d contre %d !\n",
jeu->j1->couleur == resultat[0] ? jeu->j1->nom
: jeu->j2->nom,
resultat[1], resultat[2]);
} else {
gagnant->nom, resultat[1], resultat[2]);
}
return gagnant->couleur;
} else {
if (!test->test) {
printf("Égalité parfaite, %d contre %d !\n", jeu->j1->nb_jeton,
jeu->j2->nb_jeton);
}
return VIDE;
}
}

View file

@ -74,7 +74,7 @@ int main(int argc, char const *argv[]) {
}
Jeu *jeu = nouvelle_partie();
Test_Data *test = nouveau_test_data(0, 3);
Test_Data *test = nouveau_test_data(0, 4, 6);
printf("Le jeu commence avec les noirs en tant %s et les blancs en "
"tant %s.\n",

View file

@ -1,11 +1,14 @@
#include "../includes/jeu.h"
#include <stdio.h>
#include <time.h>
Test_Data *nouveau_test_data(int test, int profondeur) {
Test_Data *nouveau_test_data(int test, int profondeur_minimax,
int profondeur_alphabeta) {
Test_Data *res = malloc(sizeof(Test_Data));
res->test = test;
res->profondeur = profondeur;
res->profondeur_minimax = profondeur_minimax;
res->profondeur_alphabeta = profondeur_alphabeta;
return res;
}
@ -13,24 +16,27 @@ Test_Data *nouveau_test_data(int test, int profondeur) {
void free_test_data(Test_Data *test_data) { free(test_data); }
void run_tests(void) {
speed_test(6, 8);
winrate_test(5, 7);
}
void speed_test(int profondeur_max_minimax, int profondeur_max_alphabeta) {
int repetions = 5;
int max_profondeur = 8;
int max_profondeur_minimax = 6;
printf("Lancement des tests, on va jusqu'à une profondeur de %d avec une "
"moyenne de %d répétitions.\n",
max_profondeur, repetions);
profondeur_max_alphabeta, repetions);
printf("On fait jouer alpha-bêta contre lui-même puis minimax contre "
"lui-même.\n");
clock_t t0;
double delta1, delta2, precedent = 0, actuel = 0;
for (int i = 1; i < max_profondeur + 1; ++i) {
for (int i = 1; i < profondeur_max_alphabeta + 1; ++i) {
delta1 = 0;
for (int j = 0; j < repetions; ++j) {
Jeu *jeu = nouvelle_partie();
Test_Data *test = nouveau_test_data(1, i);
Test_Data *test = nouveau_test_data(1, 0, i);
t0 = clock();
@ -44,17 +50,17 @@ void run_tests(void) {
}
delta1 /= repetions;
printf("Profondeur de %d (moyenne de %d tests) ->\t Alphabêta = %fs\t",
printf("Profondeur de %d (moyenne de %d tests) ->\t alpha-bêta = %fs\t",
i, repetions, delta1);
if (i < max_profondeur_minimax) {
if (i < profondeur_max_minimax) {
// On ne calcul que Minimax avec une petite profondeur parce que
// sinon c'est trop long
delta2 = 0;
for (int j = 0; j < repetions; ++j) {
Jeu *jeu = nouvelle_partie();
Test_Data *test = nouveau_test_data(1, i);
Test_Data *test = nouveau_test_data(1, i, 0);
t0 = clock();
@ -69,10 +75,10 @@ void run_tests(void) {
delta2 /= repetions;
actuel = delta2 - delta1;
printf("| Minimax = %fs\t | Différence (m - a) = %fs", delta2,
printf("| minimax = %fs\t | différence (m - a) = %fs", delta2,
actuel);
}
if (i > 1 && i < max_profondeur_minimax) {
if (i > 1 && i < profondeur_max_minimax) {
printf("\tavec le précédent = %fs\n", actuel - precedent);
} else {
printf("\n");
@ -80,3 +86,69 @@ void run_tests(void) {
precedent = actuel;
}
}
void winrate_test(int profondeur_max_minimax, int profondeur_max_alphabeta) {
int nb_tests = 0;
int nb_victoire_minimax = 0, nb_victoire_alphabeta = 0, nb_egalite = 0;
for (int i = 1; i < profondeur_max_alphabeta; ++i) {
for (int j = 1; j < profondeur_max_minimax; ++j, ++nb_tests) {
Jeu *jeu = nouvelle_partie();
Test_Data *test = nouveau_test_data(1, j, i);
// On alterne qui commence le jeu
int joueur_noir = i % 2 ? MINIMAX : ALPHABETA;
int joueur_blanc = joueur_noir == MINIMAX ? ALPHABETA : MINIMAX;
int res;
switch (res = deroulement_partie(jeu, joueur_noir, joueur_blanc,
test)) {
case VIDE:
nb_egalite++;
break;
case BLANC:
if (joueur_blanc == MINIMAX) {
nb_victoire_minimax++;
printf("Minimax a gagné (profondeur minimax = %d vs %d = "
"profondeur alphabêta)\n",
j, i);
} else {
nb_victoire_alphabeta++;
printf(
"Alpha-bêta a gagné (profondeur minimax = %d vs %d = "
"profondeur alphabêta)\n",
j, i);
}
break;
case NOIR:
if (joueur_noir == MINIMAX) {
nb_victoire_minimax++;
printf("Minimax a gagné (profondeur minimax = %d vs %d = "
"profondeur alphabêta)\n",
j, i);
} else {
nb_victoire_alphabeta++;
printf(
"Alpha-bêta a gagné (profondeur minimax = %d vs %d = "
"profondeur alphabêta)\n",
j, i);
}
break;
default:
fprintf(stderr,
"Une erreur est survenue lors des tests de victoire "
"'%c'.\n",
res);
exit(1);
}
free_jeu(jeu);
free_test_data(test);
}
}
printf("Nombre totale de parties : %d.\n", nb_tests);
printf("Alpha-bêta a gagné %d fois.\n", nb_victoire_alphabeta);
printf("Minimax a gagné %d fois.\n", nb_victoire_minimax);
printf("Il y a eu %d égalités.\n", nb_egalite);
}