Lassen Sie uns einen Reaper spielen - Closed for Submissions

13

HINWEIS : Der Gewinner dieses Wettbewerbs ist Jack !!!. Weitere Einsendungen werden nicht akzeptiert.

Hier ist der Chatroom für diese 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 selfzum Referenzieren von Klassenobjekten verwendet (wird später angezeigt). Der zweite ist der Reapaktuelle Wert der Ernte, den Sie verdienen würden, wenn Sie "ernten" würden. Das dritte ist prevReapeine 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 xdie 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 getRandommir bereitgestellte Funktion verwenden.

Sie finden den Controller im TIO-Link unten. Fügen Sie dazu den Namen Ihrer Funktion BotListals Zeichenfolge hinzu und fügen Sie die Funktion dem Code hinzu. Ändern Sie multiplierzu ändern , was die Reap von jedem Tick multipliziert wird, ändern winning_scoresich ändern , was notwendig Tor gegangen um das Spiel zu beenden, und ändern Sie waittimedie 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)

Don Tausend
quelle
Nehmen wir an, zwei Bots ernten gleichzeitig und derjenige mit der längsten Wartezeit gewinnt. Wird der andere Bot auch seine Wartezeit aktivieren, obwohl er diese Runde nicht wirklich ernten konnte und im Grunde genommen seine "Ernte" verschwendet? Und was passiert, wenn zwei Bots zur gleichen Zeit mit der gleichen Wartezeit ernten?
Kevin Cruijssen
1
Darf man benutzen len(BotList)?
Renzeee
1
@Renzeee Ooo hat nicht darüber nachgedacht! Ich werde eine schnelle Änderung vornehmen.
Don Thousand
1
@ Renzeee Oh, das ist sicherlich etwas Nützliches. Könnte einen zweiten Bot machen, der meinem Every 50 ähnelt, aber mit tatsächlichen Berechnungen im Bot selbst, anstelle dessen, was ich in meiner Beschreibung basierend auf 25Bots 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?
Kevin Cruijssen
1
@ Rushabh Mehta Gotcha, ich werde es unterlassen. Ich habe b / c gefragt, ob ich die Punkte und Wartezeiten anderer Bots unabhängig verfolgen möchte, um sie zu erbeuten, und ich bin faul. :)
Triggernometrie

Antworten:

9

Unentschlossenes nervöses Durcheinander

def mess(self, Reap, prevReap):
    if not hasattr(self.obj, "start"):
            self.obj.start = False
    if self.time < self.waittime:
        return 0
    if self.points + Reap >= self.win:
            return 1
    if Reap >= self.waittime / (self.lenBots + 2):
        self.obj.start = True
    if self.obj.start:
        return 1 if self.getRandom() > 0.2 else 0
    return 1 if self.getRandom() > 0.8 else 0

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.

Quintec
quelle
Netter Bot +1. Ich werde es gleich genauer betrachten. Nehmen Sie am Chat teil, wenn Sie es noch nicht getan haben
Don Thousand
@ RushabhMehta Jetzt mit weniger Unentschlossenheit; p
Quintec
Ich werde Ihre Änderungen hinzufügen, wenn ich kann!
Don Thousand
9

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 das Ernten dazu führen würde, dass es gewinnt, dann ernte.
  • Wenn niemand> = 70% der Gewinnpunktzahl ist:

    • Wenn sich alle anderen in ihrer Abklingzeit befinden, warten Sie bis zum letzten möglichen Moment, um zu ernten.
    • Wenn jemand anderes gewinnen würde, indem er den aktuellen Wert erntet, und er jetzt aktiv ist oder in der nächsten Runde aktiv wäre, ernten Sie.
    • 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.
    • Andernfalls ernten Sie 25% der Zeit (im Wesentlichen, um sicherzustellen, dass dieser Bot MANCHMAL erntet, für den Fall, dass etwas Seltsames passiert, als ob jeder mehrere Runden wartet).
  • Wenn jemand> = 70% der Siegpunktzahl ist:

    • Wenn Sniper einen Tiebreaker gewinnen kann und die nächste Runde über dem durchschnittlichen Reap-Wert des Gegners mit der höchsten Punktzahl liegt, ernten Sie
    • Wenn der Gegner mit der höchsten Punktzahl in der nächsten Runde seine Abklingzeit verlässt, ernte.
def Sniper(self, Reap, prevReap):
    # initialize opponents array
    if not hasattr(self.obj, "opponents"):
        self.obj.opponents = {}

    # initialize previous Reap value
    if not hasattr(self.obj, "lastReap"):
        self.obj.lastReap = 0

    # increment all stored wait times to see who will be "active" this turn
    for opponent in self.obj.opponents:
        self.obj.opponents[opponent]["time"] += 1

    # update opponents array
    for opponent in prevReap:
        # don't track yourself, since you're not an opponent
        if opponent != "Sniper":
            # initialize opponent
            if opponent not in self.obj.opponents:
                self.obj.opponents[opponent] = {"time": 0, "points": 0, "num_reaps": 0, "avg": 0}
            self.obj.opponents[opponent]["time"] = 0
            self.obj.opponents[opponent]["points"] += self.obj.lastReap
            self.obj.opponents[opponent]["num_reaps"] += 1
            self.obj.opponents[opponent]["avg"] = self.obj.opponents[opponent]["points"] / self.obj.opponents[opponent]["num_reaps"]

    # done "assigning" points for last round, update lastReap
    self.obj.lastReap = Reap

    # get current 1st place(s) (excluding yourself)
    winner = "" if len(self.obj.opponents) == 0 else max(self.obj.opponents, key=lambda opponent:self.obj.opponents[opponent]["points"])

    # you are ready now
    if self.time >= self.waittime:
        # current Reap is sufficient for you to win
        if self.points + Reap >= self.win:
            return 1

        if (
                # a 1st place exists
                winner != ''
                # if current 1st place is close to winning
                and self.obj.opponents[winner]["points"] / self.win >= .7
        ):
            if (
                    # next round's Reap value will be above opponent's average Reap
                    (Reap * self.mult >= self.obj.opponents[winner]["avg"])
                    # we have been waiting at least as long as our opponent (tiebreaker)
                    and self.time >= self.obj.opponents[winner]["time"]
            ):
                return 1

                # current 1st place opponent will be active next round
            if self.obj.opponents[winner]["time"] + 1 >= self.waittime:
                return 1

        else:
            if (
                    # everyone is waiting for their cooldown
                    all(values["time"] < self.waittime for key, values in self.obj.opponents.items())
                    # and we're tracking ALL opponents
                    and len(self.obj.opponents) == self.lenBots - 1
                    # at least one person will be ready next turn
                    and any(values["time"] + 1 >= self.waittime for key, values in self.obj.opponents.items())
            ):
                return 1

            if (
                    # opponent will be active next round
                    any( (values["time"] + 1 >= self.waittime)
                         # current Reap value would allow opponent to win
                         and (values["points"] + Reap >= self.win) for key, values in self.obj.opponents.items())
            ):
                return 1

            if (
                    # a 1st place exists
                    winner != ''
                    # current 1st place opponent will be active next round
                    and (self.obj.opponents[winner]["time"] + 1 >= self.waittime)
                    # next round's Reap value will be above their average Reap
                    and (Reap * self.mult >= self.obj.opponents[winner]["avg"])

            ):
                return 1

            # # at least half of opponents are waiting for their cooldown
            # if sum(values["time"] < self.waittime for key, values in self.obj.opponents.items()) >= (self.lenBots - 1) / 2:
            #     return 1

            # 25% of the time
            if self.getRandom() <= .25:
                return 1

    # default return: do not snipe
    return 0

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!)

def Bored(self, Reap, prevReap):
    # if this is the first round, determine your fav number
    if not hasattr(self.obj, "fav_int"):
        r = 0

        while r == 0:
            # 4 bits are required to code 1-9 (0b1001)
            for i in range(0, 4):
                # flip a coin. Puts a 1 in this bit place 50% of the time
                if self.getRandom() >= .50:
                    r += 2**i
            # if your random bit assigning has produced a number outside the range 1-9, try again
            if not (0 < r < 10):
                r = 0

        self.obj.fav_int = r

    # you are ready now
    if self.time >= self.waittime:
        # current Reap is sufficient for you to win
        if self.points + Reap >= self.win:
            return 1
        # do you like this value?
        if str(self.obj.fav_int) in str(Reap):
            return 1
        # do you like your wait time?
        if self.time % int(self.obj.fav_int) == 0:
            return 1

    # default return: do not reap
    return 0
Triggernometrie
quelle
Netter Bot! +1. Es wird interessant sein zu sehen, wie das funktioniert.
Don Thousand
1
Ich denke du solltest self.obj.opponents[opponent]["time"] += 1in 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.
Renzeee
@Triggernometry Du solltest dem Chat beitreten. Überprüfen Sie auch die von mir veröffentlichten Änderungen. Bitte stellen Sie sicher, dass die Änderungen, die ich an Ihrem Bot vorgenommen habe, korrekt sind.
Don Thousand
7

Jack

Dies ist ein einfacher Bot mit 4 Regeln:

  • Nicht ernten, wenn es nichts tut
  • Immer ernten, wenn das Ernten uns gewinnen lässt
  • Auch ernten, wenn nicht für 3 Zecken geerntet wurde
  • Sonst nichts tun

Ich habe die 3 Ticks gegenüber den aktuell vorhandenen Bots optimiert (Sniper, grim_reaper, Every50, mess, BetterRandom, Averager, einige mehr).

def Jack(self, Reap, prevReap):
    if self.time < self.waittime:
        return 0
    if self.win - self.points < Reap:
        return 1
    if self.mult ** 3 <= Reap:
        return 1
    return 0

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.

Renzeee
quelle
5

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.4und waittime = floor(1.5*25) = 37. Da das um Reapbeginnt 1, wird es so aufgehen:

Round: 1  2    3     4      5      6      7      8       9       10      11      12      13      14      15       16       17       18       19       20       etc.
Reap:  1  1.4  1.96  2.744  ~3.84  ~5.39  ~7.53  ~10.54  ~14.76  ~20.66  ~28.92  ~40.50  ~56.69  ~79.37  ~111.12  ~155.57  ~217.79  ~304.91  ~426.88  ~597.63  etc.

Wie Sie sehen können, erreicht es nach 13 Ticks über 50. Da die Reapwird jedes Mal , wenn ein Bot erntet auf 1 zurückgesetzt und die waittimefü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 Beispiel GreedyBot, die, sobald ihr ernten waittimeheiß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 ..

def Every50(self, Reap, prevReap):
  return int(Reap > 50)

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 das waittimenatürlich auch viel niedriger, so dass es sogar GreedyBotrecht leicht sein kann, von diesem Bot zu gewinnen, wenn der waittimeniedrig genug ist.

Hoffentlich werden mehr Leute viel mehr Bots hinzufügen. ; p

Kevin Cruijssen
quelle
def Every49(self, Reap, prevReap): return Reap > 49 Deine Bewegung.
Quintec
@Quintec Hehe. Mit 25 Bots im Spiel würde dies bedeuten, dass es immer noch der 13. Tick ist und wir beide den Reap gewinnen. Es macht mir also nichts aus, den Sieg mit Ihnen zu teilen, lol. ; p
Kevin Cruijssen
Vielleicht möchten Sie intdie Ungleichung umgehen, da 1 der eigentliche Befehl ist
Don Thousand
@ Quintec Ich bin mir dessen bewusst, dass ich Spaß mache, aber ich werde keine 1-up- oder doppelten Bots zulassen
Don Thousand
@RushabhMehta Ich programmiere nicht sehr oft in Python, also habe ich schon gezweifelt, ob ich die Besetzung hinzufügen sollte, um das Trueexplizit zu machen 1. Es stellte sich heraus, dass der True == 1Scheck Truefür meinen Bot immer noch zurückkehren würde, wenn er zu den Listen ReapersIhrer nextFunktion hinzugefügt würde, aber ich habe die Besetzung trotzdem zu int hinzugefügt, wie Sie vorgeschlagen haben.
Kevin Cruijssen
5

Averager

def Averager(self,Reap,prevReap):
    returner = 0
    if not hasattr(self.obj,"last"):
        self.obj.last = Reap
        self.obj.total = 0
        self.obj.count = 0
        returner = 1
    else:
        if len(prevReap) > 0:
            self.obj.total += self.obj.last
            self.obj.count += 1
        self.obj.last = Reap
    if self.obj.count > 0 and Reap > self.obj.total / self.obj.count:
        returner = 1
    return returner

Dieser Bot versucht immer dann zu ernten, wenn der aktuelle Erntewert über dem durchschnittlichen Erntewert liegt.

Jo.
quelle
Sehr schöner Bot! +1
Don Thousand
Ich bin beide sehr verärgert und beeindruckt, dass ein so einfacher Algorithmus alle so handlich schlägt. Gut gemacht!
Triggernometrie
3

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.

def grim_reaper(self, Reap, prevReap):
    if self.obj == None:
        self.obj = {}
        self.obj["reaps"] = []
        self.obj["prev"] = 1
        self.obj["players"] = {i:0 for i in range(math.ceil(self.waittime / 1.5))}
    if Reap == 1 and len(prevReap) > 0:
        self.obj["reaps"].append(self.obj["prev"])
        for player in prevReap:
            self.obj["players"][player] = 0

    retvalue = 0
    if (len(self.obj["reaps"]) > 0 
         and Reap > sum(self.obj["reaps"]) / len(self.obj["reaps"]) * 3. / 4.
         and sum([self.time >= i for i in self.obj["players"].values()]) >= len(self.obj["players"].values()) * 3 / 4):
        retvalue = 1

    for player in self.obj["players"]:
        self.obj["players"][player] += 1
    self.obj["prev"] = Reap
    return retvalue

Bearbeiten: Einige peinliche Syntaxfehler wurden behoben.

Probieren Sie es online

Zachary Cotton
quelle
1
Sie sollten self.obj.reapsanstelle von self.reapsund self.objanstelle von self.objectund prevReapanstelle von prevLeapund add () nach self.obj.players.valueszweimal verwenden. Und ich denke, self.obj.reaps = []wird nicht funktionieren, wenn self.objes 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 den self.objFall, dass es noch nicht existiert, wird Ihr Code für mich kompiliert.
Renzeee
@ ZacharyColton Sie müssen Mathe nicht importieren. Es ist bereits importiert
Don Thousand
@ RushabhMehta Ich habe class Object(object):[newline] passoben hinzugefügt und self.obj = Object()in der verwendet if not hasattr(..)(wenn ich mich richtig erinnere).
Renzeee
@ Renzeee aha ic
Don Thousand
@ZacharyCotton Du solltest dich dem Chat anschließen.
Don Thousand
3

BetterRandom

def BetterRandom(self,reap,prevReap):
    return self.getRandom()>(reap/self.mult**self.waittime)**-0.810192835

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.5optimal 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.

fejfo
quelle
Ich werde bald einige neue Statistiken mit Ihrem Bot hinzufügen
Don Thousand
1
Es sieht so aus, als ob (reap/self.mult**self.waittime)**-0.810192835es immer über 1 liegt, dh self.getRandom () ist niemals höher.
Renzeee
@fejfo Du darfst auch Daten aus früheren Runden verwenden. Dafür self.objist es da. Um einige Beispiele zu sehen, wie man es benutzt, schauen Sie sich einige andere Bots an, die es benutzen.
Don Thousand
3

Ziel

def target(self,Reap,prevReap):
    if not hasattr(self.obj, "target_time"):
        self.obj.target_time = -1
        self.obj.targeting = False
        self.obj.target = None
    if self.obj.target_time >= 0:
        self.obj.target_time += 1

    if self.time < self.waittime:
            return 0
    if self.points + Reap >= self.win:
        return 1
    if len(prevReap) > 0:
        if not self.obj.targeting:
            self.obj.target_time = 0
            self.obj.target = prevReap[int(self.getRandom() * len(prevReap))]
            self.obj.targeting = True
    if self.waittime <= self.obj.target_time + 1:
        self.obj.targeting = False
        self.obj.target = None
        self.obj.target_time = -1
        return 1
    return 0

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 :)

Quintec
quelle
2

EveryN

Ich denke, es ist Zeit für meinen zweiten Bot kurz vor Ablauf der Frist.

Dieser Bot wird:

  • Überspringen, wenn es noch in der Wartezeit für die letzte Ernte ist
  • Ernte, wenn es gewinnen kann
  • Ernte, wenn niemand für mindestens nRunden geerntet hat , wobei nmit gerechnet wirdn = 3 + ceil(self.waittime / self.lenBots)

Code:

def every_n(self, Reap, prevReap):
    # Initialize obj fields
    if not hasattr(self.obj, "roundsWithoutReaps"):
        self.obj.roundsWithoutReaps = 0

    # Increase the roundsWithoutReaps if no bots reaped last round
    if len(prevReap) < 1:
        self.obj.roundsWithoutReaps += 1
    else
        self.obj.roundsWithoutReaps = 0

    # Skip if you're still in your waiting time
    if self.time < self.waittime:
        return 0
    # Reap if you can win
    if self.win - self.points < Reap:
        return 1

    # i.e. 25 bots: 3 + ceil(37 / 25) = 5
    n = 3 + math.ceil(self.waittime / self.lenBots)

    # Only reap when no bots have reaped for at least `n` rounds
    if self.obj.roundsWithoutReaps >= n:
        self.obj.roundsWithoutReaps = 0
        return 1

    return 0

Ich programmiere nicht sehr oft in Python. Wenn Sie also Fehler sehen, lassen Sie es mich wissen.

Kevin Cruijssen
quelle
Holy Long Variablenname. (Auch PEP: python.org/dev/peps/pep-0008 )
Quintec
@Quintec Der Einzug mit zwei Leerzeichen wurde in 4 geändert. verkürzt das subsequentRoundsWithoutReapsbis roundsWithoutReaps; Kleinbuchstaben mit Unterstrichen für den Methodennamen verwendet; und entfernte die Klammer bei den if-Anweisungen. Vielen Dank.
Kevin Cruijssen
Kein Problem! (Technisch sollte es rounds_without_reaps sein, aber das ist nicht wirklich ein Problem, da diese Herausforderung auch mixedCamelCase verwendet, so dass es nicht wirklich wichtig ist)
Quintec
@Quintec Ah ok. Ich habe mir das prevReapund angeschaut lenBotsund 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.
Kevin Cruijssen
2

Laufend: Mein Projekt, T4T auf alle offenen KOTH zu erweitern.

Wie du mir so ich dir

def t4t(self, r, p):
    if(not hasattr(self.obj,"last")): self.obj.last = self.win
    if(p):
        self.obj.last = r
        return 0

    # The usual checks
    if self.time < self.waittime:
        return 0
    if self.points + r >= self.win:
        return 1

    if(r >= self.obj.last):
        return 1

Tit für n Tats

def t4nt(self, r, p):
    n = 5 # Subject to change
    if(not hasattr(self.obj,"last")): self.obj.last = [self.win]*n

    if(p):
        self.obj.last.append(r)
        self.obj.last.pop(0)
        return 0

    # The usual checks
    if(self.time < self.waittime):
        return 0
    if(self.points + r >= self.win):
        return 1

    if(r >= self.obj.last[0]):
        return 1

Kevin

Nur um dich auf Trab zu halten.

def kevin(just, a, joke):
    return 0
SIGSTACKFAULT
quelle
Denken Sie daran, self.lastist keine Sache, aber Sie können self.obj.lasteine Sache machen !. Wie auch immer, ich werde alle drei Bots für die Meme +1
Don Thousand
Ja, ich bin ein Idiot. Fest.
SIGSTACKFAULT
@ RushabhMehta Ich bin gerade durchgegangen und habe sie tatsächlich arbeiten lassen. Bitte bearbeiten.
SIGSTACKFAULT
hört sich gut an! Tritt dem GC bei, ich werde dort einige Teilergebnisse veröffentlichen
Don Thousand
1

Durchschnittstyp

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.

def average_joe(self, Reap, prevReap):

    if not hasattr(self.obj, "average_turns"):
        self.obj.turns_since_reap = 1
        self.obj.total_turns = 0
        self.obj.total_reaps = 0
        return 1

    if len(prevReap) > 0:
        self.obj.total_turns = self.obj.total_turns + self.obj.turns_since_reap
        self.obj.total_reaps += 1
        self.obj.turns_since_reap = 0
    else:
        self.obj.turns_since_reap += 1

    # Don't reap if you are in cooldown
    if self.time < self.waittime:
        return 0

    # Reap if you are going to win
    if self.win - self.points < Reap:
        return 1

    # Reap if it is one turn before average
    average_turns = self.obj.total_turns / self.obj.total_reaps

    if average_turns - 1 >= self.obj.turns_since_reap:
        return 1
    else:
        return 0
DobromirM
quelle
Ich werde das morgen hinzufügen.
Don Thousand
1

HardCoded

Ja ist es.

def HardCo(self,reap,prevReap):
    return reap > 2

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.

GB
quelle