diff --git a/LABY b/LABY new file mode 100644 index 0000000..ebaecd8 --- /dev/null +++ b/LABY @@ -0,0 +1,173 @@ +/* +* ------------------------ * +| | +| -= LabyrinthAPI =- | +| | +* ------------------------ * + + +Authors: T. Hilaire, J. Brajard +Licence: GPL +Status: beta version + +File: labyrinthAPI.h + Contains the client API for the Labyrinth game + + +*/ + + +#ifndef __API_CLIENT_LABYRINTH__ +#define __API_CLIENT_LABYRINTH__ +#include "ret_type.h" + +typedef enum +{ + ROTATE_LINE_LEFT = 0, + ROTATE_LINE_RIGHT = 1, + ROTATE_COLUMN_UP = 2, + ROTATE_COLUMN_DOWN = 3, + MOVE_UP = 4, + MOVE_DOWN = 5, + MOVE_LEFT = 6, + MOVE_RIGHT = 7, + DO_NOTHING = 8 +} t_typeMove; + + +/* +A move is a tuple (type,value): +- type can be ROTATE_LINE_LEFT, ROTATE_LINE_RIGHT, ROTATE_COLUMN_UP, +ROTATE_COLUMN_DOWN, MOVE_LEFT, MOVE_RIGHT, MOVE_UP or MOVE_DOWN +- in case of rotation, the value indicates the number of the line +(or column) to be rotated +*/ +typedef struct +{ + t_typeMove type; /* type of the move */ + int value; /* value associated with the type + (number of the line or the column to rotate)*/ +} t_move; + + +/* ------------------------------------- + * Initialize connection with the server + * Quit the program if the connection to the server + * cannot be established + * + * Parameters: + * - serverName: (string) address of the server + * (it could be "localhost" if the server is run in local, + * or "pc4521.polytech.upmc.fr" if the server runs there) + * - port: (int) port number used for the connection + * - name: (string) name of the bot : max 20 characters + * (checked by the server) + */ +void connectToServer( char* serverName, int port, char* name); + + + +/* ---------------------------------- + * Close the connection to the server + * to do, because we are polite + * + * Parameters: + * None +*/ +void closeConnection(); + +/* ---------------------------------------------------------------- + * Wait for a Game, and retrieve its name and first data + * (typically, array sizes) + * + * Parameters: + * - training: string (max 50 characters) type of the training + * player we want to play with + * (empty string for regular game) + * - labyrinthName: string (max 50 characters), + * corresponds to the game name + * - sizeX, sizeY: sizes of the labyrinth + * + * training is a string like "NAME key1=value1 key2=value1 ..." + * - NAME can be empty. It gives the type of the training player + * - key=value pairs are used for options + * (each training player has its own options) + * invalid keys are ignored, invalid values leads to error + * the following options are common to every training player + * (when NAME is not empty): + * - timeout: allows an define the timeout + * when training (in seconds) + * the NAME could be: + * - "DO_NOTHING" to play against DO_NOTHING player + * (player that does not move) + * - "PLAY_RANDOM" for a player that make random (legal) moves + * (option "rotation=False/True") + */ +void waitForLabyrinth( char* training, char* labyrinthName, + int* sizeX, int* sizeY); +/* ------------------------------------- + * Get the labyrinth and tell who starts + * It fills the char* lab with the data of the labyrinth + * 1 if there's a wall, 0 for nothing + * + * Parameters: + * - lab: the array of labyrinth + * (the pointer data MUST HAVE allocated with the right size !!) + * + * Returns 0 if you begin, or 1 if the opponent begins + */ +int getLabyrinth( char* lab); + + + +/* ---------------------- + * Get the opponent move + * + * Parameters: + * - move: a move + * + * Returns a return_code + * MOVE_OK for normal move, + * MOVE_WIN for a winning move, -1 + * MOVE_LOSE for a losing (or illegal) move + * this code is relative to the opponent (MOVE_WIN if HE wins, ...) + */ +t_return_code getMove( t_move* move ); + + + +/* ----------- + * Send a move + * + * Parameters: + * - move: a move + * + * Returns a return_code + * MOVE_OK for normal move, + * MOVE_WIN for a winning move, -1 + * MOVE_LOSE for a losing (or illegal) move + * this code is relative to your programm (MOVE_WIN if YOU win, ...) + */ +t_return_code sendMove( t_move move ); + + + +/* ---------------------- + * Display the labyrinth + * in a pretty way (ask the server what to print) + */ +void printLabyrinth(); + + + +/* ---------------------------- + * Send a comment to the server + * + * Parameters: + * - comment: (string) comment to send to the server (max 100 char.) + */ +void sendComment(char* comment); + + + +#endif diff --git a/Notes b/Notes new file mode 100644 index 0000000..e18f031 --- /dev/null +++ b/Notes @@ -0,0 +1,6 @@ +ssh -Y 3408017@pc57.polytech.upmc.fr + + "PLAY_RANDOM" for a player that make random (legal) moves + * (option "rotate=False/True") + +Position n'as pas besoin d'avoir une allocation mémoire (malloc) en tant que structure ? \ No newline at end of file diff --git a/Patchs/Document sans titre.docx b/Patchs/Document sans titre.docx new file mode 100644 index 0000000..8275036 Binary files /dev/null and b/Patchs/Document sans titre.docx differ diff --git a/Patchs/Patch Astaromove.txt b/Patchs/Patch Astaromove.txt new file mode 100644 index 0000000..6561ca6 --- /dev/null +++ b/Patchs/Patch Astaromove.txt @@ -0,0 +1,111 @@ +SUGGESTIONS DE PATCH + + +FONCTION.C +l.242 : soucis potentiel avec la circularitĂ© du bidule labyrinthe pour le calcul de l'heuristique, du chemin... + +(l.273) : première condition du while superflue ? +l.283 : traiter sĂ©paremment le cas oĂą il n'y qu'un Ă©lĂ©ment dans l'openlist : + ... + + //Suppression de la case d'openList + temp_list=openList; + if temp_list->suiv == NULL //S'il n'y qu'un seul element, t'es sur duquel faut supprimer + openList == NULL + while(temp_list->suiv!=temp){ + temp_list=temp_list->suiv; + } + temp_list->suiv=temp->suiv; + free(temp); + + ... + +(l.280) : pour eviter de creer une autre structure et faire un free de l'ancienne ou pourrait faire (a mettre apres le retrait de temp de l'openlist) : + ... + + while(temp_list->suiv!=temp){ + temp_list=temp_list->suiv; + } + temp_list->suiv=temp->suiv; + + //Transfert de la case de openList vers closedList + temp->suiv = closedList; + closedList = temp; + + ... + +(l.407) : tableau de int pour itinĂ©raire plus simple, a changer : + ... + + //CrĂ©ation de l'itinĂ©raire + temp_case=&c; + for(i=0;ipos; + temp_case=temp_case->prec; + n = move_pos(temp_case->pos,temp_pos); + itineraire[i]= n; + } + itineraire[i]=0; +} + +... +CHANGER +int move_pos(Position Ini, Position Fin){ //Donne le mouvement pour aller de Ini a Fin + + int m; + int dx, dy; + dx=Fin.x-Ini.x; + if(dx!=0){ + if(dx==1){ + m = 7; + } + else{ + m = 6; + } + } + dy=Fin.y-Ini.y; + if(dy!=0){ + if(dy==1){ + m = 5; + } + else{ + m = 4; + } + } + else{ + m = 8; + } + + return m; +} +... + +CHANGER +void free_itineraire(int* itineraire) + + + +(l.414) : On ne compte pas la case de dĂ©part comme un move + while (temp_case->suiv != NULL){ //On dĂ©termine combien de mouvement seront nĂ©cessaire + temp_case=temp_case->prec; + nb_move++; + } +Du coup on peut supprimer l.428. + + +FONCTION.H +(l.32) : structure lourde pour la mĂ©moire, utilisation d'un pointeur ? : +... + +//DĂ©claration Liste chainĂ©e de Case +typedef struct element Element; + +struct element{ + Case* c; + Element* suiv; +}; +typedef Element* ListeC; + +... + + diff --git a/Patchs/patch random.txt b/Patchs/patch random.txt new file mode 100644 index 0000000..24c7c99 --- /dev/null +++ b/Patchs/patch random.txt @@ -0,0 +1,35 @@ +#define CV(x,y,size_x) x + y*size_x + + + +void rotation_lab(char* labData, t_move move, int size_x, int size_y){ //Modifie le labyrinthe en cas de rotation (POSSIBILITE : Placer les lignes de codes des if dans pos_suivante) + int i, temp; + if(move.type==ROTATE_LINE_LEFT){ + temp=labData[CV(i,move.value,size_x)]; // On garde en mĂ©moire le terme du tableau qui va passer de l'autre cĂ´tĂ© du labyrinthe avec la rotation (Ici, le 1er terme) + for(i=0;i0;i--){//On parcours la ligne en sens inverse en Ă©changeant les termes vers la droite + labData[CV(i,move.value,size_x)]=labData[CV(i-1,move.value,size_x)]; + } + labData[CV(0,move.value,size_x)]=temp; //On place le terme au dĂ©but de la ligne + } + if(move.type==ROTATE_COLUMN_UP){ + temp=labData[move.value]; //On garde en mĂ©moire le 1er terme de la colonne + for(i=0;i0;i--){ //On parcours la colonne de bas en haut en Ă©changeant vers le bas + labData[CV(move.value,i,size_x)]=labData[CV(move.value,i-1,size-x)]; + } + labData[CV(move.value,0,size_x)]=temp; //On place le terme au dĂ©but de la colonne + } +} \ No newline at end of file diff --git a/Slide Projet info HARLE ZHONG.pptx b/Slide Projet info HARLE ZHONG.pptx new file mode 100644 index 0000000..2c94137 Binary files /dev/null and b/Slide Projet info HARLE ZHONG.pptx differ diff --git a/Test/main.c b/Test/main.c new file mode 100644 index 0000000..69c7305 --- /dev/null +++ b/Test/main.c @@ -0,0 +1,24 @@ +#include + + +typedef struct position{ + int x; + int y; +} Position; + +int main (){ + + Position p1,p2; + + p1.x = 1; + p1.y = 2; + + p2 = p1; + + p2.x = 3; + + printf("p1.x = %d\np1.y = %d\np2.x = %d\np2.y = %d\n", p1.x,p1.y,p2.x,p2.y); + + return 0; + +} diff --git a/Test/test.c b/Test/test.c new file mode 100644 index 0000000..4ff685a --- /dev/null +++ b/Test/test.c @@ -0,0 +1,37 @@ + +//Fait un move alĂ©atoire +#include +#include + +//Choisit un type de mouvement alĂ©atoire et une ligne/colonne alĂ©atoire si rotation +void random_move(t_move* move, int size_x, int size_y){ + + srand(time(NULL)); + int n1, n2; + + n1 = rand()%9; + move->type = n1; //Choisit une type de move alĂ©atoire + move->value = 0; + + if (n1==2 || n1==3){ //Cas oĂą on bouge une colonne, il y a size_x colonnes + n2 = rand()%size_x; + move->value = n2; //Choisit une colonne alĂ©atoire Ă  bouger + } + else if (n1==0 || n1==1){ //Cas oĂą on bouge une ligne, il y a size_y lignes + n2 = rand()%size_y; + move->value = n2; //Choisit une ligne alĂ©atoire Ă  bouger + } +} + +//Convertit une position en deux dimensions en une position en une dimension (pour manipuler labData) +int convert(Position pos, int size_x){ + return pos->x + pos->y * (size_x + 1); +} + +//Renvoie 1 si la case en bonne, renvoie 0 si la case n'est pas bonne +int test_case(Position pos, char* labData, int size_x){ + + if (labData[convert(pos, size_x)] == 1){return 0;} + else {return 1;} + +} diff --git a/astar.c b/astar.c new file mode 100644 index 0000000..e5a0e5f --- /dev/null +++ b/astar.c @@ -0,0 +1,298 @@ +#include "fonction.h" + +t_move** Astar(Position pos1, Position tresor, char* labData, int size_x, int size_y){ //Trouve le chemin le plus rapide vers le trĂ©sor + + //Initialisation des variables et structures + int i; + ListeC closedList=NULL, openList=NULL, temp_list, min_list; + Position voisins[4], cp; + Case D; //Case de dĂ©part de l'A* + t_move** itineraire=NULL; + + //Initialisation de la case de dĂ©part + (D.pos).x=pos1.x; + (D.pos).y=pos1.y; + D.cost=0; + D.prev=estimation_distance(D.pos, tresor, size_x,size_y); + D.prec=NULL; //Indicateur Case de dĂ©part + + //Initialisation de l'openList + openList=ajout_case(D,openList); + + //Algorithme A* + while(openList!=NULL){ + //Reinitialisation des variables + min_list=NULL; + temp_list=openList; + + //Recherche de la case proposant la plus faible estimation + while(temp_list!=NULL){ + if(min_list==NULL ||((min_list->c).prev) > ((temp_list->c).prev)){ + min_list=temp_list; + } + temp_list=temp_list->suiv; + } + + //Retrait de la case d'openList + temp_list=openList; + if(temp_list==min_list){ //Si on supprime le premier element + openList=min_list->suiv; + } + else{ + while(temp_list->suiv!=min_list){ //Si on supprime un des Ă©lĂ©ment restant + temp_list=temp_list->suiv; + } + temp_list->suiv=min_list->suiv; + } + + //Transfert de la case de openList en tete de closedList + min_list->suiv = closedList; + closedList = min_list; + cp = (closedList->c).pos; //Case considĂ©rĂ©e = permiere case de closedList + + //Verification case tresor et sortie de boucle si c'est le cas + if(verif_positions(cp,tresor)){ //Si on est arrivĂ© au trĂ©sor + itineraire= chemin(closedList->c); + break; + } + + //Determination des voisins sinon + voisins[0].x=cp.x+1; + voisins[0].y=cp.y; + ajust_pos(voisins, size_x, size_y); + voisins[1].x=cp.x-1; + voisins[1].y=cp.y; + ajust_pos(voisins+1, size_x, size_y); + voisins[2].x=cp.x; + voisins[2].y=cp.y+1; + ajust_pos(voisins+2, size_x, size_y); + voisins[3].x=cp.x; + voisins[3].y=cp.y-1; + ajust_pos(voisins+3, size_x, size_y); + + //Verification si les voisins n'ont pas dĂ©ja ete evaluĂ©es (dans openList ou closedList) ou qu'il ne soit pas des murs + verif_voisins(voisins, openList); + verif_voisins(voisins, closedList); + verif_voisins_mur(voisins, labData, size_x); + + //Ajout des voisins Ă  openList + for(i=0;i<4;i++){ + if((voisins[i]).x!=-1){ //si elle n'as pas dĂ©ja Ă©tĂ© evaluĂ©e et quelle n'est pas un mur + + D = newCase(&(closedList->c), (voisins[i]).x, (voisins[i]).y, tresor, size_x, size_y); + + openList=ajout_case(D,openList); + } + } + } + + //Liberation de memoire lorsque que l'itineraire est determine + free_liste(openList); + free_liste(closedList); + + return itineraire; +} + +void Astaromove(t_move* move, t_move** itineraire, Position pos1, Position tresor, char* labData, int size_x, int size_y){ //Joue sans rotation pour aller le plus rapidement possible au trĂ©sor + + //S'il n'y a pas eu de rotations, pas besoin de recalculer l'itinĂ©raire + if((itineraire==NULL)||(move->type==ROTATE_LINE_LEFT)||(move->type==ROTATE_LINE_RIGHT)||(move->type==ROTATE_COLUMN_UP)||(move->type==ROTATE_COLUMN_DOWN)){ + //Suppression de l'ancien itinĂ©raire + free_itineraire(itineraire); + itineraire = NULL; + + itineraire= Astar(pos1, tresor, labData, size_x, size_y); + } + + //Envoie du move + if(itineraire==NULL){ //Pas de solution trouvĂ© + + move->type=DO_NOTHING; + move->value=0; + printf("\n Pas de chemin trouvĂ© : STAND BY\n"); + } + else{ + move->type=(itineraire[0])->type; + move->value=0; + //Suppression du move dans itineraire + free(*itineraire); + itineraire=&(itineraire[1]); + } + #ifdef DEBUG + printf("Move type :%d\n",move->type); + printf("Move Value: %d",move->value); + #endif +} + +int estimation_distance(Position J, Position P, int sizeX, int sizeY){ + + int dx, dy; + + dx = fabs(P.x - J.x); //DiffĂ©rence selon les colonnes + dy = fabs(P.y - J.y); //DiffĂ©rence selon les lignes + + if (dx > sizeX/2) {dx = sizeX - dx;} //Si c'est mieux de passer de l'autre cĂ´tĂ© d'un mur gauche-droite + if (dy > sizeY/2) {dy = sizeY - dy;} //Si c'est mieux de passer de l'autre cĂ´tĂ© d'un mur haut-bas + + return dx + dy; +} + +Case newCase(Case* c, int x, int y, Position tresor, int sizeX, int sizeY){ //Initialise une case voisine Ă  c par ces coordonĂ©es (x,y) + + Case v; //case voisine de c + (v.pos).x=x; + (v.pos).y=y; + #ifdef DEBUG + if(estimation_distance(c->pos,v.pos,sizeX,sizeY)!=1){ + printf("\n newCase Error : cases non voisines :(%d,%d) -> (%d,%d)\n",(c->pos).x,(c->pos).y,(v.pos).x,(v.pos).y); + printf("Esti : %d\n",estimation_distance(c->pos,v.pos,sizeX,sizeY)); + } + #endif + v.cost = c->cost+1; + v.prev=v.cost+estimation_distance(v.pos, tresor,sizeX,sizeY); + v.prec=c; + + + return v; +} + +ListeC ajout_case(Case c, ListeC liste){ //Ajoute c en dĂ©but de liste + ListeC nliste; + nliste=(ListeC)malloc(sizeof(Element)); // Allocation mĂ©moire? + nliste->c=c; + nliste->suiv=liste; + + return nliste; +} + +void verif_voisins(Position* voisins, ListeC liste){ //Modifie voisins pour qu'il ne reste que des cases non Ă©valuĂ©es qui ne soit pas des murs + + int i; + ListeC temp_list=liste; + + while(temp_list!=NULL){ + for(i=0;i<4;i++){ + if(verif_positions(voisins[i],(temp_list->c).pos)){ + voisins[i].x=-1; + } + } + temp_list=temp_list->suiv; + } +} + +void verif_voisins_mur(Position* voisins, char* labData, int size_x){ //Modifie voisins pour qu'il ne reste que des cases qui ne sont pas des murs + + int i; + + for(i=0;i<4;i++){ + if(test_case(voisins[i], labData, size_x)==0){ + voisins[i].x=-1; + } + } +} + +int verif_positions (Position P1, Position P2){ //retourne 1 si P1 et P2 ont les mĂŞmes coordonĂ©es, 0 sinon + + if((P1.x==P2.x)&&(P1.y==P2.y)){ + return 1; + } + else{ + return 0; + } +} + +t_move** chemin(Case c){ //donne l'itinĂ©raire depuis le dĂ©part pour aller jusqu'Ă  c + + Case* temp_case=&c; + Position temp_pos; + int i, nb_move=0; + t_move** itineraire; + + while (temp_case != NULL){ //On dĂ©termine combien de mouvement seront nĂ©cessaires + temp_case=temp_case->prec; + nb_move++; + } + itineraire=(t_move**)malloc((nb_move)*sizeof(t_move*)); + + //CrĂ©ation de l'itinĂ©raire + temp_case=&c; + itineraire[nb_move-1]=NULL;//Fin de l'itinĂ©raire + + for(i=nb_move-2;i>=0;i--){//Construction dĂ©croissante car on part du trĂ©sor pour arriver au dĂ©part + temp_pos=temp_case->pos; + temp_case=temp_case->prec; + + itineraire[i]= move_pos(temp_case->pos,temp_pos); + + } + + return itineraire; +} + +t_move* move_pos(Position Ini, Position Fin){ //Donne le mouvement pour aller de Ini a Fin +//MOVE_UP = 4, MOVE_DOWN = 5, MOVE_LEFT = 6, MOVE_RIGHT = 7, DO_NOTHING = 8 + int dx, dy; + + t_move* pmove=(t_move*)malloc(sizeof(t_move)); + + dx=Fin.x-Ini.x; + dy=Fin.y-Ini.y; + + if(dx!=0){ + if(dx==1||dx<0){ + pmove->type=7; + } + if(dx==-1||dx>1){ + pmove->type=6; + } + } + + if(dy!=0){ + if(dy==1||dy<0){ + pmove->type=5; + } + if(dy==-1||dy>1){ + pmove->type=4; + } + } + if(dx==0&&dy==0){ + pmove->type= 8; + } + pmove->value=0; + + return pmove; +} + +void free_itineraire(t_move** itineraire){ + + //Cas ou itineraire n'est pas defini + if(itineraire == NULL) {return;} + + int i=0; + t_move* temp=itineraire[0]; + + while(temp!=NULL){ + free(temp); + temp=itineraire[i]; + i++; + } + free(itineraire); +} + + +void free_liste(ListeC liste){ + + //Cas ou Liste n'est pas defini + if(liste == NULL) {return;} + + ListeC temp = liste, suivant = NULL; + + while(temp->suiv!=NULL){ + suivant = temp->suiv; + free(temp); + temp=suivant; + } + free(temp); +} + + diff --git a/enonce.pdf b/enonce.pdf new file mode 100644 index 0000000..af0a632 Binary files /dev/null and b/enonce.pdf differ diff --git a/fonction.c b/fonction.c new file mode 100644 index 0000000..c1b4510 --- /dev/null +++ b/fonction.c @@ -0,0 +1,187 @@ +#include "fonction.h" + +void defmove(t_move* move){ + + int a; + + printf("\n DĂ©placement - ROTATE_LINE_LEFT = 0, ROTATE_LINE_RIGHT = 1, ROTATE_COLUMN_UP = 2, ROTATE_COLUMN_DOWN = 3, MOVE_UP = 4, MOVE_DOWN = 5, MOVE_LEFT = 6, MOVE_RIGHT = 7, DO_NOTHING = 8\n"); + + scanf(" %d", &a); + move->type = a; + + if(move->type <= 3){ + printf("Indice de ligne/colonne Ă  rotater ; le (0,0) est en haut Ă  gauche : "); + scanf(" %d", &(move->value)); + } + else {move->value=0;} + +} + +void print_labdata(char* labData, int size_x, int size_y){ //Affiche la structure du labyrinthe en binaire + + int i; + printf("\n"); + for(i=0; i<(size_x * size_y); i++){ + if(labData[i]==0){ printf(" "); } + else{ printf("@ "); } + if ((i+1)%size_x == 0){printf("\n");} + + } + +} + +void init_info(Position* J1, Position* J2, Position* Tresor, int* En1, int* En2, int player, int size_x, int size_y){ //Initialise les infos du labyrinthe de tout les Ă©lĂ©ments (J1 : Nous / J2 : Adversaire) + + if(player==0){ //On commence + J1->x=0; + J1->y=size_y/2; + J2->x=size_x-1; + J2->y=size_y/2; + *En2=2; + } + else{ //L'adversaire commence + J2->x=0; + J2->y=size_y/2; + J1->x=size_x-1; + J1->y=size_y/2; + *En1=2; + } + //Position trĂ©sor + Tresor->x=size_x/2; + Tresor->y=size_y/2; +} + +void info_suivante(t_move move, Position* pos1, Position* pos2, Position* tresor, int* E, char* labData, int size_x, int size_y){ //Actualise les infos du labyrinthe (pos1 = joueur actif) + + switch(move.type){ + + case ROTATE_LINE_LEFT: + rotation_pos(pos1, move); + rotation_pos(pos2, move); + rotation_pos(tresor, move); + rotation_lab(labData, move, size_x, size_y); + (*E)-=5; + + break; + + case ROTATE_LINE_RIGHT: + rotation_pos(pos1, move); + rotation_pos(pos2, move); + rotation_pos(tresor, move); + rotation_lab(labData, move, size_x, size_y); + (*E)-=5; + break; + + case ROTATE_COLUMN_UP: + rotation_pos(pos1, move); + rotation_pos(pos2, move); + rotation_pos(tresor, move); + rotation_lab(labData, move, size_x, size_y); + (*E)-=5; + break; + + case ROTATE_COLUMN_DOWN: + rotation_pos(pos1, move); + rotation_pos(pos2, move); + rotation_pos(tresor, move); + rotation_lab(labData, move, size_x, size_y); + (*E)-=5; + break; + + case MOVE_UP: + pos1->y-=1; + (*E)++; + break; + + case MOVE_DOWN: + pos1->y+=1; + (*E)++; + break; + + case MOVE_LEFT: + pos1->x-=1; + (*E)++; + break; + + case MOVE_RIGHT: + pos1->x+=1; + (*E)++; + break; + + case DO_NOTHING: + (*E)++; + break; + } + ajust_pos(pos1, size_x, size_y); + ajust_pos(pos2, size_x, size_y); + ajust_pos(tresor, size_x, size_y); +} + +//Ajuste la position de pos pour les depassement d'extrĂ©mitĂ©s +void ajust_pos(Position* pos, int size_x, int size_y){ + + if(pos->y<0){ pos->y=size_y-1; } //Limite haute du labyrinthe, on passe a l'autre extremitĂ© + if(pos->y>=size_y){ pos->y=0; } //Limite basse du labyrinthe, on passe a l'autre extremitĂ© + if(pos->x<0){ pos->x=size_x-1; } //Limite gauche du labyrinthe, on passe a l'autre extremitĂ© + if(pos->x>=size_x){ pos->x=0; } // Limite droite du labyrinthe, on passe a l'autre extremitĂ© + +} + +void rotation_pos(Position* pos, t_move move){ //DĂ©place l'Ă©lĂ©ment en pos s'il se situe sur une rotation + + if(move.value==pos->x){ //Si notre Ă©lement en pos se situe sur un mouvement d'une colonne + if(move.type==ROTATE_COLUMN_UP){ pos->y-=1; } + if(move.type==ROTATE_COLUMN_DOWN){ pos->y+=1; } + } + if(move.value==pos->y){ //Si notre Ă©lement en pos se situe sur un mouvement d'une ligne + if(move.type==ROTATE_LINE_LEFT){ pos->x-=1; } + if(move.type==ROTATE_LINE_RIGHT){ pos->x+=1; } + } +} + +void rotation_lab(char* labData, t_move move, int size_x, int size_y){ //Modifie le labyrinthe en cas de rotation (POSSIBILITE : Placer les lignes de codes des if dans pos_suivante) + int i, temp; + if(move.type==ROTATE_LINE_LEFT){ + temp=labData[(move.value*size_x)]; // On garde en mĂ©moire le terme du tableau qui va passer de l'autre cĂ´tĂ© du labyrinthe avec la rotation (Ici, le 1er terme) + for(i=0;i0;i--){//On parcours la ligne en sens inverse en Ă©changeant les termes vers la droite + labData[(move.value*size_x)+i]=labData[(move.value*size_x)+i-1]; + } + labData[(move.value*size_x)]=temp; //On place le terme au dĂ©but de la ligne + } + if(move.type==ROTATE_COLUMN_UP){ + temp=labData[move.value]; //On garde en mĂ©moire le 1er terme de la colonne + for(i=1;i0;i--){ //On parcours la colonne de bas en haut en Ă©changeant vers le bas + labData[move.value+size_x*i]=labData[move.value+size_x*(i-1)]; + } + labData[move.value]=temp; //On place le terme au dĂ©but de la colonne + } +} + +//Convertit une position en deux dimensions en une position en une dimension (pour manipuler labData) +int convert(Position pos, int size_x){ + return pos.x + pos.y * size_x; +} + +//Renvoie 1 si la case est libre, renvoie 0 si la case n'est pas libre +int test_case(Position pos, char* labData, int size_x){ //Il faut bien mettre size_x c-a-d longueur d'une ligne c-a-d nombre de colonnes + + if (labData[convert(pos, size_x)] == 1){return 0;} + else {return 1;} +} + + + diff --git a/fonction.h b/fonction.h new file mode 100644 index 0000000..d3c8f29 --- /dev/null +++ b/fonction.h @@ -0,0 +1,71 @@ +#ifndef __FONCTION_H__ +#define __FONCTION_H__ + +#include +#include +#include "labyrinthAPI.h" +#include +#include +#include + +//#define DEBUG + +//DEFMOVE +typedef struct position{ + int x; + int y; +} Position; + +void defmove(t_move * move); //Fonction de mouvement manuel +void print_labdata(char* labData, int size_x, int size_y); //Affiche la structure du labyrinthe en binaire +void init_info(Position* J1, Position* J2, Position* Tresor, int* En1, int* En2, int player, int size_x, int size_y); //Initialise les infos du labyrinthe de tout les Ă©lĂ©ments (J1 : Nous / J2 : Adversaire) +void info_suivante(t_move move, Position* pos1, Position* pos2, Position* tresor, int* E, char* labData, int size_x, int size_y); //Actualise les infos du labyrinthe (pos1 = joueur actif) +void ajust_pos(Position* pos, int size_x, int size_y); //Ajuste la position de pos pour les depassement d'extrĂ©mitĂ©s +void rotation_pos(Position* pos, t_move move); //DĂ©place l'Ă©lĂ©ment en pos s'il se situe sur une rotation +void rotation_lab(char* labData, t_move move, int size_x, int size_y); //Modifie le labyrinthe en cas de rotation (POSSIBILITE : Placer les lignes de codes des if dans pos_suivante) + +//RANDOM +void randomove(t_move* move, Position pos1, int E, char* labData, int size_x, int size_y); //Joue alĂ©atoirement et lĂ©galement +int convert(Position pos, int size_x); //Convertit une position en deux dimensions en une position en une dimension (pour manipuler labData) +int test_case(Position pos, char* labData, int size_x); //Il faut bien mettre size_x c-a-d longueur d'une ligne c-a-d nombre de colonnes //Renvoie 1 si la case est libre, renvoie 0 si la case n'est pas libre + +//ASTAR +typedef struct cases Case; +struct cases{ + Position pos; //Case actuelle + int cost; //CoĂ»t du dĂ©part Ă  cette position + int prev; //Prevision du coĂ»t total, du dĂ©part au tresor en passant par cette position + Case* prec; //Case d'oĂą on vient +}; + +typedef struct element Element; +struct element{ + Case c; + Element* suiv; +}; +typedef Element* ListeC; + +void Astaromove(t_move* move, t_move** itineraire, Position pos1, Position tresor, char* labData, int size_x, int size_y); //Joue sans rotation pour aller le plus rapidement possible au trĂ©sor +t_move** Astar(Position pos1, Position tresor, char* labData, int size_x, int size_y); // Trouve le chemin le plus rapide jusqu'au tresor +int estimation_distance(Position J, Position P, int sizeX, int sizeY); //Estimation de l'heuristique +Case newCase(Case* c, int x, int y, Position tresor,int sizeX, int sizeY); //Initialise une case voisine Ă  c par ces coordonĂ©es +ListeC ajout_case(Case c, ListeC liste); //Ajoute c en dĂ©but de liste +void verif_voisins(Position* voisins, ListeC liste); //Modifie voisins pour qu'il ne reste que des cases non Ă©valuĂ©es +void verif_voisins_mur(Position* voisins, char* labData, int size_x); //Modifie voisins pour qu'il ne reste que des cases qui ne sont pas des murs +int verif_positions (Position P1, Position P2); //retourne 1 si P1 et P2 ont les mĂŞmes coordonĂ©es, 0 sinon +t_move** chemin(Case c); //donne l'itinĂ©raire depuis le dĂ©part pour aller jusqu'Ă  c +t_move* move_pos(Position Ini, Position Fin); //Donne le mouvement pour aller de Ini a Fin +void free_itineraire(t_move** itineraire); //Libere un tableau de move +void free_liste(ListeC liste); //Libere une liste d'Element + +//SMART +void smartmove(t_move* move, t_move** actions, int E1, Position pos1, Position pos2, Position tresor, char* labData, int size_x, int size_y); //Joue avec une stratĂ©gie pour gagner ! +void smartRotate(t_move* movef, int E1, Position pos1, Position pos2, Position tresor, char* labData, int size_x, int size_y); //Cherche la rotation la plus avantageuse avec une amplitude de recherche de varX, varY +int astarCompare(Position pos1, Position pos2, Position tresor, char* labData, int size_x, int size_y); //Retourne le nombre de coup d'avance sur l'adversaire (pos1 = Joueur Actif) +int nbcoup(t_move** itineraire);//DĂ©termine le nombre de coup necessaire pour faire l'itineraire +void reset_info(Position p1, Position* pt1, Position p2, Position* pt2, Position pt, Position* ptt, char* labData, char** labTest); //Remet les infos du labyrinthe avant un test de rotation +int update_move(t_move* movef, t_move move, int avance, int temp); //Change le move retenu si le move propose est plus interessant + +#endif + + diff --git a/makefile b/makefile new file mode 100644 index 0000000..03b535e --- /dev/null +++ b/makefile @@ -0,0 +1,34 @@ +# Modèle de fichier Makefile pour le fichier template.c +LIBDIR = /home/sasl/encad/brajard/projet/CGS_lib + +# options de compilation +CC = gcc +CCFLAGS = -Wall -I $(LIBDIR)/include +LIBS = -L $(LIBDIR)/lib +LDFLAGS = -lm -lcgs + +# fichiers du projet +SRC = template.c fonction.c random.c astar.c smartstar.c +OBJ = $(SRC:.c=.o) +EXEC = template + + +# règle initiale +all: $(EXEC) + +# dĂ©pendance des .h +template.o: + +# règles de compilation +%.o: %.c + $(CC) $(CCFLAGS) -o $@ -c $< + +# règles d'Ă©dition de liens +$(EXEC): $(OBJ) + $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) + +# règles supplĂ©mentaires +clean: + rm -f *.o +rmproper: + rm -f $(EXEC) *.o diff --git a/makefile (1) b/makefile (1) new file mode 100644 index 0000000..03b535e --- /dev/null +++ b/makefile (1) @@ -0,0 +1,34 @@ +# Modèle de fichier Makefile pour le fichier template.c +LIBDIR = /home/sasl/encad/brajard/projet/CGS_lib + +# options de compilation +CC = gcc +CCFLAGS = -Wall -I $(LIBDIR)/include +LIBS = -L $(LIBDIR)/lib +LDFLAGS = -lm -lcgs + +# fichiers du projet +SRC = template.c fonction.c random.c astar.c smartstar.c +OBJ = $(SRC:.c=.o) +EXEC = template + + +# règle initiale +all: $(EXEC) + +# dĂ©pendance des .h +template.o: + +# règles de compilation +%.o: %.c + $(CC) $(CCFLAGS) -o $@ -c $< + +# règles d'Ă©dition de liens +$(EXEC): $(OBJ) + $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) + +# règles supplĂ©mentaires +clean: + rm -f *.o +rmproper: + rm -f $(EXEC) *.o diff --git a/random.c b/random.c new file mode 100644 index 0000000..aeaf0d6 --- /dev/null +++ b/random.c @@ -0,0 +1,58 @@ +#include "fonction.h" + +void randomove(t_move* move, Position pos1, int E, char* labData, int size_x, int size_y){ //Joue alĂ©atoirement et lĂ©galement + int tabM[] ={-1, -1, -1, -1, -1, -1, -1, -1, 1}; + int i; + Position postemp; + + srand(time(NULL)); + + //ValiditĂ© de la rotation + if(E>4){ // Suffisament d'energie pour une rotation + for(i=0;i<4;i++){ tabM[i]=1; } + } + + //ValiditĂ© des cases voisines + postemp = pos1; //UP + postemp.y-=1; + ajust_pos(&postemp, size_x, size_y);//Calcul de la position haut + if (test_case(postemp, labData, size_x) == 1) {tabM[4] = 1;} //Test validitĂ© position haut + + postemp = pos1; //DOWN + postemp.y+=1; + ajust_pos(&postemp, size_x, size_y); + if (test_case(postemp, labData, size_x) == 1) {tabM[5] = 1;} + + postemp = pos1; //LEFT + postemp.x-=1; + ajust_pos(&postemp, size_x, size_y); + if (test_case(postemp, labData, size_x) == 1) {tabM[6] = 1;} + + postemp = pos1; //RIGHT + postemp.x+=1; + ajust_pos(&postemp, size_x, size_y); + if (test_case(postemp, labData, size_x) == 1) {tabM[7] = 1;} + + //AlĂ©atoire + do { + i = rand()%9; + }while (tabM[i]!=1); + + move->type=i; //Type de mouvement alĂ©atoire + + if(move->type<2){ //Si rotation Ligne + i = rand()%size_y; + move->value=i; + } + else if (move->type<4){ //Si rotation Colonne + i = rand()%size_x; + move->value=i; + } + + #ifdef DEBUG + printf("Move type :%d\n",move->type); + printf("Move Value: %d",move->value); + #endif + +} + diff --git a/smartstar.c b/smartstar.c new file mode 100644 index 0000000..560e956 --- /dev/null +++ b/smartstar.c @@ -0,0 +1,139 @@ +#include "fonction.h" + +void smartmove(t_move* move, t_move** actions, int E1, Position pos1, Position pos2, Position tresor, char* labData, int size_x, int size_y){ //Joue avec une stratĂ©gie pour gagner ! + + if(astarCompare(pos1,pos2,tresor,labData,size_x,size_y)<1 && E1>=5){ + + smartRotate(move,E1,pos1,pos2,tresor,labData,size_x,size_y); + } + if(move->type==8){ + Astaromove(move, actions, pos1, tresor, labData, size_x, size_y); + } +} + +//NOTE : SI aucun move avantageux trouvĂ©, on change var de facon a faire des recherches sur tout le labyrinthe +void smartRotate(t_move* movef, int E1, Position pos1, Position pos2, Position tresor, char* labData, int size_x, int size_y){ //Cherche la rotation la plus avantageuse avec une amplitude de recherche de varX, varY + + char* labTest; //Labyrinthe temporaire + t_move test_move; + Position ptest1, ptest2, ptestt; + int avance=0,temp=0,i=0,varX=3,varY=3; //var indique la largeur des recherches autour du tresor + + //Initialisation + movef->type=8; + movef->value=0; + + labTest = strdup(labData); //Malloc + + //Evaluations des lignes + for(i=tresor.y-varY; iavance){ //Si la rotation est plus intĂ©ressante, on la garde + movef->type = move.type; + movef->value = move.value; + return temp; + } + else{ + return avance; + } +} diff --git a/template.c b/template.c new file mode 100644 index 0000000..b7f016c --- /dev/null +++ b/template.c @@ -0,0 +1,128 @@ +// +// TEMPLATE +// +// +// Permet de jouer un seul tour (en ne faisant rien s'il commence ou en +// rĂ©ceptionnant le coup de l'adversaire s'il ne commence pas) +// et termine le jeu. +// Ce programme vous sert de base pour construire votre propre programme + + +#include +#include +#include "labyrinthAPI.h" +#include +#include "fonction.h" + + +extern int debug; /* hack to enable debug messages */ + + +int main() +{ + char labName[50]; /* name of the labyrinth */ + char* labData; /* data of the labyrinth */ + t_return_code ret = MOVE_OK; /* indicates the status of the previous move */ + t_move move; /* a move */ + t_move** itineraire=NULL; + int player, mode; + int sizeX,sizeY; + int En_M, En_Y; //Energie Me & You + Position Me, You, Tresor; + #ifdef DEBUG + int debug_counter=0; + #endif + + /* connection to the server */ + connectToServer( "pc4023.polytech.upmc.fr", 1234, "TrumpvsMexico"); + + + /* wait for a game, and retrieve informations about it */ + waitForLabyrinth( "ASTAR timeout=100", labName, &sizeX, &sizeY); + labData = (char*) malloc( sizeX * sizeY ); + player = getLabyrinth( labData); + + //Initialisation des Positions + init_info(&Me, &You, &Tresor, &En_M, &En_Y, player, sizeX, sizeY); + + #ifdef DEBUG + print_labdata(labData, sizeX, sizeY); + printf("\nTrump : (%d,%d)", Me.x, Me.y); + printf("\nMexico : (%d,%d)\n", You.x, You.y); + #endif + + printf("\nMode de Jeu : 0.Passif / 1.Manuel / 2.Random / 3.Astaromove / 4.Smartmove\n"); + scanf(" %d",&mode); + + sendComment("We will build a great WALL"); + + while(ret==MOVE_OK){ + + /* display the labyrinth */ + printLabyrinth(); + //print_labdata(labData, sizeX, sizeY); + + if (player==1) /* The opponent plays */ + { + ret = getMove( &move); + info_suivante(move, &You, &Me, &Tresor, &En_Y, labData, sizeX, sizeY); //Modification des positions + + //sendComment("The WALL got 10 feets higher !"); + } + else + { + if(mode==0){ + move.type=8; + move.value=0; + } + if(mode==1){ + defmove(&move); + } + if(mode==2){ + randomove(&move, Me, En_M, labData, sizeX, sizeY); + } + if(mode==3){ + Astaromove(&move, itineraire, Me, Tresor, labData, sizeX, sizeY); + } + if(mode==4){ + move.type=8; + move.value=0; + smartmove(&move, itineraire, En_M, Me, You, Tresor, labData, sizeX, sizeY); + } + ret = sendMove(move); + info_suivante(move, &Me, &You, &Tresor, &En_M, labData, sizeX, sizeY); //Modification des positions + + } + #ifdef DEBUG + //Test + print_labdata(labData, sizeX, sizeY); + printf("\nLes Gentils: (%d,%d)", Me.x, Me.y); + printf("\nLes MĂ©chants: (%d,%d)", You.x, You.y); + printf("\nEnergie Gentils : %d\nEnergie MĂ©chants : %d\n\n\n", En_M, En_Y); + if(debug_counter==0){ + printf("\nCombien de tour avant prochaine pause :"); + scanf(" %d",&debug_counter); + } + debug_counter--; + #endif + + if ((player ==1 && ret == MOVE_WIN) || (player==0 && ret == MOVE_LOSE)) + printf("No rage N00B\n"); + + if ((player ==0 && ret == MOVE_WIN) || (player==1 && ret == MOVE_LOSE)) + printf("GG WP\n"); + + player = (player+1)%2;//Changement de joueur + } + + /* we do not forget to free the allocated array */ + free(labData); + free_itineraire(itineraire); + + /* end the connection, because we are polite */ + closeConnection(); + + return EXIT_SUCCESS; +} + +