Mafia (também conhecido como Lobisomem) é um jogo de festa que é mais ou menos assim:
- O jogo começa no dia 0. Depois de cada dia
n
chega uma noiten
. Depois de toda noiten
chega o dian+1
. ieD0, N0, D1, N1, D2, N2
... - No início do dia 0, um anfitrião escolhe secretamente os jogadores para desempenhar certas funções:
- Algum número de jogadores se torna a máfia. Toda noite, todo mafioso escolhe um jogador. Ao amanhecer do dia seguinte, o jogador escolhido pelos mais mafiosos é morto. Eles são permanentemente removidos do jogo e seu papel é revelado publicamente. Alinhado à máfia.
- Algum número de jogadores se torna policial. Toda noite, cada policial escolhe um jogador. No amanhecer do dia seguinte, o policial toma conhecimento do alinhamento dos jogadores. Alinhado pela vila.
- Algum número de jogadores se torna médico. Toda noite, cada médico escolhe um jogador. Se este jogador for o mesmo que a máfia escolheu matar, as ações da máfia naquela noite serão canceladas. Alinhado pela vila.
- Todos os jogadores que não são escolhidos para outro papel são aldeões. Os moradores não têm habilidades que não são compartilhadas por toda a cidade. Alinhado pela vila.
- Todos os dias, exceto o dia 0, a cidade inteira (ou seja, todos os jogadores vivos) vota em um jogador. No final do dia, esse jogador é removido do jogo e seu papel é revelado. (No dia 0, todos relaxam até o anoitecer.)
- Se, a qualquer momento, não houver mafiosos restantes, o jogo termina com todos os jogadores alinhados à aldeia vitoriosos (incluindo os mortos).
- Se, a qualquer momento, os jogadores alinhados à aldeia não superarem os jogadores alinhados à máfia, o jogo terminará com todos os jogadores alinhados à máfia vitoriosos (incluindo os mortos).
Para esse desafio, seu objetivo é escrever um bot para vencer outros bots na Mafia!
Como fazer um bot funcionando
Tudo o que você precisa fornecer para mim é um arquivo chamado run
. Dentro da estrutura de diretórios em que esse desafio ocorrerá, seu bot viverá aqui:
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/
O run
arquivo, quando executado, fará com que seu bot faça seu trabalho. É importante observar que esse arquivo não deve exigir argumentos de linha de comando ou algo assim. Será executado exatamente como ./run
. Se você precisar ser executado de uma maneira diferente, precisará contorná-lo fazendo algo assim:
real_bot.py
#!/bin/python2
# code goes here
run
#!/bin/bash
./real_bot.py --flags --or --whatever
Uma coisa importante a ser observada é que todas as entradas recebidas pelo bot serão encontradas no arquivo from_server
e o programa de controle procurará a saída do bot to_server
. Eu escolhi fazer dessa maneira para que qualquer idioma que possa fazer a E / S de arquivo possa participar. Se seu idioma facilitar o trabalho com stdin e stdout do que com E / S de arquivos, você pode escrever um run
arquivo parecido com este:
#!/bin/bash
./real_bot.py < from_server > to_server
Isso fará com que stdin venha do from_server
arquivo e stdout vá diretamente para to_server
.
Seu bot não ficará em execução durante o jogo. Em vez disso, ele será executado quando precisar tomar uma decisão. Da mesma forma, ele não será informado quando estiver morto, apenas não será mais executado. Planeje isso salvando tudo o que deseja lembrar em um arquivo e lendo-o mais tarde. Você pode criar, gravar ou ler qualquer arquivo na pasta do seu bot, mas não pode escrever ou ler em qualquer lugar fora dessa pasta, incluindo acesso à rede ou qualquer outra coisa . Se o seu bot souber algo que não foi informado de dentro da pasta, ou se tocar em algo que não está nessa pasta, seu bot será desqualificado.
Como fazer um bot funcional
Dia
No início do jogo, o arquivo players
será preenchido com uma lista delimitada por nova linha de todos os jogadores no jogo. Não será atualizado quando os jogadores saírem do jogo.
No início do dia 0, todos os jogadores encontrarão esta mensagem em seu from_server
arquivo:
Rise and shine! Today is day 0.
No voting will occur today.
Be warned: Tonight the mafia will strike.
Se você é o policial, a linha You are the cop
é anexada ao final. O médico vê You are the doctor
. A máfia vê You are a member of the mafia.\nYour allies are:
e uma lista delimitada por nova linha de membros da máfia, excluindo o jogador que está lendo a mensagem.
No início de todos os outros dias, esta mensagem aparecerá:
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
é substituído pelo número do dia. victim
é substituído pelo nome da vítima da noite passada e victim_role
é um dos seguintes:
a villager
a mafioso
the cop
the doctor
cop_target
é o nome do jogador que o policial investigou na noite passada e target_alignment
é village
ou mafia
. Finalmente, remaining_players
é uma lista de jogadores que ainda estão vivos neste formato:player1, player2, player3
A segunda linha é omitida se não houve morte ontem à noite, e a terceira linha é mostrada apenas para o policial.
Por exemplo,
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
Uma vez que esta mensagem está fora do caminho, o dia começa! Cada bot pode realizar 50 ações ao longo do dia, onde uma "ação" está votando em um jogador ou dizendo algo em voz alta.
Para votar em um jogador, escreva vote player_name
no seu to_server
arquivo e termine. Para votar para não matar ninguém, escreva vote no one
. Quando você votar, todos os jogadores (incluindo você) verão your_bot votes to kill your_selection
. Os votos são ignorados no dia 0.
Um número de mensagens predefinidas pode ser enviado a todos os jogadores. O ID de cada mensagem possível está listado aqui:
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?
Todas essas mensagens, exceto as cinco primeiras, estão se referindo a um jogador específico. Para dizer uma dessas mensagens, escreva say message_id player_name
. Para uma das cinco primeiras mensagens, basta escrever say message_id
. Você pode adicionar um terceiro argumento opcional a ambos, especificando o nome do jogador com quem está falando (todos os jogadores ainda podem lê-lo, mas saberão quem é o destinatário pretendido).
Quando o seu bot diz uma mensagem, todos os jogadores leem your_bot says "message"
, onde message
está a mensagem associada ao ID que você escreveu. Se a mensagem incluir um assunto, um caractere de espaço e o assunto serão inseridos diretamente após o final da mensagem. Se incluir um destinatário, seu nome, dois pontos e um caractere de espaço serão inseridos imediatamente antes da mensagem.
No final do dia, todos os jogadores vivos são disputados uma última vez para ver o resultado da votação. Se um jogador foi eliminado, está escrito:
The town has killed player_name!
They were a villager
... ou a mafioso
, ou the cop
, ou the doctor
.
Se nenhum jogador foi votado, isto está escrito:
The town opted to lynch no one today.
Quando o controlador envia essas mensagens, ele ignora qualquer resposta dos jogadores. O dia acabou.
Noite
À noite, todos, menos os moradores, usam seu poder.
Máfia:
Você vai ler It is night. Vote for a victim.
. Quando isso acontecer, digite o nome do jogador que você gostaria de matar.
Policial:
Você vai ler It is night. Who would you like to investigate?
. Quando isso acontece, imprima o nome do player que você deseja verificar.
Médico:
Você vai ler It is night. Who would you like to save?
. Quando isso acontecer, digite o nome do jogador que você deseja proteger.
Depois disso, o dia seguinte começa normalmente.
Você pode se salvar apenas uma vez por jogo.
Informação geral
- O jogo não será executado sem 6 ou mais jogadores.
- Um terço dos jogadores, arredondados, será da máfia. Um jogador será médico e um jogador será policial. Todos os outros jogadores são aldeões.
- Os laços no voto da aldeia ou o voto da máfia da noite para o dia são resolvidos aleatoriamente.
- Os nomes dos bot devem ser alfanuméricos + traços e sublinhados.
- É proibido usar o conhecimento do código do oponente diretamente. Em teoria, eu deveria ser capaz de colocar seu bot contra bots que você nunca viu antes e ter um desempenho comparável.
- Lamentavelmente, se eu não conseguir executar seu programa usando software exclusivamente gratuito (como em cerveja), terei que desqualificá-lo.
- Reservo-me o direito de desqualificar qualquer envio, se achar que é malicioso. Isso inclui, mas não se limita ao uso excessivo de tempo, memória ou espaço para execução. Intencionalmente deixei o limite baixo, mas lembre-se: estou executando isso no meu computador doméstico, não em um supercomputador, e não quero que os resultados levem um ano. Não espero ter que usar isso, pois meus padrões são bem baixos. Isso é basicamente "se eu acho que você está sendo um idiota de propósito", e se você pode me convencer do contrário, vou reverter minha decisão.
Pontuação
A cada rodada, 100 jogos serão executados (isso pode aumentar à medida que mais bots se juntam para manter o tamanho da amostra grande o suficiente, mas na teoria isso não afeta nada). Vou gravar quantas vezes cada bot vence como aldeão em comparação com quantas vezes ele joga como aldeão, e o mesmo para a máfia. Um bot villager_ratio
é number of games won as villager / number of games played as villager
, e mafia_ratio
é o mesmo, mas s/villager/mafia/g
. A pontuação de um bot é (villager_ratio - mean villager_ratio) + (mafia_ratio - mean mafia_ratio)
.
Exemplo de bot
Randy, o robô, não é um bom jogador da máfia. Randy ignora praticamente tudo, escolhendo aleatoriamente o que dizer, em quem votar e em quem mirar com poderes noturnos.
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
O @undergroundmonorail escreveu um programa de controle para esse desafio, disponível aqui .
Você tem um mês para codificar e entregar as respostas. Eu darei ao bot vencedor (o desempate com maior taxa de vitória é o voto) pelo menos uma recompensa de 50 reputação (dependendo de quanto rep eu posso ganhar em um mês)
Aqui está um script de wrapper, criado por @Blacksilver, para usar com idiomas compilados:
#!/bin/bash
run="./a.out"
compile="gcc bot.c"
if [ -e $run ]; then
$run
else
$compile
$run
fi
Coloque isso run
.
Este post foi escrito por @undergroundmonorail (fiz algumas edições).
Ele o entregou aqui para quem quisesse terminar e publicá-lo.