Мафія (також відома як перевертень) - це партійна гра, яка грає приблизно так:
- Гра починається в день 0. Після кожного дня
n
настає нічn
. Після кожної ночіn
настає деньn+1
. тобтоD0, N0, D1, N1, D2, N2
... - На світанку дня 0 господар таємно вибирає гравців для виконання певних ролей:
- Деяка кількість гравців стає мафією. Щовечора кожен мафіоз обирає гравця. На світанку наступного дня вбивається гравець, обраний самими мафіозами. Вони назавжди вилучаються з гри, і їх роль публічно розкривається. Мафія вирівняна.
- Деяка кількість гравців стають поліцейськими. Щовечора кожен поліцейський обирає гравця. На світанку наступного дня поліцейський дізнається про вирівнювання гравців. Вирівняні по селу.
- Деяка кількість гравців стають лікарями. Щовечора кожен лікар обирає гравця. Якщо цей гравець є тим самим гравцем, якого мафія вирішила вбити, дії мафії за цю ніч скасовуються. Вирівняні по селу.
- Усі гравці, яких не обрали на іншу роль, - жителі села. Селяни не мають здібностей, якими не ділиться все місто. Вирівняні по селу.
- Кожного дня, крім дня 0, все місто (тобто всі живі гравці) голосує за гравця. Зрештою, цей гравець вилучається з гри і виявляється їх роль. (0-го дня всі просто остуджуються до настання темноти.)
- Якщо в будь-який момент не залишилося мафіозів, гра закінчується перемогою всіх гравців по селах (включаючи мертвих).
- Якщо в будь-який момент гравці, розташовані на селі, не перевищують мафіованих гравців, гра закінчується перемогою всіх гравців, вирівняних у мафії (включаючи мертвих).
Для цього виклик, ваша мета - написати бота, щоб бити інших ботів у Mafia!
Як зробити робочого бота
Все, що вам потрібно надати, - це файл, який називається run
. Всередині структури каталогів, де відбуватиметься цей виклик, ваш бот житиме тут:
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/
Після виконання run
файлу ваш бот зробить свою справу. Важливо зауважити, що цей файл не повинен вимагати жодних аргументів командного рядка чи нічого. Він буде виконуватися саме так ./run
. Якщо вам потрібно виконати іншим способом, вам доведеться обійти це, зробивши щось подібне:
real_bot.py
#!/bin/python2
# code goes here
run
#!/bin/bash
./real_bot.py --flags --or --whatever
Важливо відзначити, що весь вхід, який отримує ваш бот, знайдеться у файлі, from_server
а програма керування шукатиме вихід вашого бота to_server
. Я вирішив зробити це таким чином, щоб будь-яка мова, яка може робити файл вводу / виводу, могла брати участь. Якщо ваша мова полегшує роботу зі stdin та stdout, ніж введення / виведення файлів, ви можете написати run
файл, який виглядає приблизно так:
#!/bin/bash
./real_bot.py < from_server > to_server
Це зробить так, що stdin надходить з from_server
файлу, а stdout переходить безпосередньо до to_server
.
Ваш бот не буде працювати протягом гри. Натомість він працюватиме тоді, коли потрібно прийняти рішення. Крім того, він не буде повідомлений, коли він мертвий, він просто більше не буде запущений. Плануйте це, зберігаючи у файлі все, що ви хочете запам'ятати, і читати його пізніше. Ви можете створювати, записувати чи читати з будь-якого файлу у папці вашого бота, але ви не можете писати чи читати в будь-якому місці за межами цієї папки, включаючи доступ до мережі чи будь-що інше . Якщо ваш бот знає що- небудь, що йому не було сказано всередині папки, або якщо він торкається чогось, що не знаходиться в цій папці, ваш бот буде дискваліфікований.
Як зробити функціонального бота
День
На початку гри файл players
заповниться новим рядком з усіма гравцями гри. Він не оновлюватиметься, коли гравці покинуть гру.
На світанку дня 0 всі гравці знайдуть це повідомлення у своєму from_server
файлі:
Rise and shine! Today is day 0.
No voting will occur today.
Be warned: Tonight the mafia will strike.
Якщо ви поліцейський, рядок You are the cop
додається до кінця. Лікар бачить You are the doctor
. Мафія бачить You are a member of the mafia.\nYour allies are:
і список нових членів мафії, обмежений новим рядком, за винятком гравця, який читає повідомлення.
На світанку всіх інших днів з'явиться це повідомлення:
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
замінюється номером дня. victim
замінено іменем жертви минулої ночі і victim_role
є одним із:
a villager
a mafioso
the cop
the doctor
cop_target
- ім'я гравця, якого поліція розслідувала вчора ввечері, і target_alignment
є village
або mafia
. Нарешті, remaining_players
список гравців, які ще живуть у такому форматі:player1, player2, player3
Другий рядок опущено, якщо минулого вечора не було вбито, а третій рядок показаний лише поліцейському.
Наприклад,
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
Як тільки це повідомлення не виходить, починається день! Кожен бот може робити 50 дій протягом дня, де "дія" голосує за гравця або говорить щось вголос.
Щоб проголосувати за гравця, напишіть vote player_name
у свій to_server
файл і припиніть. Щоб проголосувати, щоб нікого не вбити, пишіть vote no one
. Коли ви проголосуєте, всі гравці (включаючи вас) побачать your_bot votes to kill your_selection
. День голосування ігнорується.
Кілька попередньо визначених повідомлень можна надіслати всім гравцям. Ідентифікатор кожного можливого повідомлення вказаний тут:
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?
Усі ці повідомлення, крім першої п'ятірки, стосуються конкретного гравця. Щоб сказати одне з цих повідомлень, напишіть say message_id player_name
. Для одного з перших п’яти повідомлень просто напишіть say message_id
. Ви можете додати необов'язковий третій аргумент обом цим, вказавши ім’я гравця, з яким ви розмовляєте (усі гравці все ще можуть його прочитати, але вони будуть знати, хто призначений одержувач).
Коли ваш бот каже повідомлення, всі гравці читають your_bot says "message"
, де message
це повідомлення, пов'язане з ідентифікатором, який ви написали. Якщо повідомлення включає тему, один пробіл та суб'єкт вставляються безпосередньо після закінчення повідомлення. Якщо він включає одержувача, їх ім'я, двокрапка та один пробіл вставляються безпосередньо перед повідомленням.
Зрештою, всі живі гравці проходять останній раз, щоб побачити результат голосування. Якщо гравця проголосували, пишеться:
The town has killed player_name!
They were a villager
... або a mafioso
, або the cop
, або the doctor
.
Якщо жодного гравця не проголосували, замість цього пишеться:
The town opted to lynch no one today.
Коли контролер надсилає ці повідомлення, він ігнорує будь-яку відповідь гравців. День закінчився
Ніч
Вночі всі, крім жителів села, користуються своєю владою.
Мафія:
Ви прочитаєте It is night. Vote for a victim.
. Коли це станеться, виведіть ім’я гравця, якого ви хочете вбити.
Коп:
Ви прочитаєте It is night. Who would you like to investigate?
. Коли це станеться, виведіть ім’я гравця, якого ви хочете перевірити.
Лікар:
Ви прочитаєте It is night. Who would you like to save?
. Коли це станеться, виведіть ім’я гравця, якого ви хочете захистити.
Після цього наступний день починається як нормально.
Ви можете заощадити себе лише один раз у грі.
Загальна інформація
- Гра не буде працювати без 6 і більше гравців.
- Третина гравців, округлених вниз, буде мафією. Один гравець буде лікарем, а один гравець - копом. Усі інші гравці - жителі села.
- Зв'язки в голосуванні на селі або голосування мафії протягом ночі вирішуються випадковим чином.
- Назви ботів мають бути буквено-цифровими + тире та підкресленнями.
- Забороняється безпосередньо використовувати знання коду противника. Теоретично я маю змогу поставити вашого бота проти ботів, яких ви ніколи не бачили, і зробити це порівняно.
- На жаль, якщо я не можу запустити вашу програму за допомогою виключно безкоштовного (як у пиві) програмного забезпечення, мені доведеться дискваліфікувати її.
- Я залишаю за собою право дискваліфікувати будь-яке подання, якщо вважаю це шкідливим. Це включає, але не обмежується використанням надмірного часу, пам'яті або місця для запуску. Я навмисно залишив межу м'якою, але пам’ятайте: я запускаю це на своєму домашньому комп’ютері, а не на суперкомп'ютері, і не хочу, щоб результати зайняли рік. Я не сподіваюся використовувати це, оскільки мої стандарти досить низькі. Це, в основному, "якщо я думаю, що ти навмисно робиш хуй", і якщо ти можеш переконати мене в іншому, я скасую своє рішення.
Оцінка балів
Кожного раунду буде запущено 100 ігор (це може збільшитися, оскільки більше ботів приєднається, щоб розмір вибірки був досить великим, але теоретично це не вплине на що-небудь). Я запишу, скільки разів кожен бот виграє як житель села порівняно з тим, скільки разів він грає як житель села, і те саме для мафії. Бот villager_ratio
є number of games won as villager / number of games played as villager
, і mafia_ratio
це те саме, але s/villager/mafia/g
. Оцінка бота - це (villager_ratio - mean villager_ratio) + (mafia_ratio - mean mafia_ratio)
.
Приклад бот
Ренді Робот - не хороший мафієрист. Ренді майже все ігнорує, випадково вибираючи, що сказати, за кого голосувати та за кого націлитись з нічними повноваженнями.
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
Контролер
@undergroundmonorail написав контрольну програму для цього виклику, доступну тут .
У вас є один місяць, щоб кодувати і перетворювати відповіді, я дам боту-переможцю (найвищий виграш виграшів, який виграв виграш - це голоси), як мінімум, 50 репутаційних виграшів (залежно від того, скільки реп я можу заробити за місяць)
Ось скрипт для обгортки, створений @Blacksilver, для використання зі скомпільованими мовами:
#!/bin/bash
run="./a.out"
compile="gcc bot.c"
if [ -e $run ]; then
$run
else
$compile
$run
fi
Покладіть це run
.
Це повідомлення написав @undergroundmonorail (я зробив декілька змін).
Він віддав його тут усім, хто хотів закінчити і опублікувати.