|
|
@ -102,71 +102,128 @@ int read_from_stdin(char *str, int length) |
|
|
|
|
|
|
|
void interact(int width) |
|
|
|
{ |
|
|
|
/* Avant de permettre à l'utilisateur d'intéragir
|
|
|
|
* avec la grille, encore faut-il la générer ! */ |
|
|
|
grid *gd = init_grid(width); |
|
|
|
refresh_grid(gd); |
|
|
|
init_player_route(gd); |
|
|
|
|
|
|
|
// Afficher un message de bienvenue et d'aide courte
|
|
|
|
printf("Welcome to Catwalk CLI. Type 'help' or '?' to see all available commands.\n"); |
|
|
|
|
|
|
|
/* Création des deux tableaux de caractères contenant les
|
|
|
|
* entrées de l'utilisateur. Le premier sert à stocker |
|
|
|
* directement les entrées de l'utilisateur. Le second est |
|
|
|
* utilisé pour permettre la copie et la modification |
|
|
|
* du premier. */ |
|
|
|
char prompt[COMMAND_MAX_SIZE] = ""; |
|
|
|
char buffer[COMMAND_MAX_SIZE] = ""; |
|
|
|
|
|
|
|
refresh_grid(gd); |
|
|
|
init_player_route(gd); |
|
|
|
|
|
|
|
// Boucle principale
|
|
|
|
for(;;) |
|
|
|
{ |
|
|
|
// vérification de la non-vacuité de prompt
|
|
|
|
if (is_whitespace(prompt)) |
|
|
|
{ |
|
|
|
printf("catwalk> "); |
|
|
|
printf("catwalk> "); // affichage
|
|
|
|
|
|
|
|
// on met dans "prompt" l'entrée de l'utilisateur
|
|
|
|
read_from_stdin(prompt, COMMAND_MAX_SIZE); |
|
|
|
|
|
|
|
/* on met une copie de "prompt" dans
|
|
|
|
* "buffer" sans les espaces */ |
|
|
|
ltrim(buffer, prompt); |
|
|
|
|
|
|
|
// on remet tout dans "prompt"
|
|
|
|
strcpy(prompt, buffer); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
/* Succession d'expressions conditionnelles.
|
|
|
|
* Fonctionnement de l'entrée : l'utilisateur |
|
|
|
* entre une suite de commandes; elles sont |
|
|
|
* éxécutées successivement : par exemple, |
|
|
|
* "llurus" est éxécuté comme cela : |
|
|
|
* - "l" comme "left" (X2) |
|
|
|
* - "u" comme "up" |
|
|
|
* - "r" comme "right" |
|
|
|
* - "u" comme "up" |
|
|
|
* - "s" comme "show" |
|
|
|
* Pour éviter les problèmes du type : |
|
|
|
* prompt = "undo" : j'éxécute "u" pour "up" |
|
|
|
* -> prompt = "ndo": commande inconnue, |
|
|
|
* Les commandes en toutes lettres sont testées |
|
|
|
* avant les commandes abrégées. */ |
|
|
|
if STR_STARTS_WITH(prompt, "help") |
|
|
|
{ |
|
|
|
print_help(); |
|
|
|
print_help(); // action correspondante
|
|
|
|
|
|
|
|
/* on enlève "help" de prompt et décale
|
|
|
|
* les caractères en conséquence */ |
|
|
|
strcpy(buffer, prompt+strlen("help")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "?") |
|
|
|
{ |
|
|
|
print_help(); |
|
|
|
print_help(); // action correspondante
|
|
|
|
|
|
|
|
/* on enlève "?" de prompt et décale
|
|
|
|
* les caractères en conséquence */ |
|
|
|
strcpy(buffer, prompt+strlen("?")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "show") |
|
|
|
{ |
|
|
|
/* on affiche la grille, en précisant qu'elle
|
|
|
|
* est interactive (afficher le chemin) */ |
|
|
|
print_interactive_grid(gd); |
|
|
|
|
|
|
|
/* on enlève "show" de prompt et décale
|
|
|
|
* les caractères en conséquence */ |
|
|
|
strcpy(buffer, prompt+strlen("show")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "reset") |
|
|
|
{ |
|
|
|
// Réinitialisation de la grille
|
|
|
|
|
|
|
|
/* si le chemin du joueur ne
|
|
|
|
* contient qu'un élément */ |
|
|
|
if (gd->player_route->first->next == NULL) |
|
|
|
{ |
|
|
|
// demander à jouer d'abord
|
|
|
|
printf("Play first!\n"); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
/* supprimer récursivement tous les éléments
|
|
|
|
* du chemin du joueur, sauf le premier */ |
|
|
|
delete_element(gd->player_route->first->next); |
|
|
|
gd->player_route->first->next = NULL; |
|
|
|
gd->player_route->last = gd->player_route->first; |
|
|
|
} |
|
|
|
|
|
|
|
// supprimer "reset" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("reset")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "route") |
|
|
|
{ |
|
|
|
// afficher le chemin
|
|
|
|
print_route(gd->player_route); |
|
|
|
strcpy(buffer, prompt+strlen("route")); |
|
|
|
|
|
|
|
// supprimer "route" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("route")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if (STR_STARTS_WITH(prompt, "exit") || STR_STARTS_WITH(prompt, "quit") || STR_STARTS_WITH(prompt, "q")) |
|
|
|
{ |
|
|
|
// arrêter l'interaction
|
|
|
|
break; |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "undo") |
|
|
|
{ |
|
|
|
// annulation imposible s'il n'y a qu'un unique élément
|
|
|
|
if (gd->player_route->first->next == NULL) |
|
|
|
{ |
|
|
|
printf("Can't undo! (single element)\n"); |
|
|
@ -175,87 +232,129 @@ void interact(int width) |
|
|
|
{ |
|
|
|
pop_back(gd->player_route); |
|
|
|
} |
|
|
|
|
|
|
|
// supprimer "undo" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("undo")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "left") |
|
|
|
{ |
|
|
|
/* tenter de se déplacer, et si erreur,
|
|
|
|
* afficher le message correspondant */ |
|
|
|
switch (move_left(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// supprimer "left" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("left")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "right") |
|
|
|
{ |
|
|
|
/* tenter de se déplacer, et si erreur,
|
|
|
|
* afficher le message correspondant */ |
|
|
|
switch (move_right(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// supprimer "right" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("right")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "up") |
|
|
|
{ |
|
|
|
/* tenter de se déplacer, et si erreur,
|
|
|
|
* afficher le message correspondant */ |
|
|
|
switch (move_up(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// supprimer "up" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("up")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "down") |
|
|
|
{ |
|
|
|
/* tenter de se déplacer, et si erreur,
|
|
|
|
* afficher le message correspondant */ |
|
|
|
switch (move_down(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// supprimer "down" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("down")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "s") |
|
|
|
{ |
|
|
|
// afficher la grille
|
|
|
|
print_interactive_grid(gd); |
|
|
|
|
|
|
|
// supprimer "s" de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("s")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "l") |
|
|
|
{ |
|
|
|
// se déplacer
|
|
|
|
switch (move_left(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// MàJ de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("l")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "r") |
|
|
|
{ |
|
|
|
// se déplacer
|
|
|
|
switch (move_right(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// MàJ de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("r")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "u") |
|
|
|
{ |
|
|
|
// se déplacer
|
|
|
|
switch (move_up(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// MàJ de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("u")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "d") |
|
|
|
else if STR_STARTS_WITH(prompt, "d") |
|
|
|
{ |
|
|
|
switch (move_down(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
strcpy(buffer, prompt+strlen("d")); |
|
|
|
|
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "z") |
|
|
|
{ |
|
|
|
// annuler, mais seulement si possible
|
|
|
|
if (gd->player_route->first->next == NULL) |
|
|
|
{ |
|
|
|
printf("Can't undo! (single element)\n"); |
|
|
@ -264,30 +363,25 @@ void interact(int width) |
|
|
|
{ |
|
|
|
pop_back(gd->player_route); |
|
|
|
} |
|
|
|
strcpy(buffer, prompt+strlen("d")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else if STR_STARTS_WITH(prompt, "z") |
|
|
|
{ |
|
|
|
switch (move_down(gd->player_route)) |
|
|
|
{ |
|
|
|
case 1: puts("Cannot move: border of the grid"); break; |
|
|
|
case 2: puts("Cannot move: already went there"); break; |
|
|
|
} |
|
|
|
|
|
|
|
// MàJ de prompt
|
|
|
|
strcpy(buffer, prompt+strlen("z")); |
|
|
|
ltrim(prompt, buffer); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// afficher un message d'erreur
|
|
|
|
printf("Unrecognized command : '%s'!\n", prompt); |
|
|
|
prompt[0] = '\0'; |
|
|
|
prompt[0] = '\0'; // effacer prompt
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (gd->player_route->last->x == gd->end[0] && gd->player_route->last->y == gd->end[1]) |
|
|
|
{ |
|
|
|
print_interactive_grid(gd); |
|
|
|
print_interactive_grid(gd); // afficher à nouveau la grille
|
|
|
|
|
|
|
|
// afficher un message de fin
|
|
|
|
if (verify(gd)) |
|
|
|
{ |
|
|
|
printf("You won!\n"); |
|
|
@ -297,11 +391,13 @@ void interact(int width) |
|
|
|
printf("You lost!\n"); |
|
|
|
} |
|
|
|
|
|
|
|
// régénérer la grille
|
|
|
|
random_start(gd); |
|
|
|
refresh_grid(gd); |
|
|
|
reset_player_route(gd); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Pour finir, détruire la grille
|
|
|
|
delete_grid(gd); |
|
|
|
} |
|
|
|