Endgültige Ergebnisse verfügbar
Einführung
Nach meinem vorherigen KOTH mit heftigen Themen ( Fantasiekrieg , weltweite Pandemie ...) bin ich mit einem neuen unbeschwerten Spiel zurück. Dieses Mal stehen Sie vor einer Situation, die einem Brettspiel ähnelt. Ein Stapel umgedrehter Münzen wird in die Mitte eines wirklich großen Tisches gelegt, und Sie sind entschlossen, Ihren Anteil an der Beute zu bekommen!
Glossar
Münzen : Marken, die entweder umgedreht oder nicht umgedreht werden können.
Nicht gekippt : Münzen werden mit dem Wert nach unten auf den Tisch gelegt. Dies ist der Standardstatus der Münzen.
Umgedreht : Münzen werden mit ihrem Wert nach oben auf den Tisch gelegt.
Lokal : Bezieht sich auf Ihren Stapel Münzen.
Global : Bezieht sich auf den Stapel Münzen in der Mitte.
Prinzip
Zu Beginn des Spiels beginnt jeder Spieler mit 0 Punkten und 0 Münzen (umgedreht oder nicht umgedreht). Das Spiel ist rundenbasiert. Während ihres Zuges können die Spieler bis zu drei Aktionen ausführen, die entweder mit dem Münzstapel in der Tischmitte, ihrem eigenen Münzstapel oder mit anderen Spielern interagieren.
Die Spielreihenfolge wird zu Beginn des Spiels zufällig festgelegt. Die Reihenfolge der Spieler in der Argumentliste stellt die Zugreihenfolge dar und geht in dieser Liste von links nach rechts. "Weiter" und "Zurück" beziehen sich jeweils auf "rechts in dieser Liste" und "links in dieser Liste" mit einer Schleife, wenn Sie der letzte von beiden Seiten sind.
Das Spiel dauert 50 Runden oder bis sich am Ende eines Spielzuges in der Mitte 0 Münzen befinden (was bedeutet, dass Sie Ihre 3 Aktionen beenden, auch wenn der Stapel nach Ihrer ersten Aktion leer ist, und Sie können die zu lassenden Münzen zurücklegen das Spiel geht weiter). Die Startzahl der globalen Münzen wird zufällig mit dieser Formel definiert:
(2 ^ nb_players) + (nb_players * 10) - random(1 + (nb_players ^ 2))`
Jede Aktion bringt Ihnen Punkte (oder bringt Sie dazu, einige zu verlieren) und am Ende des Spiels wird jede Münze, die Sie haben, Ihren Punkten hinzugefügt ( -1 für nicht umgedreht, +2 für umgedreht ). Der Spieler mit der höchsten Punktzahl gewinnt.
Die Steuerung stellt Ihnen die Eingabe über Befehlsargumente zur Verfügung und Ihr Programm muss über stdout ausgeben.
Syntax
Eingang
Jedes Mal, wenn Ihr Programm aufgerufen wird, erhält es Argumente in folgendem Format:
Round;YourPlayerId;Coins;PlayerId_Points_Flipped_Unflipped;PlayerId_Points_Flipped_Unflipped;...
Runden sind 1-indiziert.
Beispiel Eingabe
6;2;52;1_20_3_12;0_-2_0_1;2_12_1_0
Hier sehen Sie, dass es die 6. Runde ist und Sie Spieler 2. Es befinden sich 52 Münzen auf dem Mittelstapel. Sie haben 12 Punkte, 1 eingeworfene Münze und 0 nicht eingeworfene Münze. Punkte können negativ sein.
Ausgabe
Sie müssen drei Zeichen (kein Leerzeichen, kein Trennzeichen) ausgeben, die jeweils einer Aktion entsprechen, die Sie in diesem Zug ausführen. Die Reihenfolge der Zeichen bestimmt die Reihenfolge der Aktionen. Sie können die gleichen Aktionen mehrfach ausgeben. Falls nicht genügend Münzen vorhanden sind, um Ihre Aktion abzuschließen, werden die maximal verfügbaren Münzen und Zählpunkte nur für die verwendeten Münzen verwendet.
N
: Mach nichts
1
: Nimm 1 Münze vom Mittelstapel [Effekte: +1 lokal nicht geworfen / -1 Punkt / -1 global nicht geworfen]
2
: Nimm 2 Münzen vom Mittelstapel [Effekte: +2 lokal nicht geworfen / -2 Punkte / -2 global unflipped]
3
: Nimm 3 Münzen vom zentralen Stapel. [Effekte: +3 lokaler unflipped / -3 Punkte / -3 globaler unflipped]
A
: Lege 1 Münze von deinem Stapel zurück. [Effekte: -1 lokaler unflipped / +1 Punkt / +1 global nicht gewendet]
B
: Lege 2 Münzen von deinem Stapel zurück [Effekte: -2 lokal nicht gewendet / +2 Punkte / +2 global nicht gewendet]
C
: Lege 3 Münzen von deinem Stapel zurück [Effekte: -3 lokal nicht gewendet / +3 Punkte / +3 global unflipped]
X
: Entferne 1 Münze von deinem Stapel[Effekte: -1 lokaler nicht umgedrehter Punkt / 0 Punkte]
Y
: Entferne 2 Münzen von deinem Stapel. [Effekte: -2 lokaler nicht umgedrehter Punkt / 0 Punkte]
Z
: Entferne 3 Münzen von deinem Stapel. [Effekte: -3 lokaler nicht umgedrehter Punkt / 0 Punkte]
R
: Drehe Münzen zum vorherigen Spieler [Effekte: -1 Punkt pro nicht umgedrehtem Empfang, +2 Punkte pro umgedrehtem Empfang / gilt für alle Spieler]
T
: Münzen zum nächsten Spieler umdrehen [Effekte: -1 Punkt pro nicht umgedrehtem Empfang, +2 Punkte pro umgedrehtem Empfang / gilt für alle Spieler]
F
: Wirf 1 Münze um [Effekte: -1 lokaler nicht umgedrehter / +1 lokaler nicht umgedrehter / +2 Punkt]
U
: Wirf 1 Münze um [Effekte: +1 lokaler nicht umgedrehter / -1 lokaler nicht umgedrehter / -2 Punkt]
Beispielausgabe
2FF
: Nimmt zwei Münzen und wirft zwei Münzen -2 + 2 + 2 = 2 points
Wenn Ihre Ausgabe falsch ist, übernimmt der Controller NNN
.
Regler
Sie finden den Controller auf GitHub . Es enthält auch zwei in Java geschriebene Beispielbots. Überprüfen Sie das Projekt, und öffnen Sie es in Ihrer Java-IDE, damit es ausgeführt wird. Der Einstiegspunkt in die main
Methode der Klasse Game
. Java 8 erforderlich.
Zum Hinzufügen von Bots benötigen Sie zunächst entweder die kompilierte Version für Java (.class-Dateien) oder die Quellen für interpretierte Sprachen. Platzieren Sie sie im Stammverzeichnis des Projekts. Erstellen Sie dann eine neue Java-Klasse im players
Paket (Sie können ein Beispiel für die bereits vorhandenen Bots verwenden). Diese Klasse muss implementiert werden Player
, um die Methode zu überschreiben String getCmd()
. Der zurückgegebene String ist der Shell-Befehl zum Ausführen Ihrer Bots. Sie können zum Beispiel eine Ruby - Bot Arbeit mit diesem Befehl machen: return "C:\Ruby\bin\ruby.exe MyBot.rb";
. Zum Schluss fügen Sie den Bot in das Players-Array oben in der Game
Klasse ein.
Regeln
- Bots sollten nicht geschrieben werden, um bestimmte andere Bots zu schlagen oder zu unterstützen.
- Das Schreiben in Dateien ist erlaubt. Bitte schreibe an "yoursubmissionname.txt", der Ordner wird vor Spielbeginn geleert. Andere externe Ressourcen sind nicht zulässig.
- Ihr Beitrag hat 1 Sekunde Zeit, um zu antworten.
- Stellen Sie Befehle zum Kompilieren und Ausführen Ihrer Übermittlungen bereit.
Unterstützte Sprachen
Ich werde versuchen, jede Sprache zu unterstützen, aber sie muss kostenlos online verfügbar sein. Bitte geben Sie Anweisungen für die Installation, wenn Sie keine "Mainstream" -Sprache verwenden.
Ab sofort kann ich Java 6-7-8, PHP, Ruby, Perl, Python 2-3, Lua, R, node.js, Haskell, Kotlin, C ++ 11 ausführen.
Endgültige Ergebnisse
Dies sind die Ergebnisse von 100 Spielen (Punkte werden addiert):
1. BirdInTheHand: 1017790
2. Balance: 851428
3. SecondBest: 802316
4. Crook: 739080
5. Jim: 723440
6. Flipper: 613290
7. Wheeler: 585516
8. Oracle: 574916
9. SimpleBot: 543665
10. TraderBot: 538160
11. EgoisticalBot: 529567
12. RememberMe: 497513
13. PassiveBot: 494441
14. TheJanitor: 474069
15. GreedyRotation: 447057
16. Devil: 79212
17. Saboteur: 62240
Einzelne Ergebnisse der Spiele finden Sie hier: http://pasted.co/63f1e924 (mit Startmünzen und Anzahl der Runden pro Spiel).
Der Gewinner erhält eine Prämie von 50 Reputationen: Bird In The Hand von Martin Büttner .
Vielen Dank für Ihre Teilnahme, bis zum nächsten KOTH ~
quelle
Antworten:
Vogel in der Hand, Rubin
Wenn keiner von uns einen Fehler in seinen Programmen hat, ist der Hauptalgorithmus wahrscheinlich dem von Mathias 'Oracle sehr ähnlich. Ausgehend von der Annahme, dass wir vor der Endrunde nicht wissen können, mit welchen Münzen wir enden werden, bewerten wir die aktuellen Züge ausschließlich auf der Grundlage der sofort erhaltenen Punkte, wobei wir völlig ignorieren, um welche Art von Münzen es sich handelt mit. Da es nur 14 3 = 2744 mögliche Zugsätze gibt , können wir alle leicht simulieren, um herauszufinden, wie viele Punkte sie bringen werden.
Wenn jedoch ein Zugsatz das Spiel beendet (entweder weil er den globalen Pot auf Null reduziert oder weil dies die 50. Runde ist und wir als letzter ziehen), werden auch die Münzen berücksichtigt, die am Ende von im Besitz sind Der Verschiebungssatz, um den Wert des Verschiebungssatzes zu bestimmen. Ich überlegte zuerst, das Spiel zu beenden, wann immer es möglich war, aber dies würde zu einem schrecklichen Zug führen,
333
wenn nur noch 9 Münzen im Pot sind.Wenn es mehrere Züge gibt, die das gleiche Ergebnis liefern, wählen wir einen zufälligen. (Ich könnte dies ändern, um es zugunsten von spielbeendenden Zugsätzen zu voreingenommen zu machen.)
quelle
Oracle, Python 3
Update: Die Reihenfolge der verschiedenen Versuche wurde geändert, um einen niedrigen Stapel Münzen gegenüber Rotationen zu bevorzugen.
Versucht jede einzelne mögliche Ausgabe und behält diejenige bei, die die maximale Punktzahl für diesen Zug ergibt.
quelle
deepcopy
Komplexität von Raum (also Zeit [ ]) zu verbessern, indem nur relevante Nachbarn beibehalten werden . Ich bin mir nicht sicher, wie es sich auf die Dinge auswirken wird.filter_neighbors
und modifiziertinvalid_move
, um Klarstellungen in der Frage zu berücksichtigen. Ich kann den Fehler jedoch nicht reproduzieren:$ python oracle.py '4;7;2040;8_-28_1_10;9_-43_0_9;2_-10_4_3;6_-24_6_3;0_6_2_12;1_48_3_0;10_21_4_8;5_6_5_1;4_-12_3_7;7_10_1_3;3_1_1_0'
printsTTR
Gierige Rotation, Ruby
Dies ist dem Ansatz von ArtOfCode ziemlich ähnlich, mit der Ausnahme, dass überprüft wird, von welchem Nachbarn wir mehr Punkte erhalten können.
C
Stattdessen wird ausgewählt,F
ob wir nach der Drehung 3 oder mehr Münzen haben.Nachdem ich das aufgeschrieben habe, bin ich mir ziemlich sicher, dass ein besserer Ansatz darin besteht, jedes Mal gierig das Beste aus allen Zügen herauszusuchen und die Drehung möglichst voranzutreiben (anstatt an einem festen Punkt festzuhalten: "Loslassen, drehen, loswerden" von ungeflipptem "Muster).
Dies berücksichtigt auch nicht die impliziten Punkte, die durch die tatsächlich im Besitz befindlichen Münzen dargestellt werden (basierend auf der Annahme, dass das Spiel genügend Runden dauert, so dass ich meine Münzen wahrscheinlich sowieso nicht behalten werde).
quelle
Flipper, Python 2
Flipper sammelt Münzen und versucht, von Unflipped zu Flipped zu wechseln. Flipper ist kein schlauer Spieler, sondern versucht, eine positive Kraft im Spiel zu sein.
Flipper muss nur noch
python flipper.py <arg>
rennen.quelle
SimpleBot, Python 3
SimpleBot ist einfach. Er hat eine Strategie ausgearbeitet und wird dabei bleiben.
Zu rennen:
wo der Inhalt der
main.py
Datei ist:quelle
Gleichgewicht, Lua
Balance wird versuchen, das Gleichgewicht in seinem Wert zu halten, um den Verlust zu minimieren, falls jemand die
R
undT
-Aktionen gegen ihn einsetzt. Er ist der Meinung, dass dieser Lebensstil der wahre ist, und sollte für jeden durchgesetzt werden, der kein ausgewogenes Verhältnis zwischen eingeworfenen und nicht eingeworfenen Münzen hat, so dass jeder, der ihm nahe steht, bestraft wird, sobald er dadurch Punkte verlieren könnte.Er benötigt den folgenden Befehl zum Ausführen:
Wobei die Datei balance.lua den folgenden Code enthält:
quelle
Der Hausmeister, Python 3
Er versucht, das Durcheinander, das die anderen Spieler mit all diesen Münzen anrichten, zu beseitigen und sie wieder in den Pool zu legen.
Er versucht, alle seine nicht umgedrehten Münzen zurückzugeben. Wenn er einige festsitzende umgedrehte Münzen hat, wird er sie umdrehen und wenn er alle seine Münzen loswird, wird er jemand anderes bekommen.
quelle
Crook, R
Zu rennen:
Rscript Crook.R
Grundsätzlich tauscht es seine Münzen nur dann mit seinen Nachbarn aus, wenn der Umtausch ungleich zu seinen Gunsten ist. Wenn kein vorteilhafter Tausch möglich ist, werden Münzen mit dem globalen Stapel so ausgetauscht, dass das Verhältnis intakt bleibt, aber einige Punkte generiert werden.
Bearbeiten: Ich habe diesem Bot ein wenig Tiefe verliehen, indem ich ihn veranlasste, den nächsten und vorherigen Stapel von 2 und 3 Spielern anstelle des nächsten zu überprüfen und zu überprüfen, ob es insgesamt von Vorteil ist, ihn so oft zu drehen.
2nd Edit : Nach der Idee von @ MartinBüttner führt der Bot nun ein "RT" oder "TR" durch, wenn es für ihn mehr von Nutzen wäre als für seine Nachbarn (wenn ich es nicht durcheinander gebracht hätte :)).
quelle
RTR
du die Punktzahl zweimal von seinen Münzen erhältst.Jim, Ruby
basierend auf Martin Büttners Greedy Rotation .
dreht sich in die eine oder andere Richtung, je nachdem, was ihm im Vergleich zum besten anderen Spieler die meisten Punkte bringt. Dann schnappt er sich schnell Geld.
quelle
TraderBot
Dieser Bot versucht zu drehen, wann immer er die meisten Punkte in dieser Aktion erzielt. Wenn es sich nicht drehen kann, versuchen Sie, die nicht geworfenen Münzen zu entfernen, oder nehmen Sie ein paar mehr, um sie in den folgenden Aktionen zu ändern.
import java.util.List;
public class TraderBot {
So führen Sie es aus: Fügen Sie es einfach demselben Ordner wie die Standard-Bots hinzu und erstellen Sie die folgende Klasse
Fügen Sie dann diese Klasse zum
Player[] players
Array hinzu.quelle
Wheeler
Wheeler errechnete die bestmögliche Bewegung beim Drehen der Münzen.
quelle
Saboteur, Python 2
Die Zufälligkeit bedeutet, dass es wahrscheinlich nicht sehr gut sabotieren wird, aber ich denke, ich werde es später warten lassen, bis das 'Ende' erreicht ist (wie viele Runden / Münzen noch übrig sind) und DANN drehen, nachdem ich mir die erreichbaren Spieler in der Nähe angesehen habe, von denen ich stehlen möchte ... nur eine Umdrehung zu machen, scheint wirklich schlecht zu sein, wenn man bedenkt, dass andere Leute wahrscheinlich auch Umdrehungen machen. Ich denke nicht, dass das sehr gut funktionieren wird ...
quelle
Zweitens, Python 3
Dieses Programm durchläuft alle möglichen 3 Zugkombinationen und wählt den zweitbesten aus.
Denn wenn Sie den perfekten Zug haben, ist es wahrscheinlich eine Falle.
Bearbeiten: Auskommentierte Eingabe entfernt
Bearbeiten: Der Code druckte einen zufälligen legalen Zug. Es sollte jetzt das zweitbeste Ergebnis zurückgeben.
quelle
Teufelsbot
Obwohl die Ausgabe nur halb so hoch ist wie die des Teufels, sollten die Ergebnisse ziemlich katastrophal sein. Wenn Sie 9 Münzen pro Spielzug nehmen, erschöpft sich der Stapel der Münzen. Da dieser Bot niemals eine der Münzen abwirft, die er benötigt, ist es äußerst schlimm für alle anderen, die neben ihm sitzen, wenn es eine Rotation gibt (-9 Punkte für jede Runde, die dieser Bot unternimmt).
Befehl:
python3 devil.py
Ich hoffe, dass ich später einige echte Bots machen kann.
quelle
Erinnere dich an mich, Python 3
Dieses Programm enthält eine erhebliche Menge an eingebauten Daten aus einem Test gegen den festen SecondBest-Bot.
Es sollte lernen, welche Züge am besten zu verwenden sind, verwendet jedoch nicht die Eingaben anderer Spieler.
Bearbeiten: unnötige Punktberechnung entfernt
Bearbeiten: unkommentierte Spielereingabe
quelle