Projet de Programmation

Premier Semestre 2004-2005

 

Projet de Programmation

Le jeu de Wargame.

 

Travailler en binôme :

Pour ce TER vous allez travailler avec une autre personne. Vous devez bien sûr travailler ensemble : concevoir le programme ensemble, le taper et le mettre au point ensemble sur l'ordinateur. Il n'est pas question que certains fassent le travail, et que d'autres y ajoutent leur nom ! Vous ne devrez rendre qu'un rapport en indiquant vos noms ainsi que le numéro de votre groupe de TD.

 

Comment rendre les rapports :

Il faudra rendre un programme : c'est-à-dire un ou plusieurs packages sous la forme de plusieurs fichiers. Vous devrez envoyer par mail vos fichiers à votre chargé de Projet (il vous indiquera son adresse lors de la première séance). N'envoyez qu'un et un seul mail par binôme (on vous renverra un accusé de réception). Utilisez la commande suivante depuis les machines du bât. 308 pour la licence ou du bât. 334 pour la MIAGe (pas de document attaché avec Netscape ou autre). On suppose que Toto et Titi sont deux étudiants binômés du groupe B, que le chargé de TD est dupont@ici.fr, et que les fichiers sont C1.java et C2.java; bien sûr les noms mentionnés ici sont des exemples, toute ressemblance avec de vraies personnes serait fortuite !!

 

tar cvf - C1.java C2.java | uuencode Toto.Titi.B | mail dupont@ici.fr

 

Attention à ne pas oublier le - après le tar cvf sinon vous écraserez le fichier C1.java . . .

Les buts de ce projet :

·        Vous apprendre à écrire un programme à partir de spécifications informelles (énoncé en français).

·        Vous familiariser avec le fait que vos programmes seront réutilisés par d'autres plus tard; donc à les écrire lisiblement en les commentant judicieusement.

·        Vous faire utiliser javadoc pour engendrer la documentation d'implémentation de vos classes.

·        Vous entraîner à encapsuler vos données et méthodes pour obtenir des programmes robustes.

·        Vous montrer l'intérêt de séparer la partie traitement d'un programme de sa partie interface utilisateur.

 

Le programme que vous allez modifier :

Ce Projet se compose de trois parties que vous allez plus ou moins réutiliser . . .

 

Que devez vous faire dans ce TER ?

On se propose de réaliser un jeu de plateau de type « jeu de guerre »  utilisant une interface graphique conviviale. On aura trois possibilités : jouer contre un autre joueur humain sur la même machine, observer une partie se déroulant entre deux autres joueurs ou jouer contre un autre joueur humain sur un autre machine.

Dans tous les cas on aura besoin d'une interface utilisateur qui permettra au joueur humain de dialoguer avec le moteur du jeu. On devra programmer trois versions de moteur jeu :

  1. Un moteur donnant tour à tour la main aux deux joueurs humain.
  2. Un moteur qui transmet à un autre moteur situé sur une autre machine le coup joué par l'utilisateur, et qui réciproquement attend la réponse du joueur adverse pour la faire afficher par l'interface utilisateur.
  3. Un moteur d'observation qui espionne le moteur tournant sur une autre machine en ne faisant qu'afficher les coups par l'interface utilisateur, sans permettre de jouer soi-même.

 

Spécifications du jeu

Le jeu qu'il vous est demandé de développer s'inspire des jeux de stratégie à deux joueurs de type jeux de plateau faisant évoluer les unités de deux joueurs sur un espace géographique prédéterminé. Il s'agit plus précisément d'une variante dans laquelle les intentions des joueurs sont belliqueuses, et où la victoire découle de la suprématie de l'un des joueurs. Toutefois vous est laissé la possibilité de modifier l’ambiance du jeu. En conservant les caractéristiques techniques du jeu vous pouvez imaginer une version se déroulant dans la Rome antique ou en l’an 2195. En poussant l’idée jusqu'à la dérision nous invitons même ceux qui le souhaite à tourner la guerre en ridicule en choisissant de remplacer le complètement le vocabulaire militaire et d’inventer des guerres de tarte à la crème ou des guerres de bisous. Afin de garder une cohérence à cet énoncé nous utiliserons ici un vocabulaire guerrier.

Caractéristiques générales du jeu

Cases - Le jeu se déroule sur un plateau de taille variable assimilable à une matrice rectangulaire de cases carrée. Les cases représentent des éléments topographiques du terrain: route, prairie, forêt, eau, etc. Le type des cases influe sur la capacité des unités à s'y déplacer: par exemple, une unité de fantassins à pieds pourra progresser dans une zone de forêt, alors que cela ne sera pas possible pour une unité d'artillerie. Cela peut être modélisé par une caractéristique coût de déplacement propre à chaque type de case.

En outre, certaines cases représentent des constructions fixes: quartiers généraux, hôpitaux, bunkers, ports, etc.

Unités - Chaque joueur dispose au début de la partie d'un certain nombre d'unités, qui dépendent du type de jeu (époque, réalisme, etc.). Ces unités ont des caractéristiques propres en ce qui concerne leurs capacités d'attaque, de défense, et de mouvement. Les unités de transport possèdent également une capacité de chargement, alors que les autres unités sont caractérisées par une charge.

Les unités ont toutes un niveau de vie, qui dépend initialement du type d'unité et qui décroît au fur et à mesure des batailles et qui peut être augmenté jusqu'à la valeur initiale par un séjour dans un hôpital. Un niveau de vie nul implique la disparition de l'unité.

Les unités ont également un niveau d'expérience, initialement nul, qui augmente au fur et à mesure des batailles et qui influe sur la capacité au combat (force d'attaque et résistance). Le niveau d'expérience augmente proportionnellement au nombre de combats dans lequel une unité a été impliquée. Il a une valeur maximale qui dépend du type d'unité, et il ne peut diminuer.

Bâtiments - Les bâtiments occupent une case du plateau. Ils possèdent une capacité d'accueil (assimilable à la capacité de chargement des unités de transport). Une unité peut ainsi pénétrer dans un bâtiment si la capacité d'accueil du bâtiment peut supporter la "charge" représentée par l'unité.

Un bâtiment appartient par ailleurs à un joueur (ce qui peut être indiqué visuellement par un bandeau à la couleur du joueur sur le bâtiment). Si une unité d'un joueur adverse pénètre dans le bâtiment, celui-ci passe sous son contrôle et toutes les unités du premier joueur présentes dans le bâtiment sont éliminées.

Un bâtiment particulier est le quartier général: la prise d'un quartier général ennemi est une condition de suprématie et donc de victoire du joueur ayant effectué la prise.

Les quartiers généraux et les hôpitaux ont la possibilité de "réparer" des unités en fonction de leurs points de réparation. A la fin de chaque tour, ces points sont augmentés en fonction du type de bâtiment jusqu'à un maximum suivant la formule suivante (on dénote par Bx le bâtiment considéré):

Tours de jeu - Le jeu se décompose en deux modes de tours: déplacement et attaque. A chaque tour, les joueurs sont en modes opposés, ce qui signifie qu'un joueur est en mode déplacement et l'autre en mode attaque. A la fin de chaque tour, les modes de jeu sont inversés. Chaque mode de jeu se compose d'ordres donnés par le joueur à ses unités (toutes les unités peuvent recevoir un et un seul ordre à chaque tour).

Mode déplacement - Chaque unité possède une caractéristique de mouvement: il s'agit d'un nombre de points de déplacement. Donner un ordre de déplacement à une unité correspond à lui indiquer une case où elle doit se rendre, et qui est séparée de la case où elle se trouve actuellement par une suite de cases contiguës (un chemin) dont la somme des coûts de déplacement est inférieur ou égal au nombre de points de déplacement de l'unité. Une case contenant une autre unité (amie ou ennemie) ne pourra pas faire partie d'un chemin de déplacement.

Considérons par exemple le cas d'une unité dont le nombre de points de déplacement vaut 9, et une configuration où le coût de déplacement sur une case de type prairie vaut 2 et le coût de déplacement sur une case de type forêt vaut 5. L'unité pourra donc effectuer un chemin constitué de 2 cases de type prairie et d'une case de type forêt (coût total: 9 points), ou de 4 cases de type prairie (coût total: 8 points).

Mode attaque - Chaque unité possède des caractéristiques d'attaque qui se décomposent en une portée d'attaque (composée d'une portée minimale et d'une portée maximale) et un nombre de points d'attaque de référence. Elle possède également des caractéristiques de défense qui se décomposent en un nombre de points de défense et un nombre de points de contre-attaque.

Pour qu'une attaque puisse avoir lieu, il faut que le chemin séparant l'unité attaquée de l'unité attaquante ait une taille comprise dans la portée de l'unité attaquante (par exemple, une unité d'artillerie pourra attaquer à une distance comprise entre 3 et 7 cases, alors qu'une unité d'infanterie pourra attaquer à une distance entre 1 et 2 cases). Il peut éventuellement se trouver d'autres unités amies ou ennemies sur ce chemin sans que cela n'influence le combat.

Pour qu'une contre-attaque puisse avoir lieu, il faut nécessairement que l'attaque ait eu lieu a une distance comprise dans la portée d'attaque de l'unité attaquée. Par exemple, une unité d'infanterie attaquée à plusieurs cases de distance par une unité d'artillerie ne pourra pas contre-attaquer si le nombre de cases séparant ces deux unités est plus grand que la portée de l'unité d'infanterie.

Une attaque implique deux unités ennemies et se déroule comme suit: tout d'abord, le nombre de points correspondant à l'attaque et celui correspondant à la défense sont calculés. Le dommage porté à l'unité attaquée est alors reporté sur ses points de vie. Si celle-ci est encore en vie, on calcule le nombre de points correspondant à sa contre-attaque, qui est alors reporté sur les points de vie de l'unité attaquante. Finalement, les points d'expérience des deux unités sont mis à jour. Les différents éléments mentionnés se calculent ainsi (on dénote par U1 l'unité attaquante et U2 l'unité attaquée):

Réparation d'unités - Lorsqu'une unité est dans un hôpital ou un quartier général contrôlé par son joueur, elle peut être "réparée". Cette réparation s'effectue à la place d'un tour de déplacement ou d'un tour d'attaque (i.e., si l'unité est en cours de réparation, elle ne peut sortir du bâtiment; si l'unité est parvenue dans la bâtiment pendant le tour courant par un déplacement, elle ne peut être réparée). Une unité en cours de réparation est immobilisée pendant deux tours (le tour où la réparation est demandée, et le tour suivant). Le joueur doit pouvoir choisir le nombre de points de réparation affecté à chaque unité qu'il décide de réparer à un tour donné, à concurrence d'un nombre de points de vie maximal par type d'unité. Les points de réparation sont enlevés au bâtiment lorsque l'ordre de réparation est donné. Les différents éléments mentionnés se calculent ainsi (on dénote par Bx un bâtiment de réparation et Ux une unité amie):

Conditions de fin du jeu - Le jeu se termine soit lorsque un joueur n'a plus d'unité, soit lorsque qu'un joueur pénètre dans le quartier général adverse. Le jeu peut également se terminer automatiquement au bout d'un nombre de tours prédéterminé; dans ce cas, le joueur déclaré victorieux est celui disposant du plus grand nombre d'unités. En cas d'égalité, la somme des points de vie et des points d'expérience des unités du joueur sera considérée.

Particularités du jeu demandé

Après une présentation générale des principes du jeu, nous présentons ici les particularités du jeu que vous devez développer.

Plateau de jeu - La taille de la matrice rectangulaire servant à représenter le plateau de jeu n'est pas prédéfinie. Elle dépend d'une description de plateau lue depuis un fichier. Les cases ont chacune 8 cases voisines (on considère une case située en haut à gauche, en haut à droite, en bas à droite ou en bas à gauche d'une case comme sa voisine), hormis pour celles situées en bordure de plateau.

Types de cases - Les types de cases retenus et leurs caractéristiques sont décrites dans le tableau ci-dessous:

Type de case

Dessin

Coût de déplacement

prairie

1

forêt

3

montagne

4

eau

10

Les images pour ces différents types de case vous sont fournies en format PNG de taille 48*48 (ceci dit, si vous vous sentez une âme d'artiste, rien ne vous empêche de proposer les vôtres!).

Types d'unités - Les types d'unités retenus et leurs caractéristiques sont décrites dans les deux tableaux ci-dessous:

Type d'unité

Niveau de vie MAX

Niveau expérience MAX

Points mouvement

Charge

Capacité de chargement

infanterie

20

6

4

1

0

infanterie d'élite

20

8

5

1

0

cavalerie

20

6

7

3

0

véhicule blindé

20

4

6

6

0

artillerie légère

10

6

3

3

0

artillerie lourde

10

6

1

6

0

camion

20

3

6

20

6

 

Type d'unité

Points d'attaque

Portée (min-max)

Points de défense

Points de contre-attaque

infanterie

5

1-1

2

3

infanterie d'élite

6

1-2

3

3

cavalerie

3

1-1

3

4

véhicule blindé

7

1-2

6

2

artillerie légère

7

2-4

2

1

artillerie lourde

10

3-8

3

1

camion

0

1-1

3

1

Types de bâtiments - Les types de bâtiments retenus et leur caractéristiques sont décrites dans le tableau ci-dessous:

Type de bâtiment

Capacité d'accueil

Points de réparation initiaux

Points de réparation à chaque tour

Particularités

quartier général

6

10

3

Chaque joueur a initialement un et un seul quartier général. Si une unité ennemie y pénètre, son joueur est déclaré vainqueur.

hôpital

3

10

6

Un hôpital appartient à un joueur. Si une unité ennemie y pénètre, son joueur prend le contrôle de l'hôpital. Les unités du premier joueur se trouvant dans l'hôpital lors de sa prise sont éliminées.

bibliothèque

30

0

0

Une bibliothèque permet aux unités d'oublier le temps d'une lecture le caractère oppressant du champ de bataille. Si une unité ennemie y pénètre, son joueur en prend le contrôle et les unités prises en flagrant délit de lecture sont éliminées.

Contrairement aux cases du plateau, les bâtiments ne doivent pas exister sous forme d'images préexistantes mais doivent être dessinés au-dessus de la case où ils sont situés (la qualité du graphisme n'est pas primordiale, il faut simplement que les bâtiments soient bien reconnaissables).

Indications pour la réalisation

Nous vous donnons ici quelques indications pour votre réalisation. Le jeu qui vous est demandé est fortement inspiré d'un jeu de stratégie au tour par tour, History Lines, dont vous pouvez télécharger une version pour Windows ici (le jeu est considéré comme un abandonware par son éditeur, il peut donc être utilisé librement). Vous pouvez vous inspirez de ce jeu pour les éléments qui n'entrent pas en contradiction avec les spécifications présentées.

Données utilisées par le programme - Toutes les données utilisées par le programme (telles que celles données ci-dessus) doivent pouvoir facilement évoluer. Elles seront donc stockées dans des fichiers (dont vous choisirez le format le plus adapté) et seront chargées au début du jeu.

Initialisation d'une partie - Un plateau de jeu sera chargé au début du jeu: sa description comprend la matrice rectangulaire des cases constituant le plateau, et pour chaque joueur la description des bâtiments et des unités se trouvant sur la carte. Par défaut, les bâtiments auront une capacité de réparation maximale, et les unités des points de vie maximaux. Au début de la partie, les joueurs doivent s'entendre sur les conditions de victoires: prise du quartier général OU meilleur score au bout de tour OU destruction de toutes les unités ennemies.

Déroulement d'un tour - Pour le déroulement d'un tour, les joueurs "programment" leurs coups chacun leur tour. Le joueur programmant son tour d'attaque joue le premier. Il ne faut pas qu'ils puissent voir les coups programmés par leur adversaire. Lors de la programmation, chaque unité ne peut recevoir qu'un seul ordre. Un ordre peut être déprogrammé pour une unité donnée (par exemple, si un ordre est déjà programmé pour une unité, celle-ci peut apparaître dans une couleur grisée. Si son joueur cherche à lui affecter un autre ordre, le programme pourra commencer par lui demander s'il veut invalider l'ordre précédent.).

Mode attaque - Pour donner un ordre d'attaque lors du mode correspondant, il faut sélectionner l'unité. Toutes les unités ennemies qu'elle peut attaquer (i.e. qui sont dans sa portée d'attaque) sont alors "mises en valeur". En recliquant plus tard sur cette même unité, on veut pouvoir trouver l'information comme quoi une attaque a été programmée pour cette unité (par exemple, un trait peut être tiré entre les deux unités).

Mode déplacement - Pour donner un ordre de déplacement lors du mode correspondant, il faut sélectionner l'unité. Toutes les cases atteignables par un plus court chemin sont alors "mises en valeur". Cliquer sur une de ces cases programme le déplacement, qui est affiché à l'écran (i.e. l'unité est effectivement déplacée) afin que le joueur ait un aperçu de la position de ses unités après le déplacement. Un déplacement peut être annulé en cliquant sur une unité déjà déplacée (qui pourra par exemple être grisée). Attention cependant, l'annulation d'un déplacement peut annuler d'autre déplacement: en effet, si une unité A se déplace puis qu'une unité B se déplace et prend la place laissée vacante par l'unité A, annuler le déplacement de l'unité A implique l'annulation du déplacement de l'unité B. Dans un tel cas de figure, le joueur doit être averti de la conséquence de son déplacement. Une alternative acceptable serait de permettre le déplacement d'une unité déjà déplacée dans une des cases atteignables depuis sa case d'origine (i.e. d'avant son déplacement).

Le cas des déplacements vers ou depuis des bâtiments et des unités de transport est particulier. Un déplacement vers un bâtiment ou une unité de transport n'est permis que si la capacité de chargement disponible de l'hôte est supérieure ou égale à la charge de l'unité qu'on souhaite y déplacer. Un clic sur un bâtiment ou une unité de transport doit afficher son "chargement" ou "contenu": la sélection d'une unité présente active alors le mode déplacement de l'unité depuis son hôte jusqu'à un autre point atteignable de la carte.

Réparation d'unités - La réparation d'unités peut avoir lieu lors de n'importe quel tour. Néanmoins, l'unité reste ensuite immobilisée pour le tour courant et le tour suivant. Pour qu'une unité soit réparée, il faut qu'elle se trouve dans un bâtiment ayant une capacité de réparation, et que la capacité actuelle de réparation du bâtiment soit inférieure ou égale à la réparation demandée pour l'unité. Pour chaque unité qu'il souhaite réparer, le joueur peut spécifier une réparation comprise entre 1 et les points de vie maximums de l'unité concernée.

Idées d'amélioration du jeu

Dessin des unités - Vous devez dessiner les unités par dessus les dessins des cases où elles se trouvent (hormi pour les bâtiments et les unités de transport, où on ne peut voir les unités que lorsque l'on demande à voir "à l'intérieur" d'un hôte). Vous pouvez faire en sorte que l'orientation d'un unité dépendent par exemple de la direction de son dernier déplacement, ou bien de l'emplacement des unités qu'elle attaque ou qui l'attaquent.

Sauvegarde de partie - Vous pouvez implémenter une sauvegarde de l'état d'une partie dans un fichier (référence à la carte jouée, état des unités restantes et des bâtiment, tour courant) et une restauration.

Déroulement des batailles - Vous pouvez proposer des idées originales pour illustrer le déroulement des batailles pour informer les joueurs des résultats (ex: disparition d'unité, affaiblissement d'unité, etc.).

Informations sur les unités - Vous pouvez implémenter une zone d'information sur les unités, qui sera soit présente constamment dans une zone de l'écran et correspondra à l'unité présente sous la souris, soit présente en surimpression sur la carte lorsqu'une commande sera déclenchée.

Intelligence artificielle - Vous pouvez implémenter une intelligence artificielle pour permettre à un joueur humain d'affronter l'ordinateur... Non, là c'est vraiment dur!!! Il s'agirait d'un autre projet en soi!

Réalisation

Pour que votre code soit lisible vous mettrez un gros commentaire au début de chaque fichier indiquant à quoi servent les classes qui s'y trouvent, comment elles s'articulent pour constituer le module et à quoi sert ce module. Vous mettrez aussi un petit commentaire en tête de chaque méthode indiquant ce qu'elle fait, la signification de chacun de ses arguments, et celle de la valeur de retour. Enfin, mettez un petit commentaire indiquant ce que représente chaque champ de donnée de vos classes. Veillez aussi à respecter les conventions de nommage qui vous ont été indiquées dans le cours (verbe pour les fonction, noms pour les variables, etc.).

 

La fenêtre aura la géométrie suivante : en haut, une barre de menus pour initialiser, abandonner, charger une partie, sauver la partie en cours, quitte,et.. Au centre, et occupant toute la largeur de la fenêtre on aura le plateau de jeu, puis en bas de la fenêtre une ligne d’information (objet de classe JLabel) affichant les divers messages (qui a gagné, quel unité est déplacée). Pour jouer, l'utilisateur doit cliquer directement dans le plateau de jeu sur l'unité qu’il désire deplacée.

 

Un aspect important de ce projet est de bien prévoir que toutes les fonctionnalités seront facilement réalisables avec votre façon d’implanter une unité et avec l’organisation des données.

 

Si vous voyez des améliorations possibles, faites les et justifiez les. Par exemple avoir la possibilité de changer les images du terrain, afficher des animations lors des déplacements, afficher une fenêtre d'aide, etc.

 

Les commandes de sauvegarde et de rechargement de parties se feront par l'intermédiaire d'un sélecteur de fichiers (prévoir une boite de dialogue pour traiter les cas d'erreur, si on veut écraser un fichier déjà existant, ou charger un fichier inexistant par exemple . . . ).

 

Pour implémenter votre interface graphique vous pouvez utiliser un dérivé de la classe JPanel. Il vous faudra redéfinir la méthode d'affichage (paint) pour dessiner les cases et les unités. Vous pouvez utiliser des images gif ou jpeg pour représenter le plateau de jeu et les tuiles, ou bien les fonctions de dessin de la classe Graphics. Quand la partie est terminée le programme doit afficher qui a gagné (soit avec une boite de dialogue, soit par un message dans la fenêtre principale).

 

On désire réaliser une application, et non pas une applette, entre autres pour pouvoir accéder aux fichiers (pour charger ou sauver une partie). Pour cela, on fera dériver la classe principale de la classe JFrame, qui comportera tous les composants nécessaires au jeu.

 

Afin de vous aider à évaluer votre état d’avancement nous proposons vous proposons de respecter les étapes suivantes :

1.      Une hiérarchie de classe pour représenter les unités et les batiments.

2.      Une fenêtre simple avec son menu, sa barre d’état et un contenu vide

3.      Insérer un contenu correspondant à une case avec une unité dessus.

4.      Une grille de case avec le même type case partout. Une unité simple sur la case du milieu.

5.      Réaliser l’interaction qui permet de sélectionner une unité, de la poser ailleurs. Réaliser l’interaction lorsque le joueur tente un coup illégal.

6.      Créer les 2 joueurs, la liste des unités et des bâtiments.

7.      Réaliser les algorithmes pour connaître les déplacements autorisés.

8.      Réaliser les algorithmes pour les combats.

9.      Réaliser la gestion des tours. Gestion des coups autorisées ou non.

10.  Réaliser les fonctions de sauvegarde et de chargement

11.  Réaliser un mini-serveur qui reçoit les coups joués par un client et les affiche simplement dans la grille.

12.  Modifier le serveur pour que se soit lui qui gère les tours de jeu.

13.  Modifier le serveur pour centraliser le démarrage, le chargement et la sauvegarde.

14.  Modifier le serveur pour diffuser les coups joués à distance au client et vice-versa.

 

Structure du programme

C'est à vous de concevoir l'architecture de votre programme de façon à ce qu'il ait toutes les qualités exigées d'un bon logiciel : simplicité, concision, clarté, etc. Comme il s’agit de votre premier projet nous fournissons quelques interfaces a respecter :

 

Les moteurs manuels

Vous devrez réaliser trois versions du moteur de jeu, la version bi-joueur qui fait jouer deux joueurs humains, la version espionne qui observe sans permettre de jouer, et enfin une version complète à travers le réseau. Bien sûr, le coup joué par l'humain numéro un doit être légal (son moteur doit le vérifier), alors que le coup de adversaire reçu par ce même moteur manuel est forcément légal (son propre moteur l'ayant vérifié).

 

Tant qu'aucun client n'est connecté, l'interface du serveur est inactive (le joueur ne peut rien faire). Une fois un client connecté, l'interface du serveur devient active et c'est à lui de jouer en premier. Quand un joueur décide d'arrêter de jouer, son moteur envoie le code 70 à son vis-à-vis pour le lui indiquer. Si c'est le client qui décide de s'arrêter, le serveur, sur réception du code de fin, se réinitialise (i.e. se remet en attente d'un nouveau client). Si c'est le serveur qui décide de s'arrêter, le client et les espions se terminent (de toutes façons, ils n'auront plus de serveur à qui parler!).

 

Si une panne, ou toute autre cause, provoque l'arrêt du client, le serveur s'en rendra compte par une exception et devra se réinitialiser; Si la panne provoque l'arrêt du serveur, tous les autres, le client et les éventuels espions, devront se terminer.

 

Un joueur a la possibilité d'abandonner la partie en cours, cela signifie qu'il a perdu de fait. Cette possibilité est donc à traiter de façon analogue à une fin de partie (perdante pour celui qui abandonne). La différence est que le code transmis à l'opposant a la valeur 71, et que les programmes ne s'arrêtent pas : on peut recommencer une nouvelle partie.

 

De même, un joueur a la possibilité de recharger une nouvelle partie (quand c'est à lui de jouer bien sûr) cela signifie qu'il abandonne la partie en cours, avec les conséquences citées plus haut.

 

Le moteur espion est une version simplifiée du moteur manuel client : il ne permet pas à l'utilisateur de jouer (il interdit tout coup, et toute demande de chargement ou de sauvegarde de partie). Il ne permet que de faire afficher par son interface utilisateur la partie qu'il observe.

 

On ne peut avoir qu'un seul moteur manuel client, mais plusieurs moteurs espions connectés au même moteur manuel serveur. Celui-ci devra gérer correctement tous ses clients : une bonne façon de faire est d'avoir un thread par client.

Attention : le moteur serveur doit indiquer aux moteurs espions tous les coups joués : les siens, et ceux de l'autre joueur.

 

Comme un moteur espion peut se connecter au serveur à tout moment de la partie, il est clair que le serveur doit pouvoir lui transmettre la totalité de son plateau de jeu. Initialement (avant que le client soit connecté), le serveur ne peut pas modifier le plateau de jeu : il ne peut pas jouer, ni charger de partie.

 

Le protocole de communication entre les moteurs est le suivant (fig. 5) :

·        le moteur client, une fois connecté au moteur serveur, s'identifie en lui envoyant l'octet de valeur 67.

·        les moteurs espions s'identifient auprès du serveur en envoyant l'octet de valeur 69.

·        la transmission d'un plateau de jeu se fait en envoyant l'octet de valeur 64, une fin de ligne, puis le contenu complet du tableau, ligne par ligne, en ascii lisible avec un espace et une virgule entre chaque case (c'est à dire exactement le même format que pour la sauvegarde dans un fichier).

 

Pour indiquer le coup joué, un moteur envoie à son vis-à-vis l'octet de valeur 97 suivi des coordonnées de la case jouée (en ajoutant un décalage de 64 pour avoir de l'ascii lisible), soit trois octets en tout.

 

Figure 1 : Architecture du réseau.

A vous de voir quelles sont les relations entre les différents moteurs, pour réutiliser au maximum le code que vous allez écrire; pensez d'abord aux différentes classes dont vous allez avoir besoin, avant de vous lancer dans la programmation : faites un diagramme des relations entre les classes (utilisation croisée, dérivation, . . . ), énumérez les attributs et les méthodes  de chaque classe, ce n'est qu'ensuite que vous écrirez le corps des méthodes.