マフィアを遊ぼう!


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を実行できるすべての言語が参加できるように、この方法を選択しました。言語がファイルI / Oよりも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いずれvillagemafiaです。最後に、remaining_playersこの形式でまだ生きているプレイヤーのリストです:player1, player2, player3

昨夜殺害がなかった場合、2行目は省略され、3行目は警官にのみ表示されます。

例えば、

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

このメッセージが途切れると、その日が始まります!各ボットは1日を通して50のアクションを実行できます。「アクション」はプレイヤーに投票したり、何かを大声で言ったりします。

プレーヤーに投票するにはvote player_nameto_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?

最初の5つを除くこれらのメッセージはすべて、特定のプレーヤーに関するものです。それらのメッセージの1つを言うには、と書きsay message_id player_nameます。最初の5つのメッセージの1つについては、単に書き込みsay message_idます。これらの両方にオプションの3番目の引数を追加して、会話しているプレーヤーの名前を指定することができます(すべてのプレーヤーはそれを読むことができますが、目的の受信者が誰であるかはわかります)。

ボットがメッセージを言うと、すべてのプレイヤーがを読みますyour_bot says "message"。ここmessageで、書いたIDに関連付けられたメッセージがあります。メッセージに件名が含まれる場合、1つのスペース文字と件名がメッセージの終わりの直後に挿入されます。受信者が含まれる場合は、名前、コロン、スペース文字がメッセージの直前に挿入されます。

一日の終わりに、投票の結果を見るために、すべての生きているプレーヤーが最後にもう一度実行されます。プレイヤーが投票された場合、これは次のように書かれます。

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?。この場合、保護したいプレーヤーの名前を出力します。

この後、通常どおり翌日が始まります。

ゲームごとに1回だけ保存できます。

一般情報

  • ゲームは6人以上のプレイヤーなしでは実行されません。
  • プレイヤーの3分の1は切り捨てられ、マフィアになります。1人のプレイヤーが医者になり、1人のプレイヤーが警官になります。他のすべてのプレイヤーは村人です。
  • 村の投票またはマフィアの一晩の投票は、ランダムに解決されます。
  • ボット名は、英数字+ダッシュとアンダースコアでなければなりません。
  • 相手のコードの知識を直接使用することは禁じられています。理論的には、これまで見たことのないボットに対してボットを配置し、同等のパフォーマンスを発揮できるはずです。
  • 残念なことに、もしも独占的に無料の(ビールのように)ソフトウェアを使用してプログラムを実行できない場合は、失格にする必要があります。
  • 悪意があると思われる場合、提出物を失格にする権利を留保します。これには、実行に時間、メモリ、またはスペースを過度に使用することが含まれますが、これらに限定されません。私は意図的に制限をソフトのままにしましたが、覚えておいてください:私はこれをスーパーコンピューターではなく自宅のコンピューターで実行しているので、結果を得るのに1年かかりたくありません。私の基準はかなり低いので、これを使用する必要はありません。これは基本的に「あなたが意図的にペニスをしていると思うなら」であり、そうでなければ私を納得させることができれば、私は私の決定を覆します。

得点

各ラウンドでは、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 the Robotはマフィアの良いプレイヤーではありません。ランディはほとんど何も無視して、何を言うか、誰に投票するか、誰が夜の力で標的にするかをランダムに選択します。

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は、このチャレンジの制御プログラムを作成しましたこちらから入手できます

コーディングして回答を提出するのに1か月かかります。勝ったボット(最高の勝率のタイブレーカーは投票です)に少なくとも50の評判バウンティを与えます(1か月でどれだけの担当者を獲得できるかによって異なります)


@Blacksilverが作成した、コンパイルされた言語で使用するラッパースクリプトを次に示します。

#!/bin/bash

run="./a.out"
compile="gcc bot.c"

if [ -e $run ]; then
        $run
else
        $compile
        $run
fi

これを入れrunます。


この投稿は@undergroundmonorailによって書かれました(私はいくつかの編集を行いました)。

彼はここでそれを終わらせて、それを投稿したかった誰にでも断念しまし


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
マーティンエンダー

回答:


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. a。マフィア-可能であれば、マフィアに(ランダムに)投票した村人、そうでなければランダムな村人に投票してください。

    b。警官-アライメントが不明な人を調査します。

    c。ドクター-最初のターンで自己を保存し、既知の場合は警官を保存します(現時点ではこれを知ることができないと思います)、既知の場合は村人を保存します(おそらくこれも知らない)

  2. a。誰かが自分に直接メッセージを話している場合は、それらに応答します(限られた応答が可能です)。

    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

この作品を作っている間に私が学んだいくつかのこと(そしてそれは説明で私には明確ではありませんでした)

  • printconsole.logjsのようなゲームでは何もしません
  • input() それを実行しているプログラムをブロックして、ステップバイステップのデバッグに適している可能性があります
  • from_serverそしてto_serverすべてのラウンドをクリアされます。
  • Ctrl+C組み合わせてスクリプトを停止することはできません。これは迷惑です。

PPCGへようこそ!素晴らしい最初の投稿!頑張ってね!機能する構文を強調表示するように投稿を編集しましたrun.sh。一貫性のためにを追加しました。
Rɪᴋᴇʀ

1
ありがとうございました!< from_server > to_serverコードにファイル名をハードコーディングしているため、必要かどうかはわかりません。ゲームエンジンは./runパイプなしで呼び出すだけです。そうinput()print()ゲームで動作しませんでした。mayn.py行57:os.system('./run')
ピーター

2
コントローラーをどのように実行しましたか?わかりません。サンプル呼び出しを提供できますか?
Rɪᴋᴇʀ

注:オリジナルrandy.pyPython 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の標準(テストを行う)
スタンストラム

いいえ、私のrun.shは、通常の入力および出力パイプなしで純粋に「run.py」にすることができますが、標準は機能します。
pppery

1
これは、私が時間と傾向があれば、私が書いたものと非常によく似ています。
Draco18s

何らかの理由で、論理学者は他のボットの周りであまりうまくいかないと思う...他のボットは誰も警官の調査を報告しない
-JavaScriptCoder

1
...そして、数か月後、私の答えは警官/医師が1人しかいないと誤って仮定していることに気付きました。
pppery

4

サバイバリスト(v 1.0)

あらすじ

サバイバリストは、彼がマフィアであるかどうかに関係なく、あえて彼を非難する人をbe辱することによって、残酷にゲームを生き残ります。

論理

ゲームの最後まで生き延びれば、何があっても勝ちます。したがって、あなたはすべてのコストで生き残ります。

バックストーリー

軍隊は暗く湿った森の中を行進した。

「中Li、私たちはどこへ行進していますか?」若き新兵は明らかに残虐行為に身を固めていなかった、と司令官は考えた。しかたがない。彼は「敵を破壊するために」大胆に答えました。

村では、スカウトがニュースに駆けつけたとき、敵の指揮官がクラブの他の役員と一緒に飲んで笑っていました。「長さ数百ヤードの円柱があり、私たちのためにユーリンの森を行進します!軍隊を結集してください!」

明らかに酔っ払った敵の指揮官は、「他のスカウトからの報告はない」と予想外に言った。スカウト(後のサバイバリスト)は、自分で軍隊を結集しなければならないと考えました。仲間のスカウトに話をした後、彼らは一緒に戻ってきて、全員が敵軍を見たと言った。司令官はまだ信じていませんでした、「私はあなたに偵察を中止するよう命じています。敵軍はいません」。

スカウトは、コミュニティを救うために武器を手に入れることにしました。彼らは、敵が力で村に到着したちょうどその時、彼らの位置に着くことに成功しました。"充電!" 待ち伏せの司令官を叫んだ。「家を燃やせ!家を燃やせ!女性と子供を含め、みんな殺せ!

スカウトは全軍を救った。彼らは昇進、賞、メダルを期待していました。その代わりに、彼らは反乱、有罪判決、10年の刑務所、軍隊と亡命者からの不名誉な退役のために装備された軍法会議を受けました。


マサチューセッツ州セーラム市議会には年長者がいます。伝説によると、彼は町を設立しました。森の中の彼の孤立したコテージで彼に会うとき、彼の目にきらめいて彼を平和だと思わせないでください。あなたが彼を非難すると、彼は町の前であなたを台無しにします。

ベテランは暗闇の中で笑った。暗闇を恐れて、まさか。ベッドの下のモンスターが怖い?銃の引き金を握った男は神経質に笑った。彼は何も怖がっていませんでした、彼は自分自身に言いました。確かに、彼は過去の戦時のヒーローでしたが、彼は待ち伏せや生命を脅かす状況に非常に慣れていたので、その男は単に神経症になりました。彼の引き金の指は単純な影にひきつりました。彼の鼓動は小さな音で一息ついた。はい、彼は死を恐れていました。非常に多くの人々が恐ろしい方法で死ぬのを見て、どうして彼はできなかったのでしょうか?彼が誘nされ、奇跡的に敵から逃げることで知っていたのは、慈悲がないということだけでした。

ベテラン


コード(私は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

アバター

アバターは、開始時に「ランダムに」1人のプレイヤーを選択し、ラウンドの残りの期間に執lentに集中します。

これは、同様の名前のアニメ化されたテレビ番組への参照ではありません。

それは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と実行スクリプトとともにダウンロードに含まれています。

TODO

  • ターゲットが殺されたりリンチされたりしたら、ターゲットに対する投票を停止します。

私がここにいる間に、ボット以外のスティーブを提出します。


FYI、私は上のDIBのを呼び出しavatarerebusleviathan、およびragnarok
SIGSTACKFAULT

「これは、同様の名前のアニメ化されたテレビ番組への参照ではありません。」映画への参照ですか?
スタンストラム

@StanStrumいいえ、そうではありません。
SIGSTACKFAULT

ボットのfrom_serverファイルに書き込まれていません。特定の許可などを設定する必要がありましたか?
Rɪᴋᴇʀ

1
不思議なことに注意してください:ここで参照されている聖書は、EVE OnlineのAmarrのものです。聖書には黙示録2:12があります、読み方はかなり異なります。
DLosc

2

リヴァイアサン

リヴァイアサンは、playersファイル内のすべてのプレーヤーを反復処理し、それらを1つずつターゲットにします。

ダウンロード

/*  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);
}

アバターと同じように、それは必要ですmafia.cし、mafia.h同じディレクトリにあります。

これらは、Makefileと実行スクリプトとともにダウンロードに含まれています。


:)それが終わったらサバイバリストを追加
JavaScriptCoder
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.