Aller au contenu

Commandes & délais

Cette page décrit comment le serveur parse, représente et planifie les commandes envoyées par les IA, ainsi que le coût en temps (délai) de chacune.

Parsing — CommandParser

Chaque ligne reçue d'une IA est analysée par CommandParser::parse (server/srcs/protocol/CommandParser.cpp:38-67). Le parser découpe le nom (avant le premier espace) et l'argument (le reste), puis instancie la sous‑classe ACommand correspondante :

if (name == "Forward" && arg.empty())      return new CmdForward();
...
if (name == "Broadcast" && !arg.empty())   return new CmdBroadcast(arg);
if (name == "Take" && !arg.empty())        return new CmdTake(arg);
if (name == "Set" && !arg.empty())         return new CmdSet(arg);
if (name == "Incantation" && arg.empty())  return new CmdIncantation();
return nullptr;

Présence d'argument stricte

Le parser rejette toute commande dont la présence d'argument est incorrecte : un argument fourni à Forward, ou un argument manquant à Take, renvoie nullptr → le serveur répond ko. Seuls Broadcast, Take et Set exigent un argument ; toutes les autres doivent en être dépourvues.

Représentation — une classe par commande

Chaque commande est une sous‑classe de l'interface ACommand (server/srcs/commands/ACommand.hpp:42-69), avec une instance par commande dans server/srcs/commands/. L'interface clé :

class ACommand {
public:
    virtual void        execute(Player& player, World& world) = 0;
    virtual int         getDelay()    const = 0;   // coût en unités de temps
    virtual std::string getResponse() const { return "ok\n"; }
    virtual CommandType getType() const = 0;
    ...
};

Les 12 commandes IA sont toutes implémentées : Forward, Right, Left, Look, Inventory, Broadcast, Connect_nbr, Fork, Eject, Take, Set, Incantation.

CmdIncantation est un no‑op

CmdIncantation::execute ne fait rien (server/srcs/commands/CmdIncantation.cpp:22-26). Toute la logique d'élévation est portée par IncantationHandler et IncantationAlgo — voir Mécaniques de jeu. La commande sert uniquement de marqueur de type dans la boucle.

Planification — un délai par commande

La boucle principale dépile une commande par IA inactive à chaque itération. Une IA est inactive si elle n'est pas en incantation, pas busy, et a une commande en file (server/srcs/core/Server.cpp:163-217). La commande est ensuite planifiée pour s'exécuter après cmd->getDelay() unités de temps :

ai->setBusy(true);
...
int playerId = ai->getPlayer()->id;
_scheduler->schedule([this, playerId, cmd]() {
    ...
    cmd->execute(*ai->getPlayer(), *_world);
    ...
    ai->queueWrite(cmd->getResponse());
    ai->setBusy(false);
    _aiDispatcher->decrementPendingResponses(*ai);
    delete cmd;
}, cmd->getDelay());

Pendant l'attente, l'IA est busy : elle n'exécute aucune autre commande, ce qui sérialise ses actions. L'incantation est un cas particulier traité en amont par IncantationHandler::start (voir Mécaniques de jeu).

Délais en unités de temps

getDelay() renvoie un coût en unités de temps, converti en millisecondes par le Scheduler : delai_ms = délai × 1000 / fréquence. Plus la fréquence (-f) est élevée, plus les actions sont rapides. Voir Boucle de jeu & temps.

Table des délais

Commande Délai (unités de temps) Argument
Forward 7
Right 7
Left 7
Look 7
Inventory 1
Broadcast 7 texte requis
Connect_nbr 0
Fork 42
Eject 7
Take 7 objet requis
Set 7 objet requis
Incantation 300

(Valeurs lues dans les getDelay() des en‑têtes commands/Cmd*.hpp ; Connect_nbr : server/srcs/commands/CmdConnectNbr.cpp:29-32.)

Connect_nbr instantané

Connect_nbr a un délai de 0 : sa réponse (nombre d'œufs restants de l'équipe) est fixée dans la boucle juste avant l'envoi (server/srcs/core/Server.cpp:311-316). Voir Joueurs, équipes & œufs.

flowchart LR
    L["Ligne IA"] --> P["CommandParser::parse"]
    P -->|null| KO["ko"]
    P -->|ACommand*| Q["File par IA"]
    Q --> D["Boucle : 1 cmd / IA inactive"]
    D --> S["scheduler.schedule(getDelay())"]
    S -->|échéance| E["cmd->execute()<br/>+ réponse + setBusy(false)"]

Voir aussi