Jouons à la mafia!

42

Mafia (également connu sous le nom de loup-garou) est un jeu de société qui se joue à peu près comme ceci:

  • Le jeu commence le jour 0. Après chaque jour nvient une nuit n. Après chaque nuit nvient un jour n+1. c'est à dire D0, N0, D1, N1, D2, N2...
  • À l'aube du jour 0, un hôte choisit secrètement des joueurs pour remplir certains rôles:  
    • Un certain nombre de joueurs deviennent la mafia. Chaque nuit, chaque mafieux choisit un joueur. À l'aube du lendemain, le joueur choisi par le plus grand nombre de mafieux est tué. Ils sont définitivement retirés du jeu et leur rôle est révélé publiquement. Mafia-aligné.  
    • Un certain nombre de joueurs deviennent des flics. Chaque soir, chaque flic choisit un joueur. À l'aube du lendemain, le policier prend conscience de l'alignement de ses joueurs. Aligné au village.  
    • Un certain nombre de joueurs deviennent des médecins. Chaque nuit, chaque médecin choisit un joueur. Si ce joueur est le même joueur que la mafia a choisi de tuer, les actions de la mafia pour cette nuit sont annulées. Aligné au village.  
    • Tous les joueurs qui ne sont pas choisis pour un autre rôle sont des villageois. Les villageois n'ont aucune capacité qui ne soit partagée par toute la ville. Aligné au village.
  • Tous les jours sauf le jour 0, toute la ville (c'est-à-dire tous les joueurs vivants) vote pour un joueur. À la fin de la journée, ce joueur est retiré du jeu et son rôle est révélé. (Au jour 0, tout le monde frissonne jusqu'à la nuit.)
  • Si, à un moment quelconque, il ne reste aucun mafieux, le jeu se termine par la victoire de tous les joueurs alignés au village (y compris les morts).
  • Si, à un moment quelconque, les joueurs alignés au village ne sont pas plus nombreux que les joueurs alignés à la mafia, le jeu se termine par la victoire de tous les joueurs alignés à la mafia (y compris les morts).

Pour ce défi, votre objectif est d'écrire un bot pour battre d'autres robots à la Mafia!

Comment faire un bot de travail

Tout ce que vous avez à me fournir est un fichier appelé run. Dans la structure de répertoires où se déroulera ce défi, votre bot vivra ici:

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/

Le runfichier, une fois exécuté, fera en sorte que votre bot fasse son travail. Il est important de noter que ce fichier ne doit nécessiter aucun argument de ligne de commande ou quoi que ce soit. Il sera exécuté exactement comme ./run. Si vous devez être exécuté différemment, vous devrez contourner le problème en procédant comme suit:

real_bot.py

#!/bin/python2

# code goes here

run

#!/bin/bash

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

Une chose importante à noter est que toutes les entrées que votre bot reçoit seront trouvées dans le fichier from_serveret le programme de contrôle cherchera la sortie de votre bot dans to_server. J'ai choisi de le faire de cette manière pour que toute langue capable de gérer des fichiers puisse participer. Si votre langue facilite l'utilisation de stdin et de stdout par rapport aux E / S de fichier, vous pouvez écrire un runfichier qui ressemble à ceci:

#!/bin/bash

./real_bot.py < from_server > to_server

Cela fera en sorte que stdin provienne du from_serverfichier et que stdout ira directement à to_server.

Votre bot ne fonctionnera pas pendant la durée de la partie. Au lieu de cela, il sera exécuté lorsqu'il devra prendre une décision. De même, il ne sera pas informé quand il sera mort, il ne sera plus exécuté. Planifiez cela en enregistrant tout ce que vous voulez rappeler dans un fichier et en le lisant plus tard. Vous pouvez créer, écrire ou lire à partir de n’importe quel fichier du dossier de votre bot, mais vous ne pouvez pas écrire ou lire ailleurs que dans ce dossier, y compris un accès réseau ou autre . Si votre bot sait quoi que ce soit qui ne l'a pas été dit à l'intérieur du dossier, ou s'il touche tout ce qui ne se trouve pas à l'intérieur de ce dossier, votre bot est disqualifié.

Comment faire un bot fonctionnel

journée

Au début du jeu, le fichier playerssera rempli avec une liste délimitée par des lignes et contenant tous les joueurs du jeu. Il ne sera pas mis à jour lorsque les joueurs quitteront la partie.

À l'aube du jour 0, tous les joueurs trouveront ce message dans leur from_serverdossier:

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

Si vous êtes le flic, la ligne You are the copest ajoutée à la fin. Le docteur voit You are the doctor. La mafia voit You are a member of the mafia.\nYour allies are:une liste de membres de la mafia délimitée par une nouvelle ligne, à l'exclusion du lecteur qui lit le message.

À l'aube de tous les autres jours, ce message apparaîtra:

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`

dayNumberest remplacé par le numéro du jour. victimest remplacé par le nom de la victime de la nuit dernière et victim_rolefait partie de:

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

cop_targetest le nom du joueur sur lequel le flic a enquêté la nuit dernière, et target_alignmentest l'un villageou l' autre mafia. Enfin, remaining_playersest une liste de joueurs qui sont encore en vie dans ce format:player1, player2, player3

La deuxième ligne est omise s'il n'y a pas eu de tueries hier soir, et la troisième ligne n'est montrée qu'au flic.

Par exemple,

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

Une fois que ce message est passé, la journée commence! Chaque bot peut effectuer 50 actions tout au long de la journée, lorsqu'une "action" consiste à voter pour un joueur ou à dire quelque chose à haute voix.

Pour voter pour un joueur, écrivez vote player_namedans votre to_serverfichier et terminez. Pour voter pour ne tuer personne, écrivez vote no one. Lorsque vous voterez, tous les joueurs (y compris vous) verront your_bot votes to kill your_selection. Les votes sont ignorés au jour 0.

Un certain nombre de messages prédéfinis peuvent être envoyés à tous les joueurs. L'identifiant de chaque message possible est répertorié ici:

 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?

Tous ces messages, à l’exception des cinq premiers, font référence à un joueur spécifique. Pour dire un de ces messages, écrivez say message_id player_name. Pour l’un des cinq premiers messages, écrivez simplement say message_id. Vous pouvez ajouter un troisième argument facultatif aux deux, en spécifiant le nom du joueur avec lequel vous parlez (tous les joueurs peuvent toujours le lire, mais ils sauront qui est le destinataire souhaité).

Lorsque votre bot dit un message, tous les joueurs lisent your_bot says "message", où se messagetrouve le message associé à l'identifiant que vous avez écrit. Si le message comprend un objet, un espace et l'objet sont insérés directement après la fin du message. S'il comprend un destinataire, son nom, un caractère deux-points et un espace sont insérés immédiatement avant le message.

À la fin de la journée, tous les joueurs en vie sont exécutés une dernière fois pour voir le résultat du vote. Si un joueur a été éliminé, ceci est écrit:

The town has killed player_name!
They were a villager

... ou a mafioso, ou the cop, ou the doctor.

Si aucun joueur n'a été éliminé, ceci est écrit à la place:

The town opted to lynch no one today.

Lorsque le contrôleur envoie ces messages, il ignore toutes les réponses des joueurs. La journée est finie.

Nuit

La nuit, tout le monde sauf les villageois utilise son pouvoir.

Mafia:

Vous lirez It is night. Vote for a victim.. Lorsque cela se produit, indiquez le nom du joueur que vous souhaitez tuer.

Flic:

Vous lirez It is night. Who would you like to investigate?. Lorsque cela se produit, indiquez le nom du lecteur que vous souhaitez vérifier.

Médecin:

Vous lirez It is night. Who would you like to save?. Lorsque cela se produit, indiquez le nom du lecteur que vous souhaitez protéger.

Après cela, le jour suivant commence normalement.

Vous ne pouvez vous sauver qu'une fois par match.

Informations générales

  • Le jeu ne fonctionnera pas sans 6 joueurs ou plus.
  • Un tiers des joueurs, arrondis à la baisse, seront des mafieux. Un joueur sera un médecin et un joueur sera un flic. Tous les autres joueurs sont des villageois.
  • Les liens dans le vote du village ou le vote de la mafia au jour le jour sont réglés au hasard.
  • Les noms de bot doivent être alphanumériques + tirets et traits de soulignement.
  • Il est interdit d'utiliser directement la connaissance du code de l'adversaire. En théorie, je devrais être capable de mettre votre bot contre des bots que vous n'avez jamais vus et de le faire fonctionner de manière comparable.
  • Malheureusement, si je ne parviens pas à faire fonctionner votre programme avec un logiciel exclusivement gratuit (comme dans Beer), je devrai le disqualifier.
  • Je me réserve le droit de disqualifier toute soumission si je la considère comme malveillante. Cela inclut, sans toutefois s'y limiter, l'utilisation excessive de temps, de mémoire ou d'espace pour s'exécuter. J'ai volontairement laissé la limite souple, mais rappelez-vous: j'utilise ce logiciel sur mon ordinateur personnel, pas sur un superordinateur, et je ne veux pas que les résultats prennent un an. Je ne m'attends pas à devoir utiliser ceci, car mes normes sont assez basses. Ceci est fondamentalement "si je pense que vous êtes une bite à dessein", et si vous pouvez me convaincre du contraire, je reviendrai sur ma décision.

Notation

À chaque tour, 100 parties seront jouées (ceci peut augmenter si davantage de bots se joignent pour que l'échantillon soit suffisamment grand, mais en théorie cela n'affectera rien). Je vais enregistrer le nombre de fois où chaque bot gagne en tant que villageois par rapport au nombre de fois où il joue en tant que villageois, et le même pour la mafia. Un bot villager_ratioest number of games won as villager / number of games played as villager, et mafia_ratioest le même mais s/villager/mafia/g. Le score d'un bot est (villager_ratio - mean villager_ratio) + (mafia_ratio - mean mafia_ratio).

Exemple bot

Randy the Robot n'est pas un bon joueur de la mafia. Randy ignore pratiquement tout, choisissant au hasard quoi dire, pour qui voter et pour qui cibler avec des pouvoirs nocturnes.

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

Manette

@undergroundmonorail a écrit un programme de contrôle pour ce défi, disponible ici .

Vous avez un mois pour coder et donner des réponses, je donnerai au bot gagnant (le nombre de votes ayant le plus fort taux de victoire) au moins 50 primes de réputation (en fonction du nombre de représentants que je peux gagner en un mois)


Voici un script de wrapper, créé par @Blacksilver, à utiliser avec les langages compilés:

#!/bin/bash

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

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

Mettez ceci dans run.


Cet article a été écrit par @undergroundmonorail (j'ai apporté quelques modifications).

Il l'a donné ici à quiconque voulait finir et l'afficher.

Christopher
la source
Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacée pour discuter .
Martin Ender

Réponses:

3

zoulou

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

Pas tout ce que j'espérais. Je peux finir par le peaufiner de temps en temps.

Comment ça marche v1.0

Garde le numéro du jour, qui est en vie, qui est mort, qui est mafieux, qui est aligné avec le village, les rôles, les votes / messages du jour en cours et les votes / messages globaux.

  1. Nuit

    une. Mafia - Votez pour tout villageois qui a voté contre la mafia (au hasard) si possible, sinon un villageois au hasard.

    b. Cop - Enquêter sur toute personne d'alignement inconnu.

    c. Docteur - Sauvez le premier tour, puis sauvez le flic s'il est connu (je ne pense pas qu'il puisse le savoir à ce jour), sauvez le villageois s'il est connu (probablement ne le sait pas non plus), sinon sauvez une personne au hasard.

  2. journée

    une. Si quelqu'un a parlé directement à un message, répondez-y (réponses limitées possibles).

    b. Mafia - Votez pour le villageois qui a le plus de votes.

    c. Villageois avec une personne connue alignée sur la mafia vivante - votez pour mafioso.

    ré. Villageois dont la seule morte est connue - votez pour un robot aléatoire qui n'a jamais voté pour le mafieux.

    e. Villageois avec flic connu - votez pour un bot aléatoire pour lequel le flic a voté.

    F. Villageois avec des morts alignés sur des villages connus - votez pour un bot aléatoire qui a voté pour les morts.

    g. Villageois avec voix contre - vote pour le plus haut bot actuellement aligné, non voté.

Jo.
la source
1
Attends, qu'est-ce que ça fait?
SIGSTACKFAULT le
1
Pourquoi, il joue la mafia, bien sûr! :)
Jo.
Je veux dire la stratégie.
SIGSTACKFAULT le
6

L'exemple de code ne fonctionnant pas pour moi, j'utilise Python 3 et j'ai donc modifié le main.pyfichier pour le faire fonctionner.

Voici donc ma version corrigée pour Python 3, je n’avais jamais programmé en Python, alors c’est peut-être un code horrible mais ça marche :)

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

Quelques choses que j'ai apprises en faisant ce travail (et ce n'était pas clair pour moi dans la description)

  • printne fait rien avec le jeu c'est comme un console.logjs
  • input() bloque le programme en cours d'exécution, il peut être bon pour le débogage étape par étape
  • from_serveret to_serverest effacé à chaque tour.
  • Il est impossible d'arrêter le script avec une Ctrl+Ccombinaison, ce qui est ennuyeux.
Peter
la source
Bienvenue chez PPCG! Excellent premier post! J'espère que vous restez! J'ai modifié votre message pour que la syntaxe soit soulignée et que, par souci de cohérence, nous y ajoutions un run.sh.
Rɪᴋᴇʀ
1
Merci! Je ne suis pas sûr que ce < from_server > to_serversoit nécessaire car j'ai codé en dur les noms de fichiers dans le code. le moteur de jeu appelle simplement ./runsans tuyaux. donc input()et print()ne fonctionne pas avec le jeu. mayn.pyligne 57:os.system('./run')
Peter
2
Comment avez-vous eu le contrôleur à courir? Je ne peux pas comprendre. Pouvez-vous fournir un exemple d'invocation?
Rɪᴋᴇʀ
Remarque: L'original a randy.pyété écrit en Python 2 , ce qui a causé les problèmes.
SIGSTACKFAULT
pour le contrôleur, vous devez utiliser ./startle dossier d'origine ou vous avez besoin d'une version python 3 dumain.py
Peter
5

Le logicien

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

Fantaisie, longue bande de code python que je ne vais pas expliquer (bien que ce ne soit pas joué au golf), à part le fait qu'il conserve des listes "d'amis" et d '"ennemis" qui sont initialement peuplés sur la base d'une enquête du hasard et / ou du flic. . Attention: ne mentez pas en présence du logicien.

poivré
la source
est votre run.shstandard (faire des tests)
Stan Strum
Non, mon run.sh pourrait simplement être "run.py" sans les tuyaux d'entrée et de sortie habituels, mais la norme fonctionnerait.
pppery
1
Cela ressemble beaucoup à ce que j'aurais écrit si j'avais le temps et l'envie.
Draco18s
Pour une raison quelconque, je pense que le logicien ne fera pas si bien autour des autres bots ... aucun des autres bots ne rapporte une enquête de flic
JavaScriptCoder
1
... et je réalise, des mois plus tard, que ma réponse suppose à tort qu'il ne peut y avoir qu'un seul policier / médecin.
pppery
4

Survivaliste (v 1.0)

Synopsis

Le survivant survit simplement brutalement au jeu en réprimandant tous ceux qui osent l’accuser, qu’il soit mafieux ou non.

Logique

Si vous survivez jusqu'à la fin du jeu, vous gagnez quoi qu'il arrive. Par conséquent, vous survivez à tout prix.

Histoire

Les troupes ont marché à travers la forêt sombre et humide.

"Lieutenant, où marchons-nous?" La jeune recrue ne s’est apparemment pas endurcie aux atrocités, pensa le commandant. Tant pis. Il répondit par un brusque "pour détruire l'ennemi".

Au village, le commandant ennemi buvait et riait avec les autres officiers du club lorsqu'un éclaireur se précipita pour annoncer la nouvelle. "Il y a une colonne de plusieurs centaines de mètres qui défile pour nous dans la forêt de Yulin! Rassemblez les troupes!"

Le commandant de l'ennemi, manifestement en état d'ébriété, dit de façon inattendue: "Je n'ai reçu aucun rapport d'autres éclaireurs." L'éclaireur (futur survivant) pensa, alors je devrai rassembler les troupes moi-même . Après avoir raconté l’histoire aux autres éclaireurs, ils sont revenus ensemble en disant qu’ils avaient vu des troupes ennemies. Le commandant n'a toujours pas cru en disant: "Je vous ordonne de cesser le dépistage. Il n'y a pas de troupes ennemies".

Les éclaireurs ont décidé de prendre leurs armes pour sauver la communauté. Ils ont réussi à atteindre leurs positions au moment où l'ennemi est arrivé en force dans le village. "CHARGE!" cria le commandant de l'embuscade. "Brûlez les maisons! Brûlez les maisons! Tuez tout le monde, y compris les femmes et les enfants! "

Les éclaireurs ont sauvé toute leur armée. Ils attendaient des promotions, des récompenses et des médailles. Au lieu de cela, ils ont obtenu une cour martiale truquée pour mutinerie, condamnation, 10 ans de prison, destitution déshonorante de l'armée et exil.


Il y a un ancien âgé au conseil municipal de Salem, dans le Massachusetts. La légende raconte qu'il a fondé la ville. Lorsque vous le rencontrez dans son chalet isolé dans la forêt, ne laissez pas le scintillement de ses yeux vous faire croire qu'il est en paix. Si vous l'accusez, il vous perdra devant la ville.

Le vétéran a ri dans l'obscurité. Peur du noir, pas moyen. Peur des monstres sous le lit? L'homme avec sa main sur la gâchette d'une arme à feu rit nerveusement. Il n'avait peur de rien, se disait-il. Bien sûr, il était un héros du passé, mais il était tellement habitué aux embuscades et aux situations mettant sa vie en danger que cela rendait l'homme simplement névrotique. Son doigt de détente tressauta à de simples ombres; ses battements de coeur s'accéléraient avec chaque petit son. Oui, il avait cette peur de la mort. Comment pourrait-il ne pas voir autant de personnes mourir de façon horrible? Tout ce qu'il savait, après avoir été kidnappé et avoir échappé miraculeusement à ses ennemis, c'était qu'il n'y avait pas de pitié.

Vétéran


Code (je suis un débutant en python, je ne sais pas si le code est bon)

#!/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
la source
Vouliez-vous dire orau lieu de ||? L'avez-vous testé? En outre, vous devriez probablement indiquer qu'il s'agit de Python 2.
Solomon Ucko
3

Avatar

Avatar "aléatoirement" choisit un joueur au début et le concentre sans relâche pour le reste du tour.

Ce n'est pas une référence à une émission de télévision animée portant le même nom.

C'est une référence EVE en ligne.

Télécharger le tar de tous les fichiers requis

Changelog

  • v1 anniversaire
  • v2 Ne connecte rien à stdout, seulement à stderr.
    Pour supprimer stderraussi, ajoutez 2>/dev/nullà la fin du runfichier.
/*  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);
    }
}

Cela nécessite mafia.cet mafia.h, bibliothèques que j'ai écrites, dans le même répertoire.

Ceux-ci sont inclus dans le téléchargement, avec un Makefile et un script d'exécution.

FAIRE

  • Arrêtez de voter contre la cible quand ils sont tués ou lynchés.

Pendant que je suis ici, je vais soumettre le non-bot, Steve:

SIGSTACKFAULT
la source
Pour votre information, je l' appelle dibs avatar, erebus, leviathanetragnarok
SIGSTACKFAULT
"Ce n'est pas une référence à une émission de télévision animée portant le même nom." est-ce une référence au film?
Stan Strum
@StanStrum non, ce n'est pas.
SIGSTACKFAULT
Le from_serverfichier de mon bot n'est pas en cours d'écriture. Avez-vous eu à définir des autorisations spécifiques ou quelque chose?
Rɪᴋᴇʀ
1
Remarque pour les curieux: les Écritures citées ici sont celles du Amarr d’EVE Online. Il y a une révélation 2:12 dans la Bible, mais elle lit plutôt différemment.
DLosc
2

Léviathan

Leviathan parcourt tous les lecteurs du playersfichier et les cible un par un.

Télécharger

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

Comme avec Avatar, il nécessite mafia.cet mafia.hdans le même répertoire.

Ceux-ci sont inclus dans le téléchargement, avec un Makefile et un script d'exécution.

SIGSTACKFAULT
la source
:) ajout de survivaliste une fois que j'ai terminé
JavaScriptCoder