Mafia (znana również jako wilkołak) to gra towarzyska, która działa mniej więcej tak:
- Gra rozpoczyna się w dniu 0. Po każdym dniu
n
przychodzi nocn
. Po każdej nocyn
przychodzi dzieńn+1
. tj.D0, N0, D1, N1, D2, N2
... - Na początku dnia 0 gospodarz potajemnie wybiera graczy, którzy pełnią określone role:
- Pewna liczba graczy staje się mafią. Każdej nocy każdy mafioso wybiera gracza. O świcie następnego dnia gracz wybrany przez większość mafiosów zostaje zabity. Są trwale usuwani z gry, a ich rola jest publicznie ujawniana. Dostosowane do mafii.
- Pewna liczba graczy zostaje policjantami. Każdej nocy każdy policjant wybiera gracza. Na początku następnego dnia gliniarz zdaje sobie sprawę z wyrównania graczy. Dostosowane do wsi.
- Pewna liczba graczy zostaje lekarzami. Każdej nocy każdy lekarz wybiera gracza. Jeśli ten gracz jest tym samym graczem, którego mafia postanowiła zabić, akcje mafii na tę noc zostaną anulowane. Dostosowane do wsi.
- Wszyscy gracze, którzy nie zostali wybrani do innej roli, są wieśniakami. Wieśniacy nie mają umiejętności, które nie są wspólne dla całego miasta. Dostosowane do wsi.
- Każdego dnia oprócz dnia 0 całe miasto (czyli wszyscy żyjący gracze) głosuje na gracza. Pod koniec dnia ten gracz zostaje usunięty z gry i zostaje ujawniona jego rola. (W dniu 0 wszyscy po prostu dreszcze aż do zmroku.)
- Jeśli w którymkolwiek momencie nie ma już mafiosów, gra kończy się zwycięstwem wszystkich graczy z wioski (w tym zmarłych).
- Jeśli w którymś momencie gracze wyrównani do wioski nie przewyższą liczebnie graczy wyrównanych do mafii, gra kończy się zwycięstwem wszystkich wyrównanych do mafii graczy (w tym zmarłych).
W tym wyzwaniu Twoim celem jest napisanie bota, który pokona inne boty w Mafii!
Jak zrobić działającego bota
Wszystko, co musisz mi podać, to plik o nazwie run
. Wewnątrz struktury katalogów, w której odbędzie się to wyzwanie, twój bot będzie tu mieszkał:
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/
Po run
uruchomieniu plik sprawi, że bot zrobi to samo. Należy zauważyć, że ten plik nie może wymagać żadnych argumentów wiersza poleceń ani niczego. Będzie działał dokładnie tak jak ./run
. Jeśli musisz zostać wykonany w inny sposób, musisz obejść ten problem, wykonując coś takiego:
real_bot.py
#!/bin/python2
# code goes here
run
#!/bin/bash
./real_bot.py --flags --or --whatever
Ważną rzeczą do zapamiętania jest to, że wszystkie dane wejściowe, które otrzymuje twój bot, zostaną znalezione w pliku, from_server
a program sterujący wyszuka dane wyjściowe twojego bota to_server
. Postanowiłem to zrobić w ten sposób, aby każdy język, który może wykonywać operacje we / wy pliku, mógł wziąć udział. Jeśli Twój język ułatwia pracę ze stdin i stdout niż we / wy pliku, możesz napisać run
plik, który wygląda następująco:
#!/bin/bash
./real_bot.py < from_server > to_server
Sprawi to, że stdin pochodzi z from_server
pliku, a stdout przechodzi bezpośrednio do to_server
.
Twój bot nie będzie działał przez cały czas gry. Zamiast tego zostanie uruchomiony, gdy będzie musiał podjąć decyzję. Podobnie, nie będzie informowany, kiedy będzie martwy, po prostu nie będzie już uruchamiany. Zaplanuj to, zapisując w pliku wszystko, co chcesz zapamiętać, i przeczytaj później. Można tworzyć, pisać lub czytać z dowolnego pliku w folderze bota, ale nie może pisać lub czytać gdziekolwiek poza tym folderze, w tym dostępu do sieci lub cokolwiek . Jeśli Twój bot wie coś , czego nie powiedziano w folderze lub jeśli dotyka czegoś , co nie znajduje się w tym folderze, Twój bot jest zdyskwalifikowany.
Jak zrobić funkcjonalnego bota
Dzień
Na początku gry plik players
zostanie wypełniony listą wszystkich graczy w grze rozdzieloną znakiem nowej linii. Nie będzie aktualizowany, gdy gracze opuszczą grę.
O świcie dnia 0 wszyscy gracze znajdą tę wiadomość w swoim from_server
pliku:
Rise and shine! Today is day 0.
No voting will occur today.
Be warned: Tonight the mafia will strike.
Jeśli jesteś gliną, linia You are the cop
jest dołączana na końcu. Lekarz widzi You are the doctor
. Mafia widzi You are a member of the mafia.\nYour allies are:
listę członków mafii rozdzieloną znakiem nowej linii, z wyłączeniem gracza czytającego wiadomość.
U zarania wszystkich pozostałych dni pojawi się ten komunikat:
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
zastępuje się liczbą dnia. victim
zostaje zastąpiony imieniem ofiary zeszłej nocy i victim_role
jest jednym z:
a villager
a mafioso
the cop
the doctor
cop_target
to nazwa odtwarzacza policjant badanego ostatniej nocy, i target_alignment
jest albo village
albo mafia
. Na koniec remaining_players
znajduje się lista graczy, którzy wciąż żyją w tym formacie:player1, player2, player3
Drugi wiersz jest pomijany, jeśli ostatniej nocy nie było zabójstwa, a trzeci wiersz jest wyświetlany tylko gliniarzowi.
Na przykład,
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
Gdy wiadomość zniknie z drogi, zaczyna się dzień! Każdy bot może wykonać 50 akcji w ciągu dnia, przy czym „akcja” głosuje na gracza lub mówi coś głośno.
Aby zagłosować na gracza, napisz vote player_name
do to_server
pliku i zakończ. Aby głosować, aby nikogo nie zabić, napisz vote no one
. Podczas głosowania wszyscy gracze (łącznie z tobą) zobaczą your_bot votes to kill your_selection
. Głosy są ignorowane w dniu 0.
Do wszystkich graczy można wysłać pewną liczbę wstępnie zdefiniowanych wiadomości. Identyfikator każdej możliwej wiadomości znajduje się tutaj:
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?
Wszystkie te wiadomości, z wyjątkiem pierwszych pięciu, odnoszą się do konkretnego gracza. Aby wypowiedzieć jedną z tych wiadomości, napisz say message_id player_name
. W przypadku jednej z pierwszych pięciu wiadomości po prostu napisz say message_id
. Możesz dodać opcjonalny trzeci argument do obu z nich, określając nazwę gracza, z którym rozmawiasz (wszyscy gracze nadal mogą go przeczytać, ale będą wiedzieć, kto jest zamierzonym odbiorcą).
Kiedy twój bot mówi wiadomość, wszyscy gracze czytają your_bot says "message"
, gdzie message
jest wiadomość związana z napisanym przez ciebie identyfikatorem. Jeśli wiadomość zawiera temat, jeden znak spacji i temat są wstawiane bezpośrednio po końcu wiadomości. Jeśli zawiera on adresata, jego nazwa, dwukropek i jeden znak spacji są wstawiane bezpośrednio przed wiadomością.
Pod koniec dnia wszyscy żyjący gracze są uruchamiani ostatni raz, aby zobaczyć wynik głosowania. Jeśli gracz został wykluczony, jest to napisane:
The town has killed player_name!
They were a villager
... lub a mafioso
, lub the cop
, lub the doctor
.
Jeśli żaden gracz nie został wykluczony, zamiast tego jest napisane:
The town opted to lynch no one today.
Gdy kontroler wysyła te wiadomości, ignoruje wszelkie odpowiedzi graczy. Dzień się skończył.
Noc
W nocy wszyscy oprócz wieśniaków mogą korzystać ze swojej mocy.
Mafia:
Można przeczytać It is night. Vote for a victim.
. Kiedy tak się stanie, wypisz nazwę gracza, którego chcesz zabić.
Policjant:
Można przeczytać It is night. Who would you like to investigate?
. Kiedy tak się stanie, wypisz nazwę odtwarzacza, który chcesz sprawdzić.
Lekarz:
Można przeczytać It is night. Who would you like to save?
. Kiedy tak się stanie, wypisz nazwę odtwarzacza, który chcesz chronić.
Następnie następny dzień zaczyna się jak zwykle.
Możesz uratować się tylko raz na grę.
Informacje ogólne
- Gra nie będzie działać bez 6 lub więcej graczy.
- Jedna trzecia graczy, w zaokrągleniu w dół, będzie mafią. Jeden gracz będzie lekarzem, a jeden będzie gliną. Wszyscy pozostali gracze to wieśniacy.
- Więzy w głosowaniu na wsi lub głosowanie mafii z dnia na dzień są rozstrzygane losowo.
- Nazwy botów muszą być alfanumeryczne + myślniki i podkreślenia.
- Zabronione jest bezpośrednie korzystanie z wiedzy o kodzie przeciwnika. Teoretycznie powinienem być w stanie stawić czoła botowi przeciwko botom, których nigdy wcześniej nie widziałeś, i zapewnić mu porównywalną wydajność.
- Niestety, jeśli nie mogę uruchomić twojego programu przy użyciu wyłącznie darmowego (jak w przypadku piwa) oprogramowania, będę musiał go zdyskwalifikować.
- Zastrzegam sobie prawo do zdyskwalifikowania każdego zgłoszenia, jeśli uważam je za złośliwe. Obejmuje to między innymi nadmierne zużycie czasu, pamięci lub miejsca do uruchomienia. Celowo zostawiłem limit miękki, ale pamiętaj: uruchamiam to na moim komputerze domowym, a nie superkomputerze, i nie chcę, aby wyniki trwały rok. Nie oczekuję, że będę musiał z tego korzystać, ponieważ moje standardy są dość niskie. Jest to w zasadzie „jeśli myślę, że celowo jesteś kutasem” i jeśli możesz mnie przekonać, w przeciwnym razie cofnę moją decyzję.
Punktacja
W każdej rundzie uruchomionych zostanie 100 gier (może się to zwiększyć wraz ze wzrostem liczby botów, aby wielkość próbki była wystarczająco duża, ale teoretycznie nie wpłynie to na nic). Będę rejestrować, ile razy każdy bot wygrywa jako wieśniak w porównaniu do tego, ile razy gra jako wieśniak, i to samo dla mafii. Bot villager_ratio
jest number of games won as villager / number of games played as villager
i mafia_ratio
jest taki sam, ale s/villager/mafia/g
. Wynik bota to (villager_ratio - mean villager_ratio) + (mafia_ratio - mean mafia_ratio)
.
Przykładowy bot
Randy the Robot nie jest dobrym graczem mafijnym. Randy ignoruje prawie wszystko, losowo wybierając, co powiedzieć, na kogo głosować i kogo celować za pomocą nocnych mocy.
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
Kontroler
@undergroundmonorail napisał program kontrolny dla tego wyzwania, dostępny tutaj .
Masz jeden miesiąc na kodowanie i przekazanie odpowiedzi, dam zwycięskiemu botowi (najwyższy wskaźnik wygranych remis to głosy) co najmniej 50 nagród za reputację (w zależności od tego, ile przedstawicieli mogę zarobić w ciągu miesiąca)
Oto skrypt otoki, stworzony przez @Blacksilver, do użycia ze skompilowanymi językami:
#!/bin/bash
run="./a.out"
compile="gcc bot.c"
if [ -e $run ]; then
$run
else
$compile
$run
fi
Włóż to run
.
Ten post został napisany przez @undergroundmonorail (wprowadziłem kilka zmian).
Dał go tutaj każdemu, kto chciał go dokończyć i opublikować.