O dilema do prisioneiro v.3 - Dilema de Petri


17

Um cientista louco acabou de criar uma nova espécie de bactéria! Ele decidiu nomear Noblus Gentlemanus, depois de observar seu comportamento. No entanto, suas bactérias ficaram sem comida e declararam guerra, pois são capazes de colher cadáveres de outras bactérias por comida suficiente para criar cópias de si mesmas. Existem várias subespécies diferentes dessa bactéria, que têm estratégias diferentes para jogar o Dilema do Prisioneiro, seu jogo favorito. Existem cinco bactérias de cada subespécie diferente. No dilema do prisioneiro, cada um dos dois jogadores escolhe simultaneamente o defeito ou coopera. Se um jogador escolhe cooperar e o outro escolhe o padrão, o inadimplente recebe 2 pontos e o cooperador perde 3 pontos. Se ambos os jogadores escolherem cooperar, ambos ganham 1 ponto. Se ambos os jogadores escolherem o padrão, ambos perderão 1 ponto.

Sendo nobres senhores, as bactérias decidiram travar esta guerra jogando 200 rodadas de jogos do Dilema Iterado do Prisioneiro. O perdedor de cada duelo cometerá suicídio, permitindo que o vencedor se clone. Em caso de empate, ambas as bactérias permanecerão vivas, mas nenhuma delas poderá se clonar. Além disso, todas as bactérias de uma partida transportam mais de 10% de seus pontos para a próxima partida. Um clone transporta os pontos da bactéria pela qual foi clonado. Além disso, há uma chance em dez a cada turno de uma bactéria se transformar em outra subespécie, com 0 pontos de bônus (se eu receber reclamações sobre a aleatoriedade disso, posso removê-la). Depois que as bactérias jogam um número desses duelos igual ao número de subespécies de bactérias vezes dez, o cientista louco acidentalmente derruba a placa de Petri em que as bactérias residem, e todas as bactérias adquirem novas fontes de alimento, terminando seus duelos. Isso é diferente de um concurso de dilemas de prisioneiros iterados comuns, pois envolve duelos 1x1 com pontos de transição, em vez de simplesmente tentar obter o máximo de pontos no geral. Isso faz uma grande diferença na eficácia de uma determinada estratégia.

Cada bactéria receberá entrada no início de seu turno no formato: (número do turno, pontos atuais, pontos inimigos, seus movimentos anteriores [em uma sequência, usando o caractere "c" para cooperar e o caractere "d" para defeito) ], movimentos anteriores dos inimigos [no mesmo formato]).

Aqui estão quatro exemplos de estratégias que serão inseridas. Na verdade, acho que o Defector pode vencer, mesmo que seja extremamente simples.

Olho por olho

def titfortatfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter==0 or enlist[counter-1] == "c":
        return "c"
    else:
        return "d"

RandomPick

from random import choice
def randompickfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter == 199:
        return "d"
    else:
        return choice(["d", "c"])

Cooperador

def cooperatorfunc(counter, mypoints, enpoints, mylist, enlist):
    return "c"

Defector

def defectorfunc(counter, mypoints, enpoints, mylist, enlist):
    return "d"

Todos os envios devem estar na forma de uma função Python 2.7, com o nome sendo o nome do envio sem espaços, com funcno final. Se alguém quiser enviar uma resposta em um idioma diferente, digite-o no pseudo-código, para que eu possa converter para Python em uma edição da sua resposta assim que tiver tempo, ou me dê instruções sobre como fazer a interface do seu idioma com o meu controlador que encontra-se abaixo, configurado para todos os envios a partir de 4 de junho.

from titfortat import titfortatfunc
from randompick import randompickfunc
from cooperator import cooperatorfunc
from defector import defectorfunc
from luckytitfortat import luckytitfortatfunc
from randomtitfortat import randomtitfortatfunc
from remorsefulaggressor import remorsefulaggressorfunc
from everyother import everyotherfunc
from niceguy import niceguyfunc
from titfortatbackstab import titfortatbackstabfunc
from gentleDefector import gentleDefectorfunc
from anticapitalist import anticapitalistfunc
from grimtrigger import grimtriggerfunc
from bizzaro import bizzarofunc
from neoanticapitalist import neoanticapitalistfunc
from bittertat import bittertatfunc
from teamer import teamerfunc
from copyfirst import copyfirstfunc
from exploitivetat import exploitativetatfunc
from defectorv2 import defectorv2func
from crazytat import crazytatfunc
from randomchoicev2 import randomchoicev2func
from twotitsforatat import twotitsforatatfunc
from threetitsforatat import threetitsforatatfunc
from fourtitsforatat import fourtitsforatatfunc
from fivetitsforatat import fivetitsforatatfunc
from sixtitsforatat import sixtitsforatatfunc
from tentitsforatat import tentitsforatatfunc
from theelephant import theelephantfunc
from xbittertat import xbittertatfunc
from fifteentitsforatat import fifteentitsfortatfunc
from twentytitsforatat import twentytitsforatatfunc
from fox import foxfunc
from onehundredfortysixtitsforatat import onehundredfourtysixtitsforatatfunc
from gameofthrones import gameofthronesfunc
from boy import boyfunc
from grimace import grimacefunc
from fiftytitsforatat import fiftytitsfortatfunc
from soreloser import soreloserfunc
from everyotherd import everyotherdfunc
from fiftythreetitsfortat import fiftythreetitsfortatfunc
from twentyfivetitsfortat import twentyfivetitsfortatfunc
from handshake import handshakefunc
from anty import antyfunc
from fiftyfourtitsforatat import fiftyfourtitsfortatfunc
from kindatitsfortat import kindatitsfortatfunc

import random

players = 38

rounds = players*10

def runcode(num, points1, points2, history1, history2, cell):
    ans = ""
    if cell == 0:
        ans = titfortatfunc(num, points1, points2, history1, history2)
    elif cell == 1:
        ans = randompickfunc(num, points1, points2, history1, history2)
    elif cell == 2:
        ans = cooperatorfunc(num, points1, points2, history1, history2)
    elif cell == 3:
        ans = defectorfunc(num, points1, points2, history1, history2)
    elif cell == 4:
        ans = luckytitfortatfunc(num, points1, points2, history1, history2)
    elif cell == 5:
        ans = randomtitfortatfunc(num, points1, points2, history1, history2)
    elif cell == 6:
        ans = remorsefulaggressorfunc(num, points1, points2, history1, history2)
    elif cell == 7:
        ans = everyotherfunc(num, points1, points2, history1, history2)
    elif cell == 8:
        ans = niceguyfunc(num, points1, points2, history1, history2)
    elif cell == 9:
        ans = titfortatbackstabfunc(num, points1, points2, history1, history2)
    elif cell == 10:
        ans = gentleDefectorfunc(num, points1, points2, history1, history2)
    elif cell == 11:
        ans = anticapitalistfunc(num, points1, points2, history1, history2)
    elif cell == 12:
        ans = grimtriggerfunc(num, points1, points2, history1, history2)
    elif cell == 13:
        ans = bizzarofunc(num, points1, points2, history1, history2)
    elif cell == 14:
        ans = neoanticapitalistfunc(num, points1, points2, history1, history2)
    elif cell == 15:
        ans = tentitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 16:
        ans = bittertatfunc(num, points1, points2, history1, history2)
    elif cell == 17:
        ans = copyfirstfunc(num, points1, points2, history1, history2)
    elif cell == 18:
        ans = exploitativetatfunc(num, points1, points2, history1, history2)
    elif cell == 19:
        ans = sixtitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 20:
        ans = fifteentitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 21:
        ans = fivetitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 22:
        ans = twentytitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 23:
        ans = threetitsforatatfunc(num, points1, points2, history1, history2)
    elif cell == 24:
        ans = fiftyfourtitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 25:
        ans = theelephantfunc(num, points1, points2, history1, history2)
    elif cell == 26:
        ans = xbittertatfunc(num, points1, points2, history1, history2)
    elif cell == 27:
        ans = foxfunc(num, points1, points2, history1, history2)
    elif cell == 28:
        ans = gameofthronesfunc(num, points1, points2, history1, history2)
    elif cell == 29:
        ans = boyfunc(num, points1, points2, history1, history2)
    elif cell == 30:
        ans = grimacefunc(num, points1, points2, history1, history2)
    elif cell == 31:
        ans = soreloserfunc(num, points1, points2, history1, history2)
    elif cell == 32:
        ans = everyotherdfunc(num, points1, points2, history1, history2)
    elif cell == 33:
        ans = twentyfivetitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 34:
        ans = fiftythreetitsfortatfunc(num, points1, points2, history1, history2)
    elif cell == 35:
        ans = handshakefunc(num, points1, points2, history1, history2)
    elif cell == 36:
        ans = antyfunc(num, points1, points2, history1, history2)
    elif cell == 37:
        ans = kindatitsfortatfunc(num, points1, points2, history1, history2)


    return ans

def fight(l1,l2):
    num1,num2=l1[0],l2[0]
    points1,points2=l1[1],l2[1]
    history1 = ""
    history2 = ""

    for num in range(200):
        p1 = runcode(num, points1, points2, history1, history2, num1)
        p2 = runcode(num, points2, points1, history2, history1, num2)

        history1+=p1
        history2+=p2

        if p1 == "c" and p2 == "c":
            points1 += 1
            points2 += 1
        elif p1 == "c" and p2 == "d":
            points1 -= 3
            points2 += 2
        elif p1 == "d" and p2 == "c":
            points1 += 2
            points2 -= 3
        elif p1 == "d" and p2 == "d":
            points1 -= 1
            points2 -= 1

    if points1 > points2:
        return [l1[0], points1/10], [l1[0], points1/10]
    elif points1 < points2:
        return [l2[0], points2/10], [l2[0], points2/10]
    else:
        return [l1[0], points1/10], [l2[0], points2/10]

def rounddoer(bots):
    bots2=[]
    for x in range(len(bots)):
        if x%2==0:
            out1, out2 = fight(bots[x], bots[x-1])
            bots2.append(out1)
            bots2.append(out2)

    return bots2

def gamedoer():

    bots=[[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0],[0,0],[1,0],[2,0],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0],[14,0],[15,0],[16,0],[17,0],[18,0],[19,0],[20,0],[21,0],[22,0],[23,0],[24,0],[25,0],[26,0],[27,0],[28,0],[29,0],[30,0],[31,0],[32,0],[33,0],[34,0],[35,0],[36,0],[37,0]]
    random.shuffle(bots)
    counter=0

    while counter < rounds:

        counter += 1
        bots = rounddoer(bots)

        if random.randint(0,10) == 9:
            bots[random.randint(0, players*5)-1] = [random.randint(0, players-1), 0]

        random.shuffle(bots)

##        for item in bots:
##            print str(item[0]) + " with " + str(item[1]) + " bonus points."

    return bots

a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,mycounter=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

while mycounter < 1000:
    mycounter += 1
    bots = gamedoer()

    print "Game: " + str(mycounter)

    for item in bots:
        if item[0]==0:
            a0 += 1
        if item[0]==1:
            a1 += 1
        if item[0]==2:
            a2 += 1
        if item[0]==3:
            a3 += 1
        if item[0]==4:
            a4 += 1
        if item[0]==5:
            a5 += 1
        if item[0]==6:
            a6 += 1
        if item[0]==7:
            a7 += 1
        if item[0]==8:
            a8 += 1
        if item[0]==9:
            a9 += 1
        if item[0]==10:
            a10 += 1
        if item[0]==11:
            a11 += 1
        if item[0]==12:
            a12 += 1
        if item[0]==13:
            a13 += 1
        if item[0]==14:
            a14+=1
        if item[0]==15:
            a15+=1
        if item[0]==16:
            a16+=1
        if item[0]==17:
            a17+=1
        if item[0]==18:
            a18 += 1
        if item[0]==19:
            a19+=1
        if item[0]==20:
            a20+=1
        if item[0]==21:
            a21+=1
        if item[0]==22:
            a22+=1
        if item[0]==23:
            a23+=1
        if item[0]==24:
            a24+=1
        if item[0]==25:
            a25+=1
        if item[0]==26:
            a26+=1
        if item[0]==27:
            a27+=1
        if item[0]==28:
            a28+=1
        if item[0]==29:
            a29+=1
        if item[0]==30:
            a30+=1
        if item[0]==31:
            a31+=1
        if item[0]==32:
            a32+=1
        if item[0]==33:
            a33+=1
        if item[0]==34:

Este concurso está concluído

Se você quiser adicionar uma resposta, verei se consigo adicionar um placar pós-desafio abaixo do dos competidores originais. Eu adicionarei um assim que o programa de teste terminar (provavelmente mais 2-3 dias).

PONTOS FINAIS !!!!!

Tit for Tat: 18
Random Pick: 28
Cooperator: 19
Defector: 24
Lucky Tit for Tat: 23
Random Tit for Tat: 23
Remorseful Aggressor: 22
Every Other C: 23
Nice Guy: 18
Tit for Tat Backstab: 15
Gentle Defector: 22
Anticapitalist: 27
Grim Trigger: 19
Bizzaro: 21
NeoAnticapitalist: 24
Ten Tits for a Tat: 240
Bitter Tat: 12
Copy First: 30
Exploitative Tat: 19
Six Tits for a Tat: 16
Thirty Tits for Tat: 4129
Five Tits for a Tat: 22
Forty Tits for a Tat: 1972
Three Tits for a Tat: 22
Fifty Four Tits for a Tat: 25805
The Elephant: 31
Extra Bitter Tat: 28
Fox: 35
Game of Thrones: 11297
The Boy: 31
Grimace: 26
Sore Loser: 39
Every Other D: 18
Twenty Five Tits for a Tat: 2399
Fifty Three Tits for a Tat: 5487
Handshake: 28
Anty: 26
Kinda Tits for Tat: 20
Prudent Defector: 154539
Bizzarro Trigger: 25
Young Mathematician: 21
Older Mathematician: 16
Perfect Gentleman: 1953341

Então, parece que Perfect Gentleman é o vencedor. Parabéns a Draco18, que definitivamente merece sua marca de seleção verde.


Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Dennis

11
OBSERVAÇÃO: SE VOCÊ ESTÁ EDITANDO O SEU PROGRAMA, FAÇA UM COMENTÁRIO PARA AVISO, OU NÃO PODE SER COLOCADO NO PAINEL DE AVALIAÇÃO !!!!!!!!!!!!!!!!!!!! !!!
Gryphon - Restabelece Monica

Caramba! Acabei de perceber quantas importações são essas.
Gryphon - Restabelece Monica

11
Ei Gryphon, você está trabalhando no ranking final? ;)
Draco18s não confia mais em SE

Desculpe, eu esqueci isso. Dê-me um pouco para executá-lo.
Gryphon - Restabelece Monica

Respostas:


8

O Cavalheiro Perfeito

Não tenho uma boa descrição para este bot. Encontrei algumas otimizações em potencial, testei-as, afinei-as e acabei com uma bactéria que destrói totalmente a concorrência. Em vez disso, comentei o próprio código para explicar o que ele faz.

import random
def perfectgentlemanfunc(num, i, d, c, en):
    if num>0 and i < 0 and d > 0 and -i%3 == 0 and d%2 == 0 and en[0] == "d":
        #probably very first iteration, probably facing a defector: feed it free points
        #    defector cannot be beaten by *any* bot unless that bot
        #    entered with a point lead. defector does some of our work for us
        if num >= 140:
            #140 threshold restricts how much we feed
            return "d"
        return "c"
    turn_to_betray = 130
    if num > turn_to_betray and en[turn_to_betray -2] == "c" and
     en[turn_to_betray -1] == "c" and en[turn_to_betray] == "d":
        #if self, then sacrifice the lower point bot to raise the points of the higher
        #(better net outcome than "c/c" cooperation)
        #    Handshake independently arrived at this same optimization
        if i == d:
            #max 50% probability of choosing different possible. May as well take it
            #    "ccd" has a 55% chance of choosing the same
            #    better outcomes for splitting early
            return "cd"[random.randint(0,1)]
        if i > d:
            return "d"
        return "c"
    #betray after betray point, or if behind by >200
    #performs 6 percentage points better than not having the condition
    if num >= turn_to_betray or i + 200 < d
        return "d"
    else:
        #be nice the first turn
        if num == 0:
            return "c";
        #finally, be tit-for-tat
        return en[-1]

Vários valores foram escolhidos arbitrariamente com as alternativas testadas e os valores aqui são quase ótimos neste momento. Contra a atual disseminação de facções opostas, The Perfect Gentleman alcança o domínio completo (100% da população de bactérias) cerca de 90% das vezes (mais ou menos 3 pontos percentuais).

Ainda não adicionei os matemáticos aos meus testes, no entanto, esses dois devem servir apenas para alimentar as estratégias existentes e não alterar muito o resultado.

Ele gerencia boa parte de seu controle por meio da manutenção do Defector, mas isso foi permitido pelas regras (as estratégias de exemplo eram um jogo justo para direcionar). Tem um efeito colateral de também sustentar Game of Thrones, mas isso não foi intencional, pois os dois são indistinguíveis com base nos critérios que escolhi. Esses "tipos desertores" têm uma vantagem em pontos na rodada 2 e, como resultado, eliminam vários vizinhos problemáticos (os tipos N-T4T) e, quando refazem The Perfect Gentleman, gastam sua vantagem em pontos e são rapidamente consumidos.

Há uma chance aproximada de 5% de que todos os cavalheiros perfeitos acabem emparelhados com os tipos de desertores no primeiro turno e acabem cometendo suicídio em massa. Nesse caso, um dos tipos de n-T4t atinge a dominação total (196 células de 196). Muito raramente, um dos outros tipos (Game of Thrones, Boy, Careta, Sore Loser ...) consegue não ficar completamente extinto e marcar um ou dois pontos.

Simulação atual (ainda em andamento para 200 jogos no total). Todas as entradas com pontuação 0 foram removidas. Parece que Game of Thrones e 54-T4T dividiram uma rodada (195 pontos entre eles) depois que PG foi eliminado.

Game: 90

Cooperator: 1
Remorseful Aggressor: 1
Copy First: 1
Six Tits for a Tat: 1
Thirty Tits for Tat: 393
Five Tits for a Tat: 1
Fifty Four Tits for a Tat: 538
Game of Thrones: 248
Perfect Gentleman: 16456 (93.2)%

##Simulation Terminated: Adding new bots

Punhalada pelas costas por Tat (com perdão)

Este é basicamente o Lucky Tit for Tat (também conhecido como Tit for Tat with Forgiveness), que é a solução ótima "resolvida" (para algum valor de "lucky"), com um toque especial. Como sabemos exatamente quantas rodadas o jogo vai durar, essa bactéria dá um backstabs na rodada final, garantindo assim um resultado benéfico contra qualquer outra tit para as bactérias Tat e Cooperator (contra si mesma termina com um zero líquido, como se tivesse cooperado). Devido à transição de 10%, isso resulta em uma vantagem a longo prazo.

from random import randint
def titfortatbackstabfunc(num, i, d, c, enlist):
    if num == 199:
        return "d";
    lucky = randint(0, 200)
    if lucky == 0:
        return "c"
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Tat amargo

Tat amarga tira proveito de qualquer tentativa de cooperação dada pelo inimigo quando o inimigo está à frente em pontos. A maioria das bactérias oferece um ramo de oliveira pelo menos uma vez durante as 200 rodadas e, como o Bitter Tat está atrasado, ele ordenhará esses 5 pontos em uma tentativa desesperada de recuperação.

Caso contrário, ele apostará na estratégia dominante usual. Além disso, é um pouco mais idiota do que seu primo e apunhala as costas uma rodada mais cedo e não oferece perdão.

def bittertatfunc(num, i, d, c, enlist):
    if i < d:
        return "d";
    if num >= 198:
        return "d";
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

O Tat amargo foi projetado observando o comportamento de outros bots contra o Tit for Tat e os padrões expressos nesses resultados, mas não foi projetado para combater explicitamente essas estratégias: ainda é uma fórmula de uso geral.

Tat Extra Amargo

def xbittertatfunc(num, i, d, c, enlist):
    if i < d:
        return "d";
    if num >= 188:
        return "d";
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Mais amargo, desertando mais cedo.


11
Por favor, mude o nome da sua função, pois esta já está em uso.
Gryphon - Restabelece Monica

@ Gregry Opa, desculpe, eu não sabia que tinha feito isso. Na verdade, não codifico em Python, apenas esmaguei dois bits de código.
Draco18s não confia mais no SE

11
I suspect it will outperform NeoAnticapitalist by a small margin. Mais de 30.000 pontos.
Gryphon - Restabelece Monica


2
Eu aprecio que você cometeu um bot para fazer este koth não é uma piada mais
Destrutível Lemon

8

Anticapitalista

Outro simples. Para partidas pares (começando com a mesma pontuação) se comporta como TitForTat, mas a idéia principal é tentar sobreviver à partida.

def anticapitalistfunc(counter, mypoints, enpoints, mylist, enlist):
    if mypoints >= enpoints:
        return "c"
    else:
        return "d"

Defector Suave

Minha idéia aqui é desertar, exceto se meu inimigo geralmente estiver cooperando. No entanto, ele começa a cooperar.

def gentleDefectorfunc(counter, mypoints, enpoints, mylist, enlist):
    if enlist.count("d") * 4 > len(enlist):
        return "d"
    else:
        return "c"

NeoAnticapitalist

Uma melhoria do anticapitalista (ou assim eu acho). Não vejo razão para colaborar no último turno. Também não vejo razão para colaborar quando tenho certeza de que meu oponente não o fará.

def neoanticapitalistfunc(counter, mypoints, enpoints, mylist, enlist):
    if mypoints >= enpoints:
        if counter > 1:
            if counter == 199 or (enlist[-1] != "c" and enlist[-2] != "c"):
                return "d"
        return "c"
    else:
        return "d"

Estou realmente surpreso por não ter pensado nisso, mas é brilhante. Não sei se vai ganhar, mas acho que deve funcionar muito bem.
Gryphon - Restabelece Monica

@Gryphon adicionou um novo bot (e fundiu meus dois outros)
Masclins

@Gryphon obrigado por ambas as edições
Masclins

Não há problema, @AlbertMasclans
Gryphon - Reinstate Monica

A partir das simulações que tenho realizado, o NeoAnticapitalist parece ter assumido a liderança de Backstabbing Tit for Tat.
Gryphon - Restabelece Monica

6

Agressor Remorso

from random import randint
def remorsefulaggressorfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter == 0:
        return "d"
    if (counter > 195 and mylist[-1] == "d"):
        return "d"
    if ((counter == 1 or counter > 2) and enlist[-1] == "d"):
        return "d"
    if (counter == 2 and enlist[-1] == "d" and enlist[-2] == "d"):
        return "d"
    if (counter >= 195 and randint(0, 200 - counter) == 0):
        return "d"
    else:
        return "c"

Ele foi projetado para "acompanhar" o Defector, desertando sempre contra ele e também para vencer estratégias baseadas em tetas por tato.

A idéia básica é que começamos a desertar, mas se o oponente cooperou no turno 1, cooperamos duas vezes para evitar um ciclo de recriminação mútuo, evitando assim uma penalidade de ponto muito grande. (Se, no entanto, o adversário falhar mais tarde, não interromperemos o ciclo, faremos com que o façam e provavelmente perderemos o jogo como resultado.) Depois, no final do jogo, escolhemos um tempo aleatório nas últimas 5 voltas, para dar uma punhalada no inimigo, dando-nos mais uma deserção do que eles, o que significa que, desde que não fiquemos muito atrasados ​​nos pontos de transição, acabamos vencendo, sem sacrificar muito em termos de transição no processo. . (Aleatorizar o período significa que é muito provável que entremos em primeiro lugar com o backstab, também que essa estratégia não pode ser "ajustada", com o objetivo de dar um backstab no turno anterior).


Parabéns pelo seu número 3! +1
Gryphon - Restabelece Monica

6

Gatilho Sombrio

Bot simplista, para tentar preencher a competição

Ele cooperará, a menos que o inimigo apresente defeito; nesse caso, ele a implacável

def grimtriggerfunc(I, Do, Not, Care, enlist): return "d" if "d" in enlist else "c"

bem, parece que isso não funciona por causa da meta ntitsfortat de desertar cedo


Parabéns pelo seu número 5, +1.
Gryphon - Restabelece Monica

@ Sleafar eu queria saber quem seria tão mau; _; ok
Destructible Lemon

5

Guerra dos Tronos

def gameofthronesfunc(counter, mypoints, enpoints, mylist, enlist):
    turn_to_betray = 140
    if counter >= turn_to_betray or mypoints > enpoints or "d" in enlist:
        return "d"
    else:
        return "c"

A idéia aqui é que você nunca pode perder traindo, então a única razão para cooperar é se você está atrasado. Ele também possui a estrutura geral das outras respostas T4T (sem perdão, porque não tenho certeza se há muito sentido com os outros concorrentes aqui).

Talvez seja necessário mudar a vez de trair para vencer, pois em uma corrida equilibrada, o T4Ter que trair primeiro vencerá, mas contra um robô muito cooperativo, você perderá alguns pontos da vida. Não tenho certeza do ápice certo para esta colina, então só vou para a 140. Não ficaria surpreso se fosse muito mais cedo.

Se isso acabar em uma placa de Petri com um T4Ter que trai mais cedo ou com um desertor (por exemplo, 146 T4T), depende inteiramente de se o GoT já estiver à frente (permanecerá à frente) ou se estiver quieto / o GoT estiver atrasado , nesse caso o traidor precoce vencerá.


Parabéns pelo terceiro lugar! +1
Gryphon - Restabelece Monica

E agora até o segundo!
Gryphon - Restabelece Monica

Game of Thrones está lutando bastante contra o bot que estou testando atualmente. A estratégia simples está funcionando bem para isso.
Draco18s não confia mais no SE

4

Melharuco afortunado para Tat

import os
def luckytitfortatfunc(num, i, d, c, enlist):
    lucky = ord(os.urandom(1))
    lucky = int(round(200 * float(lucky - 0) / 255.0))
    if lucky == 0:
        return "c"
    if num == 0 or enlist[-1] == "c":
        return "c"
    else:
        return "d"

Tenho certeza de que li em algum lugar que tit por tat era a melhor estratégia. Decidi tornar possível que outros programas se redimissem apenas para adicionar alguma variedade. Agora, com um gerador de números aleatórios adequado (isso me dá uma vantagem, certo?).


Basicamente, esta é a estratégia vencedora, sem dúvida, o tempo todo, conforme observado na wikipedia . A única variação está na probabilidade de romper um ciclo de defeitos tit-for-tat (que depende da combinação de todas as outras entradas).
Draco18s não confia mais no SE

11
@ Draco18s É a estratégia vencedora para um sistema de pontuação diferente, o sistema de pontuação total. O tit-for-tat básico nunca pode ganhar uma rodada, se não levar alguns pontos na rodada, portanto não seria bom.
Isaacg

@isaacg é certo, que é a razão dessa estratégia está agora em 14º de 18 (embora eu não tenho o direito de culpar AH L para este como o programa 18 é um dos meus.)
Gryphon - Reintegrar Monica

4

O elefante

O elefante nunca esquece!

import re
def theelephantfunc(counter, mypoints, enpoints, mylist, enlist):
    interwoven = "".join(i for j in zip(mylist, enlist) for i in j)
    backwoven = interwoven[::-1]
    predict = re.match("^((?:..)*).*?(.).\\1(?:..)*$",backwoven)
    if(predict is None):
        return "c"
    predict = predict.groups()[1]
    if(predict == "d"):
        return "d"
    if(mypoints - enpoints >= 6):
        return "c"
    return "d"

O elefante olha para a história da luta e tenta descobrir o que o inimigo planejou. Ele olha para seus movimentos e seus inimigos!

Ele tenta encontrar o grupo simultâneo mais longo que corresponde ao que acabou de acontecer e pega o que o inimigo fez logo depois.

Se ele não conseguir, o elefante cooperará, pois a amizade é sempre a resposta.

Se ele acha que seu oponente irá desertar, ele também irá desertar, não querendo perder seus pontos conquistados.

Se ele acha que seu oponente cooperará, mas seus menos de ou exatamente 6 pontos de vantagem, então ele desertará, para ganhar alguma posição.

E, finalmente, se ele acha que seu oponente cooperará e ele tem uma liderança forte, ele cooperará.


Eu estava esperando por algo assim que funcionasse melhor que o Cara Bonzinho. No entanto, não poderei testá-lo por cerca de 8 horas, portanto, devo atualizar entre 12 e 13.
Gryphon - Restabelece Monica

4

54 Seios para um Tat

def fiftyfourtitsfortatfunc (num, mais, divertido, eu, en):
    tits = 54
    se "d" em en [-tits:] ou num> = (200-tits):
        retornar "d"
    retornar "c"

Gostaria de saber se isso ainda vai ganhar?
Gryphon - Restabelece Monica

Parece estar ganhando agora!
Gryphon - Restabelece Monica

Parabéns, você venceu por pouco meus dois melhores bots!
Gryphon - Restabelece Monica

@Gryphon eu faria 5 mamas para um tat se eu não estivesse tão ligado para os meus outros bots :)
Alex

Eu acho que estaria passando do outro lado da curva. Eu mesmo posso testar um!
Gryphon - Restabelece Monica

3

Cara legal

def niceguyfunc(counter, mypoints, enpoints, mylist, enlist):
  if counter < 2:
    return "c"

  mylast = mylist[-1]
  enlast = enlist[-1]
  last_found_index = -1

  for i, item in enumerate(mylist):
    if i == counter - 1:
      break
    if mylist[i] == mylast and enlist[i] == enlast:
      last_found_index = i

  if last_found_index == -1:
    return "c"
  else:
    if enlist[last_found_index + 1] == "c":
      return "c"
    else:
      return "d"

Tenta prever a saída dos oponentes olhando o histórico. Por exemplo, se os últimos movimentos foram ( c, inimigo d), ele tenta encontrar a última ocorrência dos mesmos movimentos.


3

Hackman [desqualificado conforme o esperado]

Ok, este provavelmente será excluído do concurso, mas eu realmente sinto vontade de experimentá-lo:

def hackmanfunc(counter, mypoints, enpoints, mylist, enlist):
        if enlist.count("#") > 0:
                return "c"
        elif counter >= 2 and enpoints > mypoints:
                return "d"
        elif counter == 198:
                return "d"
        elif counter == 199:
                return "#"
        elif counter == 0 or enlist[-1] == "c":
                return "c"
        elif counter >= 2 and enlist[-2] != "c":
                return "#"
        else:
                return "d"

Aqui estou tomando como base o BackstabbingTitForTat que provou ser o melhor em minhas simulações. Além disso, é fortemente baseado no uso de um símbolo não usado "#"(é por isso que digo que provavelmente será descartado).

Agora, deixe-me explicar as condições aqui:

1º: Garanta que dois Hackman cooperem se algo der errado.

2º: Se eu vou perder contra um bot diferente, pelo menos faça com que ele perca o máximo de pontos possível, para que não seja um grande inimigo depois.

3º: trair um turno antes, para ganhar contra backstabbing

usar "#" em vez de "d" faz com que eu ganhe 0 pontos em vez de -1 e também me comunico com outro Hackman que tem menos pontos, então ele para de desertar.


2
Desculpe, mas desqualificado. Isso conta como mexer com o processo de julgamento. Você DEVE retornar "c" ou "d" a cada turno.
Gryphon - Restabelece Monica

2
No entanto, isso é bastante inventivo, então lamento ter que desqualificá-lo.
Gryphon - Reinstate Monica

3

Bizzaro

Faz exatamente o oposto de tit para tat. Quando alguém é gentil com ele, ele mostra seu amor por ser mau, e quando alguém é mau, ele mostra vingança por ser bom. Fortemente baseado em tit para tat.

def bizzarofunc(counter, mypoints, enpoints, mylist, enlist):
    if counter==0 or enlist[counter-1] == "c":
        return "d"
    else:
        return "c"

Interessante. Isso vai ser morto por Defector, no entanto.
Gryphon - Restabelece Monica

@Gryphon Lmao, na verdade não percebeu isso. Mas ei, Bizzaro não sabe diferença entre certo e errado, ganha e perde.
TitusLucretius

Sim, isso será desertor em relação ao cooperador e cooperador em relação ao desertor, o que poderia criar algumas possibilidades interessantes. Não pode realmente coexistir com mais nada, inclusive a si próprio.
Gryphon - Restabelece Monica

@ Gregphon, sim, deve receber 0, quando se toca. Imagine o que acontecerá com o Gentle Defector.
TitusLucretius

Gostaria de saber o que acontece quando ele enfrenta uma punhalada pelas costas, que foi o que estava ganhando antes desta finalização.
Gryphon - Restabelece Monica

3

6 mamas para um Tat

def sixtitsforatatfunc (num, mais, divertido, eu, en):
    se "d" em en [-6:] ou num> = 194:
        retornar "d"
    retornar "c"

Tit para corrida armamentista Tat está acontecendo :)


Sinto que vamos ao mar e o Defector roubará o primeiro lugar.
Gryphon - Restabelece Monica

3

Dez mamas para um tat

def tentitsforatatfunc(num, more, fun, me, en):
    if "d" in en[-10:] or num >= 190:
        return "d"
    return "c"

Defeitos anteriores, e também defeitos se seu oponente desertou nos últimos dez turnos.

CopyFirst

def copyfirstfunc(num, mypoints, enpoints, myhistory, enhistory):        
    if num == 0 or num >= 197:
        return "d"
    else:
        return enhistory[0]

Isso falha na primeira rodada e, em seguida, faz o que o oponente fez na primeira rodada, até a 197ª rodada, quando acertou as costas.

Quarenta mamas para um Tat

def fourtytitsforatatfunc(num, mypoints, enpoints, myhistory, enhistory):
    if "d" in en[-40:] or num >= 150:
        return "d"
    return "c"

Se o oponente desertou nos últimos 40 turnos, defeito, caso contrário, coopere. Costas traseiras nas últimas 50 voltas.

Três mamas para um Tat

Se o oponente desertou nos últimos 3 turnos, defeito, caso contrário, coopere. Dê um backstab nas últimas 5 voltas. Este programa roubou a liderança do Tit for Two Tats por uma margem estreita.

def threetitsforatatfunc(num, mypoints, enpoints, myhistory, enhistory):
    if num == 0 or num==1 and enhistory[-1]=="c" or num==2 and enhistory[-1]=="c" and enhistory[-2]=="c":
        return "c"
    if enhistory[-1] == "d" or enhistory[-2] == "d" or enhistory[-3] == "d" or num >= 195:
        return "d"
    else:
        return "c"

Cinco mamas para um tat

def fivetitsforatatfunc(num, more, fun, me, en):
    if "d" in en[-5:] or num >= 194:
        return "d"
    return "c"

Se você não consegue descobrir o que esse faz, você é um idiota. Também dê backstabs uma rodada antes.


IMO, fique à vontade para enviar sua própria inscrição.
Draco18s não confia mais no SE

Só não tinha certeza se era geralmente considerado justo.
Gryphon - Restabelece Monica

O que geralmente é comum, porém, é que a melhor resposta é o bot vencedor.
Masclins

Será, não vou apenas escolher minha própria resposta. Definitivamente, isso não seria justo.
Gryphon - Restabelece Monica

Peço desculpas, eu não tinha percebido que acidentalmente aceitei minha resposta. Agora é inaceitável, e eu vou aceitar a melhor resposta a partir de julho 1.
Gryphon - Reintegrar Monica

3

Careta

def grimacefunc(I, Do, Not, Care, enlist):
    if round < 123: return "d" if "d" in enlist else "c"
    return "d"

Parece que a solução "ideal" para essa colina é fazer algo assim (T4nT com n> 5 é basicamente isso) e apenas otimizar a rodada quando ela trai. Qualquer coisa mais criativa será destruída.
Robert Fraser

3

Every Other D

def everyotherdfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter % 2 == 0:
        return "d"
    else:
        return "c"

Todos os outros C

def everyotherdfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter % 2 == 0:
        return "c"
    else:
        return "d"

Talvez você deva enviar outra entrada começando com cooperar.
Gryphon - Restabelece Monica

Apenas pensei que poderia ser interessante.
Gryphon - Restabelece Monica

3

Matemáticos previsíveis:

Jovem matemático

Novo para a dureza do mundo

import math
def ymathfunc(num, mpoints, enpoints, mlist, enlist):
  if(math.sin(num) + 0.8 > 0):
    return 'c'
  else:
    return 'd'

Matemático mais antigo

Mais experiente nessas questões

import math
def omathfunc(num, mpoints, enpoints, mlist, enlist):
  if(math.cos(num) + 0.8 > 0):
    return 'd'
  else:
    return 'c'

Duvido que qualquer uma dessas coisas se dê bem, mas pelo menos elas acrescentam maneiras de os outros ganharem pontos!


Nenhum deles vai se sair bem, heh. Tudo o que eles fazem é alimentar os desertores, na maior parte.
Draco18s não confia mais no SE

2

Teta aleatória para Tat

import os
def randomtitfortatfunc(forgot, ten, var, iables, enlist):
    luck = enlist.count("d") + 1
    choice = ord(os.urandom(1))
    choice = int(round(luck * float(choice - 0) / 255.0))
    if choice == 0:
        return "c"
    return "d"

Melharuco Para Tat, mas randomizado. Isso não vai ganhar nenhum prêmio (a menos que eu tenha muita sorte). Agora, com números aleatórios gerados a partir de uma fonte adequada.


2

Tat exploratório

O Tat exploratório tenta usar as seguintes estratégias:

  • Defeito quando estiver para trás. É a única maneira de recuperar o atraso.

  • Coopere contra tit-for-tat e estratégias similares. É a única maneira de obter uma boa pontuação a longo prazo.

  • Defeito contra sempre-cooperadores e outros idiotas.

  • Defeito 5 rodadas mais cedo.

Aqui está o código:

def exploitativetatfunc(num, mypoints, enpoints, mylist, enlist):
    if mypoints < enpoints:
        return "d"
    if num >= 195:
        return "d"
    if num == 0:
        return "c"
    # Test defect, and keep defecting as long as they'll allow
    if (num == 5 or num >= 8) and all(choice == "c" for choice in enlist):
        return "d"
    # Recover if that goes wrong, and they were nice.
    if (num == 6 or num == 7) and all(choice == "c" for choice in enlist[:4]):
        return "c"
    # Otherwise, tit for tat.
    return enlist[-1]

Estou surpreso que isso não tenha sido melhor do que empatar em 8º, mas acho que foi a hora errada para isso, e infelizmente foi inserida ao mesmo tempo que Two Tits for a Tat.
Gryphon - Restabelece Monica

2

30 mamas para um Tat

def fiftytitsfortatfunc (num, mais, divertido, eu, en):
    tits = 30
    se "d" em en [-tits:] ou num> = (200-tits):
        retornar "d"
    retornar "c"

2

mas e se ... a próxima resposta não foi um gatilho sombrio ou algo para tat

eu apresento

Anty

def antyfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter > 150: return "d"
    if not "c" in enlist[-2:]:
        return "d"
    if enpoints >= mypoints:
        return "d"
    else:
        return "c"

Interessante, testarei quando eu chegar em casa.
Gryphon - Restabelece Monica

2

Raposa

def foxfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter > enpoints:
        return "d"
    return "c"

Defeitos se o número da rodada for maior que os pontos do inimigo, cooperará de outra forma.

O menino

def boyfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter!=0 and enlist[-1]=="c" and counter <= 194 or enpoints+10<mypoints:
        return "c"
    return "d"

Coopera no primeiro turno, depois atua por tit para tat, mas dá backstabs nas últimas cinco rodadas e falha se não estiver dez pontos à frente.

53 mamas para um tat

def fiftythreetitsfortatfunc(num, more, fun, me, en):
    tits = 53
    if "d" in en[-tits:] or num >= (200-tits):
        return "d"
    return "c"

Vocês todos sabem o que é isso :)


2

Twentyfivetitsforatat

def twentyfivetitsfortatfunc(num, more, fun, me, en):
    tits = 25
    if "d" in en[-tits:] or num >= (200-tits):
        return "d"
    return "c"

Kinda titsforatat

def kindatitsfortatfunc(num, more, fun, me, en):
    tits = 54  
    if "c" in en[-tits:] or num >= (200-tits):
        return "c"
    return "d"

Da próxima vez que você editar para adicionar um programa, adicione um comentário para que eu seja alertado. Obrigado!
Gryphon - Restabelece Monica

@Gryphon oh sorry
Christopher

2

Traidor Prudente

def PrudentBetrayer(counter, mypoints, enpoints, mylist, enlist):
    # Am I ahead, even if he betrays first?
    if mypoints > enpoints + 5:
        if counter == 0:
            return "c"
        else:
            return enlist[-1]
    # Can I catch up if I betray first?
    elif mypoints + 5 > enpoints:
        if counter == 0:
            return "c"
        elif counter > 130:
            return "d"
        else:
            return "d" if "d" in enlist else "c"
    # can't win -> kill his score
    else:
        return "d"

Supõe que está lutando contra n-tits-for-a-tat bot. Se ele tiver o placar a ser traído e ainda vencer, ele permitirá que o outro bot o acerte primeiro (jogando como tacógrafo). robô. Se houver muitos pontos atrás do seu oponente, ele jogará apenas como desertor na tentativa de diminuir a pontuação de bots desavisados.


Aperto de mão

import random
def handshakefunc(num, me, him, m, en):
    handshake = "cdccd"
    # For the first few rounds, give the handshake.
    if num < len(handshake):
        if m == en:
            return handshake[num]
        return "d"
    if en[:len(handshake)] == handshake:
        if me > him:
            return "d"
        if me == him:
            return "ccd"[random.randint(0,2)]
        return "c"
    return "d"

Usa o padrão cdccd nas cinco primeiras rodadas, para descobrir se está com ele mesmo. Nesse caso, ele tentará maximizar seus pontos mantendo o bot com mais pontos sempre com defeito, enquanto o outro sempre coopera. Se achar que está lutando contra um inimigo, jogará com o desertor.

Nos meus testes, acho que a dose é boa se compõe uma parcela significativa da população. Quando a dose não tem chance de se combater, será basicamente reduzida a um desertor.

EDIT: Claramente a partir das pontuações, são muitos os bots para que isso funcione bem. Ainda vencerá se lutar apenas contra os primeiros ...


Bizzaro Trigger

def bizzaroTriggerfunc(round,ms,ts,mm,tm):
  if round==1:return 'c'
  if 'c' in tm:return'd'
  return 'c'

Sempre coopere, a menos que seu oponente jamais coopere com você, caso em que você desertar. Sempre.


@Gryphon, o perdedor dolorido, foi removido e um novo bot foi adicionado!
MegaTom 5/06/19

No teste que estou executando agora em um bot que ainda não publiquei, o Handshake está em 2º lugar após 390 jogos (5338 bots sobreviventes) superando o 54-T4T em cerca de 1200. Meu novo bot é muito mais forte do que isso, no entanto . Os testes iniciais tiveram uma pontuação de 196 em 196, apesar de, a longo prazo, marcar uma média de ~ 124 / jogo. Curiosamente, a base por trás do Handshake era o que eu tentaria a seguir, e você me derrotou sem perceber.
Draco18s não confia mais em

0

FakeShake

tira proveito do aperto de mão - faz um aperto de mão e apenas falha enquanto o aperto de mão confia nele. Quando se encontra, no entanto, faz o aperto de mão 'real'. Se encontrar um bot diferente, ele joga chapinha por tat, com uma traição no final. Isso parece meio ...

import random
def fakeshakefunc(num, i, d, m, enlist):
      secret_handshake="cdccdd"
      handshake= "cdccd"
      #checks if it is meeting itself
      if enlist[:len(secret_handshake)] == secret_handshake:
          if me > him:
            return "d"
          if me == him:
             return "ccd"[random.randint(0,2)]
          return "c"
      #does handshake's handshake,if the bot is not handshake or fakeshake it plays T4T
      if num < len(handshake):
            if m == enlist:
                return handshake[num]
            if i < d or num>= 198:
                return "d";
            if num == 0 or enlist[-1] == "c":
                return "c"
            else:
                return "d"
            if enlist[:len(handshake)] == handshake:
                return "d"
            if i < d or num>= 198:
                return "d";
            if num == 0 or enlist[-1] == "c":
                return "c"
            else:
                return "d"

Um problema com isso é que, se ele atende ao aperto de mão e tem mais pontos, ele pensa que está jogando sozinho. Eu sou um novato em python e neste site (na verdade, esta é minha primeira resposta), portanto, certifique-se de me dizer se cometi algum erro estúpido!


Bem-vindo ao PPCG!
Laikoni

@Laikoni Thanks!
Arkine 17/11/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.