Add vigilante

This commit is contained in:
skizzerz 2016-08-10 13:16:17 -05:00
parent ac2f28e6ed
commit 67f698a701
4 changed files with 149 additions and 23 deletions

View File

@ -38,7 +38,6 @@ def hunter_kill(cli, nick, chan, rest):
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",))
@ -64,6 +63,9 @@ def hunter_pass(cli, nick, chan, rest):
PASSED.add(nick)
pm(cli, nick, messages["hunter_pass"])
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
chk_nightdone(cli)
@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()):

140
src/roles/vigilante.py Normal file
View File

@ -0,0 +1,140 @@
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]
PASSED = set()
@cmd("kill", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("vigilante",))
def vigilante_kill(cli, nick, chan, rest):
"""Kill someone at night, but you die too if they aren't a wolf or win stealer!"""
victim = get_victim(cli, nick, re.split(" +",rest)[0], False)
if not victim:
return
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
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=("vigilante",))
def vigilante_retract(cli, nick, chan, rest):
"""Removes a vigilante's kill selection."""
if nick not in KILLS and nick not in PASSED:
return
if nick in KILLS:
del KILLS[nick]
PASSED.discard(nick)
pm(cli, nick, messages["retracted_kill"])
@cmd("pass", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("vigilante",))
def vigilante_pass(cli, nick, chan, rest):
"""Do not kill anyone tonight as a vigilante."""
if nick in KILLS:
del KILLS[nick]
PASSED.add(nick)
pm(cli, nick, messages["hunter_pass"])
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
chk_nightdone(cli)
@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:
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 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]
if get_role(d) not in var.WOLF_ROLES | var.WIN_STEALER_ROLES:
var.DYING.add(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]
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(get_roles("vigilante"))
@event_listener("transition_night_end", priority=2)
def on_transition_night_end(evt, cli, var):
ps = list_players()
for vigilante in var.ROLES["vigilante"]:
pl = ps[:]
random.shuffle(pl)
pl.remove(vigilante)
if vigilante in var.PLAYERS and not is_user_simple(vigilante):
pm(cli, vigilante, messages["vigilante_notify"])
else:
pm(cli, vigilante, messages["vigilante_simple"])
pm(cli, vigilante, "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()
# vim: set sw=4 expandtab:

View File

@ -282,6 +282,8 @@ SEEN_DEFAULT = frozenset({"traitor", "hag", "sorcerer", "time lord", "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 roles are win stealers, and are valid kills for vigilante
WIN_STEALER_ROLES = frozenset({"monster", "succubus", "demoniac", "piper", "fool"})
# 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"})

View File

@ -3826,7 +3826,7 @@ def begin_day(cli):
# Reset nighttime variables
var.GAMEPHASE = "day"
var.OTHER_KILLS = {} # other kill victims (vigilante/vengeful ghost)
var.OTHER_KILLS = {} # other kill victims (dullahan/vengeful ghost)
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
@ -4133,9 +4133,6 @@ def transition_day(cli, gameid=0):
killers[d].append(k)
if var.VENGEFUL_GHOSTS.get(k) == "villagers":
wolfghostvictims.append(d)
if k in var.ROLES["vigilante"]:
if get_role(d) not in var.WOLF_ROLES | {"monster", "succubus", "demoniac", "piper", "fool"}:
var.DYING.add(k)
for v in var.ENTRANCED_DYING:
var.DYING.add(v)
@ -4672,7 +4669,7 @@ def chk_nightdone(cli):
nightroles = get_roles("harlot", "succubus", "bodyguard", "guardian angel",
"sorcerer", "hag", "shaman", "crazed shaman",
"warlock", "piper", "vigilante", "doomsayer",
"warlock", "piper", "doomsayer",
"prophet", "wolf shaman")
for ghost, against in var.VENGEFUL_GHOSTS.items():
@ -5331,7 +5328,7 @@ def kill(cli, nick, chan, rest):
role = get_role(nick)
except KeyError:
role = None
if role not in {"dullahan", "vigilante"} and nick not in var.VENGEFUL_GHOSTS.keys():
if role != "dullahan" and nick not in var.VENGEFUL_GHOSTS.keys():
return
if nick in var.VENGEFUL_GHOSTS.keys() and var.VENGEFUL_GHOSTS[nick][0] == "!":
# ghost was driven away by retribution
@ -5885,7 +5882,7 @@ def bite_cmd(cli, nick, chan, rest):
chk_nightdone(cli)
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",),
roles=("harlot", "bodyguard", "guardian angel", "turncoat", "warlock", "piper", "succubus", "vigilante"))
roles=("harlot", "bodyguard", "guardian angel", "turncoat", "warlock", "piper", "succubus"))
def pass_cmd(cli, nick, chan, rest):
"""Decline to use your special power for that night."""
nickrole = get_role(nick)
@ -5941,11 +5938,6 @@ def pass_cmd(cli, nick, chan, rest):
return
pm(cli, nick, )
var.PASSED.add(nick)
elif nickrole == "vigilante":
if nick in var.OTHER_KILLS:
del var.OTHER_KILLS[nick]
pm(cli, nick, messages["hunter_pass"])
var.PASSED.add(nick)
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
chk_nightdone(cli)
@ -6705,16 +6697,6 @@ def transition_night(cli):
pm(cli, succubus, messages["succubus_simple"])
pm(cli, succubus, "Players: " + ", ".join(("{0} ({1})".format(x, get_role(x)) if x in var.ROLES["succubus"] else x for x in pl)))
for vigilante in var.ROLES["vigilante"]:
pl = ps[:]
random.shuffle(pl)
pl.remove(vigilante)
if vigilante in var.PLAYERS and not is_user_simple(vigilante):
pm(cli, vigilante, messages["vigilante_notify"])
else:
pm(cli, vigilante, messages["vigilante_simple"])
pm(cli, vigilante, "Players: " + ", ".join(pl))
for ms in var.ROLES["mad scientist"]:
pl = ps[:]
index = var.ALL_PLAYERS.index(ms)