Communication
Votre programme communique avec le jeu grâce à deux composants que tous les robots possèdent :
- L’émetteur (emitter) envoie des messages au jeu. Il n’a pas besoin d’être activé.
- Le récepteur (receiver) reçoit les messages du jeu. Activez-le comme un capteur.
Chaque section ci-dessous est un programme complet pour le robot de départ. Tous les messages sont listés dans la Référence des messages.
Marquer des points avec les marqueurs muraux
Section intitulée « Marquer des points avec les marqueurs muraux »Pour marquer les points d’une victime lettre (letter victim) ou d’une cible cognitive (cognitive target), le robot doit :
- S’arrêter plus d’une seconde près du marqueur. Erebus ignore le signalement si le robot a bougé au cours de la dernière seconde.
- Envoyer la position et le type du marqueur : X et Z en centimètres, et le type sous forme d’une lettre.
| Marqueur mural | Type |
|---|---|
| Victime lettre Φ (blessée, harmed) | H |
| Victime lettre Ψ (stable) | S |
| Victime lettre Ω (indemne, unharmed) | U |
| Cible cognitive, somme 0 (Gaz inflammable, Flammable Gas) | F |
| Cible cognitive, somme 1 (Toxique, Poison) | P |
| Cible cognitive, somme 2 (Corrosif, Corrosive) | C |
| Cible cognitive, somme 3 (Peroxyde organique, Organic Peroxide) | O |
Les types sont des lettres, même si les victimes affichent des symboles depuis 2026. Le GPS donne des mètres : multipliez donc par 100.
from controller import Robotimport struct
robot = Robot()timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter") # Always on the robot. It does not need to be enabled.gps = robot.getDevice("gps")gps.enable(timeStep)leftWheel = robot.getDevice("left wheel motor")rightWheel = robot.getDevice("right wheel motor")leftWheel.setPosition(float("inf"))rightWheel.setPosition(float("inf"))
def wait(seconds): start = robot.getTime() while robot.step(timeStep) != -1: if robot.getTime() - start >= seconds: break
def report(tokenType): # 1. Stop for more than 1 second leftWheel.setVelocity(0) rightWheel.setVelocity(0) wait(1.2) # 2. Send the position in centimeters, and the type as one letter x, _, z = gps.getValues() message = struct.pack("i i c", int(x * 100), int(z * 100), tokenType.encode()) emitter.send(message) robot.step(timeStep)
report("H") # Reports a harmed victim (Φ) where the robot isprint("Reported")#include <iostream>#include <cmath>#include <cstring>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>#include <webots/GPS.hpp>#include <webots/Motor.hpp>
using namespace webots;
Robot *robot;Emitter *emitter;GPS *gps;Motor *leftWheel, *rightWheel;int timeStep;
void wait(double seconds) { double start = robot->getTime(); while (robot->step(timeStep) != -1) { if (robot->getTime() - start >= seconds) break; }}
void report(char tokenType) { // 1. Stop for more than 1 second leftWheel->setVelocity(0); rightWheel->setVelocity(0); wait(1.2); // 2. Send the position in centimeters, and the type as one letter int position[2] = {(int)(gps->getValues()[0] * 100), (int)(gps->getValues()[2] * 100)}; char message[9]; memcpy(message, position, sizeof(position)); message[8] = tokenType; emitter->send(message, sizeof(message)); robot->step(timeStep);}
int main() { robot = new Robot(); timeStep = (int)robot->getBasicTimeStep();
emitter = robot->getEmitter("emitter"); // Always on the robot. It does not need to be enabled. gps = robot->getGPS("gps"); gps->enable(timeStep); leftWheel = robot->getMotor("left wheel motor"); rightWheel = robot->getMotor("right wheel motor"); leftWheel->setPosition(INFINITY); rightWheel->setPosition(INFINITY);
report('H'); // Reports a harmed victim (Φ) where the robot is std::cout << "Reported" << std::endl;
delete robot; return 0;}Le robot doit être du même côté du mur que le marqueur, et le robot comme la position envoyée doivent en être proches. Les règles exigent au plus une demi-case : visez cela. Erebus v26.1 vérifie une distance de 9 cm.
Exécutez ce programme au départ de world1.wbt : il n’y a pas de marqueur à cet endroit, donc l’historique de la fenêtre de contrôle affiche Misidentification of Victim -5. Un mauvais signalement, y compris le signalement d’un leurre, coûte 5 points, et chaque marqueur ne rapporte des points qu’une seule fois.

Absence de progression
Section intitulée « Absence de progression »Quand le robot est bloqué, une absence de progression (Lack of Progress) le ramène au dernier point de contrôle et coûte 5 points. Elle se produit automatiquement au bout de 20 secondes sans mouvement, et votre programme peut aussi la déclencher en envoyant L. À chaque fois, le jeu envoie L au robot, pour que votre programme sache que sa position a changé.
from controller import Robotimport struct
robot = Robot()timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")receiver = robot.getDevice("receiver")receiver.enable(timeStep) # The receiver must be enabled
askedAt = Nonewhile robot.step(timeStep) != -1: # Call a lack of progress once, after 2 seconds if askedAt is None and robot.getTime() > 2: emitter.send(struct.pack("c", b"L")) askedAt = robot.getTime()
# Listen for messages from the game while receiver.getQueueLength() > 0: data = receiver.getBytes() if len(data) == 1 and data == b"L": print("Lack of progress! The robot is back at the last checkpoint.") receiver.nextPacket()#include <iostream>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>#include <webots/Receiver.hpp>
using namespace webots;using namespace std;
int main() { Robot *robot = new Robot(); int timeStep = (int)robot->getBasicTimeStep();
Emitter *emitter = robot->getEmitter("emitter"); Receiver *receiver = robot->getReceiver("receiver"); receiver->enable(timeStep); // The receiver must be enabled
bool asked = false; while (robot->step(timeStep) != -1) { // Call a lack of progress once, after 2 seconds if (!asked && robot->getTime() > 2) { char message = 'L'; emitter->send(&message, 1); asked = true; }
// Listen for messages from the game while (receiver->getQueueLength() > 0) { const char *data = (const char *)receiver->getData(); if (receiver->getDataSize() == 1 && data[0] == 'L') cout << "Lack of progress! The robot is back at the last checkpoint." << endl; receiver->nextPacket(); } }
delete robot; return 0;}Le récepteur peut recevoir différents messages : vérifiez donc la longueur de chacun avant de le lire, comme dans l’exemple.
Informations de jeu
Section intitulée « Informations de jeu »Envoyez G pour obtenir le score et le temps restant. Le jeu répond par un message de 16 octets : la lettre G, le score, le temps de jeu restant et le temps réel restant, en secondes.
from controller import Robotimport struct
robot = Robot()timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")receiver = robot.getDevice("receiver")receiver.enable(timeStep)
lastAsked = 0while robot.step(timeStep) != -1: # Ask for the game information once a second if robot.getTime() - lastAsked > 1: emitter.send(struct.pack("c", b"G")) lastAsked = robot.getTime()
while receiver.getQueueLength() > 0: data = receiver.getBytes() if len(data) == 16: # The game information is 16 bytes long _, score, timeLeft, realTimeLeft = struct.unpack("c f i i", data) print("Score:", round(score, 2), "Time left:", timeLeft, "s", "Real time left:", realTimeLeft, "s") receiver.nextPacket()#include <iostream>#include <cstring>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>#include <webots/Receiver.hpp>
using namespace webots;using namespace std;
int main() { Robot *robot = new Robot(); int timeStep = (int)robot->getBasicTimeStep();
Emitter *emitter = robot->getEmitter("emitter"); Receiver *receiver = robot->getReceiver("receiver"); receiver->enable(timeStep);
double lastAsked = 0; while (robot->step(timeStep) != -1) { // Ask for the game information once a second if (robot->getTime() - lastAsked > 1) { char message = 'G'; emitter->send(&message, 1); lastAsked = robot->getTime(); }
while (receiver->getQueueLength() > 0) { const char *data = (const char *)receiver->getData(); if (receiver->getDataSize() == 16 && data[0] == 'G') { // The game information is 16 bytes long float score; int timeLeft, realTimeLeft; memcpy(&score, data + 4, 4); memcpy(&timeLeft, data + 8, 4); memcpy(&realTimeLeft, data + 12, 4); cout << "Score: " << score << " Time left: " << timeLeft << " s Real time left: " << realTimeLeft << " s" << endl; } receiver->nextPacket(); } }
delete robot; return 0;}Le temps de jeu s’écoule plus vite dans les marécages, et la partie se termine dès que l’un des deux temps est écoulé. Utilisez les deux pour savoir quand revenir au départ.
Terminer la partie
Section intitulée « Terminer la partie »Envoyez E pour terminer la partie. Si le robot est sur la case de départ et a identifié au moins un marqueur mural, il obtient le bonus de sortie (exit bonus) de 10 %.
from controller import Robotimport struct
robot = Robot()timeStep = int(robot.getBasicTimeStep())emitter = robot.getDevice("emitter")
robot.step(timeStep)print("Ending the game")# Ends the game. Send it on the starting tile, after identifying a token, to get the exit bonus.# The game stops your program right after this message.emitter.send(struct.pack("c", b"E"))robot.step(timeStep)#include <iostream>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>
using namespace webots;
int main() { Robot *robot = new Robot(); int timeStep = (int)robot->getBasicTimeStep(); Emitter *emitter = robot->getEmitter("emitter");
robot->step(timeStep); std::cout << "Ending the game" << std::endl; // Ends the game. Send it on the starting tile, after identifying a token, to get the exit bonus. // The game stops your program right after this message. char message = 'E'; emitter->send(&message, 1); robot->step(timeStep);
delete robot; return 0;}Ensuite, apprenez à distinguer les marqueurs dans Marqueurs muraux.
