TP1 Poule-poule

Sommaire

L’objectif du TP1 est de développer un programme assembleur RISC-V inspiré de l’excellent jeu poule-poule de Charles Bossart, illustré par Pauline Berdal.

Le programme compte des œufs et prend en entrée une séquence de cartes représentées sous forme de caractères (lettres minuscules et chiffres). Les espaces et sauts de ligne sont ignorés.

Cartes œuf (o), affichage (a) et coq (q)

Une carte œuf (lettre o) ajoute un œuf en jeu. Le jeu commence avec aucun œuf en jeu.

Une carte d’affichage (lettre a) affiche le nombre d’œufs disponibles en jeu suivi d’un saut de ligne (utilisez PrintInt et PrintChar).

Une carte coq (lettre q) fait chanter le coq et termine le programme. (utilisez Exit)

Ainsi, la séquence de lettres « aooaoooaqa » doit afficher

0
2
5

En effet:

  • lors du premier a, il n’y a aucun œuf ;
  • au second a, deux œufs ont été ajoutés ;
  • au troisième a trois œufs ont été ajoutés, ce qui porte le total à cinq ;
  • enfin, le dernier a n’est jamais considéré, car le programme a quitté avant.

Note d’affichage: pour améliorer le sentiment d’interactivité, le simulateur combine les entrées et les sorties dans une même zone de texte, ce qui fait qu’interactivement, la zone de texte peut ressembler à:

a0
ooa2
ooooa5
q

et le programme quitte sans même laisser l’utilisateur saisir le a final. C’est un comportement normal, toutefois, dans les exemples du sujet, on indique indépendamment les entrées et les sorties attendues. Ce n’est qu’une affaire de présentation et ne change rien au final.

Cartes multiples

Afin de passer l’échelle et de pouvoir gérer de grandes quantités de cartes, chaque lettre peut être optionnellement préfixée par un multiplicateur qui est un chiffre entre 0 et 9 qui indique la quantité de cartes jouées.

Ainsi, la séquence de lettres et de chiffres « 5oa8oa1oa0o2a9q » doit afficher

5
13
14
14
14

En effet :

  • on met en jeu 5 œufs;
  • le total affiché est donc de 5;
  • on ajoute 8 œufs de plus;
  • le total affiché est donc de 13;
  • on ajoute 1 seul œuf — en fait, le 1 ici est superflu, car o sans chiffre est équivalent;
  • le total affiché est donc de 14;
  • on n’ajoute aucun œuf (c’est pas très utile, mais c’est autorisé);
  • le total (toujours 14) est affiché deux fois;
  • enfin, on fait chanter le coq 9 fois… mais, en fait, le premier coq suffit à quitter le programme, les 8 autres coqs sont superflus.

Note d’implémentation: vous ne pouvez pas simplement utiliser ReadInt ici, car au moment de lire un caractère, vous ne savez pas si vous devez lire une carte (une lettre) ou un multiplicateur (un chiffre). Vous devez donc utiliser ReadChar pour les deux cas et gérer la situation spécifique du multiplicateur.

Carte poule (p)

Quand une carte poule (lettre p) arrive en jeu, si aucun œuf n’est disponible, alors la poule s’en va et ne fait rien. Par contre, si au moins un œuf est disponible, alors la poule se met à couver l’œuf qui devient indisponible (il n’est plus compté lors d’un a, et une autre poule ne peut pas couver ce même œuf).

Ainsi, la séquence de lettres « poopapapoaq » doit afficher

1
0
1

En effet:

  • quand la première poule arrive, aucun œuf n’est en jeu, elle s’en va sans rien faire;
  • quand la seconde poule arrive, deux œufs sont disponibles, elle en couve un;
  • l’autre œuf reste disponible ce qui fait que a affiche 1;
  • quand la troisième poule arrive, elle se met justement à couver cet œuf disponible.
  • les deux œufs sont couvés chacun par une poule, on affiche 0;
  • quand la quatrième poule arrive, il n’y a plus d’œuf disponible et elle s’en va sans rien faire;
  • enfin, un troisième œuf est ajouté, et c’est le seul disponible quand l’affichage est demandé.

Les poules, comme toutes les cartes, peuvent être préfixées d’un multiplicateur. Ainsi, la séquence de lettres et de chiffres « 5o4pa3pa2oaq » doit afficher

1
0
2

Carte renard (r)

Quand une carte renard (lettre r) arrive en jeu, elle chasse une des poules qui couvaient un œuf. La poule s’enfuit et le renard la poursuit (les deux quittent le jeu), laissant l’œuf découvé à découvert.

Si aucune poule n’est en jeu, le renard passe son chemin et s’en va sans rien faire.

Ainsi, la séquence de lettres « roopprapaq » doit afficher

1
0

En effet:

  • le premier renard arrive, mais il n’y a pas de poule, il s’en va sans rien faire;
  • deux œufs sont mis en jeu, puis deux poules, qui se mettent à les couver;
  • quand le second renard arrive, il se lance à la poursuite d’une des poules qui s’enfuit, laissant son œuf en jeu, non couvé;
  • l’affichage est donc 1;
  • une autre poule arrive, et couve l’œuf;
  • l’affichage donne alors 0 œuf disponible.

La séquence de lettres et de chiffres « 5o4p3ra2ra2p3r4oaq » doit afficher

4
5
9

Carte chien (c)

Le chien de garde protège les poules. Quand il arrive en jeu, il attend qu’un renard se pointe et lui court après, le faisant fuir. Quand plusieurs chiens sont en jeu et qu’un renard apparaît, seul l’un d’entre eux poursuit le renard, les autres chiens restent en jeu pour guetter les futurs renards éventuels.

Ainsi, la séquence de lettres « ccrooppraraq » doit afficher

0
1

En effet:

  • deux chiens entrent en jeu et attendent, car un chien reste en jeu, même s’il n’y a pas encore d’œuf ou de poule;
  • puis un premier renard pointe le bout de son museau, mais est immédiatement attaqué et poursuivi par un des chiens sans que le renard aie eu le temps d’agir (même si le renard n’allait rien faire), un chien et le renard sont partis, un chien reste monter la garde;
  • ensuite deux œufs sont mis en jeu et deux poules qui les couvent;
  • un deuxième renard arrive et se fait lui aussi pourchasser par le chien restant, les deux quittent la partie.
  • les poules continuent de couver chacune leur œuf, mais il n’y a plus aucun œuf disponible et il n’y a plus non plus de chien de garde en jeu ;
  • quand le troisième renard arrive, il pourchasse librement une des poules qui s’enfuit, ce qui laisse un œuf visible.

Carte ver (v)

Un vers qui arrive en jeu reste en jeu et est ignoré des chiens, des renards et des poules qui couvent. Par contre, quand une nouvelle poule arrive à la recherche d’un œuf à couver, celle-ci poursuit un des vers sans même considérer s’il y a un œuf disponible.

Ainsi, la séquence de lettres « oopvvpappaq » doit afficher

1
0
  • deux œufs sont mis en jeu;
  • une poule arrive et en couve un;
  • deux vers arrivent et sont ignorés par la poule qui couve;
  • quand une nouvelle poule arrive, elle jette son dévolu sur l’un des deux vers, et ignore l’œuf restant;
  • on a donc toujours un œuf visible;
  • une troisième poule arrive et course le ver restant;
  • quand la quatrième poule arrive, elle couve l’œuf libre;
  • on n’a donc aucun œuf visible.

La séquence de lettres et de chiffres « 2v8o7pa2c3r2aq » doit afficher

3
4
4

En effet,

  • deux vers arrivent en jeu et attendent;
  • huit œufs sont mis en jeu;
  • sept poules arrivent, deux poursuivent les deux vers et les cinq autres couvent les œufs;
  • il reste trois œufs visibles;
  • deux chiens entrent en jeu et attendent;
  • trois renards entrent en jeu, deux sont poursuivis par les chiens, le troisième s’attaque à une poule qui découve son œuf et le laisse découvert.
  • il reste quatre œufs visibles, qu’on affiche 2 fois.

Gestion des erreurs

Quand un caractère inconnu est rencontré, le programme quitte en affichant « Err ». Les caractères qui suivent ne sont pas considérés, car le programme a quitté avant.

Ainsi, la séquence « oaoXoaq » doit afficher:

1
Err

Extra: grand multiplicateur

Important : Cette partie est optionnelle et ne vaut que 2 points. Ne la faire que si tout le reste fonctionne et est d’excellente qualité.

Le multiplicateur peut être un nombre plus grand que 9. Ainsi, la séquence de lettres et de nombres « 12v189o77pa22c38raq » doit afficher

124
140

L’entrée suivante :

9r7p9vc3a
o799p10o110crara
vr3o543p6o03vovca
cov6v65ra
200633p251636c3127pcoc72590c45o15rc798rcv4p0aa
p20c419ccro1271r9308p2cr55219va
879339p626v02cc926o2aa
8pr0r322330r858p785o807co93o0c0108rr399440povv1r24806o440pp940r43v0va
o13r06c899pa
452o531611pooa
o8483o99c64ov1773960oa
poc28r24p4c11p4c935v84ror4cc470p766oa
o11c954p0c1cpop1v1306ora
65c67r4rpo8ro5442oo728oc9o7oa
v06p2367oa
5542v461118cvo24rrv798695v05696p9768cpcvpp0crpca
2670116prrr4co1491497ra
ov8pvvr441c30r21398vp7v6571cr696cva0a
ro4v320654p4p13cc538pc3p76p8v6o8pc8oa
049c84c0857co86375rpc19c6o650o00863c9v2o04p4op08or0v4opa
4vr6v733c21vpc8288cp81v861c37r8209r2o74v2175o926697cor9r14o4pa
33p0565773r11ccrp3936v8ro9r37v5p732o5oor7o00v451o8pp8c9vr968p392o5361ca
077cv2v7popv76r25ococpa
71265cr8co8o265o0p5c51crpcv2v06vrpco6ca
3426p469cv260984c69121rp1c26p48rp25595v9c34pa
r9ov2rvro6003ccp91p553o1raq

Devrait donner la sortie suivante :

0
0
0
10
10
7
8
43
0
926
926
926
24368
23513
2
1782510
1783243
1784060
1790249
1792611
1792612
1020584
1020579
720730
799097
801289
802878
802905
803180
802878
803441

Pour vous simplifier la vie, vous avez l’autorisation d’utiliser les instructions arithmétiques et logiques avancées du chapitre 5 (calculs) pour cette partie extra.

Réalisation

La réalisation de ce programme se fera par groupes d’au plus deux personnes. Chaque membre de l’équipe devra maîtriser tous les aspects du programme.

Contraintes d’implémentation:

  • Votre programme doit fonctionner avec le fork de RARS de Jean Privat en mode 64 bits (voir site du cours).
  • Vous pouvez utiliser les appels systèmes RARS ou les fonctions équivalentes de libs.s pour les entrées-sorties et la terminaison du programme.
  • Saut avis contraire, il ne faut pas utiliser d’instructions au delà du chapitre 3 comme l’accès à la mémoire (load ou store) ou l’utilisation de routines. De doute façon, pour ce TP elles compliqueraient votre solution plus qu’autre chose. Ce qui fait que la section .data ou la pseudo-instruction la sont interdites par exemple. Dans le doute, demandez.
  • Il n’est pas demandé de gérer les cas de débordement arithmétique.

Évaluation

Aptitude fonctionnelle

  • 50%: 10 tests publics (5 points par test).
    Les tests publics sont ceux présentés ci-dessus.

  • 50%: plusieurs tests privés évalués par le correcteur après la remise.
    Il est donc de votre responsabilité de vous assurer que votre programme fonctionne correctement au-delà des tests publics fournis.

Le script de correction qui sera utilisé est disponible à https://gitlab.info.uqam.ca/inf2171/20241/tp1-corrige. Tous les cas de tests sont disponibles à https://gitlab.info.uqam.ca/inf2171/20241/tp1-corrige/-/tree/master/tests?ref_type=heads et correspondent aux exemples du sujet.

Important: si le programme remis ne s’assemble pas (erreur de syntaxe, fichier corrompu, etc.) ou si aucun test ne passe avec l’outil (échec systématique), la note zéro sera automatiquement attribuée au TP, et ce, indépendamment de la qualité du code, du temps de développement passé ou des affichages de RARS sur l’ordinateur de l’étudiant.

Qualité et lisibilité du code source

Des points bonus et malus seront attribués en fonction de la qualité du code.

  • Indentation et aération.
  • Nommage adéquat des symboles.
  • Présence et pertinence des commentaires.
  • Organisation du code, simplicité, modularité. Pour information, ma solution fait moins de 150 lignes d’assembleur (commentaires et lignes blanches incluses).

Les critères sont plus détaillés dans le guide de style.

Modalités de remise et dates

  • Date de remise: dimanche 18 février à 23h55.
  • La remise se fait via moodle.
    • Remettez un seul fichier appelé poule.s (pas d’archive, juste ce fichier)
    • Mettez les noms, prénoms et codes permanents des étudiants du groupe en commentaire au début du fichier.
    • Dans un groupe de deux étudiants, un seul étudiant doit remettre.
    • Seule la remise la plus récente est considérée. Vous pouvez remettre autant de fois que vous le voulez avant l’échéance.
  • Si vous ne voulez pas perdre de points, assurez-vous de respecter le guide de style