one of the last commit
This commit is contained in:
118
README.md
118
README.md
@@ -1,12 +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>
|
||||||
|
|
||||||
# Preliminaries
|
## Contenu du dépôt
|
||||||
|
|
||||||
cowsay options :
|
- `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.
|
||||||
|
|
||||||
- -e/--eyes
|
## Dépendances
|
||||||
- -T
|
|
||||||
-
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
clang "$1" -o "${1%%.c}".out
|
|
||||||
325
start.sh
Executable file
325
start.sh
Executable 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
|
||||||
Reference in New Issue
Block a user