Comunicação
O seu programa conversa com a partida por meio de dois dispositivos que todo robô tem:
- O emissor (emitter) envia mensagens para a partida. Ele não precisa ser ativado.
- O receptor (receiver) recebe mensagens da partida. Ative-o como um sensor.
Cada seção abaixo é um programa completo para o robô inicial. Todas as mensagens estão listadas na Referência de mensagens.
Pontuando com marcadores nas paredes
Seção intitulada “Pontuando com marcadores nas paredes”Para pontuar com uma vítima de letra (letter victim) ou um alvo cognitivo (cognitive target), o robô precisa:
- Ficar parado por mais de 1 segundo perto do marcador. O Erebus ignora o informe se o robô se moveu no último segundo.
- Enviar a posição e o tipo do marcador: X e Z em centímetros, e o tipo como uma letra.
| Marcador de parede | Tipo |
|---|---|
| Vítima de letra Φ (ferida) | H |
| Vítima de letra Ψ (estável) | S |
| Vítima de letra Ω (ilesa) | U |
| Alvo cognitivo, soma 0 (gás inflamável) | F |
| Alvo cognitivo, soma 1 (veneno) | P |
| Alvo cognitivo, soma 2 (corrosivo) | C |
| Alvo cognitivo, soma 3 (peróxido orgânico) | O |
Os tipos são letras, mesmo que as vítimas mostrem símbolos desde 2026. O GPS fornece metros, então multiplique por 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;}O robô precisa estar do mesmo lado da parede que o marcador, e tanto o robô quanto a posição que você envia precisam estar perto dele. As regras exigem no máximo meio ladrilho, então mire nisso. O Erebus v26.1 verifica uma distância de 9 cm.
Execute este programa no início de world1.wbt: não há nenhum marcador ali, então o histórico da janela de controle mostra Misidentification of Victim -5. Um informe errado, incluindo o informe de um falso, custa 5 pontos, e cada marcador só pode ser pontuado uma vez.

Falta de progresso
Seção intitulada “Falta de progresso”Quando o robô fica preso, uma falta de progresso (Lack of Progress, LoP) o leva de volta ao último ponto de controle (checkpoint) e custa 5 pontos. Ela acontece automaticamente após 20 segundos sem se mover, e o seu programa também pode declará-la enviando L. A cada vez, a partida envia L ao robô, para que o seu programa saiba que a posição dele mudou.
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;}O receptor pode receber mensagens diferentes, então confira o tamanho de cada uma antes de lê-la, como no exemplo.
Informações da partida
Seção intitulada “Informações da partida”Envie G para obter a pontuação e o tempo restante. A partida responde com uma mensagem de 16 bytes: a letra G, a pontuação, o tempo de partida restante e o tempo real restante, em segundos.
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;}O tempo de partida corre mais rápido nos pântanos, e a partida termina quando qualquer um dos dois tempos acaba. Use os dois para saber quando voltar para o início.
Terminando a partida
Seção intitulada “Terminando a partida”Envie E para terminar a partida. Se o robô estiver no ladrilho inicial e tiver identificado pelo menos um marcador, ele ganha o bônus de saída (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;}Em seguida, aprenda a diferenciar os marcadores em Marcadores nas paredes.
