OloNO/ia/bouchon.c

524 lines
17 KiB
C
Raw Normal View History

2009-09-14 12:10:52 +02:00
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/select.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<signal.h>
#include<errno.h>
int joueHM(int taille, char * p2, char *log);
int joueMH(int taille, char * p1, char *log);
int joueMM(int taille, char * p1, char * p2, char *log);
int dansGrille(char col ,int lig, int taille);
void finMachineSimple(int from1, char *nom1, int status, int from2, int to2, int pid2, char *nom2, FILE *logFile);
int safeWrite(int fd, char *s);
int main(int argc, char *argv[]){
int taille;
char joueur1, joueur2, trace, rep;
char *path1 = NULL, *path2 = NULL;
char *logFile = NULL;
signal(SIGPIPE,SIG_IGN); /* on ignore les signaux de tube ferme */
printf("Bonjour\n");
printf("procedure simplifiee ? (O/N): ");
scanf(" %c",&rep);
if (rep == 'N') {
/* filtre de saisie: taille impaire, entre 5 et 25 */
do {
printf("Quelle est la taille (impaire) pour la grille ? ");
scanf("%d",&taille);
} while ((taille%2 ==0)||(taille>26)||(taille<4));
/* filtre de saisie: premier joueur humain ou programme */
do {
printf("Qui joue les blancs ? Humain ? Machine ? (H/M): ");
scanf(" %c",&joueur1);
} while ((joueur1 != 'H') && (joueur1 != 'M'));
/* filtre de saisie: second joueur humain ou programme */
do {
printf("Qui joue les noirs ? Humain ? Machine ? (H/M): ");
scanf(" %c",&joueur2);
} while ((joueur2 != 'H') && (joueur2 != 'M'));
if (joueur1 == 'M'){
/* le chemin d'acces au programme joueur 1 */
path1 = malloc(513 * sizeof(char));
printf("Veuillez entrer le chemin du programme joueur 1: ");
scanf("%s",path1);
while(access(path1,R_OK|X_OK|F_OK) != 0) {
printf("Ce fichier n'existe pas ou bien n'est pas executable\n");
printf("Veuillez entrer le chemin du programme joueur 1: ");
scanf("%s",path1);
}
}
if (joueur2 == 'M'){
/* le chemin d'acces au programme joueur 2 */
path2 = malloc(513 * sizeof(char));
printf("Veuillez entrer le chemin du programme joueur 2: ");
scanf("%s",path2);
while(access(path2,R_OK|X_OK|F_OK) != 0) {
printf("Ce fichier n'existe pas ou bien n'est pas executable\n");
printf("Veuillez entrer le chemin du programme joueur 2: ");
scanf("%s",path2);
}
}
/* si jamais on veut une trace: non implementee pour l'instant */
do {
printf("voulez-vous enregistrer la trace d'execution ? (O/N): ");
scanf(" %c",&trace);
} while (trace != 'O' && trace != 'N');
if (trace == 'O'){
logFile = malloc(513 * sizeof(char));
printf("Veuillez entrer le chemin du fichier de log: ");
scanf("%s",logFile);
}
} else { /* remplissage par defaut */
joueur1 = 'M';
joueur2 = 'M';
taille = 25;
path1 = malloc(30*sizeof(char));
strcpy(path1,"./olono");
path2 = malloc(30*sizeof(char));
strcpy(path2,"./olono-rand");
logFile = malloc(30*sizeof(char));
strcpy(logFile,"test");
}
/* maintenant on a toutes les informations qu'il faut */
/* pour l'instant, on n'implemente pas le fichier de log */
int retval;
if ((joueur1 == 'H') && (joueur2 == 'H')){
printf("Deux joueurs humains, ce n'est pas mon boulot\n");
} else if((joueur1 == 'H') && (joueur2 == 'M')) {
printf("Humain contre machine (%s), taille %d\n",path2,taille);
retval = joueHM(taille,path2,logFile);
} else if((joueur1 == 'M') && (joueur2 == 'H')) {
printf("Machine (%s) contre humain, taille %d\n",path1,taille);
retval = joueMH(taille,path1,logFile);
} else {
printf("Machine (%s) contre machine (%s)\n",path1,path2);
retval = joueMM(taille,path1,path2,logFile);
}
printf("\n\nLe jeu est termine ! \n\n");
free(path1);
free(path2);
free(logFile);
return retval;
}
int dansGrille(char col, int lig, int taille){
return (((col -'A') >= 0) && ((col - 'A') < taille) &&
(lig >= 0) && (lig < taille));
}
/* jeu d'un homme contre une machine */
int joueHM(int taille, char *p2, char *log){
int versProgramme[2]; /* tube pour envoyer des infos VERS le programme */
int deProgramme[2]; /* tube pour recuperer des infos DEPUIS le programme */
FILE *logFile = NULL;
if (log != NULL){
printf("fichier d'enregistrement: %s\n",log);
logFile = fopen(log,"w");
}
pipe(versProgramme);
pipe(deProgramme);
int pid = fork();
if (pid == -1){
perror("Fork n'a pas reussi\n");
return(-1);
} else if (pid == 0){
/* on est l'enfant: lancer le programme apres avoir
* redirige entree et sortie standard vers les tubes */
dup2(versProgramme[0],STDIN_FILENO);
dup2(deProgramme[1],STDOUT_FILENO);
close(versProgramme[1]); // pas besoin de lire ce qu'on ecrit
close(deProgramme[0]); // et inversement
char t[40];
sprintf(t,"%d",taille);
execlp(p2,p2,t,"grilleOn","ia","N",(char *) NULL);
perror("Pas reussi a executer le programme. Desole");
free(p2);
exit(-4);
} else {
/* on est le pere et pid est le pid du fils */
/* on recupere les infos du tube. On veut bien sur aussi
* garder entree et sortie standard */
close(versProgramme[0]);
close(deProgramme[1]);
printf("Vous etes les blancs, vous commencez\n");
char *coupBlanc = malloc(513 * sizeof(char));
char *coupNoir = malloc(513 * sizeof(char));
coupNoir[512] = '\0';
char colonneB, colonneN;
int ligneB, ligneN;
int nbRead;
int status;
int changed;
do {
changed = waitpid(pid,&status,WNOHANG); // on regarde si le fils n'a pas termine
if (changed == 0) {
do {
printf("Votre coup (blancs) : ");
scanf("%s",coupBlanc);
colonneB = coupBlanc[0];
sscanf(coupBlanc+1,"%d",&ligneB);
} while (dansGrille(colonneB,ligneB,taille) == 0);
printf("Vous jouez le coup: %s\n",coupBlanc);
write(versProgramme[1],coupBlanc,strlen(coupBlanc));
if (logFile != NULL){
fprintf(logFile,coupBlanc);
fflush(logFile);
}
/* attente bloquante */
nbRead = read(deProgramme[0],coupNoir,512);
printf("Lu %d caracteres\n",nbRead);
if (nbRead >= 5){
printf("Les noirs declarent %s\n",coupNoir);
} else { /* un coup legal */
printf("Les noirs jouent %s\n",coupNoir);
}
if (logFile != NULL){
fprintf(logFile,coupNoir);
fflush(logFile);
}
} else {
printf("Les noirs ont termine de jouer: %d\n",WEXITSTATUS(status));
}
} while (changed == 0);
/* on continue tant que le fils n'a pas termine */
/* puis on libere tout */
free(coupNoir);
free(coupBlanc);
close(versProgramme[1]);
close(deProgramme[0]);
return 0;
}
}
/* jeu d'une machine contre un homme */
int joueMH(int taille, char *p1, char *log){
int versProgramme[2]; /* tube pour envoyer des infos VERS le programme */
int deProgramme[2]; /* tube pour recuperer des infos DEPUIS le programme */
FILE *logFile = NULL;
if (log != NULL){
printf("fichier d'enregistrement: %s\n",log);
logFile = fopen(log,"w");
}
pipe(versProgramme);
pipe(deProgramme);
int pid = fork();
if (pid == -1){
perror("Fork n'a pas reussi\n");
return(-1);
} else if (pid == 0){
/* on est l'enfant: lancer le programme apres avoir
* redirige entree et sortie standard vers les tubes */
dup2(versProgramme[0],STDIN_FILENO);
dup2(deProgramme[1],STDOUT_FILENO);
close(versProgramme[1]); // pas besoin d ecrire ce qu'on lit
close(deProgramme[0]); // et inversement
char t[40];
sprintf(t,"%d",taille);
execlp(p1,p1,t,"grilleOn","ia","B",(char *) NULL);
perror("Pas reussi a executer le programme. Desole");
free(p1);
exit(-4);
} else {
/* on est le pere et pid est le pid du fils */
/* on recupere les infos du tube. On veut bien sur aussi
* garder entree et sortie standard */
close(versProgramme[0]);
close(deProgramme[1]);
printf("Vous etes les noirs, vous jouez en second\n");
char *coupBlanc = malloc(513 * sizeof(char));
char *coupNoir = malloc(513 * sizeof(char));
coupBlanc[512] = '\0';
char colonneB, colonneN;
int ligneB, ligneN;
int nbRead;
int status;
int changed;
do {
changed = waitpid(pid,&status,WNOHANG); // on regarde si le fils n'a pas termine
if (changed == 0) {
/* attente bloquante ??? */
nbRead = read(deProgramme[0],coupBlanc,512*sizeof(char));
if (nbRead >= 5){
printf("Les blancs declarent: %s",coupBlanc);
} else { /* un coup legal */
printf("Les blancs jouent: %s",coupBlanc);
}
if (logFile != NULL){
fprintf(logFile,coupBlanc);
fflush(logFile);
}
changed = waitpid(pid,&status,WNOHANG); // on teste encore une fois le fils
if (changed == 0) {
do {
printf("Votre coup (noirs) : ");
scanf("%s",coupNoir);
colonneN = coupNoir[0];
sscanf(coupNoir+1,"%d",&ligneN);
} while (dansGrille(colonneN,ligneN,taille) == 0);
printf("Vous jouez le coup: %s\n",coupNoir);
write(versProgramme[1],coupNoir,strlen(coupNoir));
if (logFile != NULL){
fprintf(logFile,coupNoir);
fflush(logFile);
}
}
} else {
printf("Les blancs ont termine de jouer: %d\n",WEXITSTATUS(status));
}
} while (changed == 0);
/* on continue tant que les blancs n'ont pas termine */
/* puis on libere tout */
free(coupNoir);
free(coupBlanc);
close(versProgramme[1]);
close(deProgramme[0]);
return 0;
}
}
int joueMM(int taille, char *p1, char *p2, char *log){
FILE *logFile = NULL;
if (log != NULL){
printf("fichier d'enregistrement: %s\n",log);
logFile = fopen(log,"w");
}
int versProgrammeA[2], versProgrammeB[2];
int deProgrammeA[2], deProgrammeB[2];
pipe(versProgrammeA);
pipe(deProgrammeA);
int pidA = fork();
if (pidA == -1){
perror("Fork n'a pas reussi");
return(-1);
} else if (pidA == 0){
/* fils A: les blancs */
dup2(versProgrammeA[0],STDIN_FILENO);
dup2(deProgrammeA[1],STDOUT_FILENO);
close(versProgrammeA[1]);
close(deProgrammeA[0]);
fclose(logFile);
char t[40];
sprintf(t,"%d",taille);
execlp(p1,p1,t,"grilleOn","ia","B",(char *) NULL);
perror("Pas reussi a executer le programme A. Desole");
return -4;
} else {
/* pere */
pipe(versProgrammeB);
pipe(deProgrammeB);
close(versProgrammeA[0]);
close(deProgrammeA[1]);
int pidB = fork();
if (pidB == -1){
perror("Fork 2 n'a pas reussi");
return -1; /* le fils A est tue quand le pere meurt */
} else if (pidB == 0) {
/* fils B: les noirs */
close(versProgrammeA[1]);
close(deProgrammeA[0]);
close(versProgrammeB[1]);
close(deProgrammeB[0]);
fclose(logFile);
dup2(versProgrammeB[0],STDIN_FILENO);
dup2(deProgrammeB[1],STDOUT_FILENO);
char t[40];
sprintf(t,"%d",taille);
execlp(p2,p2,t,"grilleOff","ia","N",(char *) NULL);
perror("Pas reussi a executer le programme B. Desole");
return -5;
} else {
/* le pere */
close(versProgrammeB[0]);
close(deProgrammeB[1]);
char *coupBlanc = malloc(513 * sizeof(char));
char *coupNoir = malloc(513 * sizeof(char));
int nbRead;
int status;
int changed;
int i=0;
do {
changed = waitpid(pidA,&status,WNOHANG);
if (changed == 0) {
nbRead = read(deProgrammeA[0],coupBlanc,512);
coupBlanc[nbRead] = '\0';
if (nbRead >= 5){
printf("Les blancs declarent: %s",coupBlanc);
} else { /* un coup legal: colonne, ligne, \n et \0 */
printf("Les blancs jouent: %s",coupBlanc);
}
safeWrite(versProgrammeB[1],coupBlanc);
if (logFile != NULL){
fprintf(logFile,coupBlanc);
fflush(logFile);
}
changed = waitpid(pidB,&status,WNOHANG);
if (changed == 0){
nbRead = read(deProgrammeB[0],coupNoir,512);
coupNoir[nbRead] = '\0';
if (nbRead >= 5){
printf("Les noirs declarent: %s",coupNoir);
} else { /* un coup legal: colonne, ligne, \n et \0 */
printf("Les noirs jouent: %s",coupNoir);
}
/* tester si on peut ecrire avant de le faire ! Sinon ca plante */
safeWrite(versProgrammeA[1],coupNoir);
if (logFile != NULL){
fprintf(logFile,coupNoir);
fflush(logFile);
}
} else {
finMachineSimple(deProgrammeB[0],"noirs",status,deProgrammeA[0],versProgrammeA[1],pidA,"blancs",logFile);
}
} else {
finMachineSimple(deProgrammeA[0],"blancs",status,deProgrammeB[0],versProgrammeB[1],pidB,"noirs",logFile);
}
} while (changed == 0);
free(coupNoir);
free(coupBlanc);
if (logFile != NULL){
fprintf(logFile,"\n---- partie terminee ----\n ");
fflush(logFile);
fclose(logFile);
}
close(versProgrammeA[1]);
close(deProgrammeA[0]);
close(versProgrammeB[1]);
close(deProgrammeB[0]);
return 0;
} // fin second fork
} // fin premier fork
}
void finMachineSimple(int from1, char *nom1, int status, int from2, int to2, int pid2, char *nom2, FILE *logFile){
int nbRead;
char *coup1 = malloc(513 * sizeof(char));
char *coup2 = malloc(513 * sizeof(char));
struct rusage infoFils;
double uFils1, sFils1, uFils2, sFils2;
printf("Les %s ont termine de jouer: %d!\n",nom1,WEXITSTATUS(status));
getrusage(RUSAGE_CHILDREN,&infoFils);
/* on recupere des secondes et des micro secondes pour le temps CPU passe
* en calculs utilisateurs et en appel de fonctions systeme du fils 1 */
sFils1 = ((double) infoFils.ru_stime.tv_sec) + ((double) infoFils.ru_stime.tv_usec)/1000000;
uFils1 = ((double) infoFils.ru_utime.tv_sec) + ((double) infoFils.ru_utime.tv_usec)/1000000;
printf("Les %s ont utilise %lf sec de systeme et %lf de temps utilisateur\n",
nom1,sFils1,uFils1);
nbRead = read(from1,coup1,512);
if (nbRead > 0){
coup1[nbRead] = '\0';
printf("Les %s ont un dernier message: %s",nom1,coup1);
safeWrite(to2,coup1);
if (logFile != NULL){
fprintf(logFile,coup1);
fflush(logFile);
}
}
sleep(1); /* on attend une seconde que l'autre ait aussi termine ! */
if (waitpid(pid2,&status,WNOHANG) == 0){
printf("Cependant, les %s n'ont pas termine de jouer ... tant pis.\n",nom2);
/* on les tue */
kill(pid2,SIGKILL);
waitpid(pid2,&status,WNOHANG);
} else {
printf("Les %s on aussi termine: %d!\n",nom2,WEXITSTATUS(status));
}
getrusage(RUSAGE_CHILDREN,&infoFils);
/* idem, sauf qu'on recupere la somme du fils 1 et du fils 2 ... */
sFils2 = ((double) infoFils.ru_stime.tv_sec) + ((double) infoFils.ru_stime.tv_usec)/1000000;
uFils2 = ((double) infoFils.ru_utime.tv_sec) + ((double) infoFils.ru_utime.tv_usec)/1000000;
/* idem, sauf qu'on recupere la somme du fils 1 et du fils 2 */
sFils2 = sFils2 - sFils1;
uFils2 = uFils2 - uFils1;
printf("Les %s ont utilise %lf sec de systeme et %lf de temps utilisateur\n",
nom2,sFils2,uFils2);
nbRead = read(from2,coup2,512);
if(nbRead > 0){
coup2[nbRead] = '\0';
printf("Les %s ont un dernier message: %s",nom2,coup2);
if (logFile != NULL){
fprintf(logFile,coup2);
fflush(logFile);
}
}
}
/* ecrit de facon "sure" dans un tube: si on essaie d'ecrire dans un tube *
* ferme, on recoit un signal qui fait terminer le programme */
/* retourne le nombre de caracteres ecrit et -1 si ca s'est mal passe */
int safeWrite(int fd, char *s){
if (write(fd,s,strlen(s)) == -1)
printf("Impossible d'ecrire dans le tube: il est ferme en lecture\n");
return 0;
}
/* vieux machin complique et qui marche pas
void finMachine(int from1, char *nom1, int status, int from2, int to2, int pid2, char *nom2, FILE *logFile){
int nbRead;
fd_set set;
struct timeval timeout = {1,0};// timeout a 1 seconde
char *coup1 = malloc(513 * sizeof(char));
char *coup2 = malloc(513 * sizeof(char));
printf("Les %s ont termine de jouer: %d!\n",nom1,WEXITSTATUS(status));
FD_ZERO(&set);
FD_SET(from1,&set);
// s'il y a encore des choses a lire
if (select(from1+1,&set,NULL,NULL,&timeout) == 0){
printf("Les %s n'ont rien d'autre a ajouter\n",nom1);
} else {
nbRead = read(from1,coup1,512);
coup1[nbRead] = '\0';
printf("Les %s ont un dernier message: %s",nom1,coup1);
safeWrite(to2,coup1);
if (logFile != NULL){
fprintf(logFile,coup1);
fflush(logFile);
}
}
if (waitpid(pid2,&status,WNOHANG) == 0){
printf("Cependant, les %s n'ont pas termine de jouer ... tant pis.\n",nom2);
} else {
printf("Les %s on aussi termine: %d!\n",nom2,WEXITSTATUS(status));
}
FD_ZERO(&set);
FD_SET(from2,&set);
if (select(from2+1,&set,NULL,NULL,&timeout) == 0){
printf("Les %s n'ont rien a dire\n",nom2);
} else {
nbRead = read(from2,coup2,512);
coup2[nbRead] = '\0';
printf("Les %s ont un dernier message: %s",nom2,coup2);
if (logFile != NULL){
fprintf(logFile,coup2);
fflush(logFile);
}
}
}
*/