Hunger Gaming - Essen oder Sterben
Wenn du nicht isst, stirbst du. Wenn Sie essen, leben Sie (bis Sie sterben). Du wirst sterben, also versuche zuletzt zu sterben.
Überblick
Es gibt eine Insel mit einer Herde von Beutetieren. Du kontrollierst ein Rudel mit fünf Raubtieren. Ihr Ziel ist es, Ihren Rucksack am Leben zu erhalten. Tun Sie dies, indem Sie Beute essen. Die Beute neigt dazu, vor Raubtieren davonzulaufen und zu versuchen, ansonsten in einer Herde zu bleiben. Natürlich befindet sich Ihr Rudel auf dem gleichen Feld wie jedes andere Rudel , daher wird die Konkurrenz versuchen, sie zu essen, bevor Sie können. Lass dich nicht entmutigen, sonst wirst du verhungern.
Spielanleitung
Erstellen und senden Sie ein Befehlszeilenprogramm, um Ihr Paket zu leiten. Es empfängt Statusinformationen vom Steuerprogramm auf STDIN und gibt Befehle auf STDOUT aus. Das Format wird unten detailliert beschrieben. Jedes Programm wird nur einmal ausgeführt und muss so lange ausgeführt werden, bis keine Mitglieder mehr am Leben sind. Sie müssen die eingegangenen Eingaben sofort lesen und schnell reagieren. Für jede Antwort gibt es ein striktes Timeout von 200 ms. Wenn Sie bis dahin nicht geantwortet haben, erhält Ihr Rudel keine neuen Anweisungen für die aktuelle Runde.
Wenn Ihr Programm nicht von der Steuerung ausgeführt werden kann, wird es als ungültig betrachtet. Bitte geben Sie die Befehlszeilenzeichenfolge an, die ich zum Ausführen Ihrer Übermittlung verwenden muss. Wenn es spezielle Anweisungen gibt (zum Einrichten von Compilern usw.), fügen Sie diese bitte bei. Wenn ich es nicht zum Laufen bringen kann, werde ich Sie in Kommentaren um Unterstützung bitten. Wenn Sie nicht antworten, kann ich Ihre Einsendung nicht akzeptieren.
Das Turnier findet auf einem 64-Bit-Linux-System statt. Beachten Sie dies, wenn Sie die erforderlichen Anweisungen geben.
Einzelheiten
Jede Kreatur die Position und Richtung sind in der Form eines Paares von doppeltgenauen Gleitkommazahlen (z
double
) repräsentiert , derenx
undy
Koordinaten, respectively.Jede Kreatur gilt als ein Punkt. Dies bedeutet, dass sie sich überlappen und denselben Raum einnehmen können. Sie werden nicht beiseite gestoßen, und es gibt kein Konzept der Kollision mit anderen Kreaturen.
Die Insel ist ein Quadrat, 500 Einheiten an einer Seite. Wenn Sie versuchen, diese Grenzen zu überschreiten, werden Sie an der Kante festgeklemmt. Der Ursprung
{0,0}
befindet sich oben links, wobei erx
nach rechts undy
nach unten zunimmt. Auch hier wird die Karte nicht umgebrochen .Das Spiel beginnt mit 1500+ (packCount * 50) Beutetieren. Sie werden in der Mitte der Insel versammelt, entscheiden sich aber schnell für den Umzug.
Die Packs werden in einem gleichmäßig verteilten Kreis um den Umfang herum angeordnet. Die Packreihenfolge wird gemischt, rechnen Sie also nicht damit, an einem bestimmten Ort zu beginnen.
Beutetiere können alle anderen Tiere innerhalb eines Radius von 30 Einheiten sehen. Sie können sich mit maximal 6,0 Einheiten pro Spielzug bewegen .
Raubtiere können alle anderen Tiere in einem Radius von 50 Einheiten sehen. Sie können sich mit maximal 6,1 Einheiten pro Runde bewegen . Dies bedeutet, dass sie Beute sehen können, bevor sie gesehen werden, und ihnen (kaum) entkommen können.
Raubtiere leben und sterben entsprechend ihrem Hungerlevel . Sie beginnt bei 1000 und verringert sich bei jeder Umdrehung um eins. Befindet sich ein Raubtier nach einer Bewegung innerhalb einer Beuteeinheit, frisst es diese automatisch. Dies entfernt die Beute und setzt den Hunger des Raubtiers auf 1000. Jeder Raubtier darf nur eine Beute pro Spielzug essen. Wenn sich mehr als eine in Reichweite befinden, frisst sie diejenige, zu der die Schleife zuerst gelangt (nicht unbedingt die nächstgelegene). Ein Raubtier stirbt, wenn sein Hunger Null erreicht.
Die Pakete beginnen mit jeweils fünf Mitgliedern . Alle 5000 Runden bringen alle noch im Spiel befindlichen Packs ein neues Mitglied hervor. Es wird im sichtbaren Bereich eines anderen Rudelmitglieds platziert. Stellen Sie sicher, dass Ihre Einträge mehr als fünf Mitglieder verarbeiten können.
Alle 1000 Runden wird mehr Beute erscheinen. Die Anzahl der neuen Beute ist die Anzahl der lebenden Raubtiere minus eins.
Raubtiere können andere Raubtiere nicht angreifen. Sie essen Beute, wenn sie sie fangen. Das ist es.
Die Reihenfolge innerhalb einer Runde ist:
- Alle Beute treffen Entscheidungen
- Alle Raubtiere treffen Entscheidungen
- Alle Beute bewegen sich
- Alle Raubtiere bewegen sich / fressen
Die Reihenfolge, in der jedes Rudel seine Entscheidungen trifft / einzieht, wird in jeder Runde zufällig festgelegt.
Protokoll (allgemein)
Die gesamte Kommunikation erfolgt im Zeichenfolgenformat US-ASCII
. Zahlen werden mit Java's Double.toString()
oder in Strings konvertiert Integer.toString()
. Ihre Ausgabe muss so formatiert sein, dass sie von Java gelesen werden kann Double.valueOf(String)
(Sie geben keine ganzen Zahlen aus). Einzelheiten zu syntaktisch analysierbaren Formaten finden Sie in der Dokumentation zuDouble
. Alle Felder in einer Zeile werden durch den Standard getrennt \t
Charakter und Zeilenumbrüche sind \n
. Die gesamte Zeichenfolge wird mit einem Null-Byte beendet \0
.
In den folgenden Beispielen <>
markiere ich die Felder aus Gründen der Lesbarkeit. Diese sind in den tatsächlichen Zeichenfolgen nicht vorhanden.
Protokoll (Eingabe)
Die Länge der Eingabezeichenfolge hängt davon ab, wie viele Kreaturen in Ihrem Rudel sichtbar sind. Es kann mehr als 100.000 Zeichen enthalten, seien Sie also darauf vorbereitet. Das Grundsetup ist:
Zeile 0: Grundlegende Informationen zum Spiel.
turn
ist die aktuelle Zugnummer und die Anzahl ist die Gesamtzahl der Beutetiere und Raubtiere, die noch auf dem Spielfeld sind. Diese sindinteger
in Stringform.<turn>\t<preyCount>\t<predatorCount>\n
Zeile 1: Die eindeutigen IDs und Hungerlevel Ihrer Rudelmitglieder. Diese werden nicht für jede Eingabe in derselben Reihenfolge angegeben. Verwenden Sie die eindeutigen IDs, um einzelne Mitglieder zu verfolgen, nicht die Reihenfolge, in der sie in der Eingabe angezeigt werden. Auch dies sind
integer
als Zeichenfolgen. Für eine Zweierpackung wäre dies:<id[0]>\t<hunger[0]>\t<id[1]>\t<hunger[1]>\n
Zeile 2: Die Positionen Ihrer Packmitglieder in derselben Reihenfolge wie in Zeile 1 angegeben . Dies sind
double
als Zeichenfolge:<x[0]>\t<y[0]>\t<x[1]>\t<y[1]>\n
Die folgenden Zeilen geben die Sichtbarkeit jedes Packmitglieds in der Reihenfolge an , in der sie in Zeile 1 angegeben sind . Diese werden als zwei Zeilen pro Mitglied angegeben.
Die erste für jede besteht aus Orten für die Beute, die er sehen kann. Das zweite sind Orte für die Raubtiere, die er sehen kann. Diese Standorte sind insgesamt nicht eindeutig. Wenn beispielsweise zwei Rudelmitglieder dasselbe Tier sehen können, befindet es sich in der Zeichenfolge beider Mitglieder. Auch Ihre eigenen Rudelmitglieder werden enthalten sein. Wenn Sie sie ausschließen möchten, möchten Sie möglicherweise Standorte mit Ihren eigenen Mitgliedern vergleichen. Alle Speicherorte sind im double
Zeichenfolgenformat.
Für jedes lebende Mitglied:
<prey[0].x>\t<prey[0].y>\t<prey[1].x>\t<prey[1].y>\n
<predator[0].x>\t<predator[0].y>\t<predator[1].x>\t<predator[1].y>\n
Schließlich steht das letzte Zeichen \0
am Anfang der nächsten Zeile.
Ausnahme: Wenn Sie die Eingabe erhalten dead\0
, ist Ihr Rucksack tot. Beenden Sie Ihr Programm bitte mit Vorbehalt. Der Controller sollte alle lebenden Prozesse herunterfahren, wenn er geschlossen ist, aber ich möchte lieber keine Zombie-Prozesse überall haben. Aus Höflichkeitsgründen können Sie eine Zeitüberschreitung für die Eingabe angeben. Zum Beispiel endet meine Beispielklasse, wenn sie 15 Sekunden lang keine Eingabe erhält.
Protokoll (Ausgabe)
Die Ausgabe ist einfach. Sie geben double
für jedes Live-Pack-Mitglied ein Wertepaar an . Diese stellen die Bewegung dar, die Sie in dieser Runde einnehmen möchten. Wenn sich Ihre Kreatur beispielsweise gerade in befindet {100.0, 100.0}
und Sie ihnen den Befehl geben {-1.0, 1.0}
, werden sie sich zu bewegen {99.0, 101.0}
. Alle Zahlen werden in einer einzelnen Zeile durch Tabulatoren getrennt.
Wenn Sie beispielsweise 3 Packmitglieder am Leben hätten, wäre dies eine gültige Antwort:
1.0\t-1.0\t2.0\t-2.0\t3.0\t-3.0\0
Dies würde Ihre Kreaturen bewegen {1.0,-1.0}
, {2.0,-2.0}
und {3.0,-3.0}
. Die Bestellung ist die gleiche wie in der Eingabe erhalten. Vergiss das Ende nicht \0
!
Wenn Sie eine ungültige Eingabe machen, folgen schlechte Ergebnisse. Wenn eine einzelne Zahl nicht zu a analysiert werden kann double
, wird sie zu Null. Wenn die Zeichenfolge als Ganzes nicht analysiert werden kann, werden keine neuen Anweisungen gegeben, und Ihr gesamtes Paket verwendet die Anweisungen aus der vorherigen Runde.
Alle Richtungen werden auf einen maximalen Abstand von 6,1 Einheiten geklemmt. Sie können sich langsamer bewegen, wenn Sie möchten. Zum Beispiel {1, 0}
wird Sie eine Einheit bewegen. {6,8}
(Distanz 10) bewegt nur 6.1 Einheiten und reduziert sich auf ungefähr {3.66, 4.88}
. Die Richtung bleibt konstant.
Wichtig: Das Steuerprogramm liest sowohl Ihren STDOUT als auch Ihren STDERR. Wenn Sie eine Ausnahme auslösen und an STDERR drucken, ist es sehr unwahrscheinlich, dass die Nachricht in Form einer gültigen Antwort vorliegt. Versuchen Sie dies zu vermeiden.
Steuerungsprogramm / Testen
Die Quelle für den Controller finden Sie hier auf bitbucket.org . Sie müssen es kompilieren, bevor Sie es ausführen können. Die Hauptklasse ist Game
und alle Klassen sind im Standardpaket enthalten. Fügen Sie zum Ausführen den Befehl jedes Pakets als separates Argument ein. Wenn Sie beispielsweise Java ChaserPack und Python LazyPack.py ausführen möchten, können Sie Folgendes verwenden:
java Game "java ChaserPack" "python LazyPack.py"
Auf der Karte werden Beute in Grün und Raubtiere in Rot angezeigt. Unabhängig davon, welches Paket das erste ist , das als Argument angegeben wird, wird es stattdessen blau angezeigt. Dies soll zu Testzwecken die Unterscheidung erleichtern. Raubtiere blinken auch fünf Frames lang weiß, wenn sie fressen.
Das Spiel wird fortgesetzt, bis der letzte Raubtier verhungert und auf die Konsole geschrieben wird, wenn Hunger oder Aussterben eintreten. Sobald das Spiel beendet ist, wird die Punktzahl für jedes Paket vergeben. Wenn Sie die Verhungern / Aussterben-Ereignisse nicht sehen möchten, können Sie das -silent
Argument verwenden. Dann wird nur das Endergebnis ausgegeben. Sie müssen dies als erstes Argument übergeben :
java Game -silent "java ChaserCat" "./someOtherPack"
Im Lieferumfang ist ein Java-Paket mit dem Namen "Skeleton" enthalten GenericPack
. Es enthält die grundlegenden Ein- / Ausgabeoperationen, die benötigt werden. Es soll ein klares Beispiel geben, wie man parst und antwortet. Wenn Sie eine Vorlage in einer anderen Sprache hinzufügen möchten, lassen Sie es mich wissen.
Ebenfalls enthalten ist ein Raubtier, das auf der Vorlage basiert ChaserPack
. Es wird nicht in das Turnier aufgenommen und ist nur zu Testzwecken enthalten. Die Leistung ist aufgrund eines absichtlichen Zielfehlers ziemlich schlecht. Wenn Sie es nicht schlagen können, versuchen Sie es weiter.
Unten sehen Sie ein Beispiel für den Ablauf des Steuerungsprogramms (für Video klicken). Die Videoqualität ist nicht besonders gut (sorry), aber Sie können ein Gefühl dafür bekommen, wie sich die Beute bewegt. ( Vorsicht: Audio )
Wertung
Der Gewinner wird nach Turnier ermittelt und erhält in jeder Runde Punkte.
Jede Runde geht weiter, bis alle Raubtiere tot sind. Jedes Rudel wird danach gewertet, wann sein letztes Mitglied an Hunger gestorben ist. Sie erhalten dann auf der Grundlage der Bestellung Punkte. Punkte werden für zehn Runden gesammelt, und der Sieger ist das Rudel mit den höchsten Gesamtpunkten.
Der erste Platz für jede Runde erhält 100 Punkte. Für jeden weiteren Platz wird die Belohnung um 20% reduziert (abgerundet). Dies wird fortgesetzt, bis die Punkte Null erreichen (nach dem 17. Platz). Die Plätze 18+ erhalten keine Punkte für die Runde. Packs, die gleichberechtigt sind, erhalten gleiche Punkte. Zum Beispiel:
1st : 100
2nd : 80
3rd : 64 (T)
3rd : 64 (T)
4th : 51
...
17th: 1
18th: 0
19th: 0
Die maximal mögliche Punktzahl im Verlauf des Turniers beträgt 1000 Punkte, vom ersten Platz alle zehn Male.
Wenn mehrere Programme das Turnier mit dem ersten Platz beenden, wird ein weiteres Turnier mit zehn Runden abgehalten, wobei nur die Einträge mit dem ersten Platz eingereicht werden. Dies wird so lange fortgesetzt, bis ein Sieger hervorgeht.
Ich werde versuchen, ungefähr wöchentlich ein Turnier zu veranstalten, oder wenn neue Einreichungen eingehen.
Zusatzregeln (fair spielen!)
Sie dürfen keine externen Ressourcen lesen oder darauf schreiben. Da Sie Ihr Programm nicht mehrmals aufrufen, können alle Statusinformationen intern gespeichert werden.
Stören Sie nicht andere Prozesse / Einreichungen. Dies bedeutet nicht, dass Sie nicht versuchen, ihre Beute zu stehlen, ihnen zu entkommen usw. Dies bedeutet , dass Sie den Ablauf des Prozesses nicht stören. Dies liegt in meinem Ermessen.
Die Teilnehmer sind auf maximal drei Einsendungen beschränkt. Wenn Sie mehr einreichen, erziele ich nur die ersten drei eingereichten Punkte. Wenn Sie einen widerrufen möchten, löschen Sie ihn.
Einträge dürfen nicht nur existieren, um andere Einträge zu unterstützen. Jeder sollte spielen, um für sich zu gewinnen.
Ihr Programm kann maximal einen untergeordneten Prozess gleichzeitig erzeugen ( insgesamt Nachkommen, nicht direkt). Stellen Sie in jedem Fall sicher, dass Sie die Zeitüberschreitung nicht überschreiten. Sie dürfen die
Game
Klasse selbst in keiner Weise aufrufen .
Ergebnisse - 29. April 2014
Hier sind die Ergebnisse des letzten Turniers mit zehn Runden:
Clairvoyant : 1000
EcoCamels : 752
Netcats : 688
RubySpiders : 436
RubyVultures : 431
CivilizedBeasts : 382
LazyPack : 257
Packs, die vor 09:00 EDT 2014/04/29 eingereicht wurden, sind in diesem Lauf enthalten.
Sie können auch die Details für jede Runde anzeigen . Aus irgendeinem Grund habe ich mich entschlossen, die Runden rückwärts zu nummerieren, also beginnt es mit "Runde 10".
Aktualisierung
23.04.2014: FGreg hat einen Fehler im Zusammenhang mit Timeouts gemeldet (danke!). Ein Fix wurde implementiert, sodass Tester ihren Steuerprogrammcode aktualisieren möchten.