HINWEIS : Der Gewinner dieses Wettbewerbs ist Jack !!!. Weitere Einsendungen werden nicht akzeptiert.
Hier ist der Chatroom für diese King-of-the-Hill- Herausforderung. Dies ist meine erste, also bin ich offen für Vorschläge!
Reaper ist ein Spielkonzept, das von der Art of Problem Solving entwickelt wurde und Geduld und Gier beinhaltet. Nachdem Sie das Spiel an einen KOTH-Wettbewerb angepasst haben (Vielen Dank an @NathanMerrill und @dzaima für Ihre Vorschläge und Verbesserungen), ist hier die Herausforderung.
Das Spiel funktioniert wie folgt: Wir haben einen Wert, der als Reap bezeichnet wird und mit jeder Zecke mit einer gegebenen Konstante multipliziert wird. Nach jedem Tick hat jeder Bot die Möglichkeit zu "ernten", was bedeutet, dass der aktuelle Wert von Reap zu seiner Punktzahl addiert wird und Reap auf 1 reduziert wird.
Es gibt jedoch eine feste Anzahl von Ticks, die ein Bot zwischen den "Ernten" warten muss, und eine feste Anzahl von Punkten, die erforderlich sind, um das Spiel zu gewinnen.
Einfach genug? Hier sind Ihre Eingaben:
I / O
Sie müssen in Python 3 eine Funktion schreiben, die 3 Eingaben akzeptiert. Der erste wird self
zum Referenzieren von Klassenobjekten verwendet (wird später angezeigt). Der zweite ist der Reap
aktuelle Wert der Ernte, den Sie verdienen würden, wenn Sie "ernten" würden. Das dritte ist prevReap
eine Liste der Bots, die während des vorherigen Ticks geerntet haben.
Andere Objekte, auf die Sie in Ihrer Funktion zugreifen können:
self.obj: An object for your use to store information between ticks.
self.mult: The multiplier that Reap is multiplied by each tick
self.win: The score you need to win
self.points: Your current set of points
self.waittime: The amount of ticks that you must wait between reaps during the game
self.time: The number of ticks since your last reap
self.lenBots: The number of bots (including you) in the game.
self.getRandom(): Use to produce a random number between 0 and 1.
Sie MÜSSEN nicht irgendwas vom Inhalt dieser Objekte bearbeiten, mit Ausnahme self.obj
.
Sie müssen ausgeben 1
, um zu ernten, und alles andere (oder nichts), um nicht zu ernten. Beachten Sie, dass ich die Tatsache, dass Sie sich für das Ernten entschieden haben, ignoriere, wenn Sie ernten, wenn Sie nicht genügend Zecken gewartet haben.
Regeln
Die Parameter I verwenden werden sind winning_score=10000
, multiplier=1.6-(1.2/(1+sqrt(x)))
, waittime = floor(1.5*x)
wo x
die Anzahl der Bots in der KOTH.
- Das Spiel endet, wenn ein Spieler (oder mehrere) die Siegpunktzahl erreicht hat.
- Wenn mehrere Bots gleichzeitig um die Ernte bitten, erhalten die Bots, die länger gewartet haben, Vorrang (bei Gleichstand dürfen die Bots, die die maximale Zeit gewartet haben, alle ernten und die Punkte im Reap sammeln).
- Ihr Bot darf im Durchschnitt über 5 Ticks nicht mehr als 100 ms benötigen.
- Wenn Sie Bibliotheken importieren möchten, fragen Sie! Ich werde versuchen, alle Bibliotheken hinzuzufügen, die ich auf meiner Desktop-Version von Python ausführen kann (Mathe ist bereits importiert: zögern Sie nicht, es zu verwenden).
- Alle Standardlücken für KoTHs, wie doppelte Bots, 1-up-Bots usw., sind auf ähnliche Weise gesperrt.
- Alle Bots, die eine beliebige Art von Zufälligkeit verwenden, müssen die von
getRandom
mir bereitgestellte Funktion verwenden.
Sie finden den Controller im TIO-Link unten. Fügen Sie dazu den Namen Ihrer Funktion BotList
als Zeichenfolge hinzu und fügen Sie die Funktion dem Code hinzu. Ändern Sie multiplier
zu ändern , was die Reap von jedem Tick multipliziert wird, ändern winning_score
sich ändern , was notwendig Tor gegangen um das Spiel zu beenden, und ändern Sie waittime
die Anzahl der Ticks , um zwischen erntet zu warten.
Hier sind einige Beispiele (und ziemlich dumme) Bots. Das Senden von Bots, die diesen ähnlich sind, ist nicht gestattet. Sie zeigen jedoch, wie der Controller funktioniert.
def Greedybot(self,Reap, prevReap):
return 1
def Randombot(self,Reap, prevReap):
if self.obj == None:
self.obj=[]
self.obj.append(prevReap)
if self.getRandom()>0.5:
return 1
Für Interessierte ist hier der Controller mit den 15 darin eingebauten Einsendungen: Try it Online
ENDGÜLTIGE ERGEBNISSE
WOO SIE SIND ENDLICH HIER! Überprüfen Sie den TIO-Link oben, um festzustellen, mit welchem Code ich die endgültige Rangliste erstellt habe. Die Ergebnisse sind nicht besonders interessant. Über die 1000 Läufe, die ich mit verschiedenen zufälligen Samen gemacht habe, waren die Ergebnisse
1000 wins - Jack
0 wins - everyone else
Glückwunsch an den Kopfgeldgewinner Jack !! (aka @Renzeee)
quelle
len(BotList)
?25
Bots im Spiel gemacht habe. Wartet aber erstmal ein bisschen, bis andere die Bots sehen. Rushabh Mehta , wird es eine Frist / einen Endtermin geben, an dem alle Bots ausgeführt werden und ein Gewinner ermittelt wird?Antworten:
Unentschlossenes nervöses Durcheinander
Dieser Bot führt zuerst die üblichen Prüfungen durch (Kann ich ernten, kann ich gewinnen?) Und sucht dann nach einem Zielwert, bevor er erntet. Es ist jedoch unentschlossen, und nachdem es das Ziel erreicht hat, fragt es sich, wie lange es warten kann und nicht sofort erntet. Außerdem ist es nervös, so dass es versehentlich auf den Knopf drückt und vor dem Ziel erntet.
Unterhaltsame Tatsache: So spiele ich als Mensch im Grunde genommen Schnitter.
quelle
Scharfschütze
Ein Bot voller Trotz. Verfolgt die Abklingzeiten und Punkte des Gegners. Versuche, andere vom Gewinnen abzuhalten. Eigentlich gewinnt so gut wie nie, aber es ist frustrierend, für andere zu spielen.
BEARBEITEN:
Wenn niemand> = 70% der Gewinnpunktzahl ist:
Wenn sich mindestens die Hälfte der anderen Benutzer in der Abklingzeit befindet, versuchen Sie zu ernten.Dies macht es schwierig, bestimmte Gegner anzugreifen, und wurde daher entfernt.Wenn jemand> = 70% der Siegpunktzahl ist:
Gelangweilt
Nur zum Spaß wurde dieser Bot von einem Freund mitgebracht und möchte eigentlich nicht hier sein. Sie würfeln einen W16, bis sie eine Zahl von 1-9 erhalten, und versuchen dann, immer dann zu ernten, wenn eine Zahl die gewählte Ziffer enthält. (Ein d10 zu suchen würde das Spiel stören, was unhöflich ist und 0 ist einfach zu einfach!)
quelle
self.obj.opponents[opponent]["time"] += 1
in der ersten for-Schleife undself.obj.lastReap
am Ende der zweiten For-Schleife verwenden. Ansonsten schöne Ideen. Ich bin gespannt, wie es gegen viele andere Bots ausgehen würde. Wenn ich viele gierige und zufällige Bots benutze, wird es so schnell wie möglich ernten, da die meiste Zeit die Hälfte der Bots nicht ernten kann. Aber das sind natürlich keine realistischen Konkurrenten.Jack
Dies ist ein einfacher Bot mit 4 Regeln:
Ich habe die 3 Ticks gegenüber den aktuell vorhandenen Bots optimiert (Sniper, grim_reaper, Every50, mess, BetterRandom, Averager, einige mehr).
Ich habe versucht, bei meiner alten Lösung zu bleiben (5 Ticks), aber auch zu ernten, wenn Sie nicht länger als X Ticks ernten, und dann zu ernten, nachdem weniger Ticks während des Nicht-Erntens verstrichen sind (dh 5, wenn Sie länger als Selbst gewartet haben) .Wartezeit + 5, auch ernten, wenn nicht für 4 Zecken geerntet wurde). Aber das hat sich nicht verbessert, nur immer nach 4 anstatt nach 5 Zecken zu ernten.
quelle
Alle 50
Diese Bots werden jedes Mal ernten, wenn
Reap
Betrag über 50 liegt.Warum 50?
Wenn ich davon ausgehe, dass 25 Bots im Spiel sind, bedeutet dies
multiplier = 1.6-(1.2/(1+sqrt(25))) = 1.4
undwaittime = floor(1.5*25) = 37
. Da das umReap
beginnt1
, wird es so aufgehen:Wie Sie sehen können, erreicht es nach 13 Ticks über 50. Da die
Reap
wird jedes Mal , wenn ein Bot erntet auf 1 zurückgesetzt und diewaittime
für einen Bot , dass erntet 37 ist, ist die Wahrscheinlichkeit , dass ein Bot erntet eher früher als später ziemlich hoch, vor allem mit Bots ähnlich dem BeispielGreedyBot
, die, sobald ihr erntenwaittime
heißt wieder verfügbar. Zuerst wollte ich 200 machen, was der 17. Tick ist, etwas in der Mitte der 37 Wartezeit-Ticks, aber mit der Annahme, dass 25 Bots im Spiel sind, ist die Chance groß, dass jemand anderes den schnapptReap
vor mir . Also habe ich es auf 50 gesenkt. Es ist immer noch eine schöne, gerundete Zahl, aber vor allem, weil es das 13. Häkchen (mit 25 Bots) ist und 13 und "ernten" auch ein bisschen in dasselbe "böse" Genre passen.Code:
Der Code ist lächerlich trivial ..
Anmerkungen:
Dieser Bot ist ziemlich schlecht, da nur wenige Bots im Spiel sind. Im Moment lasse ich es, und ich könnte einen besseren Bot machen, der die beste Zeit dafür berechnet
Reap
. Mit einer extrem geringen Anzahl von Bots im Spiel ist daswaittime
natürlich auch viel niedriger, so dass es sogarGreedyBot
recht leicht sein kann, von diesem Bot zu gewinnen, wenn derwaittime
niedrig genug ist.Hoffentlich werden mehr Leute viel mehr Bots hinzufügen. ; p
quelle
def Every49(self, Reap, prevReap): return Reap > 49
Deine Bewegung.int
die Ungleichung umgehen, da 1 der eigentliche Befehl istTrue
explizit zu machen1
. Es stellte sich heraus, dass derTrue == 1
ScheckTrue
für meinen Bot immer noch zurückkehren würde, wenn er zu den ListenReapers
Ihrernext
Funktion hinzugefügt würde, aber ich habe die Besetzung trotzdem zu int hinzugefügt, wie Sie vorgeschlagen haben.Averager
Dieser Bot versucht immer dann zu ernten, wenn der aktuelle Erntewert über dem durchschnittlichen Erntewert liegt.
quelle
Gevatter Tod
Dieser Bot hält einen laufenden Durchschnitt der Werte aller vorherigen Ernten sowie die Zeit, die jeder Bot gewartet hat. Es erntet, wenn es länger als 3/4 der anderen Bots gewartet hat und die Ernte mindestens 3/4 der Größe der durchschnittlichen Ernte entspricht, die bisher gesehen wurde. Das Ziel ist es, eine Menge angemessener Ernten mit geringem Risiko zu erzielen.
Bearbeiten: Einige peinliche Syntaxfehler wurden behoben.
Probieren Sie es online
quelle
self.obj.reaps
anstelle vonself.reaps
undself.obj
anstelle vonself.object
undprevReap
anstelle vonprevLeap
und add () nachself.obj.players.values
zweimal verwenden. Und ich denke,self.obj.reaps = []
wird nicht funktionieren, wennself.obj
es sich nicht um ein Objekt handelt. Ich bin mir nicht ganz sicher, ob alles dann noch wie vorgesehen funktioniert und ob alles, was ich gesagt habe, wahr ist. Nach diesen Änderungen und der Verwendung eines Dummy-Objekts für denself.obj
Fall, dass es noch nicht existiert, wird Ihr Code für mich kompiliert.class Object(object):
[newline]pass
oben hinzugefügt undself.obj = Object()
in der verwendetif not hasattr(..)
(wenn ich mich richtig erinnere).BetterRandom
Der Bot basiert auf der Annahme, dass die Chance zu ernten proportional zur Größe der Ernte sein sollte, da ein Punkt ein Punkt ist, egal wann er erreicht wurde. Es gibt immer eine sehr kleine Chance zu ernten, dies hält das Verhalten ausnutzbar. Zuerst dachte ich, es wäre direkt proportional und nahm an, dass die Proportionalitätskonstante ungefähr so ist
1/mult^waittime
(die maximale Ernte, vorausgesetzt, mindestens ein Bot spielt gierig). Nach einigen Simulationen stellte ich fest, dass dies in der Tat die optimale Konstante ist. Aber der Bot wurde immer noch von Random übertroffen, also kam ich zu dem Schluss, dass die Relation nicht direkt proportional ist, und fügte eine Konstante hinzu, um zu berechnen, wie die Relation lautete. Nach einigen Simulationen stellte ich fest, dass meine Testmenge an Bots-1.5
optimal war. Dies entspricht tatsächlich einem umgekehrt proportionalen Verhältnis zwischen der Erntechance undreap*sqrt(reap)
Das ist überraschend. Ich vermute, dass dies stark von den spezifischen Bots abhängt. Eine Version dieses Bots, die k während des Spielens berechnet, ist daher besser. (Aber ich weiß nicht, ob Sie Daten aus früheren Runden verwenden dürfen).EDIT: Ich habe Programm gemacht, um die Art der Proportionalität automatisch zu finden. Auf dem Testset habe
["myBot("+str(k)+")","Randombot","Greedybot","Every50","Jack","grim_reaper","Averager","mess"]
ich den neuen Wert gefunden.quelle
(reap/self.mult**self.waittime)**-0.810192835
es immer über 1 liegt, dh self.getRandom () ist niemals höher.self.obj
ist es da. Um einige Beispiele zu sehen, wie man es benutzt, schauen Sie sich einige andere Bots an, die es benutzen.Ziel
Meine Gewinnchancen mit Chaos sind jetzt so gut wie unbegrenzt, also ist es an der Zeit, alle anderen Bots auf so viele Arten wie möglich durcheinander zu bringen! :)
Dieser Bot funktioniert ähnlich wie Sniper. Immer wenn jemand erntet, wählt er ein zufälliges Ziel von dem, der erntet hat. Dann wartet es einfach, bis dieses Ziel fast wieder ernten kann und es abschneidet. Der Fokus ändert sich jedoch nicht - wenn du erst einmal ausgewählt und fixiert bist, kannst du nicht mehr entkommen :)
quelle
EveryN
Ich denke, es ist Zeit für meinen zweiten Bot kurz vor Ablauf der Frist.
Dieser Bot wird:
n
Runden geerntet hat , wobein
mit gerechnet wirdn = 3 + ceil(self.waittime / self.lenBots)
Code:
Ich programmiere nicht sehr oft in Python. Wenn Sie also Fehler sehen, lassen Sie es mich wissen.
quelle
subsequentRoundsWithoutReaps
bisroundsWithoutReaps
; Kleinbuchstaben mit Unterstrichen für den Methodennamen verwendet; und entfernte die Klammer bei den if-Anweisungen. Vielen Dank.prevReap
und angeschautlenBots
und solche und angenommene Variablen sind camelCase wie in Java. ;) Na ja, in jedem Fall sollte es trotzdem funktionieren. Die 2 statt 4 eingerückten Leerzeichen hätten wahrscheinlich einige Probleme verursacht, also danke so oder so.Laufend: Mein Projekt, T4T auf alle offenen KOTH zu erweitern.
Wie du mir so ich dir
Tit für n Tats
Kevin
Nur um dich auf Trab zu halten.
quelle
self.last
ist keine Sache, aber Sie könnenself.obj.last
eine Sache machen !. Wie auch immer, ich werde alle drei Bots für die Meme +1Durchschnittstyp
Ich habe mich von Averager inspirieren lassen und einen Bot erstellt, der im Durchschnitt berechnet, wie viele Runden es dauert, bis jemand erntet, und versucht, vorher eine Runde zu ernten.
quelle
HardCoded
Ja ist es.
Verwenden Sie einen vorab berechneten Durchschnitt für einen typischen Lauf, anstatt den Durchschnitt der vergangenen Ernten zu berechnen. Mit der Zeit wird es sowieso nicht besser.
quelle