Revert "Revert last 3 commits - broken code"
This reverts commit 5e91556426
.
This commit is contained in:
parent
5e91556426
commit
09d90fd7e2
@ -229,7 +229,8 @@ class VillagergameMode(GameMode):
|
|||||||
tgt = hlt
|
tgt = hlt
|
||||||
if not tgt:
|
if not tgt:
|
||||||
tgt = random.choice(pl)
|
tgt = random.choice(pl)
|
||||||
var.KILLS[botconfig.NICK] = [tgt]
|
from src.roles import wolf
|
||||||
|
wolf.KILLS[botconfig.NICK] = [tgt]
|
||||||
|
|
||||||
@game_mode("foolish", minp = 8, maxp = 24, likelihood = 8)
|
@game_mode("foolish", minp = 8, maxp = 24, likelihood = 8)
|
||||||
class FoolishMode(GameMode):
|
class FoolishMode(GameMode):
|
||||||
|
151
src/roles/hunter.py
Normal file
151
src/roles/hunter.py
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import re
|
||||||
|
import random
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
import src.settings as var
|
||||||
|
from src.utilities import *
|
||||||
|
from src import debuglog, errlog, plog
|
||||||
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.messages import messages
|
||||||
|
from src.events import Event
|
||||||
|
|
||||||
|
KILLS = {} # type: Dict[str, str]
|
||||||
|
HUNTERS = set()
|
||||||
|
PASSED = set()
|
||||||
|
|
||||||
|
@cmd("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",))
|
||||||
|
def hunter_kill(cli, nick, chan, rest):
|
||||||
|
"""Kill someone once per game."""
|
||||||
|
if nick in HUNTERS and nick not in KILLS:
|
||||||
|
pm(cli, nick, messages["hunter_already_killed"])
|
||||||
|
return
|
||||||
|
pieces = re.split(" +", rest)
|
||||||
|
victim = pieces[0]
|
||||||
|
orig = victim
|
||||||
|
evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True})
|
||||||
|
evt.dispatch(cli, var, "kill", nick, victim, frozenset({"detrimental"}))
|
||||||
|
if evt.prevent_default:
|
||||||
|
return
|
||||||
|
victim = evt.data["target"]
|
||||||
|
|
||||||
|
KILLS[nick] = victim
|
||||||
|
HUNTERS.add(nick)
|
||||||
|
PASSED.discard(nick)
|
||||||
|
|
||||||
|
msg = messages["wolf_target"].format(orig)
|
||||||
|
pm(cli, nick, messages["player"].format(msg))
|
||||||
|
|
||||||
|
debuglog("{0} ({1}) KILL: {2} ({3})".format(nick, get_role(nick), victim, get_role(victim)))
|
||||||
|
|
||||||
|
chk_nightdone(cli)
|
||||||
|
|
||||||
|
@cmd("retract", "r", chan=False, pm=True, playing=True, phases=("night",), roles=("hunter",))
|
||||||
|
def hunter_retract(cli, nick, chan, rest):
|
||||||
|
"""Removes a hunter's kill selection."""
|
||||||
|
if nick not in KILLS and nick not in PASSED:
|
||||||
|
return
|
||||||
|
if nick in KILLS:
|
||||||
|
del KILLS[nick]
|
||||||
|
HUNTERS.discard(nick)
|
||||||
|
PASSED.discard(nick)
|
||||||
|
pm(cli, nick, messages["retracted_kill"])
|
||||||
|
|
||||||
|
@cmd("pass", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hunter",))
|
||||||
|
def hunter_pass(cli, nick, chan, rest):
|
||||||
|
"""Do not use hunter's once-per-game kill tonight."""
|
||||||
|
if nick in HUNTERS and nick not in KILLS:
|
||||||
|
pm(cli, nick, messages["hunter_already_killed"])
|
||||||
|
return
|
||||||
|
if nick in KILLS:
|
||||||
|
del KILLS[nick]
|
||||||
|
HUNTERS.discard(nick)
|
||||||
|
PASSED.add(nick)
|
||||||
|
pm(cli, nick, messages["hunter_pass"])
|
||||||
|
|
||||||
|
@event_listener("del_player")
|
||||||
|
def on_del_player(evt, cli, var, nick, nickrole, nicktpls, lynched, end_game, death_triggers, killer_role, deadlist, original, ismain, refresh_pl):
|
||||||
|
for h,v in list(KILLS.items()):
|
||||||
|
if v == nick:
|
||||||
|
HUNTERS.discard(h)
|
||||||
|
PASSED.discard(h)
|
||||||
|
pm(cli, h, messages["hunter_discard"])
|
||||||
|
del KILLS[h]
|
||||||
|
elif h == nick:
|
||||||
|
del KILLS[h]
|
||||||
|
|
||||||
|
@event_listener("rename_player")
|
||||||
|
def on_rename(evt, cli, var, prefix, nick):
|
||||||
|
kvp = []
|
||||||
|
for a,b in KILLS.items():
|
||||||
|
if a == prefix:
|
||||||
|
a = nick
|
||||||
|
if b == prefix:
|
||||||
|
b = nick
|
||||||
|
kvp.append((a,b))
|
||||||
|
KILLS.update(kvp)
|
||||||
|
if prefix in KILLS:
|
||||||
|
del KILLS[prefix]
|
||||||
|
if prefix in HUNTERS:
|
||||||
|
HUNTERS.discard(prefix)
|
||||||
|
HUNTERS.add(nick)
|
||||||
|
if prefix in PASSED:
|
||||||
|
PASSED.discard(prefix)
|
||||||
|
PASSED.add(nick)
|
||||||
|
|
||||||
|
@event_listener("acted")
|
||||||
|
def on_acted(evt, cli, var, nick, sender):
|
||||||
|
if nick in KILLS:
|
||||||
|
evt.data["acted"] = True
|
||||||
|
|
||||||
|
@event_listener("transition_day", priority=2)
|
||||||
|
def on_transition_day(evt, cli, var):
|
||||||
|
for k, d in list(KILLS.items()):
|
||||||
|
evt.data["victims"].append(d)
|
||||||
|
evt.data["onlybywolves"].discard(d)
|
||||||
|
evt.data["killers"][d] = k
|
||||||
|
# important, otherwise our del_player listener lets hunter kill again
|
||||||
|
del KILLS[k]
|
||||||
|
|
||||||
|
@event_listener("exchange_roles")
|
||||||
|
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):
|
||||||
|
if actor in KILLS:
|
||||||
|
del KILLS[actor]
|
||||||
|
if nick in KILLS:
|
||||||
|
del KILLS[nick]
|
||||||
|
HUNTERS.discard(actor)
|
||||||
|
HUNTERS.discard(nick)
|
||||||
|
PASSED.discard(actor)
|
||||||
|
PASSED.discard(nick)
|
||||||
|
|
||||||
|
@event_listener("chk_nightdone")
|
||||||
|
def on_chk_nightdone(evt, cli, var):
|
||||||
|
evt.data["actedcount"] += len(KILLS) + len(PASSED)
|
||||||
|
evt.data["nightroles"].extend([p for p in var.ROLES["hunter"] if p not in HUNTERS or p in KILLS])
|
||||||
|
|
||||||
|
@event_listener("transition_night_end", priority=2)
|
||||||
|
def on_transition_night_end(evt, cli, var):
|
||||||
|
ps = list_players()
|
||||||
|
for hunter in var.ROLES["hunter"]:
|
||||||
|
if hunter in HUNTERS:
|
||||||
|
continue #already killed
|
||||||
|
pl = ps[:]
|
||||||
|
random.shuffle(pl)
|
||||||
|
pl.remove(hunter)
|
||||||
|
if hunter in var.PLAYERS and not is_user_simple(hunter):
|
||||||
|
pm(cli, hunter, messages["hunter_notify"])
|
||||||
|
else:
|
||||||
|
pm(cli, hunter, messages["hunter_simple"])
|
||||||
|
pm(cli, hunter, "Players: " + ", ".join(pl))
|
||||||
|
|
||||||
|
@event_listener("begin_day")
|
||||||
|
def on_begin_day(evt, cli, var):
|
||||||
|
KILLS.clear()
|
||||||
|
PASSED.clear()
|
||||||
|
|
||||||
|
@event_listener("reset")
|
||||||
|
def on_reset(evt, var):
|
||||||
|
KILLS.clear()
|
||||||
|
PASSED.clear()
|
||||||
|
HUNTERS.clear()
|
||||||
|
|
||||||
|
# vim: set sw=4 expandtab:
|
@ -82,6 +82,11 @@ def on_rename(evt, cli, var, prefix, nick):
|
|||||||
SEEN.remove(prefix)
|
SEEN.remove(prefix)
|
||||||
SEEN.add(nick)
|
SEEN.add(nick)
|
||||||
|
|
||||||
|
@event_listener("acted")
|
||||||
|
def on_acted(evt, cli, var, nick, sender):
|
||||||
|
if nick in SEEN:
|
||||||
|
evt.data["acted"] = True
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("exchange_roles")
|
||||||
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):
|
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):
|
||||||
if actor_role in ("seer", "oracle", "augur"):
|
if actor_role in ("seer", "oracle", "augur"):
|
||||||
|
52
src/roles/villager.py
Normal file
52
src/roles/villager.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import src.settings as var
|
||||||
|
from src.utilities import *
|
||||||
|
from src import debuglog, errlog, plog
|
||||||
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.messages import messages
|
||||||
|
from src.events import Event
|
||||||
|
|
||||||
|
# handles villager and cultist
|
||||||
|
|
||||||
|
@event_listener("transition_night_end", priority=2)
|
||||||
|
def on_transition_night_end(evt, cli, var):
|
||||||
|
if var.FIRST_NIGHT or var.ALWAYS_PM_ROLE:
|
||||||
|
villroles = var.HIDDEN_VILLAGERS | {"villager"}
|
||||||
|
if var.DEFAULT_ROLE == "villager":
|
||||||
|
villroles |= var.HIDDEN_ROLES
|
||||||
|
villagers = list_players(villroles)
|
||||||
|
for villager in villagers:
|
||||||
|
if villager in var.PLAYERS and not is_user_simple(villager):
|
||||||
|
pm(cli, villager, messages["villager_notify"])
|
||||||
|
else:
|
||||||
|
pm(cli, villager, messages["villager_simple"])
|
||||||
|
|
||||||
|
cultroles = {"cultist"}
|
||||||
|
if var.DEFAULT_ROLE == "cultist":
|
||||||
|
cultroles |= var.HIDDEN_ROLES
|
||||||
|
cultists = list_players(cultroles)
|
||||||
|
for cultist in cultists:
|
||||||
|
if cultist in var.PLAYERS and not is_user_simple(cultist):
|
||||||
|
pm(cli, cultist, messages["cultist_notify"])
|
||||||
|
else:
|
||||||
|
pm(cli, cultist, messages["cultist_simple"])
|
||||||
|
|
||||||
|
# No listeners should register before this one
|
||||||
|
# This sets up the initial state, based on village/wolfteam/neutral affiliation
|
||||||
|
@event_listener("player_win", priority=0)
|
||||||
|
def on_player_win(evt, cli, var, nick, role, winner, survived):
|
||||||
|
# init won/iwon to False
|
||||||
|
evt.data["won"] = False
|
||||||
|
evt.data["iwon"] = False
|
||||||
|
|
||||||
|
if role in var.WOLFTEAM_ROLES or (var.DEFAULT_ROLE == "cultist" and role in var.HIDDEN_ROLES):
|
||||||
|
if winner == "wolves":
|
||||||
|
evt.data["won"] = True
|
||||||
|
evt.data["iwon"] = survived
|
||||||
|
elif role in var.TRUE_NEUTRAL_ROLES:
|
||||||
|
# handled in their individual files
|
||||||
|
pass
|
||||||
|
elif winner == "villagers":
|
||||||
|
evt.data["won"] = True
|
||||||
|
evt.data["iwon"] = survived
|
||||||
|
|
||||||
|
# vim: set sw=4 expandtab:
|
270
src/roles/wolf.py
Normal file
270
src/roles/wolf.py
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
import re
|
||||||
|
import random
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
import src.settings as var
|
||||||
|
from src.utilities import *
|
||||||
|
from src import debuglog, errlog, plog
|
||||||
|
from src.decorators import cmd, event_listener
|
||||||
|
from src.messages import messages
|
||||||
|
from src.events import Event
|
||||||
|
|
||||||
|
KILLS = {} # type: Dict[str, List[str]]
|
||||||
|
|
||||||
|
@cmd("kill", chan=False, pm=True, playing=True, phases=("night",))
|
||||||
|
def wolf_kill(cli, nick, chan, rest):
|
||||||
|
"""Kills one or more players as a wolf."""
|
||||||
|
role = get_role(nick)
|
||||||
|
# eventually cub will listen on targeted_command and block kills that way
|
||||||
|
if role not in var.WOLF_ROLES - {"wolf cub"}:
|
||||||
|
return
|
||||||
|
if nick in var.SILENCED:
|
||||||
|
pm(cli, nick, messages["silenced"])
|
||||||
|
return
|
||||||
|
if var.DISEASED_WOLVES:
|
||||||
|
pm(cli, nick, messages["ill_wolves"])
|
||||||
|
return
|
||||||
|
# eventually crow will listen on targeted_command and block kills that way
|
||||||
|
# (or more likely, that restriction will be lifted and crow can do both)
|
||||||
|
if role == "werecrow" and var.OBSERVED.get(nick):
|
||||||
|
pm(cli, nick, messages["werecrow_transformed_nokill"])
|
||||||
|
return
|
||||||
|
|
||||||
|
pieces = re.split(" +", rest)
|
||||||
|
victims = []
|
||||||
|
orig = []
|
||||||
|
num_kills = 1
|
||||||
|
if var.ANGRY_WOLVES:
|
||||||
|
num_kills = 2
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
extra = 0
|
||||||
|
while i < num_kills + extra:
|
||||||
|
try:
|
||||||
|
victim = pieces[i]
|
||||||
|
except IndexError:
|
||||||
|
break
|
||||||
|
if victim.lower() == "and":
|
||||||
|
extra += 1
|
||||||
|
i += 1
|
||||||
|
victim = pieces[i]
|
||||||
|
victim = get_victim(cli, nick, victim, False)
|
||||||
|
if not victim:
|
||||||
|
return
|
||||||
|
|
||||||
|
if victim == nick:
|
||||||
|
pm(cli, nick, messages["no_suicide"])
|
||||||
|
return
|
||||||
|
if in_wolflist(nick, victim):
|
||||||
|
pm(cli, nick, messages["wolf_no_target_wolf"])
|
||||||
|
return
|
||||||
|
orig.append(victim)
|
||||||
|
evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True})
|
||||||
|
evt.dispatch(cli, var, "kill", nick, victim, frozenset({"detrimental"}))
|
||||||
|
if evt.prevent_default:
|
||||||
|
return
|
||||||
|
victim = evt.data["target"]
|
||||||
|
victims.append(victim)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if len(set(victims)) < len(victims):
|
||||||
|
pm(cli, nick, messages["wolf_must_target_multiple"])
|
||||||
|
return
|
||||||
|
KILLS[nick] = victims
|
||||||
|
if len(orig) > 1:
|
||||||
|
# need to expand this eventually
|
||||||
|
msg = messages["wolf_target_multiple"].format(orig[0], orig[1])
|
||||||
|
pm(cli, nick, messages["player"].format(msg))
|
||||||
|
debuglog("{0} ({1}) KILL: {2} ({3}) and {4} ({5})".format(nick, role, victims[0], get_role(victims[0]), victims[1], get_role(victims[1])))
|
||||||
|
else:
|
||||||
|
msg = messages["wolf_target"].format(orig[0])
|
||||||
|
pm(cli, nick, messages["player"].format(msg))
|
||||||
|
if num_kills > 1:
|
||||||
|
pm(cli, nick, messages["wolf_target_second"])
|
||||||
|
debuglog("{0} ({1}) KILL: {2} ({3})".format(nick, role, victims[0], get_role(victims[0])))
|
||||||
|
|
||||||
|
if in_wolflist(nick, nick):
|
||||||
|
relay_wolfchat_command(cli, nick, messages["wolfchat"].format(nick, msg), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
|
||||||
|
|
||||||
|
chk_nightdone(cli)
|
||||||
|
|
||||||
|
@cmd("retract", "r", chan=False, pm=True, playing=True, phases=("night",))
|
||||||
|
def wolf_retract(cli, nick, chan, rest):
|
||||||
|
"""Removes a wolf's kill selection."""
|
||||||
|
if nick not in KILLS:
|
||||||
|
return
|
||||||
|
del KILLS[nick]
|
||||||
|
pm(cli, nick, messages["retracted_kill"])
|
||||||
|
relay_wolfchat_command(cli, nick, messages["wolfchat_retracted_kill"].format(nick), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
|
||||||
|
|
||||||
|
@event_listener("del_player")
|
||||||
|
def on_del_player(evt, cli, var, nick, nickrole, nicktpls, lynched, end_game, death_triggers, killer_role, deadlist, original, ismain, refresh_pl):
|
||||||
|
for a,b in list(KILLS.items()):
|
||||||
|
for n in b:
|
||||||
|
if n == nick:
|
||||||
|
KILLS[a].remove(nick)
|
||||||
|
if a == nick or len(KILLS[a]) == 0:
|
||||||
|
del KILLS[a]
|
||||||
|
|
||||||
|
@event_listener("rename_player")
|
||||||
|
def on_rename(evt, cli, var, prefix, nick):
|
||||||
|
kvp = []
|
||||||
|
for a,b in KILLS.items():
|
||||||
|
nl = []
|
||||||
|
for n in b:
|
||||||
|
if n == prefix:
|
||||||
|
n = nick
|
||||||
|
nl.append(n)
|
||||||
|
if a == prefix:
|
||||||
|
a = nick
|
||||||
|
kvp.append((a,nl))
|
||||||
|
KILLS.update(kvp)
|
||||||
|
if prefix in KILLS:
|
||||||
|
del KILLS[prefix]
|
||||||
|
|
||||||
|
@event_listener("acted")
|
||||||
|
def on_acted(evt, cli, var, nick, sender):
|
||||||
|
if nick in KILLS:
|
||||||
|
evt.data["acted"] = True
|
||||||
|
|
||||||
|
@event_listener("transition_day", priority=1)
|
||||||
|
def on_transition_day(evt, cli, var):
|
||||||
|
# figure out wolf target
|
||||||
|
found = defaultdict(int)
|
||||||
|
# split off into event + wolfcub.py
|
||||||
|
num_kills = 1
|
||||||
|
if var.ANGRY_WOLVES:
|
||||||
|
num_kills = 2
|
||||||
|
for v in KILLS.values():
|
||||||
|
for p in v:
|
||||||
|
if p:
|
||||||
|
# kill target starting with ! is invalid
|
||||||
|
# right now nothing does this, but monster eventually will
|
||||||
|
if p[0] == "!":
|
||||||
|
continue
|
||||||
|
found[p] += 1
|
||||||
|
for i in range(num_kills):
|
||||||
|
maxc = 0
|
||||||
|
dups = []
|
||||||
|
for v, c in found.items():
|
||||||
|
if c > maxc:
|
||||||
|
maxc = c
|
||||||
|
dups = [v]
|
||||||
|
elif c == maxc:
|
||||||
|
dups.append(v)
|
||||||
|
if maxc and dups:
|
||||||
|
victim = random.choice(dups)
|
||||||
|
evt.data["victims"].append(victim)
|
||||||
|
evt.data["bywolves"].add(victim)
|
||||||
|
evt.data["onlybywolves"].add(victim)
|
||||||
|
# special key to let us know to randomly select a wolf in case of retribution totem
|
||||||
|
evt.data["killers"][victim].append("@wolves")
|
||||||
|
del found[victim]
|
||||||
|
|
||||||
|
# this should be moved to an event in kill, where monster prefixes their nick with !
|
||||||
|
# and fallen angel subsequently removes the ! prefix
|
||||||
|
if len(var.ROLES["fallen angel"]) == 0:
|
||||||
|
for monster in var.ROLES["monster"]:
|
||||||
|
if monster in victims:
|
||||||
|
evt.data["victims"].remove(monster)
|
||||||
|
evt.data["bywolves"].discard(monster)
|
||||||
|
evt.data["onlybywolves"].discard(monster)
|
||||||
|
|
||||||
|
@event_listener("exchange_roles")
|
||||||
|
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):
|
||||||
|
if actor in KILLS:
|
||||||
|
del KILLS[actor]
|
||||||
|
if nick in KILLS:
|
||||||
|
del KILLS[nick]
|
||||||
|
|
||||||
|
@event_listener("chk_nightdone", priority=3)
|
||||||
|
def on_chk_nightdone(evt, cli, var):
|
||||||
|
if not var.DISEASED_WOLVES:
|
||||||
|
evt.data["actedcount"] += len(KILLS)
|
||||||
|
# eventually wolf cub will remove itself from nightroles in wolfcub.py
|
||||||
|
evt.data["nightroles"].extend(list_players(var.WOLF_ROLES - {"wolf cub"}))
|
||||||
|
|
||||||
|
@event_listener("chk_nightdone", priority=20)
|
||||||
|
def on_chk_nightdone2(evt, cli, var):
|
||||||
|
if not evt.prevent_default and not var.DISEASED_WOLVES:
|
||||||
|
# flatten KILLS
|
||||||
|
kills = set()
|
||||||
|
for ls in KILLS.values():
|
||||||
|
kills.update(ls)
|
||||||
|
# check if wolves are actually agreeing
|
||||||
|
# allow len(kills) == 0 through as that means that crow was dumb and observed instead
|
||||||
|
if not var.ANGRY_WOLVES and len(kills) > 1:
|
||||||
|
evt.data["actedcount"] -= 1
|
||||||
|
elif var.ANGRY_WOLVES and (len(kills) == 1 or len(kills) > 2):
|
||||||
|
evt.data["actedcount"] -= 1
|
||||||
|
|
||||||
|
@event_listener("transition_night_end", priority=2)
|
||||||
|
def on_transition_night_end(evt, cli, var):
|
||||||
|
ps = list_players()
|
||||||
|
wolves = list_players(var.WOLFCHAT_ROLES)
|
||||||
|
for wolf in wolves:
|
||||||
|
# should make the cursed information an event that cursedvillager can then add to
|
||||||
|
# (e.g. an event to change what prefixes are sent with the role message, and a
|
||||||
|
# 2nd event to change information in parens in player list)
|
||||||
|
normal_notify = wolf in var.PLAYERS and not is_user_simple(wolf)
|
||||||
|
role = get_role(wolf)
|
||||||
|
cursed = "cursed " if wolf in var.ROLES["cursed villager"] else ""
|
||||||
|
|
||||||
|
if normal_notify:
|
||||||
|
msg = "{0}_notify".format(role.replace(" ", "_"))
|
||||||
|
cmsg = "cursed_" + msg
|
||||||
|
try:
|
||||||
|
if cursed:
|
||||||
|
try:
|
||||||
|
pm(cli, wolf, messages[cmsg])
|
||||||
|
except KeyError:
|
||||||
|
pm(cli, wolf, messages[msg].format(cursed))
|
||||||
|
else:
|
||||||
|
pm(cli, wolf, messages[msg].format(cursed))
|
||||||
|
except KeyError:
|
||||||
|
# catchall in case we forgot something above
|
||||||
|
an = 'n' if role.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
pm(cli, wolf, messages["undefined_role_notify"].format(an, role))
|
||||||
|
|
||||||
|
if len(wolves) > 1:
|
||||||
|
pm(cli, wolf, messages["wolfchat_notify"])
|
||||||
|
else:
|
||||||
|
an = "n" if cursed == "" and role.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
pm(cli, wolf, messages["wolf_simple"].format(an, cursed, role)) # !simple
|
||||||
|
|
||||||
|
pl = ps[:]
|
||||||
|
random.shuffle(pl)
|
||||||
|
pl.remove(wolf) # remove self from list
|
||||||
|
for i, player in enumerate(pl):
|
||||||
|
prole = get_role(player)
|
||||||
|
if prole in var.WOLFCHAT_ROLES:
|
||||||
|
cursed = ""
|
||||||
|
if player in var.ROLES["cursed villager"]:
|
||||||
|
cursed = "cursed "
|
||||||
|
pl[i] = "\u0002{0}\u0002 ({1}{2})".format(player, cursed, prole)
|
||||||
|
elif player in var.ROLES["cursed villager"]:
|
||||||
|
pl[i] = player + " (cursed)"
|
||||||
|
|
||||||
|
pm(cli, wolf, "Players: " + ", ".join(pl))
|
||||||
|
if var.DISEASED_WOLVES:
|
||||||
|
pm(cli, wolf, messages["ill_wolves"])
|
||||||
|
# TODO: split the following out into their own files (mystic, cub and alpha)
|
||||||
|
if role == "wolf mystic":
|
||||||
|
# if adding this info to !myrole, you will need to save off this count so that they can't get updated info until the next night
|
||||||
|
# # of special villagers = # of players - # of villagers - # of wolves - # of neutrals
|
||||||
|
numvills = len(ps) - len(list_players(var.WOLFTEAM_ROLES)) - len(list_players(("villager", "vengeful ghost", "time lord", "amnesiac", "lycan"))) - len(list_players(var.TRUE_NEUTRAL_ROLES))
|
||||||
|
pm(cli, wolf, messages["wolf_mystic_info"].format("are" if numvills != 1 else "is", numvills, "s" if numvills != 1 else ""))
|
||||||
|
if not var.DISEASED_WOLVES and var.ANGRY_WOLVES and role in var.WOLF_ROLES and role != "wolf cub":
|
||||||
|
pm(cli, wolf, messages["angry_wolves"])
|
||||||
|
if var.ALPHA_ENABLED and role == "alpha wolf" and wolf not in var.ALPHA_WOLVES:
|
||||||
|
pm(cli, wolf, messages["wolf_bite"])
|
||||||
|
|
||||||
|
@event_listener("begin_day")
|
||||||
|
def on_begin_day(evt, cli, var):
|
||||||
|
KILLS.clear()
|
||||||
|
|
||||||
|
@event_listener("reset")
|
||||||
|
def on_reset(evt, var):
|
||||||
|
KILLS.clear()
|
||||||
|
|
||||||
|
# vim: set sw=4 expandtab:
|
@ -283,6 +283,10 @@ SEEN_WOLF = WOLF_ROLES | {"monster", "mad scientist", "succubus"}
|
|||||||
# These are seen as the default role (or villager) when seen by seer (this overrides SEEN_WOLF)
|
# These are seen as the default role (or villager) when seen by seer (this overrides SEEN_WOLF)
|
||||||
SEEN_DEFAULT = frozenset({"traitor", "hag", "sorcerer", "time lord", "villager", "cultist", "minion", "turncoat", "amnesiac",
|
SEEN_DEFAULT = frozenset({"traitor", "hag", "sorcerer", "time lord", "villager", "cultist", "minion", "turncoat", "amnesiac",
|
||||||
"vengeful ghost", "lycan", "clone", "fool", "jester", "werekitten", "warlock", "piper", "demoniac"})
|
"vengeful ghost", "lycan", "clone", "fool", "jester", "werekitten", "warlock", "piper", "demoniac"})
|
||||||
|
# These roles are notified that they are villager
|
||||||
|
HIDDEN_VILLAGERS = frozenset({"time lord"})
|
||||||
|
# These roles are notified that they are the default role. They also win alongside the default role barring other role-specific win conds.
|
||||||
|
HIDDEN_ROLES = frozenset({"vengeful ghost", "amnesiac"})
|
||||||
|
|
||||||
# these totems are beneficial for the *receiving* person, but can be detrimental to someone else acting on the receiver!
|
# these totems are beneficial for the *receiving* person, but can be detrimental to someone else acting on the receiver!
|
||||||
BENEFICIAL_TOTEMS = frozenset({"protection", "revealing", "desperation", "influence", "luck", "pestilence", "retribution"})
|
BENEFICIAL_TOTEMS = frozenset({"protection", "revealing", "desperation", "influence", "luck", "pestilence", "retribution"})
|
||||||
|
468
src/wolfgame.py
468
src/wolfgame.py
@ -2486,6 +2486,19 @@ def stop_game(cli, winner="", abort=False, additional_winners=None, log=True):
|
|||||||
|
|
||||||
won = False
|
won = False
|
||||||
iwon = False
|
iwon = False
|
||||||
|
survived = list_players()
|
||||||
|
if not pentry["dced"]:
|
||||||
|
evt = Event("player_win", {"won": won, "iwon": iwon, "special": pentry["special"]})
|
||||||
|
evt.dispatch(cli, var, splr, rol, winner, splr in survived)
|
||||||
|
won = evt.data["won"]
|
||||||
|
iwon = evt.data["iwon"]
|
||||||
|
# ensure that it is a) a list, and b) a copy (so it can't be mutated out from under us later)
|
||||||
|
pentry["special"] = list(evt.data["special"])
|
||||||
|
|
||||||
|
# special-case everyone for after the event
|
||||||
|
if winner == "everyone":
|
||||||
|
iwon = True
|
||||||
|
|
||||||
# determine if this player's team won
|
# determine if this player's team won
|
||||||
if rol in var.TRUE_NEUTRAL_ROLES:
|
if rol in var.TRUE_NEUTRAL_ROLES:
|
||||||
# most true neutral roles never have a team win, only individual wins. Exceptions to that are here
|
# most true neutral roles never have a team win, only individual wins. Exceptions to that are here
|
||||||
@ -2499,19 +2512,8 @@ def stop_game(cli, winner="", abort=False, additional_winners=None, log=True):
|
|||||||
elif winner != "succubi" and splr in var.ENTRANCED:
|
elif winner != "succubi" and splr in var.ENTRANCED:
|
||||||
# entranced players can't win with villager or wolf teams
|
# entranced players can't win with villager or wolf teams
|
||||||
won = False
|
won = False
|
||||||
elif rol in ("amnesiac", "vengeful ghost") and splr not in var.VENGEFUL_GHOSTS:
|
|
||||||
if var.DEFAULT_ROLE == "villager" and winner == "villagers":
|
|
||||||
won = True
|
|
||||||
elif var.DEFAULT_ROLE == "cultist" and winner == "wolves":
|
|
||||||
won = True
|
|
||||||
elif rol in var.WOLFTEAM_ROLES:
|
|
||||||
if winner == "wolves":
|
|
||||||
won = True
|
|
||||||
elif winner == "villagers":
|
|
||||||
won = True
|
|
||||||
|
|
||||||
survived = list_players()
|
if pentry["dced"]:
|
||||||
if plr.startswith("(dced)"):
|
|
||||||
# You get NOTHING! You LOSE! Good DAY, sir!
|
# You get NOTHING! You LOSE! Good DAY, sir!
|
||||||
won = False
|
won = False
|
||||||
iwon = False
|
iwon = False
|
||||||
@ -2581,8 +2583,6 @@ def stop_game(cli, winner="", abort=False, additional_winners=None, log=True):
|
|||||||
iwon = True
|
iwon = True
|
||||||
elif winner == "succubi" and splr in var.ENTRANCED | var.ROLES["succubus"]:
|
elif winner == "succubi" and splr in var.ENTRANCED | var.ROLES["succubus"]:
|
||||||
iwon = True
|
iwon = True
|
||||||
elif winner == "everyone" and not survived:
|
|
||||||
iwon = True # nobody survived but an event made everyone win
|
|
||||||
elif not iwon:
|
elif not iwon:
|
||||||
iwon = won and splr in survived # survived, team won = individual win
|
iwon = won and splr in survived # survived, team won = individual win
|
||||||
|
|
||||||
@ -3171,12 +3171,6 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
|||||||
if var.PHASE in var.GAME_PHASES:
|
if var.PHASE in var.GAME_PHASES:
|
||||||
# remove the player from variables if they're in there
|
# remove the player from variables if they're in there
|
||||||
if ret:
|
if ret:
|
||||||
for a,b in list(var.KILLS.items()):
|
|
||||||
for n in b: #var.KILLS can have 2 kills in a list
|
|
||||||
if n == nick:
|
|
||||||
var.KILLS[a].remove(nick)
|
|
||||||
if a == nick or len(var.KILLS[a]) == 0:
|
|
||||||
del var.KILLS[a]
|
|
||||||
for x in (var.OBSERVED, var.HVISITED, var.GUARDED, var.TARGETED, var.LASTGUARDED, var.LASTGIVEN, var.LASTHEXED):
|
for x in (var.OBSERVED, var.HVISITED, var.GUARDED, var.TARGETED, var.LASTGUARDED, var.LASTGIVEN, var.LASTHEXED):
|
||||||
for k in list(x):
|
for k in list(x):
|
||||||
if nick in (k, x[k]):
|
if nick in (k, x[k]):
|
||||||
@ -3187,7 +3181,6 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
|||||||
del x[k]
|
del x[k]
|
||||||
for k in list(var.OTHER_KILLS):
|
for k in list(var.OTHER_KILLS):
|
||||||
if var.OTHER_KILLS[k] == nick:
|
if var.OTHER_KILLS[k] == nick:
|
||||||
var.HUNTERS.discard(k)
|
|
||||||
pm(cli, k, messages["hunter_discard"])
|
pm(cli, k, messages["hunter_discard"])
|
||||||
del var.OTHER_KILLS[k]
|
del var.OTHER_KILLS[k]
|
||||||
elif nick == k:
|
elif nick == k:
|
||||||
@ -3203,7 +3196,7 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
|||||||
# remove players from night variables
|
# remove players from night variables
|
||||||
# the dicts are handled above, these are the lists of who has acted which is used to determine whether night should end
|
# the dicts are handled above, these are the lists of who has acted which is used to determine whether night should end
|
||||||
# if these aren't cleared properly night may end prematurely
|
# if these aren't cleared properly night may end prematurely
|
||||||
for x in (var.SEEN, var.PASSED, var.HUNTERS, var.HEXED, var.MATCHMAKERS, var.CURSED, var.CHARMERS):
|
for x in (var.SEEN, var.PASSED, var.HEXED, var.MATCHMAKERS, var.CURSED, var.CHARMERS):
|
||||||
x.discard(nick)
|
x.discard(nick)
|
||||||
if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching
|
if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching
|
||||||
var.VOTES.pop(nick, None) # Delete other people's votes on the player
|
var.VOTES.pop(nick, None) # Delete other people's votes on the player
|
||||||
@ -3558,21 +3551,6 @@ def rename_player(cli, prefix, nick):
|
|||||||
var.DOCTORS, var.BITTEN_ROLES, var.LYCAN_ROLES, var.AMNESIAC_ROLES):
|
var.DOCTORS, var.BITTEN_ROLES, var.LYCAN_ROLES, var.AMNESIAC_ROLES):
|
||||||
if prefix in dictvar.keys():
|
if prefix in dictvar.keys():
|
||||||
dictvar[nick] = dictvar.pop(prefix)
|
dictvar[nick] = dictvar.pop(prefix)
|
||||||
# Looks like {'jacob2': ['5'], '7': ['3']}
|
|
||||||
for dictvar in (var.KILLS,):
|
|
||||||
kvp = []
|
|
||||||
for a,b in dictvar.items():
|
|
||||||
nl = []
|
|
||||||
for n in b:
|
|
||||||
if n == prefix:
|
|
||||||
n = nick
|
|
||||||
nl.append(n)
|
|
||||||
if a == prefix:
|
|
||||||
a = nick
|
|
||||||
kvp.append((a,nl))
|
|
||||||
dictvar.update(kvp)
|
|
||||||
if prefix in dictvar.keys():
|
|
||||||
del dictvar[prefix]
|
|
||||||
# Looks like {'6': {'jacob3'}, 'jacob3': {'6'}}
|
# Looks like {'6': {'jacob3'}, 'jacob3': {'6'}}
|
||||||
for dictvar in (var.LOVERS, var.ORIGINAL_LOVERS, var.DULLAHAN_TARGETS):
|
for dictvar in (var.LOVERS, var.ORIGINAL_LOVERS, var.DULLAHAN_TARGETS):
|
||||||
kvp = []
|
kvp = []
|
||||||
@ -3596,7 +3574,7 @@ def rename_player(cli, prefix, nick):
|
|||||||
b = nick
|
b = nick
|
||||||
var.EXCHANGED_ROLES[idx] = (a, b)
|
var.EXCHANGED_ROLES[idx] = (a, b)
|
||||||
for setvar in (var.SEEN, var.HEXED, var.ASLEEP, var.DESPERATE, var.REVEALED, var.SILENCED, var.TOBESILENCED,
|
for setvar in (var.SEEN, var.HEXED, var.ASLEEP, var.DESPERATE, var.REVEALED, var.SILENCED, var.TOBESILENCED,
|
||||||
var.REVEALED_MAYORS, var.MATCHMAKERS, var.HUNTERS, var.PASSED, var.JESTERS, var.AMNESIACS,
|
var.REVEALED_MAYORS, var.MATCHMAKERS, var.PASSED, var.JESTERS, var.AMNESIACS,
|
||||||
var.INFLUENTIAL, var.LYCANTHROPES, var.TOBELYCANTHROPES, var.LUCKY, var.TOBELUCKY, var.SICK,
|
var.INFLUENTIAL, var.LYCANTHROPES, var.TOBELYCANTHROPES, var.LUCKY, var.TOBELUCKY, var.SICK,
|
||||||
var.DISEASED, var.TOBEDISEASED, var.RETRIBUTION, var.MISDIRECTED, var.TOBEMISDIRECTED,
|
var.DISEASED, var.TOBEDISEASED, var.RETRIBUTION, var.MISDIRECTED, var.TOBEMISDIRECTED,
|
||||||
var.EXCHANGED, var.IMMUNIZED, var.CURED_LYCANS, var.ALPHA_WOLVES, var.CURSED, var.CHARMERS,
|
var.EXCHANGED, var.IMMUNIZED, var.CURED_LYCANS, var.ALPHA_WOLVES, var.CURSED, var.CHARMERS,
|
||||||
@ -3827,8 +3805,7 @@ def begin_day(cli):
|
|||||||
|
|
||||||
# Reset nighttime variables
|
# Reset nighttime variables
|
||||||
var.GAMEPHASE = "day"
|
var.GAMEPHASE = "day"
|
||||||
var.KILLS = {} # nicknames of kill victims (wolves only)
|
var.OTHER_KILLS = {} # other kill victims (vigilante/vengeful ghost)
|
||||||
var.OTHER_KILLS = {} # other kill victims (hunter/vengeful ghost)
|
|
||||||
var.KILLER = "" # nickname of who chose the victim
|
var.KILLER = "" # nickname of who chose the victim
|
||||||
var.SEEN = set() # set of doomsayers that have had visions
|
var.SEEN = set() # set of doomsayers that have had visions
|
||||||
var.HEXED = set() # set of hags that have silenced others
|
var.HEXED = set() # set of hags that have silenced others
|
||||||
@ -4083,10 +4060,12 @@ def transition_day(cli, gameid=0):
|
|||||||
for crow, target in iter(var.OBSERVED.items()):
|
for crow, target in iter(var.OBSERVED.items()):
|
||||||
if crow not in var.ROLES["werecrow"]:
|
if crow not in var.ROLES["werecrow"]:
|
||||||
continue
|
continue
|
||||||
|
evt = Event("night_acted", {"acted": False})
|
||||||
|
evt.dispatch(cli, var, target, crow)
|
||||||
if ((target in var.HVISITED and var.HVISITED[target]) or target in var.SEEN or target in var.SHAMANS or
|
if ((target in var.HVISITED and var.HVISITED[target]) or target in var.SEEN or target in var.SHAMANS or
|
||||||
(target in var.GUARDED and var.GUARDED[target]) or target in var.OTHER_KILLS or
|
(target in var.GUARDED and var.GUARDED[target]) or target in var.OTHER_KILLS or
|
||||||
(target in var.PRAYED and var.PRAYED[target][0] > 0) or target in var.CHARMERS or
|
(target in var.PRAYED and var.PRAYED[target][0] > 0) or target in var.CHARMERS or
|
||||||
target in var.OBSERVED or target in var.KILLS or target in var.HEXED or target in var.CURSED):
|
target in var.OBSERVED or target in var.HEXED or target in var.CURSED or evt.data["acted"]):
|
||||||
pm(cli, crow, messages["werecrow_success"].format(target))
|
pm(cli, crow, messages["werecrow_success"].format(target))
|
||||||
else:
|
else:
|
||||||
pm(cli, crow, messages["werecrow_failure"].format(target))
|
pm(cli, crow, messages["werecrow_failure"].format(target))
|
||||||
@ -4102,63 +4081,29 @@ def transition_day(cli, gameid=0):
|
|||||||
var.NIGHT_TIMEDELTA += td
|
var.NIGHT_TIMEDELTA += td
|
||||||
min, sec = td.seconds // 60, td.seconds % 60
|
min, sec = td.seconds // 60, td.seconds % 60
|
||||||
|
|
||||||
found = defaultdict(int)
|
# built-in logic runs at the following priorities:
|
||||||
for v in var.KILLS.values():
|
# 1 = wolf kills
|
||||||
for p in v:
|
# 2 = non-wolf kills
|
||||||
found[p] += 1
|
# 3 = alpha wolf bite
|
||||||
|
# 4 = protections/fallen angel
|
||||||
maxc = 0
|
# 5 = rearranging victim list (ensure bodyguard/harlot messages plays),
|
||||||
victims = []
|
# fixing killers dict to have correct priority (wolf-side VG kills -> non-wolf kills -> wolf kills)
|
||||||
bitten = []
|
# Actually killing off the victims happens in transition_day_resolve
|
||||||
# dict of victim: list of killers (for retribution totem)
|
evt = Event("transition_day", {
|
||||||
killers = defaultdict(list)
|
"victims": [],
|
||||||
# wolves targeted, others may have as well (needed for harlot visit and maybe other things)
|
"killers": defaultdict(list),
|
||||||
bywolves = set()
|
"bywolves": set(),
|
||||||
# wolves and nobody else targeted (needed for lycan)
|
"onlybywolves": set(),
|
||||||
onlybywolves = set()
|
"protected": {},
|
||||||
|
"bitten": []
|
||||||
dups = []
|
})
|
||||||
for v, c in found.items():
|
evt.dispatch(cli, var)
|
||||||
if c > maxc:
|
victims = evt.data["victims"]
|
||||||
maxc = c
|
killers = evt.data["killers"]
|
||||||
dups = [v]
|
bywolves = evt.data["bywolves"]
|
||||||
elif c == maxc:
|
onlybywolves = evt.data["onlybywolves"]
|
||||||
dups.append(v)
|
protected = evt.data["protected"]
|
||||||
|
bitten = evt.data["bitten"]
|
||||||
if maxc and dups:
|
|
||||||
victim = random.choice(dups)
|
|
||||||
victims.append(victim)
|
|
||||||
bywolves.add(victim)
|
|
||||||
onlybywolves.add(victim)
|
|
||||||
# special key to let us know to randomly select a wolf
|
|
||||||
killers[victim].append("@wolves")
|
|
||||||
|
|
||||||
|
|
||||||
if victims and var.ANGRY_WOLVES:
|
|
||||||
# they got a 2nd kill
|
|
||||||
del found[victims[0]]
|
|
||||||
maxc = 0
|
|
||||||
dups = []
|
|
||||||
for v, c in found.items():
|
|
||||||
if c > maxc:
|
|
||||||
maxc = c
|
|
||||||
dups = [v]
|
|
||||||
elif c == maxc:
|
|
||||||
dups.append(v)
|
|
||||||
if maxc and dups:
|
|
||||||
victim = random.choice(dups)
|
|
||||||
victims.append(victim)
|
|
||||||
bywolves.add(victim)
|
|
||||||
onlybywolves.add(victim)
|
|
||||||
# special key to let us know to randomly select a wolf
|
|
||||||
killers[victim].append("@wolves")
|
|
||||||
|
|
||||||
if len(var.ROLES["fallen angel"]) == 0:
|
|
||||||
for monster in var.ROLES["monster"]:
|
|
||||||
if monster in victims:
|
|
||||||
victims.remove(monster)
|
|
||||||
bywolves.discard(monster)
|
|
||||||
onlybywolves.discard(monster)
|
|
||||||
|
|
||||||
wolfghostvictims = []
|
wolfghostvictims = []
|
||||||
for k, d in var.OTHER_KILLS.items():
|
for k, d in var.OTHER_KILLS.items():
|
||||||
@ -4174,7 +4119,6 @@ def transition_day(cli, gameid=0):
|
|||||||
for v in var.ENTRANCED_DYING:
|
for v in var.ENTRANCED_DYING:
|
||||||
var.DYING.add(v)
|
var.DYING.add(v)
|
||||||
|
|
||||||
# clear list so that it doesn't pm hunter / ghost about being able to kill again
|
|
||||||
var.OTHER_KILLS = {}
|
var.OTHER_KILLS = {}
|
||||||
|
|
||||||
for k, d in var.DEATH_TOTEM:
|
for k, d in var.DEATH_TOTEM:
|
||||||
@ -4701,16 +4645,14 @@ def chk_nightdone(cli):
|
|||||||
# TODO: alphabetize and/or arrange sensibly
|
# TODO: alphabetize and/or arrange sensibly
|
||||||
pl = list_players()
|
pl = list_players()
|
||||||
spl = set(pl)
|
spl = set(pl)
|
||||||
actedcount = sum(map(len, (var.SEEN, var.HVISITED, var.GUARDED, var.KILLS,
|
actedcount = sum(map(len, (var.SEEN, var.HVISITED, var.GUARDED,
|
||||||
var.OTHER_KILLS, var.PASSED, var.OBSERVED,
|
var.OTHER_KILLS, var.PASSED, var.OBSERVED,
|
||||||
var.HEXED, var.SHAMANS, var.CURSED, var.CHARMERS)))
|
var.HEXED, var.SHAMANS, var.CURSED, var.CHARMERS)))
|
||||||
|
|
||||||
nightroles = get_roles("harlot", "succubus", "bodyguard",
|
nightroles = get_roles("harlot", "succubus", "bodyguard", "guardian angel",
|
||||||
"guardian angel", "wolf", "werecrow", "alpha wolf",
|
"sorcerer", "hag", "shaman", "crazed shaman",
|
||||||
"sorcerer", "hunter", "hag", "shaman", "crazed shaman",
|
"warlock", "piper", "vigilante", "doomsayer",
|
||||||
"werekitten", "warlock", "piper", "wolf mystic",
|
"prophet", "wolf shaman")
|
||||||
"fallen angel", "vigilante", "doomsayer", "doomsayer", # NOT a mistake, doomsayer MUST be listed twice
|
|
||||||
"prophet", "wolf shaman", "wolf shaman") # wolf shaman also must be listed twice
|
|
||||||
|
|
||||||
for ghost, against in var.VENGEFUL_GHOSTS.items():
|
for ghost, against in var.VENGEFUL_GHOSTS.items():
|
||||||
if not against.startswith("!"):
|
if not against.startswith("!"):
|
||||||
@ -4734,22 +4676,11 @@ def chk_nightdone(cli):
|
|||||||
actedcount += len(var.MATCHMAKERS | var.CLONED.keys())
|
actedcount += len(var.MATCHMAKERS | var.CLONED.keys())
|
||||||
nightroles.extend(get_roles("matchmaker", "clone"))
|
nightroles.extend(get_roles("matchmaker", "clone"))
|
||||||
|
|
||||||
if var.DISEASED_WOLVES:
|
if var.ALPHA_ENABLED:
|
||||||
nightroles = [p for p in nightroles if p not in list_players(var.WOLF_ROLES - {"wolf cub", "werecrow", "doomsayer"})]
|
|
||||||
# only remove 1 doomsayer instance to indicate they cannot kill but can still see
|
|
||||||
for p in var.ROLES["doomsayer"]:
|
|
||||||
nightroles.remove(p)
|
|
||||||
elif var.ALPHA_ENABLED:
|
|
||||||
# alphas both kill and bite if they're activated at night, so add them into the counts
|
# alphas both kill and bite if they're activated at night, so add them into the counts
|
||||||
nightroles.extend(get_roles("alpha wolf"))
|
nightroles.extend(get_roles("alpha wolf"))
|
||||||
actedcount += len([p for p in var.ALPHA_WOLVES if p in var.ROLES["alpha wolf"]])
|
actedcount += len([p for p in var.ALPHA_WOLVES if p in var.ROLES["alpha wolf"]])
|
||||||
|
|
||||||
for p in var.HUNTERS:
|
|
||||||
# only remove one instance of their name if they have used hunter ability, in case they have templates
|
|
||||||
# the OTHER_KILLS check ensures we only remove them if they acted in a *previous* night
|
|
||||||
if p in var.ROLES["hunter"] and p not in var.OTHER_KILLS:
|
|
||||||
nightroles.remove(p)
|
|
||||||
|
|
||||||
# but remove all instances of their name if they are silenced
|
# but remove all instances of their name if they are silenced
|
||||||
nightroles = [p for p in nightroles if p not in var.SILENCED]
|
nightroles = [p for p in nightroles if p not in var.SILENCED]
|
||||||
|
|
||||||
@ -4777,21 +4708,6 @@ def chk_nightdone(cli):
|
|||||||
for ass in var.ROLES["assassin"]:
|
for ass in var.ROLES["assassin"]:
|
||||||
if ass not in var.TARGETED.keys() | var.SILENCED:
|
if ass not in var.TARGETED.keys() | var.SILENCED:
|
||||||
return
|
return
|
||||||
if not var.DISEASED_WOLVES:
|
|
||||||
# flatten var.KILLS
|
|
||||||
kills = set()
|
|
||||||
for ls in var.KILLS.values():
|
|
||||||
if not isinstance(ls, str):
|
|
||||||
kills.update(ls)
|
|
||||||
else:
|
|
||||||
kills.add(ls)
|
|
||||||
# check if wolves are actually agreeing
|
|
||||||
# allow len(kills) == 0 through as that means that crow was dumb and observed instead
|
|
||||||
# of killingor alpha wolf was alone and chose to bite instead of kill
|
|
||||||
if not var.ANGRY_WOLVES and len(kills) > 1:
|
|
||||||
return
|
|
||||||
elif var.ANGRY_WOLVES and (len(kills) == 1 or len(kills) > 2):
|
|
||||||
return
|
|
||||||
|
|
||||||
for x, t in var.TIMERS.items():
|
for x, t in var.TIMERS.items():
|
||||||
t[0].cancel()
|
t[0].cancel()
|
||||||
@ -4980,13 +4896,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
del var.SHAMANS[actor]
|
del var.SHAMANS[actor]
|
||||||
if actor in var.LASTGIVEN:
|
if actor in var.LASTGIVEN:
|
||||||
del var.LASTGIVEN[actor]
|
del var.LASTGIVEN[actor]
|
||||||
elif actor_role in var.WOLF_ROLES - {"werecrow", "wolf cub", "alpha wolf", "doomsayer"}:
|
|
||||||
if actor in var.KILLS:
|
|
||||||
del var.KILLS[actor]
|
|
||||||
elif actor_role == "hunter":
|
|
||||||
if actor in var.OTHER_KILLS:
|
|
||||||
del var.OTHER_KILLS[actor]
|
|
||||||
var.HUNTERS.discard(actor)
|
|
||||||
elif actor_role in ("bodyguard", "guardian angel"):
|
elif actor_role in ("bodyguard", "guardian angel"):
|
||||||
if actor in var.GUARDED:
|
if actor in var.GUARDED:
|
||||||
pm(cli, var.GUARDED.pop(actor), messages["protector_disappeared"])
|
pm(cli, var.GUARDED.pop(actor), messages["protector_disappeared"])
|
||||||
@ -4995,8 +4904,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
elif actor_role in ("werecrow", "sorcerer"):
|
elif actor_role in ("werecrow", "sorcerer"):
|
||||||
if actor in var.OBSERVED:
|
if actor in var.OBSERVED:
|
||||||
del var.OBSERVED[actor]
|
del var.OBSERVED[actor]
|
||||||
if actor in var.KILLS:
|
|
||||||
del var.KILLS[actor]
|
|
||||||
elif actor_role == "harlot":
|
elif actor_role == "harlot":
|
||||||
if actor in var.HVISITED:
|
if actor in var.HVISITED:
|
||||||
if var.HVISITED[actor] is not None:
|
if var.HVISITED[actor] is not None:
|
||||||
@ -5015,12 +4922,8 @@ def check_exchange(cli, actor, nick):
|
|||||||
var.DOCTORS[nick] = var.DOCTORS.pop(actor)
|
var.DOCTORS[nick] = var.DOCTORS.pop(actor)
|
||||||
elif actor_role == "alpha wolf":
|
elif actor_role == "alpha wolf":
|
||||||
var.ALPHA_WOLVES.discard(actor)
|
var.ALPHA_WOLVES.discard(actor)
|
||||||
if actor in var.KILLS:
|
|
||||||
del var.KILLS[actor]
|
|
||||||
elif actor_role == "doomsayer":
|
elif actor_role == "doomsayer":
|
||||||
var.SEEN.discard(actor)
|
var.SEEN.discard(actor)
|
||||||
if actor in var.KILLS:
|
|
||||||
del var.KILLS[actor]
|
|
||||||
elif actor_role == "warlock":
|
elif actor_role == "warlock":
|
||||||
var.CURSED.discard(actor)
|
var.CURSED.discard(actor)
|
||||||
elif actor_role == "turncoat":
|
elif actor_role == "turncoat":
|
||||||
@ -5046,13 +4949,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
del var.SHAMANS[nick]
|
del var.SHAMANS[nick]
|
||||||
if nick in var.LASTGIVEN:
|
if nick in var.LASTGIVEN:
|
||||||
del var.LASTGIVEN[nick]
|
del var.LASTGIVEN[nick]
|
||||||
elif nick_role in var.WOLF_ROLES - {"werecrow", "wolf cub", "alpha wolf", "doomsayer"}:
|
|
||||||
if nick in var.KILLS:
|
|
||||||
del var.KILLS[nick]
|
|
||||||
elif nick_role == "hunter":
|
|
||||||
if nick in var.OTHER_KILLS:
|
|
||||||
del var.OTHER_KILLS[nick]
|
|
||||||
var.HUNTERS.discard(nick)
|
|
||||||
elif nick_role in ("bodyguard", "guardian angel"):
|
elif nick_role in ("bodyguard", "guardian angel"):
|
||||||
if nick in var.GUARDED:
|
if nick in var.GUARDED:
|
||||||
pm(cli, var.GUARDED.pop(nick), messages["protector_disappeared"])
|
pm(cli, var.GUARDED.pop(nick), messages["protector_disappeared"])
|
||||||
@ -5061,8 +4957,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
elif nick_role in ("werecrow", "sorcerer"):
|
elif nick_role in ("werecrow", "sorcerer"):
|
||||||
if nick in var.OBSERVED:
|
if nick in var.OBSERVED:
|
||||||
del var.OBSERVED[nick]
|
del var.OBSERVED[nick]
|
||||||
if nick in var.KILLS:
|
|
||||||
del var.KILLS[nick]
|
|
||||||
elif nick_role == "harlot":
|
elif nick_role == "harlot":
|
||||||
if nick in var.HVISITED:
|
if nick in var.HVISITED:
|
||||||
if var.HVISITED[nick] is not None:
|
if var.HVISITED[nick] is not None:
|
||||||
@ -5080,12 +4974,8 @@ def check_exchange(cli, actor, nick):
|
|||||||
var.DOCTORS[actor] = var.DOCTORS.pop(nick)
|
var.DOCTORS[actor] = var.DOCTORS.pop(nick)
|
||||||
elif nick_role == "alpha wolf":
|
elif nick_role == "alpha wolf":
|
||||||
var.ALPHA_WOLVES.discard(nick)
|
var.ALPHA_WOLVES.discard(nick)
|
||||||
if nick in var.KILLS:
|
|
||||||
del var.KILLS[nick]
|
|
||||||
elif nick_role == "doomsayer":
|
elif nick_role == "doomsayer":
|
||||||
var.SEEN.discard(nick)
|
var.SEEN.discard(nick)
|
||||||
if nick in var.KILLS:
|
|
||||||
del var.KILLS[nick]
|
|
||||||
elif nick_role == "warlock":
|
elif nick_role == "warlock":
|
||||||
var.CURSED.discard(nick)
|
var.CURSED.discard(nick)
|
||||||
elif nick_role == "turncoat":
|
elif nick_role == "turncoat":
|
||||||
@ -5121,15 +5011,15 @@ def check_exchange(cli, actor, nick):
|
|||||||
del var.LYCAN_ROLES[nick]
|
del var.LYCAN_ROLES[nick]
|
||||||
|
|
||||||
actor_rev_role = actor_role
|
actor_rev_role = actor_role
|
||||||
if actor_role == "vengeful ghost":
|
if actor_role in var.HIDDEN_ROLES:
|
||||||
actor_rev_role = var.DEFAULT_ROLE
|
actor_rev_role = var.DEFAULT_ROLE
|
||||||
elif actor_role == "time lord":
|
elif actor_role in var.HIDDEN_VILLAGERS:
|
||||||
actor_rev_role = "villager"
|
actor_rev_role = "villager"
|
||||||
|
|
||||||
nick_rev_role = nick_role
|
nick_rev_role = nick_role
|
||||||
if nick_role == "vengeful ghost":
|
if nick_role in var.HIDDEN_ROLES:
|
||||||
nick_rev_role = var.DEFAULT_ROLE
|
nick_rev_role = var.DEFAULT_ROLE
|
||||||
elif actor_role == "time lord":
|
elif actor_role in var.HIDDEN_VILLAGERS:
|
||||||
nick_rev_role = "villager"
|
nick_rev_role = "villager"
|
||||||
|
|
||||||
# don't say who, since misdirection/luck totem may have switched it
|
# don't say who, since misdirection/luck totem may have switched it
|
||||||
@ -5264,7 +5154,7 @@ def retract(cli, nick, chan, rest):
|
|||||||
|
|
||||||
if chan == nick: # PM, use different code
|
if chan == nick: # PM, use different code
|
||||||
role = get_role(nick)
|
role = get_role(nick)
|
||||||
if role not in var.WOLF_ROLES - {"wolf cub"} and role != "hunter" and nick not in var.VENGEFUL_GHOSTS.keys():
|
if role not in var.WOLF_ROLES - {"wolf cub"} and nick not in var.VENGEFUL_GHOSTS.keys():
|
||||||
return
|
return
|
||||||
if var.PHASE != "night":
|
if var.PHASE != "night":
|
||||||
return
|
return
|
||||||
@ -5272,17 +5162,9 @@ def retract(cli, nick, chan, rest):
|
|||||||
if var.OBSERVED.get(nick):
|
if var.OBSERVED.get(nick):
|
||||||
pm(cli, nick, (messages["werecrow_transformed"]))
|
pm(cli, nick, (messages["werecrow_transformed"]))
|
||||||
return
|
return
|
||||||
elif role == "hunter" and nick in var.HUNTERS and nick not in var.OTHER_KILLS.keys():
|
|
||||||
return
|
|
||||||
|
|
||||||
if role in var.WOLF_ROLES and nick in var.KILLS.keys():
|
if role not in var.WOLF_ROLES and nick in var.OTHER_KILLS.keys():
|
||||||
del var.KILLS[nick]
|
|
||||||
pm(cli, nick, messages["retracted_kill"])
|
|
||||||
relay_wolfchat_command(cli, nick, messages["wolfchat_retracted_kill"].format(nick), var.WOLF_ROLES - {"wolf cub"}, is_wolf_command=True, is_kill_command=True)
|
|
||||||
elif role not in var.WOLF_ROLES and nick in var.OTHER_KILLS.keys():
|
|
||||||
del var.OTHER_KILLS[nick]
|
del var.OTHER_KILLS[nick]
|
||||||
if role == "hunter":
|
|
||||||
var.HUNTERS.remove(nick)
|
|
||||||
pm(cli, nick, messages["retracted_kill"])
|
pm(cli, nick, messages["retracted_kill"])
|
||||||
elif role == "alpha wolf" and nick in var.BITE_PREFERENCES.keys():
|
elif role == "alpha wolf" and nick in var.BITE_PREFERENCES.keys():
|
||||||
del var.BITE_PREFERENCES[nick]
|
del var.BITE_PREFERENCES[nick]
|
||||||
@ -5291,8 +5173,6 @@ def retract(cli, nick, chan, rest):
|
|||||||
relay_wolfchat_command(cli, nick, messages["wolfchat_no_bite"].format(nick), ("alpha wolf",), is_wolf_command=True)
|
relay_wolfchat_command(cli, nick, messages["wolfchat_no_bite"].format(nick), ("alpha wolf",), is_wolf_command=True)
|
||||||
elif role == "alpha wolf" and var.ALPHA_ENABLED:
|
elif role == "alpha wolf" and var.ALPHA_ENABLED:
|
||||||
pm(cli, nick, messages["kill_bite_pending"])
|
pm(cli, nick, messages["kill_bite_pending"])
|
||||||
else:
|
|
||||||
pm(cli, nick, messages["kill_pending"])
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if var.PHASE != "day":
|
if var.PHASE != "day":
|
||||||
@ -5413,10 +5293,7 @@ def kill(cli, nick, chan, rest):
|
|||||||
role = get_role(nick)
|
role = get_role(nick)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
role = None
|
role = None
|
||||||
wolfroles = var.WOLF_ROLES - {"wolf cub"}
|
if role not in {"dullahan", "vigilante"} and nick not in var.VENGEFUL_GHOSTS.keys():
|
||||||
if role in var.WOLFCHAT_ROLES and role not in wolfroles:
|
|
||||||
return # they do this a lot.
|
|
||||||
if role not in wolfroles | {"hunter", "dullahan", "vigilante"} and nick not in var.VENGEFUL_GHOSTS.keys():
|
|
||||||
return
|
return
|
||||||
if nick in var.VENGEFUL_GHOSTS.keys() and var.VENGEFUL_GHOSTS[nick][0] == "!":
|
if nick in var.VENGEFUL_GHOSTS.keys() and var.VENGEFUL_GHOSTS[nick][0] == "!":
|
||||||
# ghost was driven away by retribution
|
# ghost was driven away by retribution
|
||||||
@ -5425,31 +5302,11 @@ def kill(cli, nick, chan, rest):
|
|||||||
# all their targets are dead
|
# all their targets are dead
|
||||||
pm(cli, nick, messages["dullahan_targets_dead"])
|
pm(cli, nick, messages["dullahan_targets_dead"])
|
||||||
return
|
return
|
||||||
if role == "hunter" and nick in var.HUNTERS and nick not in var.OTHER_KILLS:
|
|
||||||
# they are a hunter and did not kill this night (if they killed this night, this allows them to switch)
|
|
||||||
pm(cli, nick, messages["hunter_already_killed"])
|
|
||||||
return
|
|
||||||
if nick in var.SILENCED:
|
if nick in var.SILENCED:
|
||||||
pm(cli, nick, messages["silenced"])
|
pm(cli, nick, messages["silenced"])
|
||||||
return
|
return
|
||||||
if role in wolfroles and var.DISEASED_WOLVES:
|
|
||||||
pm(cli, nick, messages["ill_wolves"])
|
|
||||||
return
|
|
||||||
pieces = re.split(" +",rest)
|
pieces = re.split(" +",rest)
|
||||||
victim = pieces[0]
|
victim = pieces[0]
|
||||||
victim2 = None
|
|
||||||
if role in wolfroles and var.ANGRY_WOLVES:
|
|
||||||
if len(pieces) > 1:
|
|
||||||
if len(pieces) > 2 and pieces[1].lower() == "and":
|
|
||||||
victim2 = pieces[2]
|
|
||||||
else:
|
|
||||||
victim2 = pieces[1]
|
|
||||||
else:
|
|
||||||
victim2 = None
|
|
||||||
if role == "werecrow": # Check if flying to observe
|
|
||||||
if var.OBSERVED.get(nick):
|
|
||||||
pm(cli, nick, (messages["werecrow_transformed_nokill"]))
|
|
||||||
return
|
|
||||||
|
|
||||||
victim = get_victim(cli, nick, victim, False)
|
victim = get_victim(cli, nick, victim, False)
|
||||||
if not victim:
|
if not victim:
|
||||||
@ -5457,15 +5314,8 @@ def kill(cli, nick, chan, rest):
|
|||||||
if is_safe(nick, victim):
|
if is_safe(nick, victim):
|
||||||
pm(cli, nick, messages["no_acting_on_succubus"].format("kill"))
|
pm(cli, nick, messages["no_acting_on_succubus"].format("kill"))
|
||||||
return
|
return
|
||||||
if victim2 != None:
|
|
||||||
victim2 = get_victim(cli, nick, victim2, False)
|
|
||||||
if not victim2:
|
|
||||||
return
|
|
||||||
if is_safe(nick, victim2):
|
|
||||||
pm(cli, nick, messages["no_acting_on_succubus"].format("kill"))
|
|
||||||
return
|
|
||||||
|
|
||||||
if victim == nick or victim2 == nick:
|
if victim == nick:
|
||||||
if nick in var.VENGEFUL_GHOSTS.keys():
|
if nick in var.VENGEFUL_GHOSTS.keys():
|
||||||
pm(cli, nick, messages["player_dead"])
|
pm(cli, nick, messages["player_dead"])
|
||||||
else:
|
else:
|
||||||
@ -5481,53 +5331,16 @@ def kill(cli, nick, chan, rest):
|
|||||||
pm(cli, nick, messages["vengeful_ghost_villager"])
|
pm(cli, nick, messages["vengeful_ghost_villager"])
|
||||||
return
|
return
|
||||||
|
|
||||||
if role in wolfroles:
|
rv = choose_target(nick, victim)
|
||||||
if in_wolflist(nick, victim) or (victim2 is not None and in_wolflist(nick, victim2)):
|
if nick not in var.VENGEFUL_GHOSTS.keys():
|
||||||
pm(cli, nick, messages["wolf_no_target_wolf"])
|
if check_exchange(cli, nick, rv):
|
||||||
return
|
return
|
||||||
if var.ANGRY_WOLVES and victim2 is not None:
|
var.OTHER_KILLS[nick] = rv
|
||||||
if victim == victim2:
|
|
||||||
pm(cli, nick, messages["wolf_must_target_multiple"])
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
rv = choose_target(nick, victim)
|
|
||||||
rv2 = choose_target(nick, victim2)
|
|
||||||
if check_exchange(cli, nick, rv):
|
|
||||||
return
|
|
||||||
if check_exchange(cli, nick, rv2):
|
|
||||||
return
|
|
||||||
var.KILLS[nick] = [rv, rv2]
|
|
||||||
else:
|
|
||||||
rv = choose_target(nick, victim)
|
|
||||||
if check_exchange(cli, nick, rv):
|
|
||||||
return
|
|
||||||
var.KILLS[nick] = [rv]
|
|
||||||
else:
|
|
||||||
rv = choose_target(nick, victim)
|
|
||||||
if nick not in var.VENGEFUL_GHOSTS.keys():
|
|
||||||
if check_exchange(cli, nick, rv):
|
|
||||||
return
|
|
||||||
var.OTHER_KILLS[nick] = rv
|
|
||||||
if role == "hunter":
|
|
||||||
var.HUNTERS.add(nick)
|
|
||||||
var.PASSED.discard(nick)
|
|
||||||
|
|
||||||
if victim2 != None:
|
msg = messages["wolf_target"].format(victim)
|
||||||
msg = messages["wolf_target_multiple"].format(victim, victim2)
|
pm(cli, nick, messages["player"].format(msg))
|
||||||
pm(cli, nick, messages["player"].format(msg))
|
|
||||||
else:
|
|
||||||
msg = messages["wolf_target"].format(victim)
|
|
||||||
pm(cli, nick, messages["player"].format(msg))
|
|
||||||
if var.ANGRY_WOLVES and role in wolfroles:
|
|
||||||
pm(cli, nick, messages["wolf_target_second"])
|
|
||||||
|
|
||||||
if in_wolflist(nick, nick):
|
debuglog("{0} ({1}) KILL: {2} ({3})".format(nick, role, victim, get_role(victim)))
|
||||||
relay_wolfchat_command(cli, nick, messages["wolfchat"].format(nick, msg), var.WOLF_ROLES - {"wolf cub"}, is_wolf_command=True, is_kill_command=True)
|
|
||||||
|
|
||||||
if victim2:
|
|
||||||
debuglog("{0} ({1}) KILL: {2} and {3} ({4})".format(nick, role, victim, victim2, get_role(victim2)))
|
|
||||||
else:
|
|
||||||
debuglog("{0} ({1}) KILL: {2} ({3})".format(nick, role, victim, get_role(victim)))
|
|
||||||
|
|
||||||
chk_nightdone(cli)
|
chk_nightdone(cli)
|
||||||
|
|
||||||
@ -5652,8 +5465,10 @@ def observe(cli, nick, chan, rest):
|
|||||||
if check_exchange(cli, nick, victim):
|
if check_exchange(cli, nick, victim):
|
||||||
return
|
return
|
||||||
var.OBSERVED[nick] = victim
|
var.OBSERVED[nick] = victim
|
||||||
if nick in var.KILLS.keys():
|
# temp hack, will do something better once crow is split off
|
||||||
del var.KILLS[nick]
|
from src.roles import wolf
|
||||||
|
if nick in wolf.KILLS:
|
||||||
|
del wolf.KILLS[nick]
|
||||||
if role == "werecrow":
|
if role == "werecrow":
|
||||||
pm(cli, nick, messages["werecrow_observe_success"].format(victim))
|
pm(cli, nick, messages["werecrow_observe_success"].format(victim))
|
||||||
relay_wolfchat_command(cli, nick, messages["wolfchat_observe"].format(nick, victim), ("werecrow",), is_wolf_command=True)
|
relay_wolfchat_command(cli, nick, messages["wolfchat_observe"].format(nick, victim), ("werecrow",), is_wolf_command=True)
|
||||||
@ -5845,7 +5660,6 @@ def hvisit(cli, nick, chan, rest):
|
|||||||
if var.OTHER_KILLS.get(victim) in var.ROLES["succubus"]:
|
if var.OTHER_KILLS.get(victim) in var.ROLES["succubus"]:
|
||||||
pm(cli, victim, messages["no_kill_succubus"].format(var.OTHER_KILLS[victim]))
|
pm(cli, victim, messages["no_kill_succubus"].format(var.OTHER_KILLS[victim]))
|
||||||
del var.OTHER_KILLS[victim]
|
del var.OTHER_KILLS[victim]
|
||||||
var.HUNTERS.discard(victim)
|
|
||||||
if var.TARGETED.get(victim) in var.ROLES["succubus"]:
|
if var.TARGETED.get(victim) in var.ROLES["succubus"]:
|
||||||
msg = messages["no_target_succubus"].format(var.TARGETED[victim])
|
msg = messages["no_target_succubus"].format(var.TARGETED[victim])
|
||||||
del var.TARGETED[victim]
|
del var.TARGETED[victim]
|
||||||
@ -5863,13 +5677,19 @@ def hvisit(cli, nick, chan, rest):
|
|||||||
var.TOBESILENCED.remove(nick)
|
var.TOBESILENCED.remove(nick)
|
||||||
var.HEXED.remove(victim)
|
var.HEXED.remove(victim)
|
||||||
del var.LASTHEXED[victim]
|
del var.LASTHEXED[victim]
|
||||||
if set(var.KILLS.get(victim, ())) & var.ROLES["succubus"]:
|
# temp hack, will do something better once succubus is split off
|
||||||
|
from src.roles import wolf, hunter
|
||||||
|
if set(wolf.KILLS.get(victim, ())) & var.ROLES["succubus"]:
|
||||||
for s in var.ROLES["succubus"]:
|
for s in var.ROLES["succubus"]:
|
||||||
if s in var.KILLS[victim]:
|
if s in wolf.KILLS[victim]:
|
||||||
pm(cli, victim, messages["no_kill_succubus"].format(nick))
|
pm(cli, victim, messages["no_kill_succubus"].format(nick))
|
||||||
var.KILLS[victim].remove(s)
|
wolf.KILLS[victim].remove(s)
|
||||||
if not var.KILLS[victim]:
|
if not wolf.KILLS[victim]:
|
||||||
del var.KILLS[victim]
|
del wolf.KILLS[victim]
|
||||||
|
if hunter.KILLS.get(victim) in var.ROLES["succubus"]:
|
||||||
|
pm(cli, victim, messages["no_kill_succubus"].format(hunter.KILLS[victim]))
|
||||||
|
del hunter.KILLS[victim]
|
||||||
|
hunter.HUNTERS.discard(victim)
|
||||||
if var.BITE_PREFERENCES.get(victim) in var.ROLES["succubus"]:
|
if var.BITE_PREFERENCES.get(victim) in var.ROLES["succubus"]:
|
||||||
pm(cli, victim, messages["no_kill_succubus"].format(var.BITE_PREFERENCES[victim]))
|
pm(cli, victim, messages["no_kill_succubus"].format(var.BITE_PREFERENCES[victim]))
|
||||||
del var.BITE_PREFERENCES[victim]
|
del var.BITE_PREFERENCES[victim]
|
||||||
@ -6027,7 +5847,7 @@ def bite_cmd(cli, nick, chan, rest):
|
|||||||
chk_nightdone(cli)
|
chk_nightdone(cli)
|
||||||
|
|
||||||
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",),
|
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",),
|
||||||
roles=("hunter", "harlot", "bodyguard", "guardian angel", "turncoat", "warlock", "piper", "succubus", "vigilante"))
|
roles=("harlot", "bodyguard", "guardian angel", "turncoat", "warlock", "piper", "succubus", "vigilante"))
|
||||||
def pass_cmd(cli, nick, chan, rest):
|
def pass_cmd(cli, nick, chan, rest):
|
||||||
"""Decline to use your special power for that night."""
|
"""Decline to use your special power for that night."""
|
||||||
nickrole = get_role(nick)
|
nickrole = get_role(nick)
|
||||||
@ -6040,17 +5860,7 @@ def pass_cmd(cli, nick, chan, rest):
|
|||||||
cli.notice(nick, messages["silenced"])
|
cli.notice(nick, messages["silenced"])
|
||||||
return
|
return
|
||||||
|
|
||||||
if nickrole == "hunter":
|
if nickrole == "harlot":
|
||||||
if nick in var.OTHER_KILLS.keys():
|
|
||||||
del var.OTHER_KILLS[nick]
|
|
||||||
var.HUNTERS.remove(nick)
|
|
||||||
if nick in var.HUNTERS:
|
|
||||||
pm(cli, nick, messages["hunter_already_killed"])
|
|
||||||
return
|
|
||||||
|
|
||||||
pm(cli, nick, messages["hunter_pass"])
|
|
||||||
var.PASSED.add(nick)
|
|
||||||
elif nickrole == "harlot":
|
|
||||||
if var.HVISITED.get(nick):
|
if var.HVISITED.get(nick):
|
||||||
pm(cli, nick, (messages["harlot_already_visited"]).format(var.HVISITED[nick]))
|
pm(cli, nick, (messages["harlot_already_visited"]).format(var.HVISITED[nick]))
|
||||||
return
|
return
|
||||||
@ -6563,14 +6373,13 @@ def transition_night(cli):
|
|||||||
var.TIMERS = {}
|
var.TIMERS = {}
|
||||||
|
|
||||||
# Reset nighttime variables
|
# Reset nighttime variables
|
||||||
var.KILLS = {}
|
|
||||||
var.GUARDED = {} # key = by whom, value = the person that is visited
|
var.GUARDED = {} # key = by whom, value = the person that is visited
|
||||||
var.KILLER = "" # nickname of who chose the victim
|
var.KILLER = "" # nickname of who chose the victim
|
||||||
var.SEEN = set() # set of seers that have had visions
|
var.SEEN = set() # set of seers that have had visions
|
||||||
var.HEXED = set() # set of hags that have hexed
|
var.HEXED = set() # set of hags that have hexed
|
||||||
var.CURSED = set() # set of warlocks that have cursed
|
var.CURSED = set() # set of warlocks that have cursed
|
||||||
var.SHAMANS = {}
|
var.SHAMANS = {}
|
||||||
var.PASSED = set() # set of hunters that have chosen not to kill
|
var.PASSED = set()
|
||||||
var.OBSERVED = {} # those whom werecrows have observed
|
var.OBSERVED = {} # those whom werecrows have observed
|
||||||
var.CHARMERS = set() # pipers who have charmed
|
var.CHARMERS = set() # pipers who have charmed
|
||||||
var.HVISITED = {}
|
var.HVISITED = {}
|
||||||
@ -6638,9 +6447,9 @@ def transition_night(cli):
|
|||||||
if var.FIRST_NIGHT: # we don't need to tell them twice if they remember right away
|
if var.FIRST_NIGHT: # we don't need to tell them twice if they remember right away
|
||||||
continue
|
continue
|
||||||
showrole = amnrole
|
showrole = amnrole
|
||||||
if showrole == "time lord":
|
if showrole in var.HIDDEN_VILLAGERS:
|
||||||
showrole = "villager"
|
showrole = "villager"
|
||||||
elif showrole == "vengeful ghost":
|
elif showrole in var.HIDDEN_ROLES:
|
||||||
showrole = var.DEFAULT_ROLE
|
showrole = var.DEFAULT_ROLE
|
||||||
n = ""
|
n = ""
|
||||||
if showrole.startswith(("a", "e", "i", "o", "u")):
|
if showrole.startswith(("a", "e", "i", "o", "u")):
|
||||||
@ -6665,78 +6474,6 @@ def transition_night(cli):
|
|||||||
|
|
||||||
# send PMs
|
# send PMs
|
||||||
ps = list_players()
|
ps = list_players()
|
||||||
wolves = list_players(var.WOLFCHAT_ROLES)
|
|
||||||
for wolf in wolves:
|
|
||||||
normal_notify = wolf in var.PLAYERS and not is_user_simple(wolf)
|
|
||||||
role = get_role(wolf)
|
|
||||||
cursed = "cursed " if wolf in var.ROLES["cursed villager"] else ""
|
|
||||||
|
|
||||||
if normal_notify:
|
|
||||||
if role == "wolf":
|
|
||||||
pm(cli, wolf, messages["wolf_notify"])
|
|
||||||
elif role == "traitor":
|
|
||||||
if cursed:
|
|
||||||
pm(cli, wolf, messages["cursed_traitor_notify"])
|
|
||||||
else:
|
|
||||||
pm(cli, wolf, messages["traitor_notify"])
|
|
||||||
elif role == "werecrow":
|
|
||||||
pm(cli, wolf, messages["werecrow_notify"])
|
|
||||||
elif role == "hag":
|
|
||||||
pm(cli, wolf, messages["hag_notify"].format(cursed))
|
|
||||||
elif role == "sorcerer":
|
|
||||||
pm(cli, wolf, messages["sorcerer_notify"].format(cursed))
|
|
||||||
elif role == "wolf cub":
|
|
||||||
pm(cli, wolf, messages["wolf_cub_notify"])
|
|
||||||
elif role == "alpha wolf":
|
|
||||||
pm(cli, wolf, messages["alpha_wolf_notify"])
|
|
||||||
elif role == "werekitten":
|
|
||||||
pm(cli, wolf, messages["werekitten_notify"])
|
|
||||||
elif role == "warlock":
|
|
||||||
pm(cli, wolf, messages["warlock_notify"].format(cursed))
|
|
||||||
elif role == "wolf mystic":
|
|
||||||
pm(cli, wolf, messages["wolf_mystic_notify"])
|
|
||||||
elif role == "wolf shaman":
|
|
||||||
pm(cli, wolf, messages["wolf_shaman_notify"])
|
|
||||||
elif role == "fallen angel":
|
|
||||||
pm(cli, wolf, messages["fallen_angel_notify"])
|
|
||||||
elif role == "doomsayer":
|
|
||||||
pm(cli, wolf, messages["doomsayer_notify"])
|
|
||||||
else:
|
|
||||||
# catchall in case we forgot something above
|
|
||||||
an = 'n' if role.startswith(("a", "e", "i", "o", "u")) else ""
|
|
||||||
pm(cli, wolf, messages["undefined_role_notify"].format(an, role))
|
|
||||||
|
|
||||||
if len(wolves) > 1:
|
|
||||||
pm(cli, wolf, messages["wolfchat_notify"])
|
|
||||||
else:
|
|
||||||
an = "n" if cursed == "" and role.startswith(("a", "e", "i", "o", "u")) else ""
|
|
||||||
pm(cli, wolf, messages["wolf_simple"].format(an, cursed, role)) # !simple
|
|
||||||
|
|
||||||
pl = ps[:]
|
|
||||||
random.shuffle(pl)
|
|
||||||
pl.remove(wolf) # remove self from list
|
|
||||||
for i, player in enumerate(pl):
|
|
||||||
prole = get_role(player)
|
|
||||||
if prole in var.WOLFCHAT_ROLES:
|
|
||||||
cursed = ""
|
|
||||||
if player in var.ROLES["cursed villager"]:
|
|
||||||
cursed = "cursed "
|
|
||||||
pl[i] = "\u0002{0}\u0002 ({1}{2})".format(player, cursed, prole)
|
|
||||||
elif player in var.ROLES["cursed villager"]:
|
|
||||||
pl[i] = player + " (cursed)"
|
|
||||||
|
|
||||||
pm(cli, wolf, "Players: " + ", ".join(pl))
|
|
||||||
if role == "wolf mystic":
|
|
||||||
# if adding this info to !myrole, you will need to save off this count so that they can't get updated info until the next night
|
|
||||||
# # of special villagers = # of players - # of villagers - # of wolves - # of neutrals
|
|
||||||
numvills = len(ps) - len(list_players(var.WOLFTEAM_ROLES)) - len(list_players(("villager", "vengeful ghost", "time lord", "amnesiac", "lycan"))) - len(list_players(var.TRUE_NEUTRAL_ROLES))
|
|
||||||
pm(cli, wolf, messages["wolf_mystic_info"].format("are" if numvills != 1 else "is", numvills, "s" if numvills != 1 else ""))
|
|
||||||
if var.DISEASED_WOLVES:
|
|
||||||
pm(cli, wolf, messages["ill_wolves"])
|
|
||||||
elif var.ANGRY_WOLVES and role in var.WOLF_ROLES and role != "wolf cub":
|
|
||||||
pm(cli, wolf, messages["angry_wolves"])
|
|
||||||
if var.ALPHA_ENABLED and role == "alpha wolf" and wolf not in var.ALPHA_WOLVES:
|
|
||||||
pm(cli, wolf, messages["wolf_bite"])
|
|
||||||
|
|
||||||
for harlot in var.ROLES["harlot"]:
|
for harlot in var.ROLES["harlot"]:
|
||||||
pl = ps[:]
|
pl = ps[:]
|
||||||
@ -6896,18 +6633,6 @@ def transition_night(cli):
|
|||||||
if role not in var.WOLFCHAT_ROLES:
|
if role not in var.WOLFCHAT_ROLES:
|
||||||
pm(cli, shaman, "Players: " + ", ".join(pl))
|
pm(cli, shaman, "Players: " + ", ".join(pl))
|
||||||
|
|
||||||
for hunter in var.ROLES["hunter"]:
|
|
||||||
if hunter in var.HUNTERS:
|
|
||||||
continue #already killed
|
|
||||||
pl = ps[:]
|
|
||||||
random.shuffle(pl)
|
|
||||||
pl.remove(hunter)
|
|
||||||
if hunter in var.PLAYERS and not is_user_simple(hunter):
|
|
||||||
pm(cli, hunter, messages["hunter_notify"])
|
|
||||||
else:
|
|
||||||
pm(cli, hunter, messages["hunter_simple"])
|
|
||||||
pm(cli, hunter, "Players: " + ", ".join(pl))
|
|
||||||
|
|
||||||
for dullahan in var.ROLES["dullahan"]:
|
for dullahan in var.ROLES["dullahan"]:
|
||||||
targets = list(var.DULLAHAN_TARGETS[dullahan])
|
targets = list(var.DULLAHAN_TARGETS[dullahan])
|
||||||
for target in var.DEAD:
|
for target in var.DEAD:
|
||||||
@ -7118,25 +6843,6 @@ def transition_night(cli):
|
|||||||
pm(cli, minion, messages["minion_simple"])
|
pm(cli, minion, messages["minion_simple"])
|
||||||
pm(cli, minion, "Wolves: " + ", ".join(wolves))
|
pm(cli, minion, "Wolves: " + ", ".join(wolves))
|
||||||
|
|
||||||
villagers = copy.copy(var.ROLES["villager"])
|
|
||||||
villagers |= var.ROLES["time lord"]
|
|
||||||
if var.DEFAULT_ROLE == "villager":
|
|
||||||
villagers |= var.ROLES["vengeful ghost"] | var.ROLES["amnesiac"]
|
|
||||||
for villager in villagers:
|
|
||||||
if villager in var.PLAYERS and not is_user_simple(villager):
|
|
||||||
pm(cli, villager, messages["villager_notify"])
|
|
||||||
else:
|
|
||||||
pm(cli, villager, messages["villager_simple"])
|
|
||||||
|
|
||||||
cultists = copy.copy(var.ROLES["cultist"])
|
|
||||||
if var.DEFAULT_ROLE == "cultist":
|
|
||||||
cultists |= var.ROLES["vengeful ghost"] | var.ROLES["amnesiac"]
|
|
||||||
for cultist in cultists:
|
|
||||||
if cultist in var.PLAYERS and not is_user_simple(cultist):
|
|
||||||
pm(cli, cultist, messages["cultist_notify"])
|
|
||||||
else:
|
|
||||||
pm(cli, cultist, messages["cultist_simple"])
|
|
||||||
|
|
||||||
for blessed in var.ROLES["blessed villager"]:
|
for blessed in var.ROLES["blessed villager"]:
|
||||||
if blessed in var.PLAYERS and not is_user_simple(blessed):
|
if blessed in var.PLAYERS and not is_user_simple(blessed):
|
||||||
pm(cli, blessed, messages["blessed_notify"])
|
pm(cli, blessed, messages["blessed_notify"])
|
||||||
@ -7360,10 +7066,8 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
var.GUNNERS = {}
|
var.GUNNERS = {}
|
||||||
var.SEEN = set()
|
var.SEEN = set()
|
||||||
var.OBSERVED = {}
|
var.OBSERVED = {}
|
||||||
var.KILLS = {}
|
|
||||||
var.GUARDED = {}
|
var.GUARDED = {}
|
||||||
var.HVISITED = {}
|
var.HVISITED = {}
|
||||||
var.HUNTERS = set()
|
|
||||||
var.VENGEFUL_GHOSTS = {}
|
var.VENGEFUL_GHOSTS = {}
|
||||||
var.CLONED = {}
|
var.CLONED = {}
|
||||||
var.TARGETED = {}
|
var.TARGETED = {}
|
||||||
@ -8201,9 +7905,9 @@ def myrole(cli, nick, chan, rest):
|
|||||||
return
|
return
|
||||||
|
|
||||||
role = get_role(nick)
|
role = get_role(nick)
|
||||||
if role == "time lord":
|
if role in var.HIDDEN_VILLAGERS:
|
||||||
role = "villager"
|
role = "villager"
|
||||||
elif role in ("amnesiac", "vengeful ghost"):
|
elif role in var.HIDDEN_ROLES:
|
||||||
role = var.DEFAULT_ROLE
|
role = var.DEFAULT_ROLE
|
||||||
|
|
||||||
evt = Event("myrole", {"role": role, "messages": []})
|
evt = Event("myrole", {"role": role, "messages": []})
|
||||||
|
Loading…
Reference in New Issue
Block a user