## 4. Roboter-Programmierung

Dieses Kapitel beschreibt, wie man eigene Roboter programmiert. Das wichtigste was man wissen muss ist die Messaging-Sprache, die aus ca. 35 Befehlen besteht die zur Kommunikation mit dem Server-Programm benutzt werden. Zudem kann es sehr hilfreich sein, die Beispiel-Roboter im `Robots/`-Verzeichnis zu studieren.

## 4.1 Nachrichten lesen

Am Anfang jeder Sequenz werden die Roboter-Prozesse gestartet und jeder bekommt zwei Pipes zugewiesen, eine für Input die andere für Output. Diese Pipes sind mit `stdin` und `stdout` verbunden, so dass es für die Roboter so aussieht, als würden sie mit dem Server über Standard Input und Standard Output kommunizieren. Dieses Verfahren ermöglicht es, Roboter in nahezu jeder Programmiersprache zu schreiben. Es gibt nur ein Problem: der Roboter muss wissen, wann er eine Nachricht erhalten hat. Um das zu erreichen gibt es (mindestens) drei verschiedene Methoden:

STDIN blockiert:

  Dies ist die einfachste Methode. Wenn man von stdin liest, wird das Program blockiert bis die nächste Nachricht ankommt. Daher kann man das Programm so schreiben als wäre immer eine Nachricht vorhanden. Der Nachteil ist, dass man keine Berechnungen durchführen kann während man auf neue Nachrichten wartet. Um die Blockieren-Methode auszuwählen, sende folgende Roboter-Option solbald das Programm gestartet wurde:

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

  Beachte, dass das C++ Code ist. Wenn du nicht C++ verwendest gib einfach die obenstehenden Informationen auf stdout aus. endl bedeutet 'end of line'.
Select:

  Wenn man die Unix Libc Funktion `select` verwendet, hat der Roboter mehr Kontrolle darüber, wann er nach neuen Nachrichten schauen soll. Dies ermöglicht dir, z.B. alle vorhandenen Nachrichten zu lesen, einige Berechnungen durchzuführen, Kommandos zu senden und dann auf weitere Nachrichten zu warten. Um mehr über `select` zu lernen, lies bitte die Unix-Dokumentation (man- oder info-pages).

  Um die Select-Methode auszuwählen sende folgede Roboter-Option solbald das Programm gestartet wurde:

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

  Beachte auch hier, dass das C++ Code ist.
Signale:

  Wenn du willst kannst du RealTimeBattle sagen, der Roboter soll jedesmal ein Signal gesendet bekommen, wenn neue Nachrichten gesendet werden. Diese Methode ermöglicht es dem Roboter ständig auf dem laufenden zu sein, auch wenn er gerade mit Berechnungen beschäftigt ist. Verwende die Unix-Dokumentation um mehr über Signale zu erfahren, oder alternativ: schau dir den Quelltext anderer Roboter an um mehr darüber zu lernen.

  Um die Signal-Methode auszuwählen sende folgede Roboter-Optionen solbald das Programm gestartet wurde:

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

  Beachte auch hier, dass das C++ Code ist.

  Natürlich kannst du irgendein anderes Signal als `SIGUSR1` wählen.

Als kleine Hilfe diese drei Methoden zu implementieren, wurde der Roboter `rotate_and_fire` in drei verschiedenen, aber funktionell äquivalenten, Versionen geschrieben. Du kannst diese gerne studieren und in deinen eigenen Robotern verwenden.

Ein ''busy wait'', also ein wiederholtes Nachschauen, ob eine Nachricht da ist, ist keine gute Idee. Das würde zu einer drastischen Verlangsamung des Spielablaufs führen, schlimmer noch: im Competition-Modus würde der Roboter ziemlich schnell wegen mangelnder CPU-Zeit draufgehen.

## 4.2 Messagetypes.h

Die Datei `Messagetypes.h` ist eine gute Quelle für Informationen über die Messaging-Sprache. Es ist eine C/C++ Include-Datei, kann aber leicht für die Benutzung mit anderen Programmiersprachen umgeschrieben werden. Dort findet man eine Auflistung von Nachrichten, Warning-Typen, Objekten, Spiel-Optionen und Roboter-Optionen.

## 4.3 Schummeln

Da der Kampf der Roboter in Echtzeit und mit richtigen Prozessen stattfindet, gibt es möglicherweise Methoden Roboter zu schreiben, die auf die eine oder andere Art schummeln, z.B. indem sie andere Roboter oder sogar RealTimeBattle selber untersuchen, um mehr Informationen zu erhalten, sehr viele Ressourcen aufbrauchen damit andere Roboter weniger haben, etc. Das ist natürlich nicht die feine, englische Art, einen Gegner zu schlagen, daher versuchen wir das so gut wie möglich zu verhindern.

Im Competition-Modus ist die CPU-Zeit der Roboter beschränkt, denn auf diese Art kann ein Roboter nicht die ganze CPU-Zeit aufbrauchen. Dies könnte man durch das Öffnen weiterer Kind-Prozesse umgehen, aber seitdem die vom Kind-Prozess genutzte Zeit beim Beenden des Prozesses gezählt wird, sollte es sehr einfach sein zu Erkennen ob ein Roboter irgendetwas verdächtiges tut.

Es ist nicht möglich alle Möglichkeiten des Schummelns in RTB zu verhindern. So ist es z.B erlaubt, Dateien zu lesen und zu schreiben, man sollte sich aber dessen bewusst sein, dass die Organisatoren von Wettkämpfen dies verbieten können, wenn sie wollen, indem die einfach Besitzer und Rechte der Roboter-Programme richtig setzen. Es ist vielleicht immer noch möglich, Wege zu finden, um diese Einschränkungen zu umgehen; Wenn du eine solche Möglichkeit findest, sende bitte einen Bug-Report an uns. Im übrigen ist es die Aufgabe der Turnier-Organisatoren sicherzustellen, dass die Regeln befolgt werden.

## 4.4 Nachrichten an Roboter

Initialize [ErsteSequenz? (int)]

  Dies ist die allererste Nachricht die der Roboter bekommen wird. Wenn das Argument eins ist, ist es die erste Sequenz im Turnier und der Roboter sollte seinen Namen und seine Farbe and den Server senden, ansonsten sollte er auf YourName- und YourColor-Nachrichten warten.

YourName [Name (string)]

  Der momentane Name des Roboters; man sollte ihn nur ändern, wenn man `sehr` gute Gründe dafür hat.

YourColour [Farbe (hex)]

  Die momentane Farbe des Roboters; wenn sie einem nicht gefällt, kann man sie ändern. Alle Roboter in einem Team haben dieselbe Farbe.

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

  Am Anfang jedes Spieles werden dem Roboter einige Einstellungen mitgeteilt, die dem Roboter nützlich sein können. Für eine komplette Liste sollte man sich das `game_option_type` enum in der Datei Messagetypes.h anschauen. Im Optionen-Kapitel gibt's mehr Informationen zu den einzelnen Optionen. Der Debug-Level wird auch als Spiel-Option gesendet obwohl es nicht in der Options-Liste ist.

GameStarts

  Diese Nachricht wird gesendet wenn das Spiel anfängt (wer hätte das gedacht?).

Radar [Entfernung (double)] [Typ des beobachteten Objekts (int)] [Radar-Winkel (double)]

  Diese Nachricht gibt jede Runde Radar-Informationen. Der Radar-Winkel wird relativ zur Vorderseite des Roboters angegeben, und zwar im Bogenmaß.

Info [Zeit (double)] [Geschwindigkeit (double)] [Kanonen-Winkel (double)]

  Die Info-Nachricht wird immer nach der Radar-Nachricht gesendet. Sie gibt mehr allgemeine Informationen über den Status des Roboters. Die Zeit ist jene Zeit, die seit dem Start des Spieles vergangen ist. Dies ist nicht unbedingt die Zeit, die in Wirklichkeit vergangen ist, und zwar wegen time scale und max timestep.

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

  Diese Nachricht teilt Dir die aktuelle Prosition mit. Sie ist nur gesendet wenn die Option Send robot coordinates auf 1 oder 2 gesetzt ist. Der Wert 1 bedeutet das die Koordinaten relativ zur Startposition gesendet werden, so dass der Roboter nicht weiß wo er gestartet ist sondern nur wohin er sich seitdem bewegt hat.

RobotInfo [Energie-Level (double)] [Team-Mitglied? (int)]

  Wenn dein Roboter einen anderen Roboter mittels des Radars entdeckt, wird diese Nachricht an deinen Roboter gesendet. Sie gibt verschiedene Informationen über den feindlichen Roboter. Die Energie des anderen Roboters wird auf die gleiche Art und Weise angegeben, wie die Energie deines eigenen Roboters(siehe unten). Der zweite Parameter ist nur im Team-Mode interessant, 1 heisst Team-Mitglied, 0 steht für einen Gegner.

RotationReached [Was hat seine Rotation beendet?(int)]

  Wenn die Roboter-Option SEND_ROTATION_REACHED richtig gesetzt ist, wird diese Nachricht gesendet, wenn eine Rotation (mit RotateTo oder RotateAmount) beendet wurde, oder die Richtung sich geändert hat (beim 'sweeping'). Der Parameter entspricht dem 'was soll ich rotieren', z.B. bei Rotate.

Energy [Energie-Level(double)]

  Am Ende jeder Runde wird der Roboter seinen eigenen Energie-Level erfahren. Er wird jedoch nicht die exakte Energie gesagt bekommen, sondern nur einen der Energie-Level.

RobotsLeft [Anzahl der Roboter (int)]

  Am Anfang des Spiels, und wenn ein Roboter getötet wird, wird die Anzahl der verbleibenden Roboter allen noch lebenden Robotern bekanntgegeben.

Collision [Objekt-Typ mit dem der Roboter zusammengestossen ist (int)] [angle relative robot (double)]

  Wenn ein Roboter von etwas getroffen wird, oder selber etwas rammt, bekommt er diese Nachricht. In der Datei Messagetypes.h findest du eine Liste aller Objekt-Typen.

Warning [Warnungs-Typ (int)] [Nachricht (string)]

  Eine Warnungs-Nachricht wird dann gesendet wenn ein Problem aufgetaucht ist. Momentan können 7 verschiedene Warnungs-Nachrichten gesendet werden, nämlich:

  `UNKNOWN_MESSAGE:` Der Server hat eine Nachricht erhalten, mit der er nichts anfangen kann.

  `PROCESS_TIME_LOW:` Die CPU-Last hat den CPU Warnungs-Prozentsatz erreicht. Taucht nur im Competition-Modus auf.

  `MESSAGE_SENT_IN_ILLEGAL_STATE:` Die erhaltene Nachricht konnte in diesem Spielstadium nicht verarbeitet werden. Z.B. wenn Rotate vor dem Anfang des Spiels gesendet wurde.

  `UNKNOWN_OPTION:` Der Roboter hat eine robot option gesendet, die entweder einen unzulässigen Optionsnamen oder Options-Parameter enthielt.

  `OBSOLETE_KEYWORD:` Das Schlüsselwort ist veraltet, und sollte nicht mehr verwendet werden. Lies die Datei `ChangeLog` um herauszufinden was stattdessen benutzt werden sollte.

  `NAME_NOT_GIVEN:` Der Roboter hat seinen Namen nicht vor Spielbeginn gesendet. Das passiert wenn die robot startup time zu kurz ist oder der Roboter seinen Namen nicht früh genug sendet.

  `COLOUR_NOT_GIVEN:` Der Roboter hat seine Farbe nicht vor Spielbeginn gesendet.

Dead

  Der Roboter ist gestorben. Versuche nicht, weitere Nachrichten an den Server zu senden bis das Spiel zu ende ist. Der Server wird sie nicht lesen.

GameFinishes

  Das aktuelle Spiel ist beendet, mache dich bereit für das nächste.

ExitRobot

  Verlasse *sofort* das Programm, oder du wirst mit Gewalt rausgeschmissen!

## 4.5 Nachrichten von Robotern

Nachrichten von einem Roboter an RealTimeBattle dürfen nicht länger als 128 Zeichen sein. Anderenfalls wird RealTimeBattle die Nachricht in zwei Teile schneiden und möglicherweise eine "Unbekannte Nachricht" melden.

When you send messages to RealTimeBattle make shure that they are not longer than 128 chars, otherwise RealTimeBattle will cut them in two parts and may report an unknown message.

RobotOption [Optionsnummer (int)] [Wert (int)]

  Momentan sind nur zwei Optionen verfügbar:

  `SIGNAL:` Teilt dem Server mit, er soll ein Signal senden, wenn Nachrichten eintreffen. Der Parameter wird angeben, welches Signal. Sende diese Nachricht (z.B. mit Parameter SIGUSR1), sobald du bereit bist Signale zu empfangen. Der Standardwert ist 0, d.h. der Server soll keine Signale senden.

  `SEND_SIGNAL:` Sagt dem Server er soll SIGUSR1 senden, wenn eine Nachricht eintrifft. Sende diese Nachricht (mit Parameter 1 (=true)) sobald du bereit bist ein Signal zu empfangen. Der Standardwert ist false.

  `SEND_ROTATION_REACHED:` Wenn du willst das der Server eine RotationReached Nachricht sendet, wenn eine Rotation beendet wurde, solltest du diese Option setzen. Mit 1 als Wert wird die Nachricht gesendet, wenn ein RotateTo oder ein RotateAmount fertig ist, mit 2 als Wert werden auch Veränderungen in der Sweep-Richtung gemeldet. Standardwert ist 0, d.h. es werden keine Nachrichten gesendet.

  `USE_NON_BLOCKING:` Bestimmt wie Nachrichten gelesen werden. Diese Option sollte genau einmal gesendet werden, sobald das Programm gestartet wird. Da die Option immer angegeben werden sollte, gibt es keinen Default-Wert.

Name [Name (string)]

  Wenn man die Initialize-Nachricht mit 1 als Argument erhält, die anzeigt dass dies die erste Sequenz ist, sollte der Roboter seinen Namen und seine Farbe senden. Im Namen kann die Teamzugehörigkeit mitgeteilt werden. Lautet der Name `foo Team: bar`, so heißt der Roboter `foo` und spielt im Team `bar`. Teammitglieder bekommen dieselbe Farbe und erkennen sich als Freund bei der RobotInfo Nachricht. Ausgefeilteren Team-Support bietet das RealTimeBattle Team FrameWork.

Colour [home colour (hex)] [away colour (hex)]

  Siehe oben. Die Farben sind wie normale Fußballtrikots. Die "home colour" wird verwendet falls sie nicht schon vergeben ist. Anderenfalls wird die "away colour" oder als letzten Ausweg eine zufällig gewählte, freie Farbe benutzt.

Rotate [Was soll rotieren (int)] [angular velocity (double)]

  Setzt die "angular velocity" für den Roboter, die Kanone und den Radar. Setze 'Was soll rotieren' auf 1 für den Roboter, 2 für die Kanone, 4 für den Radar, oder zu einer Summe dieser Werte, um mehrere Objekte gleichzeitig zu rotieren. Die "angular velocity" wird in "Radians" pro Sekunde angegeben und wird von Robot (cannon/radar) max rotate speed begrenzt.

RotateTo [Was soll rotieren (int)] [angular velocity (double)] [End-Winkel (double)]

  Genau wie Rotate, allerdings wird nur um einen bestimmten Winkel rotiert. Beachte dass Radar- und Kanonen-Winkel relativ zum Roboter-Winkel angegeben werden. Dieses Kommando kann nicht dazu benutzt werden den Roboter selber rotieren zu lassen, benutze RotateAmount dafür.

RotateAmount [Was soll rotieren (int)] [angular velocity (double)] [Winkel (double)]

  Funktioniert wie Rotate, wird aber relativ zum momentanen Winkel rotieren.

Sweep [what to rotate (int)] [angular velocity (double)] [right angle (double)] [left angle (double)]

  Funktioniert wie Rotate, setzt aber den Radar und/oder die Kanone in einen "Sweep Mode"(nicht möglich für den Roboter selber).

Accelerate [Wert (double)]

  Setzt die Roboter-Beschleunigung. Der Wert ist durch Robot max/min acceleration beschränkt.

Brake [portion (double)]

  Dient zum Bremsen. Vollbremsung (portion=1.0) heisst dass die Reibung in Roboter-Richtung gleich der Gleit-Reibung ist.

Shoot [Schuss-Energie (double)]

  Schuss mit der angegebenen Energie. Die Schuss-Optionen geben dazu mehr Informationen.

Print [Nachricht (string)]

  Zeigt die Nachricht im Message-Fenster an.

Debug [message (string)]

  Zeigt die Nachricht im Message-Fenster an, wenn man sich im Debug-Modus befindet.

DebugLine [Winkel1 (double)] [Radius1 (double)] [Winkel2 (double)] [Radius2 (double)]

  Zeichnet eine Linie direkt in die Arena. Dies ist nur im höchsten Debug-Level(5) erlaubt; Ist dies nicht der Fall wird eine Warnungs-Nachricht gesendet. Die Parameter sind die Start- und End-Punkte der Linie, angegeben in Polarkoordinaten relativ zum Roboter.

DebugCircle [Mittelpunkts-Winkel (double)] [Mittelpunkts-Radius (double)] [Kreisradius (double)]

  Ähnlich wie DebugLine, zeichnet aber einen Kreis. Die ersten zwei Parameter sind Winkel und Radius des Kreismittelpunktes relativ zum Roboter. Der dritte Parameter gibt den Radius des Kreises an.