Compare commits

...

14 Commits

Author SHA1 Message Date
5d4f148003 todo update 2026-04-27 00:04:36 +02:00
97987b649a added the asm, even though after 4 hours of debugging it still didn't worked ( and using ai to debug ) this was an interesting add-on 2026-04-27 00:01:20 +02:00
58cc78a9a7 e 2026-04-26 23:55:55 +02:00
46d24f5367 one of the last commit 2026-04-26 23:51:55 +02:00
edc421996f newcows options -T and -p 2026-04-26 22:39:02 +02:00
eab4fe940e tamagoshi_cow 2026-04-26 22:35:02 +02:00
6213633c13 finished last C file 2026-04-26 21:36:09 +02:00
01f0b552ac bash scripts done 2026-04-26 19:41:31 +02:00
ea416d1a2e update the TODO.md 2026-04-23 13:42:40 +02:00
0fb0597f26 jfqdskfjsqdkl 2026-04-23 13:40:12 +02:00
a2d27a2ea8 first version of the reading cow 2026-04-22 14:04:38 +02:00
6620de21ad created animated cow 2026-04-22 13:57:49 +02:00
ae219bbff4 Q2 2026-04-22 13:52:01 +02:00
528de80d51 first question of C 2026-04-22 13:49:33 +02:00
14 changed files with 1128 additions and 68 deletions

BIN
LICENSE

Binary file not shown.

117
README.md
View File

@@ -1,3 +1,118 @@
# cowsay # cowsay
cowsay project for school Projet INF203 autour de `cowsay`.
Cette même README est aussi publiée sur le site : <https://docs.fare-elouan.net/cowsay>, Les graphisme pour la charte seront mieux
il y a aussi le depot sur <https://git.fare-elouan.net/school/cowsay>
## Contenu du dépôt
- `start.sh` : lance un tour guidé de la plupart des programmes du projet.
- `ProjetCowsay.pdf` : document de projet au format PDF.
- `TODO.md` : checklist de suivi du travail demandé.
- `src/bash_scripts/` : scripts Bash.
- `src/C/` : programmes C principaux.
- `src/C/newcows/` : variantes C supplémentaires et script de compilation rapide.
## Dépendances
Pour exécuter tout le projet, il faut au minimum :
- `bash`
- `cowsay`
- `bc` pour `smart_cow.sh`
- un compilateur C : `cc`, `clang` ou `gcc`
## Lancement rapide
Depuis la racine du dépôt :
```bash
bash start.sh
```
Le script de démonstration compile les programmes C dans un dossier temporaire puis exécute les différents exemples les uns après les autres.
## Résumé des scripts Bash
| Programme | Rôle | Exemple |
| --- | --- | --- |
| `cow_kindergarten.sh` | Fait parler la vache de `1` à `10`, avec une pause d'une seconde entre chaque valeur, puis termine avec une langue sortie. | `bash src/bash_scripts/cow_kindergarten.sh` |
| `cow_primaryschool.sh` | Fait parler la vache de `1` à `n`. | `bash src/bash_scripts/cow_primaryschool.sh 5` |
| `cow_highschool.sh` | Affiche les carrés parfaits de `1^2` à `n^2`. | `bash src/bash_scripts/cow_highschool.sh 5` |
| `cow_college.sh` | Affiche les `n` premiers termes de la suite de Fibonacci avec mémoïsation. | `bash src/bash_scripts/cow_college.sh 7` |
| `cow_university.sh` | Affiche les nombres premiers jusqu'à `n` avec un crible d'Ératosthène. | `bash src/bash_scripts/cow_university.sh 30` |
| `smart_cow.sh` | Évalue une expression arithmétique simple et essaie d'afficher le résultat dans les yeux de la vache. | `bash src/bash_scripts/smart_cow.sh '4+13'` |
| `crazy_cow.sh` | Génère une suite "look-and-say" de manière interactive, puis affiche toutes les étapes dans `cowsay`. | `bash src/bash_scripts/crazy_cow.sh` |
## Résumé des programmes C
| Programme | Rôle | Exemple |
| --- | --- | --- |
| `src/C/newcow.c` | Affiche une vache ASCII sans bulle, avec option `-e` ou `--eyes` pour changer les yeux. | `cc src/C/newcow.c -o /tmp/newcow && /tmp/newcow -e ^^` |
| `src/C/newcows/newcowT.c` | Variante de `newcow` qui gère la langue avec l'option `-T`. | `cc src/C/newcows/newcowT.c -o /tmp/newcowT && /tmp/newcowT -T U` |
| `src/C/newcows/newcowp.c` | Ajoute une bulle de texte simple au-dessus de la vache. | `cc src/C/newcows/newcowp.c -o /tmp/newcowp && /tmp/newcowp -p "Hello"` |
| `src/C/newcows/makefilealacon.sh` | Compile rapidement un fichier `.c` en un exécutable `.out` avec `clang`. | `bash src/C/newcows/makefilealacon.sh src/C/newcows/newcowT.c` |
| `src/C/newcow2.c` | Regroupe plusieurs animations terminales : clignement, langue, marche, rebond. | `cc src/C/newcow2.c -o /tmp/newcow2 && /tmp/newcow2 blink` |
| `src/C/reading_cow.c` | Lit un fichier caractère par caractère et montre la vache en train de "manger" le texte. | `cc src/C/reading_cow.c -o /tmp/reading_cow && /tmp/reading_cow --i 0.10 README.md` |
| `src/C/tamagoshi_cow.c` | Mini jeu en boucle avec gestion de `stock`, `fitness` et score de survie. | `cc src/C/tamagoshi_cow.c -o /tmp/tamagoshi_cow && /tmp/tamagoshi_cow` |
## Tour d'ensemble du projet
1. Bash simple avec comptage et pauses.
2. Bash plus algorithmique avec carrés, Fibonacci et nombres premiers.
3. Personnalisation de la vache en C.
4. Animations et interactions dans le terminal.
5. Programme de lecture de fichier.
6. Automate de jeu avec états pour le tamagotchi.
## Partie automate
- `liferocks` si `fitness` est entre `4` et `6`
- `lifesucks` si `fitness` est entre `1` et `3` ou entre `7` et `9`
- `byebyelife` si `fitness` vaut `0` ou `10`
À chaque tour :
- le joueur choisit `lunchfood`
- `fitness` est mise à jour avec un effet de digestion aléatoire
- `stock` est mis à jour avec une variation aléatoire de récolte
- si `fitness` atteint `0` ou `10`, la partie s'arrête
```flow
st=>start: Début du jeu
init=>operation: fitness = 5 ; stock = 5 ; score = 0
etat=>condition: fitness == 0 ou fitness == 10 ?
mort=>end: byebyelife Afficher score final
checkRock=>condition: 4 ≤ fitness ≤ 6 ?
liferocks=>operation: liferocks;Afficher vache saine
lifesucks=>operation: lifesucks;Afficher vache malade
affStock=>operation: Afficher stock
choix=>operation: lunchfood choisi;0 ≤ lunchfood ≤ stock
alea=>operation: digestion ∈ [-3,0];crop ∈ [-3,3]
majFit=>operation: fitness = fitness + lunchfood + digestion
clampFit=>operation: fitness borné entre 0 et 10
majStock=>operation: stock = stock - lunchfood + crop
clampStock=>operation: stock borné entre 0 et 10
score=>operation: score += 1
st->init->etat
etat(yes)->mort
etat(no)->checkRock
checkRock(yes)->liferocks->affStock
checkRock(no)->lifesucks->affStock
affStock->choix->alea->majFit->clampFit->majStock->clampStock->score->etat
```
## Remarques
- Il faut utiliser start.sh pour avoir une demo du projet

72
TODO.md
View File

@@ -28,56 +28,56 @@
- [x] **`cow_university`** - [x] **`cow_university`**
- [x] Cow says prime numbers up to `n`. - [x] Cow says prime numbers up to `n`.
- [x] **`smart_cow`** - [x] **`smart_cow`**
- [ ] Cow says a simple arithmetic expression (e.g., "3+11"), eyes show the result. - [x] Cow says a simple arithmetic expression (e.g., "3+11"), eyes show the result.
- [ ] **`crazy_cow`** - [x] **`crazy_cow`**
- [ ] Create a "crazy arithmetic cow" script with something unusual or complex. - [x] Create a "crazy arithmetic cow" script with something unusual or complex.
--- ---
## 4. C Programming ## 4. C Programming
- [ ] **`newcow.c`** - [x] **`newcow.c`**
- [ ] Create `affiche_vache` function: displays a cow without a speech bubble. - [x] Create `affiche_vache` function: displays a cow without a speech bubble.
- [ ] Compile and run. - [x] Compile and run.
- [ ] **Add Features** - [x] **Add Features**
- [ ] Support `-e`/ `--eyes` option to change cow's eyes. - [x] Support `-e`/ `--eyes` option to change cow's eyes.
- [ ] Implement other options from `cowsay` manpage. - [x] Implement other options from `cowsay` manpage.
- [ ] **New Feature** - [x] **New Feature**
- [ ] Implement a new feature (e.g., `--tail L` to adjust tail length, or display a herd). - [x] Implement a new feature (e.g., `--tail L` to adjust tail length, or display a herd).
- [ ] **`wildcow`** - [x] **`wildcow`**
- [ ] Test and explain `update()` and `gotoxy()`. - [-] Test and explain `update()` and `gotoxy()`.
- [ ] Create an animated cow using `update()`, `gotoxy()`, and `sleep()`. - [x] Create an animated cow using `update()`, `gotoxy()`, and `sleep()`.
- [ ] **`reading_cow`** - [x] **`reading_cow`**
- [ ] Cow "reads" a file character by character, displaying each in its mouth before "swallowing". - [x] Cow "reads" a file character by character, displaying each in its mouth before "swallowing".
--- ---
## 5. Automata (Cow-Tamagotchi) ## 5. Automata (Cow-Tamagotchi)
- [ ] **Design** - [x] **Design**
- [ ] Draw an automaton for cow's health states: `liferocks`, `lifesucks`, `byebyelife`. - [x] Draw an automaton for cow's health states: `liferocks`, `lifesucks`, `byebyelife`.
- [ ] Assume fixed `fitness`, `digestion`, and `stock`. - [x] Assume fixed `fitness`, `digestion`, and `stock`.
- [ ] **`tamagoshi_cow.c`** - [x] **`tamagoshi_cow.c`**
- [ ] Reuse `affiche_vache` to display cow's health state. - [x] Reuse `affiche_vache` to display cow's health state.
- [ ] Initialize `stock` and `fitness` to 5. - [x] Initialize `stock` and `fitness` to 5.
- [ ] Create `stock_update()` and `fitness_update()` functions. - [x] Create `stock_update()` and `fitness_update()` functions.
- [ ] Main loop: - [x] Main loop:
- [ ] Display cow's state. - [x] Display cow's state.
- [ ] Display `stock`. - [x] Display `stock`.
- [ ] Prompt for `lunchfood`. - [x] Prompt for `lunchfood`.
- [ ] Update `stock` and `fitness`. - [x] Update `stock` and `fitness`.
- [ ] Increment `duree_de_vie`. - [x] Increment `duree_de_vie`.
- [ ] End game at `byebyelife`, display score. - [x] End game at `byebyelife`, display score.
--- ---
## 6. Report ## 6. Report
- [ ] Format: plain text, Markdown, Org, or LaTeX. - [x] Format: plain text, Markdown, Org, or LaTeX.
- [ ] Include: - [x] Include:
- [ ] Source code. - [x] Source code.
- [ ] Execution outputs for relevant test cases. - [x] Execution outputs for relevant test cases.
- [ ] Comments in code and report: justify choices, ideas, challenges. - [x] Comments in code and report: justify choices, ideas, challenges.
- [ ] Highlight original and advanced implementations. - [x] Highlight original and advanced implementations.
--- ---

View File

@@ -1,12 +1,23 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
int main() { void affiche_vache(char yeux[3]) {
const char *cow = " ^__^\n" printf(" \\ ^__^\n");
" (oo)\\_______\n" printf(" \\ (%s)\\_______\n", yeux);
" (__)\\ )\\/\\\n" printf(" (__)\\ )\\/\\\n");
" ||----w |\n" printf(" ||----w |\n");
" || ||\n"; printf(" || ||\n");
}
printf("%s", cow); int main(int argc, char *argv[]) {
char yeux[3] = "oo";
if (argc == 3 &&
(strcmp(argv[1], "-e") == 0 || strcmp(argv[1], "--eyes") == 0)) {
strncpy(yeux, argv[2], 2);
yeux[2] = '\0';
}
affiche_vache(yeux);
return 0; return 0;
} }

101
src/C/newcow2.c Normal file
View File

@@ -0,0 +1,101 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void update() { printf("\033[H\033[J"); }
void gotoxy(int x, int y) { printf("\033[%d;%dH", y, x); }
void affiche_vache(int x, int y, const char *yeux, const char *langue) {
gotoxy(x, y);
printf(" \\ ^__^\n");
gotoxy(x, y + 1);
printf(" \\ (%s)\\_______\n", yeux);
gotoxy(x, y + 2);
printf(" (__)\\ )\\/\\\\\n");
gotoxy(x, y + 3);
printf(" %s ||----w |\n", langue);
gotoxy(x, y + 4);
printf(" || ||\n");
fflush(stdout);
}
void animation_blink() {
for (int i = 0; i < 12; i++) {
update();
if (i % 4 == 0)
affiche_vache(5, 3, "--", " ");
else
affiche_vache(5, 3, "oo", " ");
usleep(250000);
}
}
void animation_tongue() {
for (int i = 0; i < 12; i++) {
update();
if (i % 2 == 0)
affiche_vache(5, 3, "oo", "U ");
else
affiche_vache(5, 3, "oo", " ");
usleep(250000);
}
}
void animation_walk() {
for (int x = 1; x <= 40; x += 2) {
update();
if ((x / 2) % 2 == 0)
affiche_vache(x, 3, "oo", " ");
else
affiche_vache(x, 3, "OO", " ");
usleep(120000);
}
}
void animation_bounce() {
int x = 20;
for (int i = 0; i < 18; i++) {
update();
int y;
if (i % 4 == 0 || i % 4 == 2)
y = 3;
else
y = 2;
affiche_vache(x, y, "oo", " ");
usleep(180000);
}
}
void usage(char *prog) {
printf("Usage : %s [blink|tongue|walk|bounce]\n", prog);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
usage(argv[0]);
return 1;
}
if (strcmp(argv[1], "blink") == 0) {
animation_blink();
} else if (strcmp(argv[1], "tongue") == 0) {
animation_tongue();
} else if (strcmp(argv[1], "walk") == 0) {
animation_walk();
} else if (strcmp(argv[1], "bounce") == 0) {
animation_bounce();
} else {
usage(argv[0]);
return 1;
}
gotoxy(1, 10);
return 0;
}

22
src/C/newcows/newcowT.c Normal file
View File

@@ -0,0 +1,22 @@
#include <stdio.h>
#include <string.h>
void affiche_vache(char tongue[3]) {
printf(" \\ ^__^\n");
printf(" \\ (oo)\\_______\n");
printf(" (__)\\ )\\/\\\n");
printf(" %s ||----w |\n", tongue);
printf(" || ||\n");
}
int main(int argc, char *argv[]) {
char tongue[3] = "";
if (argc == 3 && (strcmp(argv[1], "-T") == 0)) {
strncpy(tongue, argv[2], 2);
tongue[2] = '\0';
}
affiche_vache(tongue);
return 0;
}

23
src/C/newcows/newcowp.c Normal file
View File

@@ -0,0 +1,23 @@
#include <stdio.h>
void affiche_vache(char message[128]) {
printf(" _____\n");
printf("< %s >\n", message);
printf(" -----\n");
printf(" \\ ^__^\n");
printf(" \\ (@@)\\_______\n");
printf(" (__)\\ )\\/\\\n");
printf(" ||----w |\n");
printf(" || ||\n");
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Usage : -p 'message'\n");
return 1;
}
affiche_vache(argv[2]);
return 0;
}

137
src/C/reading_cow.c Normal file
View File

@@ -0,0 +1,137 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_TEXT 1024
void update(void) { printf("\033[H\033[J"); }
void gotoxy(int x, int y) { printf("\033[%d;%dH", y, x); }
void print_repeat(char c, int n) {
for (int i = 0; i < n; i++)
putchar(c);
}
void affiche_bulle(const char *texte) {
int len = strlen(texte);
putchar(' ');
print_repeat('_', len + 2);
putchar('\n');
printf("< %s >\n", texte);
putchar(' ');
print_repeat('-', len + 2);
putchar('\n');
}
void affiche_vache(char lettre_en_bouche) {
printf(" \\ ^__^\n");
printf(" \\ (oo)\\_______\n");
printf(" (__)\\ )\\/\\\\\n");
if (lettre_en_bouche == '\0')
printf(" \\_ ||----w |\n");
else
printf(" %c ||----w |\n", lettre_en_bouche);
printf(" || ||\n");
}
void affiche_scene(const char *deja_lu, char lettre_en_bouche) {
update();
affiche_bulle(deja_lu);
affiche_vache(lettre_en_bouche);
fflush(stdout);
}
void usage(const char *prog) {
fprintf(stderr, "Usage: %s [--i intervalle] fichier\n", prog);
fprintf(stderr, " ou: %s [--i intervalle] -\n", prog);
}
int main(int argc, char *argv[]) {
double intervalle = 1.0;
char *nom_fichier = NULL;
FILE *f = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--i") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "erreur : --i attend une valeur.\n");
usage(argv[0]);
return 1;
}
intervalle = atof(argv[++i]);
if (intervalle < 0) {
fprintf(stderr, "erreur : l'intervalle doit etre >= 0.\n");
return 1;
}
} else if (nom_fichier == NULL) {
nom_fichier = argv[i];
} else {
fprintf(stderr, "erreur : trop d'arguments.\n");
usage(argv[0]);
return 1;
}
}
if (nom_fichier == NULL) {
usage(argv[0]);
return 1;
}
if (strcmp(nom_fichier, "-") == 0) {
f = stdin;
} else {
f = fopen(nom_fichier, "r");
if (f == NULL) {
perror("erreur ouverture fichier");
return 1;
}
}
char texte_lu[MAX_TEXT];
int taille = 0;
texte_lu[0] = '\0';
int c;
useconds_t pause_us = (useconds_t)(intervalle * 1000000.0);
while ((c = fgetc(f)) != EOF) {
if (taille >= MAX_TEXT - 1) {
fprintf(stderr, "erreur : texte trop long (max %d caracteres).\n",
MAX_TEXT - 1);
if (f != stdin)
fclose(f);
return 1;
}
if (c == '\n') {
texte_lu[taille++] = ' ';
texte_lu[taille] = '\0';
affiche_scene(texte_lu, '\0');
usleep(pause_us);
continue;
}
affiche_scene(texte_lu, (char)c);
usleep(pause_us);
texte_lu[taille++] = (char)c;
texte_lu[taille] = '\0';
}
affiche_scene(texte_lu, '\0');
if (f != stdin)
fclose(f);
gotoxy(1, 10);
return 0;
}

125
src/C/tamagoshi_cow.c Normal file
View File

@@ -0,0 +1,125 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
enum State {
byebyelife = 0,
lifesucks = 1,
liferocks = 2
};
int stock = 5;
int fitness = 5;
int clamp(int x, int min, int max) {
if (x < min) return min;
if (x > max) return max;
return x;
}
enum State get_state(void) {
if (fitness == 0 || fitness == 10) {
return byebyelife;
} else if ((fitness >= 1 && fitness <= 3) || (fitness >= 7 && fitness <= 9)) {
return lifesucks;
} else {
return liferocks;
}
}
void affiche_vache(enum State s) {
if (s == liferocks) {
printf(" _______________________________________\n");
printf("< You are a good sla... I mean player ! >\n");
printf("-----------------------------------------\n");
printf(" \\ ^__^\n");
printf(" \\ ($$)\\_______\n");
printf(" ( _)\\ )\\/\\\n");
printf(" U ||----w |\n");
printf(" || ||\n");
} else if (s == lifesucks) {
printf(" _______________________\n");
printf("< You SUCK at this game >\n");
printf("-------------------------\n");
printf(" \\ ^__^\n");
printf(" \\ (@@)\\_______\n");
printf(" (__)\\ )\\/\\\n");
printf(" | ||----w |\n");
printf(" ' /| ||\n");
} else {
printf(" _______________________________\n");
printf("< Where is my warranty ticket :( >\n");
printf(" ----------------------------------\n");
printf(" \\ ||\n");
printf(" \\ ||\n");
printf(" \\ ||\n");
printf(" \\||\n");
printf(" ~__~\n");
printf(" (xx)\\_______\n");
printf(" (__)\\ )\\\n");
printf(" o o||----w | \\\n");
printf(" o o|| ||\n");
}
}
int fitness_update(int lunchfood) {
int digestion = -(rand() % 4); // valeur entre 0 et -3
fitness = fitness + lunchfood + digestion;
fitness = clamp(fitness, 0, 10);
return fitness;
}
int stock_update(int lunchfood) {
int crop = (rand() % 7) - 3; // valeur entre -3 et +3, il y a probablement le biais avec le modulo comme parler dans les fichiers bash mais la n'est pas le sujet....
stock = stock - lunchfood + crop;
stock = clamp(stock, 0, 10);
return stock;
}
int main(void) {
srand((unsigned) time(NULL));
int duree_vie = 0;
int lunchfood;
enum State state = get_state();
while (state != byebyelife) {
printf("\n============================\n");
printf("TAMAGOSHI COW\n");
printf("============================\n\n");
affiche_vache(state);
printf("\nStock actuel : %d / 10\n", stock);
do {
printf("Quantite de nourriture a donner : ");
scanf("%d", &lunchfood);
if (lunchfood < 0 || lunchfood > stock) {
printf("Valeur invalide. Entrez une valeur entre 0 et %d.\n", stock);
}
} while (lunchfood < 0 || lunchfood > stock);
fitness_update(lunchfood);
stock_update(lunchfood);
duree_vie++;
state = get_state();
}
printf("\n============================\n");
printf("GAME OVER\n");
printf("============================\n\n");
affiche_vache(byebyelife);
printf("\nScore final : %d\n", duree_vie);
return 0;
}

View File

@@ -1,7 +1,31 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
USE_ASM=0
usage() {
echo "usage: $0 [--asm] <number>"
echo
echo " <number> nombre de termes à afficher"
echo " --asm utilise le programme assembleur ./fib"
echo
echo "sans --asm, le calcul est fait directement en bash"
}
if [[ $# -lt 1 || $# -gt 2 ]]; then
usage
exit 1
fi
if [[ "${1:-}" == "--asm" ]]; then
USE_ASM=1
shift
fi
if [[ $# -ne 1 ]]; then if [[ $# -ne 1 ]]; then
echo "usage: $0 <number>" usage
exit 1 exit 1
fi fi
@@ -12,41 +36,62 @@ fi
n=$1 n=$1
declare -A memo fib_bash() {
memo[1]=0
memo[2]=1
result=0
fib() {
local k=$1 local k=$1
local a local a=0
local b local b=1
local tmp
if [[ -n "${memo[$k]:-}" ]]; then for ((j = 0; j < k; j++)); do
result=${memo[$k]} tmp=$((a + b))
return a=$b
b=$tmp
done
printf '%s\n' "$a"
}
fib_asm() {
local k=$1
local bin="$DIR/fib"
if [[ ! -x "$bin" ]]; then
echo "error: ASM binary not found or not executable: $bin" >&2
echo "compile with:" >&2
echo " nasm -f elf64 fib.asm -o fib.o && ld fib.o -o fib" >&2
exit 1
fi fi
fib $((k - 1)) "$bin" "$k"
a=$result }
fib $((k - 2)) display_value() {
b=$result local value=$1
local last=$2
memo[$k]=$((a + b)) if command -v cowsay >/dev/null 2>&1; then
result=${memo[$k]} if ((last)); then
printf '%s\n' "$value" | cowsay -e oo -T U
else
printf '%s\n' "$value" | cowsay
fi
else
printf '%s\n' "$value"
fi
} }
for ((i = 1; i <= n; i++)); do for ((i = 1; i <= n; i++)); do
fib "$i" if ((USE_ASM)); then
value=$result value="$(fib_asm "$i")"
else
value="$(fib_bash "$i")"
fi
if ((i < n)); then if ((i < n)); then
printf '%s\n' "$value" | cowsay # il y a eu un peu de problèmes pour afficher correctement le nombre avec cowsay il attendait une sorte d'input ?? display_value "$value" 0
sleep 1 sleep 1
clear clear
else else
printf '%s\n' "$value" | cowsay -e oo -T U display_value "$value" 1
fi fi
done done

52
src/bash_scripts/crazy_cow.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
# Cette crazy cow écrit une suite de chiffres tels qu'ils sont lus à l'oral
# exemple :
# etape 1 : 1 (= un 1 )
# etape 2 : 11 (= deux 1 )
# etape 3 : 21 (= un 2 un 1)
# etape 4 : 1211
# ....
read -p "nombre n de répétitions de la suite : " repetitions
look_and_say() {
local input="$1"
local output=""
local previous_number=""
local n=0 # nombre de fois qu'on a vu le même nombre
local i
for ((i = 0; i < ${#input}; i++)); do # on parcourt chaque chiffre de la chaine input
local pos_number="${input:$i:1}" # représente chiffre de l'input à la position i
if [ "$pos_number" == "$previous_number" ]; then
((n++))
else
if [ $n -gt 0 ]; then
output="$output$n$previous_number" # on écrit ce qu'on a compté jusqu'à présent
fi
# fin de la boucle : on passe au chiffre suivant
previous_number="$pos_number"
n=1
fi
done
output="$output$n$previous_number"
echo "$output"
}
for ((etape = 1; etape <= repetitions; etape++)); do
current=$(look_and_say "$current")
resultat="$resultat\n etape $etape : $current"
done
echo -e "$resultat" | cowsay -e "oo"

104
src/bash_scripts/fib.asm Normal file
View File

@@ -0,0 +1,104 @@
; x86-64 Linux, NASM
; usage: ./fib 10
; output: 55
global _start
section .bss
buffer resb 32
section .text
_start:
mov rdi, [rsp] ; argc
cmp rdi, 2
jl error
mov rsi, [rsp + 16] ; argv[1]
call atoi ; rax = n
mov rcx, rax
xor rax, rax ; a = 0
mov rbx, 1 ; b = 1
test rcx, rcx
jz print_result
fib_loop:
mov rdx, rax
add rdx, rbx
mov rax, rbx
mov rbx, rdx
dec rcx
jnz fib_loop
print_result:
call print_uint
call exit_ok
error:
mov rax, 60
mov rdi, 1
syscall
exit_ok:
mov rax, 60
xor rdi, rdi
syscall
atoi:
xor rax, rax
atoi_loop:
movzx rdx, byte [rsi]
cmp rdx, 0
je atoi_done
cmp rdx, '0'
jl atoi_done
cmp rdx, '9'
jg atoi_done
sub rdx, '0'
imul rax, rax, 10
add rax, rdx
inc rsi
jmp atoi_loop
atoi_done:
ret
print_uint:
mov rdi, buffer + 31
mov byte [rdi], 10
dec rdi
mov rcx, 10
test rax, rax
jnz convert_loop
mov byte [rdi], '0'
jmp print_now
convert_loop:
xor rdx, rdx
div rcx
add dl, '0'
mov [rdi], dl
dec rdi
test rax, rax
jnz convert_loop
inc rdi
print_now:
mov rax, 1
mov rsi, rdi
mov rdx, buffer + 32
sub rdx, rsi
mov rdi, 1
syscall
ret

View File

@@ -14,7 +14,7 @@ if [ $# -eq 0 ]; then
((rb < 32742)) && r2=$((rb % 51)) && break ((rb < 32742)) && r2=$((rb % 51)) && break
done done
result=$((r1 + r2)) result=$((r1 + r2))
message="$r1 + $r2 = $result" message="$r1 + $r2"
else else
expression="$1" expression="$1"
result=$(echo "scale=2; $expression" | bc -l) result=$(echo "scale=2; $expression" | bc -l)

325
start.sh Executable file
View File

@@ -0,0 +1,325 @@
#!/usr/bin/env bash
set -u
set -o pipefail
ROOT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/cowsay-tour.XXXXXX")
trap 'rm -rf "$TMP_DIR"' EXIT
AUTO_RUN=0
COUNTDOWN=10
STOP_TOUR=0
COMPILER=""
usage() {
cat <<'EOF'
Usage:
./tour_programmes.sh
./tour_programmes.sh --auto
Options:
--auto starts immediately without waiting
-h, --help shows this help
EOF
}
while (($# > 0)); do
case "$1" in
--auto)
AUTO_RUN=1
;;
-h | --help)
usage
exit 0
;;
*)
printf 'Unknown option: %s\n\n' "$1" >&2
usage >&2
exit 1
;;
esac
shift
done
hr() {
printf '\n============================================================\n'
}
show_intro() {
hr
printf 'Quick cowsay program tour\n'
if ((AUTO_RUN == 1)); then
printf 'Auto mode: demos start immediately.\n'
else
printf 'The first demo starts after %d seconds.\n' "$COUNTDOWN"
printf 'After each demo, the tour waits %d seconds before the next one.\n' "$COUNTDOWN"
printf 'Press Enter to continue faster, or type n then Enter to stop.\n'
fi
}
need_commands() {
local missing=0
local cmd
for cmd in "$@"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
printf 'Missing dependency: %s\n' "$cmd" >&2
missing=1
fi
done
return "$missing"
}
detect_compiler() {
if [[ -n "$COMPILER" ]]; then
return 0
fi
local candidate
for candidate in cc clang gcc; do
if command -v "$candidate" >/dev/null 2>&1; then
COMPILER="$candidate"
return 0
fi
done
printf 'No C compiler found.\n' >&2
return 1
}
compile_c() {
local source="$1"
local output="$2"
detect_compiler || return 1
"$COMPILER" -std=c99 -Wall -Wextra -O2 -D_DEFAULT_SOURCE "$source" -o "$output"
}
run_command() {
"$@"
}
run_command_with_input() {
local input="$1"
shift
printf '%s' "$input" | "$@"
}
announce_demo() {
local name="$1"
local description="$2"
hr
printf '%s: %s\n' "$name" "$description"
}
drain_stdin() {
if [[ ! -t 0 ]]; then
return 0
fi
while IFS= read -r -t 0; do
:
done
}
timed_continue() {
local prompt="$1"
if ((AUTO_RUN == 1)) || [[ ! -t 0 ]]; then
printf 'Starting...\n'
return 0
fi
drain_stdin
printf '%s' "$prompt"
local answer=""
if IFS= read -r -t "$COUNTDOWN" answer; then
printf '\n'
case "${answer,,}" in
n)
STOP_TOUR=1
return 1
;;
*)
return 0
;;
esac
fi
printf '\n'
return 0
}
run_demo() {
local name="$1"
local function_name="$2"
"$function_name"
local status=$?
if ((status != 0)); then
printf '%s: failed (%d)\n' "$name" "$status" >&2
fi
}
demo_cow_kindergarten() {
need_commands cowsay || return 1
run_command bash "$ROOT_DIR/src/bash_scripts/cow_kindergarten.sh"
}
demo_cow_primaryschool() {
need_commands cowsay || return 1
run_command bash "$ROOT_DIR/src/bash_scripts/cow_primaryschool.sh" 3
}
demo_cow_highschool() {
need_commands cowsay || return 1
run_command bash "$ROOT_DIR/src/bash_scripts/cow_highschool.sh" 3
}
demo_cow_college() {
need_commands cowsay || return 1
run_command bash "$ROOT_DIR/src/bash_scripts/cow_college.sh" 5
}
demo_cow_university() {
need_commands cowsay || return 1
run_command bash "$ROOT_DIR/src/bash_scripts/cow_university.sh" 12
}
demo_smart_cow() {
need_commands cowsay bc || return 1
run_command bash "$ROOT_DIR/src/bash_scripts/smart_cow.sh" '4+13'
}
demo_crazy_cow() {
need_commands cowsay || return 1
run_command_with_input $'5\n' bash "$ROOT_DIR/src/bash_scripts/crazy_cow.sh"
}
demo_newcow() {
local bin="$TMP_DIR/newcow"
compile_c "$ROOT_DIR/src/C/newcow.c" "$bin" || return 1
run_command "$bin" -e "^^"
}
demo_newcowt() {
local bin="$TMP_DIR/newcowT"
compile_c "$ROOT_DIR/src/C/newcows/newcowT.c" "$bin" || return 1
run_command "$bin" -T "U"
}
demo_newcowp() {
local bin="$TMP_DIR/newcowp"
compile_c "$ROOT_DIR/src/C/newcows/newcowp.c" "$bin" || return 1
run_command "$bin" -p "Hello"
}
demo_newcow2() {
local bin="$TMP_DIR/newcow2"
compile_c "$ROOT_DIR/src/C/newcow2.c" "$bin" || return 1
run_command "$bin" blink
}
demo_reading_cow() {
local bin="$TMP_DIR/reading_cow"
local sample="$TMP_DIR/reading_demo.txt"
compile_c "$ROOT_DIR/src/C/reading_cow.c" "$bin" || return 1
printf 'Hello.\nI read.\n' >"$sample"
run_command "$bin" --i 0.10 "$sample"
}
demo_tamagoshi_cow() {
local bin="$TMP_DIR/tamagoshi_cow"
if ((AUTO_RUN == 1)) || [[ ! -t 0 ]]; then
printf 'Tamagoshi skipped in auto mode.\n'
return 0
fi
compile_c "$ROOT_DIR/src/C/tamagoshi_cow.c" "$bin" || return 1
run_command "$bin"
}
visit_programs() {
local -a names=(
'cow_kindergarten.sh'
'cow_primaryschool.sh'
'cow_highschool.sh'
'cow_college.sh'
'cow_university.sh'
'smart_cow.sh'
'crazy_cow.sh'
'newcow.c'
'newcowT.c'
'newcowp.c'
'newcow2.c'
'reading_cow.c'
'tamagoshi_cow.c'
)
local -a descriptions=(
'Counts from 1 to 10.'
'Counts up to n.'
'Shows square numbers.'
'Shows Fibonacci.'
'Shows prime numbers.'
'Calculates an expression.'
'Generates a weird sequence.'
'Basic cow.'
'Cow with a tongue option.'
'Cow with a speech bubble.'
'Compiles a .c file into .out.'
'Animates the cow.'
'The cow reads a file.'
'Small cow game.'
)
local -a functions=(
'demo_cow_kindergarten'
'demo_cow_primaryschool'
'demo_cow_highschool'
'demo_cow_college'
'demo_cow_university'
'demo_smart_cow'
'demo_crazy_cow'
'demo_newcow'
'demo_newcowt'
'demo_newcowp'
'demo_newcow2'
'demo_reading_cow'
'demo_tamagoshi_cow'
)
local total=${#names[@]}
local i
for ((i = 0; i < total; i++)); do
announce_demo "${names[i]}" "${descriptions[i]}"
if ((i == 0)); then
timed_continue "Press Enter to start, type n then Enter to stop, auto-start in ${COUNTDOWN} seconds... " || return
else
timed_continue "Press Enter to start the next program, type n then Enter to stop, or wait ${COUNTDOWN} seconds... " || return
fi
run_demo "${names[i]}" "${functions[i]}"
((STOP_TOUR == 1)) && return
done
}
show_outro() {
hr
if ((STOP_TOUR == 1)); then
printf 'Tour stopped.\n'
else
printf 'End of tour.\n'
fi
}
show_intro
visit_programs
show_outro