Dilema del prisionero v.3 - Dilema de Petri

17

¡Un científico loco acaba de crear una nueva especie de bacteria! Él ha decidido llamarlo Noblus Gentlemanus, luego de observar su comportamiento. Sin embargo, sus bacterias se han quedado sin comida y han declarado la guerra, ya que pueden cosechar los cadáveres de otras bacterias para obtener suficiente comida para crear copias de sí mismos. Hay varias subespecies diferentes de esta bacteria, que tienen diferentes estrategias para jugar Dilema del prisionero, su juego favorito. Hay cinco bacterias de cada subespecie diferente. En el dilema del prisionero, cada uno de los dos jugadores elige simultáneamente un defecto o cooperar. Si un jugador elige cooperar y el otro elige incumplimiento, el infractor obtiene 2 puntos y el cooperador pierde 3 puntos. Si ambos jugadores eligen cooperar, ambos jugadores obtienen un 1 punto. Si ambos jugadores eligen por defecto, ambos jugadores pierden 1 punto.

Al ser Nobles Caballeros, las bacterias han decidido luchar en esta guerra jugando 200 largos juegos de Dilema del Prisionero Iterado. El perdedor de cada duelo se suicidará, permitiendo que el vencedor se clone a sí mismo. En caso de empate, ambas bacterias permanecerán vivas, pero ninguna podrá clonarse. Además, todas las bacterias de un partido llevan más del 10% de sus puntos al siguiente partido. Un clon arrastra los puntos de la bacteria por la que fue clonado. Además, hay una probabilidad de una en diez de cada turno de que una bacteria mute en otra subespecie, con 0 puntos de bonificación (si recibo quejas sobre la aleatoriedad de esto, puedo eliminarla). Después de que las bacterias hayan jugado un número de estos duelos igual al número de subespecies de bacterias multiplicado por diez, el científico loco deja caer accidentalmente la placa de Petri en la que residen las bacterias, y todas las bacterias adquieren nuevas fuentes de alimentos, terminando sus duelos. Esto es diferente de un concurso de dilema de prisionero iterativo ordinario, ya que involucra duelos 1v1 con puntos de arrastre, en lugar de simplemente intentar obtener la mayor cantidad de puntos en general. Esto hace una gran diferencia en la efectividad de una estrategia dada.

Cada bacteria recibirá información al comienzo de su turno en el formato: (número de turno, puntos actuales, puntos enemigos, sus movimientos anteriores [en una cadena, usando el carácter "c" para cooperar y el carácter "d" para defectos ], movimientos previos enemigos [en el mismo formato]).

Aquí hay cuatro estrategias de muestra que se ingresarán. De hecho, creo que Defector podría ganar, aunque sea extremadamente simple.

Tal para cual

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"

Desertor

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

Todos los envíos deben tener la forma de una función Python 2.7, con el nombre del envío sin espacios, funcal final. Si alguien desea enviar una respuesta en un idioma diferente, ingrésela en pseudocódigo, para que yo pueda convertir a Python en una edición a su respuesta una vez que tenga tiempo, o darme instrucciones sobre la interfaz de su idioma con mi controlador que se encuentra a continuación configurado para todas las presentaciones desde el 4 de junio.

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 ya está terminado

Si desea agregar una respuesta, veré si puedo agregar un tablero de puntuación posterior al desafío para los concursantes originales. Lo agregaré tan pronto como finalice el programa de prueba (probablemente 2-3 días más).

PUNTUACIONES FINALES !!!!!

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

Entonces, parece que Perfect Gentleman es el ganador. Felicitaciones a Draco18, quien definitivamente merece su marca de verificación verde.

Gryphon - Restablece a Monica
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Dennis
1
NOTA: SI ESTÁS EDITANDO TU PROGRAMA, POR FAVOR, DAME UN COMENTARIO PARA QUE LO AVISO, O PUEDE NO PONERSE EN EL MARCADOR POR UN MOMENTO !!!!!!!!!!!!!!!!!!!! !!!
Gryphon - Restablece a Monica el
¡Ay! Me acabo de dar cuenta de cuántas importaciones son.
Gryphon - Restablece a Monica el
1
Hola Gryphon, ¿estás trabajando en esas clasificaciones finales? ;)
Draco18s ya no confía en SE
Lo siento, me olvidé de esto. Dame un poco para ejecutarlo.
Gryphon - Restablece a Mónica el

Respuestas:

8

El caballero perfecto

No tengo una buena descripción para este bot. Me topé con un par de optimizaciones potenciales, las probé, ajusté y terminé con una bacteria que destruye completamente a la competencia. En cambio, he comentado el código en sí para explicar lo que hace.

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]

Varios valores fueron elegidos arbitrariamente con alternativas probadas y los valores aquí son casi óptimos en este punto. Contra la propagación actual de facciones opuestas, The Perfect Gentleman logra el dominio completo (100% de la población de bacterias) aproximadamente el 90% del tiempo (más o menos 3 puntos porcentuales).

Todavía no he agregado los Matemáticos a mis pruebas, sin embargo, esos dos solo deberían servir para alimentar las estrategias existentes y no alterar el resultado en gran medida.

Gestiona una buena parte de su control al apuntalar a Defector, pero eso estaba permitido según las reglas (las estrategias de ejemplo eran un juego justo para apuntar). Tiene un efecto secundario de la también apuntalando Juego de Tronos, pero que no fue intencional ya que los dos son indistinguibles en base a los criterios que elegí. Esos "tipos de desertores" tienen una ventaja de puntos en la ronda 2 y, como resultado, eliminan a varios vecinos problemáticos (los tipos N-T4T) y cuando cambian el The Perfect Gentleman, han gastado su ventaja de puntos y se consumen rápidamente.

Hay una probabilidad aproximada del 5% de que todos los Caballeros Perfectos terminen emparejados con los tipos Defector en la primera ronda y terminen cometiendo suicidio en masa. En cuyo caso, uno de los tipos n-T4t logra la dominación total (196 células de 196). Muy raramente, uno de los otros tipos (Game of Thrones, Boy, Grimace, Sore Loser ...) logran no extinguirse por completo y sumar un punto o dos.

Simulación actual (todavía en progreso hacia 200 juegos en total). Todas las entradas con puntaje 0 eliminadas. Parece que Game of Thrones y 54-T4T dividieron una ronda (195 puntos entre ellos) después de que PG fue 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

Teta de puñalada por Tat (con perdón)

Esto es básicamente Lucky Tit para Tat (también conocido como Tit para Tat con Perdón), que es la solución óptima "resuelta" (por cierto valor de "suerte"), con un giro. Como sabemos exactamente cuántas rondas durará el juego, esta bacteria apuñala por la espalda en la ronda final, lo que garantiza un resultado neto beneficioso contra cualquier otra Tit para las bacterias Tat y Cooperator (contra sí misma termina con un cero neto, igual que si hubiera tenido cooperado). Debido al 10% de arrastre, esto resulta en una ventaja a largo plazo.

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 amargo se aprovecha de cualquier intento de cooperación dado por el enemigo cuando el enemigo está por delante en puntos. La mayoría de las bacterias ofrecen una rama de olivo al menos una vez durante las 200 rondas, y como Bitter Tat está atrasado en general, extraerá esos 5 puntos en un intento desesperado por recuperarse.

De lo contrario, se tit-por-tats según la estrategia dominante habitual. Además, es un poco más un idiota que su primo y apuñala por la espalda una ronda antes y no ofrece perdón.

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"

Bitter Tat fue diseñado mediante la observación de los comportamientos de otros bots contra Tit for Tat y los patrones expresados ​​en esos resultados, pero no está diseñado para contrarrestar explícitamente esas estrategias: sigue siendo una fórmula de propósito general.

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"

Extra amargo al desertar más temprano.

Draco18s ya no confía en SE
fuente
1
Cambie el nombre de su función, ya que esta ya está ocupada.
Gryphon - Restablece a Monica
@Gryphon Whoops, lo siento, no me di cuenta de que había hecho eso. En realidad no codifico en Python, simplemente rompí dos bits de código juntos.
Draco18s ya no confía en SE
1
I suspect it will outperform NeoAnticapitalist by a small margin. Más como por más de 30,000 puntos.
Gryphon - Restablece a Monica
1
Continuemos esta discusión en el chat .
Draco18s ya no confía en SE
2
Aprecio que hayas hecho un bot para que este koth ya no sea una broma
Destructible Lemon
8

Anticapitalista

Otro simple. Para los partidos pares (comenzando con el mismo puntaje) se comporta más o menos como TitForTat, pero la idea principal es tratar de sobrevivir al partido.

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

Defector apacible

Mi idea aquí es desertar, excepto si mi enemigo generalmente está cooperando. Sin embargo, comienza a cooperar.

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

NeoAnticapitalista

Una mejora del anticapitalista (o eso creo). No veo ninguna razón para colaborar en el último turno. Tampoco veo ninguna razón para colaborar cuando estoy bastante seguro de que mi oponente no lo hará.

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"
Masclins
fuente
De hecho, me sorprende no haber pensado en esto, pero es brillante. No sé si ganará, pero creo que debería funcionar muy bien.
Gryphon - Restablece a Monica
@Gryphon agregó un nuevo bot (y fusionó mis otros dos)
Masclins
@Gryphon gracias por ambas ediciones
Masclins
No hay problema, @AlbertMasclans
Gryphon - Restablece a Monica
De las simulaciones que he estado ejecutando, NeoAnticapitalist parece haber tomado la delantera de Backstabbing Tit para Tat.
Gryphon - Restablece a Monica
6

Agresor arrepentido

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"

Esto está diseñado para "mantenerse al día" con Defector, al desertar cada vez en su contra, y también para vencer las estrategias basadas en el ojo por ojo.

La idea básica es que empecemos por desertar, pero si el oponente cooperó en el turno 1, cooperamos dos veces para evitar un ciclo de recriminación mutua, evitando así una penalización de puntos demasiado grande. (Sin embargo, si el oponente falla más adelante, no rompemos el ciclo nosotros mismos; haremos que lo hagan y probablemente perdamos el juego como resultado). Luego, al final del juego, elegimos un tiempo aleatorio en los últimos 5 turnos para apuñalar por la espalda al enemigo, dándonos una deserción más que ellos y, por lo tanto, siempre y cuando no estemos muy atrasados ​​en los puntos de arrastre, terminamos ganando, sin sacrificar mucho en términos de arrastre en el proceso . (Aleatorizar el período de tiempo significa que es muy probable que lleguemos primero con la puñalada por la espalda, también que esta estrategia no se puede "sintonizar" con el objetivo de apuñalar por la espalda una vuelta antes).

Gryphon - Restablece a Monica
fuente
¡Felicidades por tu puesto número 3! +1
Gryphon - Restablece a Monica
6

Gatillo sombrío

Bot simplista, para intentar completar la competencia.

Cooperará, a menos que el enemigo presente defectos, en cuyo caso presenta defectos imperdonables.

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

bueno, parece que esto no funciona debido al ntitsfortat meta de desertar temprano

Limón Destructible
fuente
Felicidades por tu puesto número 5, +1.
Gryphon - Restablece a Monica
@Sleafar Me preguntaba quién sería tan malo; _; ok
Destructible Lemon
5

Game of Thrones

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"

La idea aquí es que nunca puedes perder traicionando, por lo que la única razón para cooperar es si estás atrasado. También tiene el marco general de las otras respuestas T4T (sin ningún perdón, porque no estoy seguro de si tiene mucho sentido con los otros contendientes aquí).

Es posible que sea necesario cambiar el turno para traicionar para ganar, ya que en una carrera pareja, el T4Ter que traiciona primero ganará, pero contra un robot muy cooperativo, perderá algunos puntos de por vida. No estoy seguro del vértice correcto para esta colina, así que solo voy por 140. Sin embargo, no me sorprendería si fuera mucho antes.

Si esto termina en una placa de Petri con un T4Ter que traiciona antes o un desertor (es decir, 146 T4T), entonces depende completamente de si el GoT ya está adelante (se mantendrá adelante) o si están a la par / GoT está detrás , en cuyo caso el traidor temprano ganará.

Robert Fraser
fuente
¡Felicidades por tu tercer puesto! +1
Gryphon - Restablece a Monica
Y ahora hasta el segundo!
Gryphon - Restablece a Monica el
Game of Thrones está luchando bastante contra el bot que estoy probando actualmente. La estrategia simple está funcionando bien para ello.
Draco18s ya no confía en SE
4

Lucky Tit For 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"

Estoy bastante seguro de que leí en alguna parte que ojo por ojo era la mejor estrategia. Decidí hacer posible que otros programas se redimieran solo para agregar alguna variedad. Ahora con un generador de números aleatorios adecuado (me da una ventaja, ¿verdad?).

Alex
fuente
Básicamente, esta es la estrategia ganadora, sin lugar a dudas, todo el tiempo como se señala en wikipedia . La única variación está en la probabilidad de romper un ciclo de defectos de ojo por ojo (que depende del emparejamiento de todas las otras entradas).
Draco18s ya no confía en SE
1
@ Draco18s Es la estrategia ganadora para un sistema de puntuación diferente, el sistema de puntuación total de puntos. El juego básico tit-for-tat nunca puede ganar una ronda, si no lleva algunos puntos a la ronda, por lo que no funcionaría bien.
isaacg
@isaacg es correcto, que es la razón de esta estrategia es ahora en el puesto 14 de los 18 (aunque no tengo derecho a culpar AH L para esto como el programa 18a es una de las mías.)
Gryphon - Restablecer Mónica
4

El elefante

¡El elefante nunca olvida!

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"

El elefante mira la historia de la pelea e intenta descubrir qué ha planeado el enemigo. ¡Mira sus movimientos y sus enemigos!

Intenta encontrar el grupo concurrente más largo que coincida con lo que acaba de suceder, y toma lo que hizo el enemigo justo después de eso.

Si no puede resolverlo, el Elefante simplemente cooperará, ya que la amistad es siempre la respuesta.

Si cree que su oponente desertará, él también desertará, no queriendo perder sus puntos ganados con tanto esfuerzo.

Si cree que su oponente cooperará, pero su ventaja de menos de o exactamente 6 puntos, entonces desertará, para ganar un punto de apoyo.

Y, por último, si cree que su oponente cooperará y tiene una fuerte ventaja, cooperará.

Un taco
fuente
Estaba esperando algo como esto que funcionó mejor que Nice Guy. Sin embargo, no podré probarlo durante aproximadamente 8 horas, por lo que debería poder actualizar en aproximadamente 12-13.
Gryphon - Restablece a Monica
4

54 tetas para un tat

def fiftyfourtitsfortatfunc (num, more, fun, me, en):
    tetas = 54
    si "d" en es [-tits:] o num> = (200-tits):
        volver "d"
    volver "c"
Alex
fuente
Me pregunto si esto seguirá ganando?
Gryphon - Restablece a Monica
¡Esto parece estar ganando ahora mismo!
Gryphon - Restablece a Monica
¡Felicidades, superaste estrechamente a mis dos mejores bots!
Gryphon - Restablece a Monica
@Gryphon Haría 5 tetas por un tatuaje si no estuviera tan apegado a mis otros bots :)
Alex
Creo que eso iría al otro lado de la curva. ¡Aunque podría probar uno yo mismo!
Gryphon - Restablece a Monica
3

Buen chico

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"

Intenta predecir la salida de los oponentes mirando el historial. Por ejemplo, si los últimos movimientos fueron ( c, enemigo d), intenta encontrar la última aparición de los mismos movimientos.

CommonGuy
fuente
3

Hackman [descalificado como se esperaba]

Ok, este probablemente será descartado del concurso, pero realmente tengo ganas de probarlo:

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"

Aquí estoy tomando como base el BackstabbingTitForTat que resultó ser el mejor en mis simulaciones. Además, se basa en gran medida en el uso de un símbolo no utilizado"#" (por eso digo que probablemente se descartará).

Ahora déjame explicarte las condiciones aquí:

1º: Asegúrese de que dos Hackman cooperen si algo sale mal.

2º: Si voy a perder contra un bot diferente, al menos haz que pierda tantos puntos como sea posible, por lo que no es un gran enemigo después.

3 °: Traicionar un turno antes, así que gana vs Backstabbing

usar "#" en lugar de "d" me hace obtener 0 puntos en lugar de -1 y también comunicarme con otros Hackman que tienen menos puntos, por lo que deja de desertar.

Masclins
fuente
2
Lo siento, pero descalificado. Esto cuenta como perder el tiempo con el proceso de juzgar. DEBE devolver "c" o "d" cada turno.
Gryphon - Restablece a Monica
2
Sin embargo, esto es bastante ingenioso, así que lamento tener que descalificarlo.
Gryphon - Restablece a Monica
3

Bizzaro

Hace exactamente lo contrario de tit por tat. Cuando alguien es amable con él, muestra su amor siendo malvado, y cuando alguien es malo, muestra venganza por ser bueno. Fuertemente basado en tit por tat.

def bizzarofunc(counter, mypoints, enpoints, mylist, enlist):
    if counter==0 or enlist[counter-1] == "c":
        return "d"
    else:
        return "c"
Tito Lucrecio
fuente
Interesante. Sin embargo, esto será asesinado por Defector.
Gryphon - Restablece a Monica
@Gryphon Lmao, en realidad no se dio cuenta de eso. Pero bueno, Bizzaro no sabe la diferencia entre lo correcto y lo incorrecto, gana y pierde.
TitusLucretius
Sí, esto será desertor hacia cooperador y cooperador hacia desertor, lo que podría generar algunas posibilidades interesantes. Realmente no puede coexistir con nada más, incluido él mismo.
Gryphon - Restablece a Monica
@Gryphon, sí, debería obtener 0, cuando se juega solo. Me pregunto qué pasará con Gentle Defector.
TitusLucretius
Me pregunto qué pasará cuando se enfrente a puñaladas por tat, que es lo que estaba ganando antes de esta presentación.
Gryphon - Restablece a Monica
3

6 tetas para un tat

def sixtitsforatatfunc (num, more, fun, me, en):
    si "d" en es [-6:] o num> = 194:
        volver "d"
    volver "c"

Teta para la carrera armamentista Tat está sucediendo :)

Alex
fuente
Siento que vamos a ir por la borda y Defector robará el primer puesto.
Gryphon - Restablece a Monica
3

Diez tetas para un tat

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

Defectos anteriores, y también defectos si su oponente ha desertado en los últimos diez turnos.

Copiar Primero

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

Esto daña la primera ronda, luego hace lo que el oponente hizo en la primera ronda, hasta la 197ª ronda, cuando apuñala por la espalda.

Cuarenta tetas por un Tat

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

Si el oponente desertó en los últimos 40 turnos, defecto, de lo contrario coopere. Puñalada en los últimos 50 turnos.

Tres tetas para un tat

Si el oponente desertó en los últimos 3 turnos, defecto, de lo contrario coopere. Puñalada en los últimos 5 turnos. Este programa ha robado la ventaja de Tit for Two Tats por un margen estrecho.

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 tetas para un tat

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

Si no puedes entender lo que hace, eres un idiota. También apuñala por la espalda una ronda antes.

Gryphon - Restablece a Monica
fuente
OMI, no dude en enviar su propia entrada.
Draco18s ya no confía en SE
Simplemente no estaba seguro de si en general se consideraba justo.
Gryphon - Restablece a Monica
Sin embargo, lo que suele ser común es que Best Answer es el bot ganador.
Masclins
Será, no elegiré mi propia respuesta. Eso definitivamente no sería justo.
Gryphon - Restablece a Monica
Pido disculpas, no me había dado cuenta de que había aceptado accidentalmente mi respuesta. Ahora no está aceptado, y aceptaré la mejor respuesta a partir del 1 de julio.
Gryphon - Restablece a Monica
3

Mueca

def grimacefunc(I, Do, Not, Care, enlist):
    if round < 123: return "d" if "d" in enlist else "c"
    return "d"
Limón Destructible
fuente
Parece que la solución "óptima" para esta colina es hacer algo como esto (T4nT con n> 5 es básicamente esto), y simplemente optimizar la ronda cuando traiciona. Cualquier cosa más creativa será destruida.
Robert Fraser
3

Cada otro D

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

Todos los demás c

def everyotherdfunc(counter, mypoints, enpoints, mylist, enlist):
    if counter % 2 == 0:
        return "c"
    else:
        return "d"
Stephen
fuente
Tal vez debería enviar otra entrada comenzando con cooperar.
Gryphon - Restablece a Monica el
Solo pensé que podría ser interesante.
Gryphon - Restablece a Monica el
3

Matemáticos predecibles:

Joven matemático

Nuevo en la dureza del mundo.

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

Matemático mayor

Más experiencia en estos asuntos.

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

Dudo que alguno de estos funcione bien, pero al menos agregarán formas para que otros obtengan puntos.

Panda0nEarth
fuente
A ninguno de estos les va a ir bien, je. Todo lo que hacen es alimentar a los desertores, en su mayor parte.
Draco18s ya no confía en SE
2

Tit aleatorizado 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"

Tit For Tat, pero al azar. Esto no va a ganar ningún premio (a menos que tenga mucha suerte). Ahora con números aleatorios generados a partir de una fuente adecuada.

Alex
fuente
2

Tat explotador

Explotador Tat intenta jugar las siguientes estrategias:

  • Defecto cuando está atrás. Es la única forma de ponerse al día.

  • Coopere contra las estrategias de ojo por ojo y similares. Es la única forma de obtener una buena puntuación a largo plazo.

  • Defecto contra los siempre cooperadores y otros tontos.

  • Defecto 5 rondas temprano.

Aquí está el 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]
isaacg
fuente
Me sorprende que esto no haya sido mejor que empatar en el octavo puesto, pero creo que fue el momento equivocado, y desafortunadamente se ingresó al mismo tiempo que Two Tits for a Tat.
Gryphon - Restablece a Monica
2

30 tetas para un tat

def treintatitsfortatfunc (num, more, fun, me, en):
    tetas = 30
    si "d" en es [-tits:] o num> = (200-tits):
        volver "d"
    volver "c"
Alex
fuente
2

pero qué pasa si ... la siguiente respuesta no fue un desencadenante sombrío o algo por el estilo

estoy presente

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"
Limón Destructible
fuente
Intersting, probará cuando llegue a casa.
Gryphon - Restablece a Monica el
2

zorro

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

Defectos si el número de ronda es mayor que los puntos enemigos, coopera de otra manera.

El chico

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 en la primera ronda, luego actúa por ojo por ojo, pero apuñala por la espalda en las últimas cinco rondas, y falla si no tiene diez puntos de ventaja.

53 tetas por un tatuaje

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

Todos ustedes saben lo que es :)

astuto
fuente
2

Twentyfivetitsforatat

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

Un poco de tetas

def kindatitsfortatfunc(num, more, fun, me, en):
    tits = 54  
    if "c" in en[-tits:] or num >= (200-tits):
        return "c"
    return "d"
Christopher
fuente
La próxima vez que edite para agregar un programa, agregue también un comentario para que me avisen. ¡Gracias!
Gryphon - Restablece a Monica el
@Gryphon oh lo siento
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"

Asume que está luchando contra un n-tits-for-a-tatbot. Si tiene el puntaje para ser traicionado y sigue ganando, permitirá que el otro bot lo golpee primero (jugando como tit for tat). Si puede ganar solo cuando traiciona primero, traicionará en la ronda 130, mucho antes de cualquier corriente larva del moscardón. Si está a muchos puntos de su oponente, solo jugará al desertor en un intento de reducir la puntuación de los bots desprevenidos.


Apretón de manos

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 el patrón cdccd en las primeras cinco rondas, para averiguar si está consigo mismo. Si es así, intentará maximizar sus puntos haciendo que el bot con más puntos siempre tenga defectos, mientras que el otro siempre coopera. Si descubre que está luchando contra un enemigo, jugará al desertor.

En mis pruebas, encuentro que se dosifica bien si constituye una porción significativa de la población. Cuando no tiene la oportunidad de luchar contra sí mismo, básicamente se reducirá a un desertor.

EDITAR: Claramente a partir de los puntajes, hay muchos bots para que esto funcione bien. Todavía ganará si pelea solo con los primeros ...


Bizzaro Trigger

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

Siempre coopere, a menos que su oponente coopere con usted, en cuyo caso usted desertará. Siempre.

MegaTom
fuente
¡@Gryphon, el perdedor dolorido, fue eliminado y se agregó un nuevo bot!
MegaTom
En la prueba que estoy ejecutando ahora en un bot que aún no he publicado, Handshake ocupa el segundo lugar después de 390 juegos (5338 bots sobrevivientes) superando el 54-T4T en aproximadamente 1200. Sin embargo, mi nuevo bot es mucho más fuerte que eso. . Las pruebas iniciales lo hicieron puntuar 196 de 196, aunque a largo plazo está obteniendo un promedio de ~ 124 / juego. Curiosamente, la base detrás de Handshake era lo que iba a intentar a continuación, resulta que me ganaste sin que me diera cuenta.
Draco18s ya no confía en SE
0

FakeShake

aprovecha el apretón de manos: hace un apretón de manos y luego solo defectos mientras el apretón de manos confía en él. Cuando se encuentra, sin embargo, hace el apretón de manos 'real'. Si se encuentra con un bot diferente, juega tit for tat, con una traición al final. Esto se siente un poco malo ...

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"

Un problema con esto es que si se encuentra con el apretón de manos y tiene más puntos, piensa que está jugando solo. Soy un novato en Python y este sitio (de hecho, esta es mi primera respuesta), así que asegúrese de decirme si he cometido algún error estúpido.

Arkine
fuente
Bienvenido a PPCG!
Laikoni
@Laikoni ¡Gracias!
Arkine