ESTADO DO DESAFIO: ABERTO
Comente, abra um PR ou grite comigo se estiver sentindo falta do seu bot.
O dilema do prisioneiro ... com três opções. Louco, hein?
Aqui está a nossa matriz de pagamento. Jogador A à esquerda, B na parte superior
A,B| C | N | D
---|---|---|---
C |3,3|4,1|0,5
N |1,4|2,2|3,2
D |5,0|2,3|1,1
A matriz de pagamento é projetada para que seja melhor os dois jogadores sempre cooperarem, mas você pode ganhar (geralmente) escolhendo Neutro ou Deserção.
Aqui estão alguns exemplos de bots (concorrentes).
# turns out if you don't actually have to implement __init__(). TIL!
class AllC:
def round(self, _): return "C"
class AllN:
def round(self, _): return "N"
class AllD:
def round(self, _): return "D"
class RandomBot:
def round(self, _): return random.choice(["C", "N", "D"])
# Actually using an identically-behaving "FastGrudger".
class Grudger:
def __init__(self):
self.history = []
def round(self, last):
if(last):
self.history.append(last)
if(self.history.count("D") > 0):
return "D"
return "C"
class TitForTat:
def round(self, last):
if(last == "D"):
return "D"
return "C"
Seu bot é uma classe Python3. Uma nova instância é criada para cada jogo e round()
é chamada a cada rodada, com a escolha do seu oponente da última rodada (ou Nenhuma, se for a primeira rodada)
Há uma recompensa de 50 representantes para o vencedor em um mês.
Específicos
- Todo bot joga todos os outros bot (1v1), inclusive ele mesmo, nas rodadas [REDACTED].
- Falhas padrão não permitidas.
- Não mexa com nada fora da sua classe ou outras desvantagens ocultas.
- Você pode enviar até cinco bots.
- Sim, você pode implementar o aperto de mão.
- Qualquer resposta que não
C
,N
ouD
será silenciosamente tomado comoN
. - Os pontos de cada bot de cada jogo que eles jogam serão totalizados e comparados.
Controlador
Outras línguas
Vou montar uma API, se alguém precisar.
Pontuações: 27/11/2018
27 bots, 729 games.
name | avg. score/round
----------------|-------------------
PatternFinder | 3.152
DirichletDice2 | 3.019
EvaluaterBot | 2.971
Ensemble | 2.800
DirichletDice | 2.763
Shifting | 2.737
FastGrudger | 2.632
Nash2 | 2.574
HistoricAverage | 2.552
LastOptimalBot | 2.532
Number6 | 2.531
HandshakeBot | 2.458
OldTitForTat | 2.411
WeightedAverage | 2.403
TitForTat | 2.328
AllD | 2.272
Tetragram | 2.256
Nash | 2.193
Jade | 2.186
Useless | 2.140
RandomBot | 2.018
CopyCat | 1.902
TatForTit | 1.891
NeverCOOP | 1.710
AllC | 1.565
AllN | 1.446
Kevin | 1.322
king-of-the-hill
python
SIGSTACKFAULT
fonte
fonte
while len(botlist) > 1:
combotlist.remove(lowest_scoring_bot)
a parte inferior do loop, você começa um torneio de eliminação com resultados interessantes.Respostas:
EvaluaterBot
Ganha contra todos os bots enviados anteriormente, exceto (talvez) o bot aleatório (mas pode ter uma vantagem, porque escolhe D em um empate e D deve ser ideal) e joga um empate constante contra si mesmo.
fonte
Equilíbrio de Nash
Esse bot participou de uma aula de teoria dos jogos na faculdade, mas era preguiçoso e não foi para a classe em que abordava jogos iterados. Então, ele joga apenas um jogo de equilíbrio nash misto. Acontece que 1/5 2/5 2/5 é o NE misto para os pagamentos.
Equilíbrio de Nash com abuso constante
Esse bot pegou uma ou duas lições do irmão preguiçoso. O problema de seu irmão preguiçoso era que ele não se aproveitava de estratégias fixas. Esta versão verifica se o oponente é um jogador constante ou um titfortat e joga de acordo, caso contrário, ele joga o equilíbrio nash regular.
A única desvantagem é que ele calcula a média de 2,2 pontos por turno contra si mesmo.
fonte
class NashEquilibrium: def round(self, _): a = random.random() for k, v in [(0.2, "C"), (0.6, "N"), (1, "D")]: if a <= k: return v
TatForTit
Esse bot alternará a escolha do DNDN enquanto o TitForTat alterna o CDCD, para um ganho líquido médio de 3 pontos por rodada, se eu li a matriz de pagamento corretamente. Eu acho que isso pode ser ideal contra TitForTat. Obviamente, poderia ser melhorado detectar um oponente não-TFT e adotar outras estratégias, mas eu estava apenas buscando a recompensa original.
fonte
PatternFinder
Esse bot procura ocorrências anteriores do estado do jogo recente para ver como o oponente respondeu a essas ocorrências, com uma preferência por partidas com padrões mais longas e partidas mais recentes, e depois executa a jogada que "superará" a jogada prevista do oponente. Há muito espaço para que seja mais inteligente com todos os dados que acompanha, mas fiquei sem tempo para trabalhar nisso.
fonte
Jade
Começa otimista, mas fica progressivamente mais amargo à medida que o oponente se recusa a cooperar. Muitas constantes mágicas que provavelmente poderiam ser aprimoradas, mas isso provavelmente não será suficiente para justificar o tempo.
fonte
Conjunto
Isso executa um conjunto de modelos relacionados. Os modelos individuais consideram diferentes quantidades do histórico e têm a opção de escolher sempre a jogada que otimizará a diferença de pagamento esperada ou selecionará aleatoriamente uma jogada na proporção da diferença de pagamento esperada.
Cada membro do grupo vota em sua jogada preferida. Eles recebem um número de votos igual ao quanto mais ganharam do que o oponente (o que significa que modelos terríveis receberão votos negativos). Qualquer movimento que vencer, o voto será selecionado.
(Eles provavelmente devem dividir seus votos entre os movimentos na proporção de quanto eles favorecem cada um, mas eu não me importo o suficiente para fazer isso agora.)
Ele supera tudo publicado até agora, exceto EvaluaterBot e PatternFinder. (Um a um, ele vence o EvaluaterBot e perde para o PatternFinder).
Estrutura de Teste
Caso alguém ache útil, aqui está uma estrutura de teste para analisar correspondências individuais. Python2. Basta colocar todos os oponentes nos quais você está interessado em oponentes.py e alterar as referências ao Ensemble às suas.
fonte
OldTitForTat
O jogador da velha escola está com preguiça de atualizar para as novas regras.
fonte
NeverCOOP
Se o bot adversário falhar ou for neutro, escolha defeito. Caso contrário, se for o primeiro turno ou o bot oposto cooperar, escolha neutro. Não sei ao certo como isso funcionará ...
fonte
if(last):
no seu bot Grudger, detectando se houve uma rodada anterior.None in "ND"
erros.if last and last in "ND":
era muito complicado?LastOptimalBot
Supõe que o bot oponente sempre jogará o mesmo movimento novamente e escolhe aquele que tem a melhor recompensa contra ele.
Médias:
fonte
return last
.return last
, o LOB passaria 18-9 ao longo de 6 rodadas, em vez das 13-10 ao longo de 5 rodadas atualmente. Eu acho que está tudo bem como está - não se preocupe em otimizar os bots de exemplo.return last
seria uma melhor T4T para este desafio, eu achoif(last): return last; else: return "C"
é pior.Imitador
Copia a última jogada do oponente.
Não espero que isso dê certo, mas ninguém implementou esse clássico ainda.
fonte
Dados aprimorados de Dirichlet
Esta é uma versão aprimorada do Dirichlet Dice. Em vez de obter a distribuição multinomial esperada da distribuição Dirichlet, ela extrai uma distribuição Multinomial aleatoriamente da distribuição Dirichlet. Então, em vez de extrair do Multinomial e fornecer a resposta ideal para isso, ele fornece a resposta ideal esperada para o Multinomial fornecido usando os pontos. Portanto, a aleatoriedade foi essencialmente deslocada do sorteio Multinomial para o sorteio Dirichlet. Além disso, os priores estão mais planos agora, para incentivar a exploração.
Ele é "aprimorado" porque agora é responsável pelo sistema de pontos, fornecendo o melhor valor esperado contra as probabilidades, enquanto mantém sua aleatoriedade ao desenhar as próprias probabilidades. Antes, eu tentei simplesmente fazer o melhor retorno esperado das probabilidades esperadas, mas isso foi muito ruim porque ficou travado e não explorou o suficiente para atualizar seus dados. Também era mais previsível e explorável.
Submissão original:
Dirichlet Dice
Basicamente, estou assumindo que a resposta do oponente à minha última saída é uma variável multinomial (dado ponderado), uma para cada uma das minhas saídas, então há um dado para "C", um para "N" e um para "D" . Portanto, se meu último lançamento foi, por exemplo, um "N", lancei o "N-dice" para adivinhar qual seria a resposta deles ao meu "N". Começo com um Dirichlet anterior, que pressupõe que meu oponente é um pouco "inteligente" (é mais provável jogar aquele com o melhor retorno contra o meu último lançamento, menos propenso a jogar aquele com o pior retorno). Eu gero a distribuição Multinomial "esperada" a partir do Dirichlet apropriado anterior (este é o valor esperado da distribuição de probabilidade sobre o peso de seus dados). Lancei os dados ponderados da minha última saída,
Começando na terceira rodada, faço uma atualização bayesiana do Dirichlet apropriado antes da última resposta do meu oponente à coisa que joguei duas rodadas atrás. Estou tentando aprender iterativamente o peso dos dados.
Eu também poderia simplesmente escolher a resposta com o melhor resultado "esperado" depois de gerar os dados, em vez de simplesmente rolar os dados e responder ao resultado. No entanto, eu queria manter a aleatoriedade, para que meu bot fique menos vulnerável aos que tentam prever um padrão.
fonte
Kevin
Escolhe a pior escolha. O pior bot feito.
Sem utilidade
Ele analisa os dois últimos movimentos realizados pelo oponente e escolhe o máximo que não foi feito, caso contrário, escolhe algo aleatório. Provavelmente existe uma maneira melhor de fazer isso.
fonte
Média histórica
Analisa a história e encontra a ação que teria sido melhor em média. Inicia cooperativa.
fonte
Média ponderada
O comportamento do oponente é modelado como um triângulo retângulo com cantos para CND a 0,0 0,1 1,0, respectivamente. Cada movimento do oponente muda o ponto dentro desse triângulo em direção àquele canto, e jogamos para vencer o movimento indicado pelo ponto (com C recebendo uma fatia ajustável do triângulo). Em teoria, eu queria que isso tivesse uma memória mais longa com mais peso dos movimentos anteriores, mas, na prática, a meta atual favorece os bots que mudam rapidamente, e isso se transforma em uma aproximação do LastOptimalBot contra a maioria dos inimigos. Postagem para posteridade; talvez alguém seja inspirado.
fonte
Tetragrama
Tente encontrar um padrão nos movimentos do oponente, supondo que eles também estejam assistindo nosso último movimento.
fonte
Aperto de mão
Reconhece quando está jogando contra si mesmo e depois coopera. Caso contrário, imita LastOptimalBot, que parece ser a melhor estratégia de uma linha. Executa pior que LastOptimalBot, em uma quantidade inversamente proporcional ao número de rodadas. Obviamente, seria melhor se houvesse mais cópias no campo * tosse ** piscadela *.
fonte
ShiftingOptimalBot
Este bot usa o algoritmo de LastOptimalBot, desde que esteja ganhando. Se o outro bot começar a prever, no entanto, ele começará a jogar o que o oponente tiver jogado por último (que é o movimento que supera o movimento que venceria LastOptimalBot). Ele alterna entre transposições simples desses algoritmos, desde que continue a perder (ou quando fica entediado por desenhar muito).
Sinceramente, estou surpreso que LastOptimalBot esteja em 5º lugar quando eu postar isso. Estou bastante certo de que isso será melhor, assumindo que eu escrevi esse python corretamente.
fonte
Aperto de mãoPadrão
Por que o padrão combina com você? Aperto de mão e cooperar.
fonte
import PatternFinder
está trapaceando nos meus livros.Codificado
Apenas reproduz uma sequência codificada de movimentos otimizada para vencer alguns dos principais bots determinísticos.
fonte