黑手党(也称为狼人)是一款派对游戏,大致玩法如下:
- 游戏从第0天开始。每一天之后都有
n
一个晚上n
。每天晚上之后n
是一天n+1
。即D0, N0, D1, N1, D2, N2
... - 在第0天的黎明,主持人秘密地选择玩家担任某些角色:
- 一些玩家成为黑手党。每个夜晚,每个黑手党成员都会选择一名球员。在第二天的黎明,被最黑手党成员选择的玩家被杀死。它们已从游戏中永久删除,并且其角色已公开显示。黑手党对齐。
- 一些玩家成为警察。每天晚上,每个警察都会选一个球员。在第二天的黎明,警察开始意识到玩家的状态。村落对齐。
- 一些球员成为医生。每天晚上,每个医生都会选择一名球员。如果此玩家与黑手党选择杀死的玩家相同,则黑手党当晚的行动将被取消。村落对齐。
- 没有被选为其他角色的所有玩家都是村民。村民没有全镇无法分享的能力。村落对齐。
- 除第0天外,每天都有整个城镇(即所有在世玩家)为一名玩家投票。最终,该玩家将从游戏中删除,并显示他们的角色。(在第0天,每个人都直到晚上降临。)
- 如果在任何时候都没有剩余的黑手党成员,那么游戏将以所有与村庄结盟的玩家胜利(包括死亡)结束。
- 如果在任何时候,以村庄为中心的玩家数量都不超过以黑手党为基础的玩家,则游戏将以所有以黑手党为基础的玩家胜利(包括死亡)而结束。
对于这个挑战,您的目标是写一个机器人来击败黑手党的其他机器人!
如何制作一个可以工作的机器人
您需要为我提供的只是一个名为的文件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
。我选择以这种方式进行操作,以便可以执行文件I / O的任何语言都可以参与。如果您的语言使使用stdin和stdout比使用文件I / O更容易,则可能需要编写如下run
文件:
#!/bin/bash
./real_bot.py < from_server > to_server
这样就可以使stdin来自from_server
文件,而stdout直接进入to_server
。
您的机器人在游戏期间不会一直运行。相反,它将在需要做出决定时运行。同样,当它死了时也不会被通知,只是不再运行了。为此进行计划,方法是将要记住的所有内容保存到文件中,然后再阅读。您可以创建,写入或读取bot文件夹中的任何文件,但不能写入或读取该文件夹以外的任何位置,包括网络访问权限或任何其他内容。如果您的漫游器知道该文件夹中未告知的任何内容,或者接触到该文件夹中未包含的任何内容,则该机器人将被取消资格。
如何制作功能性机器人
天
在游戏开始时,文件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天,投票将被忽略。
可以向所有播放器发送许多预定义的消息。此处列出了每条可能的消息的ID:
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
该消息与您编写的ID相关联。如果消息中包含主题,则在消息结尾之后立即插入一个空格字符和主题。如果包含收件人,则在邮件之前立即插入其名称,一个冒号和一个空格字符。
在一天结束时,所有在世的玩家最后一次跑动,以查看投票结果。如果某个球员被投票否决,则将这样写:
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个或更多的玩家,游戏将无法运行。
- 四舍五入的球员中有三分之一是黑手党。一名球员将是一名医生,一名球员将是一名警察。所有其他参与者都是村民。
- 乡村投票或黑手党的通宵投票中的关系是随机解决的。
- Bot名称必须为字母数字+破折号和下划线。
- 禁止直接使用对方密码知识。从理论上讲,我应该能够使您的机器人与您从未见过的机器人抗衡,并使其具有可比性。
- 遗憾的是,如果我无法使用排他性的免费软件(如啤酒)运行您的程序,那么我将不得不取消其资格。
- 如果我认为任何提交都是恶意的,我保留取消其提交资格的权利。这包括但不限于使用过多的时间,内存或空间来运行。我故意将限制设为软限制,但请记住:我正在家用计算机而不是超级计算机上运行此限制,并且我不希望结果花费一年的时间。由于我的标准相当低,我不希望使用此方法。这基本上是“如果我认为您是故意的家伙”,并且如果您可以说服我,我将推翻我的决定。
计分
每回合将运行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)
。
机器人示例
兰迪(Randy)机器人不是一名出色的黑手党玩家。兰迪几乎忽略了所有事情,随机选择说些什么,投票给谁以及用夜间力量瞄准谁。
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撰写的(我做了一些编辑)。
他放弃了在这里的人谁想要完成并发布。