src/algos.c

Functions

Name
int max_value(int a, int b)return the max value of a and b
int min_value(int a, int b)return the min value of a and b
int max(tree_t * tree, bool player)returns the max/min value of a tree node, depending on the player turn
play_t * max_play(tree_t * tree)return the max play of a tree node
int basic_heuristic(cell_t ** cell_tab)basic heuristic function maximizing the ratio between our cells and the adversary
play_t * choose_play(board_t * board, cell_t ** cell_tab, bool player)returns the best play depending on the player
board_t * apply_play(board_t * board, play_t * play)applies a play to the board
board_t * undo_play(board_t * board, play_t * play)reverts a play to the board
int eval(board_t * board, cell_t ** cell_tab, int depth, int max_depth, bool player, int alpha, int beta)applies the min-max algorithm

Attributes

Name
int play_count
int undo_count

Functions Documentation

function max_value

int max_value(
    int a,
    int b
)

return the max value of a and b

function min_value

int min_value(
    int a,
    int b
)

return the min value of a and b

function max

int max(
    tree_t * tree,
    bool player
)

returns the max/min value of a tree node, depending on the player turn

function max_play

play_t * max_play(
    tree_t * tree
)

return the max play of a tree node

function basic_heuristic

int basic_heuristic(
    cell_t ** cell_tab
)

basic heuristic function maximizing the ratio between our cells and the adversary

function choose_play

play_t * choose_play(
    board_t * board,
    cell_t ** cell_tab,
    bool player
)

returns the best play depending on the player

function apply_play

board_t * apply_play(
    board_t * board,
    play_t * play
)

applies a play to the board

function undo_play

board_t * undo_play(
    board_t * board,
    play_t * play
)

reverts a play to the board

function eval

int eval(
    board_t * board,
    cell_t ** cell_tab,
    int depth,
    int max_depth,
    bool player,
    int alpha,
    int beta
)

applies the min-max algorithm

Attributes Documentation

variable play_count

int play_count = 0;

variable undo_count

int undo_count = 0;

Source code

/* name : algos.c
 * authors : eloi petit, matheo thomas, domitille vale
 * date : 18-06-24
 */

#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "algos.h"
#include "graphics.h"
#include "init.h"
#include "utilities.h"


int play_count = 0;
int undo_count = 0;

int max_value(int a, int b) {
    // printf("max_value\n");
    return a < b ? b : a;
}

int min_value(int a, int b) {
    // printf("min_value\n");
    return a < b ? a : b;
}

int max(tree_t *tree, bool player) {
    // printf("max\n");
    int is_max = player ? 1 : -1;

    tree_t *temp = tree;
    int val_max = tree->value;

    while(temp->next_tree != NULL) {
        if (temp->value * is_max > val_max * is_max) {
            val_max = temp->value;
        }
        temp = temp->next_tree;
    }

    return val_max;
}

play_t *max_play(tree_t *tree) {
    // printf("max_play\n");
    tree_t *tree_max = tree;
    tree_t *temp = tree;
    int val_max = tree->value;

    while(temp->next_tree != NULL) {
        if (temp->value > val_max) {
            tree_max = temp;
            val_max = temp->value;
        }
        temp = temp->next_tree;
    }

    // printf("max play value : %d\n", tree_max->value);
    return tree_max->play;
}

int basic_heuristic(cell_t **cell_tab) {
    // printf("basic_heuristic\n");
    int score;
    int nb_white = 0;
    int nb_black = 0;
    for(int i = 0; i < CELL_NUMBER; i++) {
        if(cell_tab[i]->state == WHITE) {
            nb_white++;
        }
        if(cell_tab[i]->state == BLACK) {
            nb_black++;
        }
    }
    score = nb_white - nb_black;

    return score;
}

// play_t *choose_play(board_t *board, graphics_t *g, cell_t **cell_tab) {
play_t *choose_play(board_t *board, cell_t **cell_tab, bool player) {
    // printf("choose_play\n");
    play_count = 0;
    undo_count = 0;
    tree_t *tree = gen_plays(board, 0, player);
    tree_t *temp = tree;

    if(tree == NULL) {
        // printf("something is null\n");
        return NULL;
    }
    while (temp->next_tree != NULL) {
        // display_board(g->board, g->white, g->white, g->window, g->renderer, cell_tab);
        // SDL_Delay(1000);
        // printf("play : %d\n", temp->play->cell_tab_length);
        if(validity_play(temp->play, player)) {
            temp->value = eval(apply_play(board, temp->play), cell_tab, 0, MAX_DEPTH, !player, INT_MIN, INT_MAX);
            // printf("temp->value : %d\n", temp->value);
            undo_play(board, temp->play);
        }

        temp = temp->next_tree;
    }

    printf("play_count : %d\n", play_count);
    printf("undo_count : %d\n", undo_count);
    return max_play(tree);
}

board_t *apply_play(board_t *board, play_t *play) {
    // printf("apply_play\n");
    play_count++;

    // duplicates the balls
    for(int i = play->cell_tab_length - 1; i >= 0; i--) {
        if(play->cell_tab[i]->neighbor[play->movement_direction] != NULL) {
            play->cell_tab[i]->neighbor[play->movement_direction]->state = play->cell_tab[i]->state;
        } else {
            if (play->cell_tab[i]->state == WHITE) {
                board->n_white -= 1;
            } else if (play->cell_tab[i]->state == BLACK) {
                board->n_black -= 1;
            }
        }
    }

    // removes the old balls that have been duplicated
    if(play->movement_direction == play->cell_direction) {
        play->cell_tab[0]->state = EMPTY;
    } else {
        for(int i = 0; i < play->cell_tab_length; i++) {
            play->cell_tab[i]->state = EMPTY;
        }
    }

    return board;
}

board_t *undo_play(board_t *board, play_t *play) {
    // printf("undo_play\n");
    undo_count++;

    // duplicates the balls
    if(play->cell_tab[play->cell_tab_length - 1]->neighbor[play->cell_direction] == NULL) {
        if (play->buffer[play->cell_tab_length - 1] == WHITE) {
            board->n_white += 1;
        } else if (play->buffer[play->cell_tab_length - 1] == BLACK) {
            board->n_black += 1;
        }
    }

    for(int i = 0; i < play->cell_tab_length; i++) {
        play->cell_tab[i]->state = play->buffer[i];
    }

    // removes the old balls that have been duplicated
    if(play->cell_direction == play->movement_direction) {
        if(play->cell_tab[play->cell_tab_length - 1]->neighbor[play->cell_direction] != NULL) {
            play->cell_tab[play->cell_tab_length - 1]->neighbor[play->cell_direction]->state = EMPTY;
        }
    } else {
        for(int i = 0; i < play->cell_tab_length; i++) {
            if(play->cell_tab[i]->neighbor[play->movement_direction] != NULL) {
                play->cell_tab[i]->neighbor[play->movement_direction]->state = EMPTY;
            }
        }
    }

    return board;
}

int eval(board_t *board, cell_t **cell_tab, int depth, int max_depth, bool player, int alpha, int beta) {
    // printf("eval\n");

    int score = basic_heuristic(cell_tab);
    
    if (max_depth == depth || score == CELL_NUMBER/2 || score == -CELL_NUMBER/2) {
        return score;
    }
    tree_t *tree = gen_plays(board, depth, player);

    if(tree == NULL) {
        return score;
    } else {
        tree_t *temp = tree;

        while(temp->next_tree != NULL) {
            if(validity_play(temp->play, player)) {
                temp->value = eval(apply_play(board, temp->play), cell_tab, depth + 1, max_depth, !player, alpha, beta);
                undo_play(board, temp->play);

                if(player) {
                    alpha = max_value(alpha, temp->value);
                    if(beta <= alpha) {
                        break;
                    }
                } else {
                    beta = min_value(beta, temp->value);
                    if(beta <= alpha) {
                        break;
                    }
                }
            }
            temp = temp->next_tree;
        }

        if(player) {
            return max(tree, !player);
        } else {
            return max(tree, player);
        }
    }
}