Juguemos algunos Reaper - Cerrado por envíos

13

NOTA : ¡El ganador de esta competencia es Jack ! No se aceptarán más presentaciones.

Aquí está la sala de chat para este desafío del . Este es el primero, ¡así que estoy abierto a sugerencias!

Reaper es un concepto de juego desarrollado por el Arte de la resolución de problemas que implica paciencia y codicia. Después de modificar el juego para que se ajuste a un concurso de estilo KOTH (Gracias a @NathanMerrill y @dzaima por sus sugerencias y mejoras), este es el desafío.

El juego funciona de la siguiente manera: tenemos un valor conocido como Reap que se multiplica por una constante dada en cada tic. Después de cada tick, cada bot tiene la opción de "cosechar", lo que significa agregar el valor actual de Reap a la puntuación de uno y reducir Reap a 1.

Sin embargo, hay un número fijo de ticks que un bot debe esperar entre "cosechas" y un número fijo de puntos necesarios para ganar el juego.

¿Suficientemente simple? Aquí están sus entradas:

I / O

Debe escribir una función en Python 3 que tome 3 entradas. El primero es self, usado para hacer referencia a objetos de clase (mostrados más adelante). El segundo es el Reapvalor actual de la cosecha que ganaría si fuera a "cosechar". El tercero es prevReapuna lista de los bots que cosecharon durante el tic anterior.

Otros objetos a los que puede acceder en su función:

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.

Usted DEBE no editar cualquiera de los contenidos de estos objetos, a excepción de self.obj.

Debe generar resultados 1para cosechar, y cualquier otra cosa (o nada) para no cosechar. Tenga en cuenta que si cosecha cuando no ha esperado suficientes tics, ignoraré el hecho de que ha elegido cosechar.

Reglas

Los parámetros que utilizaré son winning_score=10000, multiplier=1.6-(1.2/(1+sqrt(x))), waittime = floor(1.5*x)donde xes el número de los robots en el KOTH.

  • El juego termina cuando un jugador (o múltiples) alcanza el puntaje ganador.
  • Cuando varios bots piden cosechar a la vez, se les da prioridad a los bots que han esperado más tiempo (en caso de empate, los bots que han esperado el tiempo máximo tienen permitido cosechar y ganar puntos en el Reap)
  • Su bot no debe tomar más de 100 ms en promedio en 5 ticks.
  • Si quieres importar bibliotecas, ¡pregunta! Intentaré agregar cualquier biblioteca que pueda ejecutar en mi versión de escritorio de Python (las matemáticas ya están importadas: siéntase libre de usarlo)
  • Todas las lagunas estándar para KoTH, como los bot duplicados, los bots de 1 en 1, etc., están igualmente prohibidos.
  • Cualquier bot que use algún tipo de aleatoriedad debe usar la getRandomfunción que he proporcionado.

Puede encontrar el controlador en el enlace TIO a continuación. Para usarlo, agregue el nombre de su función BotListcomo una cadena y luego agregue la función al código. Modifique multiplierpara cambiar lo que el Reap se multiplica por cada tic, modifique winning_scorepara cambiar qué puntaje es necesario para finalizar el juego, y modifique waittimepara cambiar el número de ticks a esperar entre las cosechas.

Para su comodidad, aquí hay algunos bots de muestra (y bastante tontos). No se permitirán enviar bots similares a estos. Sin embargo, demuestran cómo funciona el controlador.

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

Para aquellos interesados, aquí está el controlador con las 15 presentaciones incorporadas: Pruébelo en línea

RESULTADOS FINALES

¡WOO ESTÁN FINALMENTE AQUÍ! Verifique el enlace TIO arriba para ver qué código usé para generar la clasificación final. Los resultados no son terriblemente interesantes. Durante las 1000 carreras que hice con diferentes semillas aleatorias, los resultados fueron

1000 wins - Jack
0 wins - everyone else

¡Felicitaciones al ganador de Bounty Jack! (también conocido como @Renzeee)

Don mil
fuente
Digamos que dos robots cosechan al mismo tiempo, y gana el que tiene el tiempo de espera más largo. ¿El otro bot también tendrá su tiempo de espera habilitado a pesar de que no fue capaz de cosechar esta ronda, básicamente desperdiciando su 'cosecha'? ¿Y qué sucede cuando dos bots cosechan al mismo tiempo, con el mismo tiempo de espera?
Kevin Cruijssen
1
Está permitido usar len(BotList)?
Renzeee
1
@Renzeee ¡Ooo no pensó en eso! Haré una modificación rápida.
Don Thousand
1
@Renzeee Oh, eso es ciertamente algo útil a tener en cuenta. Podría hacer un segundo bot similar a mi Cada 50, pero con cálculos reales en el bot en sí, en lugar de lo que hice en mi descripción basada en los 25bots en juego. Sin embargo, primero esperaré un poco para ver los bots de otras personas. Rushabh Mehta , ¿habrá una fecha límite / fecha final cuando se ejecutarán todos los bots y se determinará un ganador?
Kevin Cruijssen
1
@Rushabh Mehta Gotcha, me abstendré. Solo le pregunté a b / c que estaba rastreando de forma independiente las puntuaciones de otros bots y los tiempos de espera para atacarlos, y soy flojo. :)
Triggernometry

Respuestas:

9

Twitchy Mess indeciso

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

Este bot realiza primero las comprobaciones habituales (¿Puedo cosechar, puedo ganar?) Y luego busca un valor objetivo antes de cosechar. Sin embargo, es indeciso, por lo que una vez que alcanza el objetivo, se pregunta cuánto tiempo más puede esperar y no cosecha de inmediato. Además, es nervioso, por lo que accidentalmente puede "presionar el botón" y cosechar antes del objetivo.

Dato curioso: así es básicamente como juego a Reaper como humano.

Quintec
fuente
Buen bot +1. Lo examinaré más de cerca en un momento. Únete al chat si aún no lo has hecho
Don Thousand
@RushabhMehta Ahora con menos indecisión; p
Quintec
¡Agregaré tus cambios cuando pueda!
Don Thousand
9

Francotirador

Un bot alimentado por el rencor. Realiza un seguimiento de los tiempos de reutilización y puntajes del oponente. Intenta evitar que otros ganen. Prácticamente nunca gana, pero hace que el juego sea frustrante para otros.

EDITAR:

  • Si cosechar lo haría ganar, coseche.
  • Si nadie es> = 70% del puntaje ganador:

    • Si todos los demás están en enfriamiento, espere hasta el último momento posible para cosechar.
    • Si alguien más ganara cosechando el valor actual, y está activo ahora o estaría activo el próximo turno, coseche.
    • Si al menos la mitad de los otros usuarios están en enfriamiento, intente cosechar. Esto hace que sea difícil apuntar a oponentes específicos, por lo que se eliminó.
    • De lo contrario, coseche el 25% del tiempo (esencialmente para garantizar que este bot coseche A VECES, en caso de que ocurra algo extraño, como si todos estuvieran esperando varios turnos).
  • Si alguien ES> = 70% de la puntuación ganadora:

    • Si Sniper puede ganar un desempate, y la próxima ronda estaría por encima del valor promedio de Cosecha para el oponente con la puntuación más alta, cosecha
    • Si el oponente con la puntuación más alta dejará su tiempo de reutilización el próximo turno, cosecha.
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

aburrido

Solo por diversión, este bot fue traído por un amigo y en realidad no quiere estar aquí. Lanzan un d16 hasta que obtienen un número en 1-9, luego intentan cosechar cada vez que un número contiene el dígito elegido. (¡Ir a buscar un d10 interrumpiría el juego, lo cual es grosero, y 0 es demasiado fácil!)

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
Triggernometry
fuente
Buen bot! +1. Será interesante ver cómo funciona esto.
Don Thousand
1
Creo que deberías usarlo self.obj.opponents[opponent]["time"] += 1en el primer for-loop y self.obj.lastReapal final del segundo for-loop. Además de eso, buenas ideas. Tengo curiosidad por saber cómo funcionaría contra muchos otros bots. Cuando estoy usando muchos bots codiciosos y aleatorios, solo cosecharé lo antes posible porque la mayoría de las veces la mitad de los bots no pueden cosechar. Pero, por supuesto, esos no son competidores realistas.
Renzeee
@Triggernometry Deberías unirte al chat. Además, verifique las ediciones que he publicado. Asegúrese de que los cambios que hice en su bot sean correctos.
Don Thousand
7

Jack

Este es un bot simple con 4 reglas:

  • No coseche cuando no hace nada
  • Siempre cosecha cuando cosechar nos permite ganar
  • También coseche cuando no haya cosechado 3 tics
  • De lo contrario no hagas nada

He optimizado los 3 ticks en comparación con los bots existentes actuales (Sniper, grim_reaper, Every50, mess, BetterRandom, Averager, algunos más).

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

Intenté quedarme con mi solución anterior (5 ticks) pero también cosecho si no ha cosechado más de X ticks, y luego cosecho después de que se hayan pasado menos ticks durante la no cosecha (es decir, 5, si esperó más que yo) .waittime + 5, también cosechará si no ha cosechado 4 ticks). Pero esto no mejoró solo siempre cosechando después de 4 ticks en lugar de 5.

Renzeee
fuente
5

Cada 50

Estos bots cosecharán cada vez que la Reapcantidad sea superior a 50.

¿Por qué 50?

Si supongo que habrá 25 bots en juego, significa que multiplier = 1.6-(1.2/(1+sqrt(25))) = 1.4y el waittime = floor(1.5*25) = 37. Desde el Reapcomienzo en 1, subirá así:

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.

Como puede ver, alcanza más de 50 después de 13 ticks. Dado que Reapse restablecerá a 1 cada vez que un bot cosecha, y waittimepara un bot que cosecha es 37, la probabilidad de que un bot coseche más temprano que tarde es bastante alta, especialmente con bots similares al ejemplo GreedyBot, que cosecharán tan pronto como waittimesea ​​posible. Disponible de nuevo. Al principio quería hacer 200, que es el 17 ° tic, algo en el medio de los 37 tics de tiempo de espera, pero con la suposición de que hay 25 bots en juego, existe una gran posibilidad de que alguien más me arrebata Reapantes que yo. Así que lo bajé a 50. Todavía es un buen número redondeado, pero especialmente porque es el tick 13 (con 25 bots), y 13 y 'cosechar' también encajan un poco en el mismo género 'malvado'.

Código:

El código es trivial risible.

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

Notas:

Este bot es bastante malo con poca cantidad de bots en juego. Por ahora lo dejaré, y podría hacer un mejor bot calculando el mejor momento para hacerlo Reap. Con una cantidad extremadamente baja de bots en juego, waittimees mucho más bajo, por supuesto, por lo que incluso GreedyBotpodría ganar fácilmente con este bot si waittimees lo suficientemente bajo.

Esperemos que más personas agreguen muchos más bots. ;pag

Kevin Cruijssen
fuente
def Every49(self, Reap, prevReap): return Reap > 49 Su movimiento.
Quintec
@Quintec Hehe. Con 25 bots en juego, significaría que sigue siendo el tick 13 y ambos ganamos el Reap, así que no me importa compartir la victoria contigo, jajaja. ; p
Kevin Cruijssen
Es posible que desee intevitar la desigualdad, ya que 1 es el verdadero comando
Don Thousand
@Quintec, sé que estás bromeando, pero no permitiré bots de 1 o más duplicados
Don Thousand
@RushabhMehta No programo en Python muy a menudo, por lo que ya dudaba si debería agregar el elenco para que sea Trueexplícito 1. Pensé que la True == 1verificación aún regresaría Truepara mi bot agregándolo a las listas de Reapersen su nextfunción, pero agregué el reparto a int de todos modos como usted sugirió.
Kevin Cruijssen
5

Promediador

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

Este bot intenta cosechar cada vez que el valor actual de Reap está por encima del valor promedio cosechado.

Jo
fuente
Muy bonito bot! +1
Don Thousand
Estoy extremadamente molesto e impresionado porque un algoritmo tan simple supera a todos tan fácilmente. ¡Gran trabajo!
Triggernometry
3

Parca

Este bot mantiene un promedio de los valores de todas las cosechas anteriores, así como el tiempo que cada bot ha estado esperando. Cosecha cuando ha estado esperando más de 3/4 de los otros bots y la cosecha es al menos 3/4 del tamaño de la cosecha promedio vista hasta ahora. El objetivo es obtener muchas cosechas de bajo riesgo de tamaño razonable.

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

Editar: se corrigieron algunos errores de sintaxis embarazosos.

Pruébalo en línea

Algodón Zachary
fuente
1
Debe usar en self.obj.reapslugar de self.reapsy en self.objlugar de self.objecty en prevReaplugar de prevLeapy agregar () después de self.obj.players.valuesdos veces. Y creo self.obj.reaps = []que no funcionará a menos que self.objsea ​​un objeto. No estoy completamente seguro de si todo sigue funcionando según lo previsto y si todo lo que dije es cierto, pero después de estos cambios y el uso de un Objeto ficticio para self.objcuando aún no existe, su código se compila para mí.
Renzeee
@ZacharyColton No es necesario importar matemáticas. Ya está importado
Don Thousand
@RushabhMehta Agregué class Object(object):[nueva línea] passen la parte superior y lo usé self.obj = Object()en if not hasattr(..)(si no recuerdo mal).
Renzeee
@Renzeee aha ic
Don Thousand
@ZacharyCotton Deberías unirte al chat.
Don Thousand
3

BetterRandom

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

El bot se basa en la suposición de que la posibilidad de cosechar debe ser proporcional al tamaño de cosecha porque un punto es un punto, sin importar cuándo se haya obtenido. Siempre hay una pequeña posibilidad de cosechar, esto mantiene el comportamiento explotable. Primero pensé que sería directamente proporcional y asumí que la constante de proporcionalidad debería estar alrededor 1/mult^waittime(la cosecha máxima suponiendo que al menos un bot juega codicioso) después de ejecutar algunas simulaciones, descubrí que esta era realmente la constante óptima. Pero Random todavía superó al bot, así que concluí que la relación no era directamente proporcional y agregué una constante para calcular cuál era la relación. Después de algunas simulaciones, descubrí que contra mi conjunto de pruebas de bots -1.5era óptimo. Esto en realidad corresponde a una relación inversamente proporcional entre la probabilidad de cosecha yreap*sqrt(reap)lo cual es sorprendente Así que sospecho que esto depende en gran medida de los bots específicos, por lo que sería mejor una versión de este bot que calcule k mientras se juega. (Pero no sé si puede usar datos de rondas anteriores).

EDITAR: Hice un programa para encontrar el tipo de proporcionalidad automáticamente. En el conjunto de prueba ["myBot("+str(k)+")","Randombot","Greedybot","Every50","Jack","grim_reaper","Averager","mess"]encontré el nuevo valor.

fejfo
fuente
pronto agregaré algunas estadísticas nuevas usando tu bot
Don Thousand
1
Parece que (reap/self.mult**self.waittime)**-0.810192835siempre está por encima de 1, es decir, self.getRandom () nunca es más alto.
Renzeee
@fejfo también puede usar datos de rondas anteriores. Para eso self.objes eso . Para ver algunos ejemplos sobre cómo usarlo, mira algunos otros bots que lo están usando.
Don Thousand
3

Objetivo

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

Mis posibilidades de ganar con lío son casi nulas ahora, ¡así que es hora de estropear a todos los demás bots de la mayor manera posible! :)

Este bot funciona de manera similar al francotirador. Cada vez que alguien cosecha, elige un objetivo aleatorio de quien haya cosechado. Luego, simplemente espera hasta que ese objetivo casi pueda cosechar nuevamente y lo golpea. Sin embargo, no cambia el enfoque: una vez que ha sido elegido y bloqueado, no puede escapar :)

Quintec
fuente
2

EveryN

Supongo que es hora de mi segundo bot justo antes de la fecha límite.

Este bot:

  • Saltar cuando todavía está en su tiempo de espera para la última cosecha
  • Cosecha cuando puede ganar
  • Coseche cuando nadie cosechó al menos nrondas, donde nse calcula conn = 3 + ceil(self.waittime / self.lenBots)

Código:

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

No programo en Python muy a menudo, así que si ves algún error avísame.

Kevin Cruijssen
fuente
Santo nombre largo variable. (También, PEP: python.org/dev/peps/pep-0008 )
Quintec
@Quintec Cambió la sangría de 2 espacios a 4; acortado el subsequentRoundsWithoutReapsa roundsWithoutReaps; usado minúsculas con guiones bajos para el nombre del método; y eliminó el paréntesis en las declaraciones if. Gracias.
Kevin Cruijssen
¡No hay problema! (Técnicamente debería ser rounds_without_reaps, pero eso no es realmente un problema ya que este desafío también usa MixedCamelCase, por lo que realmente no importa)
Quintec
@Quintec Ah ok. Miré el prevReapand lenBotsy such y las variables asumidas son camelCase como en Java. ;) Ah bueno, cualquiera que sea el caso que usemos, debería funcionar de todos modos. Sin embargo, los 2 espacios en lugar de los 4 con sangría probablemente habrían causado algunos problemas, así que gracias de cualquier manera.
Kevin Cruijssen
2

En curso: mi proyecto para extender T4T a cada KOTH abierto.

Tal para cual

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

Teta para n tatuajes

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

Solo para mantenerte alerta.

def kevin(just, a, joke):
    return 0
SIGSTACKFAULT
fuente
Asegúrate de recordar, self.lastno es una cosa, ¡pero puedes hacer self.obj.lastuna cosa! De todos modos, agregaré los tres bots para los memes +1
Don Thousand
Sí, soy un idiota. Fijo.
SIGSTACKFAULT
@RushabhMehta Simplemente pasó y los hizo funcionar. Por favor editar.
SIGSTACKFAULT
¡suena bien! Únase al GC, publicaré algunos resultados parciales allí
Don Thousand el
1

Joe promedio

Me inspiré en Averager y creé un bot que calcula en promedio cuántos turnos toma antes de que alguien coseche e intente cosechar un turno antes de eso.

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
fuente
Agregaré esto mañana.
Don Thousand
1

HardCoded

Sí lo es.

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

En lugar de promediar en las cosechas pasadas, use un promedio precalculado en una carrera típica. No va a mejorar con el tiempo de todos modos.

GB
fuente