/* * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #define _GNU_SOURCE #include #include #include #include "select.h" #include "throw.h" #include "position.h" #include "set.h" #include "game.h" #include "free.h" #include "draw.h" #include "callback.h" #include "list.h" #include "def.h" /* game_play_ia: play automagically. That's * what we call Artificial Intelligence. * Indeed that's not intelligent at all. */ void game_play_ia(struct _prog *prog_data) { while(prog_data->player != 2 && prog_data->players[prog_data->player] != NULL && prog_data->player != prog_data->hashand) { game_turn(prog_data, NULL); } } /* game_middle_position: set the position (x,y) * of each card in the list represented at the * center of the game area (the table). */ void game_middle_position(struct _prog *prog_data) { GList *ptr; struct _card *data; int player = prog_data->hashand; if(player != -1) { for(ptr = g_list_last(prog_data->waiting); ptr; ptr = ptr->prev) { data = ptr->data; game_position_middle(data, prog_data, player); select_player_next(&player); } } } /* game_hand_position: set the position (x,y) * of the cards in each player hand. */ void game_hand_position(struct _prog *prog_data, int player) { int x, y, w, h; enum eposition ep; int coef, start, max; if(prog_data->back) { gdk_drawable_get_size(prog_data->back, &w, &h); if(player == -1) { start = 0; max = 4; } else { start = player; max = player+1; } for(player = start; player < max; player++) { switch(player) { case 0: y = 10; coef = 1; x = (prog_data->area->allocation.width - w) / 3; ep = EP_HORIZONTAL; break; case 1: x = prog_data->area->allocation.width - w -10; coef = 1; y = (prog_data->area->allocation.height - h) / 2; ep = EP_VERTICAL; break; case 2: y = prog_data->area->allocation.height - h -10; coef = -1; x = (prog_data->area->allocation.width - w)*2 / 3; ep = EP_HORIZONTAL; break; case 3: x = 10; coef = -1; y = (prog_data->area->allocation.height - h)*2 / 3; ep = EP_VERTICAL; break; } position_list(prog_data->players[player], x, y, ep, coef*prog_data->space, prog_data); } } } /* game_send: distributing cards function. * This will send cards from one list to * players list. Each player will take * [the value of mod] cards. * * int mod: how many cards per player. * * int max: how many cards we want to send * (total) * * GList *ptr: the list where we take the * cards. */ GList* game_send(struct _prog *prog_data, int mod, int max, GList *ptr) { int player = prog_data->distributer; int i, modifier; GList *last; select_player_next(&player); for(modifier = 0, i = 1; i <= max; i++) { if(ptr != NULL) { throw_to(&prog_data->players[player], (struct _card*) ptr->data); if(player == 2) { ((struct _card*) ptr->data)->draw_face = TRUE; } /* at the second distribution phase, * we need to send three cards to each player * except the one that choose the trump family. * This one will take only two cards. * That's why we do i++ here, so we won't be * distributing [the value of mod] cards to him, * but instead [[the value of mod]-1] cards. */ if(player == prog_data->master && modifier == 0) { i++; modifier = 1; } if(i % mod == 0) { select_player_next(&player); } last = ptr; ptr = ptr->next; prog_data->pile = g_list_remove(prog_data->pile, last->data); } else i = max+1; } return(ptr); } /* game_distribute_phase1 : send five cards to * each player. (Three first, and two) */ void game_distribute_phase1(struct _prog *prog_data) { if(prog_data->players && prog_data->pile) { prog_data->pile = game_send(prog_data, 3, 12, prog_data->pile); prog_data->pile = game_send(prog_data, 2, 8, prog_data->pile); game_hand_position(prog_data, -1); } } /* game_distribute_phase2 : send remaining card in * the pile to the players. The card which was * proposed is to be sent to the master player. */ void game_distribute_phase2(struct _prog *prog_data) { if(prog_data->players && prog_data->pile) { prog_data->pile = game_send(prog_data, 3, 12, prog_data->pile); if(prog_data->waiting) { struct _card *data_ptr = (struct _card*) prog_data->waiting->data; if(prog_data->master != 2) data_ptr->draw_face = FALSE; data_ptr->moveable = FALSE; throw_to(&prog_data->players[prog_data->master], data_ptr); prog_data->waiting = g_list_remove(prog_data->waiting, data_ptr); } game_hand_position(prog_data, -1); } } /* game_finish_phase1 : just take one card from * the pile and put it on the top of the pile, * with the value displayed to the user. * This is the proposed trump card. */ void game_finish_phase1(struct _prog *prog_data) { GList *pile = prog_data->pile; if(pile != NULL) { struct _card *data_ptr = (struct _card*) pile->data; throw_to(&prog_data->waiting, data_ptr); data_ptr->draw_face = TRUE; data_ptr->moveable = TRUE; if(prog_data->output) { fprintf(prog_data->output, _("Proposed card is ") ); game_print_card(prog_data->output, data_ptr); fprintf(prog_data->output, "\n"); } prog_data->pile = g_list_remove(prog_data->pile, data_ptr); } } /* game_drop_middle: there should be four * cards on the table when calling this * function. It means we need to know * what team wins the turn, and send * all of those cards to the winner team * list. * Note: indeed the winner player of * this turn has already been determined, * it's the 'menext' value in struct _prog * That's why we don't need to find the * winner team here, we know it already * (it's [menext MODULO 2]) */ void game_drop_middle(struct _prog *prog_data) { struct _card *data_ptr; GList *ptr; int winner = -1; if(prog_data->menext >= 0) { winner = prog_data->menext % 2; if(prog_data->output != NULL) { fprintf(prog_data->output, _("Team %d"), winner); if(winner == 0) fprintf(prog_data->output, _("(0 = top, 2 = you)") ); else fprintf(prog_data->output, _("(1 = right, 3 = left)") ); fprintf(prog_data->output, _(" wins this turn\n") ); } ptr = prog_data->waiting; while( ptr ) { data_ptr = (struct _card *)ptr->data; data_ptr->blink = FALSE; data_ptr->draw = FALSE; throw_to(&prog_data->teams[winner], data_ptr); ptr = ptr->next; } g_list_free(prog_data->waiting); prog_data->waiting = NULL; } else if(prog_data->output != NULL) { fprintf(prog_data->output, _("Unable to check who win this turn.\n") ); } } void game_middle_offset_static(int player, int *midx, int *midy, int size) { switch(player) { case 0: *midy -= size; break; case 1: *midx += size; break; case 2: *midy += size; break; case 3: *midx -= size; break; } } void game_middle_offset_dynamic(int player, int *midx, int *midy, int w, int h, int cardw, int cardh) { switch(player) { case 0: *midy = cardh + 20; break; case 1: *midx = w - 2*cardw - 20; break; case 2: *midy = h - 2*cardh - 20; break; case 3: *midx = cardw + 20; break; } } /* game_position_middle : set the position (x,y) * of a card on the table. Each card is * positionned in relation to the player * who dropped it. */ void game_position_middle(struct _card *card, struct _prog *prog_data, int player) { int midx, midy; midx = (prog_data->area->allocation.width - card->dim.w)/2; midy = (prog_data->area->allocation.height - card->dim.h)/2; game_middle_offset_dynamic(player, &midx, &midy, prog_data->area->allocation.width, prog_data->area->allocation.height, card->dim.w, card->dim.h); if(card->dim.x != midx || card->dim.y != midy) { if(prog_data->animation) position_move_card(card, midx, midy, prog_data); card->dim.x = midx; card->dim.y = midy; draw_container(prog_data); } } /* game_print_family: that's in french atm, * feel free to translate. */ void game_print_family(FILE *stream, int family) { switch(family) { case 0: fprintf(stream, _("diamond") ); break; case 1: fprintf(stream, _("spade") ); break; case 2: fprintf(stream, _("heart") ); break; case 3: fprintf(stream, _("club") ); break; } } /* game_print_card: print the card as * a nominative value. * Example: ace of diamond * Feel free to translate. */ void game_print_card(FILE *stream, struct _card *card) { switch(card->num) { case 0: fprintf(stream, _("ace") ); break; case 6: case 7: case 8: case 9: fprintf(stream, "%d", card->num+1); break; case 10: fprintf(stream, _("jack") ); break; case 11: fprintf(stream, _("queen") ); break; case 12: fprintf(stream, _("king") ); break; } fprintf(stream, _(" of ") ); game_print_family(stream, card->family); } /* game_get_family_best: what is the most * powerfull card we get on a GList in * a particular family only. */ int game_get_family_best(int family, GList *lst) { int nb = -1, i, best = 0; struct _card *data; for(i=0; lst; i++) { data = (struct _card*)lst->data; if(data->family == family) { if(data->points > best) { best = data->points; nb = i; } } lst = lst->next; } return(nb); } gboolean game_find_card(int family, int num, GList *lst) { gboolean found = FALSE; struct _card *data; while(lst) { data = lst->data; if(data->family == family && data->num == num) { found = TRUE; lst = NULL; } else lst = lst->next; } return(found); } /* game_get_best: what is the most * powerful card on a list, related * to a family, but not only. * If we found a trump card, it will * probably be better than something * else. That's what majorfamily is * all about. * * Note: if the family value is -1, * then the first card family is * taken as a reference to find more * powerfull cards. Don't forget * that if majorfamily is set (other * than -1), and if it's different * than the value of family, any * card of the majorfamily is better * then the first card. * * That function is heavily used to * find if a card dropped on the * table is better than others. * * We just find what is the best * card on the table. Then we check * this card against the one to be * dropped. */ struct _card* game_get_best(int *best, int *family, int majorfamily, GList *lst) { struct _card *data, *first = NULL; lst = g_list_last(lst); while(lst) { data = (struct _card*)lst->data; if(*family == -1) { first = data; *best = data->points; *family = data->family; } else if(data->family == *family) { if(data->points > *best) *best = data->points; } else if(data->family == majorfamily) { *best = data->points; *family = data->family; } lst = lst->prev; } return(first); } /* game_check_cardisbetter: check if a card * is more powerfull than the most powerfull * card on a GList */ gboolean game_check_cardisbetter(struct _card *card, GList *lst, int majorfamily) { int best = 0, family = -1; gboolean better = FALSE; struct _card *first; first = game_get_best(&best, &family, majorfamily, lst); if(best > 0) { if(card->family == family) { if(card->points > best) better = TRUE; } else if(card->family == majorfamily) { better = TRUE; } } return(better); } int *game_card_get_ordered(int family, int trump) { int *nums = (int*)g_malloc(sizeof(int)*8); if(nums != NULL) { if(family == trump) { nums[0] = 6; nums[1] = 7; nums[2] = 11; nums[3] = 12; nums[4] = 9; nums[5] = 0; nums[6] = 8; nums[7] = 10; } else { nums[0] = 6; nums[1] = 7; nums[2] = 8; nums[3] = 10; nums[4] = 11; nums[5] = 12; nums[6] = 9; nums[7] = 0; } } return nums; } gboolean game_card_is_best_remaining(struct _prog *prog_data, struct _card *card) { gboolean best = TRUE, list1, list2; int num, i; int *numequivalent; numequivalent = game_card_get_ordered(card->family, prog_data->family); if(numequivalent) { num = game_card_get_ordered_num(card, prog_data->family); for(i = num+1; i < 8; i++) { list1 = game_find_card(card->family, numequivalent[i], prog_data->teams[0]); list2 = game_find_card(card->family, numequivalent[i], prog_data->teams[1]); if(!list1 && !list2) { i = 10; best = FALSE; } else if (prog_data->output) fprintf(prog_data->output, _("num(0,7): %d ; family %d\n"), i, card->family); } g_free(numequivalent); } else best = FALSE; return(best); } struct _card* game_ia_choose_any(struct _prog *prog_data) { struct _card *data_ptr, *lowest = NULL, *besttrump=NULL; GList *tmp; int lowpts = 1000; for(tmp = prog_data->players[prog_data->player]; tmp; tmp = tmp->next) { data_ptr = tmp->data; if(data_ptr->points < lowpts && data_ptr->family != prog_data->family ) { lowpts = data_ptr->points; lowest = data_ptr; } if(data_ptr->family == prog_data->family && (!besttrump || besttrump->points < data_ptr->points) ) { besttrump = data_ptr; } } if(!lowest) { if(game_card_is_best_remaining(prog_data, besttrump) ) lowest = besttrump; else { tmp = prog_data->players[prog_data->player]; lowest = tmp->data; } } return(lowest); } struct _card* game_ia_choose_first(struct _prog *prog_data) { struct _card *card = NULL, *data_ptr, *lowest = NULL; GList *tmp; int lowpts = 1000; if(prog_data->output) fprintf(prog_data->output, _("Player %d to start\n") , prog_data->player); for(tmp = prog_data->players[prog_data->player]; tmp; tmp = tmp->next) { data_ptr = tmp->data; if(data_ptr->points < lowpts) { lowpts = data_ptr->points; lowest = data_ptr; } if(game_card_is_best_remaining(prog_data, data_ptr)) { if(prog_data->output) fprintf(prog_data->output, _("This is the best of this family: num%d family%d points%d \n"), data_ptr->num, data_ptr->family, data_ptr->points); card = data_ptr; } } if(!card) card = lowest; return card; } GList *game_get_cards(GList *from, int family, int betterthan) { GList *tmp; GList *to = NULL; struct _card *card; for(tmp = from; tmp; tmp = tmp->next) { card = tmp->data; if(card->family == family && card->points > betterthan ) to = g_list_prepend(to, (gpointer) card); } return(to); } int get_card_num_trump(int num) { switch(num) { case 10: num = 7; break; case 8: num = 6; break; case 0: num = 5; break; case 9: num = 4; break; case 11: case 12: num -= 9; break; case 6: case 7: num -= 6; break; } return(num); } int get_card_num_nottrump(int num) { if(num > 9) num -= 7; else if(num == 9) num = 6; else if(num == 0) num = 7; else num -= 6; return(num); } int game_card_get_ordered_num(struct _card *card, int family) { int num; if(card->family == family) { num = get_card_num_trump(card->num); } else { num = get_card_num_nottrump(card->num); } return(num); } struct _card* game_ia_choose_last_or_first(GList *from, struct _prog *prog_data) { struct _card *theone = NULL, *first = g_list_first(prog_data->waiting)->data; gboolean best = FALSE; int n = g_list_length(prog_data->waiting); theone = g_list_last(from)->data; if(theone) best = game_card_is_best_remaining(prog_data, theone); switch(n) { case 1: if(theone->family != first->family) { if(best) theone = g_list_first(from)->data; } else if(!best) theone = g_list_first(from)->data; break; case 2: if(theone->family != first->family) { if(best == TRUE || game_check_cardisbetter(theone, prog_data->waiting, prog_data->family) == FALSE) theone = g_list_first(from)->data; } else /* We don't have the best card */ if(best == FALSE) { best = game_card_is_best_remaining(prog_data, first); if(best == FALSE) theone = g_list_first(from)->data; } else { best = game_check_cardisbetter(theone, prog_data->waiting, prog_data->family); if(!best) theone = g_list_first(from)->data; } break; case 3: /* We need to drop a trump on a non-trump hand */ if(theone->family != first->family) { /* If we have the best of remaining trumps, * then play the lowest allowed trump we have. * That means we win the hand anyway. */ if(best) theone = g_list_first(from)->data; /* Otherwise play the best trump we have. */ } else { best = game_check_cardisbetter(theone, prog_data->waiting, prog_data->family); if(best == FALSE && prog_data->menext%2 != prog_data->player%2) theone = g_list_first(from)->data; } break; } return(theone); } GList * game_get_valid_cards(struct _prog *prog_data) { GList *good = NULL; gboolean trumpforce; int best = 0, family = -1; struct _card *first = NULL; first = game_get_best(&best, &family, prog_data->family, prog_data->waiting); if(first && first->family >= 0) { if(prog_data->output) fprintf(prog_data->output, _("player %d, trump %d, family of the first card: %d\n"), prog_data->player, prog_data->family, first->family); /* Get a list of cards allowed to * be dropped by the rules. * The first card is not a trump one. */ if(first->family != prog_data->family) { good = game_get_cards(prog_data->players[prog_data->player], first->family, 0); if(good && prog_data->output) fprintf(prog_data->output, _("Not a trump card\n") ); } if(good == NULL) { trumpforce = first->family == prog_data->family || prog_data->menext%2!= prog_data->player%2; /* We must play a trump card, * because we don't have any * card from the first card * family, or the first card * family is a trump one. */ if(family == prog_data->family && trumpforce == TRUE) { /* The best card is a trump card, * we must play bigger */ good = game_get_cards(prog_data->players[prog_data->player], family, best); if(good && prog_data->output) fprintf(prog_data->output, _("A bigger trump\n") ); } if(!good && trumpforce == TRUE ) { /* we don't have any bigger * trump or don't have to * play bigger, drop any * trump */ good = game_get_cards(prog_data->players[prog_data->player], prog_data->family, 0); if(good && prog_data->output) fprintf(prog_data->output, _("A lower trump\n") ); } } } return(good); } /* game_ia_select_card: what the computer should * play. This is where every decision should be * made. * * * Note: the rules of the game should be excluded * from here and put on another function, because * the human player is also affected by the rules. * --Need to be Fixed-- */ struct _card* game_ia_select_card(struct _prog *prog_data) { int nb=0; struct _card *theone = NULL; GList *good = NULL; if(prog_data->waiting != NULL) { good = game_get_valid_cards(prog_data); if(good) { good = g_list_sort(good, list_sort); theone = game_ia_choose_last_or_first(good, prog_data); g_list_free(good); } else { /* Any card is good */ if(prog_data->output) fprintf(prog_data->output, _("Anything\n") ); theone = game_ia_choose_any(prog_data); } } else { theone = game_ia_choose_first(prog_data); } return(theone); } /* game_start: makes the main list * of cards, called the pile. * That's where we take care of * preparing that pile and the * status of each card before * starting a new round. */ void game_start(struct _prog *prog_data) { int i; for(i = 0; i<2; i++) prog_data->declarations[i] = 0; throw_card_list( prog_data->all ); throw_cards(prog_data); prog_data->state = READY_PILE; prog_data->turn = 8; gtk_button_set_label(GTK_BUTTON(prog_data->allwidgets[2]), _("Start") ); gtk_image_set_from_pixbuf(GTK_IMAGE(prog_data->allwidgets[5]), prog_data->icons[4]); gtk_label_set_text(GTK_LABEL(prog_data->allwidgets[7]), _("N/a") ); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[8]), _("None") ); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[18]), NULL); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[19]), NULL); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[3]), NULL); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[4]), NULL); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[20]), NULL); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[21]), NULL); gtk_widget_set_sensitive(prog_data->allwidgets[2], TRUE); for(i =0; i< 4; i++) gtk_widget_set_sensitive(prog_data->allwidgets[10+i], FALSE); } int game_points_carre(int num) { int points = 0; switch(num) { case 12: case 11: case 9: case 0: points = 100; break; case 10: points = 200; break; case 8: points = 150; break; } return(points); } int game_check_carre(GList *lst, int num) { int points = 0, i; for(i=0;lst;lst = lst->next) { if( ((struct _card *)lst->data)->num == num ) i++; } if(i == 4) { points = game_points_carre(num); } return(points); } void game_check_sequence_valid(GList **plst, int cards, int higher, int family) { struct _sequence *sequence = NULL; if(cards > 2) { sequence = (struct _sequence *)g_malloc(sizeof(struct _sequence) ); if(sequence) { sequence->hinum = higher; sequence->family = family; if(cards >= 5) { sequence->points = 100; } else if(cards == 4) sequence->points = 50; else sequence->points = 20; *plst = g_list_prepend(*plst, (gpointer) sequence); /* a sequence of 8 cards is counted as a * quint (five cards) and a tierce (three) */ if(cards == 8) { struct _sequence *onemore = (struct _sequence *) g_malloc(sizeof(struct _sequence) ); if(onemore) { onemore->hinum = higher-5; onemore->family = family; onemore->points = 20; *plst = g_list_prepend(*plst, (gpointer) onemore); } } } } } void game_check_sequence(GList *lst, GList **seqlist) { int bits[4][8] = { {0} }, num; struct _card *data; for(;lst; lst=lst->next) { data = lst->data; if(data->num == 0) num = 7; else num = data->num-6; bits[data->family][num] = 1; } int i, j, cards, higher; for(j = 0; j < 4; j++) { cards = 0; higher = 0; for(i = 7; i>= 0; i--) { if(bits[j][i] == 1) { if(i > higher) higher = i; cards++; } else { game_check_sequence_valid(seqlist, cards, higher, j); higher = 0; cards = 0; } } game_check_sequence_valid(seqlist, cards, higher, j); } } int game_check_carre_x(GList **players, int num) { int i; for(i = 0; i< 4; i++) { if(game_check_carre(players[i], num) > 0) return(i); } return(-1); } void game_show_seqcards(GList *seqlist, GList *player) { GList *tmp; struct _sequence *data; int ncards, i, num, cardnum; for(tmp = seqlist; tmp; tmp = tmp->next) { data = (struct _sequence*) tmp->data; switch(data->points) { case 20: ncards = 3; break; case 50: ncards = 4; break; case 100: ncards = 5; break; default: ncards = 0; } num = data->hinum + 6; for(i = 0; i < ncards; i++) { if(num-i == 13) cardnum = 0; else cardnum = num-i; set_draw_face_x(player, TRUE, data->family, cardnum); } } } void game_check_declarations(struct _prog *prog_data) { int p, points[4] = {0}, bestteam = -1; /* Four Jacks */ p = game_check_carre_x(prog_data->players, 10); if(p > -1) { if(bestteam == -1) bestteam = p%2; if(prog_data->output) fprintf(prog_data->output, _("Four Jacks (%d)\n"), p); points[p] += game_points_carre(10); if(bestteam == p%2) set_show_carre(prog_data->players[p], TRUE, 10); } /* Four Nines */ p = game_check_carre_x(prog_data->players, 8); if(p > -1) { if(bestteam == -1) bestteam = p%2; if(prog_data->output) fprintf(prog_data->output, _("Quads of Nines (%d)\n"), p); points[p] += game_points_carre(8); if(bestteam == p%2) set_show_carre(prog_data->players[p], TRUE, 8); } /* Four Aces */ p = game_check_carre_x(prog_data->players, 0); if(p > -1) { if(bestteam == -1) bestteam = p%2; if(prog_data->output) fprintf(prog_data->output, _("Quads of Aces (%d)\n"), p); points[p] += game_points_carre(0); if(bestteam == p%2) set_show_carre(prog_data->players[p], TRUE, 0); } /* Four Kings */ p = game_check_carre_x(prog_data->players, 12); if(p > -1) { if(bestteam == -1) bestteam = p%2; if(prog_data->output) fprintf(prog_data->output, _("Quads of Kings (%d)\n"), p); points[p] += game_points_carre(12); if(bestteam == p%2) set_show_carre(prog_data->players[p], TRUE, 12); } /* Four Queens */ p = game_check_carre_x(prog_data->players, 11); if(p > -1) { if(bestteam == -1) bestteam = p%2; if(prog_data->output) fprintf(prog_data->output, _("Quads of Queens (%d)\n"), p); points[p] += game_points_carre(11); if(bestteam == p%2) set_show_carre(prog_data->players[p], TRUE, 11); } /* Four Tens */ p = game_check_carre_x(prog_data->players, 9); if(p > -1) { if(bestteam == -1) bestteam = p%2; if(prog_data->output) fprintf(prog_data->output, _("Quads of Tens (%d)\n"), p); points[p] += game_points_carre(9); if(bestteam == p%2) set_show_carre(prog_data->players[p], TRUE, 9); } /* List of sequences now */ GList *seqlist[4] = {NULL}; int i; for(i = 0; i<4; i++) game_check_sequence(prog_data->players[i], &seqlist[i]); /* Check results */ GList *tmp; struct _sequence *data; int bestpoints=0, bestseqfamily = -1, higher = 0, tmpteam = -1; for(i=0; i<4 ; i++) { for(tmp = seqlist[i]; tmp; tmp = tmp->next) { data = (struct _sequence*) tmp->data; if(prog_data->output) { fprintf(prog_data->output, _("Player %d has a straight (points: %d, color: %d, higher: %d)\n"), i, data->points, data->family, data->hinum); } points[i] += data->points; if(data->points > bestpoints) { bestpoints = data->points; bestseqfamily = data->family; tmpteam = i%2; higher = data->hinum; } else if(data->points == bestpoints) { if(data->hinum > higher) { higher = data->hinum; bestseqfamily = data->family; tmpteam = i%2; } else if(data->hinum == higher) { /* Higher Trump */ if(data->family == prog_data->family) { bestpoints = data->points; bestseqfamily = data->family; tmpteam = i%2; } /* Equality canceled */ else if(tmpteam == !(i%2)) tmpteam = -1; } } } } if(bestteam!=-1) tmpteam = bestteam; if(tmpteam !=-1) { char text[10]; prog_data->declarations[tmpteam] = points[tmpteam] + points[tmpteam+2]; g_sprintf(text, "+%d", prog_data->declarations[tmpteam]); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[18 + tmpteam]), text); if(prog_data->output) fprintf(prog_data->output, _("Team %d has the best declaration(s)\n"), tmpteam); prog_data->hide = TRUE; if(tmpteam == 0) game_show_seqcards(seqlist[0], prog_data->players[0]); else { game_show_seqcards(seqlist[1], prog_data->players[1]); game_show_seqcards(seqlist[3], prog_data->players[3]); } } /* Clear all */ for(i = 0; i< 4; i++) { free_generic_list(&seqlist[i]); } } /* game_totalcards: calculate the * total value of points in a GList. */ int game_totalcards(GList *lst) { int total = 0; struct _card *data; while(lst) { data = lst->data; /* Warning: the points value of cards * are not set to the real value * of the card in the game, but at * a more powerfull value. * The real value is [value/10] */ total += data->points/10; lst = lst->next; } return(total); } /* game_restart: reset state and int values * of the game before each new rounds. */ void game_restart(struct _prog *prog_data) { prog_data->state = LOADING; prog_data->player = -1; prog_data->master = -1; prog_data->family = -1; prog_data->hashand = -1; prog_data->menext = -1; prog_data->belote = -1; } /* game_turn: so complicated. * --Need to be simplified-- */ void game_turn(struct _prog *prog_data, struct _card *card) { int cardnb; if(prog_data->player == prog_data->hashand) { if(prog_data->waiting != NULL) { char str[10]; if(prog_data->output) fprintf(prog_data->output, _("dropping the cards on the middle\n") ); clear_blink(prog_data); g_sprintf(str, "%d/8", (9-prog_data->turn) ); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[8]), str); game_drop_middle(prog_data); g_sprintf(str, "%d", game_totalcards(prog_data->teams[0]) ); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[20]), str); g_sprintf(str, "%d", game_totalcards(prog_data->teams[1]) ); gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[21]), str); if(prog_data->menext >= 0) { prog_data->hashand = prog_data->menext; prog_data->player = prog_data->menext; } } } if(prog_data->turn > 0) { if(card == NULL && prog_data->player != 2) { card = game_ia_select_card(prog_data); } if(card != NULL) { if(prog_data->output != NULL) { fprintf(prog_data->output, _("Player %d drop card "), prog_data->player); game_print_card(prog_data->output, card); fprintf(prog_data->output, "\n"); } if(prog_data->waiting != NULL && game_check_cardisbetter(card, prog_data->waiting, prog_data->family)) { if(prog_data->output != NULL) fprintf(prog_data->output, _("Player %d has the hand\n"), prog_data->player); prog_data->menext = prog_data->player; } throw_to(&prog_data->waiting, card); card->draw_face = TRUE; card->moveable = FALSE; if(card->family == prog_data->family) { if(card->points == 40) { /* Look for the trump queen, * because this player just dropped * the trump king. * If he got both, then it's a "Belote" * and 20 points goes to the team. */ if(game_find_card(card->family, 11, prog_data->players[prog_data->player]) == TRUE) { gtk_label_set_text( GTK_LABEL( prog_data->allwidgets[3+(prog_data->player%2)]), "+20"); gtk_label_set_text(GTK_LABEL(prog_data->allwidgets[6]), _("Belote!")); prog_data->belote = prog_data->player; } } else if(card->points == 30) { if( prog_data->belote == prog_data->player) gtk_label_set_text(GTK_LABEL(prog_data->allwidgets[6]), _("Rebelote!")); } } prog_data->players[prog_data->player] = g_list_remove( prog_data->players[prog_data->player], (gconstpointer) card); game_hand_position(prog_data, prog_data->player); game_position_middle(card, prog_data, prog_data->player); select_player_next(&prog_data->player); if(prog_data->player == 2) { set_player_hand_moveable(prog_data); } else { set_moveable(prog_data->players[2], FALSE); } if(prog_data->player == prog_data->hashand) { struct _card *card = NULL; int player; int i; if(prog_data->menext == 2) { set_moveable(prog_data->players[2], TRUE); } else { set_moveable(prog_data->players[2], FALSE); } if(prog_data->waiting) { /* now find the number of the card (from 0 to 3) * which is the best card in the list. * This is pretty hard to know : * Get the player who dropped the first * card and increment i till player == menext * Because menext is the winner player * of this turn. */ player = prog_data->hashand; select_player_prev(&player); if(prog_data->output) fprintf(prog_data->output, "hashand %d, menext %d\n", prog_data->hashand, prog_data->menext); for(i = 0; player != prog_data->menext ; i++) { select_player_prev(&player); } card = throw_card_x(prog_data->waiting, i); if(card && !prog_data->copy) { card->blink = TRUE; card->draw = FALSE; draw_copy(prog_data); prog_data->blinkid = g_timeout_add(800, event_blink, (gpointer)prog_data); } } prog_data->turn--; if(prog_data->turn <= 0) { gtk_widget_set_sensitive(prog_data->allwidgets[2], TRUE); gtk_button_set_label(GTK_BUTTON(prog_data->allwidgets[2]), "Finish"); } } } } else { int Pts[2]; char str[5]; GtkWidget *cell; int masterteam = prog_data->master%2; prog_data->state = ENDGAME; set_moveable(prog_data->players[2], FALSE); Pts[0] = game_totalcards(prog_data->teams[0]); Pts[1] = game_totalcards(prog_data->teams[1]); /* Belote */ if( prog_data->belote != -1 ) { if(prog_data->output != NULL) fprintf(prog_data->output, _("Team %d wins 20 points for Belote/Rebelote\n"), (prog_data->belote%2)); Pts[prog_data->belote%2] += 20; } /* Declarations */ if(prog_data->withdeclaration == TRUE) { if(prog_data->output) { fprintf(prog_data->output, _("Your team wins %d points for declarations\n"), prog_data->declarations[0]); fprintf(prog_data->output, _("The other team wins %d points for declarations\n"), prog_data->declarations[1]); } if(Pts[0] > 0) Pts[0] += prog_data->declarations[0]; if(Pts[1] > 0) Pts[1] += prog_data->declarations[1]; } /* Final turn winner's team wins Ten points */ Pts[prog_data->menext%2] += 10; if(prog_data->output != NULL) { fprintf(prog_data->output, _("Total: [0,2] %d (your) versus (them) %d [1,3]\n"), Pts[0], Pts[1]); fprintf(prog_data->output, _("master was %d, menext is %d\n"), (prog_data->master), prog_data->menext ); } int Totals[2]={Pts[0], Pts[1]}; Pts[0] = (int)roundf(Pts[0]/(float)10); Pts[1] = (int)roundf(Pts[1]/(float)10); if(Totals[masterteam] >= Totals[!masterteam]) { /* Points of the master team are reported */ if(Totals[masterteam] == Totals[!masterteam]) { if(prog_data->output) { fprintf(prog_data->output, _("Equality. Points of the master team(%d) are reported.\n%d points, (%d total)\n"), prog_data->master, Pts[masterteam], prog_data->report); } prog_data->report += Pts[masterteam]; Pts[masterteam] = 0; } /* If the other team is Capot! */ if(Pts[!masterteam] == 0) { Pts[masterteam] += 9 +prog_data->report ; prog_data->report = 0; } } /* Couille ! */ else { /* Do we have to add all the points to the winning team, * even the "Belote/Rebelote" thing ?*/ Pts[!masterteam] += prog_data->report + Pts[masterteam]; Pts[masterteam] = 0; prog_data->report = 0; } prog_data->points[0] += Pts[0]; prog_data->points[1] += Pts[1]; prog_data->row++; gtk_table_resize(GTK_TABLE(prog_data->allwidgets[9]), prog_data->row, 2); g_sprintf(str, "%d", prog_data->points[0]); cell = gtk_label_new(str); prog_data->cells = g_list_prepend(prog_data->cells, (gpointer) cell ); gtk_table_attach_defaults(GTK_TABLE(prog_data->allwidgets[9]), cell, 0, 1, prog_data->row-1, prog_data->row); g_sprintf(str, "%d", prog_data->points[1]); cell = gtk_label_new(str); prog_data->cells = g_list_prepend(prog_data->cells, (gpointer) cell ); gtk_table_attach_defaults(GTK_TABLE(prog_data->allwidgets[9]), cell, 1, 2, prog_data->row-1, prog_data->row); GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(prog_data->allwidgets[1]) ); gtk_adjustment_set_value(adjustment, adjustment->upper); if(Pts[0] > Pts[1]) gtk_label_set_text(GTK_LABEL(prog_data->allwidgets[6]), "You Win"); else gtk_label_set_text(GTK_LABEL(prog_data->allwidgets[6]), "Computer Wins"); gtk_widget_show_all(prog_data->allwidgets[0]); if((prog_data->points[0] > 100 || prog_data->points[1] > 100) && prog_data->points[0] != prog_data->points[1]) { GtkWidget *dialog; char winstr[50]; if(prog_data->points[0] > prog_data->points[1]) g_stpcpy(winstr, _("Congratulation, you won this game!")); else g_stpcpy(winstr, _("Sorry, you have lost this game!")); if(prog_data->output) fprintf(prog_data->output, _("\nEnd of the game !!\n\n\n")); dialog = gtk_message_dialog_new( GTK_WINDOW(prog_data->allwidgets[0]), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, winstr, NULL); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(dialog_response_event), prog_data); gtk_widget_show_all(dialog); } if(prog_data->allwidgets && prog_data->allwidgets[5]) { if(gtk_image_get_pixbuf(GTK_IMAGE(prog_data->allwidgets[5]))) gtk_image_clear(GTK_IMAGE(prog_data->allwidgets[5]) ); } gtk_label_set_text( GTK_LABEL(prog_data->allwidgets[8]), "None"); free_clear(prog_data); game_restart(prog_data); game_start(prog_data); } } void game_count_cards(GList *lst, int family, int *pointstrump, int *pointsnottrump, int *counttrump, int *countnottrump, int *best) { struct _card *card; int points; while(lst) { card = (struct _card *)lst->data; if( card->family == family) { points = set_master_points(card->num); if(points > *best) *best = points; *pointstrump += points; (*counttrump)++; } else { *pointsnottrump += set_notmaster_points(card->num); (*countnottrump)++; } lst = lst->next; } } gboolean game_ia_select_second(struct _prog *prog_data, int player, int *family) { gboolean select = FALSE; struct _card *card = ((struct _card*)prog_data->waiting->data); int pointstrump = 0, pointsnottrump = 0, counttrump = 0, countnottrump = 0, best = 0, i; for(i=0; i<4; i++) { if(i != card->family) { pointstrump = 0; pointsnottrump = 0; counttrump = 0; countnottrump = 0; best = 0; game_count_cards(prog_data->players[player], i, &pointstrump, &pointsnottrump, &counttrump, &countnottrump, &best); if(counttrump > 1) { pointsnottrump += set_notmaster_points(card->num); /* from 140 to 225 * lesser means more crazyness */ if(pointstrump >= 225) { if(prog_data->output) fprintf(prog_data->output, "Player %d is susceptible to choose the family %d [%d, %d]\n", prog_data->player, i, pointsnottrump, pointstrump); if( pointsnottrump+pointstrump > 270 && (pointsnottrump/countnottrump) + (pointstrump/counttrump) >= 60 && best >= 110) { *family = i; select = TRUE; i = 3; } } } } } return(select); } /* */ gboolean game_ia_select_trump(struct _prog *prog_data, int player) { gboolean select = FALSE; struct _card *card = ((struct _card*)prog_data->waiting->data); int pointstrump = 0, pointsnottrump = 0, counttrump = 0, countnottrump = 0, best = 0; game_count_cards(prog_data->players[player], card->family, &pointstrump, &pointsnottrump, &counttrump, &countnottrump, &best); if(counttrump > 1) { pointstrump += set_master_points(card->num); /* from 140 to 225 * lesser means more crazyness */ if(pointstrump >= 225) { if(prog_data->output) fprintf(prog_data->output, "Player %d is susceptible to take the card [%d],[%d]\n", prog_data->player, pointsnottrump, pointstrump); if( pointsnottrump+pointstrump > 270 && (pointsnottrump/countnottrump) + (pointstrump/counttrump) >= 60 && best >= 110) { select = TRUE; } } } return(select); } /* */ void game_choose_trump_next(struct _prog *prog_data) { gboolean play = FALSE; int player, trump, i, family; select_player_next(&prog_data->player); for(i =0; i< 4; i++) { if(prog_data->player != prog_data->menext) { if(prog_data->output != NULL) { fprintf(prog_data->output, "Computer turn to choose (%d)\n", prog_data->player); } if(prog_data->state == READY_DISTRIB1) play = game_ia_select_trump(prog_data, prog_data->player); else play = game_ia_select_second(prog_data, prog_data->player, &family); if(play == TRUE) { player = prog_data->player; if(prog_data->state == READY_DISTRIB1) trump = ((struct _card *)prog_data->waiting->data)->family; else trump = family; i = 3; } else select_player_next(&prog_data->player); } else i = 3; } if(play == TRUE) { click_selectmaster(prog_data, player, trump); } else { if(prog_data->state == READY_DISTRIB1) { if(prog_data->output != NULL) { fprintf(prog_data->output, "No one want this trump, second pass\n"); } prog_data->state = EGS_SECOND; game_choose_trump(prog_data); } else { if(prog_data->output != NULL) { fprintf(prog_data->output, "No one seems to want this card, restart!\n"); } free_clear(prog_data); game_restart(prog_data); game_start(prog_data); } } } /* game_choose_trump : first phase of the game, * we need to select the trump. */ void game_choose_trump(struct _prog *prog_data) { int i, j, trump, family; if(prog_data->output != NULL) { fprintf(prog_data->output, "Please choose trump\n"); } trump = ((struct _card*)prog_data->waiting->data)->family; for(i = 0; i < 4; i++) { if(prog_data->player == 2) { i = 5; if(prog_data->output != NULL) { fprintf(prog_data->output, "It's your turn to choose!\n"); } if(prog_data->state == READY_DISTRIB1) { gtk_widget_set_sensitive(prog_data->allwidgets[2], TRUE); gtk_widget_set_sensitive(prog_data->allwidgets[10+trump], TRUE); } else { for(j=0; j<4; j++) { if(j != trump) gtk_widget_set_sensitive(prog_data->allwidgets[10+j], TRUE); } } } else { if(prog_data->output != NULL) { fprintf(prog_data->output, "Computer turn to choose (%d)\n", prog_data->player); } if( prog_data->state == READY_DISTRIB1 && game_ia_select_trump(prog_data, prog_data->player) == TRUE) { click_selectmaster(prog_data, prog_data->player, trump); i=5; } else if( prog_data->state == EGS_SECOND && game_ia_select_second(prog_data, prog_data->player, &family) == TRUE ) { click_selectmaster(prog_data, prog_data->player, family); i=5; } else select_player_next(&prog_data->player); } } }