int ft_parse_file(int fd, struct s_params *par, t_piece *pieces) { char current_piece[21]; t_tetro *tetro[MAX_PIECES]; while ((par->lus = GET_PIECE(fd, current_piece))) { par->line_at_end = 0; if (!(tetro[par->cpt] = (t_tetro *)malloc(sizeof(t_tetro) * 4))) return (ERROR_ALLOCATION); current_piece[par->lus] = '\0'; if ((par->cpt >= 26) \ || !(ft_verif_piece(current_piece, &pieces[par->cpt]))) return (INVALID_DESCRIPTION); par->lus = READ_NL(fd, current_piece); current_piece[par->lus] = '\0'; if (par->lus && current_piece[0] != '\n') return (INVALID_DESCRIPTION); par->line_at_end = (par->lus != 0) ? 1 : 0; par->cpt++; } if (par->line_at_end) { current_piece[par->lus] = '\0'; return (INVALID_DESCRIPTION); } return (1); }
int prep_available(QuartoBoard *board, int *available) { for(int i = 0; i < 16; i++){ //Because C doesn't like to place information in a new array //we need to do it explicit to ensure that none of the elements //are 0 by default available[i] = 1; } QuartoPiece tmp; int res = 16; for(int i = 0; i < 4; i++){ for(int j = 0; j < 4; j++){ tmp = GET_PIECE(i, j, board->board); if(is_valid_piece(&tmp)){ available[tmp.piece] = 0; res--; } } } return res; }
int maxValue(QuartoPiece a, QuartoBoard *board, MinimaxRes *res, int numPly, int alpha, int beta) { int local_alpha = -10000000; for(int i = 0; i < 4; i++){ for(int j = 0; j < 4; j++){ if(!is_valid_piece(&GET_PIECE(j, i, board->board))){ QuartoBoard newB = *board; set_piece(&newB, j, i, &a); int won = quarto_win(&newB); if(newB.size == 16){ //This placement filled up the board which means that //we can't go further down so we just update the x, j //and return the value of this end state res->x = j; res->y = i; return won*100; }else if(won){ //This is the maximum we can get, which means that we won the game //no reason to go further down since this lead to a victory res->x = j; res->y = i; return 100; }else if(numPly == 0){ //We have reached the bottom of the recursion //and we need only evaluate the possible placements //of the piece that we have gotten int quarto_value = quarto_herustic(&newB); if(quarto_value > local_alpha){ local_alpha = quarto_value; res->x = j; res->y = i; } if(local_alpha >= beta) return local_alpha; }else{ int pieces_left[16]; //Array with 0 or 1 to indicate if the pieces //in that index is available prep_available(&newB, pieces_left); for(int k = 0; k < 16; k++){ if(pieces_left[k]){ MinimaxRes r; int value = minValue(create_piece_from_int(k), &newB, &r, numPly-1, local_alpha, beta); if(value > local_alpha){ //The value we got from below is better //than what we have currently found //which means we need to keep this //position and update our alpha res->x = j; res->y = i; res->next_piece = k; local_alpha = value; } //If alpha is lager than beta there is //no use continuing because the min node above //will always chose the path that lead to beta if(local_alpha >= beta) return local_alpha; } } } } } } return local_alpha; }
int quarto_gloss(QuartoBoard *board) { TriplePiece tps[10]; int size = 0; for(int i = 0; i < 4; i++){ TriplePiece tp; //Horizontal if (pieces_triple(board, &GET_PIECE(0,i, board->board), &GET_PIECE(1,i, board->board), &GET_PIECE(2,i, board->board), &GET_PIECE(3,i, board->board), &tp)) { tps[size] = tp; size++; } //Vertical TriplePiece tp2; if (pieces_triple(board, &GET_PIECE(i,0, board->board), &GET_PIECE(i,1, board->board), &GET_PIECE(i,2, board->board), &GET_PIECE(i,3, board->board), &tp2)) { tps[size] = tp2; size++; } } TriplePiece tp3; if (pieces_triple(board, &GET_PIECE(0,0, board->board), &GET_PIECE(1,1, board->board), &GET_PIECE(2,2, board->board), &GET_PIECE(3,3, board->board), &tp3)) { tps[size] = tp3; size++; } TriplePiece tp4; if (pieces_triple(board, &GET_PIECE(0,3, board->board), &GET_PIECE(1,2, board->board), &GET_PIECE(2,1, board->board), &GET_PIECE(3,0, board->board), &tp4)) { tps[size] = tp4; size++; } for(int i=0; i<size-1; i++) { for(int j=i+1; j<size; j++) { QuartoPiece *a1 = tps[i].a; QuartoPiece *a2 = tps[j].a; QuartoPiece *b1 = tps[i].b; QuartoPiece *b2 = tps[j].b; QuartoPiece *c1 = tps[i].c; QuartoPiece *c2 = tps[j].c; int val1 = (a1->piece & b1->piece & c1->piece); int val2 = (a2->piece & b2->piece & c2->piece); int xor1 = (a1->xor & b1->xor & c1->xor); int xor2 = (a2->xor & b2->xor & c2->xor); if (val1 == xor2) { return 1; } else if (val2 == xor1) { return 1; } } } return 0; }
int quarto_triple_neg(QuartoBoard *board) { int numTrips = 0; int avail[16]; int num_pieces_left = prep_available(board, avail); TriplePiece tp; for(int i = 0; i < 4; i++){ //Horizontal int horiz_pieces = pieces_triple(board, &GET_PIECE(0,i, board->board), &GET_PIECE(1,i, board->board), &GET_PIECE(2,i, board->board), &GET_PIECE(3,i, board->board), &tp); if(horiz_pieces > 0){ int diff = num_pieces_left - horiz_pieces; if(diff % 2 == 0){ //Since there are an even number of pieces which //will not fit into the available third spot //The opponent will force us to give him a winning //piece numTrips++; } } //Vertical int vert_pieces = pieces_triple(board, &GET_PIECE(i,0, board->board), &GET_PIECE(i,1, board->board), &GET_PIECE(i,2, board->board), &GET_PIECE(i,3, board->board), &tp); if(vert_pieces > 0){ //See logic above int diff = num_pieces_left - vert_pieces; if(diff % 2 == 0){ numTrips++; } } } int cross_pieces = pieces_triple(board, &GET_PIECE(0,0, board->board), &GET_PIECE(1,1, board->board), &GET_PIECE(2,2, board->board), &GET_PIECE(3,3, board->board), &tp); if(cross_pieces > 0){ //See logic above int diff = num_pieces_left - cross_pieces; if(diff % 2 == 0){ numTrips++; } } int cross2_pieces = pieces_triple(board, &GET_PIECE(0,3, board->board), &GET_PIECE(1,2, board->board), &GET_PIECE(2,1, board->board), &GET_PIECE(3,0, board->board), &tp); if(cross2_pieces > 0){ //See logic above int diff = num_pieces_left - cross2_pieces; if(diff % 2 == 0){ numTrips++; } } return numTrips; }
int quarto_triple_pos(QuartoBoard *board) { int numTrips = 0; int avail[16]; int num_pieces_left = prep_available(board, avail); TriplePiece tp; for(int i = 0; i < 4; i++){ //Horizontal int horiz_pieces = pieces_triple(board, &GET_PIECE(0,i, board->board), &GET_PIECE(1,i, board->board), &GET_PIECE(2,i, board->board), &GET_PIECE(3,i, board->board), &tp); if(horiz_pieces > 0){ int diff = num_pieces_left - horiz_pieces; if(diff % 2 != 0){ //Since there is an odd number of pieces which can not //complete the triple we found we might be able to //force our opponent to give us a piece which we //can win with numTrips++; } } //Vertical int vert_pieces = pieces_triple(board, &GET_PIECE(i,0, board->board), &GET_PIECE(i,1, board->board), &GET_PIECE(i,2, board->board), &GET_PIECE(i,3, board->board), &tp); if(vert_pieces > 0){ //See logic above int diff = num_pieces_left - vert_pieces; if(diff % 2 != 0){ numTrips++; } } } int cross_pieces = pieces_triple(board, &GET_PIECE(0,0, board->board), &GET_PIECE(1,1, board->board), &GET_PIECE(2,2, board->board), &GET_PIECE(3,3, board->board), &tp); if(cross_pieces > 0){ //See logic above int diff = num_pieces_left - cross_pieces; if(diff % 2 != 0){ numTrips++; } } int cross2_pieces = pieces_triple(board, &GET_PIECE(0,3, board->board), &GET_PIECE(1,2, board->board), &GET_PIECE(2,1, board->board), &GET_PIECE(3,0, board->board), &tp); if(cross2_pieces > 0){ //See logic above int diff = num_pieces_left - cross2_pieces; if(diff % 2 != 0){ numTrips++; } } return numTrips; }
int quarto_win(QuartoBoard *board) { for(int i = 0; i < 4; i++){ //Horizontal if(pieces_equal(&GET_PIECE(0,i, board->board), &GET_PIECE(1,i, board->board), &GET_PIECE(2,i, board->board), &GET_PIECE(3,i, board->board))){ return 1; } //Vertical if(pieces_equal(&GET_PIECE(i,0, board->board), &GET_PIECE(i,1, board->board), &GET_PIECE(i,2, board->board), &GET_PIECE(i,3, board->board))){ return 1; } } if(pieces_equal(&GET_PIECE(0,0, board->board),&GET_PIECE(1,1, board->board), &GET_PIECE(2,2, board->board), &GET_PIECE(3,3, board->board))){ return 1; } if(pieces_equal(&GET_PIECE(0,3, board->board),&GET_PIECE(1,2, board->board), &GET_PIECE(2,1, board->board), &GET_PIECE(3,0, board->board))){ return 1; } return 0; }
int minValue(QuartoPiece a, QuartoBoard *board, MinimaxRes *res, int numPly, int alpha, int beta) { int local_beta = 1000000; for(int i = 0; i < 4; i++){ for(int j = 0; j < 4; j++){ if(!is_valid_piece(&GET_PIECE(j, i, board->board))){ QuartoBoard newB = *board; set_piece(&newB, j, i, &a); int won = quarto_win(&newB); if(newB.size == 16){ //This placement filled up the board which means that //we can't go further down so we just update the x, j //and return the value of this end state res->x = j; res->y = i; return won*-100; }else if(won){ //This is the maximum we can get, which means that we won the game //no reason to go further down since this lead to a victory res->x = j; res->y = i; return -100; }else if(numPly == 0){ //We have reached the bottom of the recursion //and we need only evaluate the possible placements //of the piece that we have gotten int quarto_value = quarto_herustic(&newB)*(-1); if(quarto_value < local_beta){ local_beta = quarto_value; res->x = j; res->y = i; } if(local_beta <= alpha) return local_beta; }else{ int pieces_left[16]; //Array with 0 or 1 to indicate if the pieces //in that index is available prep_available(&newB, pieces_left); for(int k = 0; k < 16; k++){ if(pieces_left[k]){ MinimaxRes r; int value = maxValue(create_piece_from_int(k), &newB, &r, numPly-1, alpha, local_beta); if(value < local_beta){ //The value we got from below is smaller //than the best beta we have found which //means we want that, so we need to update //x, y and update beta res->x = j; res->y = i; res->next_piece = k; local_beta = value; } //Our beta value is smaller than alpha //which means that the max "node" above //will always chose the path which leads //to that alpha value and there is no use //in recursing any more if(local_beta <= alpha) return local_beta; } } } } } } return local_beta; }