|
|
@ -15,6 +15,7 @@ |
|
|
|
#define debug |
|
|
|
#define score_filename "scores" |
|
|
|
|
|
|
|
#define allow_to_returning_to_the_starting_point_in_a_round 1 |
|
|
|
|
|
|
|
enum bool {false, true}; |
|
|
|
enum validation_movement_t {neighbour_valid, jump, jump_valid, invalid}; |
|
|
@ -53,7 +54,7 @@ enum bool ia_call_function(const struct player_t player, const enum api_function |
|
|
|
void *d, *e; |
|
|
|
if(!player.ia_lib_p) { |
|
|
|
#ifdef debug |
|
|
|
fputs("the player is not a strategy.\n",stderr); |
|
|
|
fputs("le joueur n'est pas une stratégie.\n",stderr); |
|
|
|
#endif |
|
|
|
return false; |
|
|
|
} |
|
|
@ -103,7 +104,7 @@ enum bool ia_call_function(const struct player_t player, const enum api_function |
|
|
|
res = true; |
|
|
|
} else { |
|
|
|
#ifdef debug |
|
|
|
fprintf(stderr,"function \"%s\" not found in strategy. (%s)\n", function_name, error); |
|
|
|
fprintf(stderr,"la fonction \"%s\" n'a pas été trouvée dans la stratégie. (%s)\n", function_name, error); |
|
|
|
#endif |
|
|
|
res = false; |
|
|
|
} |
|
|
@ -216,7 +217,7 @@ enum bool pawn_on_branch(const struct player_t player, const size_t index, const |
|
|
|
return true; |
|
|
|
return false; |
|
|
|
} |
|
|
|
enum validation_movement_t valid_move(const struct move_t move, const struct move_t previous_move, const struct player_t player, const struct game_state_t game, const size_t start_position[6][10], const enum bool last_move) { |
|
|
|
enum validation_movement_t valid_move(const int start_pos_first_move, const struct move_t move, const struct move_t previous_move, const struct player_t player, const struct game_state_t game, const size_t start_position[6][10], const enum bool last_move) { |
|
|
|
size_t j; |
|
|
|
ssize_t dest, dest2; |
|
|
|
|
|
|
@ -229,7 +230,7 @@ enum validation_movement_t valid_move(const struct move_t move, const struct mov |
|
|
|
#ifdef debug |
|
|
|
fputs("vérification de ne pas stationner sur une branche\n", stderr); |
|
|
|
#endif |
|
|
|
return pawn_on_branch(player, previous_move.end_pos, start_position)?invalid:jump_valid; |
|
|
|
return (pawn_on_branch(player, previous_move.end_pos, start_position) || (start_pos_first_move == previous_move.end_pos && ! allow_to_returning_to_the_starting_point_in_a_round ))?invalid:jump_valid; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef debug |
|
|
@ -312,7 +313,7 @@ enum bool winner(const struct player_t player, const size_t start_position[6][10 |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void save(const char *filename, const struct player_t *player_state, const int nb_game, const int nb_game_end, const int nb_player, const time_t start_match, const int *winner, const time_t *duration) { |
|
|
|
void save(const char *filename, const struct player_t *player_state, const int nb_game, const int nb_game_end, const int nb_player, const time_t start_match, const int *winner, const time_t *duration, const char *const couleurs[6]) { |
|
|
|
FILE* file; |
|
|
|
char *buffer; |
|
|
|
int i; |
|
|
@ -320,42 +321,43 @@ void save(const char *filename, const struct player_t *player_state, const int n |
|
|
|
/* remove '\n' from ctime */ |
|
|
|
buffer = ctime(&start_match); |
|
|
|
buffer[strlen(buffer)-1] = '\0'; |
|
|
|
fprintf(file, "=== %s (%d game%s - %d players) ===\n", buffer, nb_game, (nb_game>1)?"s":"", nb_player); |
|
|
|
fprintf(file, "=== %s (%d partie%s - %d joueurs) ===\n", buffer, nb_game, (nb_game>1)?"s":"", nb_player); |
|
|
|
for(i=0; i < nb_game_end ; i++) { |
|
|
|
if(duration[i] > 3600) |
|
|
|
fprintf(file, "game %d (%d hour%s %d minute%s %d second%s) : ", i+1, duration[i]/3600, ((duration[i]/3600)>1?"s":""), (duration[i]%3600)/60, ((((duration[i]%3600)/60)>1)?"s":""), (duration[i]%3600)%60, (((duration[i]%3600)%60)>1?"s":"")); |
|
|
|
fprintf(file, "partie %d (%d heure%s %d minute%s %d seconde%s) : ", i+1, duration[i]/3600, ((duration[i]/3600)>1?"s":""), (duration[i]%3600)/60, ((((duration[i]%3600)/60)>1)?"s":""), (duration[i]%3600)%60, (((duration[i]%3600)%60)>1?"s":"")); |
|
|
|
else if(duration[i] > 60) |
|
|
|
fprintf(file, "game %d (%d minute%s %d second%s) : ", i+1, duration[i]/60, (((duration[i]/60)>1)?"s":""), duration[i]%60, ((duration[i]%60)>1?"s":"")); |
|
|
|
fprintf(file, "partie %d (%d minute%s %d seconde%s) : ", i+1, duration[i]/60, (((duration[i]/60)>1)?"s":""), duration[i]%60, ((duration[i]%60)>1?"s":"")); |
|
|
|
else |
|
|
|
fprintf(file, "game %d (%d second%s) : ", i+1, duration[i], ((duration[i]%60)>1?"s":"")); |
|
|
|
fprintf(file, "partie %d (%d second%s) : ", i+1, duration[i], ((duration[i]%60)>1?"s":"")); |
|
|
|
if(winner[i] >= 0 && winner[i] < nb_player) |
|
|
|
fprintf(file, "won by player %d (%s)\n", winner[i]+1, player_state[winner[i]].name); |
|
|
|
fprintf(file, "gagnée par le joueur %s (%s)\n", couleurs[winner[i]], player_state[winner[i]].name); |
|
|
|
else |
|
|
|
fputs("no player has won\n", file); |
|
|
|
fputs("aucun joueur n'a gagné\n", file); |
|
|
|
} |
|
|
|
if(nb_game != nb_game_end) |
|
|
|
fputs("match stopped abruptly\n", file); |
|
|
|
fputs("match interrompu brutalement\n", file); |
|
|
|
fputs("\n", file); |
|
|
|
fclose(file); |
|
|
|
} |
|
|
|
#ifdef debug |
|
|
|
else |
|
|
|
fprintf(stderr, "cannot open file \"%s\"\n", filename); |
|
|
|
fprintf(stderr, "impossible d'ouvrir le fichier \"%s\"\n", filename); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
int main(int argc, char** argv) { |
|
|
|
int main(int argc, char **argv) { |
|
|
|
const size_t start_position[6][10] = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, |
|
|
|
{19, 20, 21, 22, 32, 33, 34, 44, 45, 55}, |
|
|
|
{74, 84, 85, 95, 96, 97, 107, 108, 109, 110}, |
|
|
|
{111, 112, 113, 114, 115, 116, 117, 118, 119, 120}, |
|
|
|
{65, 75, 76, 86, 87, 88, 98, 99, 100, 101}, |
|
|
|
{10, 11, 12, 13, 23, 24, 25, 35, 36, 46}}; |
|
|
|
const char *const couleurs[6] = {"jaune", "noir", "bleu", "rouge", "vert", "violet"}; |
|
|
|
struct player_t player_state[6]; |
|
|
|
struct game_state_t game_state, game_state_copy, game_state_ia_copy; |
|
|
|
struct move_t movement, previous_movement; |
|
|
|
int first_move, next_move; |
|
|
|
int nb_game, nb_player, nb_game_end, nb_player_end; |
|
|
|
int nb_game, nb_player, nb_game_end, nb_player_end, start_pos_first_move; |
|
|
|
int i, j, k; |
|
|
|
char *buffer; |
|
|
|
enum validation_movement_t validation_movement; |
|
|
@ -371,19 +373,19 @@ int main(int argc, char** argv) { |
|
|
|
|
|
|
|
/* on lit le nombre de parties */ |
|
|
|
if(!char_to_int(argv[1],&nb_game) || nb_game <= 0) { |
|
|
|
fprintf(stderr, "nb_game (%s) must be a positive number.\n", argv[1]); |
|
|
|
fprintf(stderr, "nb_game (%s) doit être un nombre positif.\n", argv[1]); |
|
|
|
return 2; |
|
|
|
} |
|
|
|
|
|
|
|
/* on lit le nombre de joueurs */ |
|
|
|
if(!char_to_int(argv[2],&nb_player) || nb_player < 2 || nb_player > 6 || nb_player == 5) { |
|
|
|
fprintf(stderr, "nb_player (%s) must be 2, 3, 4 or 6.\n", argv[2]); |
|
|
|
fprintf(stderr, "nb_player (%s) doit être 2, 3, 4 ou 6.\n", argv[2]); |
|
|
|
return 3; |
|
|
|
} |
|
|
|
|
|
|
|
/* on vérifie que le nombre de joueurs est supérieur au nombse d'ia passées en paramètrest */ |
|
|
|
if(nb_player < argc-3) { |
|
|
|
fprintf(stderr, "%d IA specified but only %d player%s.\n", argc-3, nb_player, nb_player==1?"":"s"); |
|
|
|
fprintf(stderr, "%d IA précisées mais seulement %d joueurs.\n", argc-3, nb_player); |
|
|
|
return 4; |
|
|
|
} |
|
|
|
|
|
|
@ -393,18 +395,18 @@ int main(int argc, char** argv) { |
|
|
|
j = 3; |
|
|
|
for( i = 0; i < nb_player ; i++ ) { |
|
|
|
/* on prépare pour le nom */ |
|
|
|
snprintf(player_state[i].name,50,"player %d",i+1); |
|
|
|
snprintf(player_state[i].name,50,"joueur %s", couleurs[i]); |
|
|
|
player_state[i].name[49] = '\0'; |
|
|
|
/* on choisit de placer un joueur réel ou une stratégie */ |
|
|
|
if( (rand()%(nb_player-i)) < (argc-j) ) { |
|
|
|
/* on ajoute une stratégie */ |
|
|
|
#ifdef debug |
|
|
|
fprintf(stderr,"strategy %s (%d)\n", argv[j], i); |
|
|
|
fprintf(stderr,"strategie %s (%d)\n", argv[j], i); |
|
|
|
#endif |
|
|
|
player_state[i].ia_lib_p = dlopen(argv[j], RTLD_LAZY); |
|
|
|
if( (buffer = (char*) dlerror()) != NULL ) { |
|
|
|
#ifdef debug |
|
|
|
fprintf(stderr,"error while loading %s : %s (%d)\n", argv[j], buffer, i); |
|
|
|
fprintf(stderr,"erreur pendant le chargement de %s : %s (%d)\n", argv[j], buffer, i); |
|
|
|
#endif |
|
|
|
/* échec du chargement, on décharge toutes les stratégies précédement chargées */ |
|
|
|
for( j=0 ; j<i ; j++ ) |
|
|
@ -418,14 +420,14 @@ int main(int argc, char** argv) { |
|
|
|
} else { |
|
|
|
/* on ajoute un joueur réel */ |
|
|
|
#ifdef debug |
|
|
|
fprintf(stderr,"real player (%d)\n", i); |
|
|
|
fprintf(stderr,"joueur réel (%d)\n", i); |
|
|
|
#endif |
|
|
|
player_state[i].ia_lib_p = NULL; |
|
|
|
} |
|
|
|
/* petite vérification sur le nom */ |
|
|
|
#ifdef debug |
|
|
|
if(player_state[i].name[49] != '\0') |
|
|
|
fprintf(stderr,"warning : the length of the player's name %d must be to 49 characters maximum.\n", i); |
|
|
|
fprintf(stderr,"attention : la longueur du nom du joueur %s doit être inférieur à 49 caractères.\n", couleurs[i]); |
|
|
|
#endif |
|
|
|
player_state[i].name[49] = '\0'; |
|
|
|
} |
|
|
@ -465,7 +467,7 @@ int main(int argc, char** argv) { |
|
|
|
int quit = 0; |
|
|
|
for( nb_game_end = 0 ; nb_game_end < nb_game && !quit ; nb_game_end++ ) { |
|
|
|
#ifdef debug |
|
|
|
fprintf(stderr,"%d %s left\n", nb_game, nb_game>1?"games":"game"); |
|
|
|
fprintf(stderr,"%d partie%s restante%s\n", nb_game, nb_game>1?"s":"", nb_game>1?"s":""); |
|
|
|
#endif |
|
|
|
duration_games[nb_game_end] = time(NULL); |
|
|
|
winner_games[nb_game_end] = -1; |
|
|
@ -503,7 +505,7 @@ int main(int argc, char** argv) { |
|
|
|
while(nb_player_end < nb_player-1 && !quit) { |
|
|
|
|
|
|
|
#ifdef debug |
|
|
|
fprintf(stderr, "joueur %d (%s)\n", i, player_state[i].name); |
|
|
|
fprintf(stderr, "joueur %s (%d) (%s)\n", couleurs[i], i, player_state[i].name); |
|
|
|
#endif |
|
|
|
game_state_copy = game_state; |
|
|
|
previous_movement.start_pos=-1; previous_movement.end_pos=-1; |
|
|
@ -514,8 +516,10 @@ int main(int argc, char** argv) { |
|
|
|
/* on suppose qu'on a une stratégie */ |
|
|
|
ia_call_function(player_state[i], ia_next_move, &next_move, &game_state_ia_copy, first_move, &movement); |
|
|
|
printf("(GUI) Moving pawn %d → hole %d\n", movement.start_pos, movement.end_pos); |
|
|
|
/* on effectue le mouvement à l'écran */ |
|
|
|
validation_movement = valid_move(movement, previous_movement, player_state[i], game_state_copy, start_position, !next_move); |
|
|
|
if(first_move) |
|
|
|
start_pos_first_move = movement.start_pos; /* on retient le point de départ pour éviter les coups qui reviendraient là où on est parti */ |
|
|
|
/* on cherche à valider le coup */ |
|
|
|
validation_movement = valid_move(start_pos_first_move, movement, previous_movement, player_state[i], game_state_copy, start_position, !next_move); |
|
|
|
#ifdef debug |
|
|
|
switch(validation_movement) { |
|
|
|
case invalid: fputs("validation → invalide\n", stderr); break; |
|
|
@ -524,9 +528,10 @@ int main(int argc, char** argv) { |
|
|
|
case jump_valid: fputs("validation → commit jump\n", stderr); break; |
|
|
|
} |
|
|
|
#endif |
|
|
|
/* on effectue le mouvement à l'écran */ |
|
|
|
if(validation_movement != jump_valid && movement.start_pos != movement.end_pos && movement.start_pos >= 0 && movement.end_pos >= 0 && movement.start_pos < 121 && movement.end_pos < 121) |
|
|
|
quit += display_animove_pawn(gui_res, game_state_copy, player_state[i].branch, movement.start_pos, movement.end_pos); |
|
|
|
/* on cherche à valider le coup */ |
|
|
|
/* on regarde le résultat de la validation */ |
|
|
|
if(validation_movement == invalid) { |
|
|
|
#ifdef debug |
|
|
|
fprintf(stderr, "mouvement (%d,%d) invalide\n",movement.start_pos, movement.end_pos); |
|
|
@ -608,7 +613,7 @@ int main(int argc, char** argv) { |
|
|
|
} |
|
|
|
|
|
|
|
/* on enregistre le résultat du jeu dans le fichier */ |
|
|
|
save(score_filename, player_state, nb_game, nb_game_end-(quit?1:0), nb_player, time_start_match, winner_games, duration_games); |
|
|
|
save(score_filename, player_state, nb_game, nb_game_end-(quit?1:0), nb_player, time_start_match, winner_games, duration_games, couleurs); |
|
|
|
|
|
|
|
free(winner_games); |
|
|
|
free(duration_games); |
|
|
|