让我们玩黑手党吧!


42

黑手党(也称为狼人)是一款派对游戏,大致玩法如下:

  • 游戏从第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_alignmentvillagemafia。最后,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 mafiosothe copthe 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_rationumber 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撰写的(我做了一些编辑)。

他放弃了在这里的人谁想要完成并发布。


评论不作进一步讨论;此对话已转移至聊天
Martin Ender '18

Answers:


3

祖鲁族

run

#!/usr/bin/env php
<?php
error_reporting(E_ERROR|E_WARNING|E_PARSE);

$self = basename(__DIR__);

$msgids = array(
    "No",
    "Yes",
    "I am the cop",
    "I am the doctor",
    "I am a normal villager",
    "I trust this player:",
    "I think this player is suspicious:",
    "I think this player is the cop:",
    "I think this player is the doctor:",
    "I think this player is a normal villager:",
    "I think this player is mafia:",
    "Do you think this player is mafia?",
    "I tried to save this player:",
    "I successfully saved this player:",
    "I investigated this player and found that they were mafia-aligned:",
    "I investigated this player and found that they were village-aligned:",
    "Will you please use your power on this player tonight?"
);
$msgids = array_flip($msgids);

if(!file_exists('./from_server')){
    die;
}
$in = file('from_server');
if(count($in) && strpos($in[0],'day 0.') !== false){
    $game = array(
        'day'               =>0,
        'players'           =>array(),
        'alive'             =>array(),
        'dead'              =>array(),
        'mafia'             =>array(),
        'village'           =>array(),
        'cop'               =>'',
        'doctor'            =>'',
        'votes'             =>array(),
        'messages'          =>array(),
        'currentvotes'      =>array(),
        'currentmessages'   =>array()
    );
    $playersfile = file('players');
    foreach($playersfile as $name){
        $game['players'][trim($name)] = 1;
        $game['alive'][trim($name)] = 1;
        $game['votes'][trim($name)] = array();
        $game['messages'] = array();
    }
    $allies = false;
    foreach($in as $line){
        if($allies){
            if(array_key_exists(trim($line),$game['players'])){
                $game['mafia'][trim($line)] = 1;
            }
        }
        else if(strpos($line,"You are the cop") !== false){
            $game['cop'] = $self;
            $game['village'][$self] = 1;
        }
        else if(strpos($line,"You are the doctor") !== false){
            $game['doctor'] = $self;
            $game['village'][$self] = 1;
        }
        else if(strpos($line,"member of the mafia") !== false){
            $game['mafia'][$self] = 1;
        }
        else if(strpos($line,"allies are:") !== false && $game['mafia'][$self]){
            $allies = true;
        }
    }
    if(!$game['mafia'][$self]){
        $game['village'][$self] = 1;
    }
    else{
        foreach($game['players'] as $name=>$g){
            if(!$game['mafia'][$name]){
                $game['village'][$name] = 1;
            }
        }
    }
    $out = json_encode($game);
    write('myinfo',$out);
}
else{
    $myinfo = file_get_contents('myinfo');
    $game = json_decode($myinfo,true);
    if(count($in) && strpos($in[0],"town has killed") !== false){
        $e = explode(" ",trim($in[0]));
        $dead = trim($e[4],'!');
        unset($game['alive'][$dead]);
        $game['dead'][$dead] = 1;
        $e = explode(" ",trim($in[1]));
        $allegiance = trim($e[3],".");
        $game[$allegiance][$dead] = 1;
    }
    else if(count($in) && strpos($in[0],"town opted to") !== false){
        //
    }
    else if(count($in) && strpos($in[0],"night") !== false){
        if(strpos($in[0],"victim") !== false){
            $voted = false;
            if($game['day'] > 0){
                $possible = array();
                foreach($game['alive'] as $name=>$g){
                    if(!$game['mafia'][$name]){
                        foreach($game['votes'][$name] as $for){
                            if($voted && $game['mafia'][$for]){
                                $possible[] = $name;
                            }
                        }
                    }
                }
                if(count($possible)){
                    shuffle($possible);
                    write('to_server',$possible[0]);
                    $voted = 1;
                }               
            }
            if(!$voted){
                while($rand = array_rand($game['alive'])){
                    if(!$game['mafia'][$rand]){
                        write('to_server',$rand);
                        $voted = 1;
                        break;
                    }
                }
            }
        }
        else if(strpos($in[0],"investigate") !== false){
            $possible = array();
            foreach($game['alive'] as $name=>$g){
                if(!$game['village'][$name] && !$game['mafia'][$name] && $game['doctor'] != $name){
                    $possible[] = $name;
                }
            }
            if(count($possible)){
                shuffle($possible);
                write('to_server',$possible[0]);
            }
        }
        else if(strpos($in[0],"save") !== false){
            if($game['day'] == 0){
                write('to_server',$self);
            }
            else{
                if($game['cop'] != '' && $game['alive'][$game['cop']]){
                    write('to_server',$game['cop']);
                }
                else{
                    $voted = false;
                    foreach($game['alive'] as $name=>$g){
                        if($game['village'][$name] && $name != $self){
                            write('to_server',$name);
                            $voted = true;
                            break;
                        }
                    }
                    if(!$voted){
                        while($rand = array_rand($game['alive'])){
                            if($rand != $self){
                                write('to_server',$rand);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
    else if(count($in) && strpos($in[0],"Dawn of day") !== false){
        $e = explode(" ",trim($in[0]));
        $game['day'] = trim($e[3],".");
        foreach($in as $line){
            if(strpos($line,"was killed") !== false){
                $e = explode(" ",trim($line));
                $dead = $e[2];
                if(strpos($line,"the cop") !== false){
                    $game['cop'] = $dead;
                    $game['village'][$dead] = 1;
                }
                else if(strpos($line,"the doctor") !== false){
                    $game['doctor'] = $dead;
                    $game['village'][$dead] = 1;
                }
                else if(strpos($line,"a villager") !== false){
                    $game['village'][$dead] = 1;
                }
                else if(strpos($line,"a mafioso") !== false){
                    $game['mafia'][$dead] = 1;
                }
                unset($game['alive'][$dead]);
                $game['dead'][$dead] = 1;
            }
            else if(strpos($line,"Investigations showed") !== false){
                $e = explode(" ",trim($line));
                $name = $e[3];
                $align = trim($e[5]);
                $e = explode("-",$align);
                $game[$e[0]][$name] = 1;
            }
        }
        $game['currentvotes'] = array();
        $game['currentmessages'] = array();
        foreach($game['alive'] as $name=>$g){
            $game['currentvotes'][$name] = '';
        }
    }
    else{
        foreach($in as $line){
            if(strpos($line," has voted to lynch no one") !== false){
                $e = explode(" ",trim($line));
                $game['votes'][$e[0]][] = false;
                $game['currentvotes'][$e[0]] = false;
            }
            else if(strpos($line," has voted to ") !== false){
                $e = explode(" ",trim($line));
                $game['votes'][$e[0]][] = trim($e[5]," .");
                $game['currentvotes'][$e[0]] = trim($e[5]," .");
            }
            else if(strpos($line," says ") !== false){
                foreach($msgids as $msg=>$id){
                    $chk = preg_match('/([^\s]+) says "(([^\s]+)[:,] )?'.preg_quote($msg).'( ([^\s]+))?"/',$line,$matches);
                    if($chk){
                        //                                  said by     said to     said  said about
                        $game['messages'][]         = array($matches[1],$matches[3],$msg, $matches[5]);
                        $game['currentmessages'][]  = array($matches[1],$matches[3],$msg, $matches[5]);
                    }
                }
            }
        }
        $written = false;
        $convo = array();
        foreach($game['currentmessages'] as $msg){
            if($msg[1] == $self){
                $convo[$msg[0]] = $msg;
            }
            else if($msg[0] == $self && $msg[1] != ''){
                unset($convo[$msg[1]]);
            }
        }
        if(count($convo)){
            foreach($convo as $c){
                if($msgids[$c[2]] == 11){
                    if($game['mafia'][$msg[3]]){
                        write('to_server',"say 1 ".$msg[0]);
                        $written = true;
                        break;
                    }
                    else if($game['village'][$msg[3]]){
                        write('to_server',"say 0 ".$msg[0]);
                        $written = true;
                        break;
                    }
                    else{
                        write('to_server',"say 11 ".$msg[0]);
                        $written = true;
                        break;
                    }
                }
                else if($msgids[$c[2]] == 16){
                    write('to_server',"say 0 ".$msg[0]);
                    $written = true;
                }
                else{
                    write('to_server',"say 4 ".$msg[0]);
                    $written = true;
                }
            }
        }
        if(!$written){
            $currentvote = false;
            if(array_key_exists($self,$game['currentvotes'])){
                $currentvote = $game['currentvotes'][$self];
            }
            if($game['mafia'][$self]){
                $votes = @array_count_values($game['currentvotes']);
                if($votes && count($votes)){
                    arsort($votes);
                    foreach($votes as $name=>$number){
                        if($game['village'][$name]){
                            if($currentvote != $name){
                                write('to_server','vote '.$name);
                                $written = true;
                                break;
                            }
                        }
                    }
                }
            }
            else{
                if(count($game['mafia'])){
                    foreach($game['mafia'] as $name=>$g){
                        if($game['alive'][$name]){
                            $written = true;
                            if($currentvote != $name){
                                write('to_server','vote '.$name);
                            }
                            break;
                        }
                    }
                    if(!$written){
                        foreach($game['mafia'] as $name=>$g){
                            $non = $game['alive'];
                            unset($non[$self]);
                            if(array_key_exists($name,$game['votes'])){
                                foreach($game['votes'][$name] as $vote){
                                    if(array_key_exists($vote,$non)){
                                        unset($non[$vote]);
                                    }
                                }
                            }
                            if(count($non)){
                                $rand = array_rand($non);
                                write('to_server','vote '.$rand);
                                $written = true;
                                break;
                            }
                        }
                    }
                }
                if(!$written && $game['cop']){
                    $possible = array();
                    foreach($game['votes'][$game['cop']] as $name){
                        if($game['alive'][$name] && $name != $self){
                            $possible[] = $name;
                        }
                    }
                    if(count($possible)){
                        shuffle($possible);
                        write('to_server','vote '.$possible[0]);
                        $written = true;
                    }
                }
                if(!$written && count($game['dead'])){
                    foreach($game['dead'] as $name=>$g){
                        if($game['village'][$name]){
                            $v = array();
                            foreach($game['votes'] as $voted=>$arr){
                                if($game['alive'][$voted] && in_array($name,$arr)){
                                    $v[$voted] = 1;
                                }
                            }
                            unset($v[$self]);
                            if(count($v)){
                                $rand = array_rand($v);
                                write('to_server','vote '.$rand);
                                $written = true;
                                break;
                            }
                        }
                    }
                }
                if(!$written){
                    $votes = @array_count_values($game['currentvotes']);
                    if($votes && count($votes) && array_key_exists($self,$votes)){
                        arsort($votes);
                        foreach($votes as $name=>$number){
                            if(!$game['village'][$name]){
                                if($name != $self){
                                    write('to_server','vote '.$name);
                                    $written = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    $myinfo = json_encode($game);
    write('myinfo',$myinfo);
}

function write($filename,$data){
    $fh = fopen($filename,"wb+");
    if($fh){
        $bytes = fwrite($fh,$data);
        fclose($fh);
    }
}

不是我希望的一切。我可能偶尔会对其进行调整。

工作原理v1.0

跟踪每天的数字,谁还活着,谁死了,谁是黑手党,谁与村庄对齐,角色,当日票数/消息以及总体票数/消息。

  1. 一种。黑手党-投票给所有投票给黑手党的村民(如有可能),否则为随机村民。

    b。警察-调查身份不明的任何人。

    C。医生-首先保存自己,然后保存警察(如果知道的话)(我现在还不知道),保存村民(如果知道的话)(可能也不知道),否则保存随机的人。

  2. 一种。如果有人直接向自己说了一条信息,请回复他们(可能的回复有限)。

    b。黑手党-为投票最多的村民投票。

    C。村民以任何活跃的黑手党联盟而闻名-投票给黑手党成员。

    d。只知道死于黑手党的村民-为从未投票给黑手党的随机机器人投票。

    e。知道警察的村民-为警察投票的随机机器人投票。

    F。村民与死者有渊源。与村民结盟的人已知-为投票给死者的随机机器人投票。

    G。投票反对自我的村民-投票赞成目前票数最高的非乡村联盟机器人。


1
等等,这是做什么的?
SIGSTACKFAULT

1
为什么,它会玩黑手党!:)
乔。

我的意思是策略。
SIGSTACKFAULT

6

该示例代码对我不起作用,我使用Python 3,因此我更改了main.py文件以使其起作用。

所以这是我的Python 3固定版本,我以前从未用Python编程过,所以也许这是一个可怕的代码,但确实可行:)

run.sh

#!/bin/bash

./randy.py < from_server > to_server

randy.py

#!/usr/bin/env python3

import random

with open('players') as f:
    p = f.read().split() + ['no one']

with open('from_server') as f:
    fs = f.read().split()

msg = ""
day = True
try:
    line = fs[0]
    if line.endswith(('?', 'victim.')):
        day = False
    if not day:
        msg = (random.choice(p))
    else:
        if random.random() > 0.5:
            if random.random() > 0.5:
                msg = ('vote {}'.format(random.choice(p)))
            else:
                id = random.randint(0, 17)
                msg = ('say {}{}'.format(id, (' ' + random.choice(p)) if id > 4 else ''))

    with open('to_server', 'w') as f:
        f.write(msg)
    print(msg)
except: pass

我在进行这项工作时学到了一些东西(在描述中我不清楚)

  • print对游戏没有任何作用,就像console.log在js中一样
  • input() 阻止程序运行,可以很好地进行逐步调试
  • from_serverto_server在每一轮清除。
  • 通过Ctrl+C组合停止脚本是不可能的,这很烦人。

欢迎来到PPCG!很棒的第一篇文章!希望你坚持!我已经对您的帖子进行了编辑,以突出显示有效的语法,并且为了保持一致性,添加了一个run.sh
Rɪᴋᴇʀ

1
谢谢!我不确定< from_server > to_server是否有必要,因为我在代码中硬编码了文件名。游戏引擎只是调用./run而无需管道。因此input()print()不适用于游戏。mayn.py57行:os.system('./run')
彼得

2
您如何使控制器运行?我不知道。您可以提供示例调用吗?
Rɪᴋᴇʀ

注意:原始文件randy.py是用Python 2编写的,这引起了问题。
SIGSTACKFAULT

对于控制器,您需要./start从原始文件夹进入,或者您需要Python 3版本的main.py
Peter

5

逻辑学家

#!/usr/bin/env python3
import sys
import os
import re
import random
from types import SimpleNamespace
def chooseSet(set):
    return random.choice(list(set))
sys.stdin = open("from_server")
sys.stdout = open("to_server","w")
def saveData(data):
    with open("gameData.txt", "w") as datafile:
        datafile.write(repr(data.__dict__))
MY_NAME = os.path.basename(os.getcwd())
opener = input()
DATABASES = ("targets","herd","mafiosos","guilty","innocent","unlikely", "requests",
            "selfvotes","players","used_roles")
ALLOW_SELF = ("players", "mafiosos")
LIESPERROLE = {"cop": ("I am the cop",
                "I investigated this player and found that they were mafia-aligned",
                "I investigated this player and found that they were village-aligned"),
              "doctor": ("I am the doctor",
                   "I tried to save this player",
                   "I successfully saved this player"
                   )
        }
#1: At the beginning of the game, parse beginning of day 0
if opener == "Rise and shine! Today is day 0.":
    #Next two lines are completely predetermined and hold no data
    assert input() == "No voting will occur today."
    assert input() == "Be warned: Tonight the mafia will strike."
    data = SimpleNamespace(cop=False, doctor=False, queued=[],askers={})
    for datum in DATABASES:
        setattr(data, datum, set())
    try:
        nextline = input()
        if nextline == "You are a member of the mafia.":
            data.mafiosos.add(MY_NAME)
            assert input() == "Your allies are:"
            while True:
                data.mafiosos.add(input())
        elif nextline == "You are the doctor":
            data.doctor = True
            data.used_roles.add("doctor")
        elif nextline == "You are the cop":
            data.cop = True
            data.used_roles.add("cop")
    except EOFError:
        #villager, or ran out of mafiosos to add
        pass
    with open("players") as playersfile:
        data.players = set(playersfile.read().strip().splitlines())
    saveData(data)
    exit()
with open("gameData.txt") as datafile:
    data = SimpleNamespace(**eval(datafile.read().strip()))
#2: Beginning of day nonzero
if opener.startswith("Dawn of day"):
    data.requests.clear()
    data.selfvotes.clear()
    data.askers.clear()
    data.voted = False
    try:
        while True:
            nextline = input()
            victim = re.match("Last night, (.*) was killed. They were (?:a|the) (.*).", nextline)
            if victim:
                victim, role = victim.groups()
                #remove dead people from lists
                for datum in DATABASES:
                    getattr(data, datum).discard(victim)
                if role == "cop" or role == "doctor":
                    data.used_roles.add(role)
                continue
            investigated = re.match("Investigations showed that (.*) is (.*)-aligned.", nextline)
            if investigated:
                assert data.cop
                who = investigated.group(1)
                if investigated.group(2) == "mafia":
                    data.guilty.add(who)
                    data.unlikely.discard(who)
                else:
                    data.targets.discard(who)
                    data.herd.discard(who)
                    data.innocent.add(who)
                    data.unlikely.add(who)
                continue
    except EOFError:
        pass
#3: We're being told some messages / news
elif " says " in opener or " voted " in opener:
    message = opener
    acted = question = False
    try:
        while True:
            if " voted " in message:
                message = "<vote against>"
                speaker, subject = re.match("(.*) has voted to lynch (.*)", message).groups()
                target = None
            else:
                speaker, target, message, subject = \
                    re.match("(.*) says \"(?:(.*), )?([^:\?]+)(?:[:\?]\s*(.*))?\"",
                             message).groups()
            if speaker == MY_NAME:
                continue
            BAD_MESSAGES = ("<vote against>", "I think this player is mafia",
                            "I investigated this player and found that they were mafia-aligned",
                            "I think this player is suspicious")
            GOOD_MESSAGES = ("I think this player is the cop",
                             "I think this player is the doctor",
                             "I think this player is a normal villager",
                             "I trust this player",
                             "I investigated this player and found that they were village-aligned")
            OUTS = "I am the cop", "I am the doctor"
            LIES = ()
            for role in data.used_roles:
                LIES += LIESPERROLE[role]
            if message == "Yes" or message == "No":
                if question and not target:
                    target = chooseSet(data.askers)
                if target in data.askers:
                    BAD_MESSAGES += "Yes",
                    GOOD_MESSAGES += "No",
                    subject = data.askers[target]
            if message in LIES and speaker not in data.mafiosos and speaker not in data.innocent:
                # What you just said is false, and I know it!
                data.unlikely.discard(speaker)
                data.targets.add(speaker)
                if subject and subject not in (data.unlikely.union(data.mafiosos)):
                    data.targets.add(subject)
            elif message in BAD_MESSAGES:
                if speaker in data.guilty:
                    #mafiosos rarely turn on eachother
                    data.unlikely.add(subject)
                    data.targets.discard(subject)
                elif speaker in data.unlikely:
                    #believe the herd, especially people who we trust
                    data.herd.add(subject)
                elif subject in data.unlikely:
                    #how dare you speak against players likely to be village-aligned!
                    data.targets.add(speaker)
                elif subject == MY_NAME or subject in data.mafiosos:
                    #DON'T ATTACK ME (or my fellow mafiosos)
                    data.targets.add(speaker)
                else:
                    #believe the herd
                    data.herd.add(subject)
                if not acted and message == "<vote against>":
                    if subject == MY_NAME:
                        data.selfvotes.add(speaker)
                        if len(data.selfvotes) >= (len(data.players)-len(data.mafiosos))/3:
                            if data.cop:
                                print("say 2")
                                #give a data point to prove it
                                if random.random() > .5 and data.guilty:
                                    data.queued.append("say 14 %s" % chooseSet(data.guilty))
                                elif data.innocent:
                                    data.queued.append("say 15 %s" % chooseSet(data.innocent))
                            else:
                                print("say 4") #Don't out myself if I'm the doctor
                                # and just lie if I'm a mafioso
                            acted = True
                    else:
                        data.selfvotes.discard(speaker)
            elif message in OUTS and data.mafiosos and speaker not in data.unlikely:
                data.targets.add(speaker) #Kill the fools who boast!
            elif message in GOOD_MESSAGES:
                chance = random.random() < .1 - (speaker in data.targets) / 20
                if speaker in data.guilty: #Mafia liars
                    if subject not in data.unlikely:
                        data.targets.add(subject)
                elif subject == MY_NAME and chance:
                    if speaker in data.targets:data.targets.remove(speaker)
                    data.unlikely.add(speaker)
                elif speaker in data.unlikely or chance:
                    data.unlikely.add(subject)
            elif message == "Do you think this player is mafia":
                if subject == MY_NAME:
                    data.targets.append(speaker)
                if target == MY_NAME or not target:
                    if speaker in data.guilty:
                        data.queued.append("say 14 %s %s" % (subject, speaker))
                    elif speaker in data.innocent:
                        data.queued.append("say 15 %s %s" % (subject, speaker))
                    elif subject in data.targets or subject in data.herd:
                        data.queued.append("say 1 %s" % (speaker))
                    elif subject in data.unlikely:
                        data.queued.append("say 0 %s" % (speaker))
                    if data.cop:
                        data.requests.add(subject)
                data.askers[speaker] = subject
                question = True
            elif target == MY_NAME and message == "Will you please use your power on this player tonight":
                data.requests.add(subject)
            message = input()
    except EOFError:
        pass
    for datum in DATABASES:
        if datum in ALLOW_SELF: continue
        getattr(data, datum).discard(MY_NAME)
    chance = random.random()
    if data.queued:
        print(data.queued.pop())
    elif chance < .1:
        target = chooseSet(data.targets or data.players)
        if target != MY_NAME:
            print("say 10 %s" % target)
            data.askers[MY_NAME] = target
    elif chance < .3 and data.targets:
        print("say 6 %s" % chooseSet(data.guilty or data.targets))
    elif chance < .5 and data.unlikely:
        print("say 5 %s" % chooseSet(data.innocent or data.unlikely))
    elif chance < .6 and not data.voted:
        target = chooseSet(data.guilty or data.targets or data.herd or data.players)
        if target not in data.mafiosos and target != MY_NAME:
            print("vote %s" % target)
        data.voted = True
    elif chance < .8:
        #do nothing
        pass
    elif chance < .9:
        #Confuse everybody
        print("say 1")
        data.queued.append("say 0")
######################
#4: End of day
elif "has killed" in opener:
    victim = re.match("The town has killed (.*)!", opener)
    if not victim:
        exit()
    victim = victim.group(1)
    #remove dead people from lists
    for datum in DATABASES:
        getattr(data, datum).discard(victim)
    role = input()
    role = re.match("They were (?:a|the) (.*)", role).group(1)
    if role == "cop" or role == "doctor":
        data.used_roles.add(role)
    #Misc: purge people from lists if too large
    for list in data.unlikely, data.targets, data.herd:
        while len(list) > len(data.players)/3:
            list.pop()
    for player in data.innocent:
        data.unlikely.add(player)
elif opener == "The town opted to lynch no one today.":
    #Do nothing
    pass
#5: Night
elif "night" in opener:
    if not data.mafiosos and data.requests and random.random() > .5:
        print(chooseSet(data.requests))
    if data.doctor:
        print(chooseSet(data.unlikely or data.players))
    else:
        while True:
            try:
              target = (data.targets or data.herd).pop()
            except KeyError:
              target = chooseSet(data.players)
            if target in data.mafiosos or target == MY_NAME:
                continue
            print(target)
            break
else:
    raise ValueError("Unknown message")
saveData(data)

花哨的,一长串我不会解释的python代码(尽管它没有打高尔夫球),除了它保留了最初基于机会和/或警察调查而填充的“朋友”和“敌人”列表。警告:请勿躺在逻辑学家面前。


是您run.sh的标准(进行一些测试)
Stan Strum

不,我的run.sh可以纯粹是“ run.py”,而没有通常的输入和输出管道,但是该标准可以工作。
pppery

1
如果有时间和爱好,这看起来与我所写的内容非常相似。
Draco18s

由于某种原因,我认为逻辑学家不会在其他机器人周围做得很好...其他机器人都没有报告警察调查
JavaScriptCoder

1
……几个月后,我意识到我的回答错误地假设只能有一位警察/医生。
pppery

4

生存主义者(v 1.0)

概要

生存主义者只是通过指责敢于指责他的人残酷地生存下来,无论他是否是黑手党。

逻辑

如果您生存到比赛的最后,无论如何您都赢了。因此,您不惜一切代价生存。

背景故事

部队穿过黑暗潮湿的森林。

“中尉,我们要去哪里?” 这位指挥官认为,这名年轻的新兵显然没有使自己暴行。那好吧。他轻率地回答“消灭敌人”。

在村子里,当一个侦察员赶来时,敌方指挥官正在与俱乐部的其他官员一起喝酒并大笑。“有一排长几百码的圆柱,为我们在榆林森林里游行!召集部队!”

显然很生气的敌军指挥官出乎意料地说道:“我没有其他侦察员的报告。” 侦察员(后来的生存主义者)认为,那么我将不得不亲自集结部队。在向同伴们讲完故事后,他们回到了一起,都说他们见过敌军。指挥官仍然不相信,说:“我命令你停止侦察。没有敌军”。

侦察兵决定拿出武器拯救社区。当敌人到达有效村庄时,他们设法站稳了自己的位置。“收费!” 伏击指挥官大喊。“烧房子!烧房子!杀死所有人,包括妇女和儿童!

侦察员解救了他们的整个军队。他们期望获得晋升,奖励和奖牌。取而代之的是,他们因10变,定罪,10年监禁,从军方不光彩放逐和流放而被操纵的军事法庭。


马萨诸塞州塞勒姆市议会有一位年长的老人。传说他建立了这个城镇。当您在森林中他与世隔绝的小屋中遇见他时,不要让他眨眼间就让您觉得他很安宁。如果您指责他,他将在镇前毁灭您。

退伍军人在黑暗中笑了。害怕黑暗,没有办法。害怕床底下的怪物?那个手握枪的人紧张地笑了。他告诉自己,他什么都不怕。当然,他曾经是战时英雄,但由于他习惯于伏击和威胁生命的情况,因此使该人变得神经质。他的扳机手指在简单的阴影下抽动。每发出一点声音他的心跳都加快了。是的,他很害怕死亡。看到这么多人以可怕的方式死亡,他怎么可能不?他被绑架并奇迹般地逃脱了敌人,他所知道的就是没有怜悯之心。

老将


代码(我是python的新秀,不确定代码是否不错)

#!/bin/python2

import random

with open('players') as f:
    p = f.read().split() + ['no one']


day = True
target = "survivalist"
role = "villager"
try:
    line = raw_input()
    if "You are the cop" in line:
        role = "cop"
    else if "You are the doctor" in line:
        role = "doctor"
    else if "You are a member of the mafia" in line:
        role = "mafia"

    if line.endswith(('?', 'victim.')):
        day = False
    if not day:
        if target == "survivalist":
            print random.choice(p)
        else if role == mafia || role == sheriff:
            print target
        else if role == doctor:
            print random.choice(p)
    else:
        if "survivalist" in line && ("I think this player is suspicious:" in line || 
        "I think this player is mafia:" in line ||
        "I investigated this player and found that they were mafia-aligned:")):
            print 'say 0'
            if role == "villager" || role == "mafia":
                print 'say 4'
            else if role == "cop":
                print 'say 2'
            else if role == "doctor"
                print 'say 3'
            target = line.split(" ")[0]
            print 'vote ' + target

        else if target != "survivalist":
            print 'say 6 ' + target
            print 'vote ' + target
    else:
        pass

except: pass

您是or不是要说||?你测试了吗?另外,你或许应该指出的是,这是Python的2
所罗门会员名:Ucko

3

头像

阿凡达(Avatar)“随机”在开始时挑选一名球员,并在接下来的回合中不懈地专注于他们。

这不是对同名动画电视节目的引用。

这是EVE在线参考。

下载所有必需文件的tar

变更日志

  • v1生日
  • v2不记录任何内容stdout,仅记录到stderr
    要也禁止显示stderr,请添加2>/dev/nullrun文件末尾。
/*  Casting his sight on his realm, the Lord witnessed
    The cascade of evil, the torrents of war.
    Burning with wrath, He stepped 
    down from the Heavens
    To judge the unworthy,
    To redeem the pure.

    -The Scriptures, Revelation Verses 2:12
*/

#include <stdlib.h>
#include <stdio.h>
#include "mafia.h"

int getRandomNumber(){
    return 4; // Chosen by a fair dice roll.
              // Garunteed to be random.
}


void day0(){
    char * target = get_player(getRandomNumber()-1)->name;
    fprintf(stderr, "Target: `%s'\n", target);
    FILE * f = fopen("target", "w");
    if(!f){exit(1);}
    fprintf(f, "%s", target);
    fclose(f);
}


int main(){
    get_players();
    int cycle = get_cycle(day0);
    FILE * out = fopen("to_server", "w");
    if(!out){exit(1);}
    FILE * targetF = fopen("target", "r");
    if(!targetF){exit(1);}

    char target[64];

    fscanf(targetF, "%s", target);

    fprintf(stderr, "Target: %s\n", target);

    if(cycle == 0){
        // night
        fprintf(out,"%s\n", target);
        fprintf(stderr, "> Voting to kill %s\n", target);
        exit(0);
    } else if (cycle > 0) {
        // day
        fprintf(out, "vote %s\n", target);
        fprintf(stderr, "> Voting to lynch %s\n", target);
        exit(0);
    } else if (cycle == -1) {
        fprintf(stderr, "> saying 6, 10 at %s\n", target);
        fprintf(out, "say 6 %s\n", target);
        fprintf(out, "say 10 %s\n", target);
    }
}

这个需要 mafia.cmafia.h我编写的库在同一目录中。

这些内容连同Makefile和运行脚本一起包含在下载中。

去做

  • 当他们被杀死或私刑时,停止对目标投票。

当我在这里时,我将提交非机器人史蒂夫:


仅供参考,我叫了拨款上avatarerebusleviathan,和ragnarok
SIGSTACKFAULT

“这不是对同名动画电视节目的引用。” 它是对电影的引用吗?
Stan Strum,

@StanStrum不,不是。
SIGSTACKFAULT

我的机器人的from_server文件未写入。您是否需要设置特定的权限或其他内容?
Rɪᴋᴇʀ

1
出于好奇,请注意:此处引用的圣经是EVE Online 的Amarr圣经。这里一个启示2:12在圣经中,但它读取而不同。
DLosc

2

利维坦

Leviathan遍历players文件中的所有播放器,并一一针对他们。

下载

/*  Citizens of the State, rejoice!

    Today, a great milestone has been achieved by our glorious leaders.
    A stepping stone in the grand story of our empire has been traversed.
    Our individual fears may be quietened;
    the safety of our great nation has been secured.

    Today, unyielding, we have walked the way of the warrior.
    In our hands have our fates been molded.
    On the Leviathan's back will our civilization be carried home
    and the taint of the Enemy purged from our souls.

    Rejoice, citizens! Victory is at hand.

    -Caldari State Information Bureau Pamphlet, YC 12
*/

#include <stdio.h>
#include <stdlib.h>
#include "mafia.h"

void day0(){
    FILE * index = fopen("idx", "w");

    fprintf(index,"0");

    fclose(index);
}

int main(){
    get_players();
    int i, cycle = get_cycle(day0);

    FILE * out = fopen("to_server", "w");
    FILE * idx = fopen("idx", "r");

    fscanf(idx, "%d", &i);
    fclose(idx);

    char * target;
    target = get_player(i)->name;

    fprintf(stderr, "Idx: %d\n", i);
    fprintf(stderr, "Target: %s\n", target);

    if(cycle > 0){
        idx = fopen("idx", "w");
        i++;
        i = i%NPLAYERS;
        fprintf(idx, "%d", i);
        fprintf(out, "vote %s\n", target);
    } else if (cycle == -1) {
        printf("> saying 6, 10 at %s\n", target);
        fprintf(out, "say 6 %s\n", target);
        fprintf(out, "say 10 %s\n", target);
    }

    fclose(out);
}

与Avatar一样,它要求mafia.cmafia.h在同一目录中。

这些内容连同Makefile和运行脚本一起包含在下载中。


:)一旦完成就添加了生存
JavaScriptCoder
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.