You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
Bastien 790e1a7538 Correction de quelques bugs et modification du dummy pour rentrer un mouvement manuellement. 8 years ago
ai Modification du Makefile pour compiler la librairie en plus de l'exécutable de test. 8 years ago
img Ajout images de fond, plateau, pion 0 (trou vide), titre kanji 8 years ago
.gitignore Ajout du fichier .gitignore. 8 years ago
Makefile Makefile corrigé pour ubuntu (qui ne link pas si les fichiers à compiler ne sont pas en premier argument) 8 years ago
dameschinoises.h Initial commit 8 years ago
dameschinoises.patch Modification de la fonction pour valider un coup (vérification qu'on ne s'arrête pas sur une branche de l'étoile). 8 years ago
dummy.c Correction de quelques bugs et modification du dummy pour rentrer un mouvement manuellement. 8 years ago
gui.c GUI : perf — rotation de l'image seulement si angle non nul 8 years ago
gui.h GUI : header pour la fonction animsg 8 years ago
guidemo.c GUI : implémentation de l'animation de déplacement de pion. 8 years ago
main.c Correction de quelques bugs et modification du dummy pour rentrer un mouvement manuellement. 8 years ago
readme Rédaction du readme. 8 years ago

readme

Explications sur le fonctionnement du programme

fonction « char_to_int »
========================

La fonction « enum bool char_to_int(char *argv, int *nombre) » permet de convertir un nombre contenu dans une chaîne de
caractères en un entier. La fonction retourne « true » si la conversion a réussie et « false » si la conversion a échouée.
Le nombre converti est stocké à l'adresse pointée par le paramètre « nombre ».


fonction « ia_call_function »
=============================

La fonction « enum bool ia_call_function(const struct player_t player, const enum api_function_t api_function, void *result, ...) » permet d'appeler les fonctions de la stratégie.

Le paramètre « const struct player_t player » correspond au joueur (stratégie) pour lequel il faut appeler une fonction.
Le second paramètre « const enum api_function_t api_function » correspond à la fonction à appeler
Le troisième paramètre « void *result » permet de récupérer la valeur de retour de la fonction qui sera appelée (dans le cas d'une fonction void, ce paramètre vaut NULL)
Les arguments suivants sont les arguments attendus par la fonction de la stratégie.

La fonction va d'abord affecter à la variable « function_name » la chaîne de caractères correspondant au nom de la fonction à
appeler. Ce nom est déduit de la valeur du paramètre « api_function ».
Ensuite on essaie de récupérer un pointeur vers la fonction en question grâce à l'utilisation de « dlsym ». Si cela échoue la
fonction « ia_call_function » retourne « false » et se termine. Sinon, selon la fonction demandée, on lit éventuellement les
paramètres avec « va_arg() ». Enfin on appelle la fonction de la stratégie.


fonction « star_branch »
========================

La fonction « size_t star_branch(const unsigned int nb_player, const size_t index) » permet de déterminer sur quelle branche de
l'étoile doit se trouver la position de départ d'un joueur donné.

On numérote chaque branche de l'étoile :
/ \
____/ 0 \____
\ 5 1 /
\ /
/ \
/ 4 2 \
————\ 3 /————
\ /

Ainsi quand le nombre de joueurs est égal à 2, le joueur 0 doit être placé sur la branche 0 et le joueur 1 sur la branche 3.
On a donc dans ce cas « star_branch(2,0) = 0 » et « star_branch(2,1) = 3 ».

Avec trois joueurs, on place les joueurs sur les branches 0, 2 et 4
Avec quatre joueurs, on les place sur les branches 1, 2, 4 et 5
Avec six joueurs, on utilise chaque branche.

fonction « move_calculation »
=============================


La fonction « ssize_t move_calculation(const size_t index, const enum direction_t move) » permet de déterminer l'indice du
voisin d'une case sur le plateau.

La fonction prend deux paramètres. Le premier paramètre, « index » est l'indice de la case dont on veut un voisin. Le second
paramètre « move » permet de préciser quel voisin on souhaite.

La fonction retourne l'indice du voisin ou bien -1 si le voisin demandé n'existe pas (par exemple la case d'indice 0 n'a pas de
voisin à gauche).

La fonction va d'abord déterminer sur quelle ligne se trouve la case dont on cherche le voisin ainsi que sa position sur la
ligne (offset). La fonction détermine aussi dans quel « bloc » de l'étoile, la case se trouve.
Les blocs sont définis comme ceci :
/ \
____/ \____ bloc 0
----------------------
\ / bloc 1
\ /
----------------------
/ \ bloc 2
/ \
----------------------
————\ /———— bloc 3
\ /


Ensuite on applique une formule différente selon le voisin dont on veut déterminer l'indice.

Pour le voisin à gauche : si l'offset est de 0, c'est à dire qu'on est sur la case la plus à gauche de la ligne alors on
renvoie -1 (il n'y a pas de voisin gauche). Sinon on retourne l'indice de la case moins un (puisque les cases sont numérotées
ligne par ligne).

Pour le voisin droit : on retourne l'indice de la case demandée plus un, sauf si cette case est située au début de la ligne
suivante (les indices des cases au situées au début des lignes sont connus).

Pour le voisin « haut gauche » :
On commence par traîter les cas où ce voisin n'existe pas. C'est à dire si on se trouve à la frontière entre le bloc 0 et le
bloc 1 ou sur toute première d'une ligne d'un bloc :

/ \
(**)/ \_(**)
\ /
\ /
(*) \
(*) \
————\ /————
\ /

« (*) » → cases qui n'ont pas de voisin haut gauche.

Si la case ne satisfait pas ces critères (donc elle a un voisin « haut gauche », on récupère l'indice de la case à la ligne
précédente ayant de même offset. On enlève 1 selon si le bloc est impair ou non (car les offsets sont décalés de 1 selon si la
taille des lignes est croissant ou décroissante)

Enfin on peut ajouter 4 ou retirer 5 pour faire le « collage » entre les blocs 0 et 1 et les blocs 2 et 3.


Pour le voisin « haut droit », on fonctionne de la même façon.
On commence par traîter les cases qui n'ont pas ce voisin :

/ \
(**)_/ \(**)
\ /
\ /
/ (*)
/ (*)
————\ /————
\ /

Ensuite la formule est la même que précédemment sauf qu'au lieu d'enlever 1 selon le bloc, on ajoute 1.


Pour les voisins situés en bas, on applique encore ce principe.


fonction « search »
===================

La fonction « enum bool search(const size_t *tab, const size_t length, const size_t value) » est une simple recherche
dichotomique qui permet de vérifier si la valeur « value » se trouve dans le tableau trié « tab » de taille « length ».



fonction « valid_move »
=======================

La fonction « enum bool 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) »
permet de vérifier si le coup « move » est un coup valide ou non.

Le paramètre « move » est le mouvement dont on veut vérifier la validité
Le paramètre « previous_move » est le mouvement précédent. Cela permet ainsi de vérifier que pendant un même tour, on ne déplace qu'un seul pion. Si c'est le
premier mouveement d'un tour, ce mouvement doit comporter (-1,-1).
Le paramètre « player » est le joueur qui effectue le déplacement. Cela permet de vérifier que le joueur déplace un pion qui lui appartient
Le paramètre « game » est le plateau du jeu
Le paramètre « start_position » est un tableau qui contient les indices des cases formant les branches de l'étoile.
Le paramètre « last_move » permet d'indiquer qu'il s'agit du dernier mouvement d'un tour. Ces deux derniers paramètres permettent de vérifier que le joueur ne
s'arrête pas sur une branche de l'étoile.

La fonction va d'abord vérifier si le mouvement est le premier mouvement d'un coup. Si c'est le cas, que le mouvement est (-1,-1) et que c'est également le
dernier, cela signifie que le joueur passe son tour.
Sinon on vérifie que la case du début du mouvement comporte bien un pion appartenant au joueur.
Si ce n'est pas le premier mouvement d'un tour, on vérifie que la case au départ du déplacement est la même que celle qui a terminé le mouvement précédent.

Ensuite, si il s'agit du dernier mouvement d'un tour, on vérifie que la case de la fin du mouvement ne corresponde pas à la branche d'un joueur.

Ensuite on regarde chaque case située autour de la case au départ du mouvement. On a trois cas :
Si la case est vide et que c'est là qu'on veut aller, le coup est autorisé
Si la case est occupée et que c'est là qu'on veut aller, le coup est invalide
Si la case est occupée et que ce n'est pas la qu'on veut aller, on refait ce test (uniquement les deux conditions précédentes )avec la case située après le
pion voisin.

Une fois qu'on a regardé tous les voisins, si on n'a satisfait aucune condition, on considère naturellement que le coup est invalide.


fonction « winner »
===================

La fonction « enum bool winner(struct player_t player, const size_t start_position[6][10], const struct game_state_t game) » permet de vérifier que
tous les pions du joueur « player » sont situés sur la branche opposée à sa branche de départ.


fonction « main »
=================