Examen réparti Février 2013 Street Fighter II !

Transcription

Examen réparti Février 2013 Street Fighter II !
Université Pierre et Marie Curie (UPMC) Master d'Informatique M1/STL/CPS
Examen réparti Février 2013 Street Fighter II
1
TM !
Binh-Minh Bui-Xuan
2 heures. Tout document personnel non-électronique autorisé.
Introduction
Ce sujet fait partie d'un devoir global (examen réparti 1 + projet) consistant à formaliser, à l'aide du
langage de spécication de service vu en cours, un modèle simplié du mode multi-joueur du jeu Street
Fighter II: The World Warrior TM , développé par Capcom en 1991.
Dans cet épisode de la série, les joueurs ont la
possibilité de choisir le personnage combattant pour
leur cause − peu importe qu'elle soit très pieuse,
ou pas du tout. Ainsi, outre le classique (donc délaissé ?) Ryu-petit-chou on peut aussi enrôler le seul,
véritable, solidement musculaire et ardent défenseur
des valeurs de la démocratie et du pouvoir : le
personnage américain du colonel Guile.
Il s'agit probablement de l'implémentation la plus
buggée que l'industrie du jeu ait eu l'honneur de
connaître...
Enoncé de l'examen
Le barême est indicatif. L'objectif est d'exploiter au mieux le langage de spécication étudié en cours. On
souhaite obtenir une spécication cohérente, complète et bien modulaire. Décrire les services suivants :
Personnage (8 points)
Le service Personnage représente les diérents personnages enrôlables du jeu. Ces passionnés de la bastonnade sont distingués non seulement par leur nom et leurs dimensions − plus précisément leur largeur et
hauteur − mais aussi par leur force et les précieux points_de_vie leur restant. On dispose également
d'un observateur donnant leur état de service, c.à.d. si le personnage est_vaincu ou si cela se fait encore
attendre. Le nom d'un personnage est constitué d'une chaîne de caractères non-vide, et toute dimension
est composée de chires impairs mesurés en nombre de pixels. Lorsque la situation permet, ce service
ore l'opération de retrait de points de vie, qui est probablement la seule chose raisonnable que l'on
attend de tels personnages.
Moteur du jeu (4 points)
Le service MoteurJeu modélisera le jeu lui-même. Il aura comme principale opération le calcul d'un pas
de jeu. Lors de ce calcul, on passera en paramètre un déplacement éventuel d'un ou deux personnages
dans une direction gauche ou droite, ou encore l'action consistant à frapper dans la direction de l'autre.
On mettra à jour les informations concernant ces jeunes gens via un service GestionCombat à spécier
plus tard (voir squelette de MoteurJeu ci-dessous).
Concernant MoteurJeu, le nombre maximal de pas de jeu sera xé à l'avance et on prendra soin de détecter
la n du jeu avec un observateur adéquat : partie gagnée ou perdue, voire nulle, selon le point de vue de
chacun. On ne pourra entreprendre un pas de jeu supplémentaire si la partie est terminée. Les possibilités
de terminaison de partie sont les suivantes : 1. Ryu est KO mais pas Guile, les valeurs de la démocratie
et du pouvoir sont intactes ! 2. Guile est hors-service et Ryu toujours guilleret, ce dernier reçoit tout de
même les applaudissements des 4 soldats du colonel, y compris les compliments de celle en mini-jupe (voir
gure ci-dessus). 3. Les bagarreurs survivent, malgré eux, après que le nombre maximum de pas de jeu a
été atteint ; ou alors, par la seule volonté des esprits supérieurs, ils sont tous deux KO en même temps :
la partie est nie, nullement, les spectateurs partent dans la joyeuse paix du Street Fighter.
On donne ci-dessous une version incomplète de MoteurJeu et GestionCombat (à ne pas recopier sur la
feuille d'examen). Ajouter toutes les observations nécessaires an de rendre la spécication de MoteurJeu
complète.
Université Pierre et Marie Curie (UPMC) Master d'Informatique M1/STL/CPS
2
service : MoteurJeu
use : GestionCombat
types : boolean, int, enum RESULTAT{GUILEGAGNANT, GUILEPERDANT, NULLE},
enum COMMANDE{RIEN, GAUCHE, DROITE, FRAPPE}
observators :
const maxPasJeu : [MoteurJeu] → int
pasJeuCourant : [MoteurJeu] → int
estFini : [MoteurJeu] → boolean
resultatFinal : [MoteurJeu] → RESULTAT
resultatFinal(M)
estFini(M)
combat : [MoteurJeu] → GestionCombat
:
init : int × int × int → [MoteurJeu]
init(largeur,hauteur,maxPas)
largeur≥ 256 ∧ hauteur≥ 240 ∧ maxPas≥ 0
:
pasJeu : [MoteurJeu] × COMMANDE × COMMANDE → [MoteurJeu]
pasJeu(M,comGuile,comRyu)
¬estFini(M)
:
[invariants]
0 ≤ pasJeuCourant(M) ≤ maxPasJeu(M)
[init]
maxPasJeu(init(l,h,m))=m ∧ pasJeuCourant(init(l,h,m))=0
combat(init(l,h,m))=GestionCombat::init(l,h)
[pasJeu]
pasJeuCourant(pasJeu(M,cG,cR))=pasJeuCourant(M) +1
combat(pasJeu(M,cG,cR))=GestionCombat::gerer(combat(M),cG,cR)
pre
require
Constructors
pre
Operators
require
pre
Observations
require
service : GestionCombat
use : Personnage
types : int, enum COMMANDE{RIEN, GAUCHE, DROITE, FRAPPE}
observators :
const largeur : [GestionCombat] → int
const hauteur : [GestionCombat] → int
guile : [GestionCombat] → Personnage
ryu : [GestionCombat] → Personnage
//ici, la liste des observateurs est imcomplète, voir le texte ci-dessous pour les observateurs manquants
:
init : int × int → [GestionCombat]
:
gerer : [GestionCombat] × COMMANDE × COMMANDE → [GestionCombat]
Constructors
Operators
Gestion du combat (10 points)
Le service GestionCombat supervise un terrain de jeu vide sur lequel se trouvent deux protagonistes s'appellant obligatoirement "Guile" et "Ryu". Le terrain de jeu est représenté par deux entités, largeur et
hauteur, constamment xées à certaines valeurs raisonnables. Les personnages sont initialement positionnés sur le terrain à 10 pixels des deux bords gauche/droite du terrain ; leur dimension initialisée par 13
en largeur et 51 en hauteur ; leur force mesurée par (de la) 16. Leur état de vie initial est jeune et sans
bouton, plus précisément on ne peut pas les mettre KO en une seule frappe. La seule opération de ce
service est la gestion des commandes joueur : on mettra à jour les positions des personnages suivant ces
commandes, ainsi que les chocs éventuels résultants de leurs actions intrépides. On supposera que :
le fait de frapper l'autre gèle le personnage qui frappe ;
le fait d'être touché par l'autre gèle le personnage qui est touché ;
il n'y a pas d'autre façon de geler un personnage ;
un personnage gelé ne peut pas être gelé à nouveau après le pas de jeu suivant ce gel (ici encore,
il s'agit d'une simplication pour l'examen) ;
un personnage gelé ne peut entreprendre d'action pendant le pas de jeu suivant ce gel ;
un personnage est touché si et seulement s'il y a collision entre les deux personnages au moment
précédant le pas de jeu et que l'autre personnage, par un miracle quelconque, réussit à entreprendre
l'action de frappe pendant le pas de jeu en question ;
il y a collision entre personnages si et seulement s'ils sont susamment proches (physiquement !) ;
un personnage touché est renvoyé 64 pixels ( !) en arrière, dans la limite des pixels disponibles ;
l'état d'un personnage reste le même, sauf s'il est touché par l'autre : dans ce cas, il perd un
nombre de points de vie égal à la force de son adversaire.
Question bonus : la deuxième, et troisième, dimension (nombre de points mystérieux)
La première dimension (x : la largeur) constitue pour l'instant l'unique dimension apparaîssant dans le
calcul des positions des personnages. La deuxième dimension (y : la hauteur) est introduite dès le début
de l'énoncé, mais jamais vraiment utilisée par la suite : nous n'avons pas spécié l'action consistant à
faire sauter nos chers combattants, que ce soit sur place, vers la gauche, ou vers la droite. La troisième
dimension (z : la profondeur) consiste à munir des positions des personnages d'une dimension représentant
la distance virtuelle par rapport à l'écran. Expliquer les changements et/ou modications qu'il faudrait
apporter aux spécications précédentes pour inclure la deuxième, puis la troisième dimension.