Split doomsayer

This commit is contained in:
skizzerz 2016-08-17 11:41:28 -05:00
parent 3b2534d4a5
commit f66a1502dc
3 changed files with 159 additions and 88 deletions

144
src/roles/doomsayer.py Normal file
View File

@ -0,0 +1,144 @@
import re
import random
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
SEEN = set()
KILLS = {}
SICK = {}
LYCANS = {}
@cmd("see", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("doomsayer",))
def see(cli, nick, chan, rest):
"""Use your paranormal senses to determine a player's doom."""
role = get_role(nick)
if nick in SEEN:
pm(cli, nick, messages["seer_fail"])
return
victim = get_victim(cli, nick, re.split(" +",rest)[0], False)
if not victim:
return
if victim == nick:
pm(cli, nick, messages["no_see_self"])
return
if in_wolflist(nick, victim):
pm(cli, nick, messages["no_see_wolf"])
return
evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True})
evt.dispatch(cli, var, "see", nick, victim, frozenset({"detrimental", "immediate"}))
if evt.prevent_default:
return
victim = evt.data["target"]
victimrole = get_role(victim)
mode = random.randint(1, 3)
if mode == 1:
mode = "DEATH"
pm(cli, nick, messages["doomsayer_death"].format(victim))
KILLS[nick] = victim
elif mode == 2:
mode = "LYCAN"
pm(cli, nick, messages["doomsayer_lycan"].format(victim))
LYCANS[nick] = victim
elif mode == 3:
mode = "SICK"
pm(cli, nick, messages["doomsayer_sick"].format(victim))
SICK[nick] = victim
debuglog("{0} ({1}) SEE: {2} ({3}) - {4}".format(nick, role, victim, victimrole, mode))
relay_wolfchat_command(cli, nick, messages["doomsayer_wolfchat"].format(nick, victim), ("doomsayer",), is_wolf_command=True)
SEEN.add(nick)
chk_nightdone(cli)
@event_listener("rename_player")
def on_rename(evt, cli, var, prefix, nick):
if prefix in SEEN:
SEEN.remove(prefix)
SEEN.add(nick)
for dictvar in (KILLS, SICK, LYCANS):
kvp = []
for a, b in dictvar.items():
if a == prefix:
a = nick
if b == prefix:
b = nick
kvp.append((a, b))
dictvar.update(kvp)
if prefix in dictvar:
del dictvar[prefix]
@event_listener("night_acted")
def on_acted(evt, cli, var, nick, sender):
if nick in SEEN:
evt.data["acted"] = True
@event_listener("exchange_roles")
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):
if actor_role == "doomsayer" and nick_role != "doomsayer":
SEEN.discard(actor)
if actor in KILLS:
del KILLS[actor]
elif actor in SICK:
del SICK[actor]
elif actor in LYCANS:
del LYCANS[actor]
elif nick_role == "doomsayer" and actor_role != "doomsayer":
SEEN.discard(nick)
if nick in KILLS:
del KILLS[nick]
elif nick in SICK:
del SICK[nick]
elif nick in LYCANS:
del LYCANS[nick]
@event_listener("del_player")
def on_del_player(evt, cli, var, nick, nickrole, nicktpls, death_triggers):
SEEN.discard(nick)
for dictvar in (KILLS, SICK, LYCANS):
for k, v in list(dictvar.items()):
if nick == k or nick == v:
del dictvar[k]
@event_listener("chk_nightdone")
def on_chk_nightdone(evt, cli, var):
evt.data["actedcount"] += len(SEEN)
evt.data["nightroles"].extend(get_roles("doomsayer"))
@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)
# even though doomsayer is a wolf, remove from onlybywolves since
# that particular item indicates that they were the target of a wolf !kill.
# If doomsayer doesn't remove this, roles such as harlot or monster will not
# die if they are the target of a doomsayer !see that ends up killing the target.
evt.data["onlybywolves"].discard(d)
evt.data["killers"][d].append(k)
@event_listener("begin_day")
def on_begin_day(evt, cli, var):
var.DISEASED.update(SICK.values())
var.SILENCED.update(SICK.values())
var.LYCANTHROPES.update(LYCANS.values())
SEEN.clear()
KILLS.clear()
SICK.clear()
LYCANS.clear()
@event_listener("reset")
def on_reset(evt, var):
SEEN.clear()
KILLS.clear()
SICK.clear()
LYCANS.clear()
# vim: set sw=4 expandtab:

View File

@ -82,6 +82,10 @@ def on_rename(evt, cli, var, prefix, nick):
SEEN.remove(prefix)
SEEN.add(nick)
@event_listener("del_player")
def on_del_player(evt, cli, var, nick, nickrole, nicktpls, death_triggers):
SEEN.discard(nick)
@event_listener("night_acted")
def on_acted(evt, cli, var, nick, sender):
if nick in SEEN:

View File

@ -3136,12 +3136,6 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
for k in list(x):
if nick in (k, x[k][0]):
del x[k]
for k in list(var.OTHER_KILLS):
if var.OTHER_KILLS[k] == nick:
pm(cli, k, messages["hunter_discard"])
del var.OTHER_KILLS[k]
elif nick == k:
del var.OTHER_KILLS[k]
if nick in var.DISCONNECTED:
del var.DISCONNECTED[nick]
if nickrole == "succubus" and not var.ROLES["succubus"]:
@ -3153,7 +3147,7 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
# 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
# if these aren't cleared properly night may end prematurely
for x in (var.SEEN, var.PASSED, var.HEXED, var.MATCHMAKERS, var.CURSED, var.CHARMERS):
for x in (var.PASSED, var.HEXED, var.MATCHMAKERS, var.CURSED, var.CHARMERS):
x.discard(nick)
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
@ -3478,7 +3472,7 @@ def rename_player(cli, prefix, nick):
if prefix in var.PRAYED.keys():
del var.PRAYED[prefix]
for dictvar in (var.HVISITED, var.OBSERVED, var.GUARDED, var.OTHER_KILLS, var.TARGETED,
for dictvar in (var.HVISITED, var.OBSERVED, var.GUARDED, var.TARGETED,
var.CLONED, var.LASTGUARDED, var.LASTGIVEN, var.LASTHEXED,
var.BITE_PREFERENCES):
kvp = []
@ -3530,7 +3524,7 @@ def rename_player(cli, prefix, nick):
if b == prefix:
b = nick
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.HEXED, var.ASLEEP, var.DESPERATE, var.REVEALED, var.SILENCED, var.TOBESILENCED,
var.REVEALED_MAYORS, var.MATCHMAKERS, var.PASSED, var.JESTERS, var.AMNESIACS,
var.INFLUENTIAL, var.LYCANTHROPES, var.TOBELYCANTHROPES, var.LUCKY, var.TOBELUCKY, var.SICK,
var.DISEASED, var.TOBEDISEASED, var.RETRIBUTION, var.MISDIRECTED, var.TOBEMISDIRECTED,
@ -3762,9 +3756,7 @@ def begin_day(cli):
# Reset nighttime variables
var.GAMEPHASE = "day"
var.OTHER_KILLS = {}
var.KILLER = "" # nickname of who chose the victim
var.SEEN = set() # set of doomsayers that have had visions
var.HEXED = set() # set of hags that have silenced others
var.SHAMANS = {} # dict of shamans/crazed shamans that have acted and who got totems
var.OBSERVED = {} # those whom werecrows/sorcerers have observed
@ -4004,8 +3996,8 @@ def transition_day(cli, gameid=0):
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
(target in var.GUARDED and var.GUARDED[target]) or target in var.OTHER_KILLS or
if ((target in var.HVISITED and var.HVISITED[target]) or target in var.SHAMANS or
(target in var.GUARDED and var.GUARDED[target]) 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.HEXED or target in var.CURSED or evt.data["acted"]):
pm(cli, crow, messages["werecrow_success"].format(target))
@ -4047,18 +4039,9 @@ def transition_day(cli, gameid=0):
protected = evt.data["protected"]
bitten = evt.data["bitten"]
for k, d in var.OTHER_KILLS.items():
victims.append(d)
onlybywolves.discard(d)
killers[d].append(k)
if var.VENGEFUL_GHOSTS.get(k) == "villagers":
wolfghostvictims.append(d)
for v in var.ENTRANCED_DYING:
var.DYING.add(v)
var.OTHER_KILLS = {}
for k, d in var.DEATH_TOTEM:
victims.append(d)
onlybywolves.discard(d)
@ -4589,24 +4572,17 @@ def chk_nightdone(cli):
# TODO: alphabetize and/or arrange sensibly
pl = list_players()
spl = set(pl)
actedcount = sum(map(len, (var.SEEN, var.HVISITED, var.GUARDED,
var.OTHER_KILLS, var.PASSED, var.OBSERVED,
actedcount = sum(map(len, (var.HVISITED, var.GUARDED, var.PASSED, var.OBSERVED,
var.HEXED, var.SHAMANS, var.CURSED, var.CHARMERS)))
nightroles = get_roles("harlot", "succubus", "bodyguard", "guardian angel",
"sorcerer", "hag", "shaman", "crazed shaman",
"warlock", "piper", "doomsayer",
"prophet", "wolf shaman")
"warlock", "piper", "prophet", "wolf shaman")
for nick, info in var.PRAYED.items():
if info[0] > 0:
actedcount += 1
for p in var.ROLES["doomsayer"]:
if p in var.SEEN and p in var.OTHER_KILLS:
# don't count this twice
actedcount -= 1
if var.FIRST_NIGHT:
actedcount += len(var.MATCHMAKERS | var.CLONED.keys())
nightroles.extend(get_roles("matchmaker", "clone"))
@ -4857,8 +4833,6 @@ def check_exchange(cli, actor, nick):
var.DOCTORS[nick] = var.DOCTORS.pop(actor)
elif actor_role == "alpha wolf":
var.ALPHA_WOLVES.discard(actor)
elif actor_role == "doomsayer":
var.SEEN.discard(actor)
elif actor_role == "warlock":
var.CURSED.discard(actor)
elif actor_role == "turncoat":
@ -4909,8 +4883,6 @@ def check_exchange(cli, actor, nick):
var.DOCTORS[actor] = var.DOCTORS.pop(nick)
elif nick_role == "alpha wolf":
var.ALPHA_WOLVES.discard(nick)
elif nick_role == "doomsayer":
var.SEEN.discard(nick)
elif nick_role == "warlock":
var.CURSED.discard(nick)
elif nick_role == "turncoat":
@ -5525,9 +5497,6 @@ def hvisit(cli, nick, chan, rest):
if nick != victim:
pm(cli, victim, (messages["notify_succubus_target"]).format(nick))
if var.OTHER_KILLS.get(victim) in var.ROLES["succubus"]:
pm(cli, victim, messages["no_kill_succubus"].format(var.OTHER_KILLS[victim]))
del var.OTHER_KILLS[victim]
if var.TARGETED.get(victim) in var.ROLES["succubus"]:
msg = messages["no_target_succubus"].format(var.TARGETED[victim])
del var.TARGETED[victim]
@ -5546,7 +5515,7 @@ def hvisit(cli, nick, chan, rest):
var.HEXED.remove(victim)
del var.LASTHEXED[victim]
# temp hack, will do something better once succubus is split off
from src.roles import wolf, hunter, dullahan
from src.roles import wolf, hunter, dullahan, vigilante
if set(wolf.KILLS.get(victim, ())) & var.ROLES["succubus"]:
for s in var.ROLES["succubus"]:
if s in wolf.KILLS[victim]:
@ -5558,6 +5527,9 @@ def hvisit(cli, nick, chan, rest):
pm(cli, victim, messages["no_kill_succubus"].format(hunter.KILLS[victim]))
del hunter.KILLS[victim]
hunter.HUNTERS.discard(victim)
if vigilante.KILLS.get(victim) in var.ROLES["succubus"]:
pm(cli, victim, messages["no_kill_succubus"].format(vigilante.KILLS[victim]))
del vigilante.KILLS[victim]
if var.BITE_PREFERENCES.get(victim) in var.ROLES["succubus"]:
pm(cli, victim, messages["no_kill_succubus"].format(var.BITE_PREFERENCES[victim]))
del var.BITE_PREFERENCES[victim]
@ -5569,52 +5541,6 @@ def hvisit(cli, nick, chan, rest):
debuglog("{0} ({1}) VISIT: {2} ({3})".format(nick, role, victim, get_role(victim)))
chk_nightdone(cli)
@cmd("see", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("doomsayer",))
def see(cli, nick, chan, rest):
"""Use your paranormal senses to determine a player's doom."""
role = get_role(nick)
if nick in var.SEEN:
pm(cli, nick, messages["seer_fail"])
return
victim = get_victim(cli, nick, re.split(" +",rest)[0], False)
if not victim:
return
if victim == nick:
pm(cli, nick, messages["no_see_self"])
return
if is_safe(nick, victim):
pm(cli, nick, messages["no_acting_on_succubus"].format("see"))
return
if in_wolflist(nick, victim):
pm(cli, nick, messages["no_see_wolf"])
return
victim = choose_target(nick, victim)
if check_exchange(cli, nick, victim):
return
victimrole = get_role(victim)
vrole = victimrole # keep a copy for logging
mode = random.randint(1, 3)
if mode == 1:
mode = "DEATH"
pm(cli, nick, messages["doomsayer_death"].format(victim))
var.OTHER_KILLS[nick] = victim
elif mode == 2:
mode = "LYCAN"
pm(cli, nick, messages["doomsayer_lycan"].format(victim))
var.TOBELYCANTHROPES.add(victim)
elif mode == 3:
mode = "SICK"
pm(cli, nick, messages["doomsayer_sick"].format(victim))
var.TOBEDISEASED.add(victim)
var.TOBESILENCED.add(victim)
var.SICK.add(victim) # counts as unable to vote and lets them know at beginning of day that they aren't feeling well
debuglog("{0} ({1}) SEE: {2} ({3}) - {4}".format(nick, role, victim, vrole, mode))
relay_wolfchat_command(cli, nick, messages["doomsayer_wolfchat"].format(nick, victim), ("doomsayer",), is_wolf_command=True)
var.SEEN.add(nick)
chk_nightdone(cli)
@cmd("give", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=var.TOTEM_ORDER)
@cmd("totem", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=var.TOTEM_ORDER)
def totem(cli, nick, chan, rest, prefix="You"):
@ -6248,7 +6174,6 @@ def transition_night(cli):
# Reset nighttime variables
var.GUARDED = {} # key = by whom, value = the person that is visited
var.KILLER = "" # nickname of who chose the victim
var.SEEN = set() # set of seers that have had visions
var.HEXED = set() # set of hags that have hexed
var.CURSED = set() # set of warlocks that have cursed
var.SHAMANS = {}
@ -6890,7 +6815,6 @@ def start(cli, nick, chan, forced = False, restart = ""):
var.ROLES = {}
var.GUNNERS = {}
var.SEEN = set()
var.OBSERVED = {}
var.GUARDED = {}
var.HVISITED = {}
@ -6932,7 +6856,6 @@ def start(cli, nick, chan, forced = False, restart = ""):
var.EXCHANGED = set()
var.SHAMANS = {}
var.HEXED = set()
var.OTHER_KILLS = {}
var.ABSTAINED = False
var.DOCTORS = {}
var.IMMUNIZED = set()