fundo
O jogo de Morra é um jogo simples. Na versão "original", vários jogadores jogam simultaneamente um número 0-5 com as mãos, enquanto adivinha a soma total das mãos de todos. A versão que vou usar aqui foi modificada para aumentar o potencial de estratégia não trivial e está descrita abaixo:
- Existem dois jogadores.
- Como na pedra-papel-tesoura, os jogadores se movem simultaneamente.
- A cada turno, cada jogador escolhe um número de 0-5 e também adivinha a escolha de 0-5 de seus oponentes. Isso significa que dois números são emitidos a cada turno. Para esclarecer, a saída de ambos os números deve estar no intervalo de 0 a 5, inclusive.
- Se você adivinhar a escolha do seu oponente corretamente, mas seu oponente não adivinhou corretamente, você ganha um certo número de pontos igual à soma dos dois números jogados. Por exemplo, se os números jogados fossem 3 e 5, um palpite correto valeria 8 pontos.
- Se ambos ou nenhum dos jogadores acertarem, nenhum ponto será concedido.
- A pessoa com mais pontos após 1000 rodadas vence o jogo.
O torneio
O torneio será realizado no estilo round-robin e será realizado com a criação de cada possível par de participantes. Para cada vitória, o competidor ganha 2 pontos de vitória. Cada empate resulta em 1 ponto de vitória. Nenhum ponto de vitória é ganho por uma perda.
Intuitivamente, o vencedor do torneio será o competidor com mais pontos de vitória contra os outros.
Como entrar
Haverá dois métodos para enviar bots para competir. O primeiro, e muito preferido método, é implementar uma interface Java fornecida pelo controlador. O segundo método é escrever um programa independente.
Vamos abordar o método Java primeiro. A interface que você precisará implementar é Player
e define dois métodos: public String getName()
identifica seu bot e public int[] getMove(String[] args)
usa args
como uma matriz de seis strings mychoices myguesses myscore opponentchoices opponentguesses opponentscore
. Um exemplo é o seguinte:
042 045 0 324 432 6
Isso significa que eu escolhi 0 no primeiro turno e adivinhei que meu oponente jogaria um 0. Meu oponente jogou um 3 e adivinhou que eu jogaria um 4. Na terceira rodada, meu oponente fez o palpite correto de que eu jogaria a 2, o que significa que ele ganha 2 + 4 = 6 pontos.
Seu método retornará uma matriz de dois números inteiros, que são sua escolha e suposição, respectivamente. Um exemplo é {4,2}
para uma escolha de 4 e um palpite de 2.
Aqui está um exemplo de um bot Java completo escrito como um método. Se você quiser, seu envio deve incluir apenas o que está acontecendo no getMove
método.
import java.util.Random;
/**
* A simple example Morra bot to get you started.
*/
public class ExampleBot implements Player
{
public String getName()
{
return "ExampleBot";
}
public int[] getMove(String [] args)
{
//easiest way I know to break down to create a move history
//(just contains their throw history)
char[] theirThrowsC = args[3].toCharArray();
int[] theirThrows = new int[theirThrowsC.length];
for(int i = 0; i < theirThrowsC.length; i++)
{
theirThrows[i] = Integer.parseInt(Character.toString(theirThrowsC[i]));
}
//get my score
int myScore = Integer.parseInt(args[2]);
Random r = new Random();
int guess = r.nextInt(6);
if(theirThrows.length > 0)
{
guess = theirThrows[theirThrows.length-1];
}
//throws a random number, guesses what they threw last
return new int[] {r.nextInt(6),guess};
}
public static int otherMethod(int example) //you can write additional static methods
{
return 0;
}
}
Como um programa independente
Atualmente, estou limitado no meu suporte a idiomas adicionais. Além do Java, posso aceitar programas escritos em Python 3.4, Perl 5 ou Ruby 2.1.5. Se houver um idioma que várias pessoas parecem querer, farei o possível para adicioná-lo.
A entrada para o seu programa serão argumentos na linha de comando. Pode ficar assim:
perl awesomebot.plx 042 045 0 324 432 6
A saída do seu programa deve ser a sua escolha, seguida pelo seu palpite, cada um seguido pelo espaço em branco.
Inclua na sua resposta o comando exato necessário para executá-lo. Lembre-se de que estou executando o Windows 8.1.
Regras Extra
Salvando estado e tempos limite
Seu programa poderá criar um arquivo de texto no diretório local, onde você pode armazenar informações. Esta informação será mantida durante todo o torneio, mas excluída posteriormente. Dê ao arquivo um nome que eu possa identificar.
Há um limite de tempo de 500 milissegundos para o seu código responder. A falta de resposta no prazo (ou a movimentação inválida) resultará na perda dessa partida em particular. Os envios de Java atualmente têm um tempo limite passivo (que eu posso atualizar para ativo), enquanto os envios que não são de Java têm um tempo limite ativo em que seu processo é encerrado após 500 milissegundos.
Mais regras de envio
- Você pode enviar vários envios, desde que respeitem as regras e não participem da equipe de tags.
- Cada entrada deve ser exclusiva. Você não pode fazer uma cópia exata da lógica de outro bot em um idioma diferente.
- Os bots não podem interagir entre si (para formar uma equipe de qualquer tipo).
- Você não pode usar a lógica dos outros bots dentro do seu bot para, por exemplo, identificar seu concorrente e prever suas ações. Você pode, é claro, tentar determinar a estratégia do seu oponente.
- Não tente mexer com o controlador, outros concorrentes ou meu computador. Não conecte a fontes de informação externas.
O controlador
A versão atual do controlador é encontrada aqui . Está escrito em Java 8. O arquivo "Tournament" é o controlador principal, que também contém a lista de concorrentes (se você deseja hospedar suas próprias competições).
Entre os melhores
Não tenho conseguido atualizar a tabela de classificação com muita frequência. Estou bastante ocupado neste fim de semana. Por "bastante ocupado", quero dizer que não há acesso a um computador das 6:30 às 21:30. Aqui estão as pontuações após 5 corridas. O bot "Echo" continuou perdendo por algum motivo (pode ser minha culpa, ainda não investiguei).
170 - Quinn and Valor
158 - Historian
142 - DeltaMax
140 - MorraCowbell
132 - Extrapolator
115 - Rainbolt
102 - Popularity
100 - Interpolator
83 - CounterBot
80 - Basilisk
76 - Erratica
65 - Trendy
63 - Scholar
62 - RandomGuesser
60 - KingFisher
59 - NullifierBot
55 - EvolvedBot
48 - Confused
Crédito
Muito obrigado a Rainbolt e Peter Taylor por sua ajuda com o controlador.
fonte
Respostas:
Morra Cowbell
Para quem procura significado no nome desse bot, o nome Morra me faz pensar no espaço italiano , então achei que precisava de um nome que tocasse nisso. Outros candidatos incluíram Morra enganar você e Morra por mim .
Esta é uma classe completa implementando a
Player
interface. Explicação abaixo.Explicação
Comecei analisando jogos com menos dedos. O mais simples, não trivial, permite fazer chamadas
0
ou1
ter a seguinte tabela de pagamentos (os valores são pagos para o jogador de linha):A
(0,0)
estratégia é dominada por(0,1)
, para que possamos reduzir a tabela paraAgora a
(1,0)
estratégia é dominada por(0,1)
, para que possamos reduzir ainda mais a tabela paraE agora
(1,1)
é dominado por(0,1)
, então acabamos comPortanto, sempre tocar
(0,1)
é um equilíbrio de Nash. Mas o curioso é que não é o único. Este é um jogo simétrico de soma zero, portanto o retorno esperado é 0 e qualquer estratégia mista combinada(0,1)
e(1,0)
onde(0,1)
é escolhida pelo menos 50% do tempo alcança esse retorno. Portanto, temos um espaço unidimensional de equilíbrios de Nash.Parece ser o caso, embora eu não tenha provado isso, que o
n
dedo Morra tem umn
polítopo tridimensional dos equilíbrios de Nash, que são estratégias mistas entre osn+1
(pick, guess)
pares para os quaispick + guess = n
.Os números mágicos no código acima codificam os 32 vértices do pólipo 5-dimensional dos equilíbrios de Nash. Eu os encontrei configurando uma instância de programação linear que representava o politopo e, em seguida, usando funções objetivas aleatórias. A razão para codificar todos os 32, em vez de escolher um, é simples: o retorno esperado é 0, então eu preciso me sair melhor do que o esperado para obter uma vitória. Eu suponho essencialmente que o outro jogador esteja usando uma estratégia mista e estime a distribuição com base no histórico de suas escolhas. Depois, seleciono o vértice do polítopo que maximiza meu ganho esperado em relação à distribuição estimada.
QuinnAndValor demonstra a vulnerabilidade da suposição de que o outro jogador está usando uma estratégia mista. Ao detectar um jogador que usa as estratégias dos equilíbrios de Nash, ele pode mudar para um modo de passeio aleatório, onde, jogando uma estratégia de não equilíbrio, é passível de perder, em média, mas só precisa ganhar uma vantagem uma vez e depois pode voltar a jogar pares para os quais
pick + guess = n
. Portanto, os equilíbrios de Nash para um único jogo não se generalizam trivialmente aos equilíbrios de Nash para o jogo repetido, o que permite estratégias mais complexas.fonte
Quinn e Valor (Atualizado)
Quinn e Valor são um time de elite de guarda florestal. Com besta e garra, eles rasgam todo oponente ousa desafiá-lo.
Eles quase sempre vencem todas as soluções Java da minha máquina.
Editar:
Admito que Quinn e Valor não conseguiram duelar com o Historian, mas ainda tenho boa fé neles para vencer o torneio.
Meu princípio é que, para qualquer solução
choice + guess == 5
, tambémchoice + guess == 5
brinque com os donatários mantendo sua vantagem.Atualizar:
Bem ... tudo ficou complicado.
fonte
Estudioso
O estudioso tenta aprender com os movimentos de seu oponente, escolhendo aquele que seu oponente menos adivinhou e adivinhando aquele que seu oponente mais usou. Mas a teoria não é tudo, então o Scholar não se sai muito bem ...
fonte
DeltaMax
(Atualizado para não usar arquivos e adicionado uma nova seção. Também modificado para não ficar mais preso na primeira seção.)
Consiste em algumas estratégias que começam simples e se tornam mais complexas - se você desmarcar uma, ela será direcionada para a próxima seção.
{0, 5}
consistentemente(choice, guess)
par que teria a melhor expectativa, ponderado para que as rodadas recentes sejam mais importantesPara descobrir qual camada foi usada no final, remova o comentário do
linha.
Desculpas pelo horrível Java, passei minha tarde juntando pedaços e reaprendendo a linguagem :)
fonte
private int strat;
é bom o suficiente.Historiador
(Atualizado: mesma lógica, código mais curto e 100 vezes mais rápido, mas você pode usar apenas um bot do Historian em um torneio.)
Usa aleatoriamente ponderada para escolher um par de adivinhação com base na eficácia de usar apenas esse par contra o histórico anterior do oponente. Os pesos são os quadrados das pontuações alcançáveis.
Bate
Quinn and Valor
(não mais) e perde paraMorra Cowbell
. No torneio com a maioria dos botsHistorian
vem em segundoQuinn and Valor
.fonte
Morra Cowbell
. Editou a postagem. Você pode excluir comentários, se eles se tornarem obsoletos.Extrapolador (v1.1)
Extrapolação extrema de um dos equilíbrios de Nash de um jogo mais simples.
Eu apoio o formato de resposta concisa! (No estilo python.)
Parece amarrar com a vaca mágica (Morra Cowbell) e supera outras entradas que eu verifiquei.
fonte
Na moda
Trendy dá uma olhada nos movimentos passados do oponente, ponderando-os pela recência. Adivinha o mais pesado, e escolhe um que se deslocou um pouco disso. Aqui está em toda a sua glória:
A única coisa com a qual posso compará-lo agora é Cowbell. Perde por uma pequena margem a maior parte do tempo, mas sai por cima com frequência suficiente para o meu gosto. Vamos ver como isso acontece com mais concorrentes.
fonte
Random Guesser
Isso é realmente direto. Ele efetivamente lança um d6 e adiciona outro rolo ao rolo anterior para adivinhar. Não vencerá, mas fornecerá uma boa referência.
fonte
Confuso, Python 3
Uma entrada desnecessariamente complicada. Mesmo eu não sei o que faz.
Embora esse algoritmo avançado pareça ter um desempenho pior que aleatório neste torneio e use memória e tempo de execução significativos, ele possui resultados impressionantes para determinados valores de 5 ;-)
fonte
Rainbolt
Toma a diferença entre os dois últimos números que nosso oponente adivinhou, acrescenta que ao último palpite de nosso oponente, encontra o módulo e evita escolher esse número a todo custo. Por exemplo, se você adivinhar {5,4,3} (diminuindo em um), evitaríamos escolher 2 a todo custo.
Toma a diferença entre os dois últimos números que nosso oponente escolheu, acrescenta isso à última escolha do oponente e adivinha esse número. Por exemplo, se você adivinhar {1,4,5,2} (aumentando em três), adivinharemos 5.
Evita rolos inúteis ou muito próximos de inúteis.
fonte
getMove()
método estático. Você não pode implementar um método não estático como esse (pelo menos não no Java 8).Bot evoluído
Eu desenvolvi esse bot para ser o melhor bot aleatório.
fonte
Popularidade, Python 3
Calcule a estimativa com base em números populares usados no passado pelo oponente. Os números usados recentemente têm mais peso. A escolha do número geralmente é a mesma que o palpite.
fonte
Interpolador
(Comutado para Java, pois o Python estava causando problemas)
Usa interpolação polinomial nas últimas 10 opções do oponente para calcular o próximo número do oponente, depois faz o mesmo com suas próprias escolhas e evita a escolha desse número. Além disso, o Interpolator tem um leve viés contra a escolha de 0 ou 5, e sua escolha às vezes é afetada pelo seu palpite:
fonte
CounterBot
Não contraria ninguém, mas conta de 0 a 5 em um círculo (
0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4 ...
)fonte
Basilisco, Python
Segundo a lenda, o Basilisco é o rei das serpentes. ( fonte ) Imaginei que esse era um nome apropriado para um bot que toca "The Noble Game Of Kings" e está escrito em python. = D Este bot causa medo no coração dos outros bots e causa a morte com um único olhar.
Isso é executado em uma estratégia bastante simples. Não espero que vença, mas foi divertido escrever. Este também é o meu primeiro desafio do KoTH, por isso estou animado para ver como ele se sai.
Como escolhe seu próximo passo.
O Basilisco sempre faz o movimento que seu oponente adivinhou o menor número de vezes. Em caso de empate, ele escolherá o número menor. (para minimizar o número de pontos do oponente.)
Como escolhe seu próximo palpite.
O Basilisco escolherá a resposta mais provável ao seu palpite anterior. Por exemplo, se da última vez, adivinhou um 3, ele retornará todas as vezes anteriores que adivinhou um 3 e, em seguida, retornará o movimento adversário mais comum que vem após um palpite de 3. Em caso de empate , ele selecionará o número maior (para maximizar o número de pontos que ele poderia fazer).
Em uma nota técnica, isso funcionará corretamente? Print () é suficiente ou devo usar algo como sys.stdout.write () como os outros pythonistas fizeram?
fonte
Idem
Isso se transforma no oponente, mas atrasado por um palpite / escolha.
fonte
NullifierBot, Java
Sempre joga 0 para minimizar os ganhos do adversário. Se o oponente adivinhar meu número, ele só ganha o que jogou.
Sempre adivinha 5 para maximizar meus ganhos. Como não consigo obter nenhum ponto no meu arremesso, quero receber o maior número possível do oponente. Eu poderia adivinhar aleatoriamente, mas onde está a graça nisso?
fonte
Erratica, Java
Não é ótimo, mas foi originalmente projetado para ser aleatório, até que o valor da troca me ocorreu. Consegue perder consistentemente vs. Counter Bot> _ <
fonte
Echo, Ruby
Reproduz a última jogada do oponente, com a teoria de que qualquer um pode fazer um bot que não pode prever. Adivinha com base no valor esperado usando uma amostra de cem movimentos.
fonte
echo.rb:3:in
<main> ': método indefinidosize' for nil:NilClass (NoMethodError)
. Parece ocorrer apenas no primeiro turno, quando não há histórico de movimentos.if (mychoices.size > 990 && myscore == '0') nextchoice = rand(1..5)
peça?KING FISHER
Esse cara consiste em algoritmos de suposição ruim que usam matrizes ponderadas principalmente.
fonte
Uh uh Eu sei o que você está pensando. "Ele vai pegar cinco ou algo mais?" Bem, para dizer a verdade em toda essa empolgação, eu não tenho certeza, mas sendo este o método .44, o método mais poderoso do mundo e sobrecarregaria sua pilha imediatamente, você precisa se fazer uma pergunta : "Sinto-me com sorte?"
Bem, sim, punk?
fonte