/*
* gcompris - awele.c
* Copyright (C) 2005, 2008 Frederic Mazzarol
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include "awele_utils.h"
#include
#include
#include "gcompris/gcompris.h"
static gint maxprof;
/**
* Fonction d'evaluation d'un plateau
* La fonction d'evaluation va evaluer la difference du nombre de graines capturees (Facteur preponderant),\n
* la difference de la mobilite des deux joueurs, la difference des cases menacantes,\n
* et la difference du nombre de graine active de chaque joueur.\n
* @param AWALE *aw Pointeur sur la structure AWALE a evaluer
* @return Une note d'evaluation du plateau.
*/
gint eval (GNode *node){
AWALE *aw = node->data;
if (aw->CapturedBeans[COMPUTER] > 24)
return 25;
if (aw->CapturedBeans[HUMAN] > 24)
return -25;
return (aw->CapturedBeans[COMPUTER] - aw->CapturedBeans[HUMAN]);
}
/*
* Evaluation function for level 1-2
* this function returns always 0. The play is random,
* because tree building is randomised.
*
*/
gint eval_to_null (GNode *node){
return 0;
}
gint eval_to_best_capture (GNode *node){
AWALE *aw = node->data;
return (aw->CapturedBeans[COMPUTER]);
}
/*
* firstChild. create all the childs and return first one
*/
GNode *firstChild(GNode *node)
{
AWALE *aw = node->data;
AWALE *tmpaw;
GNode *tmpnode;
gint eval_node = eval(node);
gint rand_play;
/* Case node is winning one */
if ((eval_node == 25) || (eval_node == -25))
return NULL;
gint i;
rand_play = g_random_int_range(1, 5);
for (i = 0 ; i < 6; i++)
{
tmpaw = moveAwale((rand_play + i)%6 + ((aw->player == HUMAN )? 6 : 0), aw);
if (tmpaw){
tmpnode = g_node_new(tmpaw);
g_node_insert (node, -1, tmpnode);
}
}
return g_node_first_child(node);
}
/* next sibling */
GNode *nextSibling(GNode *node)
{
return g_node_next_sibling(node);
}
gboolean free_awale(GNode *node,
gpointer data){
g_free(data);
return TRUE;
}
/**
* Fonction de jeu de la machine
* Cette Fonction est appelee pour faire jouer l'ordinateur, \n
* la racine de l'arbre est cree, puis passe en argument a la fonction AlphaBeta\n
* La profondeur augmente au fur et mesure de la partie quand le nombre de graines diminue.\n
* @param aw Un pointeur sur le plateau a partir duquel reflechir
* @return Le meilleur coup calcule par la machine
* le player est celui qui a joué le dernier coup.
*/
short int think( AWALE *static_awale, short int level){
AWALE *aw = g_malloc(sizeof(AWALE));
memcpy (aw, static_awale, sizeof(AWALE));
GNode *t = g_node_new(aw) ;
int best = -1;
int value = 0;
EvalFunction use_eval = NULL;
switch (level) {
case 1:
maxprof = 1;
use_eval = (EvalFunction)&eval_to_null;
g_warning("search depth 1, evaluation null");
break;
case 2:
maxprof = 1;
use_eval = (EvalFunction)&eval_to_best_capture;
g_warning("search depth 1, evaluation best capture");
break;
case 3:
case 4:
maxprof = 2;
use_eval = (EvalFunction)&eval;
g_warning("search depth %d, evaluation best difference", maxprof);
break;
case 5:
case 6:
maxprof = 4;
use_eval = (EvalFunction)&eval;
g_warning("search depth %d, evaluation best difference", maxprof);
break;
case 7:
case 8:
maxprof = 6;
use_eval = (EvalFunction)&eval;
g_warning("search depth %d, evaluation best difference", maxprof);
break;
case 9:
maxprof = 8;
use_eval = (EvalFunction)&eval;
g_warning("search depth %d, evaluation best difference", maxprof);
break;
default:
maxprof = 8;
use_eval = (EvalFunction)&eval;
g_warning("search depth %d, evaluation best difference", maxprof);
break;
}
value = gc_alphabeta( TRUE,
t,
use_eval,
&best,
(FirstChildGameFunction) firstChild,
(NextSiblingGameFunction) nextSibling,
-INFINI ,
INFINI,
maxprof) ;
if (best < 0){
g_warning("Leaf node, game is over");
return -1;
}
GNode *tmpNode = g_node_nth_child (t, best);
AWALE *tmpaw = tmpNode->data;
g_warning("THINK best : %d, play: %d", value, tmpaw->last_play);
best = tmpaw->last_play;
/* free awales*/
g_node_traverse (t,
G_IN_ORDER,
G_TRAVERSE_ALL,
-1,
(GNodeTraverseFunc) free_awale,
NULL);
/* free tree */
g_node_destroy(t);
return (best);
}