Split priest

This commit is contained in:
Emanuelle Barry 2018-06-26 15:53:11 -04:00 committed by Vgr E. Barry
parent ef20a35deb
commit 6c2861168a
3 changed files with 106 additions and 73 deletions

96
src/roles/priest.py Normal file
View File

@ -0,0 +1,96 @@
import re
import random
import itertools
import math
from collections import defaultdict
from src.utilities import *
from src import channels, users, debuglog, errlog, plog
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
from src.decorators import command, event_listener
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
from src.messages import messages
from src.events import Event
PRIESTS = UserSet() # type: Set[users.User]
CONSECRATING = UserSet() # type: Set[users.User]
@command("bless", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("priest",))
def bless(var, wrapper, message):
"""Bless a player, preventing them from being killed for the remainder of the game."""
if wrapper.source in PRIESTS:
wrapper.pm(messages["already_blessed"])
return
target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_bless_self")
if not target:
return
evt = Event("targeted_command", {"target": target, "exchange": True, "misdirection": True})
if not evt.dispatch(var, wrapper.source, target):
return
PRIESTS.add(nick)
var.ROLES["blessed villager"].add(target)
wrapper.pm(messages["blessed_success"])
target.send(messages["blessed_notify_target"])
debuglog("{0} (priest) BLESS: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
@command("consecrate", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("priest",))
def consecrate(var, wrapper, message):
"""Consecrates a corpse, putting its spirit to rest and preventing other unpleasant things from happening."""
alive = get_players()
targ = re.split(" +", message)[0]
if not targ:
wrapper.pm(messages["not_enough_parameters"])
return
dead = set(var.ALL_PLAYERS) - set(alive)
target = users.complete_match(targ, dead)
if target is None:
wrapper.pm(messages["consecrate_fail"].format(targ))
return
# we have a target, so mark them as consecrated, right now all this does is silence a VG for a night
# but other roles that do stuff after death or impact dead players should have functionality here as well
# (for example, if there was a role that could raise corpses as undead somethings, this would prevent that from working)
# regardless if this has any actual effect or not, it still removes the priest from being able to vote
evt = Event("consecrate", {})
evt.dispatch(var, wrapper.source, target)
CONSECRATING.add(wrapper.source)
wrapper.pm(messages["consecrate_success"].format(target))
debuglog("{0} (priest) CONSECRATE: {1}".format(wrapper.source, target))
# consecrating can possibly cause game to end, so check for that
from src.wolfgame import chk_win
chk_win()
@event_listener("del_player")
def on_del_player(evt, var, player, mainrole, allroles, death_triggers):
CONSECRATING.discard(player)
@event_listener("get_voters")
def on_get_voters(evt, var):
evt.data["voters"].difference_update(CONSECRATING)
@event_listener("lynch")
def on_lynch(evt, var, user):
if user in CONSECRATING:
user.send(messages["consecrating_no_vote"])
evt.prevent_default = True
@event_listener("abstain")
def on_abstain(evt, var, user):
if user in CONSECRATING:
user.send(messages["consecrating_no_vote"])
evt.prevent_default = True
@event_listener("transition_night_begin")
def on_transition_night_begin(evt, var):
CONSECRATING.clear()
@event_listener("reset")
def on_reset(evt, var):
PRIESTS.clear()
CONSECRATING.clear()

View File

@ -67,6 +67,11 @@ def on_get_participants(evt, var):
evt.data["players"].extend([p for p in GHOSTS if GHOSTS[p][0] != "!"])
evt.data["players"].extend(drivenoff)
@event_listener("consecrate")
def on_consecrate(evt, var, actor, target):
if target in GHOSTS:
var.SILENCED.add(target)
@event_listener("player_win", priority=1)
def on_player_win(evt, var, user, role, winner, survived):
# alive VG winning is handled in villager.py

View File

@ -98,7 +98,6 @@ var.FORCE_ROLES = DefaultUserDict(UserSet)
var.DYING = UserSet()
var.WOUNDED = UserSet()
var.CONSECRATING = UserSet()
var.GUNNERS = UserDict()
var.NO_LYNCH = UserSet()
@ -1753,7 +1752,7 @@ def hurry_up(gameid, change):
var.DAY_ID = 0
pl = set(get_players()) - (var.WOUNDED | var.CONSECRATING)
pl = set(get_players()) - var.WOUNDED
evt = Event("get_voters", {"voters": pl})
evt.dispatch(var)
pl = evt.data["voters"]
@ -1818,7 +1817,7 @@ def chk_decision(force=None, end_game=True, deadlist=None):
return
# Even if the lynch fails, we want to go to night phase if we are forcing a lynch (day timeout)
do_night_transision = True if force else False
pl = set(get_players()) - (var.WOUNDED | var.CONSECRATING)
pl = set(get_players()) - var.WOUNDED
evt = Event("get_voters", {"voters": pl})
evt.dispatch(var)
pl = evt.data["voters"]
@ -1954,7 +1953,7 @@ def show_votes(cli, nick, chan, rest):
reply(cli, nick, chan, msg)
pl = set(get_players()) - (var.WOUNDED | var.CONSECRATING)
pl = set(get_players()) - var.WOUNDED
evt = Event("get_voters", {"voters": pl})
evt.dispatch(var)
pl = evt.data["voters"]
@ -2232,7 +2231,7 @@ def chk_win_conditions(rolemap, mainroles, end_game=True, winner=None):
"""Internal handler for the chk_win function."""
with var.GRAVEYARD_LOCK:
if var.PHASE == "day":
pl = set(get_players()) - (var.WOUNDED | var.CONSECRATING)
pl = set(get_players()) - var.WOUNDED
evt = Event("get_voters", {"voters": pl})
evt.dispatch(var)
pl = evt.data["voters"]
@ -2452,7 +2451,6 @@ def del_player(player, *, devoice=True, end_game=True, death_triggers=True, kill
var.NO_LYNCH.discard(player)
var.WOUNDED.discard(player)
var.CONSECRATING.discard(player)
# note: PHASE = "day" and GAMEPHASE = "night" during transition_day;
# we only want to induce a lynch if it's actually day and we aren't in a chained death
if var.GAMEPHASE == "day" and ismain and not end_game:
@ -2756,7 +2754,7 @@ def rename_player(var, user, prefix):
for setvar in (var.HEXED, var.SILENCED, var.PASSED,
var.JESTERS, var.LYCANTHROPES, var.LUCKY, var.DISEASED,
var.MISDIRECTED, var.EXCHANGED, var.IMMUNIZED, var.CURED_LYCANS,
var.ALPHA_WOLVES, var.CURSED, var.PRIESTS):
var.ALPHA_WOLVES, var.CURSED):
if prefix in setvar:
setvar.remove(prefix)
setvar.add(nick)
@ -3452,9 +3450,6 @@ def no_lynch(var, wrapper, message):
elif wrapper.source in var.WOUNDED:
channels.Main.send(messages["wounded_no_vote"].format(wrapper.source))
return
elif wrapper.source in var.CONSECRATING:
wrapper.pm(messages["consecrating_no_vote"])
return
for voter in list(var.VOTES):
if wrapper.source in var.VOTES[voter]:
var.VOTES[voter].remove(wrapper.source)
@ -3476,10 +3471,6 @@ def lynch(var, wrapper, message):
if wrapper.source in var.WOUNDED:
wrapper.send(messages["wounded_no_vote"].format(wrapper.source))
return
if wrapper.source in var.CONSECRATING:
wrapper.pm(messages["consecrating_no_vote"])
return
msg = re.split(" +", message)[0].strip()
troll = False
@ -3818,62 +3809,6 @@ def shoot(var, wrapper, message):
wrapper.send(messages["gunner_suicide_no_reveal"].format(wrapper.source))
del_player(wrapper.source, killer_role="villager") # blame explosion on villager's shoddy gun construction or something
@cmd("bless", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("priest",))
def bless(cli, nick, chan, rest):
"""Bless a player, preventing them from being killed for the remainder of the game."""
if nick in var.PRIESTS:
pm(cli, nick, messages["already_blessed"])
return
victim = get_victim(cli, nick, re.split(" +",rest)[0], False)
if not victim:
return
if victim == nick:
pm(cli, nick, messages["no_bless_self"])
return
victim = choose_target(nick, victim)
if check_exchange(cli, nick, victim):
return
var.PRIESTS.add(nick)
var.ROLES["blessed villager"].add(users._get(victim)) # FIXME
pm(cli, nick, messages["blessed_success"].format(victim))
pm(cli, victim, messages["blessed_notify_target"])
debuglog("{0} ({1}) BLESS: {2} ({3})".format(nick, get_role(nick), victim, get_role(victim)))
@cmd("consecrate", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("priest",))
def consecrate(cli, nick, chan, rest):
"""Consecrates a corpse, putting its spirit to rest and preventing other unpleasant things from happening."""
alive = list_players()
victim = re.split(" +", rest)[0]
if not victim:
pm(cli, nick, messages["not_enough_parameters"])
return
dead = [x.nick for x in var.ALL_PLAYERS if x.nick not in alive]
deadl = [x.lower() for x in dead]
tempvictim = complete_one_match(victim.lower(), deadl)
if not tempvictim:
pm(cli, nick, messages["consecrate_fail"].format(victim))
return
victim = dead[deadl.index(tempvictim)] #convert back to normal casing
# we have a target, so mark them as consecrated, right now all this does is silence a VG for a night
# but other roles that do stuff after death or impact dead players should have functionality here as well
# (for example, if there was a role that could raise corpses as undead somethings, this would prevent that from working)
# regardless if this has any actual effect or not, it still removes the priest from being able to vote
from src.roles import vengefulghost
if users._get(victim) in vengefulghost.GHOSTS:
var.SILENCED.add(victim)
var.CONSECRATING.add(users._get(nick)) # FIXME
pm(cli, nick, messages["consecrate_success"].format(victim))
debuglog("{0} ({1}) CONSECRATE: {2}".format(nick, get_role(nick), victim))
# consecrating can possibly cause game to end, so check for that
chk_win()
@cmd("observe", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("werecrow", "sorcerer"))
def observe(cli, nick, chan, rest):
"""Observe a player to obtain various information."""
@ -4266,7 +4201,6 @@ def transition_night():
var.PASSED = set()
var.OBSERVED = {} # those whom werecrows have observed
var.TOBESILENCED = set()
var.CONSECRATING.clear()
daydur_msg = ""
@ -4636,8 +4570,6 @@ def start(cli, nick, chan, forced = False, restart = ""):
var.ACTIVE_PROTECTIONS = defaultdict(list)
var.EXCHANGED_ROLES = []
var.EXTRA_WOLVES = 0
var.PRIESTS = set()
var.CONSECRATING.clear()
var.DYING.clear()
var.DEADCHAT_PLAYERS.clear()