Split GA and bodyguard

This commit is contained in:
skizzerz 2016-09-10 11:22:10 -05:00
parent 87e8b57745
commit 446d77b452
2 changed files with 277 additions and 168 deletions

258
src/roles/angel.py Normal file
View File

@ -0,0 +1,258 @@
import re
import random
import itertools
import math
from collections import defaultdict
import botconfig
import src.settings as var
from src.utilities import *
from src import debuglog, errlog, plog
from src.decorators import cmd, event_listener
from src.messages import messages
from src.events import Event
GUARDED = {} # type: Dict[str, str]
LASTGUARDED = {} # type: Dict[str, str]
PASSED = set() # type: Set[str]
@cmd("guard", "protect", "save", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("bodyguard", "guardian angel"))
def guard(cli, nick, chan, rest):
"""Guard a player, preventing them from being killed that night."""
if nick in GUARDED:
pm(cli, nick, messages["already_protecting"])
return
role = get_role(nick)
self_in_list = role == "guardian angel" and var.GUARDIAN_ANGEL_CAN_GUARD_SELF
victim = get_victim(cli, nick, re.split(" +",rest)[0], False, self_in_list)
if not victim:
return
if role == "guardian angel" and LASTGUARDED.get(nick) == victim:
pm(cli, nick, messages["guardian_target_another"].format(victim))
return
# self-guard ignores luck/misdirection/exchange totem
evt = Event("targeted_command", {"target": victim, "misdirection": victim != nick, "exchange": victim != nick})
if not evt.dispatch(cli, var, "guard", nick, victim, frozenset({"beneficial"})):
return
victim = evt.data["target"]
GUARDED[nick] = victim
LASTGUARDED[nick] = victim
if victim == nick:
pm(cli, nick, messages["guardian_guard_self"])
else:
pm(cli, nick, messages["protecting_target"].format(GUARDED[nick]))
pm(cli, victim, messages["target_protected"])
debuglog("{0} ({1}) GUARD: {2} ({3})".format(nick, role, victim, get_role(victim)))
chk_nightdone(cli)
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",), roles=("bodyguard", "guardian angel"))
def pass_cmd(cli, nick, chan, rest):
"""Decline to use your special power for that night."""
if nick in GUARDED:
pm(cli, nick, messages["already_protecting"])
return
PASSED.add(nick)
pm(cli, nick, messages["guardian_no_protect"])
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
chk_nightdone(cli)
@event_listener("rename_player")
def on_rename(evt, cli, var, prefix, nick):
for dictvar in (GUARDED, LASTGUARDED):
kvp = {}
for a,b in dictvar.items():
if a == prefix:
if b == prefix:
kvp[nick] = nick
else:
kvp[nick] = b
elif b == prefix:
kvp[a] = nick
dictvar.update(kvp)
if prefix in dictvar:
del dictvar[prefix]
if prefix in PASSED:
PASSED.discard(prefix)
PASSED.add(nick)
@event_listener("del_player")
def on_del_player(evt, cli, var, nick, nickrole, nicktpls, death_triggers):
if var.PHASE == "night" and nick in GUARDED:
pm(cli, GUARDED[nick], messages["protector_disappeared"])
for dictvar in (GUARDED, LASTGUARDED):
for k,v in list(dictvar.items()):
if nick in (k, v):
del dictvar[k]
if nick in PASSED:
PASSED.discard(nick)
@event_listener("night_acted")
def on_acted(evt, cli, var, nick, sender):
if nick in GUARDED:
evt.data["acted"] = True
@event_listener("get_special")
def on_get_special(evt, cli, var):
evt.data["special"].update(list_players(("guardian angel", "bodyguard")))
@event_listener("exchange_roles")
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):
if actor_role in ("bodyguard", "guardian angel"):
if actor in GUARDED:
pm(cli, GUARDED.pop(actor), messages["protector disappeared"])
if actor in LASTGUARDED:
del LASTGUARDED[actor]
if nick_role in ("bodyguard", "guardian angel"):
if nick in GUARDED:
pm(cli, GUARDED.pop(nick), messages["protector disappeared"])
if nick in LASTGUARDED:
del LASTGUARDED[nick]
@event_listener("chk_nightdone")
def on_chk_nightdone(evt, cli, var):
evt.data["actedcount"] += len(GUARDED) + len(PASSED)
evt.data["nightroles"].extend(list_players(("guardian angel", "bodyguard")))
@event_listener("transition_day", priority=4.2)
def on_transition_day(evt, cli, var):
pl = list_players()
vs = set(evt.data["victims"])
for v in pl:
if v in vs:
if v in var.DYING:
continue
for g in var.ROLES["guardian angel"]:
if GUARDED.get(g) == v:
evt.data["numkills"][v] -= 1
if evt.data["numkills"][v] >= 0:
evt.data["killers"][v].pop(0)
if evt.data["numkills"][v] <= 0 and v not in evt.data["protected"]:
evt.data["protected"][v] = "angel"
elif evt.data["numkills"][v] <= 0:
var.ACTIVE_PROTECTIONS[v].append("angel")
for g in var.ROLES["bodyguard"]:
if GUARDED.get(g) == v:
evt.data["numkills"][v] -= 1
if evt.data["numkills"][v] >= 0:
evt.data["killers"][v].pop(0)
if evt.data["numkills"][v] <= 0 and v not in evt.data["protected"]:
evt.data["protected"][v] = "bodyguard"
elif evt.data["numkills"][v] <= 0:
var.ACTIVE_PROTECTIONS[v].append("bodyguard")
else:
for g in var.ROLES["guardian angel"]:
if GUARDED.get(g) == v:
var.ACTIVE_PROTECTIONS[v].append("angel")
for g in var.ROLES["bodyguard"]:
if GUARDED.get(g) == v:
var.ACTIVE_PROTECTIONS[v].append("bodyguard")
@event_listener("transition_day_resolve", priority=2)
def on_transition_day_resolve(evt, cli, var, victim):
# TODO: remove these checks once everything is split
# right now they're needed because otherwise protection may fire off even if the person isn't home
# that will not be an issue once everything is using the event
if victim in var.ROLES["harlot"] | var.ROLES["succubus"] and var.HVISITED.get(victim) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]:
return
# END checks to remove
if evt.data["protected"].get(victim) == "angel":
evt.data["message"].append(messages["angel_protection"].format(victim))
evt.data["novictmsg"] = False
evt.stop_propagation = True
evt.prevent_default = True
elif evt.data["protected"].get(victim) == "bodyguard":
for bodyguard in var.ROLES["bodyguard"]:
if GUARDED.get(bodyguard) == victim:
evt.data["dead"].append(bodyguard)
evt.data["message"].append(messages["bodyguard_protection"].format(bodyguard))
evt.data["novictmsg"] = False
evt.stop_propagation = True
evt.prevent_default = True
break
@event_listener("transition_day_resolve_end")
def on_transition_day_resolve_end(evt, cli, var, victims):
for bodyguard in var.ROLES["bodyguard"]:
if GUARDED.get(bodyguard) in list_players(var.WOLF_ROLES) and bodyguard not in evt.data["dead"] and bodyguard not in evt.data["bitten"]:
r = random.random()
if r < var.BODYGUARD_DIES_CHANCE:
evt.data["bywolves"].add(bodyguard)
evt.data["onlybywolves"].add(bodyguard)
if var.ROLE_REVEAL == "on":
evt.data["message"].append(messages["bodyguard_protected_wolf"].format(bodyguard))
else: # off and team
evt.data["message"].append(messages["bodyguard_protection"].format(bodyguard))
evt.data["dead"].append(bodyguard)
for gangel in var.ROLES["guardian angel"]:
if GUARDED.get(gangel) in list_players(var.WOLF_ROLES) and gangel not in evt.data["dead"] and gangel not in evt.data["bitten"]:
r = random.random()
if r < var.GUARDIAN_ANGEL_DIES_CHANCE:
evt.data["bywolves"].add(gangel)
evt.data["onlybywolves"].add(gangel)
if var.ROLE_REVEAL == "on":
evt.data["message"].append(messages["guardian_angel_protected_wolf"].format(gangel))
else: # off and team
evt.data["message"].append(messages["guardian_angel_protected_wolf_no_reveal"].format(gangel))
evt.data["dead"].append(gangel)
@event_listener("transition_night_begin")
def on_transition_night_begin(evt, cli, var):
# needs to be here in order to allow bodyguard protections to work during the daytime
# (right now they don't due to other reasons, but that may change)
GUARDED.clear()
@event_listener("transition_night_end", priority=2)
def on_transition_night_end(evt, cli, var):
# the messages for angel and guardian angel are different enough to merit individual loops
ps = list_players()
for bg in var.ROLES["bodyguard"]:
pl = ps[:]
random.shuffle(pl)
pl.remove(bg)
chance = math.floor(var.BODYGUARD_DIES_CHANCE * 100)
warning = ""
if chance > 0:
warning = messages["bodyguard_death_chance"].format(chance)
if bg in var.PLAYERS and not is_user_simple(bg):
pm(cli, bg, messages["bodyguard_notify"].format(warning))
else:
pm(cli, bg, messages["bodyguard_simple"]) # !simple
pm(cli, bg, "Players: " + ", ".join(pl))
for gangel in var.ROLES["guardian angel"]:
pl = ps[:]
random.shuffle(pl)
gself = messages["guardian_self_notification"]
if not var.GUARDIAN_ANGEL_CAN_GUARD_SELF:
pl.remove(gangel)
gself = ""
if LASTGUARDED.get(gangel) in pl:
pl.remove(LASTGUARDED[gangel])
chance = math.floor(var.GUARDIAN_ANGEL_DIES_CHANCE * 100)
warning = ""
if chance > 0:
warning = messages["bodyguard_death_chance"].format(chance)
if gangel in var.PLAYERS and not is_user_simple(gangel):
pm(cli, gangel, messages["guardian_notify"].format(warning, gself))
else:
pm(cli, gangel, messages["guardian_simple"]) # !simple
pm(cli, gangel, "Players: " + ", ".join(pl))
@event_listener("begin_day")
def on_begin_day(evt, cli, var):
PASSED.clear()
# clear out LASTGUARDED for people that didn't guard last night
for g in list(LASTGUARDED.keys()):
if g not in GUARDED:
del LASTGUARDED[g]
@event_listener("reset")
def on_reset(evt, var):
GUARDED.clear()
LASTGUARDED.clear()
PASSED.clear()
# vim: set sw=4 expandtab:

View File

@ -2860,6 +2860,7 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
target = var.TARGETED[nick]
del var.TARGETED[nick]
if target != None and target in pl:
# TODO: split this off into an event so that individual roles can handle it as needed
if "totem" in var.ACTIVE_PROTECTIONS[target] and nickrole != "fallen angel":
var.ACTIVE_PROTECTIONS[target].remove("totem")
message = messages["assassin_fail_totem"].format(nick, target)
@ -2870,11 +2871,12 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
cli.msg(botconfig.CHANNEL, message)
elif "bodyguard" in var.ACTIVE_PROTECTIONS[target] and nickrole != "fallen angel":
var.ACTIVE_PROTECTIONS[target].remove("bodyguard")
from src.roles import angel
for ga in var.ROLES["bodyguard"]:
if var.GUARDED.get(ga) == target:
if angel.GUARDED.get(ga) == target:
message = messages["assassin_fail_bodyguard"].format(nick, target, ga)
cli.msg(botconfig.CHANNEL, message)
del_player(cli, ga, True, end_game = False, killer_role = nickrole, deadlist = deadlist, original = original, ismain = False)
del_player(cli, ga, True, end_game=False, killer_role=nickrole, deadlist=deadlist, original=original, ismain=False)
pl = refresh_pl(pl)
break
elif "blessing" in var.ACTIVE_PROTECTIONS[target] or (var.GAMEPHASE == "day" and target in var.ROLES["blessed villager"]):
@ -3077,7 +3079,7 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
if var.PHASE in var.GAME_PHASES:
# remove the player from variables if they're in there
if ret:
for x in (var.OBSERVED, var.HVISITED, var.GUARDED, var.TARGETED, var.LASTGUARDED, var.LASTHEXED):
for x in (var.OBSERVED, var.HVISITED, var.TARGETED, var.LASTHEXED):
for k in list(x):
if nick in (k, x[k]):
del x[k]
@ -3416,9 +3418,8 @@ 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.TARGETED,
var.CLONED, var.LASTGUARDED, var.LASTHEXED,
var.BITE_PREFERENCES):
for dictvar in (var.HVISITED, var.OBSERVED, var.TARGETED,
var.CLONED, var.LASTHEXED, var.BITE_PREFERENCES):
kvp = []
for a,b in dictvar.items():
if a == prefix:
@ -3679,7 +3680,6 @@ def begin_day(cli):
var.HEXED = set() # set of hags that have silenced others
var.OBSERVED = {} # those whom werecrows/sorcerers have observed
var.HVISITED = {} # those whom harlots have visited
var.GUARDED = {} # this whom bodyguards/guardian angels have guarded
var.PASSED = set() # set of certain roles that have opted not to act
var.STARTED_DAY_PLAYERS = len(list_players())
var.SILENCED = copy.copy(var.TOBESILENCED)
@ -3764,12 +3764,6 @@ def transition_day(cli, gameid=0):
pl = list_players()
if not var.START_WITH_DAY or not var.FIRST_DAY:
# bodyguard doesn't have restrictions, but being checked anyway since both GA and bodyguard use var.GUARDED
if len(var.GUARDED.keys()) < len(var.ROLES["bodyguard"] | var.ROLES["guardian angel"]):
for gangel in var.ROLES["guardian angel"]:
if gangel not in var.GUARDED or var.GUARDED[gangel] is None:
var.LASTGUARDED[gangel] = None
if len(var.HEXED) < len(var.ROLES["hag"]):
for hag in var.ROLES["hag"]:
if hag not in var.HEXED:
@ -3840,7 +3834,6 @@ def transition_day(cli, gameid=0):
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.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))
@ -3907,24 +3900,6 @@ def transition_day(cli, gameid=0):
if v in victims_set:
if v in var.DYING:
continue # bypass protections
for g in var.ROLES["guardian angel"]:
if var.GUARDED.get(g) == v:
numkills[v] -= 1
if numkills[v] >= 0:
killers[v].pop(0)
if numkills[v] <= 0 and v not in protected:
protected[v] = "angel"
elif numkills[v] <= 0:
var.ACTIVE_PROTECTIONS[v].append("angel")
for g in var.ROLES["bodyguard"]:
if var.GUARDED.get(g) == v:
numkills[v] -= 1
if numkills[v] >= 0:
killers[v].pop(0)
if numkills[v] <= 0 and v not in protected:
protected[v] = "bodyguard"
elif numkills[v] <= 0:
var.ACTIVE_PROTECTIONS[v].append("bodyguard")
if v in var.ROLES["blessed villager"]:
numkills[v] -= 1
if numkills[v] >= 0:
@ -3937,23 +3912,18 @@ def transition_day(cli, gameid=0):
onlybywolves.add(v)
else:
# player wasn't targeted, but apply protections on them
for g in var.ROLES["guardian angel"]:
if var.GUARDED.get(g) == v:
var.ACTIVE_PROTECTIONS[v].append("angel")
for g in var.ROLES["bodyguard"]:
if var.GUARDED.get(g) == v:
var.ACTIVE_PROTECTIONS[v].append("bodyguard")
if v in var.ROLES["blessed villager"]:
var.ACTIVE_PROTECTIONS[v].append("blessing")
fallenkills = set()
brokentotem = set()
from src.roles.shaman import havetotem
from src.roles import angel
if len(var.ROLES["fallen angel"]) > 0:
for p, t in list(protected.items()):
if p in bywolves:
for g in var.ROLES["guardian angel"]:
if var.GUARDED.get(g) == p and random.random() < var.FALLEN_ANGEL_KILLS_GUARDIAN_ANGEL_CHANCE:
if angel.GUARDED.get(g) == p and random.random() < var.FALLEN_ANGEL_KILLS_GUARDIAN_ANGEL_CHANCE:
if g in protected:
del protected[g]
bywolves.add(g)
@ -3963,7 +3933,7 @@ def transition_day(cli, gameid=0):
victims_set.add(g)
onlybywolves.add(g)
for g in var.ROLES["bodyguard"]:
if var.GUARDED.get(g) == p:
if angel.GUARDED.get(g) == p:
if g in protected:
del protected[g]
bywolves.add(g)
@ -4054,10 +4024,12 @@ def transition_day(cli, gameid=0):
# be correctly attributed to wolves (for vengeful ghost lover), and that any gunner events
# can play. Harlot visiting wolf doesn't play special events if they die via other means since
# that assumes they die en route to the wolves (and thus don't shoot/give out gun/etc.)
# TODO: this needs to be split off into angel.py, but all the stuff above it needs to be split off first
# so even though angel.py exists we can't exactly do this now
for v in victims_set:
if v in var.DYING:
victims.append(v)
elif v in var.ROLES["bodyguard"] and var.GUARDED.get(v) in victims_set:
elif v in var.ROLES["bodyguard"] and angel.GUARDED.get(v) in victims_set:
vappend.append(v)
elif v in var.ROLES["harlot"] and var.HVISITED.get(v) in victims_set:
vappend.append(v)
@ -4074,7 +4046,7 @@ def transition_day(cli, gameid=0):
prevlen = len(vappend)
for v in copy.copy(vappend):
if v in var.ROLES["bodyguard"] and var.GUARDED.get(v) not in vappend:
if v in var.ROLES["bodyguard"] and angel.GUARDED.get(v) not in vappend:
vappend.remove(v)
victims.append(v)
elif v in var.ROLES["harlot"] and var.HVISITED.get(v) not in vappend:
@ -4086,7 +4058,7 @@ def transition_day(cli, gameid=0):
fallenmsg = set()
if len(var.ROLES["fallen angel"]) > 0:
for v in fallenkills:
t = var.GUARDED.get(v)
t = angel.GUARDED.get(v)
if v not in fallenmsg:
fallenmsg.add(v)
if v != t:
@ -4098,7 +4070,7 @@ def transition_day(cli, gameid=0):
pm(cli, t, messages["fallen_angel_deprotect"])
# Also message GAs that don't die and their victims
for g in var.ROLES["guardian angel"]:
v = var.GUARDED.get(g)
v = angel.GUARDED.get(g)
if v in bywolves and g not in fallenkills:
if g not in fallenmsg:
fallenmsg.add(g)
@ -4170,16 +4142,6 @@ def transition_day(cli, gameid=0):
if victim not in revt.data["bitten"]:
revt.data["message"].append(messages["target_not_home"])
revt.data["novictmsg"] = False
elif revt.data["protected"].get(victim) == "angel":
revt.data["message"].append(messages["angel_protection"].format(victim))
revt.data["novictmsg"] = False
elif revt.data["protected"].get(victim) == "bodyguard":
for bodyguard in var.ROLES["bodyguard"]:
if var.GUARDED.get(bodyguard) == victim:
revt.data["dead"].append(bodyguard)
revt.data["message"].append(messages["bodyguard_protection"].format(bodyguard))
revt.data["novictmsg"] = False
break
elif revt.data["protected"].get(victim) == "blessing":
# don't play any special message for a blessed target, this means in a game with priest and monster it's not really possible
# for wolves to tell which is which. May want to change that in the future to be more obvious to wolves since there's not really
@ -4281,28 +4243,6 @@ def transition_day(cli, gameid=0):
bywolves.add(harlot)
onlybywolves.add(harlot)
dead.append(harlot)
for bodyguard in var.ROLES["bodyguard"]:
if var.GUARDED.get(bodyguard) in list_players(var.WOLF_ROLES) and bodyguard not in dead and bodyguard not in bitten:
r = random.random()
if r < var.BODYGUARD_DIES_CHANCE:
bywolves.add(bodyguard)
onlybywolves.add(bodyguard)
if var.ROLE_REVEAL == "on":
message.append(messages["bodyguard_protected_wolf"].format(bodyguard))
else: # off and team
message.append(messages["bodyguard_protection"].format(bodyguard))
dead.append(bodyguard)
for gangel in var.ROLES["guardian angel"]:
if var.GUARDED.get(gangel) in list_players(var.WOLF_ROLES) and gangel not in dead and gangel not in bitten:
r = random.random()
if r < var.GUARDIAN_ANGEL_DIES_CHANCE:
bywolves.add(gangel)
onlybywolves.add(gangel)
if var.ROLE_REVEAL == "on":
message.append(messages["guardian_angel_protected_wolf"].format(gangel))
else: # off and team
message.append(messages["guardian_angel_protected_wolf_no_reveal"].format(gangel))
dead.append(gangel)
for victim in list(dead):
if victim in var.GUNNERS.keys() and var.GUNNERS[victim] > 0 and victim in bywolves:
@ -4419,11 +4359,10 @@ def chk_nightdone(cli):
pl = list_players()
spl = set(pl)
actedcount = sum(map(len, (var.HVISITED, var.GUARDED, var.PASSED, var.OBSERVED,
actedcount = sum(map(len, (var.HVISITED, var.PASSED, var.OBSERVED,
var.HEXED, var.CURSED, var.CHARMERS)))
nightroles = get_roles("harlot", "succubus", "bodyguard", "guardian angel",
"sorcerer", "hag", "warlock", "piper", "prophet")
nightroles = get_roles("harlot", "succubus", "sorcerer", "hag", "warlock", "piper", "prophet")
for nick, info in var.PRAYED.items():
if info[0] > 0:
@ -4642,11 +4581,6 @@ def check_exchange(cli, actor, nick):
elif actor_role == "clone":
if actor in var.CLONED:
actor_target = var.CLONED.pop(actor)
elif actor_role in ("bodyguard", "guardian angel"):
if actor in var.GUARDED:
pm(cli, var.GUARDED.pop(actor), messages["protector_disappeared"])
if actor in var.LASTGUARDED:
del var.LASTGUARDED[actor]
elif actor_role in ("werecrow", "sorcerer"):
if actor in var.OBSERVED:
del var.OBSERVED[actor]
@ -4687,11 +4621,6 @@ def check_exchange(cli, actor, nick):
elif nick_role == "clone":
if nick in var.CLONED:
nick_target = var.CLONED.pop(nick)
elif nick_role in ("bodyguard", "guardian angel"):
if nick in var.GUARDED:
pm(cli, var.GUARDED.pop(nick), messages["protector_disappeared"])
if nick in var.LASTGUARDED:
del var.LASTGUARDED[nick]
elif nick_role in ("werecrow", "sorcerer"):
if nick in var.OBSERVED:
del var.OBSERVED[nick]
@ -4946,39 +4875,6 @@ def shoot(cli, nick, chan, rest):
def is_safe(nick, victim): # helper function
return nick in var.ENTRANCED and victim in var.ROLES["succubus"]
@cmd("guard", "protect", "save", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("bodyguard", "guardian angel"))
def guard(cli, nick, chan, rest):
"""Guard a player, preventing them from being killed that night."""
if var.GUARDED.get(nick):
pm(cli, nick, messages["already_protecting"])
return
role = get_role(nick)
victim = get_victim(cli, nick, re.split(" +",rest)[0], False, role == "bodyguard" or var.GUARDIAN_ANGEL_CAN_GUARD_SELF)
if not victim:
return
if role == "guardian angel" and var.LASTGUARDED.get(nick) == victim:
pm(cli, nick, messages["guardian_target_another"].format(victim))
return
if victim == nick:
if role == "bodyguard" or not var.GUARDIAN_ANGEL_CAN_GUARD_SELF:
pm(cli, nick, messages["cannot_guard_self"])
return
elif role == "guardian angel": # choosing to guard self bypasses lucky/misdirection
var.GUARDED[nick] = nick
var.LASTGUARDED[nick] = nick
pm(cli, nick, messages["guardian_guard_self"])
else:
victim = choose_target(nick, victim)
if check_exchange(cli, nick, victim):
return
var.GUARDED[nick] = victim
var.LASTGUARDED[nick] = victim
pm(cli, nick, messages["protecting_target"].format(var.GUARDED[nick]))
pm(cli, var.GUARDED[nick], messages["target_protected"])
debuglog("{0} ({1}) GUARD: {2} ({3})".format(nick, role, victim, get_role(victim)))
chk_nightdone(cli)
@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."""
@ -5345,7 +5241,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"))
roles=("harlot", "turncoat", "warlock", "piper", "succubus"))
def pass_cmd(cli, nick, chan, rest):
"""Decline to use your special power for that night."""
nickrole = get_role(nick)
@ -5370,12 +5266,6 @@ def pass_cmd(cli, nick, chan, rest):
return
var.HVISITED[nick] = None
pm(cli, nick, messages["succubus_pass"])
elif nickrole == "bodyguard" or nickrole == "guardian angel":
if var.GUARDED.get(nick):
pm(cli, nick, messages["already_protecting"])
return
var.GUARDED[nick] = None
pm(cli, nick, messages["guardian_no_protect"])
elif nickrole == "turncoat":
if var.TURNCOATS[nick][1] == var.NIGHT_COUNT:
# theoretically passing would revert them to how they were before, but
@ -5880,7 +5770,6 @@ def transition_night(cli):
var.TIMERS = {}
# Reset nighttime variables
var.GUARDED = {} # key = by whom, value = the person that is visited
var.KILLER = "" # nickname of who chose the victim
var.HEXED = set() # set of hags that have hexed
var.CURSED = set() # set of warlocks that have cursed
@ -5975,42 +5864,6 @@ def transition_night(cli):
pm(cli, harlot, messages["harlot_simple"]) # !simple
pm(cli, harlot, "Players: " + ", ".join(pl))
# the messages for angel and guardian angel are different enough to merit individual loops
for g_angel in var.ROLES["bodyguard"]:
pl = ps[:]
random.shuffle(pl)
pl.remove(g_angel)
chance = math.floor(var.BODYGUARD_DIES_CHANCE * 100)
warning = ""
if chance > 0:
warning = messages["bodyguard_death_chance"].format(chance)
if g_angel in var.PLAYERS and not is_user_simple(g_angel):
pm(cli, g_angel, messages["bodyguard_notify"].format(warning))
else:
pm(cli, g_angel, messages["bodyguard_simple"]) # !simple
pm(cli, g_angel, "Players: " + ", ".join(pl))
for gangel in var.ROLES["guardian angel"]:
pl = ps[:]
random.shuffle(pl)
gself = messages["guardian_self_notification"]
if not var.GUARDIAN_ANGEL_CAN_GUARD_SELF:
pl.remove(gangel)
gself = ""
if var.LASTGUARDED.get(gangel) in pl:
pl.remove(var.LASTGUARDED[gangel])
chance = math.floor(var.GUARDIAN_ANGEL_DIES_CHANCE * 100)
warning = ""
if chance > 0:
warning = messages["bodyguard_death_chance"].format(chance)
if gangel in var.PLAYERS and not is_user_simple(gangel):
pm(cli, gangel, messages["guardian_notify"].format(warning, gself))
else:
pm(cli, gangel, messages["guardian_simple"]) # !simple
pm(cli, gangel, "Players: " + ", ".join(pl))
for pht in var.ROLES["prophet"]:
chance1 = math.floor(var.PROPHET_REVEALED_CHANCE[0] * 100)
chance2 = math.floor(var.PROPHET_REVEALED_CHANCE[1] * 100)
@ -6417,11 +6270,9 @@ def start(cli, nick, chan, forced = False, restart = ""):
var.ROLES = {}
var.GUNNERS = {}
var.OBSERVED = {}
var.GUARDED = {}
var.HVISITED = {}
var.CLONED = {}
var.TARGETED = {}
var.LASTGUARDED = {}
var.LASTHEXED = {}
var.MATCHMAKERS = set()
var.REVEALED_MAYORS = set()