狼人杀的理论胜率是多少?

关注者
21
被浏览
100,780

17 个回答

我一定是太闲,花了两天时间来写这个答案

为了写这个答案 我用python写了一堆人工智障来玩狼人杀这个游戏。

这些智障一般都能把游戏玩到6-8天。。

然后以上帝视角输出结果,体验一把当GM的感觉。

看看他们怎么玩的

这程序没有写预言家验人,发言环节,因为这块太复杂了脑细胞有限

验人和发言环节,自动概率计算生成抗推位,原谅我太菜

以下是程序输出结果,不想看可以忽略

**************************第第 1 天夜晚开始,天黑请闭眼**************************
守卫请睁眼,请选择你要守护的玩家
守卫选择自守
狼人请睁眼,你要杀谁
狼队杀死了 村民1
女巫毒死 预言家
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人3', '狼人4'] ['女巫', '猎人', '守卫'] ['村民2', '村民3', '村民4']
**************************第 1 天白天开始,天亮请睁眼**************************
----------------第一天开始竞选警长----------------
狼人2 上警
预言家 上警
狼人1 上警
村民1 上警
村民3 上警
女巫 上警
警下玩家 ['狼人3', '狼人4', '村民2', '村民4', '猎人', '守卫']
狼人3 把票投给了 狼人2
狼人4 把票投给了预言家
村民2 把票投给了预言家
村民4 把票投给了 狼人2
猎人 把票投给了预言家
守卫 弃票
预言家 票数: 3
狼人2 票数: 2
经过一波激烈的分析讨论, 预言家 获得警长
----------------竞选警长结束----------------
接下来开始各位的表演
经过激烈的讨(si)论(bi)
['村民4', '猎人'] 进入抗推位
----------------开始公投----------------
狼人1 投票给 狼人2
狼人2 投票给 狼人2
狼人3 投票给 村民4
狼人3 投票给 猎人
狼人4 投票给 村民4
狼人4 投票给 猎人
村民2 投票给 村民4
村民3 投票给 村民4
村民4 投票给 狼人2
女巫 投票给 村民4
猎人 投票给 猎人
守卫 投票给 猎人
最终投票结果 {'狼人2': 3, '村民4': 5, '猎人': 4}
村民4 以 5 票被公投出局
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人3', '狼人4'] ['女巫', '猎人', '守卫'] ['村民2', '村民3']
**************************第第 2 天夜晚开始,天黑请闭眼**************************
守卫请睁眼,请选择你要守护的玩家
守卫守护了 狼人4
狼人请睁眼,你要杀谁
狼队杀死了 猎人
猎人没有开枪
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人3', '狼人4'] ['女巫', '守卫'] ['村民2', '村民3']
**************************第 2 天白天开始,天亮请睁眼**************************
接下来开始各位的表演
经过激烈的讨(si)论(bi)
['狼人3'] 进入抗推位
----------------开始公投----------------
狼人1 弃票
狼人2 投票给 狼人3
狼人3 投票给 狼人3
狼人4 投票给 狼人3
村民2 投票给 狼人2
村民3 投票给 村民2
女巫 投票给 狼人3
守卫 投票给 狼人2
最终投票结果 {'狼人3': 4, '狼人2': 2, '村民2': 1}
狼人3 以 4 票被公投出局
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人4'] ['女巫', '守卫'] ['村民2', '村民3']
**************************第第 3 天夜晚开始,天黑请闭眼**************************
守卫请睁眼,请选择你要守护的玩家
守卫选择自守
狼人请睁眼,你要杀谁
狼队选择刀 女巫 被女巫救起
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人4'] ['女巫', '守卫'] ['村民2', '村民3']
**************************第 3 天白天开始,天亮请睁眼**************************
接下来开始各位的表演
经过激烈的讨(si)论(bi)
['女巫'] 进入抗推位
----------------开始公投----------------
狼人1 投票给 狼人2
狼人2 弃票
狼人4 投票给 女巫
村民2 投票给 女巫
村民3 投票给 女巫
女巫 投票给 狼人2
守卫 投票给 女巫
最终投票结果 {'狼人2': 2, '女巫': 4}
女巫 以 4 票被公投出局
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人4'] ['守卫'] ['村民2', '村民3']
**************************第第 4 天夜晚开始,天黑请闭眼**************************
守卫请睁眼,请选择你要守护的玩家
守卫守护了 村民3
狼人请睁眼,你要杀谁
狼队杀死了 村民2
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人4'] ['守卫'] ['村民2', '村民3']
**************************第 4 天白天开始,天亮请睁眼**************************
接下来开始各位的表演
经过激烈的讨(si)论(bi)
['村民2'] 进入抗推位
----------------开始公投----------------
狼人1 投票给 狼人2
狼人2 投票给 村民2
狼人4 弃票
村民2 投票给 村民2
村民3 投票给 村民2
守卫 投票给 狼人2
最终投票结果 {'狼人2': 2, '村民2': 3}
村民2 以 3 票被公投出局
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人4'] ['守卫'] ['村民3']
**************************第第 5 天夜晚开始,天黑请闭眼**************************
守卫请睁眼,请选择你要守护的玩家
守卫守护了 狼人4
狼人请睁眼,你要杀谁
狼队杀死了 村民3
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2', '狼人4'] ['守卫'] ['村民3']
**************************第 5 天白天开始,天亮请睁眼**************************
接下来开始各位的表演
经过激烈的讨(si)论(bi)
['狼人4'] 进入抗推位
----------------开始公投----------------
狼人1 投票给 狼人4
狼人2 投票给 狼人4
狼人4 投票给 狼人2
村民3 弃票
守卫 投票给 狼人4
最终投票结果 {'狼人4': 3, '狼人2': 1}
狼人4 以 3 票被公投出局
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2'] ['守卫'] ['村民3']
**************************第第 6 天夜晚开始,天黑请闭眼**************************
守卫请睁眼,请选择你要守护的玩家
守卫守护了 狼人1
狼人请睁眼,你要杀谁
狼队杀死了 守卫
未决出胜负,继续游戏
当前存活玩家 ['狼人1', '狼人2'] ['守卫'] ['村民3']
**************************第 6 天白天开始,天亮请睁眼**************************
接下来开始各位的表演
经过激烈的讨(si)论(bi)
['狼人1', '守卫'] 进入抗推位
----------------开始公投----------------
狼人1 弃票
狼人2 弃票
村民3 投票给 守卫
守卫 投票给 狼人1
最终投票结果 {'守卫': 1, '狼人1': 1}
守卫 以 1 票被公投出局
狼人获胜,最后存活玩家 ['狼人1', '狼人2', '村民3']


主要几个函数

竞选警长

def jingxuanjingzhang(): #竞选警长
    global hantiaolang
    jinghui = 0 #初始化警徽
    jingxia_player=["狼人1","狼人2","狼人3","狼人4","村民1","村民2","村民3","村民4","女巫","猎人","预言家","守卫"] #玩家
    hantiaolang = random.choice(player_lang) #默认有一匹悍跳狼
    jingxia_player.remove(hantiaolang) #默认悍跳狼上警
    print(hantiaolang,"上警")
    jingxia_player.remove("预言家") #默认预言家上警
    print("预言家", "上警")
    zhunbshangjing_jingxia_player=jingxia_player
    #print(zhunbshangjing_jingxia_player)
    for player in zhunbshangjing_jingxia_player:
        if "狼人" in player:
            if random.uniform(0, 1) < 0.5: #剩下的狼人上警概率50%
                jingxia_player.remove(player)
                print(player, "上警")
        elif "村民" in player:
            if random.uniform(0, 1) < 0.4:#村民上警概率40%
                jingxia_player.remove(player)
                print(player, "上警")
        else:
            if random.uniform(0, 1) < 0.6:#神上警概率60%
                print(player, "上警")
                jingxia_player.remove(player)
    print("警下玩家",jingxia_player)
    预言家_piaoshu=0 #初始化悍跳狼票数
    hantiaolang_piaoshu=0 #初始化预言家票数
    for player in jingxia_player:
        if "狼人" in player:
            if random.uniform(0, 1) > 0.1: #狼人弃票概率20%
                if random.uniform(0, 1) < 0.3:#狼人倒钩概率30%
                    预言家_piaoshu+=1
                    print(player,"把票投给了预言家")
                else:
                    hantiaolang_piaoshu+=1
                    print(player, "把票投给了",hantiaolang)
            else:
                print(player, "弃票")
        elif "村民" in player:
            if random.uniform(0, 1) > 0.1:#村民弃票概率10%
                if random.uniform(0, 1) < 0.55:#村民投对概率60%
                    预言家_piaoshu += 1
                    print(player, "把票投给了预言家")
                else:
                    hantiaolang_piaoshu += 1
                    print(player, "把票投给了", hantiaolang)
            else:
                print(player, "弃票")
        else:
            if random.uniform(0, 1) > 0.1:#神弃票概率10%
                if random.uniform(0, 1) < 0.65:#神投对概率65%
                    预言家_piaoshu += 1
                    print(player, "把票投给了预言家")
                else:
                    hantiaolang_piaoshu += 1
                    print(player, "把票投给了", hantiaolang)
            else:
                print(player, "弃票")
    print("预言家 票数:",预言家_piaoshu)
    print(hantiaolang, "票数:", hantiaolang_piaoshu)
    if 预言家_piaoshu>hantiaolang_piaoshu:
        return "预言家"
    elif 预言家_piaoshu<hantiaolang_piaoshu:
        return hantiaolang
    else: #这里就不重新投票了,直接按之前的票数加权算吧,懒得写了。
        #算法是第一轮获得票数除以总票数作为获胜概率,如果双方都拿到警徽或者都没拿到警徽,那么就撕警徽
        #根据以上概率,进行10多万次的计算 预言家拿警徽的概率是51.4% 焊跳狼44.5% 撕警徽的概率是4.1% 可能跟实际有点差异
        if random.uniform(0, 1) < 预言家_piaoshu/(预言家_piaoshu+hantiaolang_piaoshu):
            jinghui="预言家"
        if random.uniform(0, 1) < hantiaolang_piaoshu / (预言家_piaoshu + hantiaolang_piaoshu):
            if jinghui==0:
                jinghui =hantiaolang
    return jinghui

投票

def toupiao(jinghui): #公投
    # 找抗推位
    global hantiaolang,piaoshu #引用全局变量 焊跳狼,警徽和计票字典。
    kangtuiwei=[] #初始化抗推位
    while 1:
        if len(kangtuiwei)==1 or len(kangtuiwei)==2: #抗推位只能有1个或两个
            break
        else:
            kangtuiwei = []# 重新初始化抗推位
            for lang in player_lang:
                if random.uniform(0, 1) < 0.2:  # 狼人进抗推位的概率20%
                    if lang != hantiaolang: #焊跳狼不进抗推位,单独计算
                        kangtuiwei.append(lang)
            for min in player_min:
                if random.uniform(0, 1) < 0.15:  # 村民进抗推位的概率15%
                    kangtuiwei.append(min)
            for shen in player_shen:
                if random.uniform(0, 1) < 0.10: # 神职进抗推位的概率15%
                    if shen != "预言家":  # 预言家不进抗推位,单独计算
                        kangtuiwei.append(shen)
    print(kangtuiwei,"进入抗推位")
    print("----------------开始公投----------------")
    toupiao_player_list = player_lang + player_min + player_shen
    piaoshu={} #初始化计票字典
    #print(toupiao_player_list)
    if "预言家" in player_shen and hantiaolang in player_lang: #如果焊跳狼和预言家存活
        toupiao_player_list.remove(hantiaolang)
        toupiao_player_list.remove("预言家")
        #kangtuiwei.append(hantiaolang)
        #kangtuiwei.append("预言家")
        #piaoshu = {"预言家":1,hantiaolang:1}  #默认双方互投
        toupiaodongzuo("预言家", hantiaolang)
        toupiaodongzuo(hantiaolang,"预言家")
        if jinghui=="预言家":
            piaoshu[hantiaolang]+=0.5 #如果预言家拿警徽,狼人1.5票,预言家1票
        elif jinghui==hantiaolang:
            piaoshu["预言家"]+=0.5 #如果焊跳狼拿警徽,狼人11票,预言家1.5票
        else:
            pass # 如果没有警徽双方各一票,保持不变,ps:这步其实没必要写,但是为了让大家能看懂还是写了
    for toupiao_player in toupiao_player_list: #其余人投票
        if toupiao_player in player_lang: #狼人投票
            if random.uniform(0, 1) > 0.2: #狼人弃票概率20%
                if random.uniform(0, 1) < 0.4: #倒钩概率
                    for i in kangtuiwei:
                        if "狼人" in kangtuiwei: #如果抗推位有狼队友
                            if hantiaolang in player_lang: #如果焊跳狼存活
                                if random.uniform(0, 1) > 0.6:  # 投焊跳狼概率60% 投狼队友的概率40%
                                    toupiaodongzuo(toupiao_player,i)
                                else:
                                    toupiaodongzuo(toupiao_player, hantiaolang)
                                break
                            else:
                                toupiaodongzuo(toupiao_player, i)
                                break
                        elif hantiaolang in player_lang:
                            toupiaodongzuo(toupiao_player, hantiaolang)
                            break
                else:
                    for i in kangtuiwei:
                        if "狼人" not in kangtuiwei:  # 如果抗推位有狼队友
                            if "预言家" in player_shen:  # 如果预言家存活
                                if random.uniform(0, 1) > 0.7:  # 投预言家概率70% 投别人的概率30%
                                    toupiaodongzuo(toupiao_player, i)
                                else:
                                    toupiaodongzuo(toupiao_player, "预言家")
                                break
                            else:
                                toupiaodongzuo(toupiao_player, i)
                        elif "预言家" in player_shen:
                            toupiaodongzuo(toupiao_player, "预言家")
            else:
                print(toupiao_player, "弃票")
        else: #默认其他神和村民都是闭眼
            if random.uniform(0, 1) > 0.1:  # 弃票概率 10%
                if random.uniform(0, 1) < 0.7: # 抗推位里面推的概率70%
                    beitou_player=random.choice(kangtuiwei)
                    toupiaodongzuo(toupiao_player, beitou_player)
                elif random.uniform(0, 1) < 0.55: #两个跳预言家里推的概率55%,在以上基础之上
                    if hantiaolang in player_lang and "预言家" in player_shen: #判断是否都存活
                        beitou_player = random.choice([hantiaolang,"预言家"])
                        toupiaodongzuo(toupiao_player, beitou_player)
                    elif hantiaolang in player_lang: #如果只有焊跳狼存活,推焊跳狼
                        toupiaodongzuo(toupiao_player, hantiaolang)
                    elif "预言家" in player_lang:#如果只有预言家存活,推预言家 ,就是这么凶
                        toupiaodongzuo(toupiao_player, "预言家")
                    else:
                        beitou_player = random.choice(kangtuiwei) #如果全都死了,那就在抗推位里推
                        toupiaodongzuo(toupiao_player, beitou_player)
                else: #看谁不爽就投谁,凶起来连自己都投
                    beitou_player = random.choice(toupiao_player_list)
                    toupiaodongzuo(toupiao_player, beitou_player)
            else:
                print(toupiao_player, "弃票")
    return piaoshu

狼刀

def daoren(shouhu_player): #夜晚刀人和救人
    global jieyao,kaiyao
    if random.uniform(0, 1) > 0.05:  # 空刀 概率5%,这个版本不考虑自刀也不考虑警徽了,就随机刀
        dengdao_player=player_min + player_shen
        beidao_player = random.choice(dengdao_player)
        if "女巫" in player_shen and jieyao == 1:  # 女巫存活,解药还在
            if random.uniform(0, 1) < 0.5:  # 愿意救人 概率50%
                jieyao=0  #解药没了
                if beidao_player==shouhu_player: #奶穿
                    chuju(beidao_player)
                    kaiyao = 1
                    print("狼队杀死了", beidao_player,"原因被奶穿")
                    #return beidao_player
                else: # 成功救人
                    kaiyao = 1
                    print("狼队选择刀", beidao_player, "被女巫救起")
                    #return 0
            elif shouhu_player == beidao_player:
                print("狼队选择刀", beidao_player, "被守卫守住")
                #return 0
            else:
                chuju(beidao_player)
                print("狼队杀死了", beidao_player)
                #kaiqiang(beidao_player)
                return beidao_player
        elif shouhu_player ==beidao_player:
            print("狼队选择刀",beidao_player,"被守卫守住")
            #return 0
        else:
            print("狼队杀死了", beidao_player)
            #kaiqiang(beidao_player)
            return beidao_player
    else:
        print("狼队空刀")
        #return 0
    return kaiyao

代码可能有点辣眼睛,程序结构也比较辣眼睛

还有女巫撒毒,守卫守人操作,猎人操作等等,基本操作都写了

玩家主要分三个阵营,直接用字符串代替,没有写class让不是程序猿的朋友更好理解一些,

再次希望原谅我的垃圾代码

    #初始化
    day = 0 #天数
    player_lang = ["狼人1", "狼人2", "狼人3", "狼人4"]  # 狼人玩家
    player_min = ["村民1", "村民2", "村民3", "村民4"]  # 村民玩家
    player_shen = ["女巫", "猎人", "预言家", "守卫"]  # 神玩家
    last_shouhu_player = 0 #上次守护玩家
    duyao = 1 #毒药
    jieyao = 1 #解药

然后我们让他们一起玩耍10万次看看

人工智障_狼人杀版https://www.zhihu.com/video/1153346293773484032

看一下最后结果

第 100000 次
狼人获胜次数: 47010
好人获胜次数: 52990

当然我这个程序逻辑和概率跟实际情况肯定有出入。

但是逻辑是这个逻辑

可能我哪天脑子一抽,写一个带聊天的呢。

思路大概就是,人工智障们聊天函数有以下几个动作,排狼坑,轻踩,重喷,滑水等动作。

神职位玩家发言有,报夜间信息动作,撒毒,救人,守人信息,验人信息等动作

狼人有焊跳动作,不仅仅是预言家 还有跳女巫,跳猎人,跳守卫这些动作

然后根据这些动作影响 其他人的判断,其他人的判断影响自己的动作(当然这个影响值有浮动)

但是这逻辑太过于复杂,我一时半会缕不过来,这个需要蹭一下子有思路才行

然后写一个模型来训练这些智障,让他们变成智能,然后再玩

如果有人想要交流一下,一起做这个有(dan)趣(teng)的事,或者想要上面这个程序打源码。

可以一起交流

微信:zhao0268(不是公众号,我个人微信,推销勿扰)

继续浏览内容
知乎
发现更大的世界
打开
浏览器
继续

好人的胜率趋近于100%,单个人的胜率趋近于66.66%

理论上,狼是被束缚的,无论是面杀还是网杀,狼人都是被道德伦理束缚着的,不能贴脸,甚至不能微擦边,有时候甚至不能起状态,被别人扣一个贴脸的标签,然后情况就变成了,预言家如果觉得有人是因为说你贴脸才站错边,预言家会说你不要贴脸,你个狼人要不要脸,或者预言家起比你更大的情绪,如果好人都是分奴,谁贴脸更厉害就信谁,那狼人基本就没有焊条成功的空间,首先我认为预女猎白的板子也好,狼王守卫的板子也好,白狼王守卫的板子也好,狼队想赢,一定需要一个成功的焊跳,否则试图去做一个外置位身份偏好的狼人,一定需要至少一个身份偏不好的好人,和不太会验人的预言家,且身份偏不好的好人还需要没有身份,狼人和好人如果发言水平相同或相似,考虑中高配有一定数据库的情况下,好人就不太可能被抗推,感觉到自己要被抗推就拍真实身份,神牌就不太可能被抗推,狼人也没有对跳收益,平民牌就很可能吃验,如果还有第二个没身份的好人且发言差且是平民也就最多吃女巫一毒,狼人有自信女巫毒平民且刀刀平民吗?顶配局有可能,但是顶配局就不太可能有2个发言不好的平民。

所以我的结论就是如果没有办法破解预言家和狼人不对等发言关系,熟人牌的人物属性,以及牌坊问题,预言家无解则好人无解,你能根据数据库和抿人去刀女巫,女巫凭什么不能根据数据库和卦象毒到狼人,这明显比找女巫容易,女巫毒狼人,除非狼能感觉到自爆吞毒,否则警推还是领先。

当然这都是理论上的,理论的基础是大家都为了赢而玩游戏,都认真听发言,好人不篡改别人发言。

实际情况嘛,一言难尽吧,网杀好人不认真听其他人发言,篡改别人发言,面杀好人,打操作,上警靠卦象炸身份,扰乱好人试听,都很难盘,还有什么警推领先玩动态底牌的傻逼。

只能说,可能我觉得人家是傻逼,人家觉得游戏而已,输赢无所谓。

那可能就在我理论之外了,可能人家认为这是一个装装逼撩撩妹的复盘游戏,那俺也没办法。

我突然意识到我的理论还有很多我认为是应该的,但是大多数网杀玩家以及低配玩家不认为是正确的。

1.警上必开狼是过于武断的。

2.警下必开狼是过于武断的。

3.留警徽流并不能拉到票,也不应该把票上给留自己警徽流的人,表示自己不怕验,而是上给你认为像预言家的人。

4.边角位必开狼是幸存者偏差

5.左两狼右两狼是先验逻辑和后验逻辑混淆

6.预言家警徽流一定要验最像狼的人是错误的,听过两轮发言的预言家应该把警徽流改为验容错。

其中我认为最大的不同是第6条,我倾向于,如果大家的发言都认真听了,而且共同相信前5条理论,那么预言家应该有能力在1轮警上和警下发言后,听出6个坑位出4个狼,并在其中最不像狼的2个人里留警徽流,剩下的人就拍身份,没身份吃毒吃推。

如果这个能力都没有,我认为属于低配局,不在讨论范围内,这些人可能没玩明白这个游戏。

正常来讲,以我实际经验,预言家应该在情况不复杂的条件下,正常盘出5进4,并验最不像狼的,或者性价比最高的,情况复杂的条件下,6进4,打错1个也是可以理解的,但是预言家大概率不应该出局,如果出局了,看到票型后,盘出5进4,也是比较轻松的, 而且狼人一定要吃毒,这是我对中配局的定义,更不谈高配局。

实际上我认为如果不打伪逻辑,12个人都认真听对方发言,在狼人束手束脚的发言下,好人的莫名其妙爆水,钢铁预言家,微场外,微贴脸,都是狼人不能接受的痛苦。

有人可能要说,为什么理论下好人可以贴脸,狼人不行。

因为好人不贴脸也会无意中爆水,狼人不会,好人在有压力的情况下,更会用力发言,很有可能就擦边了,这是人性决定的,也是这个游戏的风气决定的,长久以来对于狼人的苛刻要求,这个游戏已经出现了越是高端局,越是杀狼人,而不是狼人杀,好人场外,狼人无奈双爆,好人贴脸,狼人无奈交牌,从来就没有狼人贴脸能贴赢好人的情况。

所以我的理论就是建立在好人贴脸比狼人多,比狼人厉害,中配局就开始根据这种维度的信息获取大量逻辑外的视角,从而压缩狼队空间,甚至有些好人,会恶意使用擦边,比如,悍跳狼实际上只是情绪发言,而非贴脸,狼人可以有演技,非要给焊跳狼贴上贴脸的标签,然后道德绑架,最后悍跳狼害怕复盘时被攻击,所以选择自爆,这种情况屡见不鲜。

继续浏览内容
知乎
发现更大的世界
打开
浏览器
继续