Zum Inhalt springen
Deutsch

Kommunikation

Dein Programm kommuniziert mit dem Spiel über zwei Geräte, die jeder Roboter hat:

  • Der Sender (Emitter) schickt Nachrichten an das Spiel. Er muss nicht aktiviert werden.
  • Der Empfänger (Receiver) erhält Nachrichten vom Spiel. Aktiviere ihn wie einen Sensor.

Jeder Abschnitt unten ist ein vollständiges Programm für den Starter-Roboter. Alle Nachrichten sind in der Nachrichten-Referenz aufgelistet.

Um für ein Buchstabenopfer (Letter victim) oder ein kognitives Ziel (Cognitive target) Punkte zu bekommen, muss der Roboter:

  1. Länger als 1 Sekunde in der Nähe der Markierung stehen bleiben. Erebus ignoriert die Meldung, wenn sich der Roboter in der letzten Sekunde bewegt hat.
  2. Position und Typ der Markierung senden: X und Z in Zentimetern und den Typ als einen Buchstaben.
Wandmarkierung Typ
Buchstabenopfer Φ (verletzt) H
Buchstabenopfer Ψ (stabil) S
Buchstabenopfer Ω (unverletzt) U
Kognitives Ziel, Summe 0 (entzündbares Gas) F
Kognitives Ziel, Summe 1 (Gift) P
Kognitives Ziel, Summe 2 (ätzend) C
Kognitives Ziel, Summe 3 (organisches Peroxid) O

Die Typen sind Buchstaben, obwohl die Opfer seit 2026 Symbole zeigen. Das GPS liefert Meter, also multipliziere mit 100.

from controller import Robot
import 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 is
print("Reported")

Der Roboter muss auf derselben Seite der Wand sein wie die Markierung, und sowohl der Roboter als auch die gesendete Position müssen nah an ihr liegen. Die Regeln verlangen höchstens eine halbe Kachel, also ziele darauf. Erebus v26.1 prüft eine Entfernung von 9 cm.

Führe dieses Programm am Start von world1.wbt aus: Dort gibt es keine Markierung, also zeigt der Verlauf des Steuerfensters Misidentification of Victim -5. Eine falsche Meldung, auch die Meldung einer Fälschung, kostet 5 Punkte, und jede Markierung bringt nur einmal Punkte.

Der Verlauf des Steuerfensters nach einer falschen Meldung und der Abgabe einer Karte

Wenn der Roboter feststeckt, setzt ihn ein fehlender Fortschritt (Lack of Progress, LoP) zum letzten Checkpoint zurück und kostet 5 Punkte. Das passiert automatisch nach 20 Sekunden ohne Bewegung, und dein Programm kann ihn auch selbst auslösen, indem es L sendet. Jedes Mal sendet das Spiel L an den Roboter, damit dein Programm weiß, dass sich seine Position geändert hat.

from controller import Robot
import struct
robot = Robot()
timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")
receiver = robot.getDevice("receiver")
receiver.enable(timeStep) # The receiver must be enabled
askedAt = None
while 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()

Der Empfänger kann verschiedene Nachrichten erhalten. Prüfe also die Länge jeder Nachricht, bevor du sie liest, wie im Beispiel.

Sende G, um die Punktzahl und die verbleibende Zeit zu erhalten. Das Spiel antwortet mit einer 16 Byte langen Nachricht: dem Buchstaben G, der Punktzahl, der verbleibenden Spielzeit und der verbleibenden Echtzeit, in Sekunden.

from controller import Robot
import struct
robot = Robot()
timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")
receiver = robot.getDevice("receiver")
receiver.enable(timeStep)
lastAsked = 0
while 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()

Die Spielzeit läuft in Sümpfen schneller ab, und das Spiel endet, wenn eine der beiden Zeiten abgelaufen ist. Nutze beide, um zu wissen, wann du zum Start zurückkehren solltest.

Sende E, um das Spiel zu beenden. Steht der Roboter auf der Startkachel und hat mindestens eine Wandmarkierung erkannt, bekommt er den Ausgangsbonus (Exit bonus) von 10 %.

from controller import Robot
import 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)

Als Nächstes lernst du unter Wandmarkierungen, die Markierungen zu unterscheiden.