src/algos.c
Functions
Name | |
---|---|
play_t * | initialisation(game_t * game, hash_t ** h)Itinialises the root of the tree with the two tiles available. |
float | G(play_t * play) |
float | interest(play_t * play, float c, int n) |
play_t * | ucb(play_t * play, float c, int n) |
play_t * | selection(play_t * play, float c, int n)Selects the play to play. |
play_t * | get_random_tile(linked_plays_t * lp)Returns a random tile from a play list. |
bool | is_game_finished(game_t * game) |
int | calculate_score(game_t * game, bool is_bot) |
int | simulation(play_t * play, hash_t ** h, game_t * game, bool is_bot, bool is_last_node)Simulates the plays and updates their scores. |
play_t * | copy_play(play_t * play) |
play_t * | mcts(game_t * game)Applies the MCTS algorithm for a fixed time. |
Functions Documentation
function initialisation
play_t * initialisation(
game_t * game,
hash_t ** h
)
Itinialises the root of the tree with the two tiles available.
function G
float G(
play_t * play
)
function interest
float interest(
play_t * play,
float c,
int n
)
function ucb
play_t * ucb(
play_t * play,
float c,
int n
)
function selection
play_t * selection(
play_t * play,
float c,
int n
)
Selects the play to play.
function get_random_tile
play_t * get_random_tile(
linked_plays_t * lp
)
Returns a random tile from a play list.
function is_game_finished
bool is_game_finished(
game_t * game
)
function calculate_score
int calculate_score(
game_t * game,
bool is_bot
)
function simulation
int simulation(
play_t * play,
hash_t ** h,
game_t * game,
bool is_bot,
bool is_last_node
)
Simulates the plays and updates their scores.
function copy_play
play_t * copy_play(
play_t * play
)
function mcts
play_t * mcts(
game_t * game
)
Applies the MCTS algorithm for a fixed time.
Source code
/* name : algos.c
* authors : eloi petit, matheo thomas, domitille vale
* date : 23-06-24
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "algos.h"
#include "hash_map.h"
#include "init.h"
#include "utilities.h"
play_t *initialisation(game_t *game, hash_t **h) {
linked_plays_t *lp = game->bot->rocks > 0 ? gen_tiles_from_game(game, true) : gen_tiles(game->bot->cell_tab, game->card_1);
hash_map_add(h, game->bot, lp);
return lp->play;
}
float G(play_t *play) {
return play->gain_coup / (float)play->n_coup;
}
float interest(play_t *play, float c, int n) {
return G(play) + c * sqrtf(logf(n) / play->n_coup);
}
play_t *ucb(play_t *play, float c, int n) {
float temp_interest = 0, interest_max = 0;
play_t *max_play = play;
while (play != NULL) {
temp_interest = interest(play, c, n);
if (temp_interest > interest_max) {
interest_max = temp_interest;
max_play = play;
}
play = play->next;
}
return max_play;
}
play_t *selection(play_t *play, float c, int n) {
play_t *temp = play;
while(temp != NULL) {
if (temp->n_coup == 0) {
break;
}
temp = temp->next;
}
if (temp == NULL) {
// UCB
temp = ucb(play, c, n);
}
return temp;
}
play_t *get_random_tile(linked_plays_t *lp) {
int play_i = rand() % lp->size;
play_t *p = lp->play;
while(play_i > 0) {
p = p->next;
play_i--;
}
return p;
}
bool is_game_finished(game_t *game) {
return game->deck->n == 0 ? true : false;
}
int calculate_score(game_t *game, bool is_bot) {
// if(is_bot) {
// update_scoring_table(game->bot);
// calculate_score_from_table(game->bot);
// } else {
// update_scoring_table(game->player);
// calculate_score_from_table(game->player);
// }
update_scoring_table_rec_false_start(is_bot ? game->bot : game->player);
calculate_score_from_table(is_bot ? game->bot : game->player);
return is_bot ? game->bot->score - game->player->score : game->player->score - game->bot->score;
}
int simulation(play_t *play, hash_t **h, game_t *game, bool is_bot, bool is_last_node) {
linked_plays_t *lp = NULL;
if(is_game_finished(game)) {
return calculate_score(game, is_bot);
}
if(!is_last_node) {
board_t *b = is_bot ? game->bot : game->player;
uint32_t hash_value = hash_board(b);
int hash_index = hash_value % HASHMAP_SIZE;
hash_t *hash_cell = h[hash_index];
while (hash_cell != NULL && hash_cell->hashed_board != hash_value) {
hash_cell = hash_cell->next;
}
if (hash_cell != NULL) { // the node has already been explored before
play_t *new_play = get_random_tile(hash_cell->plays);
// game->deck->n++;
update_deck(game, new_play->tile, NULL);
is_bot ? add_tile_to_board_without_score(game->bot, play->tile) : add_tile_to_board_without_score(game->player, play->tile);
play->n_coup ++;
int temp_score = simulation(new_play, h, game, !is_bot, is_last_node);
play->gain_coup += temp_score;
is_bot ? remove_tile_from_board_without_null_without_score(game->bot, play->tile) : remove_tile_from_board_without_null_without_score(game->player, play->tile);
// UNDO THE DECK
// game->deck->n--;
undo_deck(game, new_play->tile, NULL);
return temp_score;
} else { // first time exploring this node, adding initialisation
if(is_bot) {
lp = game->bot->rocks > 0 ? gen_tiles_from_game(game, true) : gen_tiles(game->bot->cell_tab, game->card_1);
} else {
lp = game->player->rocks > 0 ? gen_tiles_from_game(game, false) : gen_tiles(game->player->cell_tab, game->card_1);
}
// game->deck->n++;
is_bot ? hash_map_add(h, game->bot, lp) : hash_map_add(h, game->player, lp);
play_t *new_play = get_random_tile(lp);
update_deck(game, new_play->tile, NULL);
is_bot ? add_tile_to_board_without_score(game->bot, play->tile) : add_tile_to_board_without_score(game->player, play->tile);
play->n_coup ++;
int temp_score = simulation(new_play, h, game, !is_bot, !is_last_node);
play->gain_coup += temp_score;
is_bot ? remove_tile_from_board_without_null_without_score(game->bot, play->tile) : remove_tile_from_board_without_null_without_score(game->player, play->tile);
// UNDO THE DECK
// game->deck->n--;
undo_deck(game, new_play->tile, NULL);
return temp_score;
}
} else { // random recursion until end game
if(is_bot) {
lp = game->bot->rocks > 0 ? gen_tiles_from_game(game, true) : gen_tiles(game->bot->cell_tab, game->card_1);
} else {
lp = game->player->rocks > 0 ? gen_tiles_from_game(game, false) : gen_tiles(game->player->cell_tab, game->card_1);
}
// game->deck->n++;
play_t *new_play = get_random_tile(lp);
update_deck(game, new_play->tile, NULL);
is_bot ? add_tile_to_board_without_score(game->bot, play->tile) : add_tile_to_board_without_score(game->player, play->tile);
int temp_score = simulation(new_play, h, game, !is_bot, is_last_node);
is_bot ? remove_tile_from_board_without_null_without_score(game->bot, play->tile) : remove_tile_from_board_without_null_without_score(game->player, play->tile);
// UNDO THE DECK
// game->deck->n--;
undo_deck(game, new_play->tile, NULL);
return temp_score;
}
}
play_t *copy_play(play_t *play) {
play_t *new_play = malloc(sizeof(play_t));
tile_t *tile = malloc(sizeof(tile_t));
tile->id = play->tile->id;
tile->cell_tab[0] = play->tile->cell_tab[0];
tile->cell_tab[1] = play->tile->cell_tab[1];
tile->cell_tab[2] = play->tile->cell_tab[2];
tile->cell_types[0] = play->tile->cell_types[0];
tile->cell_types[1] = play->tile->cell_types[1];
tile->cell_types[2] = play->tile->cell_types[2];
tile->id = play->tile->id;
tile->orientation = play->tile->orientation;
new_play->next = NULL;
new_play->n_coup = play->n_coup;
new_play->gain_coup = play->gain_coup;
new_play->tile = tile;
return new_play;
}
play_t *mcts(game_t *game) {
int n = 1;
float c = sqrtf(2)/10;
hash_t **h = create_hash_map();
play_t *p = initialisation(game, h);
play_t *p2 = NULL;
time_t t0 = time(0);
time_t t1 = time(0);
while(difftime(t1, t0) < 2) {
p2 = selection(p, c, n);
simulation(p2, h, game, 0, 0);
t1 = time(0);
n++;
}
float gain = 0;
float gain_max = 0;
play_t *max_play = p;
while (p != NULL) {
gain = G(p);
if (gain > gain_max) {
gain_max = gain;
max_play = p;
}
p = p->next;
}
max_play = copy_play(max_play);
free_hash_map(h);
printf("number of iterations : %d\n", n);
return max_play;
}
Updated on 2024-06-28 at 08:11:55 +0200