Cartouche

Champ Valeur
Auteur·e Élise
Édition 2024-06-04
Durée 2 séances
Taille des équipes 1~2 personnes
login des auteur·rice·s dans author.txt, séparés par des retours à la ligne
Rendu via git, dépôt 2023_morpion, branche td4, droits en lecture à delivery_collector

Préambule

Notation

Introduction

Pour le moment, votre serveur est capable de faire tourner qu’une seule partie à la fois sur un seul fil d’exécution. Il arrive cependant à gérer deux clients/joueurs sans bloquer, ce qui signifie qu’il n’est pas impossible de faire tourner une partie sans bloquer, et à terme de faire tourner plusieurs parties sans qu’elles se bloquent les unes les autres.

C’est l’objectif de ce TD : faire tourner plusieurs parties en simultané sur un même fil d’exécution.

Pour ce faire, on va faire passer votre logique de jeu vers une classe distincte, ce que vous avez peut-être déjà fait et on va la rendre elle aussi non bloquante, là où aujourd’hui elle a probablement une boucle infinie tant que la partie qu’elle contient n’est pas finie, ou que personne ne s’est déconnecté.

Le but c’est de pouvoir avoir une boucle principale qui ressemble à ceci :

int main(void)
{
    GfxPlayer  gfx_player;
    TermPlayer term_player;
    GfxPlayer  gfx_player2;
    StandaloneNetPlayer net_player;
    GameArena  arena1{&gfx_player, &term_player};
    GameArena  arena2{&gfx_player2, &net_player};

    while (!arena1.done() && !arena2.done()) {
        arena1.cycle_once();
        arena2.cycle_once();
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
}

Et à terme de pouvoir générer des arènes avec des NetPlayer au fur et a mesure des connections.

Implémentation : arène

Implémentez une classe GameArena dont le métier est de construire une MorpionGame, et de faire avancer et suivre l’avancement de la partie de deux joueurs (IPlayer).

Elle doit pouvoir être construite avec l’adresse ou la référence de deux IPlayer. À la construction elle doit envoyer l’état initial de la partie et l’ordre de jouer au premier joueur dont c’est le tour.

La classe doit avoir les fonctions membres suivantes :

class GameArena {
public:
	GameArena(IPlayer &, IPlayer &);

	// cycle once, process player events
	// check if current player made a mode,
	// check if players are still here
	void cycle_once();

	// while not done, call cycle_once in a loop
	void run();

	// if game is done or one player has left, returns 1
	// otherwise when the game is running, returns 0
	bool done() const;
private:
	// [the fields you need for the logic of the class]
};

Génération de parties

Pour reprendre le travail de TD 3 • StandaloneNetPlayer et client.

Adaptez votre serveur pour qu’il ai le comportement suivant :

  • en argument il reçoit un nombre de partie à héberger ;
  • il attend la création de 2 StandaloneNetPlayer par partie demandée ;
  • il crée une GameArena par partie, dans laquelle il met 2 StandaloneNetPlayer ;
  • il exécute en boucle la fonction run_once de toutes les parties créées jusqu’à ce qu’elles soient toutes done.