Vamos tocar Reaper - Fechado para envios

13

NOTA : O vencedor desta competição é Jack !!!. Não serão aceitas mais submissões.

Aqui está a sala de bate-papo para esse desafio do . Este é o meu primeiro, então estou aberto a sugestões!

Reaper é um conceito de jogo desenvolvido pela Art of Problem Solving, que envolve paciência e ganância. Depois de modificar o jogo para se encaixar em um concurso de estilo KOTH (obrigado a @NathanMerrill e @dzaima por suas sugestões e melhorias), aqui está o desafio.

O jogo funciona da seguinte maneira: temos um valor conhecido como Reap que se multiplica por uma constante constante a cada tick. Após cada tick, cada bot tem a opção de "colher", o que significa adicionar o valor atual de Reap à pontuação de uma pessoa e reduzir Reap para 1.

No entanto, há um número fixo de ticks que um bot deve esperar entre as "colheitas" e um número fixo de pontos necessários para vencer o jogo.

Simples o suficiente? Aqui estão suas entradas:

I / O

Você deve escrever uma função no Python 3 que aceite 3 entradas. A primeira é selfusada para referenciar objetos de classe (mostrados mais tarde). O segundo é o Reapvalor atual do Reap que você ganharia se quisesse "colher". O terceiro é prevReapuma lista dos bots que foram coletados durante o tick anterior.

Outros objetos que você pode acessar em sua função:

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.

Você NÃO deve editar nenhum conteúdo desses objetos, exceto self.obj.

Você deve produzir 1para colher e qualquer outra coisa (ou nada) para não colher. Observe que, se você colher quando não tiver esperado carrapatos suficientes, ignorarei o fato de que você escolheu colher.

Regras

Os parâmetros que serão usando são winning_score=10000, multiplier=1.6-(1.2/(1+sqrt(x))), waittime = floor(1.5*x)onde xestá o número de bots no KOTH.

  • O jogo termina quando um jogador (ou vários) atinge a pontuação vencedora.
  • Quando vários bots pedem para colher de uma só vez, é dada prioridade aos bots que esperaram mais tempo (em caso de empate, os bots que esperaram o tempo máximo permitidos para colher e ganhar pontos no Reap)
  • Seu bot não deve demorar mais de 100 ms, em média, em 5 ticks.
  • Se você deseja importar bibliotecas, pergunte! Vou tentar adicionar quaisquer bibliotecas que eu possa executar na minha versão desktop do Python (a matemática já foi importada: fique à vontade para usá-lo)
  • Todas as brechas padrão para KoTHs, como bots duplicados, bots 1-up, etc., são igualmente proibidas.
  • Qualquer robô que use qualquer tipo de aleatoriedade deve usar a getRandomfunção que forneci.

Você pode encontrar o controlador no link TIO abaixo. Para usá-lo, adicione o nome da sua função BotListcomo uma string e adicione a função ao código. Modifique multiplierpara alterar o que o Reap é multiplicado por cada tick, modifique winning_scorepara alterar a pontuação necessária para finalizar o jogo e modifique waittimepara alterar o número de ticks a esperar entre as colheitas.

Para sua conveniência, aqui estão alguns bots de amostra (e bastante tolos). Enviar bots semelhantes a estes não será permitido. No entanto, eles demonstram como o controlador funciona.

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 os interessados, aqui está o Controlador com as 15 submissões incorporadas: Experimente Online

RESULTADOS FINAIS

WOO ELES ESTÃO FINALMENTE AQUI! Verifique o link do TIO acima para ver qual código eu usei para gerar as classificações finais. Os resultados não são terrivelmente interessantes. Nas 1000 corridas que fiz com diferentes sementes aleatórias, os resultados foram

1000 wins - Jack
0 wins - everyone else

Parabéns ao vencedor do Bounty Jack !! (tcp @Renzeee)

Don Mil
fonte
Digamos que dois bots colhem ao mesmo tempo, e aquele com o maior tempo de espera vence. O outro bot também terá seu tempo de espera ativado, apesar de não ter conseguido colher essa rodada, basicamente desperdiçando sua 'ceifeira'? E o que acontece quando dois bots colhem ao mesmo tempo, com o mesmo tempo de espera?
Kevin Cruijssen 13/09/18
1
É permitido usar len(BotList)?
Renzeee 13/09/18
1
@Renzeee Ooo não pensou nisso! Eu vou fazer uma modificação rápida.
13598 Don Thousand
1
@Renzeee Oh, isso certamente é algo útil a considerar. Pode fazer um segundo bot semelhante ao meu Every 50, mas com cálculos reais no próprio bot, em vez do que eu fiz na minha descrição com base em 25bots em jogo. No entanto, primeiro espere um pouco para ver os robôs de outras pessoas. Rushabh Mehta , haverá um prazo / data final em que todos os bots serão executados e um vencedor será determinado?
Kevin Cruijssen
1
@Rushabh Mehta Gotcha, vou me abster. Eu apenas perguntei a b / c que eu estava rastreando de forma independente as pontuações e as esperas de outros bots, a fim de roubá-las, e eu sou preguiçoso. :)
Triggernometry

Respostas:

9

Confusão Twitchy Indecisa

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 faz as verificações habituais primeiro (Posso colher, posso ganhar?) E, em seguida, procura um valor-alvo antes de colher. No entanto, é indeciso; portanto, depois de atingir o alvo, ele se pergunta quanto tempo pode esperar e não colhe imediatamente. Além disso, é um tremor, por isso pode "acidentalmente apertar o botão" e colher antes do alvo.

Curiosidade: é basicamente assim que eu jogo ceifador como humano.

Quintec
fonte
Bom bot +1. Vou dar uma olhada mais de perto daqui a pouco. Entre no bate-papo, se você ainda não o fez #
Don Thousand
@RushabhMehta Agora com menos indecisão; p
Quintec 18/09/18
Adicionarei suas alterações quando puder!
Don Thousand
9

Franco atirador

Um bot alimentado por despeito. Mantém o controle das recargas e pontuações do oponente. Tentativas de impedir que outras pessoas ganhem. Praticamente nunca vence, mas torna o jogo frustrante para os outros.

EDITAR:

  • Se a colheita for um sucesso, colha.
  • Se ninguém tiver> = 70% da pontuação vencedora:

    • Se todos os outros estiverem em espera, espere até o último momento possível para colher.
    • Se mais alguém ganhar, colhendo o valor atual, e eles estão ativos agora ou no próximo turno, colham.
    • Se pelo menos metade dos outros usuários estiver em sua recarga, tente colher. Isso dificulta o direcionamento de oponentes específicos e, portanto, foi removido.
    • Caso contrário, colha 25% do tempo (essencialmente para garantir que esse bot colha ALGUMAS VEZES, caso algo estranho aconteça, como todo mundo está esperando várias vezes).
  • Se alguém for> = 70% da pontuação vencedora:

    • Se o Sniper puder vencer um desempate, e a próxima rodada estiver acima do valor médio de Reap para o oponente com maior pontuação, colha
    • Se o oponente com maior pontuação deixar sua recarga no próximo turno, colha.
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

Entediado

Apenas por diversão, esse bot foi trazido por um amigo e na verdade não quer estar aqui. Eles rolam um d16 até obter um número entre 1 e 9 e tentam colher sempre que um número contém o dígito escolhido. (Procurar um d10 atrapalharia o jogo, o que é rude e 0 é muito 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
Triggernometria
fonte
Bom bot! +1. Vai ser interessante ver como isso acontece.
Don Thousand
1
Eu acho que você deve usar self.obj.opponents[opponent]["time"] += 1no primeiro loop for e self.obj.lastReapno final do segundo for-loop. Além disso, boas idéias. Estou curioso para saber como isso funcionaria contra muitos outros bots. Quando eu estou usando muitos bots gananciosos e aleatórios, isso ocorre logo que possível, porque na maioria das vezes metade dos bots não pode colher. Mas é claro que esses não são concorrentes realistas.
Renzeee # 14/18
@Triggernometry Você deve participar do bate-papo. Além disso, verifique as edições que publiquei. Verifique se as alterações feitas no seu bot estão corretas.
18892 Don Thousand
7

Jack

Este é um bot simples com 4 regras:

  • Não colha quando não fizer nada
  • Sempre colher ao colher, vamos ganhar
  • Colher também quando não tiver sido colhido por 3 carrapatos
  • Caso contrário, não faça nada

Otimizei os 3 ticks em relação aos bots existentes atualmente (Sniper, grim_reaper, Every50, bagunça, BetterRandom, Averager, mais alguns).

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

Eu tentei ficar com minha solução antiga (5 ticks), mas também colho se você não colhe por mais de X ticks e depois colhe menos depois que menos ticks foram passados ​​durante a não colheita (ou seja, 5, se esperou mais tempo do que o próprio) .waittime + 5, também colhe se não tiver sido colhido por 4 carrapatos). Mas isso não melhorou, apenas sempre colhendo após 4 ticks em vez de 5.

Renzeee
fonte
5

A cada 50

Esses bots serão colhidos toda vez que o Reapvalor estiver acima de 50.

Por que 50?

Se eu assumir que haverá 25 bots em jogo, isso significa multiplier = 1.6-(1.2/(1+sqrt(25))) = 1.4oe o waittime = floor(1.5*25) = 37. Desde o Reapinício 1, ele aumentará assim:

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 você pode ver, atinge acima de 50 após 13 tiques. Como o Reapredefinirá para 1 toda vez que um bot colhe, e o waittimepara um bot que colhe é 37, a probabilidade de um bot colher mais cedo ou mais tarde é bastante alta, especialmente com bots semelhantes ao exemplo GreedyBot, que serão colhidos assim que waittimeforem disponível novamente. No começo, eu queria fazer 200, que é o 17º tick, um pouco no meio dos 37 ticks de tempo de espera, mas com a suposição de que há 25 bots em jogo, há uma grande chance de alguém pegar o Reapmeu antes. Então eu reduzi para 50. Ainda é um bom número arredondado, mas principalmente porque é o 13º tick (com 25 bots), e 13 e 'ceifar' também se encaixam um pouco no mesmo gênero 'maligno'.

Código:

O código é ridículo trivial.

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

Notas:

Este bot é muito ruim com baixa quantidade de bots em jogo. Por enquanto vou deixar, e talvez eu faça um robô melhor calculando o melhor momento para fazê-lo Reap. Com uma quantidade extremamente baixa de bots em jogo, waittimeé muito mais baixo também, é claro, então até GreedyBotpode ganhar bastante facilmente desse bot se o nível waittimefor baixo o suficiente.

Espero que mais pessoas adicionem muito mais bots. ; p

Kevin Cruijssen
fonte
def Every49(self, Reap, prevReap): return Reap > 49 Sua vez.
Quintec 13/09/18
@Quintec Hehe. Com 25 bots em jogo, isso significa que ainda é o 13º tick e nós dois vencemos o Reap, então não me importo de compartilhar a vitória com você, lol. ; p
Kevin Cruijssen
Você pode querer colocar intem torno da desigualdade, uma vez que 1 é o verdadeiro comando
Don Thousand
@Quintec Estou ciente brincadeira ur, mas eu não vou permitir 1-up ou bots duplicados
Don Mil
@RushabhMehta Eu não programo em Python com muita frequência, então já estava duvidando se eu deveria adicionar o elenco para tornar o Trueum explícito 1. Achei que a True == 1verificação ainda retornaria Truepara o meu bot, adicionando-a às listas de Reapersem sua nextfunção, mas adicionei o elenco ao int de qualquer maneira, como você sugeriu.
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

Este bot tenta colher a qualquer momento que o valor atual de Reap estiver acima do valor médio Reaped.

Jo.
fonte
Bot muito agradável! +1
Don Mil
Estou extremamente irritado e impressionado com o fato de um algoritmo tão simples vencer a todos com tanta facilidade. Bom trabalho!
Triggernometry
3

Ceifador

Este bot mantém uma média de execução dos valores de todas as colheitas anteriores, bem como o tempo que cada bot está esperando. Ele colhe quando espera mais de 3/4 dos outros bots e a colheita é pelo menos 3/4 do tamanho da colheita média vista até agora. O objetivo é obter muitas colheitas de tamanho razoável e baixo risco.

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: corrigidos alguns erros de sintaxe embaraçosos.

Experimente Online

Zachary Cotton
fonte
1
Você deve usar em self.obj.reapsvez de self.reapse em self.objvez de self.objecte em prevReapvez de prevLeape adicionar () depois de self.obj.players.valuesduas vezes. E acho self.obj.reaps = []que não funcionará, a menos que self.objseja um objeto. Não tenho certeza absoluta se tudo ainda funcionará como pretendido e se tudo o que eu disse é verdade, mas após essas alterações e usando um objeto fictício para self.objquando ele ainda não existe, seu código é compilado para mim.
Renzeee 13/09/18
@ZacharyColton Você não precisa importar matemática. Já foi importado
Don Thousand
@RushabhMehta Adicionei class Object(object):[newline] passna parte superior e usei self.obj = Object()o if not hasattr(..)(se bem me lembro).
Renzeee
@Renzeee aha ic
Don Thousand
@ZacharyCotton Você deve participar do bate-papo.
Don Mil
3

BetterRandom

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

O bot é baseado na suposição de que a chance de colher deve ser proporcional ao tamanho da colheita, porque um ponto é um ponto, não importa quando é obtido. Sempre há uma chance muito pequena de colher, isso mantém o comportamento explorável. Primeiro, pensei que seria diretamente proporcional e assumi que a constante de proporcionalidade estivesse ao redor 1/mult^waittime(a colheita máxima assumindo que pelo menos um bot é ganancioso) depois de executar algumas simulações, descobri que essa era realmente a constante ideal. Mas o bot ainda foi superado pelo Random, então concluí que a relação não era diretamente proporcional e adicionei uma constante para calcular qual era a relação. Após algumas simulações, descobri que, contra o meu conjunto de testes, os bots -1.5eram ótimos. Na verdade, isso corresponde a uma relação inversamente proporcional entre a chance de colher ereap*sqrt(reap)o que é surpreendente. Então, eu suspeito que isso depende muito dos bots específicos, portanto uma versão desse bot que calcula k durante o jogo seria melhor. (Mas não sei se você tem permissão para usar dados das rodadas anteriores).

EDIT: Eu criei um programa para encontrar o tipo de proporcionalidade automaticamente. No conjunto de teste ["myBot("+str(k)+")","Randombot","Greedybot","Every50","Jack","grim_reaper","Averager","mess"], encontrei o novo valor.

fejfo
fonte
Vou adicionar algumas estatísticas novas usando seu bot em breve #
Don Thousand
1
Parece que (reap/self.mult**self.waittime)**-0.810192835está sempre acima de 1, ou seja, self.getRandom () nunca é maior.
Renzeee
@fejfo você também pode usar dados de rodadas anteriores. É para isso que self.objserve. Para ver alguns exemplos de como usá-lo, veja alguns outros bots que o estão usando.
Don Thousand
3

Alvo

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

Minhas chances de ganhar com a bagunça são quase nenhuma agora, então é hora de bagunçar todos os outros bots da maneira mais possível! :)

Este bot funciona de maneira semelhante ao atirador de elite. Sempre que alguém colhe, ele escolhe um alvo aleatório de quem colhe. Então, ele simplesmente espera até que o alvo quase possa colher novamente e o rouba. No entanto, isso não muda o foco - uma vez escolhido e bloqueado, você não pode escapar :)

Quintec
fonte
2

EveryN

Eu acho que é hora do meu segundo bot antes do prazo.

Este bot irá:

  • Pule quando ainda estiver no tempo de espera da última Colheita
  • Colher quando puder vencer
  • Colher quando ninguém colheu pelo menos nrodadas, onde né calculado comn = 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

Eu não programo em Python com muita frequência, então se você encontrar algum erro, me avise.

Kevin Cruijssen
fonte
Santo longo nome da variável. (Também PEP: python.org/dev/peps/pep-0008 )
Quintec 26/09/18
@Quintec Alterou o recuo de 2 espaços para 4; encurtou o subsequentRoundsWithoutReapspara roundsWithoutReaps; usou letras minúsculas com sublinhados para o nome do método; e removeu o parêntese nas instruções if. Obrigado.
Kevin Cruijssen 26/09
Sem problemas! (Tecnicamente, ele deve ser rounds_without_reaps, mas isso não é realmente um problema desde este desafio também usa mixedCamelCase por isso realmente não importa)
Quintec
@ Quintec Ah ok. Eu olhei para as variáveis prevReape lenBotse such e assumidas como camelCase como em Java. ;) Ah, bem, seja qual for o caso, devemos funcionar de qualquer maneira. Os 2 em vez de 4 espaços recuados provavelmente teriam causado alguns problemas, então obrigado de qualquer maneira.
Kevin Cruijssen 26/09
2

Em andamento: Meu projeto para estender o T4T a todos os KOTH abertos.

Olho por olho

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

Peitos para 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

Apenas para mantê-lo alerta.

def kevin(just, a, joke):
    return 0
SIGSTACKFAULT
fonte
Lembre-se de que self.lastnão é uma coisa, mas você pode fazer self.obj.lastuma coisa! Enfim, vou adicionar todos os seus três bots para os memes +1
Don Thousand
Sim, eu sou um idiota. Fixo.
SIGSTACKFAULT
@RushabhMehta Acabei de passar e os fez realmente funcionar. pls editar.
SIGSTACKFAULT
parece bom! Junte-se ao GC, vou postar alguns resultados parciais lá #
Don Thousand
1

Joe Médio

Eu me inspirei no Averager e criei um bot que calcula, em média, quantas voltas são necessárias antes que alguém colha e tenta colher uma vez antes disso.

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
fonte
Vou adicionar isso amanhã.
Don Thousand
1

Codificado

Sim, ele é.

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

Em vez de calcular a média das colheitas anteriores, use uma média pré-calculada em uma execução típica. De qualquer maneira, não vai melhorar com o tempo.

GB
fonte