Initial commit
This commit is contained in:
parent
ab6c3353e2
commit
13161bcbd7
17 changed files with 1335 additions and 0 deletions
173
LABY
Normal file
173
LABY
Normal file
|
@ -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
|
6
Notes
Normal file
6
Notes
Normal file
|
@ -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 ?
|
BIN
Patchs/Document sans titre.docx
Normal file
BIN
Patchs/Document sans titre.docx
Normal file
Binary file not shown.
111
Patchs/Patch Astaromove.txt
Normal file
111
Patchs/Patch Astaromove.txt
Normal file
|
@ -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;i<nb_move;i++){
|
||||
temp_pos=temp_case->pos;
|
||||
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;
|
||||
|
||||
...
|
||||
|
||||
|
35
Patchs/patch random.txt
Normal file
35
Patchs/patch random.txt
Normal file
|
@ -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;i<size_x-1;i++){ //On parcours la ligne en question en échangeant les termes vers la gauche
|
||||
labData[CV(i,move.value,size_x)]=labData[CV(i+1,move.value,size_x)];
|
||||
}
|
||||
labData[CV(size_x-1,move.value,size_x)]=temp; // On place le terme a la fin de la ligne
|
||||
}
|
||||
if(move.type==ROTATE_LINE_RIGHT){
|
||||
temp=labData[CV(size_x-1,move.value,size_x)]; //On garde en mémoire le dernier terme de la ligne
|
||||
for(i=size_x-1;i>0;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;i<size_y-1;i++){ //On parcours la colonne de haut en bas en échangeant les terme vers le haut
|
||||
labData[CV(move.value, i, size_x)]=labData[CV(move.value, i+1, size_x)];
|
||||
}
|
||||
labData[CV(move.value,size_y-1,size_x)]=temp; //On place le terme la fin de la colonne
|
||||
}
|
||||
if(move.type==ROTATE_COLUMN_DOWN){
|
||||
temp=labData[CV(move.value, size_y-1, size_x)]; //On garde en mémoire le dernier terme de la colonne
|
||||
for(i=size_y-1;i>0;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
|
||||
}
|
||||
}
|
BIN
Slide Projet info HARLE ZHONG.pptx
Normal file
BIN
Slide Projet info HARLE ZHONG.pptx
Normal file
Binary file not shown.
24
Test/main.c
Normal file
24
Test/main.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include <stdio.h>
|
||||
|
||||
|
||||
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;
|
||||
|
||||
}
|
37
Test/test.c
Normal file
37
Test/test.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
//Fait un move aléatoire
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//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;}
|
||||
|
||||
}
|
298
astar.c
Normal file
298
astar.c
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
|
BIN
enonce.pdf
Normal file
BIN
enonce.pdf
Normal file
Binary file not shown.
187
fonction.c
Normal file
187
fonction.c
Normal file
|
@ -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;i<size_x-1;i++){ //On parcours la ligne en question en échangeant les termes vers la gauche
|
||||
labData[(move.value*size_x)+i]=labData[(move.value*size_x)+i+1];
|
||||
}
|
||||
labData[((move.value+1)*size_x)-1]=temp; // On place le terme a la fin de la ligne
|
||||
}
|
||||
if(move.type==ROTATE_LINE_RIGHT){
|
||||
temp=labData[((move.value+1)*size_x)-1]; //On garde en mémoire le dernier terme de la ligne
|
||||
for(i=size_x-1;i>0;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;i<size_y-1;i++){ //On parcours la colonne de haut en bas en échangeant les terme vers le haut
|
||||
labData[move.value+size_x*(i-1)]=labData[move.value+size_x*i];
|
||||
}
|
||||
labData[size_x*(size_y-1)+move.value]=temp; //On place le terme la fin de la colonne
|
||||
}
|
||||
if(move.type==ROTATE_COLUMN_DOWN){
|
||||
temp=labData[size_x*(size_y-1)+move.value]; //On garde en mémoire le dernier terme de la colonne
|
||||
for(i=size_y-1;i>0;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;}
|
||||
}
|
||||
|
||||
|
||||
|
71
fonction.h
Normal file
71
fonction.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef __FONCTION_H__
|
||||
#define __FONCTION_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "labyrinthAPI.h"
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
//#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
|
||||
|
||||
|
34
makefile
Normal file
34
makefile
Normal file
|
@ -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
|
34
makefile (1)
Normal file
34
makefile (1)
Normal file
|
@ -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
|
58
random.c
Normal file
58
random.c
Normal file
|
@ -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
|
||||
|
||||
}
|
||||
|
139
smartstar.c
Normal file
139
smartstar.c
Normal file
|
@ -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; i<tresor.y+varY; i++){
|
||||
|
||||
//Rotation vers la gauche
|
||||
test_move.type=0;
|
||||
test_move.value=i;
|
||||
|
||||
info_suivante(test_move, &ptest1, &ptest2, &ptestt, &E1, labTest, size_x, size_y);
|
||||
|
||||
//Calcul de l'avantage de la rotation
|
||||
temp = astarCompare(ptest1, ptest2, ptestt, labTest, size_x, size_y);
|
||||
avance = update_move(movef, test_move, avance, temp); //Changement du move final si necessaire
|
||||
|
||||
reset_info(pos1, &ptest1, pos2, &ptest2, tresor, &ptestt, labData, &labTest); //Reinitialisation
|
||||
|
||||
//Rotation vers la droite
|
||||
test_move.type=1;
|
||||
test_move.value=i;
|
||||
|
||||
info_suivante(test_move, &ptest1, &ptest2, &ptestt, &E1, labTest, size_x, size_y);
|
||||
|
||||
//Calcul de l'avantage de la rotation
|
||||
temp = astarCompare(ptest1, ptest2, ptestt, labTest, size_x, size_y);
|
||||
avance = update_move(movef, test_move, avance, temp); //Changement du move final si necessaire
|
||||
|
||||
reset_info(pos1, &ptest1, pos2, &ptest2, tresor, &ptestt, labData, &labTest); //Reinitialisation
|
||||
}
|
||||
|
||||
//Evaluations des colonnes
|
||||
for(i=tresor.x-varX; i<tresor.x+varX; i++){
|
||||
|
||||
//Rotation vers le haut
|
||||
test_move.type=2;
|
||||
test_move.value=i;
|
||||
|
||||
info_suivante(test_move, &ptest1, &ptest2, &ptestt, &E1, labTest, size_x, size_y);
|
||||
|
||||
//Calcul de l'avantage de la rotation
|
||||
temp = astarCompare(ptest1, ptest2, ptestt, labTest, size_x, size_y);
|
||||
avance = update_move(movef, test_move, avance, temp); //Changement du move final si necessaire
|
||||
|
||||
reset_info(pos1, &ptest1, pos2, &ptest2, tresor, &ptestt, labData, &labTest); //Reinitialisation
|
||||
|
||||
//Rotation vers le bas
|
||||
test_move.type=3;
|
||||
test_move.value=i;
|
||||
|
||||
info_suivante(test_move, &ptest1, &ptest2, &ptestt, &E1, labTest, size_x, size_y);
|
||||
|
||||
//Calcul de l'avantage de la rotation
|
||||
temp = astarCompare(ptest1, ptest2, ptestt, labTest, size_x, size_y);
|
||||
avance = update_move(movef, test_move, avance, temp); //Changement du move final si necessaire
|
||||
|
||||
reset_info(pos1, &ptest1, pos2, &ptest2, tresor, &ptestt, labData, &labTest); //Reinitialisation
|
||||
}
|
||||
//Free
|
||||
free(labTest);
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
t_move** itineraire1 = NULL;
|
||||
t_move** itineraire2 = NULL;
|
||||
int nbcoup1, nbcoup2;
|
||||
|
||||
//Estimation des itineraires des joueurs
|
||||
itineraire1 = Astar(pos1, tresor, labData, size_x, size_y);
|
||||
itineraire2 = Astar(pos2, tresor, labData, size_x, size_y);
|
||||
|
||||
//Estimation du nombre de coup jusqu'au tresor
|
||||
nbcoup1 = nbcoup(itineraire1);
|
||||
nbcoup2 = nbcoup(itineraire2);
|
||||
|
||||
//Free
|
||||
free_itineraire(itineraire1);
|
||||
free_itineraire(itineraire2);
|
||||
|
||||
return nbcoup2 - nbcoup1; //Plus c'est positif, plus c'est a notre avantage
|
||||
}
|
||||
|
||||
int nbcoup(t_move** itineraire){//Détermine le nombre de coup necessaire pour faire l'itineraire
|
||||
|
||||
int i=0;
|
||||
|
||||
if (itineraire[i]!=NULL){
|
||||
while (itineraire[i]!=NULL){i++;}
|
||||
i++; //On compte le move de rang 0
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
*pt1 = p1;
|
||||
*pt2 = p2;
|
||||
*ptt = pt;
|
||||
strcpy(*labTest, labData);
|
||||
}
|
||||
|
||||
|
||||
int update_move(t_move* movef, t_move move, int avance, int temp){ //Change le move retenu si le move propose est plus interessant
|
||||
|
||||
if(temp>avance){ //Si la rotation est plus intéressante, on la garde
|
||||
movef->type = move.type;
|
||||
movef->value = move.value;
|
||||
return temp;
|
||||
}
|
||||
else{
|
||||
return avance;
|
||||
}
|
||||
}
|
128
template.c
Normal file
128
template.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "labyrinthAPI.h"
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue