Testfahrer • Herausforderung Diskussion • Submit Adventurer
( Bildquelle )
Mehrere rivalisierende Abenteurer durchsuchen die Ruinen nach Schätzen, können aber nur so viel auf einmal tragen und haben ihre Grenzen der Ausdauer. Sie möchten den wertvollsten Schatz finden und hinausgehen, bevor sie zu müde werden, um fortzufahren. Sie versuchen, durch ihre Plünderungen so reich wie möglich zu werden.
Gameplay
Jeder Abenteurer beginnt im ersten Raum des Dungeons mit 1000 Ausdauerpunkten und 50 kg Platz im Rucksack.
Das Spiel funktioniert rundenbasiert, wobei alle Spieler gleichzeitig ihre Züge abwickeln. In jeder Runde kannst du eine der folgenden Aktionen ausführen:
- Gehe in den nächsten Raum.
- Zum vorherigen Raum gehen.
- Bieten Sie Ausdauer, um einen Schatz zu nehmen.
- Lass einen Schatz fallen.
Der Wechsel zwischen den Räumen erfordert 10 Ausdauer plus 1 Ausdauer pro 5 kg, die sich gerade in Ihrem Rucksack befinden. Zum Beispiel benötigt ein Abenteurer, der 3 kg Schatz trägt, 11 Ausdauer, und ein Abenteurer, der 47 kg trägt, benötigt 20 Ausdauer, um sich zu bewegen.
Das Fallenlassen eines Schatzes erfordert 1 Ausdauer, unabhängig davon, welcher Schatz gefallen ist.
Beim Verlassen der Ruinen werden vom Spieler keine Züge mehr ausgeführt.
Wenn ein Spieler keine dieser Aktionen ausführen kann (aufgrund mangelnder Ausdauer oder fehlender Schätze), stirbt sein Abenteurer vor Erschöpfung und verschüttet seinen gehaltenen Schatz in den aktuell besetzten Raum. Wenn ein Spieler versucht, eine ungültige Aktion auszuführen, wird sein Abenteurer stattdessen durch eine Falle getötet, was zur gleichen Verschwendung von Schätzen führt.
Bieten
Das Mindestgebot für einen Schatz beträgt 1 Ausdauer pro 1 kg, das der Schatz wiegt. Sie können auch zusätzliche Ausdauerpunkte bieten, um den Schatz mit größerer Wahrscheinlichkeit zu erhalten. Die gebotene Ausdauer wird unabhängig vom Ergebnis verbraucht.
Falls mehrere Spieler geboten haben, denselben Schatz zu nehmen, erhält der Spieler, der das höchste Gebot abgegeben hat, den Schatz. Wenn mehr als ein Spieler das höchste Gebot abgegeben hat, erhält keiner von ihnen den Schatz.
Gewinnbedingung
Der Spieler mit dem höchsten Gesamtwert an Schätzen ist der Gewinner. Im unwahrscheinlichen Fall eines Unentschieden gehen die Unentschieden zum kleinsten Gesamtgewicht, dann zur kleinsten Anzahl von Schätzen, dann zum Wert des wertvollsten Schatzes, zum zweitwertvollsten, zum dritten ... bis das Unentschieden gebrochen ist. Für den nahezu unmöglichen Fall, dass es an dieser Stelle noch ein Unentschieden gibt, sagt der Testfahrer "Screw it" und der Sieger wird dabei willkürlich ermittelt.
Im Rahmen des Turniers erhalten die Spieler den ersten Platz mit 10 Punkten, den zweiten Platz mit 9 Punkten, den dritten Platz mit 8 Punkten usw., wobei tote Spieler und Abenteurer ohne Schätze 0 Punkte erzielen.
Über die Ruinen
- Jeder Raum enthält anfangs zwischen undSchätze. (Wobeidie Zimmernummer ist)
- Es gibt beliebig viele Räume, die nur durch die Ausdauer und Erkundungsbereitschaft der Abenteurer begrenzt sind.
- Jeder Schatz hat einen Geldwert (in ganzen $) und ein Gewicht (in ganzen kg).
- Schätze sind in der Regel wertvoller und zahlreicher, wenn Sie tiefer in die Ruinen vordringen.
- Die spezifischen Formeln zum Erzeugen von Schätzen lauten wie folgt: (Verwenden der -Notation für Würfelwürfe)
- Das Gewicht wird zuerst mit der Formel berechnet. D 6 - 2 (mindestens 1)
- Der Schatzwert wird dann über (wobei die Raumnummer und das Gewicht ist).
Für Spieler sichtbare Informationen
In jedem Zug erhalten die Spieler die folgenden Informationen:
- Die Nummer des Raums, in dem sie sich gerade befinden. Dies ist 1-indiziert, daher befindet sich der Ausgang konzeptionell bei "Raum 0".
- Eine Liste der aktuell im Raum befindlichen Schätze
- Eine Liste der anderen Spieler, die sich ebenfalls gerade im Raum befinden.
- Ihr aktueller Schatzbestand
- Ihre aktuelle Ausdauer
Codierung
Den Testfahrer finden Sie hier .
Sie sollten eine Unterklasse davon implementieren Adventurer
Klasse :
class Adventurer:
def __init__(self, name, random):
self.name = name
self.random = random
def get_action(self, state):
raise NotImplementedError()
def enter_ruins(self):
pass
Sie müssen nur die get_action
Methode überschreiben . enter_ruins
wird ausgeführt, bevor ein Spiel beginnt, und ist Ihre Chance, alles vorzubereiten, was Sie für das Spiel bereithalten möchten. Sie müssen nicht überschreiben __init__
, und Sie sollten es wirklich nicht tun . Wenn Sie __init__
abstürzen, werden Sie disqualifiziert.
get_action
erhält ein einziges Argument, das a ist namedtuple
mit den folgenden Feldern (in dieser Reihenfolge, wenn Sie die Destrukturierung bevorzugen):
room
: Die Nummer des Raumes, in dem Sie sich gerade befindentreasures
: die Liste der Schätze im Raumplayers
: die Liste der anderen Spieler im Raum. Auf diese Weise erhältst du nur den Spielernamen, sodass du nicht weißt, welcher Bot sie kontrolliert oder welches Inventar / welche Ausdauer sie haben.inventory
: die Liste der Schätze in Ihrem Rucksackstamina
: Ihre aktuelle Ausdauer
Dieses Objekt bietet zusätzlich zwei Utility-Eigenschaften:
carry_weight
: das Gesamtgewicht aller Schätze, die Sie tragentotal_value
: der Gesamtwert aller Schätze, die Sie tragen
Die treasures
und inventory
Listen enthalten namedtuple
s mit diesen Attributen:
name
: der Name des Schatzes (für kosmetische Zwecke)value
: der Geldwert des Schatzes in $.weight
: das Gewicht des Schatzes in kg
get_action
sollte einen der folgenden Werte / Muster zurückgeben:
'next'
oder'previous'
, um zum nächsten / vorherigen Raum zu wechseln'take', <treasure index>, <bid>
(Ja, als Tupel, obwohl jede Sequenz auch technisch funktioniert), um auf den Schatz an dem angegebenen Index in der Schatzliste des Raums zu bieten. Beide Argumente sollten Ganzzahlen sein. Schwimmer werden abgerundet.'drop', <inventory index>
den getragenen Schatz fallen zu lassen, der bei dem gegebenen Index gefunden wurde. Der Index sollte (natürlich) eine ganze Zahl sein.
Andere Einschränkungen
- Sie dürfen nur die zufällige Instanz verwenden, die Ihnen während der Initialisierung für Pseudozufälligkeit zur Verfügung gestellt wurde.
- Alles andere, was einen verhaltensbedingten Nichtdeterminismus hervorrufen könnte, ist nicht erlaubt. Die Absicht hierbei ist, dass Bots sich identisch verhalten, wenn sie denselben Startwert erhalten, um beim Testen neuer Bots (und potenziellen Bugs im Testtreiber) zu helfen. Nur kosmische Strahlung sollte Abweichungen / Nichtdeterminismus verursachen.
- Denken Sie daran, dass Hash-Codes in Python 3 zufällig angeordnet sind, sodass die Verwendung
hash
für Entscheidungen nicht zulässig ist.dict
s sind in Ordnung, auch wenn die Iterationsreihenfolge für Entscheidungen verwendet wird, da die Reihenfolge seit Python 3.6 garantiert konsistent ist.
- Sie dürfen den
ctypes
Testtreiber nicht mit Hacks oderinspect
Stack-Voodoo (oder einer anderen Methode) umgehen . Es gibt einige beeindruckend beängstigende Dinge, die Sie mit diesen Modulen tun können. Bitte nicht- Jeder Bot ist durch defensive Kopien und die natürliche Unveränderlichkeit von einigermaßen gut in Sandkästen eingeschlossen
namedtuple
s , aber es gibt einige unverbesserliche Schlupflöcher / Exploits. - Andere Funktionen von
inspect
undctypes
können verwendet werden, sofern keine davon zur Umgehung der Steuerungsfunktionen verwendet wird. - Es ist nicht zulässig, Instanzen der anderen Bots in Ihrem aktuellen Spiel zu erfassen.
- Jeder Bot ist durch defensive Kopien und die natürliche Unveränderlichkeit von einigermaßen gut in Sandkästen eingeschlossen
- Bots sollten alleine agieren und dürfen sich in keiner Weise für irgendeinen Zweck mit anderen Bots koordinieren. Dies beinhaltet das Erstellen von zwei Bots mit unterschiedlichen Zielen, sodass sich einer für den Erfolg des anderen opfert. Sobald es mehr als 10 Konkurrenten gibt, kann nicht garantiert werden, dass die beiden Bots im selben Spiel sind, und die Namen der Abenteurer geben keinen Hinweis auf die Bot-Klasse. Daher sind diese Arten von Strategien ohnehin begrenzt.
- Derzeit gibt es keine feste Beschränkung der Ausführungszeit. Ich behalte mir jedoch das Recht vor, die Ausführungszeit in Zukunft zu beschränken, wenn Turniere zu lange dauern. Seien Sie vernünftig und versuchen Sie, die Verarbeitung unter 100 ms zu halten , da ich nicht damit , sie unter diesen Schwellenwert einschränken zu müssen. (Turniere dauern ungefähr 2 Stunden, wenn alle Bots ungefähr 100 ms pro Runde benötigen.)
- Ihre Bot-Klasse muss unter allen Einsendungen eindeutig benannt sein.
- Sie können sich an nichts zwischen Spielen erinnern. (Sie können sich jedoch an Dinge zwischen den Runden erinnern )
- Bearbeiten Sie keine sys.modules. Alle externen Instanzvariablen sollten als Konstante behandelt werden.
- Sie dürfen den Code eines Bots einschließlich Ihres eigenen Codes nicht programmgesteuert ändern.
- Dies beinhaltet das Löschen und Wiederherstellen Ihres Codes. Dies soll das Debuggen und die Turniere rationalisieren.
- Jeder Code, der zum Absturz des Controllers führt, wird sofort disqualifiziert. Während die meisten Ausnahmen abgefangen werden, können einige durchrutschen und Fehler können nicht abgefangen werden. (Ja, Sie können in Python dank segfault
ctypes
)
Einreichungen
Geben Sie oben in der Antwort den Namen Ihres Bots mit einem an, um die Antwortverwaltung zu vereinfachen #Header1
und stellen Sie sicher, dass Ihre Antwort mindestens einen Codeblock enthält (nur der erste in Ihrer Antwort wird verwendet). Sie müssen keine Importe oder Dokumentzeichenfolgen einfügen, da diese vom Scraper automatisch hinzugefügt werden.
Ich werde eher geneigt sein, Antworten mit detaillierten und verständlichen Erklärungen abzustimmen. Andere werden sich wahrscheinlich genauso verhalten.
Grob gesagt sollte Ihre Antwort so formatiert sein:
# Name of Bot
Optional blurb
#imports go here
class BotName(Adventurer):
#implementation
Explanation of bot algorithm, credits, etc...
(gerendert als)
Name des Bots
Optionaler Klappentext
#imports go here class BotName(Adventurer): #implementation
Erklärung von Bot-Algorithmen, Credits, etc ...
Lokales Ausführen des Testtreibers
Sie benötigen Python 3.7+ und ich empfehle, dass Sie auch tabulate
über Pip installieren . Das Scrappen dieser Seite für Einreichungen erfordert zusätzlich lxml
und requests
. Sie sollten auch ein Terminal mit Unterstützung für ANSI-Farbverluste verwenden, um optimale Ergebnisse zu erzielen. Informationen zum Einrichten in Windows 10 finden Sie hier .
Fügen Sie Ihren Bot zu einer Datei in einem Unterverzeichnis in demselben Verzeichnis wie ruins.py
( ruins_bots
standardmäßig) hinzu und stellen Sie sicher, dass Sie ihn from __main__ import Adventurer
oben im Modul hinzufügen . Dies wird zu den Modulen hinzugefügt, wenn der Scraper Ihre Einreichung herunterlädt, und obwohl es definitiv hacky ist, ist dies die einfachste Möglichkeit, um sicherzustellen, dass Ihr Bot richtig Zugriff hat Adventurer
.
Alle Bots in diesem Verzeichnis werden zur Laufzeit dynamisch geladen, sodass keine weiteren Änderungen erforderlich sind.
Turnier
Der endgültige Sieger wird in einer Reihe von Spielen mit bis zu 10 Bots in jedem Spiel ermittelt. Bei mehr als 10 Einsendungen werden die 10 besten Bots ermittelt, indem sie systematisch in 10er-Gruppen aufgeteilt werden, bis jeder Bot (genau) 20 Spiele gespielt hat. Die Top 10 Bots werden aus dieser Gruppe mit zurückgesetzten Punktzahlen ausgewählt und spielen solange, bis der Erstplatzierte einen Vorsprung von 50 Punkten vor dem Zweitplatzierten erreicht hat oder bis 500 Spiele gespielt wurden.
Bis mindestens 10 Einsendungen vorliegen, werden leere Slots mit "Säufer" gefüllt, die nach dem Zufallsprinzip durch die Ruinen wandern und zufällige Schätze einsammeln (und gelegentlich fallen lassen), bis ihnen die Ausdauer ausgeht und sie geradewegs zum Ausgang müssen.
Turniere werden wöchentlich wiederholt, wenn neue Einreichungen vorliegen. Dies ist eine offene KOTH-Challenge ohne festgelegtes Enddatum.
Bestenliste
Vom Lauf am 4. Mai 2019 um 16:25 Uhr MEZ: (04.05.2019 16:25 - 06:00 Uhr)
Seed: K48XMESC
Bot Class | Score | Mean Score
--------------+---------+--------------
BountyHunter | 898 | 7.301
Scoundrel | 847 | 6.886
Accountant | 773 | 6.285
Ponderer | 730 | 5.935
Artyventurer | 707 | 5.748
PlanAhead | 698 | 5.675
Sprinter | 683 | 5.553
Accomodator | 661 | 5.374
Memorizer | 459 | 3.732
Backwards | 296 | 2.407
Update - 15. April: Einige Regel-Updates / Klarstellungen
Update - 17. April: Verbot einiger bemerkenswerter Fälle schändlicher Handlungen wie das Ändern des Codes anderer Bots.
Update - 4. Mai: Sleafar erhält Kopfgeld, weil er Rückwärts absolut zerstört hat. Herzliche Glückwünsche!
pip
installiert haben PATH
(was bei neueren Installationen AFAIK Standard ist), können Sie über Windows pip install modulename
in der Eingabeaufforderung ausführen . Für andere Umstände (von denen ich nichts weiß) gehe zu pip , suche nach dem benötigten Modul und wähle eine Option.