Ayo Main Mafia!

42

Mafia (juga dikenal sebagai Werewolf) adalah gim pesta yang bermain kira-kira seperti ini:

  • Permainan dimulai pada hari ke 0. Setelah setiap hari ndatang malam n. Setelah setiap malam ndatang sehari n+1. yaitu D0, N0, D1, N1, D2, N2...
  • Pada dini hari 0, tuan rumah diam-diam memilih pemain untuk mengisi peran tertentu:  
    • Sejumlah pemain menjadi mafia. Setiap malam, setiap mafioso memilih pemain. Pada subuh keesokan harinya, pemain yang dipilih oleh sebagian besar mafiosos terbunuh. Mereka secara permanen dihapus dari permainan dan peran mereka diungkapkan kepada publik. Selaras mafia.  
    • Beberapa pemain menjadi polisi. Setiap malam, setiap polisi memilih pemain. Pada subuh keesokan harinya, polisi menjadi sadar akan keselarasan para pemain itu. Village-aligned.  
    • Sejumlah pemain menjadi dokter. Setiap malam, setiap dokter memilih pemain. Jika pemain ini adalah pemain yang sama dengan yang dipilih mafia untuk dibunuh, tindakan mafia untuk malam itu dibatalkan. Village-aligned.  
    • Semua pemain yang tidak dipilih untuk peran lain adalah penduduk desa. Penduduk desa tidak memiliki kemampuan yang tidak dimiliki oleh seluruh kota. Village-aligned.
  • Setiap hari kecuali hari 0, seluruh kota (yaitu, semua pemain yang hidup) memberikan suara untuk seorang pemain. Pada akhirnya, pemain itu dikeluarkan dari permainan dan peran mereka diungkapkan. (Pada hari 0, semua orang hanya kedinginan sampai malam hari.)
  • Jika, pada titik mana pun, tidak ada mafiosos yang tersisa, permainan berakhir dengan semua pemain yang selaras dengan desa menang (termasuk yang mati).
  • Jika, pada titik mana saja, pemain yang selaras dengan desa tidak melebihi jumlah pemain yang selaras mafia, permainan berakhir dengan semua pemain yang selaras mafia menang (termasuk yang mati).

Untuk tantangan ini, tujuan Anda adalah menulis bot untuk mengalahkan bot lain di Mafia!

Cara membuat bot yang berfungsi

Yang harus Anda berikan untuk saya adalah file bernama run. Di dalam struktur direktori tempat tantangan ini terjadi, bot Anda akan tinggal di sini:

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/

The runberkas, ketika dijalankan, akan membuat bot Anda melakukan hal tersebut. Penting untuk dicatat bahwa file ini tidak boleh memerlukan argumen baris perintah atau apa pun. Ini akan dijalankan persis seperti ./run. Jika Anda perlu dieksekusi dengan cara yang berbeda, Anda harus mengatasinya dengan melakukan sesuatu seperti ini:

real_bot.py

#!/bin/python2

# code goes here

run

#!/bin/bash

./real_bot.py --flags --or --whatever

Satu hal penting yang perlu diperhatikan adalah bahwa semua input yang diterima bot Anda akan ditemukan dalam file from_serverdan program kontrol akan mencari output bot Anda to_server. Saya memilih untuk melakukannya dengan cara ini sehingga bahasa apa pun yang dapat melakukan file I / O dapat berpartisipasi. Jika bahasa Anda membuatnya lebih mudah untuk bekerja dengan stdin dan stdout daripada file I / O, Anda mungkin ingin menulis runfile yang terlihat seperti ini:

#!/bin/bash

./real_bot.py < from_server > to_server

Ini akan membuatnya sehingga stdin berasal dari from_serverfile dan stdout langsung menuju to_server.

Bot Anda tidak akan tetap berjalan selama permainan. Sebaliknya, itu akan dijalankan ketika perlu membuat keputusan. Demikian juga, itu tidak akan diinformasikan ketika sudah mati, itu tidak akan berjalan lagi. Rencanakan ini dengan menyimpan apa pun yang ingin Anda ingat ke file dan membacanya nanti. Anda dapat membuat, menulis atau membaca dari file apa pun di folder bot Anda, tetapi Anda tidak boleh menulis atau membaca di mana pun di luar folder itu, termasuk akses jaringan atau apa pun . Jika bot Anda mengetahui sesuatu yang tidak diceritakan dari dalam folder, atau jika menyentuh apa pun yang tidak ada di dalam folder itu, bot Anda didiskualifikasi.

Cara membuat bot fungsional

Hari

Di awal permainan, file playersakan diisi dengan daftar semua pemain dalam game yang dibatasi-baris baru. Itu tidak akan diperbarui karena pemain meninggalkan permainan.

Pada dini hari 0, semua pemain akan menemukan pesan ini di from_serverfile mereka :

Rise and shine! Today is day 0.
No voting will occur today.
Be warned: Tonight the mafia will strike.

Jika Anda adalah polisi, garis You are the copditambahkan ke akhir. Dokter melihat You are the doctor. Mafia melihat You are a member of the mafia.\nYour allies are:dan daftar anggota mafia yang dibatasi baris baru, tidak termasuk pemain yang membaca pesan.

Di awal hari-hari lainnya, pesan ini akan muncul:

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`

dayNumberdiganti dengan jumlah hari. victimdiganti dengan nama korban tadi malam, dan victim_rolemerupakan salah satu dari:

  • a villager
  • a mafioso
  • the cop
  • the doctor

cop_targetadalah nama pemain yang diselidiki polisi tadi malam, dan target_alignmententah itu villageatau mafia. Akhirnya, remaining_playersadalah daftar pemain yang masih hidup dalam format ini:player1, player2, player3

Baris kedua dihilangkan jika tidak ada pembunuhan tadi malam, dan baris ketiga hanya ditampilkan kepada polisi.

Sebagai contoh,

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

Setelah pesan ini keluar dari jalan, hari dimulai! Setiap bot dapat melakukan 50 aksi sepanjang hari, di mana "aksi" memberikan suara untuk pemain atau mengatakan sesuatu dengan keras.

Untuk memilih pemain, tulis vote player_nameke to_serverfile Anda dan akhiri. Untuk memilih untuk tidak membunuh siapa pun, tulis vote no one. Saat Anda memilih, semua pemain (termasuk Anda) akan melihat your_bot votes to kill your_selection. Suara diabaikan pada hari ke 0.

Sejumlah pesan yang telah ditentukan dapat dikirim ke semua pemain. Id dari setiap pesan yang mungkin tercantum di sini:

 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?

Semua pesan ini kecuali lima yang pertama mengacu pada pemain tertentu. Untuk mengatakan salah satu pesan itu, tulis say message_id player_name. Untuk salah satu dari lima pesan pertama, cukup tulis say message_id. Anda dapat menambahkan argumen ketiga opsional untuk keduanya, menentukan nama pemain yang Anda ajak bicara (semua pemain masih bisa membacanya, tetapi mereka akan tahu siapa penerima yang dimaksud).

Ketika bot Anda mengatakan pesan, semua pemain membaca your_bot says "message", di mana messagepesan itu terkait dengan id yang Anda tulis. Jika pesan menyertakan subjek, satu karakter spasi dan subjek dimasukkan langsung setelah akhir pesan. Jika itu termasuk penerima, nama mereka, satu titik dua dan satu karakter spasi dimasukkan segera sebelum pesan.

Pada akhirnya, semua pemain yang hidup dijalankan untuk terakhir kalinya untuk melihat hasil pemungutan suara. Jika seorang pemain dipilih, ini ditulis:

The town has killed player_name!
They were a villager

... atau a mafioso, atau the cop, atau the doctor.

Jika tidak ada pemain yang dipilih, ini ditulis sebagai gantinya:

The town opted to lynch no one today.

Ketika controller mengirim pesan-pesan ini, ia mengabaikan respons dari pemain. Hari sudah berakhir.

Malam

Pada malam hari, semua orang kecuali penduduk desa bisa menggunakan kekuatan mereka.

Mafia:

Anda akan membaca It is night. Vote for a victim.. Ketika ini terjadi, keluarkan nama pemain yang ingin Anda bunuh.

Polisi:

Anda akan membaca It is night. Who would you like to investigate?. Ketika ini terjadi, keluarkan nama pemain yang ingin Anda periksa.

Dokter:

Anda akan membaca It is night. Who would you like to save?. Ketika ini terjadi, keluarkan nama pemain yang ingin Anda lindungi.

Setelah ini, hari berikutnya dimulai seperti biasa.

Anda dapat menyelamatkan diri hanya sekali per game.

Informasi Umum

  • Game tidak akan berjalan tanpa 6 pemain atau lebih.
  • Sepertiga pemain, dibulatkan ke bawah, akan menjadi mafia. Satu pemain akan menjadi dokter, dan satu pemain akan menjadi polisi. Semua pemain lain adalah penduduk desa.
  • Ikatan dalam pemungutan suara desa atau mafia semalam diselesaikan secara acak.
  • Nama bot harus + tanda hubung alfanumerik dan garis bawah.
  • Dilarang menggunakan pengetahuan kode lawan secara langsung. Secara teori, saya harus bisa menempatkan bot Anda melawan bot yang belum pernah Anda lihat sebelumnya dan membuatnya tampil sebanding.
  • Sayangnya, jika saya tidak bisa menjalankan program Anda menggunakan perangkat lunak bebas (seperti bir), saya harus membatalkannya.
  • Saya berhak untuk mendiskualifikasi pengajuan jika saya yakin itu berbahaya. Ini termasuk, tetapi tidak terbatas pada penggunaan waktu, memori, atau ruang untuk menjalankan yang berlebihan. Saya sengaja membiarkan batasnya lunak, tetapi ingat: Saya menjalankan ini di komputer rumah saya, bukan komputer super, dan saya tidak ingin mendapatkan hasil yang membutuhkan waktu satu tahun. Saya tidak berharap harus menggunakan ini, karena standar saya cukup rendah. Ini pada dasarnya "jika saya pikir Anda sengaja menjadi penipu", dan jika Anda bisa meyakinkan saya kalau tidak saya akan membalikkan keputusan saya.

Mencetak gol

Setiap putaran, 100 permainan akan dijalankan (ini dapat meningkat karena lebih banyak bot bergabung untuk menjaga ukuran sampel cukup besar, tetapi secara teori itu tidak akan mempengaruhi apa pun). Saya akan mencatat berapa kali setiap bot menang sebagai penduduk desa dibandingkan dengan berapa kali bot bermain sebagai penduduk desa, dan sama untuk mafia. Bot villager_ratioadalah number of games won as villager / number of games played as villager, dan mafia_ratiosama tetapi s/villager/mafia/g. Skor bot adalah (villager_ratio - mean villager_ratio) + (mafia_ratio - mean mafia_ratio).

Contoh bot

Randy the Robot bukanlah pemain mafia yang baik. Randy mengabaikan hampir semua hal, secara acak memilih apa yang akan dikatakan, siapa yang harus dipilih, dan siapa yang harus ditargetkan dengan kekuatan malam.

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

Pengendali

@undergroundmonorail menulis program kontrol untuk tantangan ini, tersedia di sini .

Anda memiliki satu bulan untuk kode dan menyerahkan jawaban, saya akan memberikan bot yang menang (pemecah dasi tingkat menang tertinggi adalah suara) setidaknya 50 reputasi hadiah (tergantung pada berapa banyak rep yang bisa saya dapatkan dalam sebulan)


Berikut ini skrip wrapper, dibuat oleh @Blacksilver, untuk digunakan dengan bahasa yang dikompilasi:

#!/bin/bash

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

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

Menempatkan ini dalam run.


Posting ini ditulis oleh @undergroundmonorail (saya membuat beberapa suntingan).

Dia memberikannya di sini kepada siapa saja yang ingin menyelesaikan dan mempostingnya.

Christopher
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Martin Ender

Jawaban:

3

Zulu

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

Tidak semua yang saya harapkan akan terjadi. Saya mungkin akhirnya mengubah-ubahnya sesekali.

Cara kerjanya v1.0

Catat nomor hari, siapa yang masih hidup, siapa yang mati, siapa mafia, siapa yang sejajar desa, peran, suara / pesan hari ini, dan suara / pesan keseluruhan.

  1. Malam

    Sebuah. Mafia - Pilih warga desa yang memilih mafia (secara acak) jika memungkinkan, jika tidak, warga desa acak.

    b. Cop - Selidiki siapa pun yang memiliki garis yang tidak diketahui.

    c. Dokter - Selamatkan diri, belok pertama, kemudian selamatkan polisi jika diketahui (saya rasa ini tidak akan pernah bisa diketahui sampai sekarang), selamatkan penduduk desa jika diketahui (mungkin juga tidak tahu ini), jika tidak selamatkan orang secara acak.

  2. Hari

    Sebuah. Jika ada yang mengucapkan pesan secara langsung kepada diri sendiri, balaslah (kemungkinan tanggapan terbatas).

    b. Mafia - Voting untuk penduduk desa yang memiliki suara terbanyak.

    c. Penduduk desa dengan mafia hidup yang selaras - dikenal memilih mafioso.

    d. Penduduk desa yang hanya diketahui mati selaras dengan Mafia - memilih bot acak yang tidak pernah memilih mafioso.

    e. Penduduk desa dengan Cop diketahui - memberikan suara untuk bot acak yang dipilih oleh polisi.

    f. Penduduk desa dengan desa yang diketahui sejajar - pilih bot acak yang memilih mati.

    g. Penduduk desa dengan suara menentang pemilihan sendiri untuk bot non-desa terpilih tertinggi saat ini.

Jo.
sumber
1
Tunggu, apa fungsinya?
SIGSTACKFAULT
1
Kenapa, itu memainkan mafia, tentu saja! :)
Jo.
Maksud saya strateginya.
SIGSTACKFAULT
6

Kode contoh tidak berfungsi untuk saya, saya menggunakan Python 3, jadi saya mengubah main.pyfile untuk membuatnya berfungsi.

Jadi di sini adalah versi tetap saya untuk Python 3, saya tidak pernah diprogram dalam Python sebelumnya jadi mungkin itu adalah kode yang mengerikan tetapi berfungsi :)

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

Beberapa hal yang saya pelajari ketika saya membuat karya ini (dan itu tidak jelas bagi saya dalam uraian)

  • printtidak melakukan apa pun dengan permainan itu seperti console.logdi js
  • input() memblokir program yang sedang berjalan itu bisa baik untuk langkah demi langkah debugging
  • from_serverdan to_serverdibersihkan setiap putaran.
  • Tidak mungkin menghentikan skrip dengan Ctrl+Ckombinasi, yang menjengkelkan.
Peter
sumber
Selamat datang di PPCG! Pos pertama yang bagus! Semoga kamu tetap disini! Saya telah mengedit posting Anda agar memiliki fungsi penyorotan sintaks, dan demi konsistensi menambahkan a run.sh.
Rɪᴋᴇʀ
1
Terima kasih! Saya tidak yakin < from_server > to_serverperlu karena saya nama file kode sulit dalam kode. mesin game hanya memanggil ./runtanpa pipa. begitu input()dan print()tidak bekerja dengan game. mayn.pybaris 57:os.system('./run')
Peter
2
Bagaimana Anda menjalankan pengontrol? Saya tidak bisa mengetahuinya. Bisakah Anda memberikan permohonan contoh?
Rɪᴋᴇʀ
Catatan: Dokumen asli randy.pyditulis dalam Python 2 , yang menyebabkan masalah.
SIGSTACKFAULT
untuk controller Anda perlu ./startdari folder asli atau Anda memerlukan versi python 3main.py
Peter
5

Ahli Logika

#!/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)

Fancy, banyak sekali kode python yang tidak akan saya jelaskan (walaupun bukan golf), selain itu ia menyimpan daftar "teman" dan "musuh" yang awalnya dihuni berdasarkan kesempatan dan / atau penyelidikan polisi . Peringatan: jangan berbaring di hadapan ahli logika.

pppery
sumber
adalah run.shstandar Anda (melakukan beberapa pengujian)
Stan Strum
Tidak, run.sh saya hanya bisa murni "run.py" tanpa pipa input dan output yang biasa, tetapi standar akan bekerja.
pppery
1
Ini terlihat sangat mirip dengan apa yang saya tulis, seandainya saya punya waktu dan kecenderungan.
Draco18s
Untuk beberapa alasan saya pikir ahli logika tidak akan melakukannya dengan baik di sekitar bot lain ... tidak ada bot lain yang melaporkan penyelidikan polisi
JavaScriptCoder
1
... dan saya menyadari, berbulan-bulan kemudian, bahwa jawaban saya salah mengasumsikan hanya ada satu polisi / dokter.
pppery
4

Survivalist (v 1.0)

Ringkasan

Survivalist hanya secara brutal selamat dari permainan dengan memarahi siapa pun yang berani menuduhnya, terlepas dari apakah dia mafia atau tidak.

Logika

Jika Anda bertahan hingga akhir pertandingan, Anda menang bagaimanapun caranya. Karena itu, Anda tetap bertahan dengan segala cara.

Cerita belakang

Pasukan berbaris melalui hutan yang gelap dan lembab.

"Letnan, di mana kita berbaris?" Rekrut muda itu rupanya tidak mengeraskan dirinya pada kekejaman, pikir komandan itu. Baiklah. Dia menjawab dengan kasar "untuk menghancurkan musuh".

Di desa, komandan musuh sedang minum-minum dan tertawa bersama dengan perwira lain di klub ketika seorang pengintai mengikuti berita. "Ada satu kolom, beberapa ratus meter panjangnya, berbaris di sepanjang hutan Yulin untuk kita! Rally pasukannya!"

Komandan musuh, jelas mabuk, berkata tiba-tiba, "Saya tidak punya laporan dari pengintai lain." Si pramuka (kemudian Survivalist) berpikir, maka aku harus mengumpulkan pasukan sendiri . Setelah menceritakan kisah itu kepada sesama pengintai, mereka kembali bersama, semua mengatakan bahwa mereka telah melihat pasukan musuh. Komandan masih tidak percaya, mengatakan, "Saya memerintahkan Anda untuk menghentikan kepramukaan. Tidak ada pasukan musuh".

Para pengintai memutuskan untuk mengambil senjata mereka untuk menyelamatkan komunitas. Mereka berhasil mencapai posisi mereka tepat ketika musuh tiba di desa dengan paksa. "BIAYA!" teriak komandan penyergapan. "BURN RUMAH! BURN RUMAH! BUNUH SEMUA ORANG, TERMASUK WANITA DAN ANAK-ANAK! "

Para pengintai menyelamatkan seluruh pasukan mereka. Mereka mengharapkan promosi, penghargaan, dan medali. Sebagai gantinya, mereka mendapat pengadilan militer yang dicurangi karena pemberontakan, hukuman, 10 tahun penjara, pemecatan tidak terhormat dari militer dan pengasingan.


Ada seorang penatua tua di dewan kota Salem, Massachusetts. Legenda mengatakan bahwa ia mendirikan kota. Ketika Anda bertemu dengannya di pondok terpencil di hutan, jangan biarkan binar di matanya membuat Anda berpikir dia damai. Jika Anda menuduhnya, dia akan menghancurkan Anda di depan kota.

Veteran itu tertawa dalam kegelapan. Takut akan gelap, tidak mungkin. Takut dengan monster di bawah tempat tidur? Pria itu dengan tangan di pelatuk pistol tertawa gugup. Dia tidak takut pada apa pun, katanya dalam hati. Tentu saja, dia adalah pahlawan waktu perang masa lalu, tetapi dia sudah terbiasa dengan penyergapan dan situasi yang mengancam kehidupan sehingga itu membuat pria itu hanya neurotik. Jari pemicunya bergerak-gerak di bayangan sederhana; detak jantungnya bertambah cepat dengan setiap suara kecil. Ya, dia takut akan kematian ini. Bagaimana tidak, melihat begitu banyak orang mati dengan cara yang mengerikan? Yang dia tahu dari penculikan dan secara ajaib melarikan diri dari musuhnya adalah bahwa tidak ada belas kasihan.

Veteran


Kode (Saya pemula dengan python, tidak yakin apakah kodenya bagus)

#!/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
JavaScriptCoder
sumber
Apakah maksud Anda oralih-alih ||? Apakah Anda mengujinya? Juga, Anda mungkin harus menunjukkan bahwa itu adalah Python 2.
Solomon Ucko
3

Avatar

Avatar "secara acak" memilih satu pemain di awal dan tanpa henti memfokuskan mereka untuk sisa putaran.

Ini bukan referensi ke acara TV animasi yang bernama serupa.

Ini adalah referensi online EVE.

Unduh tar semua file yang diperlukan

Changelog

  • Ulang Tahun v1
  • v2 Tidak mencatat apa pun stdout, hanya untuk stderr.
    Untuk menekan stderrjuga, tambahkan 2>/dev/nullke akhir runfile.
/*  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);
    }
}

Ini membutuhkan mafia.cdan mafia.h, perpustakaan yang saya tulis, di direktori yang sama.

Ini termasuk dalam unduhan, bersama dengan Makefile dan skrip run.

MELAKUKAN

  • Berhenti memilih terhadap target ketika mereka terbunuh atau digantung.

Sementara saya di sini, saya akan mengirimkan non-bot, Steve:

SIGSTACKFAULT
sumber
FYI, saya sebut dibs pada avatar, erebus, leviathan, danragnarok
SIGSTACKFAULT
"Ini bukan referensi ke acara TV animasi dengan nama yang sama." apakah ini referensi ke film?
Stan Strum
@StanStrum tidak, Tidak.
SIGSTACKFAULT
from_serverFile bot saya tidak sedang ditulis. Apakah Anda harus menetapkan izin khusus atau sesuatu?
R
1
Catatan untuk yang penasaran: Kitab Suci yang dirujuk di sini adalah milik Amarr dari EVE Online. Ada adalah sebuah Wahyu 2:12 dalam Alkitab, tetapi membaca agak berbeda.
DLosc
2

Raksasa

Leviathan mengulangi semua pemain dalam playersfile dan menargetkan mereka satu per satu.

Unduh

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

Seperti halnya Avatar, itu membutuhkan mafia.cdan mafia.hdi direktori yang sama.

Ini termasuk dalam unduhan, bersama dengan Makefile dan skrip run.

SIGSTACKFAULT
sumber
:) menambahkan survivalist setelah saya selesai dengannya
JavaScriptCoder