## 4. Construction d'un robot

Ce chapitre décrit ce dont vous aurez besoin afin de construire vos propres robots. Le plus important à savoir est le langage de messages, qui est composé de 35 commandes utilisées pour communiquer avec le serveur. Il peut également être interresant d'étudier les exemples de robots livrés dans le repertoire `Robots/`.

## 4.1 Lire un message

Au début de chaque séquence, les processus des robots sont lancés par le serveur et deux 'pipes' leur sont assignés (un pour les 'Entrees' et l'autre pour les 'Sortie'). Ces deux pipes sont connectés à `stdin` et `stdout`, de telle sorte que du point de vue du robot, la communication avec le serveur s'effectue via l'entrée et la sortie standards.

Cette approche vous laisse libre du langage de programmation. Toutefois, le robot doit savoir quand il reçoit un nouveau message. Il y a (au moins) trois méthodes pour y parvenir :

Standard in blocks:

  C'est la méthode la plus simple. En lisant l'entrée standard `stdin`, le programme est bloqué jusqu'à l'arrivée d'un nouveau message. Vous pouvez donc construire votre programme comme si il y avait toujours un mesage en attente. Le point noir est que vous ne pouvez faire aucun calcul pendant que le programme attend un nouveau message.

  Pour choisir cette méthode, il faut envoyer l'option suivante dès que le programme est lancé

      cout << "RobotOption " << USE_NON_BLOCKING << " " << 0 << endl;

  Ceci est un code C++. Si vous n'utilisez pas le C++, il suffit d'afficher l'information (comme si vous deviez afficher quelquechose à l'écran). endl est l'équivalent de 'fin de ligne'.

Select:

  Utiliser la fonction `select` de libc permet au robot d'avoir un meilleur contrôle pour savoir quand regarder les nouveaux messages. Il vous permet, par exemple, de lire tous les messages, faire quelques calculs, envoyer les commandes puis d'attendre de nouveaux messages. Pour en savoir plus à propos de `select`, lisez la documentation Unix ( e.g. man pages or emacs info ).

  Pour choisir cette méthode, envoyer l'information suivante dès que le programme est lancé:

      cout << "RobotOption " << USE_NON_BLOCKING << " " << 1 << endl;

  Il s'agit encore une fois d'un ligne de code C++

Signals:

  Si vous voulez, vous pouvez demander à RealTimeBattle d'envoyer un signal au robot quand une nouvelle serie de messages est envoyée. Cette méthode permet au robot d'être continuellement mis au courant des informations du serveur même lorsqu'il est occupé par des calculs. Si vous n'en savez pas assez sur les signaux, regarder la documentation Unix ou étudiez les autres robots pour en savoir plus.

  Pour utiliser cette méthoed, envoyé l'option suivante au serveur dès le lancement du programme

      cout << "RobotOption " << USE_NON_BLOCKING << " " << 1 << endl;
      cout << "RobotOption " << SIGNAL << " " << SIGUSR1 << endl;

  Toujours du C++.

  Vous pouvez bien sûr utiliser n'importe quel signal à la place de `SIGUSR1`.

Pour vous aider à implanter ces méthodes, le robot `rotate_and_fire` a été écrit de trois manières différentes, mais fonctionnent de la même façon. Vous êtes libre de l'étudier et de le copier pour votre propre robot.

Ce n'est pas une bonne idée de faire du 'busy wait', i.e., de regarder répetitivement les messages jusqu'à en avoir un. Cela ralentit considérablement les choses et pire, en mode competition le robot sera vite au delà du CPU qui lui est accordé et mourrira.

## 4.2 Messagetypes.h

Le fichier `Messagetypes.h` est une bonne source d'information sur le langage de communication. C'est un fichier d'inclusion C/C++, mais il est facile de le réécrire dans un autre langage de programmation. Vous pourrez y trouver la liste des messages, les types d'avertissement, les objets, les options de jeu et de robot.

## 4.3 Tricher

Durant la progression de la bataille en temps réel, avec des processus réels, il est possible d'écrire des programme qui 'trichent' à un moment ou à un autre. Par exemple, en examinant les autres robots ou le serveur pour avoir plus d'informations, en utilisant d'importantes resources pour ralentir les autres robots et de bien d'autres façons encore. Ce n'est bien sur pas la méthode attendue pour vaincre l'adversaire, alors nous essayons de limiter ces actions autant que possible.

Dans le mode competition les robots ne sont pas autorisé à lancer des processus fils et l'utilisation du CPU est limitée. Ainsi, un robot ne peux pas utiliser tout le CPU.

Il n'est pas possible d'empecher toutes les façons de tricher dans RTB. Il est par exemple possible d'écrire ou de lire des fichiers, mais souvenez vous que les organisateurs de compétitions peuvent interdir cele s'il le souhaite. Limiter les droits d'acces du robot donne des résultats satisfaisants.

Il est toujours possible de trouver des moyens de contourner ces restrictions; si vous trouver un de ces moyens, s'il vous plait, envoyer nous un rapport de bug. Néanmoins, il est du bon plaisir de l'oganisateur du tournoi d'assurer le respect de ces règles.

## 4.4 Messages vers les robots

Initialize [first? (int)]

  C'est le premier message que le robot recevra. Si l'argument est 1, c'est la première sequence d'un tournoi et le robot doit se présenter en envoyant son Nom et sa Couleur au serveur, sinon il devra attendre les messages YourName et YourColour (voir plus loin). (En fait, je n'en suis pas trop sur...)

YourName [name (string)]

  Le nom courant du robot, à ne pas changer sans avoir une bonne raison.

YourColour [colour (hex)]

  Couleur courante du robot, à changer si elle n'est pas à votre goût.

GameOption [optionnr (int)] [value (double)]

  Au début de chaque jeu, le robot recevra un certain nombre de caractéristiques qui pourraient lui être utiles. Pour obtenir une liste complète de ces messages, regardez le fichier Messagetypes.h pour voir l'enumeration des `game_option_type`. Dans le chapitre des options vous obtiendrez des informations plus détaillées. Le niveau de debuggage est aussi envoyé comme option, même s'il ne fait pas partie de la liste.

GameStarts

  C'est le message envoyé pour signaler le début de la bataille (surpris?)

Radar [distance (double)] [type de l'objet observé (int)] [angle radar (double)]

  Ce message donne les informations venant du radar à chaque tour. Souvenez vous que l'angle du radar est relatif à l'avant du robot. Il est donné en radians.

Info [temps (double)] [vitesse (double)] [angle cannon (double)]

  Le message Info suit toujours le message Radar. Il donne des informations plus générales sur l'état du robot. Le temps est celui écoulé depuis le début du jeu. Ce n'est pas forcement le même que le temps réellement écoulé (à cause de l'échelle de temps et du plus petit écart de temps.

Coordinates [x (double)] [y (double)] [angle (double)]

  Vous donne la position courante du robot. Il est envoyé seulement si l'option est 1 ou 2. Si elle est 1 les coordonnées sont envoyés relativement à la position de départ (Le robot ne sait pas exactement où il a commencé, mais seulement de combien il s'est déplacé).

RobotInfo [niveau d'energie (double)] [teammate? (int)]

  Si vous détecter un robot au radar, ce message suivra, donnant les informations sur ce robot. Le niveau d'énergie de l'adversaire sera donné de la même façon que votre propre énergie (voir plus bas). Le second argument concerne seulement le mode en équipe (qui n'est pas encore implanté), 1 signalant qu'il s'agit d'un membre de votre équipe et 0 un ennemi.

RotationReached [objet qui a attend(int)]

  Quand l'option robot SEND_ROTATION_REACHED est activée, ce message est envoyé quand une rotation (avec RotateTo ou RotateAmount) est terminée ou que la direction à changée (lors d'un balayage).

Energy [niveau d'energie (double)]

  A la fin de chaque tour, le robot connaîtra son niveau d'énergie. Il ne connaîtra pas exactement son niveau exact, mais une approximation correspondant à des niveaux d'énergie.

RobotsLeft [nombre de robots (int)]

  Au début du jeu et quand un robot est tué, le nombre de robots restant est envoyé à tous les robots encore vivant.

Collision [type de l'objet recontré(int)] [angle relatif au robot (double)]

  Quand un robot cogne (ou est cogné par) quelquechose, il reçoit ce message. Dans le fichier Messagetypes.h vous trouverez la liste des types d'objets. Vous recevrez aussi l'angle auquel c'est produit la collision (angle relatif au robot) et le type de l'objet qui a été cogné, mais pas l'importance du choc. Elle peut tout de même être déterminée indirectement (approximativement) par la perte d'énergie.

Warning [type de l'avertissement (int)] [message (string)]

  Un message d'avertissement peut être envoyé quand un robot à fait quelquechose d'incorrecte. Pour le moment, il y a 7 messages d'avertissement différents :

  `UNKNOWN_MESSAGE:` Le serveur a reçu un message qu'il n'arrive pas à reconnaitre.

  `PROCESS_TIME_LOW:` L'utilisation du CPU a atteind le pourcentage critique de CPU. Seulement dans le mode competition.

  `MESSAGE_SENT_IN_ILLEGAL_STATE:` Le message envoyé ne correspond pas à l'état d'avancement du programme. Par exemple Rotate a été envoyé avant le début du jeu.

  `UNKNOWN_OPTION:` Le robot a envoyé une option qui est soit un nom inégale, soit un argument ne correspondant pas à une option.

  `OBSOLETE_KEYWORD:` Le mot clef envoyé est obselete et ne doit plus être utilisée. Voir le fichier `ChangeLog` pour des informations pour ce qu'il faut utiliser à la place.

  `NAME_NOT_GIVEN:` Le robot n'a pas envoyé son nom avant le début du jeu. Ca arrive si le temps de démarrage du robot est trop (...) ou que le robot n'envoye pas son nom assez tôt.

  `COLOUR_NOT_GIVEN:` Le robot n'a pas envoyé sa couleur avant le début du jeu.

Dead

  Le robot est mort. Ce n'est plus la peine d'envoyer de nouveaux messages au server avant la fin du jeu, le serveur ne les lit plus.

GameFinishes

  Le jeu courant est terminé, préparez vous au prochain jeu!!!

ExitRobot

  Quitter le programme immédiatement!! Sinon on sera forcé de le tuer.

## 4.5 Messages venant des robots.

RobotOption [option nr (int)] [valeur (int)]

  Il n'y a pour le moment que deux options possibles :

  `SIGNAL:` Dire au serveur d'envoyer un signal quand il y a un message qui attend. L'argument déterminera quel signal utiliser. Envoyez ce message (avec l'argument SIGUSR1 par exemple) dès que vous êtes prêt à recevoir les signaux. Par défaut, cette valeur est 0, ce qui veut dire que vous ne recevrez aucun signal.

  `SEND_SIGNAL:` Demande au serveur d'envoyer SIGUSR1 quand il y un message qui attend. Envoyez ce message (avec l'argument 1 (=vrai)) dès que vous être prêt à recevoir le signal. Par défaut, la valeur est fausse.

  `SEND_ROTATION_REACHED:` Si vous voulez que le serveur vous envoye le message RotationReached quand une rotation est terminée, vous devez demander cette option. Avec une valeur de 1, le message est envoyé quand un RotateTo ou un RotateAmount est terminé, avec le valeur 2, quand les changement de direction d'un sweep est aussi indiqué. Par défaut (0) aucun message ne sera envoyé.

  `USE_NON_BLOCKING:` Choisit comment la lecture des messages s'effectue. Cette option doit être envoyée dès que le programme est lancé. Puisqu'elle doit toujours être donnée, il n'y a pas de valeur par défaut.

Name [nom (string)]

  Quand vous recevez le message Initialize avec l'argument 1, indiquant qu'il s'agit de le première séquence, vous devez envoyer votre nom et votre couleur.

Colour [première couleur (hex)] [couleur 'visiteur' (hex)]

  (Voir plus haut). Les couleurs sont comme des maillons de foot, la première couleur est utilisée si personne ne l'a déjà prise. Sinon, la couleur 'visiteur' ou en dernier recourt, une couleur choisie au hasard sera donnée au robot.

Rotate [objet a tourner (int)] [vitesse angulaire (double)]

  Selectionne la vitesse angulaire de rotation du robot, de son canon ou de son radar. L'objet doit être 1 pour le robot, 2 pour le cannon, 4 pour le radar ou la somme pour faire tourner plusieurs objets en même temps. La vitesse angulaire est donnée en radians par seconde et est limité par la Vitesse maximum de rotation du Robot (cannon/radar).

RotateTo [objet à tourner (int)] [vitesse angulaire (double)] [angle de fin (double)]

  Comme Rotate, mais s'arrêtera à un angle donné. L'angle du radar et du cannon sont relatif à l'angle du robot. Vous ne pouvez pas utiliser cette commande pour faire tourner le robot (Utilisez RotateAmount à la place).

RotateAmount [objet à tourner(int)] [vitesse angulaire (double)] [angle (double)]

  Comme Rotate, mais tourne par rapport à l'angle courant.

Sweep [objet a tourner(int)] [vitesse angulaire (dbl)] [angle gauche (dbl)] [angle droit(dbl)]

  Comme rotate, mais fait tourner le radar et/ou le cannon (pas disponible pour le robot lui même) dans un mode de balayage.

Accelerate [valeur (double)]

  Définit l'accélaration du robot. La valeur est limitée pas l'accélération max/min du Robot.

Brake [portion (double)]

  ordonne un frainage. Le frein complet (portion = 1.0) signifie que la friction du robot dans le sens de déplacement est égal au frottement dû au glissement.

Shoot [energie du missile (double)]

  Tire un missile avec l'energie donnée. Les options de tire donnent plus d'informations.

Print [message (string)]

  Affiche un message sur la fenêtre de messages.

Debug [message (string)]

  Affiche un message dans la fenêtre des messages si le mode debug est engagé.

DebugLine [angle1 (double)] [rayon1 (double)] [angle2 (double)] [rayonn2 (double)]

  Dessine une ligne directement sur l'arène. Seulement disponible dans le plus haut mode de debug(5), sinon un message d'avertissement est envoyé. Les arguments sont les points de départ et d'arrivée donnés en coordonnées polaires relativement au robot.

DebugCircle [angle centre (double)] [rayon centre (double)] [rayon cercle (double)]

  Identique que pour DebugLine, mais dessine un cercle. Les deux premiers arguments sont l'angle et le rayon relativement au robot. Le troisième argument donne le rayon du cercle.