ESTADO DEL DESAFÍO: ABIERTO
Comenta, abre un RP o grítame si me falta tu bot.
El dilema del prisionero ... con tres opciones. Loco, ¿eh?
Aquí está nuestra matriz de pagos. Jugador A a la izquierda, B en la parte superior
A,B| C | N | D
---|---|---|---
C |3,3|4,1|0,5
N |1,4|2,2|3,2
D |5,0|2,3|1,1
La matriz de pagos está diseñada para que sea mejor para ambos jugadores cooperar siempre, pero puedes ganar (generalmente) eligiendo Neutral o Defection.
Aquí hay algunos bots de ejemplo (competidores).
# turns out if you don't actually have to implement __init__(). TIL!
class AllC:
def round(self, _): return "C"
class AllN:
def round(self, _): return "N"
class AllD:
def round(self, _): return "D"
class RandomBot:
def round(self, _): return random.choice(["C", "N", "D"])
# Actually using an identically-behaving "FastGrudger".
class Grudger:
def __init__(self):
self.history = []
def round(self, last):
if(last):
self.history.append(last)
if(self.history.count("D") > 0):
return "D"
return "C"
class TitForTat:
def round(self, last):
if(last == "D"):
return "D"
return "C"
Tu bot es una clase Python3. Se crea una nueva instancia para cada juego, y round()
se llama cada ronda, con la elección de su oponente de la última ronda (o Ninguno, si es la primera ronda)
Hay una recompensa de 50 repeticiones para el ganador en como un mes.
Detalles específicos
- Cada bot juega a cualquier otro bot (1v1), incluido él mismo, en rondas [ELIMINADO].
- Lagunas estándar no permitidas.
- No te metas con nada fuera de tu clase u otras travesuras deshonestas.
- Puedes enviar hasta cinco bots.
- Sí, puedes implementar un apretón de manos.
- Cualquier respuesta que no sea
C
,N
o seD
tomará en silencio comoN
. - Los puntos de cada bot de cada juego que jueguen se sumarán y compararán.
Controlador
Otros idiomas
Prepararé una API si alguien la necesita.
Puntajes: 2018-11-27
27 bots, 729 games.
name | avg. score/round
----------------|-------------------
PatternFinder | 3.152
DirichletDice2 | 3.019
EvaluaterBot | 2.971
Ensemble | 2.800
DirichletDice | 2.763
Shifting | 2.737
FastGrudger | 2.632
Nash2 | 2.574
HistoricAverage | 2.552
LastOptimalBot | 2.532
Number6 | 2.531
HandshakeBot | 2.458
OldTitForTat | 2.411
WeightedAverage | 2.403
TitForTat | 2.328
AllD | 2.272
Tetragram | 2.256
Nash | 2.193
Jade | 2.186
Useless | 2.140
RandomBot | 2.018
CopyCat | 1.902
TatForTit | 1.891
NeverCOOP | 1.710
AllC | 1.565
AllN | 1.446
Kevin | 1.322
king-of-the-hill
python
SIGSTACKFAULT
fuente
fuente
while len(botlist) > 1:
labotlist.remove(lowest_scoring_bot)
en la parte inferior del bucle, se obtiene un torneo de eliminación con resultados interesantes.Respuestas:
EvaluaterBot
Gana contra todos los bots enviados anteriormente, excepto (tal vez) el bot aleatorio (pero podría tener una ventaja, ya que elige D en un sorteo y D debería ser óptimo) y juega un sorteo constante contra ellos mismos.
fuente
Equilibrio de Nash
Este bot ha tomado una clase de teoría de juegos en la universidad, pero fue flojo y no fue a la clase donde cubrieron juegos iterativos. Por lo tanto, solo juega un solo juego de equilibrio mixto nash. Resulta que 1/5 2/5 2/5 es el NE mixto para los pagos.
Equilibrio constante de abuso de Nash
Este robot aprendió una o dos lecciones de su hermano perezoso. El problema de su hermano perezoso era que no aprovechaba las estrategias fijas. Esta versión verifica si el oponente es un jugador constante o titfortat y juega en consecuencia, de lo contrario, juega el equilibrio nash regular.
El único inconveniente es que promedia 2.2 puntos por turno jugando contra sí mismo.
fuente
class NashEquilibrium: def round(self, _): a = random.random() for k, v in [(0.2, "C"), (0.6, "N"), (1, "D")]: if a <= k: return v
TatForTit
Este bot alternará eligiendo DNDN mientras TitForTat alterna CDCD, para una ganancia neta promedio de 3 puntos por ronda si he leído la matriz de pagos correctamente. Creo que esto podría ser óptimo contra TitForTat. Obviamente, podría mejorarse detectar a un oponente que no sea TFT y adoptar otras estrategias, pero solo apuntaba a la recompensa original.
fuente
PatternFinder
Este bot busca ocurrencias previas del estado reciente del juego para ver cómo respondió el oponente a esas ocurrencias, con preferencia por partidos de patrón más largos y partidos más recientes, luego juega el movimiento que "vencerá" el movimiento predicho del oponente. Hay mucho espacio para que sea más inteligente con todos los datos que rastrea, pero se me acabó el tiempo para trabajar en ello.
fuente
Jade
Comienza optimista, pero se vuelve cada vez más amargo a medida que el oponente se niega a cooperar. Muchas constantes mágicas que probablemente podrían modificarse, pero esto probablemente no sea lo suficientemente bueno como para justificar el tiempo.
fuente
Conjunto
Esto ejecuta un conjunto de modelos relacionados. Los modelos individuales consideran diferentes cantidades de historial y tienen la opción de elegir siempre el movimiento que optimizará la diferencia de pago esperada o seleccionar aleatoriamente un movimiento en proporción a la diferencia de pago esperada.
Cada miembro del conjunto vota sobre su movimiento preferido. Obtienen una cantidad de votos igual a cuánto más han ganado que el oponente (lo que significa que los modelos terribles obtendrán votos negativos). Cualquier movimiento que gane el voto se selecciona.
(Probablemente deberían dividir sus votos entre los movimientos en proporción a cuánto favorecen cada uno, pero no me importa lo suficiente como para hacerlo ahora).
Es mejor que todo lo publicado hasta ahora, excepto EvaluaterBot y PatternFinder. (Uno a uno, supera a EvaluaterBot y pierde a PatternFinder).
Marco de prueba
En caso de que alguien más lo encuentre útil, aquí hay un marco de prueba para mirar emparejamientos individuales. Python2. Simplemente coloque a todos los oponentes que le interesan en oponents.py, y cambie las referencias a Ensemble a las suyas.
fuente
OldTitForTat
El jugador de la vieja escuela es demasiado vago para actualizarse para las nuevas reglas.
fuente
NeverCOOP
Si el bot contrario tiene defectos o es neutral, elige defecto. De lo contrario, si este es el primer turno o el robot contrario coopera, elige neutral. No estoy seguro de lo bien que funcionará ...
fuente
if(last):
en su bot Grudger, detectando si hubo una ronda anterior.None in "ND"
erroresif last and last in "ND":
era demasiado complicado?LastOptimalBot
Asume que el bot contrario siempre volverá a jugar el mismo movimiento y elige el que tenga la mejor recompensa.
Promedios:
fuente
return last
.return last
, LOB iría 18-9 en 6 rondas en lugar de 13-10 en 5 rondas que está recibiendo actualmente. Creo que está bien como está: no se preocupe por optimizar los bots de ejemplo.return last
sería un mejor T4T para este desafío, creoif(last): return last; else: return "C"
es peor.CopyCat
Copia el último movimiento del oponente.
No espero que esto funcione bien, pero nadie ha implementado este clásico todavía.
fuente
Dados Dirichlet mejorados
Esta es una versión mejorada de Dirichlet Dice. En lugar de tomar la distribución multinomial esperada de la distribución Dirichlet, dibuja una distribución Multinomial aleatoriamente de la distribución Dirichlet. Luego, en lugar de extraer del Multinomial y dar la respuesta óptima a eso, da la respuesta óptima esperada al Multinomial dado usando los puntos. Por lo tanto, la aleatoriedad se ha cambiado esencialmente del sorteo Multinomial al sorteo Dirichlet. Además, los antecedentes son más planos ahora, para alentar la exploración.
Se "mejoró" porque ahora da cuenta del sistema de puntos al dar el mejor valor esperado contra las probabilidades, mientras mantiene su aleatoriedad al dibujar las probabilidades mismas. Antes, intenté simplemente hacer la mejor recompensa esperada de las probabilidades esperadas, pero eso fue mal porque se quedó atascado y no exploré lo suficiente como para actualizar sus dados. También fue más predecible y explotable.
Presentación original:
Dados Dirichlet
Básicamente, supongo que la respuesta del oponente a mi última salida es una variable multinomial (dados ponderados), una para cada una de mis salidas, por lo que hay un dado para "C", uno para "N" y uno para "D" . Entonces, si mi último lanzamiento fue, por ejemplo, una "N", entonces saco el "N-dice" para adivinar cuál sería su respuesta a mi "N". Comienzo con un Dirichlet antes que asume que mi oponente es algo "inteligente" (es más probable que juegue el que tenga la mejor recompensa contra mi última tirada, menos probable que juegue el que tenga la peor recompensa). Genero la distribución Multinomial "esperada" a partir del Dirichlet apropiado antes (este es el valor esperado de la distribución de probabilidad sobre sus pesos de dados). Lanzo los dados ponderados de mi última salida,
Comenzando en la tercera ronda, hago una actualización bayesiana del Dirichlet apropiado antes de la última respuesta de mi oponente a lo que jugué hace dos rondas. Estoy tratando de aprender iterativamente sus ponderaciones de dados.
También podría haber elegido simplemente la respuesta con el mejor resultado "esperado" una vez que genera el dado, en lugar de simplemente tirar el dado y responder al resultado. Sin embargo, quería mantener la aleatoriedad, para que mi bot sea menos vulnerable a los que intentan predecir un patrón.
fuente
Kevin
Elige la peor opción. El peor bot hecho.
Inútil
Mira los dos últimos movimientos realizados por el oponente y elige la mayoría de los no hechos, de lo contrario, elige algo al azar. Probablemente hay una mejor manera de hacer esto.
fuente
Promedio histórico
Mira la historia y encuentra la acción que habría sido mejor en promedio. Comienza a cooperar.
fuente
Peso promedio
El comportamiento del oponente se modela como un triángulo rectángulo con esquinas para CND a 0,0 0,1 1,0 respectivamente. Cada movimiento del oponente desplaza el punto dentro de ese triángulo hacia esa esquina, y jugamos para vencer el movimiento indicado por el punto (a C se le da una pequeña porción ajustable del triángulo). En teoría, quería que esto tuviera una memoria más larga con más peso para los movimientos anteriores, pero en la práctica el meta actual favorece a los robots que cambian rápidamente, por lo que esto se convierte en una aproximación de LastOptimalBot contra la mayoría de los enemigos. Publicar para la posteridad; Quizás alguien se inspire.
fuente
Tetragrama
Intenta encontrar un patrón en los movimientos del oponente, suponiendo que también estén viendo nuestro último movimiento.
fuente
Apretón de manos
Reconoce cuándo está jugando contra sí mismo, luego coopera. De lo contrario, imita LastOptimalBot, que parece ser la mejor estrategia de una línea. Funciona peor que LastOptimalBot, en una cantidad inversamente proporcional al número de rondas. Obviamente sería mejor si hubiera más copias de él en el campo * tos ** guiño *.
fuente
ShiftingOptimalBot
Este bot usa el algoritmo de LastOptimalBot siempre que sea ganador. Sin embargo, si el otro bot comienza a predecirlo, comenzará a jugar cualquier movimiento que haya jugado su oponente en último lugar (que es el movimiento que supera el movimiento que vencería a LastOptimalBot). Se desplaza por transposiciones simples de esos algoritmos siempre que continúe perdiendo (o cuando se aburre dibujando mucho).
Honestamente, me sorprende que LastOptimalBot esté en el quinto puesto cuando publico esto. Estoy bastante seguro de que esto funcionará mejor, suponiendo que escribí esta pitón correctamente.
fuente
Apretón De ManosPatrón
¿Por qué el patrón coincide contigo mismo? Apretón de manos y cooperar lejos.
fuente
import PatternFinder
está haciendo trampa en mis libros.Codificado
Simplemente reproduce una secuencia codificada de movimientos optimizados para vencer a algunos de los mejores bots deterministas.
fuente