/* * 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 /** * Fonction test si famine * Test si le mouvement demandee provoque une \n * famine dans le camp oppose. Met a jour la variable string errorMsg\n * pour affichage sur le plateau de jeu. * @param aw un pointeur sur la structure awale sur laquelle faire le test * @param start un entier donnant la premiere case de l'opposant * @param end un entier donnant la derniere case de l'opposant * @return TRUE si ce mouvement ne declenche pas une famine, FALSE sinon * player est le dernier à avoir joué. C'est son coté qui peut être vide. */ short int isOpponentHungry(short int player, AWALE * aw) { short int i, total, start, end; start = (player == HUMAN)? START_HUMAN : START_COMPUTER; end = (player == HUMAN)? END_HUMAN : END_COMPUTER; for (total = 0, i = start; i <= end; i++) { total += aw->board[i]; } if (!total) return TRUE; return FALSE; } /** * Fonction de test si case non vide * Test si la case choisie n'est pas vide * @param hole entier designant la case du plateau choisie * @param aw pointeur sur la structure AWALE courante. */ AWALE *moveAwale(short int hole, AWALE * aw) { AWALE *tempAw, *tempAwGs; gboolean has_capture = FALSE; if (!aw->board[hole]){ return NULL; } short int nbBeans, j, last; tempAw = g_malloc(sizeof(AWALE)); memcpy(tempAw, aw, sizeof(AWALE)); tempAw->last_play = hole; nbBeans = tempAw->board[hole]; tempAw->board[hole] = 0; // Déplacement des graines for (j = 1, last = (hole+1)%12 ; j <= nbBeans; j++) { tempAw->board[last] += 1; last = (last + 1) % 12; if (last == hole) last = (last +1)% 12; } last = (last +11) %12; /* Grand Slam (play and no capture because this let other player hungry */ tempAwGs = g_malloc(sizeof(AWALE)); memcpy(tempAwGs, tempAw, sizeof(AWALE)); // capture while ((last >= ((tempAw->player == HUMAN)? 0 : 6)) && (last < ((tempAw->player == HUMAN)? 6 : 12))){ if ((tempAw->board[last] == 2) || (tempAw->board[last] == 3)){ has_capture = TRUE; tempAw->CapturedBeans[switch_player(tempAw->player)] += tempAw->board[last]; tempAw->board[last] = 0; last = (last+11)%12; continue; } break; } if (isOpponentHungry(tempAw->player, tempAw)){ if (has_capture){ /* Grand Slam case */ //g_warning("Grand Slam: no capture"); g_free(tempAw); return tempAwGs; } else{ /* No capture and opponent hungry -> forbidden */ //g_warning("isOpponentHungry %s TRUE",(tempAw->player == HUMAN)? "HUMAN" : "COMPUTER" ); g_free(tempAw); g_free(tempAwGs); return NULL; } } else { tempAw->player = switch_player(tempAw->player); return tempAw; } } /** * Fonction de chgt de joueur * Cette fonction permet de renvoyer la valeur de l'opposant * @param player un entier representant le joueur courant * @return un entier representant l'opposant */ short int switch_player(short int player) { return (player == HUMAN) ? COMPUTER : HUMAN; } /** * Fonction coup Aleatoire * Cette fonction permet de generer un coup aleatoire * @param a pointeur sur la structure AWALE courante * @return un entier representant le coup a jouer */ short int randplay(AWALE * a) { short int i; AWALE *tmp = NULL; do { i = 6 + g_random_int() % 6; } while (a->board[i] == 0 && !(tmp = moveAwale(i, a))); g_free(tmp); return (i); } /* last player is hungry and cannot be served ? */ gboolean diedOfHunger(AWALE *aw) { gint begin = (aw->player == HUMAN) ? 6 : 0; gint k; if (isOpponentHungry(switch_player(aw->player), aw)){ for (k=0; k <6; k++){ if ( aw->board[begin+k] > 6 - k) return FALSE; } g_warning("%s is died of hunger", (aw->player == HUMAN) ? "HUMAN" : "COMPUTER"); return TRUE; } else return FALSE; }