Convert transition_day (#297)

transition_day and relevant events have been converted to the users API. Additionally, VG was converted to the users API.
This commit is contained in:
Em Barry 2017-09-11 19:55:19 -04:00 committed by Ryan Schmidt
parent e04c60a60f
commit 95fd796953
16 changed files with 336 additions and 326 deletions

View File

@ -223,7 +223,7 @@ class VillagergameMode(GameMode):
t = threading.Timer(abs(rand), transition_day, args=(cli,), kwargs={"gameid": gameid})
t.start()
def transition_day(self, evt, cli, var):
def transition_day(self, evt, var):
# 30% chance we kill a safe, otherwise kill at random
# when killing safes, go after seer, then harlot, then shaman
self.delaying_night = False
@ -256,7 +256,7 @@ class VillagergameMode(GameMode):
from src.roles import wolf
wolf.KILLS[botconfig.NICK] = [tgt]
def on_retribution_kill(self, evt, cli, var, victim, orig_target):
def on_retribution_kill(self, evt, var, victim, orig_target):
# There are no wolves for this totem to kill
if orig_target == "@wolves":
evt.data["target"] = None
@ -1130,11 +1130,13 @@ class SleepyMode(GameMode):
if self.having_nightmare is not None:
evt.data["actedcount"] = -1
def nightmare_kill(self, evt, cli, var):
def nightmare_kill(self, evt, var):
# if True, it means night ended before 1 minute
if self.having_nightmare is not None and self.having_nightmare is not True and self.having_nightmare in list_players():
var.DYING.add(self.having_nightmare)
pm(cli, self.having_nightmare, messages["sleepy_nightmare_death"])
if self.having_nightmare is not None and self.having_nightmare is not True:
user = users._get(self.having_nightmare) # FIXME
if user in get_players():
var.DYING.add(user)
user.send(messages["sleepy_nightmare_death"])
def happy_fun_times(self, evt, var, user, mainrole, allroles, death_triggers):
if death_triggers:

View File

@ -117,43 +117,43 @@ def on_chk_nightdone(evt, var):
evt.data["nightroles"].extend(get_players(("guardian angel", "bodyguard")))
@event_listener("transition_day", priority=4.2)
def on_transition_day(evt, cli, var):
pl = list_players()
def on_transition_day(evt, var):
pl = get_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:
for g in get_all_players(("guardian angel",)):
if GUARDED.get(g.nick) == v.nick:
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:
var.ACTIVE_PROTECTIONS[v.nick].append("angel")
for g in get_all_players(("bodyguard",)):
if GUARDED.get(g.nick) == v.nick:
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")
var.ACTIVE_PROTECTIONS[v.nick].append("bodyguard")
else:
for g in var.ROLES["guardian angel"]:
if GUARDED.get(g) == v:
var.ACTIVE_PROTECTIONS[v].append("angel")
if GUARDED.get(g) == v.nick:
var.ACTIVE_PROTECTIONS[v.nick].append("angel")
for g in var.ROLES["bodyguard"]:
if GUARDED.get(g) == v:
var.ACTIVE_PROTECTIONS[v].append("bodyguard")
if GUARDED.get(g) == v.nick:
var.ACTIVE_PROTECTIONS[v.nick].append("bodyguard")
@event_listener("fallen_angel_guard_break")
def on_fagb(evt, cli, var, victim, killer):
for g in var.ROLES["guardian angel"]:
if GUARDED.get(g) == victim:
def on_fagb(evt, var, user, killer):
for g in get_all_players(("guardian angel",)):
if GUARDED.get(g.nick) == user.nick:
if random.random() < var.FALLEN_ANGEL_KILLS_GUARDIAN_ANGEL_CHANCE:
if g in evt.data["protected"]:
del evt.data["protected"][g]
@ -162,10 +162,10 @@ def on_fagb(evt, cli, var, victim, killer):
evt.data["onlybywolves"].add(g)
evt.data["victims"].append(g)
evt.data["killers"][g].append(killer)
if g != victim:
pm(cli, g, messages["fallen_angel_success"].format(victim))
for g in var.ROLES["bodyguard"]:
if GUARDED.get(g) == victim:
if g is not user:
g.send(messages["fallen_angel_success"].format(user))
for g in get_all_players(("bodyguard",)):
if GUARDED.get(g.nick) == user.nick:
if g in evt.data["protected"]:
del evt.data["protected"][g]
evt.data["bywolves"].add(g)
@ -173,19 +173,19 @@ def on_fagb(evt, cli, var, victim, killer):
evt.data["onlybywolves"].add(g)
evt.data["victims"].append(g)
evt.data["killers"][g].append(killer)
if g != victim:
pm(cli, g, messages["fallen_angel_success"].format(victim))
if g is not user:
g.send(messages["fallen_angel_success"].format(user))
@event_listener("transition_day_resolve", priority=2)
def on_transition_day_resolve(evt, cli, var, victim):
def on_transition_day_resolve(evt, var, victim):
if evt.data["protected"].get(victim) == "angel":
evt.data["message"].append(messages["angel_protection"].format(victim))
evt.data["novictmsg"] = False
evt.stop_processing = True
evt.prevent_default = True
elif evt.data["protected"].get(victim) == "bodyguard":
for bodyguard in var.ROLES["bodyguard"]:
if GUARDED.get(bodyguard) == victim:
for bodyguard in get_all_players(("bodyguard",)):
if GUARDED.get(bodyguard.nick) == victim.nick:
evt.data["dead"].append(bodyguard)
evt.data["message"].append(messages["bodyguard_protection"].format(bodyguard))
evt.data["novictmsg"] = False
@ -194,9 +194,9 @@ def on_transition_day_resolve(evt, cli, var, victim):
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"]:
def on_transition_day_resolve_end(evt, var, victims):
for bodyguard in get_all_players(("bodyguard",)):
if GUARDED.get(bodyguard.nick) 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)
@ -206,8 +206,8 @@ def on_transition_day_resolve_end(evt, cli, var, victims):
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"]:
for gangel in get_all_players(("guardian angel",)):
if GUARDED.get(gangel.nick) 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)

View File

@ -14,26 +14,26 @@ from src.messages import messages
from src.events import Event
@event_listener("transition_day", priority=4.3)
def on_transition_day(evt, cli, var):
pl = list_players()
def on_transition_day(evt, var):
pl = get_players()
vs = set(evt.data["victims"])
for v in pl:
if v in vs:
if v in var.DYING:
continue
if v in var.ROLES["blessed villager"]:
if v in get_all_players(("blessed villager",)):
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] = "blessing"
elif evt.data["numkills"][v] <= 0:
var.ACTIVE_PROTECTIONS[v].append("blessing")
elif v in var.ROLES["blessed villager"]:
var.ACTIVE_PROTECTIONS[v].append("blessing")
var.ACTIVE_PROTECTIONS[v.nick].append("blessing")
elif v in get_all_players(("blessed villager",)):
var.ACTIVE_PROTECTIONS[v.nick].append("blessing")
@event_listener("transition_day_resolve", priority=2)
def on_transition_day_resolve(evt, cli, var, victim):
def on_transition_day_resolve(evt, var, victim):
if evt.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
@ -58,9 +58,9 @@ def on_desperation(evt, cli, var, votee, target, prot):
evt.stop_processing = True
@event_listener("retribution_totem")
def on_retribution(evt, cli, var, victim, loser, prot):
def on_retribution(evt, var, victim, target, prot):
if prot == "blessing":
var.ACTIVE_PROTECTIONS[target].remove("blessing")
var.ACTIVE_PROTECTIONS[target.nick].remove("blessing")
evt.prevent_default = True
evt.stop_processing = True

View File

@ -3,7 +3,7 @@ import random
import src.settings as var
from src.utilities import *
from src import debuglog, errlog, plog
from src import users, debuglog, errlog, plog
from src.functions import get_players, get_all_players
from src.decorators import cmd, event_listener
from src.messages import messages
@ -128,20 +128,25 @@ def on_get_voters(evt, var):
evt.data["voters"].difference_update(SICK.values())
@event_listener("transition_day_begin")
def on_transition_day_begin(evt, cli, var):
def on_transition_day_begin(evt, var):
for victim in SICK.values():
pm(cli, victim, messages["player_sick"])
user = users._get(victim)
user.queue_message(messages["player_sick"])
if SICK:
user.send_messages()
@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)
def on_transition_day(evt, var):
for k, v in list(KILLS.items()):
killer = users._get(k) # FIXME
victim = users._get(v) # FIXME
evt.data["victims"].append(victim)
# 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)
evt.data["onlybywolves"].discard(victim)
evt.data["killers"][victim].append(killer)
@event_listener("begin_day")
def on_begin_day(evt, var):

View File

@ -134,12 +134,12 @@ def on_get_special(evt, var):
evt.data["special"].update(get_players(("dullahan",)))
@event_listener("transition_day", priority=2)
def on_transition_day(evt, cli, var):
def on_transition_day(evt, var):
while KILLS:
k, d = KILLS.popitem()
evt.data["victims"].append(d.nick)
evt.data["onlybywolves"].discard(d.nick)
evt.data["killers"][d.nick].append(k.nick)
evt.data["victims"].append(d)
evt.data["onlybywolves"].discard(d)
evt.data["killers"][d].append(k)
@event_listener("exchange_roles")
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):

View File

@ -7,16 +7,17 @@ from collections import defaultdict
import botconfig
import src.settings as var
from src.utilities import *
from src import debuglog, errlog, plog
from src import users, debuglog, errlog, plog
from src.decorators import cmd, event_listener
from src.functions import get_players, get_all_players
from src.messages import messages
from src.events import Event
@event_listener("transition_day", priority=4.8)
def on_transition_day(evt, cli, var):
def on_transition_day(evt, var):
# now that all protections are finished, add people back to onlybywolves
# if they're down to 1 active kill and wolves were a valid killer
victims = set(list_players()) & set(evt.data["victims"]) - var.DYING
victims = set(get_players()) & set(evt.data["victims"]) - var.DYING
for v in victims:
if evt.data["numkills"][v] == 1 and v in evt.data["bywolves"]:
evt.data["onlybywolves"].add(v)
@ -25,17 +26,17 @@ def on_transition_day(evt, cli, var):
for p, t in list(evt.data["protected"].items()):
if p in evt.data["bywolves"]:
if p in evt.data["protected"]:
pm(cli, p, messages["fallen_angel_deprotect"])
p.send(messages["fallen_angel_deprotect"])
# let other roles do special things when we bypass their guards
killer = random.choice(list(var.ROLES["fallen angel"]))
killer = random.choice(list(get_all_players(("fallen angel",))))
fevt = Event("fallen_angel_guard_break", evt.data)
fevt.dispatch(cli, var, p, killer)
fevt.dispatch(var, p, killer)
if p in evt.data["protected"]:
del evt.data["protected"][p]
if p in var.ACTIVE_PROTECTIONS:
del var.ACTIVE_PROTECTIONS[p]
del var.ACTIVE_PROTECTIONS[p.nick]
# mark kill as performed by a random FA
# this is important as there may otherwise be no killers if every kill was blocked
evt.data["killers"][p].append(killer)

View File

@ -8,7 +8,7 @@ import botconfig
import src.settings as var
from src.utilities import *
from src import channels, users, debuglog, errlog, plog
from src.functions import get_players, get_all_players
from src.functions import get_players, get_all_players, get_main_role
from src.decorators import cmd, event_listener
from src.messages import messages
from src.events import Event
@ -59,16 +59,18 @@ def pass_cmd(cli, nick, chan, rest):
chk_nightdone(cli)
@event_listener("bite")
def on_bite(evt, cli, var, alpha, target):
if target not in var.ROLES["harlot"]:
def on_bite(evt, var, alpha, target):
if target.nick not in var.ROLES["harlot"] or target.nick not in VISITED:
return
hvisit = VISITED.get(target)
if hvisit and get_role(hvisit) not in var.WOLFCHAT_ROLES and (hvisit not in evt.param.bywolves or hvisit in evt.param.protected):
evt.data["can_bite"] = False
hvisit = VISITED[target.nick]
if hvisit is not None:
visited = users._get(hvisit) # FIXME
if get_main_role(visited) not in var.WOLFCHAT_ROLES and (visited not in evt.params.bywolves or visited in evt.params.protected):
evt.data["can_bite"] = False
@event_listener("transition_day_resolve", priority=1)
def on_transition_day_resolve(evt, cli, var, victim):
if victim in var.ROLES["harlot"] and VISITED.get(victim) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]:
def on_transition_day_resolve(evt, var, victim):
if victim.nick in var.ROLES["harlot"] and VISITED.get(victim.nick) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]:
if victim not in evt.data["bitten"]:
evt.data["message"].append(messages["target_not_home"])
evt.data["novictmsg"] = False
@ -76,23 +78,24 @@ def on_transition_day_resolve(evt, cli, var, victim):
evt.prevent_default = True
@event_listener("transition_day_resolve_end", priority=1)
def on_transition_day_resolve_end(evt, cli, var, victims):
def on_transition_day_resolve_end(evt, var, victims):
for victim in victims + evt.data["bitten"]:
if victim in evt.data["dead"] and victim in VISITED.values() and (victim in evt.data["bywolves"] or victim in evt.data["bitten"]):
if victim in evt.data["dead"] and victim.nick in VISITED.values() and (victim in evt.data["bywolves"] or victim in evt.data["bitten"]):
for hlt in VISITED:
if VISITED[hlt] == victim and hlt not in evt.data["bitten"] and hlt not in evt.data["dead"]:
user = users._get(hlt) # FIXME
if VISITED[hlt] == victim.nick and user not in evt.data["bitten"] and user not in evt.data["dead"]:
if var.ROLE_REVEAL in ("on", "team"):
evt.data["message"].append(messages["visited_victim"].format(hlt, get_reveal_role(hlt)))
else:
evt.data["message"].append(messages["visited_victim_noreveal"].format(hlt))
evt.data["bywolves"].add(hlt)
evt.data["onlybywolves"].add(hlt)
evt.data["dead"].append(hlt)
evt.data["bywolves"].add(user)
evt.data["onlybywolves"].add(user)
evt.data["dead"].append(user)
@event_listener("transition_day_resolve_end", priority=3)
def on_transition_day_resolve_end3(evt, cli, var, victims):
for harlot in var.ROLES["harlot"]:
if VISITED.get(harlot) in list_players(var.WOLF_ROLES) and harlot not in evt.data["dead"] and harlot not in evt.data["bitten"]:
def on_transition_day_resolve_end3(evt, var, victims):
for harlot in get_all_players(("harlot",)):
if VISITED.get(harlot.nick) in list_players(var.WOLF_ROLES) and harlot not in evt.data["dead"] and harlot not in evt.data["bitten"]:
evt.data["message"].append(messages["harlot_visited_wolf"].format(harlot))
evt.data["bywolves"].add(harlot)
evt.data["onlybywolves"].add(harlot)

View File

@ -104,11 +104,11 @@ def on_get_special(evt, var):
evt.data["special"].update(get_players(("hunter",)))
@event_listener("transition_day", priority=2)
def on_transition_day(evt, cli, var):
def on_transition_day(evt, var):
for k, d in list(KILLS.items()):
evt.data["victims"].append(d.nick)
evt.data["onlybywolves"].discard(d.nick)
evt.data["killers"][d.nick].append(k.nick)
evt.data["victims"].append(d)
evt.data["onlybywolves"].discard(d)
evt.data["killers"][d].append(k)
# important, otherwise our del_player listener lets hunter kill again
del KILLS[k]

View File

@ -6,7 +6,7 @@ from collections import defaultdict, deque
import botconfig
import src.settings as var
from src.utilities import *
from src import debuglog, errlog, plog, users
from src import debuglog, errlog, plog, users, channels
from src.functions import get_players, get_main_role
from src.decorators import cmd, event_listener
from src.messages import messages
@ -305,27 +305,29 @@ def on_player_win(evt, var, user, rol, winner, survived):
evt.data["iwon"] = True
@event_listener("transition_day_begin", priority=4)
def on_transition_day_begin(evt, cli, var):
def on_transition_day_begin(evt, var):
# Select random totem recipients if shamans didn't act
pl = list_players()
for shaman in list_players(var.TOTEM_ORDER):
if shaman not in SHAMANS and shaman not in var.SILENCED:
pl = get_players()
for shaman in get_players(var.TOTEM_ORDER):
if shaman.nick not in SHAMANS and shaman.nick not in var.SILENCED:
ps = pl[:]
if LASTGIVEN.get(shaman) in ps:
ps.remove(LASTGIVEN.get(shaman))
if shaman.nick in LASTGIVEN:
user = users._get(LASTGIVEN[shaman.nick]) # FIXME
if user in ps:
ps.remove(user)
levt = Event("get_random_totem_targets", {"targets": ps})
levt.dispatch(cli, var, shaman)
levt.dispatch(var, shaman)
ps = levt.data["targets"]
if ps:
target = random.choice(ps)
totem.func(cli, shaman, shaman, target, messages["random_totem_prefix"]) # XXX: Old API
totem.func(target.client, shaman.nick, shaman.nick, target.nick, messages["random_totem_prefix"]) # XXX: Old API
else:
LASTGIVEN[shaman] = None
LASTGIVEN[shaman.nick] = None
elif shaman not in SHAMANS:
LASTGIVEN[shaman] = None
LASTGIVEN[shaman.nick] = None
@event_listener("transition_day_begin", priority=6)
def on_transition_day_begin2(evt, cli, var):
def on_transition_day_begin2(evt, var):
# Reset totem variables
DEATH.clear()
PROTECTION.clear()
@ -382,7 +384,8 @@ def on_transition_day_begin2(evt, cli, var):
# other totem types possibly handled in an earlier event,
# as such there is no else: clause here
if target != victim:
pm(cli, shaman, messages["totem_retarget"].format(victim))
user = users._get(shaman) # FIXME
user.send(messages["totem_retarget"].format(victim))
LASTGIVEN[shaman] = victim
# In transition_day_end we report who was given totems based on havetotem.
@ -393,21 +396,23 @@ def on_transition_day_begin2(evt, cli, var):
havetotem.extend(sorted(filter(None, LASTGIVEN.values())))
@event_listener("transition_day", priority=2)
def on_transition_day2(evt, cli, var):
def on_transition_day2(evt, var):
for k, d in DEATH.items():
evt.data["victims"].append(d)
evt.data["onlybywolves"].discard(d)
evt.data["killers"][d].append(k)
shaman = users._get(k) # FIXME
target = users._get(d) # FIXME
evt.data["victims"].append(target)
evt.data["onlybywolves"].discard(target)
evt.data["killers"][target].append(shaman)
@event_listener("transition_day", priority=4.1)
def on_transition_day3(evt, cli, var):
def on_transition_day3(evt, var):
# protection totems are applied first in default logic, however
# we set priority=4.1 to allow other modes of protection
# to pre-empt us if desired
pl = list_players()
pl = get_players()
vs = set(evt.data["victims"])
for v in pl:
numtotems = PROTECTION.count(v)
numtotems = PROTECTION.count(v.nick)
if v in vs:
if v in var.DYING:
continue
@ -419,22 +424,22 @@ def on_transition_day3(evt, cli, var):
if numkills <= 0 and v not in evt.data["protected"]:
evt.data["protected"][v] = "totem"
elif numkills <= 0:
var.ACTIVE_PROTECTIONS[v].append("totem")
var.ACTIVE_PROTECTIONS[v.nick].append("totem")
evt.data["numkills"][v] = numkills
else:
for i in range(0, numtotems):
var.ACTIVE_PROTECTIONS[v].append("totem")
var.ACTIVE_PROTECTIONS[v.nick].append("totem")
@event_listener("fallen_angel_guard_break")
def on_fagb(evt, cli, var, victim, killer):
def on_fagb(evt, var, victim, killer):
# we'll never end up killing a shaman who gave out protection, but delete the totem since
# story-wise it gets demolished at night by the FA
while victim in havetotem:
havetotem.remove(victim)
brokentotem.add(victim)
while victim.nick in havetotem:
havetotem.remove(victim.nick)
brokentotem.add(victim.nick)
@event_listener("transition_day_resolve", priority=2)
def on_transition_day_resolve2(evt, cli, var, victim):
def on_transition_day_resolve2(evt, var, victim):
if evt.data["protected"].get(victim) == "totem":
evt.data["message"].append(messages["totem_protection"].format(victim))
evt.data["novictmsg"] = False
@ -442,54 +447,54 @@ def on_transition_day_resolve2(evt, cli, var, victim):
evt.prevent_default = True
@event_listener("transition_day_resolve", priority=6)
def on_transition_day_resolve6(evt, cli, var, victim):
def on_transition_day_resolve6(evt, var, victim):
# TODO: remove these checks once everything is split
# right now they're needed because otherwise retribution may fire off when the target isn't actually dying
# that will not be an issue once everything is using the event
if evt.data["protected"].get(victim):
return
if victim in var.ROLES["lycan"] and victim in evt.data["onlybywolves"] and victim not in var.IMMUNIZED:
if victim.nick in var.ROLES["lycan"] and victim in evt.data["onlybywolves"] and victim.nick not in var.IMMUNIZED:
return
# END checks to remove
if victim in RETRIBUTION:
if victim.nick in RETRIBUTION:
killers = list(evt.data["killers"].get(victim, []))
loser = None
while killers:
loser = random.choice(killers)
if loser in evt.data["dead"] or victim == loser:
if loser in evt.data["dead"] or victim is loser:
killers.remove(loser)
continue
break
if loser in evt.data["dead"] or victim == loser:
if loser in evt.data["dead"] or victim is loser:
loser = None
ret_evt = Event("retribution_kill", {"target": loser, "message": []})
ret_evt.dispatch(cli, var, victim, loser)
ret_evt.dispatch(var, victim, loser)
loser = ret_evt.data["target"]
evt.data["message"].extend(ret_evt.data["message"])
if loser in evt.data["dead"] or victim == loser:
if loser in evt.data["dead"] or victim is loser:
loser = None
if loser is not None:
prots = deque(var.ACTIVE_PROTECTIONS[loser])
prots = deque(var.ACTIVE_PROTECTIONS[loser.nick])
while len(prots) > 0:
# an event can read the current active protection and cancel the totem
# if it cancels, it is responsible for removing the protection from var.ACTIVE_PROTECTIONS
# so that it cannot be used again (if the protection is meant to be usable once-only)
ret_evt = Event("retribution_totem", {"message": []})
if not ret_evt.dispatch(cli, var, victim, loser, prots[0]):
if not ret_evt.dispatch(var, victim, loser, prots[0]):
evt.data["message"].extend(ret_evt.data["message"])
return
prots.popleft()
evt.data["dead"].append(loser)
if var.ROLE_REVEAL in ("on", "team"):
role = get_reveal_role(loser)
role = get_reveal_role(loser.nick)
an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
evt.data["message"].append(messages["totem_death"].format(victim, loser, an, role))
else:
evt.data["message"].append(messages["totem_death_no_reveal"].format(victim, loser))
@event_listener("transition_day_end", priority=1)
def on_transition_day_end(evt, cli, var):
def on_transition_day_end(evt, var):
message = []
for player, tlist in itertools.groupby(havetotem):
ntotems = len(list(tlist))
@ -497,7 +502,7 @@ def on_transition_day_end(evt, cli, var):
player, "ed" if player not in list_players() else "s", "a" if ntotems == 1 else "\u0002{0}\u0002".format(ntotems), "s" if ntotems > 1 else ""))
for player in brokentotem:
message.append(messages["totem_broken"].format(player))
cli.msg(botconfig.CHANNEL, "\n".join(message))
channels.Main.send("\n".join(message))
@event_listener("transition_night_end", priority=2.01)
def on_transition_night_end(evt, var):
@ -513,7 +518,7 @@ def on_transition_night_end(evt, var):
for shaman in get_players(var.TOTEM_ORDER):
pl = ps[:]
random.shuffle(pl)
if shaman.nick in LASTGIVEN:
if LASTGIVEN.get(shaman.nick):
user = users._get(LASTGIVEN[shaman.nick]) # FIXME
if user in pl:
pl.remove(user)

View File

@ -90,9 +90,9 @@ def on_harlot_visit(evt, cli, var, nick, victim):
ENTRANCED.add(nick)
@event_listener("get_random_totem_targets")
def on_get_random_totem_targets(evt, cli, var, shaman):
if shaman in ENTRANCED:
for succubus in var.ROLES["succubus"]:
def on_get_random_totem_targets(evt, var, shaman):
if shaman.nick in ENTRANCED:
for succubus in get_all_players(("succubus",)):
if succubus in evt.data["targets"]:
evt.data["targets"].remove(succubus)
@ -221,8 +221,8 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
ENTRANCED_DYING.clear()
@event_listener("transition_day_resolve", priority=1)
def on_transition_day_resolve(evt, cli, var, victim):
if victim in var.ROLES["succubus"] and VISITED.get(victim) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]:
def on_transition_day_resolve(evt, var, victim):
if victim.nick in var.ROLES["succubus"] and VISITED.get(victim.nick) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]:
# TODO: check if this is necessary for succubus, it's to prevent a message playing if alpha bites
# a harlot that is visiting a wolf, since the bite succeeds in that case.
if victim not in evt.data["bitten"]:
@ -232,18 +232,19 @@ def on_transition_day_resolve(evt, cli, var, victim):
evt.prevent_default = True
@event_listener("transition_day_resolve_end", priority=1)
def on_transition_day_resolve_end(evt, cli, var, victims):
def on_transition_day_resolve_end(evt, var, victims):
for victim in victims + evt.data["bitten"]:
if victim in evt.data["dead"] and victim in VISITED.values() and (victim in evt.data["bywolves"] or victim in evt.data["bitten"]):
if victim in evt.data["dead"] and victim.nick in VISITED.values() and (victim in evt.data["bywolves"] or victim in evt.data["bitten"]):
for succ in VISITED:
if VISITED[succ] == victim and succ not in evt.data["bitten"] and succ not in evt.data["dead"]:
user = users._get(succ) # FIXME
if VISITED[succ] == victim.nick and user not in evt.data["bitten"] and user not in evt.data["dead"]:
if var.ROLE_REVEAL in ("on", "team"):
evt.data["message"].append(messages["visited_victim"].format(succ, get_reveal_role(succ)))
else:
evt.data["message"].append(messages["visited_victim_noreveal"].format(succ))
evt.data["bywolves"].add(succ)
evt.data["onlybywolves"].add(succ)
evt.data["dead"].append(succ)
evt.data["bywolves"].add(user)
evt.data["onlybywolves"].add(user)
evt.data["dead"].append(user)
@event_listener("night_acted")
def on_night_acted(evt, var, user, actor):
@ -290,11 +291,12 @@ def on_begin_day(evt, var):
ENTRANCED_DYING.clear()
@event_listener("transition_day", priority=2)
def on_transition_day(evt, cli, var):
def on_transition_day(evt, var):
for v in ENTRANCED_DYING:
var.DYING.add(v) # indicate that the death bypasses protections
evt.data["victims"].append(v)
evt.data["onlybywolves"].discard(v)
user = users._get(v) # FIXME
var.DYING.add(user) # indicate that the death bypasses protections
evt.data["victims"].append(user)
evt.data["onlybywolves"].discard(user)
# we do not add to killers as retribution totem should not work on entranced not following succubus
@event_listener("get_special")

View File

@ -5,12 +5,12 @@ from collections import defaultdict
import src.settings as var
from src.utilities import *
from src import channels, users, debuglog, errlog, plog
from src.functions import get_players
from src.functions import get_players, get_target, get_main_role
from src.decorators import command, event_listener
from src.messages import messages
from src.events import Event
KILLS = {} # type: Dict[str, str]
KILLS = {} # type: Dict[users.User, users.User]
GHOSTS = {} # type: Dict[users.User, str]
# temporary holding variable, only non-empty during transition_day
@ -22,34 +22,34 @@ def vg_kill(var, wrapper, message):
if GHOSTS[wrapper.source][0] == "!":
return
victim = get_victim(wrapper.source.client, wrapper.source.nick, re.split(" +", message)[0], False)
if not victim:
target = get_target(var, wrapper, re.split(" +", message)[0])
if not target:
return
if victim == wrapper.source.nick:
if target is wrapper.source:
wrapper.pm(messages["player_dead"])
return
wolves = list_players(var.WOLFTEAM_ROLES)
if GHOSTS[wrapper.source] == "wolves" and victim not in wolves:
wolves = get_players(var.WOLFTEAM_ROLES)
if GHOSTS[wrapper.source] == "wolves" and target not in wolves:
wrapper.pm(messages["vengeful_ghost_wolf"])
return
elif GHOSTS[wrapper.source] == "villagers" and victim in wolves:
elif GHOSTS[wrapper.source] == "villagers" and target in wolves:
wrapper.pm(messages["vengeful_ghost_villager"])
return
orig = victim
evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": False})
evt.dispatch(wrapper.source.client, var, "kill", wrapper.source.nick, victim, frozenset({"detrimental"}))
orig = target
evt = Event("targeted_command", {"target": target.nick, "misdirection": True, "exchange": False})
evt.dispatch(wrapper.source.client, var, "kill", wrapper.source.nick, target.nick, frozenset({"detrimental"}))
if evt.prevent_default:
return
victim = evt.data["target"]
target = users._get(evt.data["target"]) # FIXME
KILLS[wrapper.source.nick] = victim
KILLS[wrapper.source] = target
wrapper.pm(messages["player_kill"].format(orig))
debuglog("{0} (vengeful ghost) KILL: {1} ({2})".format(wrapper.source.nick, victim, get_role(victim)))
debuglog("{0} (vengeful ghost) KILL: {1} ({2})".format(wrapper.source.nick, target, get_main_role(target)))
chk_nightdone(wrapper.source.client)
@command("retract", "r", chan=False, pm=True, playing=False, phases=("night",))
@ -57,8 +57,8 @@ def vg_retract(var, wrapper, message):
"""Removes a vengeful ghost's kill selection."""
if wrapper.source not in GHOSTS:
return
if wrapper.source.nick in KILLS:
del KILLS[wrapper.source.nick]
if wrapper.source in KILLS:
del KILLS[wrapper.source]
wrapper.pm(messages["retracted_kill"])
@event_listener("get_participants")
@ -90,9 +90,9 @@ def on_player_win(evt, var, user, role, winner, survived):
@event_listener("del_player", priority=6)
def on_del_player(evt, var, user, nickrole, nicktpls, death_triggers):
for h,v in list(KILLS.items()):
if v == user.nick:
pm(user.client, h, messages["hunter_discard"])
for h, v in list(KILLS.items()):
if user is v:
h.send(messages["hunter_discard"])
del KILLS[h]
# extending VG to work with new teams can be done by registering a listener
# at priority < 6, importing src.roles.vengefulghost, and setting
@ -105,28 +105,15 @@ def on_del_player(evt, var, user, nickrole, nicktpls, death_triggers):
user.send(messages["vengeful_turn"].format(GHOSTS[user]))
debuglog(user.nick, "(vengeful ghost) TRIGGER", GHOSTS[user])
@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]
@event_listener("transition_day_begin", priority=6)
def on_transition_day_begin(evt, cli, var):
def on_transition_day_begin(evt, var):
# select a random target for VG if they didn't kill
wolves = set(list_players(var.WOLFTEAM_ROLES))
villagers = set(list_players()) - wolves
wolves = set(get_players(var.WOLFTEAM_ROLES))
villagers = set(get_players()) - wolves
for ghost, target in GHOSTS.items():
if target[0] == "!" or ghost.nick in var.SILENCED:
continue
if ghost.nick not in KILLS:
if ghost not in KILLS:
choice = set()
if target == "wolves":
choice = wolves.copy()
@ -136,39 +123,38 @@ def on_transition_day_begin(evt, cli, var):
evt.dispatch(var, ghost, target)
choice = evt.data["pl"]
if choice:
KILLS[ghost.nick] = random.choice(list(choice))
KILLS[ghost] = random.choice(list(choice))
@event_listener("transition_day", priority=2)
def on_transition_day(evt, cli, var):
def on_transition_day(evt, var):
for k, d in KILLS.items():
evt.data["victims"].append(d)
evt.data["onlybywolves"].discard(d)
evt.data["killers"][d].append(k)
@event_listener("transition_day", priority=3.01)
def on_transition_day3(evt, cli, var):
def on_transition_day3(evt, var):
for k, d in list(KILLS.items()):
if GHOSTS[users._get(k)] == "villagers":
if GHOSTS[k] == "villagers":
evt.data["killers"][d].remove(k)
evt.data["killers"][d].insert(0, k)
@event_listener("transition_day", priority=6.01)
def on_transition_day6(evt, cli, var):
def on_transition_day6(evt, var):
for k, d in list(KILLS.items()):
if GHOSTS[users._get(k)] == "villagers" and k in evt.data["killers"][d]:
if GHOSTS[k] == "villagers" and k in evt.data["killers"][d]:
evt.data["killers"][d].remove(k)
evt.data["killers"][d].insert(0, k)
# important, otherwise our del_player listener messages the vg
del KILLS[k]
@event_listener("retribution_kill", priority=6) # FIXME: This function, and all of the event
def on_retribution_kill(evt, cli, var, victim, orig_target):
t = evt.data["target"]
user = users._get(t)
if user in GHOSTS:
drivenoff[user] = GHOSTS[user]
GHOSTS[user] = "!" + GHOSTS[user]
evt.data["message"].append(messages["totem_banish"].format(victim, t))
@event_listener("retribution_kill", priority=6)
def on_retribution_kill(evt, var, victim, orig_target):
target = evt.data["target"]
if target in GHOSTS:
drivenoff[target] = GHOSTS[target]
GHOSTS[target] = "!" + GHOSTS[target]
evt.data["message"].append(messages["totem_banish"].format(victim, target))
evt.data["target"] = None
@event_listener("get_participant_role")

View File

@ -4,8 +4,8 @@ from collections import defaultdict
import src.settings as var
from src.utilities import *
from src import debuglog, errlog, plog
from src.functions import get_players, get_all_players
from src import users, debuglog, errlog, plog
from src.functions import get_players, get_all_players, get_main_role
from src.decorators import cmd, event_listener
from src.messages import messages
from src.events import Event
@ -97,16 +97,18 @@ def on_get_special(evt, var):
evt.data["special"].update(get_players(("vigilante",)))
@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].append(k)
def on_transition_day(evt, var):
for k, v in list(KILLS.items()):
killer = users._get(k) # FIXME
victim = users._get(v) # FIXME
evt.data["victims"].append(victim)
evt.data["onlybywolves"].discard(victim)
evt.data["killers"][victim].append(killer)
# 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)
if get_main_role(victim) not in var.WOLF_ROLES | var.WIN_STEALER_ROLES:
var.DYING.add(killer)
@event_listener("exchange_roles")
def on_exchange(evt, cli, var, actor, nick, actor_role, nick_role):

View File

@ -130,16 +130,16 @@ def on_chk_nightdone(evt, var):
evt.data["nightroles"].extend(get_all_players(("wild child",)))
@event_listener("transition_day_begin")
def on_transition_day_begin(evt, cli, var):
def on_transition_day_begin(evt, var):
if (not var.START_WITH_DAY or not var.FIRST_DAY) and var.FIRST_NIGHT:
for child in var.ROLES["wild child"]:
if child not in IDOLS:
pl = list_players()
for child in get_all_players(("wild child",)):
if child.nick not in IDOLS:
pl = get_players()
pl.remove(child)
if pl:
target = random.choice(pl)
IDOLS[child] = target
pm(cli, child, messages["wild_child_random_idol"].format(target))
IDOLS[child.nick] = target.nick
child.send(messages["wild_child_random_idol"].format(target))
@event_listener("transition_night_end", priority=2)
def on_transition_night_end(evt, var):

View File

@ -4,7 +4,7 @@ from collections import defaultdict
import src.settings as var
from src.utilities import *
from src.functions import get_players, get_main_role, get_all_roles
from src.functions import get_players, get_all_players, get_main_role, get_all_roles
from src import debuglog, errlog, plog, users
from src.decorators import cmd, event_listener
from src.messages import messages
@ -148,7 +148,7 @@ def on_get_special(evt, var):
evt.data["special"].update(get_players(CAN_KILL))
@event_listener("transition_day", priority=1)
def on_transition_day(evt, cli, var):
def on_transition_day(evt, var):
# figure out wolf target
found = defaultdict(int)
nevt = Event("wolf_numkills", {"numkills": 1})
@ -173,31 +173,32 @@ def on_transition_day(evt, cli, var):
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)
user = users._get(victim) # FIXME
evt.data["victims"].append(user)
evt.data["bywolves"].add(user)
evt.data["onlybywolves"].add(user)
# special key to let us know to randomly select a wolf in case of retribution totem
evt.data["killers"][victim].append("@wolves")
evt.data["killers"][user].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
# TODO: when monster is split off
if len(var.ROLES["fallen angel"]) == 0:
for monster in var.ROLES["monster"]:
for monster in get_all_players(("monster",)):
if monster in evt.data["victims"]:
evt.data["victims"].remove(monster)
evt.data["bywolves"].discard(monster)
evt.data["onlybywolves"].discard(monster)
@event_listener("transition_day", priority=3)
def on_transition_day3(evt, cli, var):
def on_transition_day3(evt, var):
evt.data["numkills"] = {v: evt.data["victims"].count(v) for v in set(evt.data["victims"])}
on_transition_day6(evt, cli, var)
on_transition_day6(evt, var)
@event_listener("transition_day", priority=6)
def on_transition_day6(evt, cli, var):
wolfteam = list_players(var.WOLFTEAM_ROLES)
def on_transition_day6(evt, var):
wolfteam = get_players(var.WOLFTEAM_ROLES)
for victim, killers in list(evt.data["killers"].items()):
k2 = []
kappend = []
@ -215,10 +216,9 @@ def on_transition_day6(evt, cli, var):
evt.data["killers"][victim] = k2
@event_listener("retribution_kill")
def on_retribution_kill(evt, cli, var, victim, orig_target):
t = evt.data["target"]
if t == "@wolves":
wolves = list_players(var.WOLF_ROLES)
def on_retribution_kill(evt, var, victim, orig_target):
if evt.data["target"] == "@wolves":
wolves = get_players(var.WOLF_ROLES)
evt.data["target"] = random.choice(wolves)
@event_listener("exchange_roles", priority=2)

View File

@ -90,7 +90,7 @@ def on_reconfigure_stats(evt, cli, var, stats):
stats["wolf cub"] = 0
@event_listener("transition_day_resolve_end")
def on_begin_day(evt, cli, var, victims):
def on_begin_day(evt, var, victims):
global ANGRY_WOLVES
ANGRY_WOLVES = False

View File

@ -3044,7 +3044,7 @@ def rename_player(var, user, prefix):
var.JESTERS, var.AMNESIACS, var.LYCANTHROPES, var.LUCKY, var.DISEASED,
var.MISDIRECTED, var.EXCHANGED, var.IMMUNIZED, var.CURED_LYCANS,
var.ALPHA_WOLVES, var.CURSED, var.CHARMERS, var.CHARMED, var.TOBECHARMED,
var.PRIESTS, var.CONSECRATING, var.DYING):
var.PRIESTS, var.CONSECRATING):
if prefix in setvar:
setvar.remove(prefix)
setvar.add(nick)
@ -3366,9 +3366,9 @@ def transition_day(cli, gameid=0):
chan = botconfig.CHANNEL
event_begin = Event("transition_day_begin", {})
event_begin.dispatch(cli, var)
event_begin.dispatch(var)
pl = list_players()
pl = get_players()
if not var.START_WITH_DAY or not var.FIRST_DAY:
if len(var.HEXED) < len(var.ROLES["hag"]):
@ -3381,20 +3381,20 @@ def transition_day(cli, gameid=0):
if var.FIRST_NIGHT:
# Select a random target for clone if they didn't choose someone
for clone in var.ROLES["clone"]:
if clone not in var.CLONED:
for clone in get_all_players(("clone",)):
if clone.nick not in var.CLONED:
ps = pl[:]
ps.remove(clone)
if len(ps) > 0:
target = random.choice(ps)
var.CLONED[clone] = target
pm(cli, clone, messages["random_clone"].format(target))
var.CLONED[clone.nick] = target.nick
clone.send(messages["random_clone"].format(target))
for mm in var.ROLES["matchmaker"]:
if mm not in var.MATCHMAKERS:
for mm in get_all_players(("matchmaker",)):
if mm.nick not in var.MATCHMAKERS:
lovers = random.sample(pl, 2)
choose.func(cli, mm, mm, lovers[0] + " " + lovers[1], sendmsg=False) # XXX: Old API
pm(cli, mm, messages["random_matchmaker"])
choose.func(mm.client, mm.nick, mm.nick, "{0[0]} {0[1]}".format(lovers), sendmsg=False) # XXX: Old API
mm.send(messages["random_matchmaker"])
# Reset daytime variables
var.INVESTIGATED = set()
@ -3445,9 +3445,9 @@ def transition_day(cli, gameid=0):
if ((target in var.HVISITED and var.HVISITED[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))
actor.send(messages["werecrow_success"].format(user))
else:
pm(cli, crow, messages["werecrow_failure"].format(target))
actor.send(messages["werecrow_failure"].format(user))
if var.START_WITH_DAY and var.FIRST_DAY:
# TODO: need to message everyone their roles and give a short thing saying "it's daytime"
@ -3482,7 +3482,7 @@ def transition_day(cli, gameid=0):
"bitten": [],
"numkills": {} # populated at priority 3
})
evt.dispatch(cli, var)
evt.dispatch(var)
victims = evt.data["victims"]
killers = evt.data["killers"]
bywolves = evt.data["bywolves"]
@ -3503,6 +3503,8 @@ def transition_day(cli, gameid=0):
new_wolf = False
if var.ALPHA_ENABLED: # check for bites
for (alpha, target) in var.BITE_PREFERENCES.items():
actor = users._get(alpha) # FIXME
user = users._get(target) # FIXME
# bite is now separate but some people may try to double up still, if bitten person is
# also being killed by wolves, make the kill not apply
# note that we cannot bite visiting harlots unless they are visiting a wolf,
@ -3519,48 +3521,48 @@ def transition_day(cli, gameid=0):
protected=protected,
bitten=bitten,
numkills=numkills)
bite_evt.dispatch(cli, var, alpha, target)
bite_evt.dispatch(var, actor, user)
if bite_evt.data["can_bite"] and not bite_evt.data["kill"]:
# mark them as bitten
got_bit = True
# if they were also being killed by wolves, undo that
if target in bywolves:
victims.remove(target)
bywolves.discard(target)
onlybywolves.discard(target)
killers[target].remove("@wolves")
if target not in victims:
victims_set.discard(target)
if user in bywolves:
victims.remove(user)
bywolves.discard(user)
onlybywolves.discard(user)
killers[user].remove("@wolves")
if user not in victims:
victims_set.discard(user)
if target in victims_set:
if user in victims_set:
# bite was unsuccessful due to someone else killing them
var.ALPHA_WOLVES.remove(alpha)
var.ALPHA_WOLVES.remove(actor.nick)
elif bite_evt.data["kill"]:
# target immunized or a lycan, kill them instead and refund the bite
var.ALPHA_WOLVES.remove(alpha)
if var.ACTIVE_PROTECTIONS[target]:
var.ALPHA_WOLVES.remove(actor.nick)
if var.ACTIVE_PROTECTIONS[user.nick]:
# target was protected
protected[target] = var.ACTIVE_PROTECTIONS[target].pop(0)
elif target in protected:
del protected[target]
protected[user] = var.ACTIVE_PROTECTIONS[user.nick].pop(0)
elif user in protected:
del protected[user]
# add them as a kill even if protected so that protection message plays
if target not in victims:
onlybywolves.add(target)
killers[target].append(alpha)
victims.append(target)
victims_set.add(target)
bywolves.add(target)
if user not in victims:
onlybywolves.add(user)
killers[user].append(actor)
victims.append(user)
victims_set.add(user)
bywolves.add(user)
elif got_bit:
new_wolf = True
bitten.append(target)
bitten.append(user)
else:
# bite failed due to some other reason (namely harlot)
var.ALPHA_WOLVES.remove(alpha)
var.ALPHA_WOLVES.remove(actor.nick)
if alpha in var.ALPHA_WOLVES:
pm(cli, alpha, messages["alpha_bite_success"].format(target))
else:
pm(cli, alpha, messages["alpha_bite_failure"].format(target))
to_send = "alpha_bite_failure"
if actor.nick in var.ALPHA_WOLVES:
to_send = "alpha_bite_success"
actor.send(messages[to_send].format(user))
var.BITE_PREFERENCES = {}
@ -3576,9 +3578,9 @@ def transition_day(cli, gameid=0):
for v in victims_set:
if v in var.DYING:
victims.append(v)
elif v in var.ROLES["bodyguard"] and angel.GUARDED.get(v) in victims_set:
elif v.nick in var.ROLES["bodyguard"] and v.nick in angel.GUARDED and users._get(angel.GUARDED[v.nick]) in victims_set: # FIXME
vappend.append(v)
elif v in var.ROLES["harlot"] and harlot.VISITED.get(v) in victims_set:
elif v.nick in var.ROLES["harlot"] and v.nick in harlot.VISITED and users._get(harlot.VISITED[v.nick]) in victims_set: # FIXME
vappend.append(v)
else:
victims.append(v)
@ -3592,18 +3594,18 @@ def transition_day(cli, gameid=0):
continue
prevlen = len(vappend)
for v in copy.copy(vappend):
if v in var.ROLES["bodyguard"] and angel.GUARDED.get(v) not in vappend:
for v in vappend[:]:
if v.nick in var.ROLES["bodyguard"] and users._get(angel.GUARDED.get(v.nick)) not in vappend: # FIXME
vappend.remove(v)
victims.append(v)
elif v in var.ROLES["harlot"] and harlot.VISITED.get(v) not in vappend:
elif v.nick in var.ROLES["harlot"] and users._get(harlot.VISITED.get(v.nick)) not in vappend: # FIXME
vappend.remove(v)
victims.append(v)
# Select a random target for assassin that isn't already going to die if they didn't target
pl = list_players()
for ass in var.ROLES["assassin"]:
if ass not in var.TARGETED and ass not in var.SILENCED:
pl = get_players()
for ass in get_all_players(("assassin",)):
if ass.nick not in var.TARGETED and ass.nick not in var.SILENCED:
ps = pl[:]
ps.remove(ass)
for victim in victims:
@ -3611,8 +3613,8 @@ def transition_day(cli, gameid=0):
ps.remove(victim)
if len(ps) > 0:
target = random.choice(ps)
var.TARGETED[ass] = target
pm(cli, ass, messages["assassin_random"].format(target))
var.TARGETED[ass.nick] = target.nick
ass.send(messages["assassin_random"].format(target))
message = [messages["sunrise"].format(min, sec)]
@ -3621,7 +3623,7 @@ def transition_day(cli, gameid=0):
var.ALPHA_ENABLED = False
dead = []
vlist = copy.copy(victims)
vlist = victims[:]
novictmsg = True
if new_wolf:
message.append(messages["new_wolf"])
@ -3646,35 +3648,39 @@ def transition_day(cli, gameid=0):
# In general, an event listener < 6 should both stop propagation and prevent default
# Priority 6 listeners add additional stuff to the default action and should not prevent default
for victim in vlist:
if not revt.dispatch(cli, var, victim):
if not revt.dispatch(var, victim):
continue
if (victim in var.ROLES["lycan"] or victim in var.LYCANTHROPES) and victim in revt.data["onlybywolves"] and victim not in var.IMMUNIZED:
vrole = get_role(victim)
if (victim.nick in var.ROLES["lycan"] or victim.nick in var.LYCANTHROPES) and victim in revt.data["onlybywolves"] and victim.nick not in var.IMMUNIZED:
vrole = get_main_role(victim)
if vrole not in var.WOLFCHAT_ROLES:
revt.data["message"].append(messages["new_wolf"])
var.EXTRA_WOLVES += 1
pm(cli, victim, messages["lycan_turn"])
var.LYCAN_ROLES[victim] = vrole
change_role(users._get(victim), vrole, "wolf") # FIXME
var.ROLES["lycan"].discard(victim) # in the event lycan was a template, we want to ensure it gets purged
wolves = list_players(var.WOLFCHAT_ROLES)
victim.send(messages["lycan_turn"])
var.LYCAN_ROLES[victim.nick] = vrole
change_role(victim, vrole, "wolf")
var.ROLES["lycan"].discard(victim.nick) # in the event lycan was a template, we want to ensure it gets purged
wolves = get_players(var.WOLFCHAT_ROLES)
random.shuffle(wolves)
wolves.remove(victim) # remove self from list
for i, wolf in enumerate(wolves):
pm(cli, wolf, messages["lycan_wc_notification"].format(victim))
role = get_role(wolf)
to_send = []
for wolf in wolves:
wolf.queue_message(messages["lycan_wc_notification"].format(victim))
role = get_main_role(wolf)
wevt = Event("wolflist", {"tags": set()})
wevt.dispatch(cli, var, wolf, victim)
wevt.dispatch(cli, var, wolf.nick, victim.nick)
tags = " ".join(wevt.data["tags"])
if tags:
tags += " "
wolves[i] = "\u0002{0}\u0002 ({1}{2})".format(wolf, tags, role)
to_send.append("\u0002{0}\u0002 ({1}{2})".format(wolf, tags, role))
pm(cli, victim, "Wolves: " + ", ".join(wolves))
if wolves:
wolf.send_messages()
victim.send("Wolves: " + ", ".join(to_send))
revt.data["novictmsg"] = False
elif victim not in revt.data["dead"]: # not already dead via some other means
if var.ROLE_REVEAL in ("on", "team"):
role = get_reveal_role(victim)
role = get_reveal_role(victim.nick)
an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
revt.data["message"].append(messages["death"].format(victim, an, role))
else:
@ -3723,7 +3729,7 @@ def transition_day(cli, gameid=0):
"protected": revt.data["protected"],
"bitten": revt.data["bitten"]
})
revt2.dispatch(cli, var, victims)
revt2.dispatch(var, victims)
message = revt2.data["message"]
novictmsg = revt2.data["novictmsg"]
dead = revt2.data["dead"]
@ -3734,32 +3740,31 @@ def transition_day(cli, gameid=0):
bitten = revt2.data["bitten"]
for victim in list(dead):
if victim in var.GUNNERS.keys() and var.GUNNERS[victim] > 0 and victim in bywolves:
if victim.nick in var.GUNNERS and var.GUNNERS[victim.nick] > 0 and victim in bywolves:
if random.random() < var.GUNNER_KILLS_WOLF_AT_NIGHT_CHANCE:
# pick a random wofl to be shot
woflset = {wolf for wolf in get_players(var.WOLF_ROLES) if wolf.nick not in dead}
woflset = {wolf for wolf in get_players(var.WOLF_ROLES) if wolf not in dead}
# TODO: split into werekitten.py
woflset.difference_update(get_players(("werekitten",)))
woflset.difference_update(get_all_players(("werekitten",)))
wolf_evt = Event("gunner_overnight_kill_wolflist", {"wolves": woflset})
wolf_evt.dispatch(var)
woflset = wolf_evt.data["wolves"]
if woflset:
deadwolf = random.choice(tuple(woflset))
deadwolf = deadwolf.nick # FIXME: remove when dead is converted to store users
if var.ROLE_REVEAL in ("on", "team"):
message.append(messages["gunner_killed_wolf_overnight"].format(victim, deadwolf, get_reveal_role(deadwolf)))
message.append(messages["gunner_killed_wolf_overnight"].format(victim, deadwolf, get_reveal_role(deadwolf.nick)))
else:
message.append(messages["gunner_killed_wolf_overnight_no_reveal"].format(victim, deadwolf))
dead.append(deadwolf)
var.GUNNERS[victim] -= 1 # deduct the used bullet
var.GUNNERS[victim.nick] -= 1 # deduct the used bullet
for victim in dead:
if victim in bywolves and victim in var.DISEASED:
if victim in bywolves and victim.nick in var.DISEASED:
var.DISEASED_WOLVES = True
if var.WOLF_STEALS_GUN and victim in bywolves and victim in var.GUNNERS.keys() and var.GUNNERS[victim] > 0:
if var.WOLF_STEALS_GUN and victim in bywolves and victim.nick in var.GUNNERS and var.GUNNERS[victim.nick] > 0:
# victim has bullets
try:
looters = list_players(var.WOLFCHAT_ROLES)
looters = get_players(var.WOLFCHAT_ROLES)
while len(looters) > 0:
guntaker = random.choice(looters) # random looter
if guntaker not in dead:
@ -3767,52 +3772,50 @@ def transition_day(cli, gameid=0):
else:
looters.remove(guntaker)
if guntaker not in dead:
numbullets = var.GUNNERS[victim]
if guntaker not in var.GUNNERS:
var.GUNNERS[guntaker] = 0
if guntaker not in var.ROLES["gunner"] and guntaker not in var.ROLES["sharpshooter"]:
var.ROLES["gunner"].add(guntaker)
var.GUNNERS[guntaker] += 1 # only transfer one bullet
mmsg = (messages["wolf_gunner"])
mmsg = mmsg.format(victim)
pm(cli, guntaker, mmsg)
numbullets = var.GUNNERS[victim.nick]
if guntaker.nick not in var.GUNNERS:
var.GUNNERS[guntaker.nick] = 0
if guntaker not in get_all_players(("gunner", "sharpshooter")):
var.ROLES["gunner"].add(guntaker.nick)
var.GUNNERS[guntaker.nick] += 1 # only transfer one bullet
guntaker.send(messages["wolf_gunner"].format(victim))
except IndexError:
pass # no wolves to give gun to (they were all killed during night or something)
var.GUNNERS[victim] = 0 # just in case
var.GUNNERS[victim.nick] = 0 # just in case
cli.msg(chan, "\n".join(message))
channels.Main.send("\n".join(message))
for chump in bitten:
# turn all bitten people into wolves
# short-circuit if they are already a wolf or are dying
chumprole = get_role(chump)
chumprole = get_main_role(chump)
if chump in dead or chumprole in var.WOLF_ROLES:
continue
newrole = "wolf"
if chumprole == "guardian angel":
pm(cli, chump, messages["fallen_angel_turn"])
chump.send(messages["fallen_angel_turn"])
# fallen angels also automatically gain the assassin template if they don't already have it
newrole = "fallen angel"
var.ROLES["assassin"].add(chump)
debuglog("{0} ({1}) TURNED FALLEN ANGEL".format(chump, chumprole))
var.ROLES["assassin"].add(chump.nick)
debuglog("{0} (guardian angel) TURNED FALLEN ANGEL".format(chump))
elif chumprole in ("seer", "oracle", "augur"):
pm(cli, chump, messages["seer_turn"])
chump.send(messages["seer_turn"])
newrole = "doomsayer"
debuglog("{0} ({1}) TURNED DOOMSAYER".format(chump, chumprole))
elif chumprole in var.TOTEM_ORDER:
pm(cli, chump, messages["shaman_turn"])
chump.send(messages["shaman_turn"])
newrole = "wolf shaman"
debuglog("{0} ({1}) TURNED WOLF SHAMAN".format(chump, chumprole))
elif chumprole == "harlot":
pm(cli, chump, messages["harlot_turn"])
debuglog("{0} ({1}) TURNED WOLF".format(chump, chumprole))
chump.send(messages["harlot_turn"])
debuglog("{0} (harlot) TURNED WOLF".format(chump))
else:
pm(cli, chump, messages["bitten_turn"])
chump.send(messages["bitten_turn"])
debuglog("{0} ({1}) TURNED WOLF".format(chump, chumprole))
var.BITTEN_ROLES[chump] = chumprole
change_role(users._get(chump), chumprole, newrole) # FIXME
relay_wolfchat_command(cli, chump, messages["wolfchat_new_member"].format(chump, newrole), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
var.BITTEN_ROLES[chump.nick] = chumprole
change_role(chump, chumprole, newrole)
relay_wolfchat_command(cli, chump.nick, messages["wolfchat_new_member"].format(chump, newrole), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
killer_role = {}
for deadperson in dead:
@ -3821,19 +3824,20 @@ def transition_day(cli, gameid=0):
if killer == "@wolves":
killer_role[deadperson] = "wolf"
else:
killer_role[deadperson] = get_role(killer)
killer_role[deadperson] = get_main_role(killer)
else:
# no killers, so assume suicide
killer_role[deadperson] = get_role(deadperson)
killer_role[deadperson] = get_main_role(deadperson)
dead_nicks = [p.nick for p in dead] # FIXME: Update once del_player has been updated
for deadperson in dead:
# check if they have already been killed since del_player could do chain reactions and we want
# to avoid sending duplicate messages.
if deadperson in list_players():
del_player(cli, deadperson, end_game=False, killer_role=killer_role[deadperson], deadlist=dead, original=deadperson)
if deadperson in get_players():
del_player(cli, deadperson.nick, end_game=False, killer_role=killer_role[deadperson], deadlist=dead_nicks, original=deadperson.nick)
event_end = Event("transition_day_end", {"begin_day": begin_day})
event_end.dispatch(cli, var)
event_end.dispatch(var)
if chk_win(cli): # if after the last person is killed, one side wins, then actually end the game here
return
@ -3841,7 +3845,7 @@ def transition_day(cli, gameid=0):
event_end.data["begin_day"](cli)
@event_listener("transition_day_resolve_end", priority=2)
def on_transition_day_resolve_end(evt, cli, var, victims):
def on_transition_day_resolve_end(evt, var, victims):
if evt.data["novictmsg"] and len(evt.data["dead"]) == 0:
evt.data["message"].append(random.choice(messages["no_victims"]) + messages["no_victims_append"])