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.
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:
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'.
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.
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.
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.
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.
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.
Der momentane Name des Roboters; man sollte
ihn nur ändern, wenn man sehr
gute Gründe dafür hat.
Die momentane Farbe des Roboters; wenn sie einem nicht gefällt, kann man sie ändern. Alle Roboter in einem Team haben dieselbe Farbe.
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.
Diese Nachricht wird gesendet wenn das Spiel anfängt (wer hätte das gedacht?).
Diese Nachricht gibt jede Runde Radar-Informationen. Der Radar-Winkel wird relativ zur Vorderseite des Roboters angegeben, und zwar im Bogenmaß.
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.
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.
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.
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.
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.
Am Anfang des Spiels, und wenn ein Roboter getötet wird, wird die Anzahl der verbleibenden Roboter allen noch lebenden Robotern bekanntgegeben.
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.
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.
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.
Das aktuelle Spiel ist beendet, mache dich bereit für das nächste.
Verlasse *sofort* das Programm, oder du wirst mit Gewalt rausgeschmissen!
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.
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.
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.
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.
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.
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.
Funktioniert wie Rotate, wird aber relativ zum momentanen Winkel rotieren.
Funktioniert wie Rotate, setzt aber den Radar und/oder die Kanone in einen "Sweep Mode"(nicht möglich für den Roboter selber).
Setzt die Roboter-Beschleunigung. Der Wert ist durch Robot max/min acceleration beschränkt.
Dient zum Bremsen. Vollbremsung (portion=1.0) heisst dass die Reibung in Roboter-Richtung gleich der Gleit-Reibung ist.
Schuss mit der angegebenen Energie. Die Schuss-Optionen geben dazu mehr Informationen.
Zeigt die Nachricht im Message-Fenster an.
Zeigt die Nachricht im Message-Fenster an, wenn man sich im Debug-Modus befindet.
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.
Ä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.