Mafia (también conocido como Werewolf) es un juego de mesa que se juega más o menos así:
- El juego comienza el día 0. Después de cada día
n
llega una nochen
. Después de cada nochen
llega un dían+1
. es decirD0, N0, D1, N1, D2, N2
... - Al amanecer del día 0, un anfitrión elige en secreto a los jugadores para cumplir ciertos roles:
- Algunos jugadores se convierten en la mafia. Cada noche, cada mafioso elige un jugador. Al amanecer del día siguiente, el jugador elegido por los más mafiosos es asesinado. Se eliminan permanentemente del juego y su papel se revela públicamente. Alineado con la mafia.
- Algunos jugadores se convierten en policías. Todas las noches, cada policía elige un jugador. Al amanecer del día siguiente, el policía se da cuenta de la alineación de los jugadores. Alineado con el pueblo.
- Algunos jugadores se convierten en médicos. Todas las noches, cada médico elige un jugador. Si este jugador es el mismo jugador que la mafia decidió matar, las acciones de la mafia para esa noche se cancelan. Alineado con el pueblo.
- Todos los jugadores que no son elegidos para otro papel son aldeanos. Los aldeanos no tienen habilidades que no sean compartidas por toda la ciudad. Alineado con el pueblo.
- Todos los días, excepto el día 0, toda la ciudad (es decir, todos los jugadores vivos) vota por un jugador. Al final del día, ese jugador es eliminado del juego y se revela su papel. (El día 0, todo el mundo se relaja hasta el anochecer).
- Si, en algún momento, no quedan mafiosos restantes, el juego termina con todos los jugadores alineados en la aldea victoriosos (incluidos los muertos).
- Si, en algún momento, los jugadores alineados con la aldea no superan en número a los jugadores alineados con la mafia, el juego termina con todos los jugadores alineados con la mafia victoriosos (incluidos los muertos).
Para este desafío, tu objetivo es escribir un bot para vencer a otros bots en Mafia.
Cómo hacer un bot que funcione
Todo lo que tiene que proporcionarme es un archivo llamado run
. Dentro de la estructura de directorios donde tendrá lugar este desafío, su bot vivirá aquí:
start
controller/
tmp/
players/ # You are here!
some_bot/ # Let's pretend you're some_bot.
to_server
from_server
players
run # This is what you give me
mafia-game-bot/
skynet/
El run
archivo, cuando se ejecute, hará que su bot haga lo suyo. Es importante tener en cuenta que este archivo no debe requerir ningún argumento de línea de comando ni nada. Se ejecutará exactamente como ./run
. Si necesita ser ejecutado de una manera diferente, tendrá que solucionarlo haciendo algo como esto:
real_bot.py
#!/bin/python2
# code goes here
run
#!/bin/bash
./real_bot.py --flags --or --whatever
Una cosa importante a tener en cuenta es que todas las entradas que recibe su bot se encontrarán en el archivo from_server
y el programa de control buscará la salida de su bot to_server
. Elegí hacerlo de esta manera para que cualquier idioma que pueda hacer archivos de E / S pueda participar. Si su idioma facilita el trabajo con stdin y stdout que la E / S de archivo, es posible que desee escribir un run
archivo que se vea así:
#!/bin/bash
./real_bot.py < from_server > to_server
Esto hará que stdin provenga del from_server
archivo y stdout vaya directamente a to_server
.
Tu bot no se mantendrá en funcionamiento mientras dure el juego. En su lugar, se ejecutará cuando necesite tomar una decisión. Del mismo modo, no se le informará cuando esté muerto, simplemente ya no se ejecutará. Planifique esto guardando todo lo que quiera recordar en un archivo y leyéndolo más tarde. Puede crear, escribir o leer desde cualquier archivo en la carpeta de su bot, pero no puede escribir ni leer en ningún lugar fuera de esa carpeta, incluido el acceso a la red o cualquier cosa . Si su bot sabe algo que no se le dijo desde dentro de la carpeta, o si toca algo que no está dentro de esa carpeta, su bot está descalificado.
Cómo hacer un bot funcional
Día
Al comienzo del juego, el archivo players
se completará con una lista delimitada por la nueva línea de todos los jugadores en el juego. No se actualizará cuando los jugadores abandonen el juego.
Al amanecer del día 0, todos los jugadores encontrarán este mensaje en su from_server
archivo:
Rise and shine! Today is day 0.
No voting will occur today.
Be warned: Tonight the mafia will strike.
Si usted es el policía, la línea You are the cop
se agrega al final. El doctor ve You are the doctor
. La mafia ve You are a member of the mafia.\nYour allies are:
y una lista delimitada por la nueva línea de miembros de la mafia, excluyendo al jugador que lee el mensaje.
Al amanecer de todos los demás días, aparecerá este mensaje:
Dawn of day `day_number`.
Last night, `victim` was killed. They were `victim_role`.
Investigations showed that `cop_target` is `target_alignment`-aligned.
These players are still alive: `remaining_players`
dayNumber
se reemplaza con el número del día. victim
se reemplaza con el nombre de la víctima de la noche anterior y victim_role
es uno de:
a villager
a mafioso
the cop
the doctor
cop_target
es el nombre del jugador que el policía investigó anoche, y target_alignment
es village
o mafia
. Finalmente, remaining_players
hay una lista de jugadores que aún están vivos en este formato:player1, player2, player3
La segunda línea se omite si no hubo asesinato anoche, y la tercera línea se muestra solo al policía.
Por ejemplo,
Dawn of day 42.
Last night, Xyzzy was killed. They were a villager.
Investigations showed that Randy is mafia-aligned.
These players are still alive: Randy, CopBot, JohnDoe, Steve
Una vez que este mensaje está fuera del camino, ¡comienza el día! Cada bot puede realizar 50 acciones durante el día, donde una "acción" es votar por un jugador o decir algo en voz alta.
Para votar por un jugador, escriba vote player_name
en su to_server
archivo y finalice. Para votar para no matar a nadie, escribe vote no one
. Cuando vote, todos los jugadores (incluido usted) verán your_bot votes to kill your_selection
. Los votos se ignoran el día 0.
Se pueden enviar varios mensajes predefinidos a todos los jugadores. La identificación de cada mensaje posible se enumera aquí:
0: No
1: Yes
2: I am the cop
3: I am the doctor
4: I am a normal villager
5: I trust this player:
6: I think this player is suspicious:
7: I think this player is the cop:
8: I think this player is the doctor:
9: I think this player is a normal villager:
10: I think this player is mafia:
11: Do you think this player is mafia?
12: I tried to save this player:
13: I successfully saved this player:
14: I investigated this player and found that they were mafia-aligned:
15: I investigated this player and found that they were village-aligned:
16: Will you please use your power on this player tonight?
Todos estos mensajes, excepto los primeros cinco, se refieren a un jugador específico. Para decir uno de esos mensajes, escribe say message_id player_name
. Para uno de los primeros cinco mensajes, solo escriba say message_id
. Puede agregar un tercer argumento opcional a ambos, especificando el nombre de un jugador con el que está hablando (todos los jugadores aún pueden leerlo, pero sabrán quién es el destinatario previsto).
Cuando su bot dice un mensaje, todos los jugadores leen your_bot says "message"
, ¿dónde message
está el mensaje asociado con la identificación que escribió? Si el mensaje incluye un asunto, un carácter de espacio y el asunto se insertan directamente después del final del mensaje. Si incluye un destinatario, su nombre, dos puntos y un carácter de espacio se insertan inmediatamente antes del mensaje.
Al final del día, todos los jugadores vivos se ejecutan por última vez para ver el resultado de la votación. Si se votó a un jugador, esto se escribe:
The town has killed player_name!
They were a villager
... o a mafioso
, o the cop
, o the doctor
.
Si no se votó a ningún jugador, esto se escribe en su lugar:
The town opted to lynch no one today.
Cuando el controlador envía estos mensajes, ignora cualquier respuesta de los jugadores. Se acabó el día.
Noche
Por la noche, todos menos los aldeanos pueden usar su poder.
Mafia:
Usted va a leer It is night. Vote for a victim.
. Cuando esto sucede, escribe el nombre del jugador que te gustaría matar.
Policía:
Usted va a leer It is night. Who would you like to investigate?
. Cuando esto suceda, escriba el nombre del jugador que desea verificar.
Doctor:
Usted va a leer It is night. Who would you like to save?
. Cuando esto suceda, escriba el nombre del jugador que desea proteger.
Después de esto, el día siguiente comienza de manera normal.
Puede salvarse solo una vez por juego.
Información general
- El juego no se ejecutará sin 6 o más jugadores.
- Un tercio de los jugadores, redondeados hacia abajo, serán mafiosos. Un jugador será médico y un jugador será policía. Todos los demás jugadores son aldeanos.
- Los lazos en el voto del pueblo o el voto nocturno de la mafia se resuelven al azar.
- Los nombres de los bot deben ser alfanuméricos + guiones y guiones bajos.
- Está prohibido utilizar el conocimiento del código del oponente directamente. En teoría, debería ser capaz de poner tu bot contra bots que nunca hayas visto antes y que tenga un rendimiento comparable.
- Lamentablemente, si no puedo ejecutar su programa utilizando software exclusivamente gratuito (como en cerveza), tendré que descalificarlo.
- Me reservo el derecho de descalificar cualquier envío si creo que es malicioso. Esto incluye, entre otros, el uso excesivo de tiempo, memoria o espacio para ejecutar. He dejado el límite intencionalmente en blanco, pero recuerda: estoy ejecutando esto en la computadora de mi casa, no en una supercomputadora, y no quiero que los resultados tarden un año. No espero tener que usar esto, ya que mis estándares son bastante bajos. Esto es básicamente "si creo que estás siendo un idiota a propósito", y si puedes convencerme de lo contrario, revertiré mi decisión.
Tanteo
Cada ronda, se ejecutarán 100 juegos (esto puede aumentar a medida que se unen más bots para mantener el tamaño de la muestra lo suficientemente grande, pero en teoría eso no afectará nada). Registraré cuántas veces gana cada bot como aldeano en comparación con cuántas veces juega como aldeano, y lo mismo para la mafia. Un bot villager_ratio
es number of games won as villager / number of games played as villager
, y mafia_ratio
es lo mismo pero s/villager/mafia/g
. La puntuación de un bot es (villager_ratio - mean villager_ratio) + (mafia_ratio - mean mafia_ratio)
.
Ejemplo bot
Randy the Robot no es un buen jugador de la mafia. Randy ignora casi todo, eligiendo al azar qué decir, a quién votar y a quién apuntar con poderes nocturnos.
run.sh
:
#!/bin/bash
./randy.py < from_server > to_server
randy.py
:
#!/usr/bin/env python
import random
with open('players') as f:
p = f.read().split() + ['no one']
day = True
try:
line = raw_input()
if line.endswith(('?', 'victim.')):
day = False
if not day:
print random.choice(p)
else:
if random.random() > 0.5:
if random.random() > 0.5:
print 'vote {}'.format(random.choice(p))
else:
id = random.randint(0, 17)
print 'say {}{}'.format(id, (' ' + random.choice(p)) if id > 4 else '')
except: pass
Controlador
@undergroundmonorail escribió un programa de control para este desafío, disponible aquí .
Tienes un mes para codificar y entregar las respuestas, le daré al bot ganador (el mayor desempate es votos) al menos una recompensa de 50 reputación (dependiendo de la cantidad de reputación que pueda ganar en un mes)
Aquí hay un script de envoltura, creado por @Blacksilver, para usar con lenguajes compilados:
#!/bin/bash
run="./a.out"
compile="gcc bot.c"
if [ -e $run ]; then
$run
else
$compile
$run
fi
Pon esto en run
.
Esta publicación fue escrita por @undergroundmonorail (hice algunas ediciones).
Se lo entregó aquí a cualquiera que quisiera terminarlo y publicarlo.
fuente
Respuestas:
zulú
run
No todo lo que esperaba que fuera. Puedo terminar retocándolo ocasionalmente.
Cómo funciona v1.0
Lleva un registro del número del día, quién está vivo, quién está muerto, quién es la mafia, quién está alineado con la aldea, roles, votos / mensajes del día actual y mensajes / votos generales.
Noche
a. Mafia: vote por cualquier aldeano que haya votado en contra de la mafia (al azar) si es posible, de lo contrario, un aldeano al azar.
si. Policía: investiga a cualquiera que tenga una alineación desconocida.
do. Doctor: guarde el primer turno, luego guarde el policía si lo sabe (no creo que pueda saberlo hasta ahora), salve al aldeano si lo sabe (probablemente tampoco lo sepa), de lo contrario, guarde a una persona al azar.
Día
a. Si alguien ha hablado un mensaje directamente a sí mismo, responda a ellos (respuestas limitadas posibles).
si. Mafia: vota por el aldeano que tenga más votos.
do. Aldeano con cualquier conocido vivo alineado con la mafia: vote por el mafioso.
re. Aldeano con solo muertos conocidos alineados con la mafia: vote por un bot aleatorio que nunca haya votado por el mafioso.
mi. Aldeano con policía conocido: vote por un bot aleatorio por el que ha votado el policía.
F. Aldeano con muertos conocidos alineados con la aldea: vote por un robot aleatorio que votó por los muertos.
sol. Aldeano con votos en contra del voto propio para el bot no alineado más votado actualmente que no esté alineado con la aldea.
fuente
El código de ejemplo no funcionó para mí, uso Python 3, así que cambié el
main.py
archivo para que funcione.Así que aquí está mi versión fija para Python 3, nunca antes programé en Python, así que tal vez sea un código horrible, pero funciona :)
run.sh
:randy.py
:Algunas cosas que aprendí mientras hacía este trabajo (y no estaba claro para mí en la descripción)
print
no hace nada con el juego es como unconsole.log
in jsinput()
bloquea el programa en ejecución, puede ser bueno para la depuración paso a pasofrom_server
yto_server
se borra cada ronda.Ctrl+C
combinación, lo cual es molesto.fuente
run.sh
.< from_server > to_server
sea necesario porque codifiqué los nombres de archivo en el código. el motor del juego solo llama./run
sin tuberías. asíinput()
yprint()
no lo hicieron trabaja con el juego.mayn.py
línea 57:os.system('./run')
randy.py
fue escrito en Python 2 , lo que causó los problemas../start
desde la carpeta original o necesita una versión de Python 3 delmain.py
El lógico
Fantasía, código largo de python que no voy a explicar (aunque no es golf), aparte de eso, mantiene listas de "amigos" y "enemigos" que se poblaron originalmente en base a la investigación del azar y / o la policía . Advertencia: no mienta en presencia del lógico.
fuente
run.sh
estándar (haciendo algunas pruebas)Superviviente (v 1.0)
Sinopsis
Survivalist simplemente sobrevive brutalmente al juego reprendiendo a cualquiera que se atreva a acusarlo, independientemente de si es mafioso o no.
Lógica
Si sobrevives hasta el final del juego, ganas pase lo que pase. Por lo tanto, sobrevives a toda costa.
Historia de fondo
Las tropas marcharon por el bosque oscuro y húmedo.
"Teniente, ¿hacia dónde marchamos?" El joven recluta aparentemente no se había endurecido ante las atrocidades, pensó el comandante. Oh bien. Él respondió con un brusco "para destruir al enemigo".
En la aldea, el comandante enemigo estaba bebiendo y riendo junto con los otros oficiales del club cuando un explorador se apresuró a recibir la noticia. "¡Hay una columna, de varios cientos de metros de largo, que marcha por el bosque de Yulin por nosotros! ¡Reúne a las tropas!"
El comandante enemigo, obviamente ebrio, dijo inesperadamente: "No he recibido informes de otros exploradores". El explorador (luego Survivalist) pensó, luego tendré que reunir a las tropas yo mismo . Después de contar la historia a los compañeros exploradores, volvieron a estar juntos, todos diciendo que habían visto tropas enemigas. El comandante todavía no creía, diciendo: "Te estoy ordenando que dejes de explorar. No hay tropas enemigas".
Los exploradores decidieron obtener sus armas para salvar a la comunidad. Se las arreglaron para llegar a sus posiciones justo cuando el enemigo llegaba a la aldea en vigor. "¡CARGAR!" gritó el comandante de la emboscada. "¡QUEME LAS CASAS! ¡ QUEME LAS CASAS! ¡MATAR A TODOS, INCLUIDAS LAS MUJERES Y LOS NIÑOS! "
Los exploradores salvaron a todo su ejército. Esperaban promoción, premios y medallas. En cambio, obtuvieron una corte marcial manipulada por motín, condena, 10 años de prisión, destitución deshonrosa del ejército y exilio.
Hay un anciano en el ayuntamiento de Salem, Massachusetts. La leyenda dice que él fundó la ciudad. Cuando lo encuentres en su cabaña aislada en el bosque, no dejes que el brillo en sus ojos te haga pensar que es pacífico. Si lo acusas, te arruinará frente a la ciudad.
Veterano
Código (soy un novato en Python, no estoy seguro si el código es bueno)
fuente
or
lugar de||
? ¿Lo probaste? Además, probablemente deberías señalar que es Python 2.Avatar
Avatar "al azar" elige a un jugador al comienzo y lo enfoca implacablemente por el resto de la ronda.
Esto no es una referencia a un programa de televisión animado con un nombre similar.
Descargue el tar de todos los archivos requeridos
Registro de cambios
stdout
, solo enstderr
.Para suprimir
stderr
también, agregue2>/dev/null
al final delrun
archivo.Requiere
mafia.c
ymafia.h
, las bibliotecas que escribí, en el mismo directorio.Estos se incluyen en la descarga, junto con un Makefile y un script de ejecución.
QUE HACER
Mientras estoy aquí, enviaré el no bot, Steve:
fuente
avatar
,erebus
,leviathan
, yragnarok
from_server
archivo de mi bot no está siendo escrito. ¿Tuviste que establecer permisos específicos o algo así?Leviatán
Leviatán itera sobre todos los jugadores en el
players
archivo y los apunta uno por uno.Descargar
Al igual que con Avatar, requiere
mafia.c
ymafia.h
en el mismo directorio.Estos se incluyen en la descarga, junto con un Makefile y un script de ejecución.
fuente