banned/src/roles/traitor.py
2017-12-13 20:10:44 -06:00

84 lines
3.6 KiB
Python

import re
import random
import itertools
import math
from collections import defaultdict
import botconfig
import src.settings as var
from src.utilities import *
from src import debuglog, errlog, plog, users, channels
from src.decorators import cmd, event_listener
from src.messages import messages
from src.events import Event
@event_listener("get_reveal_role")
def on_get_reveal_role(evt, var, nick):
# in team reveal, show traitor as wolfteam, otherwise team stats won't sync with how
# they're revealed upon death. Team stats should show traitor as wolfteam or else
# the stats are wrong in that they'll report one less wolf than actually exists,
# which can confuse a lot of people
if evt.data["role"] == "traitor" and var.HIDDEN_TRAITOR and var.ROLE_REVEAL != "team":
evt.data["role"] = var.DEFAULT_ROLE
@event_listener("get_final_role")
def on_get_final_role(evt, cli, var, nick, role):
# if a traitor turns we want to show them as traitor in the end game readout
# instead of "wolf (was traitor)"
if role == "traitor" and evt.data["role"] == "wolf":
evt.data["role"] = "traitor"
@event_listener("update_stats", priority=1)
def on_update_stats1(evt, var, player, mainrole, revealroles, allroles):
if mainrole == var.DEFAULT_ROLE and var.HIDDEN_TRAITOR:
evt.data["possible"].add("traitor")
@event_listener("update_stats", priority=3)
def on_update_stats3(evt, var, player, mainrole, revealroles, allroles):
# if this is a night death and we know for sure that wolves (and only wolves)
# killed, then that kill cannot be traitor as long as they're in wolfchat.
# ismain True = night death, False = chain death; chain deaths can be traitors
# even if only wolves killed, so we short-circuit there as well
# TODO: an observant user will be able to determine if traitor dies due to luck/misdirection totem
# redirecting a wolf kill onto traitor
if "traitor" not in evt.data["possible"] or not evt.params.ismain or mainrole == "traitor":
return
if var.PHASE == "day" and var.GAMEPHASE == "night":
mevt = Event("get_role_metadata", {})
mevt.dispatch(var, "night_kills")
nonwolf = 0
total = 0
for role, num in mevt.data.items():
if role != "wolf":
nonwolf += num
total += num
if nonwolf == 0:
evt.data["possible"].discard("traitor")
return
# TODO: this doesn't account for everything, for example if there was a hunter kill
# and a wolf kill, and a wolf + villager died, we know the villager was the wolf kill
# and therefore cannot be traitor. However, we currently do not have the logic to deduce this
@event_listener("chk_win", priority=1.1)
def on_chk_win(evt, cli, var, rolemap, mainroles, lpl, lwolves, lrealwolves):
did_something = False
if lrealwolves == 0:
for traitor in list(rolemap["traitor"]):
rolemap["wolf"].add(traitor)
rolemap["traitor"].remove(traitor)
rolemap["cursed villager"].discard(traitor)
mainroles[traitor] = "wolf"
did_something = True
if var.PHASE in var.GAME_PHASES:
var.FINAL_ROLES[traitor.nick] = "wolf" # FIXME
traitor.send(messages["traitor_turn"])
debuglog(traitor, "(traitor) TURNING")
if did_something:
if var.PHASE in var.GAME_PHASES:
var.TRAITOR_TURNED = True
channels.Main.send(messages["traitor_turn_channel"])
evt.prevent_default = True
evt.stop_processing = True
# vim: set sw=4 expandtab: