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 rei da colina . 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 é self
usada para referenciar objetos de classe (mostrados mais tarde). O segundo é o Reap
valor atual do Reap que você ganharia se quisesse "colher". O terceiro é prevReap
uma 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 1
para 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 x
está 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
getRandom
função que forneci.
Você pode encontrar o controlador no link TIO abaixo. Para usá-lo, adicione o nome da sua função BotList
como uma string e adicione a função ao código. Modifique multiplier
para alterar o que o Reap é multiplicado por cada tick, modifique winning_score
para alterar a pontuação necessária para finalizar o jogo e modifique waittime
para 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)
fonte
len(BotList)
?25
bots 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?Respostas:
Confusão Twitchy Indecisa
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.
fonte
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 ninguém tiver> = 70% da pontuação vencedora:
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.Se alguém for> = 70% da pontuação vencedora:
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!)
fonte
self.obj.opponents[opponent]["time"] += 1
no primeiro loop for eself.obj.lastReap
no 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.Jack
Este é um bot simples com 4 regras:
Otimizei os 3 ticks em relação aos bots existentes atualmente (Sniper, grim_reaper, Every50, bagunça, BetterRandom, Averager, mais alguns).
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.
fonte
A cada 50
Esses bots serão colhidos toda vez que o
Reap
valor 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.4
oe owaittime = floor(1.5*25) = 37
. Desde oReap
início1
, ele aumentará assim:Como você pode ver, atinge acima de 50 após 13 tiques. Como o
Reap
redefinirá para 1 toda vez que um bot colhe, e owaittime
para um bot que colhe é 37, a probabilidade de um bot colher mais cedo ou mais tarde é bastante alta, especialmente com bots semelhantes ao exemploGreedyBot
, que serão colhidos assim quewaittime
forem 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 oReap
meu 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.
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éGreedyBot
pode ganhar bastante facilmente desse bot se o nívelwaittime
for baixo o suficiente.Espero que mais pessoas adicionem muito mais bots. ; p
fonte
def Every49(self, Reap, prevReap): return Reap > 49
Sua vez.int
em torno da desigualdade, uma vez que 1 é o verdadeiro comandoTrue
um explícito1
. Achei que aTrue == 1
verificação ainda retornariaTrue
para o meu bot, adicionando-a às listas deReapers
em suanext
função, mas adicionei o elenco ao int de qualquer maneira, como você sugeriu.Averager
Este bot tenta colher a qualquer momento que o valor atual de Reap estiver acima do valor médio Reaped.
fonte
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.
Editar: corrigidos alguns erros de sintaxe embaraçosos.
Experimente Online
fonte
self.obj.reaps
vez deself.reaps
e emself.obj
vez deself.object
e emprevReap
vez deprevLeap
e adicionar () depois deself.obj.players.values
duas vezes. E achoself.obj.reaps = []
que não funcionará, a menos queself.obj
seja 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 paraself.obj
quando ele ainda não existe, seu código é compilado para mim.class Object(object):
[newline]pass
na parte superior e useiself.obj = Object()
oif not hasattr(..)
(se bem me lembro).BetterRandom
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.5
eram ó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.fonte
(reap/self.mult**self.waittime)**-0.810192835
está sempre acima de 1, ou seja, self.getRandom () nunca é maior.self.obj
serve. Para ver alguns exemplos de como usá-lo, veja alguns outros bots que o estão usando.Alvo
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 :)
fonte
EveryN
Eu acho que é hora do meu segundo bot antes do prazo.
Este bot irá:
n
rodadas, onden
é calculado comn = 3 + ceil(self.waittime / self.lenBots)
Código:
Eu não programo em Python com muita frequência, então se você encontrar algum erro, me avise.
fonte
subsequentRoundsWithoutReaps
pararoundsWithoutReaps
; usou letras minúsculas com sublinhados para o nome do método; e removeu o parêntese nas instruções if. Obrigado.prevReap
elenBots
e 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.Em andamento: Meu projeto para estender o T4T a todos os KOTH abertos.
Olho por olho
Peitos para n Tats
Kevin
Apenas para mantê-lo alerta.
fonte
self.last
não é uma coisa, mas você pode fazerself.obj.last
uma coisa! Enfim, vou adicionar todos os seus três bots para os memes +1Joe 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.
fonte
Codificado
Sim, ele é.
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.
fonte