Split turncoat and convert some of the exchange_roles listeners into new_role (#342)
- Split turncoat - Add `new_role` and `swap_role_state` events, convert some `exchange_roles` listeners to them (handles both exchange as well as roleswaps such as clone->X or traitor->wolf) - Refactor change_role(). Calling that is all that is needed for a roleswap now (no boilerplate) - Always give player list to new wolf roles. This does mean they'll get double lists in some cases, dealwithit.jpg - Make exchange totem no-op due to technical issues until we get role classes set up (exchanging role state across two new_role listeners doesn't work very well when the listeners get rid of old state)
This commit is contained in:
parent
7d2eefd12a
commit
41262a148a
@ -196,10 +196,9 @@
|
|||||||
"single_winner": "The winner is \u0002{0}\u0002.",
|
"single_winner": "The winner is \u0002{0}\u0002.",
|
||||||
"two_winners": "The winners are \u0002{0}\u0002 and \u0002{1}\u0002.",
|
"two_winners": "The winners are \u0002{0}\u0002 and \u0002{1}\u0002.",
|
||||||
"many_winners": "The winners are {0}, and \u0002{1}\u0002.",
|
"many_winners": "The winners are {0}, and \u0002{1}\u0002.",
|
||||||
"clone_turn": "You are now a{0} \u0002{1}\u0002.",
|
"new_role": "You are now a{0} \u0002{1}\u0002.",
|
||||||
"forever_aclone": "It appears that \u0002{0}\u0002 was cloning you, so you are now stuck as a clone forever. How sad.",
|
"forever_aclone": "It appears that \u0002{0}\u0002 was cloning you, so you are now stuck as a clone forever. How sad.",
|
||||||
"clone_success": "You will now be cloning \u0002{0}\u0002 if they die.",
|
"clone_success": "You will now be cloning \u0002{0}\u0002 if they die.",
|
||||||
"clone_wolf": "\u0002{0}\u0002 cloned \u0002{1}\u0002 and has now become a wolf!",
|
|
||||||
"no_other_wolves": "There are no other wolves.",
|
"no_other_wolves": "There are no other wolves.",
|
||||||
"has_minions": "You have \u0002{0}\u0002 {1} at your command!",
|
"has_minions": "You have \u0002{0}\u0002 {1} at your command!",
|
||||||
"lover_suicide": "Saddened by the loss of their lover, \u0002{0}\u0002, a{1} \u0002{2}\u0002, commits suicide.",
|
"lover_suicide": "Saddened by the loss of their lover, \u0002{0}\u0002, a{1} \u0002{2}\u0002, commits suicide.",
|
||||||
@ -223,7 +222,6 @@
|
|||||||
"hunter_discard": "Your target has died, so you may now pick a new one.",
|
"hunter_discard": "Your target has died, so you may now pick a new one.",
|
||||||
"wild_child_already_picked": "You have already picked your idol for this game.",
|
"wild_child_already_picked": "You have already picked your idol for this game.",
|
||||||
"wild_child_success": "You have picked {0} to be your idol for this game.",
|
"wild_child_success": "You have picked {0} to be your idol for this game.",
|
||||||
"wild_child_as_wolf": "\u0002{0}\u0002's idol has died, and is now a \u0002wolf\u0002!",
|
|
||||||
"wild_child_random_idol": "Upon waking up, the first person you see is \u0002{0}\u0002, and they become your idol.",
|
"wild_child_random_idol": "Upon waking up, the first person you see is \u0002{0}\u0002, and they become your idol.",
|
||||||
"wild_child_revealroles_picked": "picked {0} as idol",
|
"wild_child_revealroles_picked": "picked {0} as idol",
|
||||||
"wild_child_revealroles_no_idol": "no idol picked yet",
|
"wild_child_revealroles_no_idol": "no idol picked yet",
|
||||||
@ -281,7 +279,6 @@
|
|||||||
"angel_protection": "\u0002{0}\u0002 was attacked last night, but luckily, the guardian angel was on duty.",
|
"angel_protection": "\u0002{0}\u0002 was attacked last night, but luckily, the guardian angel was on duty.",
|
||||||
"bodyguard_protection": "\u0002{0}\u0002 sacrificed their life to guard that of another.",
|
"bodyguard_protection": "\u0002{0}\u0002 sacrificed their life to guard that of another.",
|
||||||
"lycan_turn": "HOOOOOOOOOWL. You have become... a wolf!",
|
"lycan_turn": "HOOOOOOOOOWL. You have become... a wolf!",
|
||||||
"lycan_wc_notification": "\u0002{0}\u0002 is now a wolf!",
|
|
||||||
"totem_banish": "\u0002{0}\u0002's totem emitted a brilliant flash of light last night. It appears that \u0002{1}\u0002's spirit was driven away by the flash.",
|
"totem_banish": "\u0002{0}\u0002's totem emitted a brilliant flash of light last night. It appears that \u0002{1}\u0002's spirit was driven away by the flash.",
|
||||||
"totem_death": "\u0002{0}\u0002's totem emitted a brilliant flash of light last night. The dead body of \u0002{1}\u0002, a{2} \u0002{3}\u0002, was found at the scene.",
|
"totem_death": "\u0002{0}\u0002's totem emitted a brilliant flash of light last night. The dead body of \u0002{1}\u0002, a{2} \u0002{3}\u0002, was found at the scene.",
|
||||||
"totem_death_no_reveal": "\u0002{0}\u0002's totem emitted a brilliant flash of light last night. The dead body of \u0002{1}\u0002 was found at the scene.",
|
"totem_death_no_reveal": "\u0002{0}\u0002's totem emitted a brilliant flash of light last night. The dead body of \u0002{1}\u0002 was found at the scene.",
|
||||||
@ -453,9 +450,8 @@
|
|||||||
"fallen_angel_turn": "While out last night, you were overpowered by a large werewolf and bitten. Shortly thereafter, you found your wings turning black as night and sadistic thoughts infiltrating your mind...",
|
"fallen_angel_turn": "While out last night, you were overpowered by a large werewolf and bitten. Shortly thereafter, you found your wings turning black as night and sadistic thoughts infiltrating your mind...",
|
||||||
"harlot_turn": "While out visiting last night, you were overpowered by a large werewolf and bitten. Shortly thereafter, you found yourself turning into a werewolf yourself!",
|
"harlot_turn": "While out visiting last night, you were overpowered by a large werewolf and bitten. Shortly thereafter, you found yourself turning into a werewolf yourself!",
|
||||||
"bitten_turn": "You woke suddenly last night to a sharp pain, as you were bit by a large werewolf. Shortly thereafter, you found yourself turning into a werewolf yourself!",
|
"bitten_turn": "You woke suddenly last night to a sharp pain, as you were bit by a large werewolf. Shortly thereafter, you found yourself turning into a werewolf yourself!",
|
||||||
"wolfchat_new_member": "\u0002{0}\u0002 is now a \u0002{1}\u0002!",
|
"wolfchat_new_member": "\u0002{0}\u0002 is now a{1} \u0002{2}\u0002!",
|
||||||
"amnesia_clear": "Your amnesia clears and you now remember that you are {0} \u0002{1}\u0002!",
|
"amnesia_clear": "Your amnesia clears and you now remember that you are {0} \u0002{1}\u0002!",
|
||||||
"amnesia_wolfchat": "\u0002{0}\u0002 is now a \u0002{1}\u0002!",
|
|
||||||
"wolf_notify": "You are a \u0002{0}wolf\u0002. It is your job to kill all the villagers. Use \"kill <nick>\" to kill a villager.",
|
"wolf_notify": "You are a \u0002{0}wolf\u0002. It is your job to kill all the villagers. Use \"kill <nick>\" to kill a villager.",
|
||||||
"cursed_traitor_notify": "You are a \u0002{0}cursed traitor\u0002. Normally, you would be seen as a villager by the seer and oracle, but since you're cursed, you are seen as a wolf.",
|
"cursed_traitor_notify": "You are a \u0002{0}cursed traitor\u0002. Normally, you would be seen as a villager by the seer and oracle, but since you're cursed, you are seen as a wolf.",
|
||||||
"traitor_notify": "You are a \u0002{0}traitor\u0002. You are exactly like a villager and not even a seer or oracle can see your true identity, only detectives and augurs can.",
|
"traitor_notify": "You are a \u0002{0}traitor\u0002. You are exactly like a villager and not even a seer or oracle can see your true identity, only detectives and augurs can.",
|
||||||
@ -737,7 +733,6 @@
|
|||||||
"sleepy_nightmare_death": "As the sun starts rising, your legs give out, causing the beast to descend upon you and snuff out your life.",
|
"sleepy_nightmare_death": "As the sun starts rising, your legs give out, causing the beast to descend upon you and snuff out your life.",
|
||||||
"sleepy_priest_death": "The sky suddenly darkens as a thunderstorm appears from nowhere. The bell on the newly-abandoned church starts ringing in sinister tones before the building is struck repeatedly by lightning, setting it alight in a raging inferno...",
|
"sleepy_priest_death": "The sky suddenly darkens as a thunderstorm appears from nowhere. The bell on the newly-abandoned church starts ringing in sinister tones before the building is struck repeatedly by lightning, setting it alight in a raging inferno...",
|
||||||
"sleepy_doomsayer_turn": "You feel something rushing into you and taking control over your mind and body. It causes you to rapidly start transforming into a werewolf, and you realize your vision powers can now be used to inflict malady on the unwary. You are now a \u0002doomsayer\u0002.",
|
"sleepy_doomsayer_turn": "You feel something rushing into you and taking control over your mind and body. It causes you to rapidly start transforming into a werewolf, and you realize your vision powers can now be used to inflict malady on the unwary. You are now a \u0002doomsayer\u0002.",
|
||||||
"sleepy_doomsayer_wolfchat": "\u0002{0}\u0002 is now a \u0002doomsayer\u0002.",
|
|
||||||
"sleepy_succubus_turn": "You feel something rushing into you and taking control over your mind and body. You are now a \u0002succubus\u0002. Your job is to entrance the village, bringing them all under your absolute control.",
|
"sleepy_succubus_turn": "You feel something rushing into you and taking control over your mind and body. You are now a \u0002succubus\u0002. Your job is to entrance the village, bringing them all under your absolute control.",
|
||||||
"sleepy_demoniac_turn": "You feel something rushing into you and taking control over your mind and body, showing you your new purpose in life. There are far greater evils than the wolves lurking in the shadows, and by sacrificing all of the wolves, you can unleash those evils upon the world. You are now a \u0002demoniac\u0002.",
|
"sleepy_demoniac_turn": "You feel something rushing into you and taking control over your mind and body, showing you your new purpose in life. There are far greater evils than the wolves lurking in the shadows, and by sacrificing all of the wolves, you can unleash those evils upon the world. You are now a \u0002demoniac\u0002.",
|
||||||
"fquit_fail": "Forcing a live player to leave must be done in channel.",
|
"fquit_fail": "Forcing a live player to leave must be done in channel.",
|
||||||
@ -781,7 +776,7 @@
|
|||||||
"vengeful_role": "You are a \u0002vengeful ghost\u0002 who is against the \u0002{0}\u0002.",
|
"vengeful_role": "You are a \u0002vengeful ghost\u0002 who is against the \u0002{0}\u0002.",
|
||||||
"show_role": "You are a{0} \u0002{1}\u0002.",
|
"show_role": "You are a{0} \u0002{1}\u0002.",
|
||||||
"original_wolves": "Original wolves: {0}",
|
"original_wolves": "Original wolves: {0}",
|
||||||
"turncoat_side": "Current side: \u0002{0}\u0002.",
|
"turncoat_side": "You are {0}.",
|
||||||
"assassin_role_info": "You are an \u0002assassin\u0002{0}.",
|
"assassin_role_info": "You are an \u0002assassin\u0002{0}.",
|
||||||
"assassin_targeting": " and targeting {0}",
|
"assassin_targeting": " and targeting {0}",
|
||||||
"bitten_info": "You were bitten by an alpha wolf and have \u0002{0} night{1}\u0002 until your transformation.",
|
"bitten_info": "You were bitten by an alpha wolf and have \u0002{0} night{1}\u0002 until your transformation.",
|
||||||
|
@ -5,7 +5,7 @@ from src import users
|
|||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"get_players", "get_all_players", "get_participants",
|
"get_players", "get_all_players", "get_participants",
|
||||||
"get_target",
|
"get_target", "change_role"
|
||||||
"get_main_role", "get_all_roles", "get_reveal_role",
|
"get_main_role", "get_all_roles", "get_reveal_role",
|
||||||
"is_known_wolf_ally",
|
"is_known_wolf_ally",
|
||||||
]
|
]
|
||||||
@ -66,6 +66,34 @@ def get_target(var, wrapper, message, *, allow_self=False, allow_bot=False, not_
|
|||||||
|
|
||||||
return match
|
return match
|
||||||
|
|
||||||
|
def change_role(var, player, oldrole, newrole, *, inherit_from=None, message="new_role"):
|
||||||
|
# in_wolfchat is filled as part of priority 4
|
||||||
|
# if you wish to modify evt.data["role"], do so in priority 3 or sooner
|
||||||
|
evt = Event("new_role",
|
||||||
|
{"role": newrole, "messages": [], "in_wolfchat": False},
|
||||||
|
inherit_from=inherit_from)
|
||||||
|
evt.dispatch(var, player, oldrole)
|
||||||
|
newrole = evt.data["role"]
|
||||||
|
|
||||||
|
var.ROLES[oldrole].remove(player)
|
||||||
|
var.ROLES[newrole].add(player)
|
||||||
|
# only adjust MAIN_ROLES/FINAL_ROLES if we're changing the player's actual role
|
||||||
|
if var.MAIN_ROLES[player] == oldrole:
|
||||||
|
var.MAIN_ROLES[player] = newrole
|
||||||
|
var.FINAL_ROLES[player.nick] = newrole
|
||||||
|
|
||||||
|
sayrole = newrole
|
||||||
|
if sayrole in var.HIDDEN_VILLAGERS:
|
||||||
|
sayrole = "villager"
|
||||||
|
elif sayrole in var.HIDDEN_ROLES:
|
||||||
|
sayrole = var.DEFAULT_ROLE
|
||||||
|
an = "n" if sayrole.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
|
||||||
|
player.send(messages[message].format(an, sayrole))
|
||||||
|
player.send(*evt.data["messages"])
|
||||||
|
|
||||||
|
return newrole
|
||||||
|
|
||||||
def get_main_role(user):
|
def get_main_role(user):
|
||||||
role = var.MAIN_ROLES.get(user)
|
role = var.MAIN_ROLES.get(user)
|
||||||
if role is not None:
|
if role is not None:
|
||||||
|
@ -10,7 +10,7 @@ import botconfig
|
|||||||
import src.settings as var
|
import src.settings as var
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.functions import get_players, get_all_players, get_main_role
|
from src.functions import get_players, get_all_players, get_main_role, change_role
|
||||||
from src.decorators import handle_error, command
|
from src.decorators import handle_error, command
|
||||||
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
||||||
from src import events, channels, users
|
from src import events, channels, users
|
||||||
@ -870,6 +870,7 @@ class SleepyMode(GameMode):
|
|||||||
self.TEMPLATE_RESTRICTIONS["prophet"] = frozenset(self.ROLE_GUIDE.keys()) - {"priest", "blessed villager", "prophet"}
|
self.TEMPLATE_RESTRICTIONS["prophet"] = frozenset(self.ROLE_GUIDE.keys()) - {"priest", "blessed villager", "prophet"}
|
||||||
# this ensures that village drunk will always receive the gunner template
|
# this ensures that village drunk will always receive the gunner template
|
||||||
self.TEMPLATE_RESTRICTIONS["gunner"] = frozenset(self.ROLE_GUIDE.keys()) - {"village drunk", "cursed villager", "gunner"}
|
self.TEMPLATE_RESTRICTIONS["gunner"] = frozenset(self.ROLE_GUIDE.keys()) - {"village drunk", "cursed villager", "gunner"}
|
||||||
|
self.cmd_params = dict(chan=False, pm=True, playing=True, phases=("night",))
|
||||||
# disable wolfchat
|
# disable wolfchat
|
||||||
#self.RESTRICT_WOLFCHAT = 0x0f
|
#self.RESTRICT_WOLFCHAT = 0x0f
|
||||||
|
|
||||||
@ -879,13 +880,17 @@ class SleepyMode(GameMode):
|
|||||||
events.add_listener("chk_nightdone", self.prolong_night)
|
events.add_listener("chk_nightdone", self.prolong_night)
|
||||||
events.add_listener("transition_day_begin", self.nightmare_kill)
|
events.add_listener("transition_day_begin", self.nightmare_kill)
|
||||||
events.add_listener("del_player", self.happy_fun_times)
|
events.add_listener("del_player", self.happy_fun_times)
|
||||||
self.north_cmd = command("north", "n", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "n"))
|
events.add_listener("revealroles", self.on_revealroles)
|
||||||
self.east_cmd = command("east", "e", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "e"))
|
|
||||||
self.south_cmd = command("south", "s", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "s"))
|
|
||||||
self.west_cmd = command("west", "w", chan=False, pm=True, playing=True, phases=("night",))(functools.partial(self.move, "w"))
|
|
||||||
|
|
||||||
self.having_nightmare = UserList()
|
self.having_nightmare = UserList()
|
||||||
|
|
||||||
|
cmd_params = dict(chan=False, pm=True, playing=True, phases=("night",), users=self.having_nightmare)
|
||||||
|
|
||||||
|
self.north_cmd = command("north", "n", **cmd_params)(functools.partial(self.move, "n"))
|
||||||
|
self.east_cmd = command("east", "e", **cmd_params)(functools.partial(self.move, "e"))
|
||||||
|
self.south_cmd = command("south", "s", **cmd_params)(functools.partial(self.move, "s"))
|
||||||
|
self.west_cmd = command("west", "w", **cmd_params)(functools.partial(self.move, "w"))
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
from src import decorators
|
from src import decorators
|
||||||
events.remove_listener("dullahan_targets", self.dullahan_targets)
|
events.remove_listener("dullahan_targets", self.dullahan_targets)
|
||||||
@ -893,6 +898,8 @@ class SleepyMode(GameMode):
|
|||||||
events.remove_listener("chk_nightdone", self.prolong_night)
|
events.remove_listener("chk_nightdone", self.prolong_night)
|
||||||
events.remove_listener("transition_day_begin", self.nightmare_kill)
|
events.remove_listener("transition_day_begin", self.nightmare_kill)
|
||||||
events.remove_listener("del_player", self.happy_fun_times)
|
events.remove_listener("del_player", self.happy_fun_times)
|
||||||
|
events.remove_listener("revealroles", self.on_revealroles)
|
||||||
|
|
||||||
def remove_command(name, command):
|
def remove_command(name, command):
|
||||||
if len(decorators.COMMANDS[name]) > 1:
|
if len(decorators.COMMANDS[name]) > 1:
|
||||||
decorators.COMMANDS[name].remove(command)
|
decorators.COMMANDS[name].remove(command)
|
||||||
@ -909,9 +916,8 @@ class SleepyMode(GameMode):
|
|||||||
|
|
||||||
self.having_nightmare.clear()
|
self.having_nightmare.clear()
|
||||||
|
|
||||||
def dullahan_targets(self, evt, var, dullahans, max_targets):
|
def dullahan_targets(self, evt, var, dullahan, max_targets):
|
||||||
for dull in dullahans:
|
evt.data["targets"].update(var.ROLES["priest"])
|
||||||
evt.data["targets"][dull] = UserSet(var.ROLES["priest"])
|
|
||||||
|
|
||||||
def setup_nightmares(self, evt, var):
|
def setup_nightmares(self, evt, var):
|
||||||
if random.random() < 1/5:
|
if random.random() < 1/5:
|
||||||
@ -991,8 +997,6 @@ class SleepyMode(GameMode):
|
|||||||
self.nightmare_step()
|
self.nightmare_step()
|
||||||
|
|
||||||
def move(self, direction, var, wrapper, message):
|
def move(self, direction, var, wrapper, message):
|
||||||
if not self.having_nightmare or self.having_nightmare[0] is not wrapper.source:
|
|
||||||
return
|
|
||||||
opposite = {"n": "s", "e": "w", "s": "n", "w": "e"}
|
opposite = {"n": "s", "e": "w", "s": "n", "w": "e"}
|
||||||
if self.prev_direction == opposite[direction]:
|
if self.prev_direction == opposite[direction]:
|
||||||
wrapper.pm(messages["sleepy_nightmare_invalid_direction"])
|
wrapper.pm(messages["sleepy_nightmare_invalid_direction"])
|
||||||
@ -1043,17 +1047,17 @@ class SleepyMode(GameMode):
|
|||||||
cultists = [p for p in get_players(("cultist",)) if p in pl and random.random() < turn_chance]
|
cultists = [p for p in get_players(("cultist",)) if p in pl and random.random() < turn_chance]
|
||||||
channels.Main.send(messages["sleepy_priest_death"])
|
channels.Main.send(messages["sleepy_priest_death"])
|
||||||
for seer in seers:
|
for seer in seers:
|
||||||
change_role(seer, "seer", "doomsayer")
|
change_role(var, seer, "seer", "doomsayer", message="sleepy_doomsayer_turn")
|
||||||
seer.send(messages["sleepy_doomsayer_turn"])
|
|
||||||
relay_wolfchat_command(seer.client, seer.nick, messages["sleepy_doomsayer_wolfchat"].format(seer), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
|
|
||||||
for harlot in harlots:
|
for harlot in harlots:
|
||||||
change_role(harlot, "harlot", "succubus")
|
change_role(var, harlot, "harlot", "succubus", message="sleepy_succubus_turn")
|
||||||
harlot.send(messages["sleepy_succubus_turn"])
|
|
||||||
for cultist in cultists:
|
for cultist in cultists:
|
||||||
change_role(cultist, "cultist", "demoniac")
|
change_role(var, cultist, "cultist", "demoniac", message="sleepy_demoniac_turn")
|
||||||
cultist.send(messages["sleepy_demoniac_turn"])
|
|
||||||
# NOTE: chk_win is called by del_player, don't need to call it here even though this has a chance of ending game
|
# NOTE: chk_win is called by del_player, don't need to call it here even though this has a chance of ending game
|
||||||
|
|
||||||
|
def on_revealroles(self, evt, var, wrapper):
|
||||||
|
if self.having_nightmare:
|
||||||
|
evt.data["output"].append("\u0002having nightmare\u0002: {0}".format(self.having_nightmare[0]))
|
||||||
|
|
||||||
@game_mode("maelstrom", minp=8, maxp=24, likelihood=0)
|
@game_mode("maelstrom", minp=8, maxp=24, likelihood=0)
|
||||||
class MaelstromMode(GameMode):
|
class MaelstromMode(GameMode):
|
||||||
"""Some people just want to watch the world burn."""
|
"""Some people just want to watch the world burn."""
|
||||||
@ -1148,7 +1152,7 @@ class MaelstromMode(GameMode):
|
|||||||
COMMANDS["myrole"][0].caller(wrapper.source.client, wrapper.source.nick, wrapper.target.name, "") # FIXME: New/old API
|
COMMANDS["myrole"][0].caller(wrapper.source.client, wrapper.source.nick, wrapper.target.name, "") # FIXME: New/old API
|
||||||
# if they're a wolfchat role, alert the other wolves
|
# if they're a wolfchat role, alert the other wolves
|
||||||
if role in var.WOLFCHAT_ROLES:
|
if role in var.WOLFCHAT_ROLES:
|
||||||
relay_wolfchat_command(wrapper.source.client, wrapper.source.nick, messages["wolfchat_new_member"].format(wrapper.source.nick, role), var.WOLFCHAT_ROLES, is_wolf_command=True, is_kill_command=True)
|
relay_wolfchat_command(wrapper.source.client, wrapper.source.nick, messages["wolfchat_new_member"].format(wrapper.source.nick, "", role), var.WOLFCHAT_ROLES, is_wolf_command=True, is_kill_command=True)
|
||||||
# TODO: make this part of !myrole instead, no reason we can't give out wofllist in that
|
# TODO: make this part of !myrole instead, no reason we can't give out wofllist in that
|
||||||
wolves = list_players(var.WOLFCHAT_ROLES)
|
wolves = list_players(var.WOLFCHAT_ROLES)
|
||||||
pl = get_players()
|
pl = get_players()
|
||||||
|
@ -23,7 +23,7 @@ def setup_variables(rolename, *, send_role, types):
|
|||||||
def on_transition_night_end(evt, var):
|
def on_transition_night_end(evt, var):
|
||||||
villagers = set(get_players(("priest", "doctor")))
|
villagers = set(get_players(("priest", "doctor")))
|
||||||
win_stealers = set(get_players(("fool", "monster", "demoniac")))
|
win_stealers = set(get_players(("fool", "monster", "demoniac")))
|
||||||
neutrals = set(get_players(("turncoat", "jester")))
|
neutrals = set(get_players(("jester",)))
|
||||||
|
|
||||||
special_evt = Event("get_special", {"villagers": villagers, "wolves": set(), "win_stealers": win_stealers, "neutrals": neutrals})
|
special_evt = Event("get_special", {"villagers": villagers, "wolves": set(), "win_stealers": win_stealers, "neutrals": neutrals})
|
||||||
special_evt.dispatch(var)
|
special_evt.dispatch(var)
|
||||||
|
@ -26,12 +26,10 @@ def setup_variables(rolename):
|
|||||||
def on_get_special(evt, var):
|
def on_get_special(evt, var):
|
||||||
evt.data["villagers"].update(get_players((rolename,)))
|
evt.data["villagers"].update(get_players((rolename,)))
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("new_role")
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
def on_new_role(evt, var, user, old_role):
|
||||||
if actor_role == rolename and target_role != rolename:
|
if old_role == rolename and evt.data["role"] != rolename:
|
||||||
SEEN.discard(actor)
|
SEEN.discard(user)
|
||||||
elif target_role == rolename and actor_role != rolename:
|
|
||||||
SEEN.discard(target)
|
|
||||||
|
|
||||||
@event_listener("chk_nightdone")
|
@event_listener("chk_nightdone")
|
||||||
def on_chk_nightdone(evt, var):
|
def on_chk_nightdone(evt, var):
|
||||||
|
@ -6,7 +6,7 @@ from collections import defaultdict
|
|||||||
|
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import channels, users, debuglog, errlog, plog
|
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, is_known_wolf_ally
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target, is_known_wolf_ally, change_role
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
@ -29,12 +29,6 @@ def _get_blacklist(var):
|
|||||||
blacklist.add("matchmaker")
|
blacklist.add("matchmaker")
|
||||||
return blacklist
|
return blacklist
|
||||||
|
|
||||||
@event_listener("role_assignment")
|
|
||||||
def on_role_assignment(evt, var, gamemode, pl):
|
|
||||||
roles = var.ROLE_GUIDE.keys() - _get_blacklist(var)
|
|
||||||
for amnesiac in get_all_players(("amnesiac",)):
|
|
||||||
ROLES[amnesiac] = random.choice(list(roles))
|
|
||||||
|
|
||||||
@event_listener("transition_night_begin")
|
@event_listener("transition_night_begin")
|
||||||
def on_transition_night_begin(evt, var):
|
def on_transition_night_begin(evt, var):
|
||||||
global STATS_FLAG
|
global STATS_FLAG
|
||||||
@ -44,34 +38,12 @@ def on_transition_night_begin(evt, var):
|
|||||||
STATS_FLAG = True
|
STATS_FLAG = True
|
||||||
|
|
||||||
for amn in amnesiacs:
|
for amn in amnesiacs:
|
||||||
role = ROLES[amn]
|
role = change_role(var, amn, "amnesiac", ROLES[amn], message="amnesia_clear")
|
||||||
change_role(amn, "amnesiac", role)
|
debuglog("{0} REMEMBER: {1}".format(amn, role))
|
||||||
evt = Event("new_role", {})
|
|
||||||
evt.dispatch(var, amn, role)
|
|
||||||
if var.FIRST_NIGHT: # we don't need to tell them twice if they remember right away
|
|
||||||
continue
|
|
||||||
showrole = role
|
|
||||||
if showrole in var.HIDDEN_VILLAGERS:
|
|
||||||
showrole = "villager"
|
|
||||||
elif showrole in var.HIDDEN_ROLES:
|
|
||||||
showrole = var.DEFAULT_ROLE
|
|
||||||
a = "a"
|
|
||||||
if showrole.startswith(("a", "e", "i", "o", "u")):
|
|
||||||
a = "an"
|
|
||||||
amn.send(messages["amnesia_clear"].format(a, showrole))
|
|
||||||
if is_known_wolf_ally(amn, amn):
|
|
||||||
if role in var.WOLF_ROLES:
|
|
||||||
relay_wolfchat_command(amn.client, amn.nick, messages["amnesia_wolfchat"].format(amn, showrole), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
|
|
||||||
else:
|
|
||||||
relay_wolfchat_command(amn.client, amn.nick, messages["amnesia_wolfchat"].format(amn, showrole), var.WOLFCHAT_ROLES)
|
|
||||||
|
|
||||||
debuglog("{0} REMEMBER: {1} as {2}".format(amn, role, showrole))
|
|
||||||
|
|
||||||
@event_listener("new_role")
|
@event_listener("new_role")
|
||||||
def on_new_role(evt, var, user, role):
|
def doctor_new_role(evt, var, user, old_role):
|
||||||
if role == "turncoat": # FIXME: Need to split into turncoat.py when split
|
if evt.data["role"] == "doctor": # FIXME: Need to split into doctor.py when split
|
||||||
var.TURNCOATS[user.nick] = ("none", -1)
|
|
||||||
if role == "doctor": # FIXME: Need to split into doctor.py when split
|
|
||||||
var.DOCTORS[user.nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(get_players()))
|
var.DOCTORS[user.nick] = math.ceil(var.DOCTOR_IMMUNIZATION_MULTIPLIER * len(get_players()))
|
||||||
|
|
||||||
@event_listener("investigate")
|
@event_listener("investigate")
|
||||||
@ -79,28 +51,17 @@ def on_investigate(evt, var, actor, target):
|
|||||||
if evt.data["role"] == "amnesiac":
|
if evt.data["role"] == "amnesiac":
|
||||||
evt.data["role"] = ROLES[target]
|
evt.data["role"] = ROLES[target]
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("new_role", priority=1) # Exchange, clone, etc. - assign the amnesiac's final role
|
||||||
def on_exchange_roles(evt, var, actor, target, actor_role, target_role):
|
def update_amnesiac(evt, var, user, old_role):
|
||||||
# FIXME: exchange totem messes with var.HIDDEN_AMNESIAC (the new amnesiac is no longer hidden should they die)
|
# FIXME: exchange totem messes with var.HIDDEN_AMNESIAC (the new amnesiac is no longer hidden should they die)
|
||||||
if actor_role == "amnesiac":
|
if evt.params.inherit_from is not None and evt.data["role"] == "amnesiac" and old_role != "amnesiac":
|
||||||
actor_role = ROLES[actor]
|
evt.data["role"] = ROLES[evt.params.inherit_from]
|
||||||
if target in ROLES:
|
|
||||||
ROLES[actor] = ROLES[target]
|
|
||||||
ROLES[target] = actor_role
|
|
||||||
else:
|
|
||||||
del ROLES[actor]
|
|
||||||
ROLES[target] = actor_role
|
|
||||||
|
|
||||||
if target_role == "amnesiac":
|
@event_listener("new_role")
|
||||||
if actor not in ROLES:
|
def on_new_role(evt, var, user, old_role):
|
||||||
target_role = ROLES[target]
|
if evt.params.inherit_from is None and evt.data["role"] == "amnesiac":
|
||||||
ROLES[actor] = target_role
|
roles = var.ROLE_GUIDE.keys() - _get_blacklist(var)
|
||||||
del ROLES[target]
|
ROLES[user] = random.choice(list(roles))
|
||||||
else: # we swapped amnesiac_roles earlier on, get our version back
|
|
||||||
target_role = ROLES[actor]
|
|
||||||
|
|
||||||
evt.data["actor_role"] = actor_role
|
|
||||||
evt.data["target_role"] = target_role
|
|
||||||
|
|
||||||
@event_listener("revealing_totem")
|
@event_listener("revealing_totem")
|
||||||
def on_revealing_totem(evt, var, votee):
|
def on_revealing_totem(evt, var, votee):
|
||||||
@ -108,14 +69,8 @@ def on_revealing_totem(evt, var, votee):
|
|||||||
global STATS_FLAG
|
global STATS_FLAG
|
||||||
STATS_FLAG = True
|
STATS_FLAG = True
|
||||||
if evt.data["role"] == "amnesiac":
|
if evt.data["role"] == "amnesiac":
|
||||||
role = ROLES[votee]
|
|
||||||
change_role(votee, "amnesiac", role)
|
|
||||||
votee.send(messages["totem_amnesia_clear"])
|
votee.send(messages["totem_amnesia_clear"])
|
||||||
nevt = Event("new_role", {})
|
change_role(var, votee, "amnesiac", ROLES[votee])
|
||||||
nevt.dispatch(var, votee, role)
|
|
||||||
evt.data["role"] = role
|
|
||||||
# If wolfteam, don't bother giving list of wolves since night is about to start anyway
|
|
||||||
# Existing wolves also know that someone just joined their team because revealing totem says what they are
|
|
||||||
|
|
||||||
@event_listener("get_reveal_role")
|
@event_listener("get_reveal_role")
|
||||||
def on_reveal_role(evt, var, user):
|
def on_reveal_role(evt, var, user):
|
||||||
|
@ -5,8 +5,8 @@ import math
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import channels, users, debuglog, errlog, plog
|
from src import events, channels, users, debuglog, errlog, plog
|
||||||
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target
|
from src.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target, change_role
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
@ -45,14 +45,15 @@ def clone(var, wrapper, message):
|
|||||||
|
|
||||||
debuglog("{0} (clone) CLONE: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
|
debuglog("{0} (clone) CLONE: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
|
||||||
|
|
||||||
@event_listener("init")
|
def setup_clone(evt):
|
||||||
def on_init(evt):
|
|
||||||
# We need to add "clone" to the role command exceptions so there's no error
|
# We need to add "clone" to the role command exceptions so there's no error
|
||||||
# This is done here so that var isn't imported at the global scope
|
# This is done here so that var isn't imported at the global scope
|
||||||
# (when we implement proper game state this will be in a different event)
|
# (when we implement proper game state this will be in a different event)
|
||||||
from src import settings as var
|
from src import settings as var
|
||||||
var.ROLE_COMMAND_EXCEPTIONS.add("clone")
|
var.ROLE_COMMAND_EXCEPTIONS.add("clone")
|
||||||
|
|
||||||
|
events.add_listener("init", setup_clone) # no IRC connection, so no possible error handler yet
|
||||||
|
|
||||||
@event_listener("get_reveal_role")
|
@event_listener("get_reveal_role")
|
||||||
def on_get_reveal_role(evt, var, user):
|
def on_get_reveal_role(evt, var, user):
|
||||||
if var.HIDDEN_CLONE and user in var.ORIGINAL_ROLES["clone"]:
|
if var.HIDDEN_CLONE and user in var.ORIGINAL_ROLES["clone"]:
|
||||||
@ -72,19 +73,7 @@ def on_del_player(evt, var, player, mainrole, allroles, death_triggers):
|
|||||||
# clone is cloning target, so clone becomes target's role
|
# clone is cloning target, so clone becomes target's role
|
||||||
# clone does NOT get any of target's templates (gunner/assassin/etc.)
|
# clone does NOT get any of target's templates (gunner/assassin/etc.)
|
||||||
del CLONED[clone]
|
del CLONED[clone]
|
||||||
if mainrole == "amnesiac":
|
mainrole = change_role(var, clone, "clone", mainrole, inherit_from=target)
|
||||||
from src.roles.amnesiac import ROLES as amn_roles
|
|
||||||
# clone gets the amnesiac's real role
|
|
||||||
mainrole = amn_roles[player]
|
|
||||||
change_role(clone, "clone", mainrole)
|
|
||||||
debuglog("{0} (clone) CLONE DEAD PLAYER: {1} ({2})".format(clone, target, mainrole))
|
|
||||||
sayrole = mainrole
|
|
||||||
if sayrole in var.HIDDEN_VILLAGERS:
|
|
||||||
sayrole = "villager"
|
|
||||||
elif sayrole in var.HIDDEN_ROLES:
|
|
||||||
sayrole = var.DEFAULT_ROLE
|
|
||||||
an = "n" if sayrole.startswith(("a", "e", "i", "o", "u")) else ""
|
|
||||||
clone.send(messages["clone_turn"].format(an, sayrole))
|
|
||||||
# if a clone is cloning a clone, clone who the old clone cloned
|
# if a clone is cloning a clone, clone who the old clone cloned
|
||||||
if mainrole == "clone" and player in CLONED:
|
if mainrole == "clone" and player in CLONED:
|
||||||
if CLONED[player] is clone:
|
if CLONED[player] is clone:
|
||||||
@ -93,30 +82,8 @@ def on_del_player(evt, var, player, mainrole, allroles, death_triggers):
|
|||||||
CLONED[clone] = CLONED[player]
|
CLONED[clone] = CLONED[player]
|
||||||
clone.send(messages["clone_success"].format(CLONED[clone]))
|
clone.send(messages["clone_success"].format(CLONED[clone]))
|
||||||
debuglog("{0} (clone) CLONE: {1} ({2})".format(clone, CLONED[clone], get_main_role(CLONED[clone])))
|
debuglog("{0} (clone) CLONE: {1} ({2})".format(clone, CLONED[clone], get_main_role(CLONED[clone])))
|
||||||
elif mainrole in var.WOLFCHAT_ROLES:
|
|
||||||
wolves = get_players(var.WOLFCHAT_ROLES)
|
|
||||||
wolves.remove(clone) # remove self from list
|
|
||||||
for wolf in wolves:
|
|
||||||
wolf.queue_message(messages["clone_wolf"].format(clone, player))
|
|
||||||
if wolves:
|
|
||||||
wolf.send_messages()
|
|
||||||
if var.PHASE == "day":
|
|
||||||
random.shuffle(wolves)
|
|
||||||
for i, wolf in enumerate(wolves):
|
|
||||||
wolfrole = get_main_role(wolf)
|
|
||||||
wevt = Event("wolflist", {"tags": set()})
|
|
||||||
wevt.dispatch(var, wolf, clone)
|
|
||||||
tags = " ".join(wevt.data["tags"])
|
|
||||||
if tags:
|
|
||||||
tags += " "
|
|
||||||
wolves[i] = "\u0002{0}\u0002 ({1}{2})".format(wolf, tags, wolfrole)
|
|
||||||
|
|
||||||
if wolves:
|
debuglog("{0} (clone) CLONE DEAD PLAYER: {1} ({2})".format(clone, target, mainrole))
|
||||||
clone.send(messages["wolves_list"].format(wolves))
|
|
||||||
else:
|
|
||||||
clone.send(messages["no_other_wolves"])
|
|
||||||
elif mainrole == "turncoat":
|
|
||||||
var.TURNCOATS[clone.nick] = ("none", -1) # FIXME
|
|
||||||
|
|
||||||
if mainrole == "clone" and player in CLONED:
|
if mainrole == "clone" and player in CLONED:
|
||||||
del CLONED[player]
|
del CLONED[player]
|
||||||
@ -155,23 +122,12 @@ def on_transition_day_begin(evt, var):
|
|||||||
CLONED[clone] = target
|
CLONED[clone] = target
|
||||||
clone.send(messages["random_clone"].format(target))
|
clone.send(messages["random_clone"].format(target))
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("swap_role_state")
|
||||||
def on_exchange_roles(evt, var, actor, target, actor_role, target_role):
|
def on_swap_role_state(evt, var, actor, target, role):
|
||||||
actor_target = None
|
if role == "clone":
|
||||||
target_target = None
|
CLONED[target], CLONED[actor] = CLONED.pop(actor), CLONED.pop(target)
|
||||||
if actor_role == "clone":
|
evt.data["target_messages"].append(messages["clone_target"].format(CLONED[target]))
|
||||||
if actor in CLONED:
|
evt.data["actor_messages"].append(messages["clone_target"].format(CLONED[actor]))
|
||||||
actor_target = CLONED.pop(actor)
|
|
||||||
evt.data["target_messages"].append(messages["clone_target"].format(actor_target))
|
|
||||||
if target_role == "clone":
|
|
||||||
if target in CLONED:
|
|
||||||
target_target = CLONED.pop(target)
|
|
||||||
evt.data["actor_messages"].append(messages["clone_target"].format(target_target))
|
|
||||||
|
|
||||||
if actor_target is not None:
|
|
||||||
CLONED[target] = actor_target
|
|
||||||
if target_target is not None:
|
|
||||||
CLONED[actor] = target_target
|
|
||||||
|
|
||||||
@event_listener("player_win")
|
@event_listener("player_win")
|
||||||
def on_player_win(evt, var, player, role, winner, survived):
|
def on_player_win(evt, var, player, role, winner, survived):
|
||||||
@ -179,17 +135,17 @@ def on_player_win(evt, var, player, role, winner, survived):
|
|||||||
if role == "clone" and survived and not winner.startswith("@") and singular(winner) not in var.WIN_STEALER_ROLES:
|
if role == "clone" and survived and not winner.startswith("@") and singular(winner) not in var.WIN_STEALER_ROLES:
|
||||||
evt.data["iwon"] = True
|
evt.data["iwon"] = True
|
||||||
|
|
||||||
@event_listener("del_player")
|
@event_listener("del_player", priority=1)
|
||||||
def first_death_occured(evt, var, player, mainrole, allroles, death_triggers):
|
def first_death_occured(evt, var, player, mainrole, allroles, death_triggers):
|
||||||
global CLONE_ENABLED
|
global CLONE_ENABLED
|
||||||
if CLONE_ENABLED:
|
if CLONE_ENABLED:
|
||||||
return
|
return
|
||||||
if var.PHASE in var.GAME_PHASES and (CLONED or get_all_players(("clone",))) and not var.FIRST_NIGHT:
|
if CLONED and var.PHASE in var.GAME_PHASES:
|
||||||
CLONE_ENABLED = True
|
CLONE_ENABLED = True
|
||||||
|
|
||||||
@event_listener("update_stats")
|
@event_listener("update_stats")
|
||||||
def on_update_stats(evt, var, player, mainrole, revealrole, allroles):
|
def on_update_stats(evt, var, player, mainrole, revealrole, allroles):
|
||||||
if CLONE_ENABLED:
|
if CLONE_ENABLED and not var.HIDDEN_CLONE:
|
||||||
evt.data["possible"].add("clone")
|
evt.data["possible"].add("clone")
|
||||||
|
|
||||||
@event_listener("myrole")
|
@event_listener("myrole")
|
||||||
@ -212,3 +168,5 @@ def on_reset(evt, var):
|
|||||||
global CLONE_ENABLED
|
global CLONE_ENABLED
|
||||||
CLONE_ENABLED = False
|
CLONE_ENABLED = False
|
||||||
CLONED.clear()
|
CLONED.clear()
|
||||||
|
|
||||||
|
# vim: set sw=4 expandtab:
|
||||||
|
@ -64,12 +64,10 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
def on_get_special(evt, var):
|
def on_get_special(evt, var):
|
||||||
evt.data["villagers"].update(get_players(("detective",)))
|
evt.data["villagers"].update(get_players(("detective",)))
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("new_role")
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
def on_new_role(evt, var, user, old_role):
|
||||||
if actor_role == "detective" and target_role != "detective":
|
if old_role == "detective" and evt.data["role"] != "detective":
|
||||||
INVESTIGATED.discard(actor)
|
INVESTIGATED.discard(user)
|
||||||
elif target_role == "detective" and actor_role != "detective":
|
|
||||||
INVESTIGATED.discard(target)
|
|
||||||
|
|
||||||
@event_listener("transition_night_end", priority=2)
|
@event_listener("transition_night_end", priority=2)
|
||||||
def on_transition_night_end(evt, var):
|
def on_transition_night_end(evt, var):
|
||||||
|
@ -120,25 +120,40 @@ def on_transition_day(evt, var):
|
|||||||
evt.data["onlybywolves"].discard(d)
|
evt.data["onlybywolves"].discard(d)
|
||||||
evt.data["killers"][d].append(k)
|
evt.data["killers"][d].append(k)
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("new_role")
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
def on_new_role(evt, var, player, old_role):
|
||||||
for k in set(KILLS):
|
if player in TARGETS and old_role == "dullahan" and evt.data["role"] != "dullahan":
|
||||||
if k is actor or k is target:
|
del KILLS[:player:]
|
||||||
del KILLS[k]
|
del TARGETS[player]
|
||||||
|
|
||||||
for k in set(TARGETS):
|
if player not in TARGETS and evt.data["role"] == "dullahan":
|
||||||
if actor_role == "dullahan" and target_role != "dullahan" and k is actor:
|
ps = get_players()
|
||||||
targets = TARGETS.pop(k)
|
max_targets = math.ceil(8.1 * math.log(len(ps), 10) - 5)
|
||||||
if target in targets:
|
TARGETS[player] = UserSet()
|
||||||
targets.remove(target)
|
|
||||||
targets.add(actor)
|
dull_targets = Event("dullahan_targets", {"targets": TARGETS[player]}) # support sleepy
|
||||||
TARGETS[target] = targets
|
dull_targets.dispatch(var, player, max_targets)
|
||||||
if target_role == "dullahan" and actor_role != "dullahan" and k is target:
|
|
||||||
targets = TARGETS.pop(k)
|
ps.remove(player)
|
||||||
if actor in targets:
|
while len(TARGETS[player]) < max_targets:
|
||||||
targets.remove(actor)
|
target = random.choice(ps)
|
||||||
targets.add(target)
|
ps.remove(target)
|
||||||
TARGETS[actor] = targets
|
TARGETS[player].add(target)
|
||||||
|
|
||||||
|
@event_listener("swap_role_state")
|
||||||
|
def on_swap_role_state(evt, var, actor, target, role):
|
||||||
|
if role == "dullahan":
|
||||||
|
targ_targets = TARGETS.pop(target)
|
||||||
|
if actor in targ_targets:
|
||||||
|
targ_targets.remove(actor)
|
||||||
|
targ_targets.add(target)
|
||||||
|
act_targets = TARGETS.pop(actor)
|
||||||
|
if target in act_targets:
|
||||||
|
act_targets.remove(target)
|
||||||
|
act_targets.add(actor)
|
||||||
|
|
||||||
|
TARGETS[actor] = targ_targets
|
||||||
|
TARGETS[target] = act_targets
|
||||||
|
|
||||||
@event_listener("chk_nightdone")
|
@event_listener("chk_nightdone")
|
||||||
def on_chk_nightdone(evt, var):
|
def on_chk_nightdone(evt, var):
|
||||||
@ -165,24 +180,6 @@ def on_transition_night_end(evt, var):
|
|||||||
t = messages["dullahan_targets"] if var.FIRST_NIGHT else messages["dullahan_remaining_targets"]
|
t = messages["dullahan_targets"] if var.FIRST_NIGHT else messages["dullahan_remaining_targets"]
|
||||||
dullahan.send(messages[to_send], t + ", ".join(t.nick for t in targets), sep="\n")
|
dullahan.send(messages[to_send], t + ", ".join(t.nick for t in targets), sep="\n")
|
||||||
|
|
||||||
@event_listener("role_assignment")
|
|
||||||
def on_role_assignment(evt, var, gamemode, pl):
|
|
||||||
# assign random targets to dullahan to kill
|
|
||||||
if var.ROLES["dullahan"]:
|
|
||||||
max_targets = math.ceil(8.1 * math.log(len(pl), 10) - 5)
|
|
||||||
for dull in var.ROLES["dullahan"]:
|
|
||||||
TARGETS[dull] = UserSet()
|
|
||||||
dull_targets = Event("dullahan_targets", {"targets": TARGETS}) # support sleepy
|
|
||||||
dull_targets.dispatch(var, var.ROLES["dullahan"], max_targets)
|
|
||||||
|
|
||||||
for dull, ts in TARGETS.items():
|
|
||||||
ps = pl[:]
|
|
||||||
ps.remove(dull)
|
|
||||||
while len(ts) < max_targets:
|
|
||||||
target = random.choice(ps)
|
|
||||||
ps.remove(target)
|
|
||||||
ts.add(target)
|
|
||||||
|
|
||||||
@event_listener("succubus_visit")
|
@event_listener("succubus_visit")
|
||||||
def on_succubus_visit(evt, var, succubus, target):
|
def on_succubus_visit(evt, var, succubus, target):
|
||||||
succubi = get_all_players(("succubus",))
|
succubi = get_all_players(("succubus",))
|
||||||
|
@ -96,14 +96,12 @@ def on_transition_day(evt, var):
|
|||||||
# important, otherwise our del_player listener lets hunter kill again
|
# important, otherwise our del_player listener lets hunter kill again
|
||||||
del KILLS[k]
|
del KILLS[k]
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("new_role")
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
def on_new_role(evt, var, user, old_role):
|
||||||
del KILLS[:actor:]
|
if old_role == "hunter":
|
||||||
del KILLS[:target:]
|
del KILLS[:user:]
|
||||||
HUNTERS.discard(actor)
|
HUNTERS.discard(user)
|
||||||
HUNTERS.discard(target)
|
PASSED.discard(user)
|
||||||
PASSED.discard(actor)
|
|
||||||
PASSED.discard(target)
|
|
||||||
|
|
||||||
@event_listener("chk_nightdone")
|
@event_listener("chk_nightdone")
|
||||||
def on_chk_nightdone(evt, var):
|
def on_chk_nightdone(evt, var):
|
||||||
|
@ -97,12 +97,10 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
def on_get_special(evt, var):
|
def on_get_special(evt, var):
|
||||||
evt.data["villagers"].update(get_players(("investigator",)))
|
evt.data["villagers"].update(get_players(("investigator",)))
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("new_role")
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
def on_new_role(evt, var, user, old_role):
|
||||||
if actor_role == "investigator" and target_role != "investigator":
|
if old_role == "investigator" and evt.data["role"] != "investigator":
|
||||||
INVESTIGATED.discard(actor)
|
INVESTIGATED.discard(user)
|
||||||
elif target_role == "investigator" and actor_role != "investigator":
|
|
||||||
INVESTIGATED.discard(target)
|
|
||||||
|
|
||||||
@event_listener("transition_night_end", priority=2)
|
@event_listener("transition_night_end", priority=2)
|
||||||
def on_transition_night_end(evt, var):
|
def on_transition_night_end(evt, var):
|
||||||
|
@ -113,3 +113,5 @@ def on_begin_day(evt, var):
|
|||||||
@event_listener("reset")
|
@event_listener("reset")
|
||||||
def on_reset(evt, var):
|
def on_reset(evt, var):
|
||||||
PRAYED.clear()
|
PRAYED.clear()
|
||||||
|
|
||||||
|
# vim: set sw=4 expandtab:
|
||||||
|
@ -195,8 +195,8 @@ def on_get_special(evt, var):
|
|||||||
evt.data["win_stealers"].update(get_players(("succubus",)))
|
evt.data["win_stealers"].update(get_players(("succubus",)))
|
||||||
|
|
||||||
@event_listener("new_role")
|
@event_listener("new_role")
|
||||||
def on_new_role(evt, var, user, role):
|
def on_new_role(evt, var, user, old_role):
|
||||||
if role == "succubus" and user in ENTRANCED:
|
if evt.data["role"] == "succubus" and user in ENTRANCED:
|
||||||
ENTRANCED.remove(user)
|
ENTRANCED.remove(user)
|
||||||
user.send(messages["no_longer_entranced"])
|
user.send(messages["no_longer_entranced"])
|
||||||
|
|
||||||
|
134
src/roles/turncoat.py
Normal file
134
src/roles/turncoat.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
TURNCOATS = UserDict() # type: Dict[users.User, Tuple[str, int]]
|
||||||
|
PASSED = UserSet() # type: Set[users.User]
|
||||||
|
|
||||||
|
def _get_side(user):
|
||||||
|
side = "currently with \u0002{0}\u0002".format(TURNCOATS[user][0])
|
||||||
|
if TURNCOATS[user][0] == "none":
|
||||||
|
side = "not currently on any side"
|
||||||
|
return side
|
||||||
|
|
||||||
|
@command("side", chan=False, pm=True, playing=True, phases=("night",), roles=("turncoat",))
|
||||||
|
def change_sides(var, wrapper, message, sendmsg=True):
|
||||||
|
if TURNCOATS[wrapper.source][1] == var.NIGHT_COUNT - 1:
|
||||||
|
wrapper.pm(messages["turncoat_already_turned"])
|
||||||
|
return
|
||||||
|
|
||||||
|
team = re.split(" +", message)[0]
|
||||||
|
team = complete_one_match(team, ("villagers", "wolves"))
|
||||||
|
if not team:
|
||||||
|
wrapper.pm(messages["turncoat_error"])
|
||||||
|
return
|
||||||
|
|
||||||
|
wrapper.pm(messages["turncoat_success"].format(team))
|
||||||
|
TURNCOATS[wrapper.source] = (team, var.NIGHT_COUNT)
|
||||||
|
PASSED.discard(wrapper.source)
|
||||||
|
debuglog("{0} (turncoat) SIDE {1}".format(wrapper.source, team))
|
||||||
|
|
||||||
|
@command("pass", chan=False, pm=True, playing=True, phases=("night",), roles=("turncoat",))
|
||||||
|
def pass_cmd(var, wrapper, message):
|
||||||
|
"""Decline to use your special power for that night."""
|
||||||
|
if TURNCOATS[wrapper.source][1] == var.NIGHT_COUNT:
|
||||||
|
# theoretically passing would revert them to how they were before, but
|
||||||
|
# we aren't tracking that, so just tell them to change it back themselves.
|
||||||
|
wrapper.pm(messages["turncoat_fail"])
|
||||||
|
return
|
||||||
|
|
||||||
|
wrapper.pm(messages["turncoat_pass"])
|
||||||
|
if TURNCOATS[wrapper.source][1] == var.NIGHT_COUNT - 1:
|
||||||
|
# don't add to PASSED since we aren't counting them anyway for nightdone
|
||||||
|
# let them still use !pass though to make them feel better or something
|
||||||
|
return
|
||||||
|
PASSED.add(wrapper.source)
|
||||||
|
|
||||||
|
debuglog("{0} (turncoat) PASS".format(wrapper.source))
|
||||||
|
|
||||||
|
@event_listener("transition_night_end")
|
||||||
|
def on_transition_night_end(evt, var):
|
||||||
|
for turncoat in get_all_players(("turncoat",)):
|
||||||
|
# they start out as unsided, but can change n1
|
||||||
|
if turncoat not in TURNCOATS:
|
||||||
|
TURNCOATS[turncoat] = ("none", -1)
|
||||||
|
|
||||||
|
if turncoat.prefers_simple():
|
||||||
|
turncoat.send(messages["turncoat_simple"].format(TURNCOATS[turncoat][0]))
|
||||||
|
else:
|
||||||
|
message = messages["turncoat_notify"]
|
||||||
|
if TURNCOATS[turncoat][0] != "none":
|
||||||
|
message += messages["turncoat_current_team"].format(TURNCOATS[turncoat][0])
|
||||||
|
else:
|
||||||
|
message += messages["turncoat_no_team"]
|
||||||
|
turncoat.send(message)
|
||||||
|
|
||||||
|
@event_listener("chk_nightdone")
|
||||||
|
def on_chk_nightdone(evt, var):
|
||||||
|
# add in turncoats who should be able to act or who passed
|
||||||
|
# but if they can act they're in TURNCOATS where the second tuple item is the current night
|
||||||
|
# (if said tuple item is the previous night, then they are not allowed to act tonight)
|
||||||
|
pl = get_players()
|
||||||
|
evt.data["actedcount"] += len(PASSED)
|
||||||
|
for turncoat, (team, night) in TURNCOATS.items():
|
||||||
|
if turncoat not in pl:
|
||||||
|
continue
|
||||||
|
if night == var.NIGHT_COUNT:
|
||||||
|
evt.data["nightroles"].append(turncoat)
|
||||||
|
evt.data["actedcount"] += 1
|
||||||
|
elif night < var.NIGHT_COUNT - 1:
|
||||||
|
evt.data["nightroles"].append(turncoat)
|
||||||
|
|
||||||
|
@event_listener("player_win")
|
||||||
|
def on_player_win(evt, var, player, role, winner, survived):
|
||||||
|
if role == "turncoat" and player in TURNCOATS and TURNCOATS[player][0] != "none":
|
||||||
|
evt.data["won"] = (winner == TURNCOATS[player][0])
|
||||||
|
|
||||||
|
@event_listener("myrole")
|
||||||
|
def on_myrole(evt, var, user):
|
||||||
|
if evt.data["role"] == "turncoat" and user in TURNCOATS:
|
||||||
|
evt.data["messages"].append(messages["turncoat_side"].format(_get_side(user)))
|
||||||
|
|
||||||
|
@event_listener("revealroles_role")
|
||||||
|
def on_revealroles_role(evt, var, user, role):
|
||||||
|
if role == "turncoat" and user in TURNCOATS:
|
||||||
|
evt.data["special_case"].append(_get_side(user))
|
||||||
|
|
||||||
|
@event_listener("get_special")
|
||||||
|
def on_get_special(evt, var):
|
||||||
|
evt.data["neutrals"].update(get_players(("turncoat",)))
|
||||||
|
|
||||||
|
@event_listener("new_role")
|
||||||
|
def on_new_role(evt, var, player, old_role):
|
||||||
|
if old_role == "turncoat" and evt.data["role"] != "turncoat":
|
||||||
|
del TURNCOATS[player]
|
||||||
|
elif evt.data["role"] == "turncoat" and old_role != "turncoat":
|
||||||
|
TURNCOATS[player] = ("none", -1)
|
||||||
|
|
||||||
|
@event_listener("swap_role_state")
|
||||||
|
def on_swap_role_state(evt, var, actor, target, role):
|
||||||
|
if role == "turncoat":
|
||||||
|
TURNCOATS[actor], TURNCOATS[target] = TURNCOATS.pop(target), TURNCOATS.pop(actor)
|
||||||
|
evt.data["actor_messages"].append(messages["turncoat_side"].format(_get_side(actor)))
|
||||||
|
evt.data["target_messages"].append(messages["turncoat_side"].format(_get_side(target)))
|
||||||
|
|
||||||
|
@event_listener("begin_day")
|
||||||
|
def on_begin_day(evt, var):
|
||||||
|
PASSED.clear()
|
||||||
|
|
||||||
|
@event_listener("reset")
|
||||||
|
def on_reset(evt, var):
|
||||||
|
PASSED.clear()
|
||||||
|
TURNCOATS.clear()
|
||||||
|
|
||||||
|
# vim: set sw=4 expandtab:
|
@ -83,12 +83,11 @@ def on_transition_day(evt, var):
|
|||||||
if get_main_role(target) not in var.WOLF_ROLES | var.WIN_STEALER_ROLES:
|
if get_main_role(target) not in var.WOLF_ROLES | var.WIN_STEALER_ROLES:
|
||||||
var.DYING.add(vigilante)
|
var.DYING.add(vigilante)
|
||||||
|
|
||||||
@event_listener("exchange_roles")
|
@event_listener("new_role")
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
def on_new_role(evt, var, user, old_role):
|
||||||
del KILLS[:actor:]
|
if old_role == "vigilante":
|
||||||
del KILLS[:target:]
|
del KILLS[:user:]
|
||||||
PASSED.discard(actor)
|
PASSED.discard(user)
|
||||||
PASSED.discard(target)
|
|
||||||
|
|
||||||
@event_listener("chk_nightdone")
|
@event_listener("chk_nightdone")
|
||||||
def on_chk_nightdone(evt, var):
|
def on_chk_nightdone(evt, var):
|
||||||
|
@ -6,7 +6,7 @@ from collections import defaultdict
|
|||||||
|
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import channels, users, debuglog, errlog, plog
|
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.functions import get_players, get_all_players, get_main_role, get_reveal_role, get_target, change_role
|
||||||
from src.decorators import command, event_listener
|
from src.decorators import command, event_listener
|
||||||
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
@ -73,39 +73,10 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Change their main role to wolf
|
# Change their main role to wolf
|
||||||
child.send(messages["wild_child_idol_died"])
|
|
||||||
WILD_CHILDREN.add(child)
|
WILD_CHILDREN.add(child)
|
||||||
change_role(child, get_main_role(child), "wolf")
|
change_role(var, child, get_main_role(child), "wolf", message="wild_child_idol_died")
|
||||||
var.ROLES["wild child"].discard(child)
|
var.ROLES["wild child"].discard(child)
|
||||||
|
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES:
|
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF:
|
|
||||||
wcroles = var.WOLF_ROLES
|
|
||||||
else:
|
|
||||||
wcroles = var.WOLF_ROLES | {"traitor"}
|
|
||||||
|
|
||||||
wolves = get_players(wcroles)
|
|
||||||
wolves.remove(child)
|
|
||||||
if wolves:
|
|
||||||
for wolf in wolves:
|
|
||||||
wolf.queue_message(messages["wild_child_as_wolf"].format(child))
|
|
||||||
wolf.send_messages()
|
|
||||||
|
|
||||||
# Send wolf list
|
|
||||||
if var.PHASE == "day":
|
|
||||||
random.shuffle(wolves)
|
|
||||||
names = []
|
|
||||||
cursed_list = get_all_players(("cursed villager",))
|
|
||||||
for i, wolf in enumerate(wolves):
|
|
||||||
role = get_main_role(wolf)
|
|
||||||
cursed = "cursed " if wolf in cursed_list else ""
|
|
||||||
names.append("\u0002{0}\u0002 ({1}{2})".format(wolf, cursed, role))
|
|
||||||
|
|
||||||
if names:
|
|
||||||
child.send(messages["wolves_list"].format(", ".join(names)))
|
|
||||||
else:
|
|
||||||
child.send(messages["no_other_wolves"])
|
|
||||||
|
|
||||||
@event_listener("chk_nightdone")
|
@event_listener("chk_nightdone")
|
||||||
def on_chk_nightdone(evt, var):
|
def on_chk_nightdone(evt, var):
|
||||||
if var.FIRST_NIGHT:
|
if var.FIRST_NIGHT:
|
||||||
|
@ -226,8 +226,8 @@ def on_retribution_kill(evt, var, victim, orig_target):
|
|||||||
wolves = get_players(CAN_KILL)
|
wolves = get_players(CAN_KILL)
|
||||||
evt.data["target"] = random.choice(wolves)
|
evt.data["target"] = random.choice(wolves)
|
||||||
|
|
||||||
@event_listener("exchange_roles", priority=2)
|
@event_listener("new_role", priority=4)
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
def on_new_role(evt, var, player, old_role):
|
||||||
wcroles = var.WOLFCHAT_ROLES
|
wcroles = var.WOLFCHAT_ROLES
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES:
|
if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES:
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF:
|
if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF:
|
||||||
@ -235,77 +235,61 @@ def on_exchange(evt, var, actor, target, actor_role, target_role):
|
|||||||
else:
|
else:
|
||||||
wcroles = var.WOLF_ROLES | {"traitor"}
|
wcroles = var.WOLF_ROLES | {"traitor"}
|
||||||
|
|
||||||
if target_role in wcroles and actor_role not in wcroles:
|
if old_role is None:
|
||||||
|
# initial role assignment; don't do all the logic below about notifying other wolves and such
|
||||||
|
if evt.data["role"] in wcroles:
|
||||||
|
evt.data["in_wolfchat"] = True
|
||||||
|
return
|
||||||
|
|
||||||
|
sayrole = evt.data["role"]
|
||||||
|
if sayrole in var.HIDDEN_VILLAGERS:
|
||||||
|
sayrole = "villager"
|
||||||
|
elif sayrole in var.HIDDEN_ROLES:
|
||||||
|
sayrole = var.DEFAULT_ROLE
|
||||||
|
an = "n" if sayrole.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
|
||||||
|
if player.nick in KILLS: # FIXME
|
||||||
|
del KILLS[player.nick]
|
||||||
|
|
||||||
|
if old_role not in wcroles and evt.data["role"] in wcroles:
|
||||||
|
# a new wofl has joined the party, give them tummy rubs and the wolf list
|
||||||
|
# and let the other wolves know to break out the confetti and villager steaks
|
||||||
|
wofls = get_players(wcroles)
|
||||||
|
evt.data["in_wolfchat"] = True
|
||||||
|
if wofls:
|
||||||
|
new_wolves = []
|
||||||
|
for wofl in wofls:
|
||||||
|
wofl.queue_message(messages["wolfchat_new_member"].format(player, an, sayrole))
|
||||||
|
wofl.send_messages()
|
||||||
|
|
||||||
pl = get_players()
|
pl = get_players()
|
||||||
|
pl.remove(player)
|
||||||
random.shuffle(pl)
|
random.shuffle(pl)
|
||||||
pl.remove(actor) # remove self from list
|
pt = []
|
||||||
notify = []
|
wevt = Event("wolflist", {"tags": set()})
|
||||||
to_send = []
|
for p in pl:
|
||||||
for player in pl:
|
prole = get_main_role(p)
|
||||||
prole = get_main_role(player)
|
wevt.data["tags"].clear()
|
||||||
if player is target:
|
wevt.dispatch(var, p, player)
|
||||||
prole = actor_role
|
|
||||||
wevt = Event("wolflist", {"tags": set()})
|
|
||||||
wevt.dispatch(var, player, actor)
|
|
||||||
tags = " ".join(wevt.data["tags"])
|
tags = " ".join(wevt.data["tags"])
|
||||||
if prole in wcroles:
|
if prole in wcroles:
|
||||||
if tags:
|
if tags:
|
||||||
tags += " "
|
tags += " "
|
||||||
to_send.append("\u0002{0}\u0002 ({1}{2})".format(player, tags, prole))
|
pt.append("\u0002{0}\u0002 ({1}{2})".format(p, tags, prole))
|
||||||
notify.append(player)
|
|
||||||
elif tags:
|
elif tags:
|
||||||
to_send.append("{0} ({1})".format(player, tags))
|
pt.append("{0} ({1})".format(p, tags))
|
||||||
else:
|
else:
|
||||||
to_send.append(player.nick)
|
pt.append(p.nick)
|
||||||
|
|
||||||
for player in notify:
|
evt.data["messages"].append(messages["players_list"].format(", ".join(pt)))
|
||||||
player.queue_message(messages["players_exchanged_roles"].format(target, actor))
|
|
||||||
if notify:
|
|
||||||
player.send_messages()
|
|
||||||
|
|
||||||
evt.data["actor_messages"].append(messages["players_list"].format(", ".join(to_send)))
|
if var.PHASE == "night":
|
||||||
if target_role in CAN_KILL and var.DISEASED_WOLVES:
|
# inform the new wolf that they can kill and stuff
|
||||||
evt.data["actor_messages"].append(messages["ill_wolves"])
|
if evt.data["role"] in CAN_KILL and var.DISEASED_WOLVES:
|
||||||
if var.ALPHA_ENABLED and target_role == "alpha wolf" and actor.nick not in var.ALPHA_WOLVES:
|
evt.data["messages"].append(messages["ill_wolves"])
|
||||||
evt.data["actor_messages"].append(messages["wolf_bite"])
|
# FIXME: split when alpha wolf is split
|
||||||
elif actor_role in wcroles and target_role not in wcroles:
|
if var.ALPHA_ENABLED and evt.data["role"] == "alpha wolf" and player.nick not in var.ALPHA_WOLVES:
|
||||||
pl = get_players()
|
evt.data["messages"].append(messages["wolf_bite"])
|
||||||
random.shuffle(pl)
|
|
||||||
pl.remove(target) # remove self from list
|
|
||||||
notify = []
|
|
||||||
to_send = []
|
|
||||||
for player in pl:
|
|
||||||
prole = get_main_role(player)
|
|
||||||
if player is actor:
|
|
||||||
prole = target_role
|
|
||||||
wevt = Event("wolflist", {"tags": set()})
|
|
||||||
wevt.dispatch(var, player, target)
|
|
||||||
tags = " ".join(wevt.data["tags"])
|
|
||||||
if prole in wcroles:
|
|
||||||
if tags:
|
|
||||||
tags += " "
|
|
||||||
to_send.append("\u0002{0}\u0002 ({1}{2})".format(player, tags, prole))
|
|
||||||
notify.append(player)
|
|
||||||
elif tags:
|
|
||||||
to_send.append("{0} ({1})".format(player, tags))
|
|
||||||
else:
|
|
||||||
to_send.append(player.nick)
|
|
||||||
|
|
||||||
for player in notify:
|
|
||||||
player.queue_message(messages["players_exchanged_roles"].format(actor, target))
|
|
||||||
if notify:
|
|
||||||
player.send_messages()
|
|
||||||
|
|
||||||
evt.data["target_messages"].append(messages["players_list"].format(", ".join(to_send)))
|
|
||||||
if actor_role in CAN_KILL and var.DISEASED_WOLVES:
|
|
||||||
evt.data["target_messages"].append(messages["ill_wolves"])
|
|
||||||
if var.ALPHA_ENABLED and actor_role == "alpha wolf" and target.nick not in var.ALPHA_WOLVES:
|
|
||||||
evt.data["target_messages"].append(messages["wolf_bite"])
|
|
||||||
|
|
||||||
if actor.nick in KILLS:
|
|
||||||
del KILLS[actor.nick]
|
|
||||||
if target.nick in KILLS:
|
|
||||||
del KILLS[target.nick]
|
|
||||||
|
|
||||||
@event_listener("chk_nightdone", priority=3)
|
@event_listener("chk_nightdone", priority=3)
|
||||||
def on_chk_nightdone(evt, var):
|
def on_chk_nightdone(evt, var):
|
||||||
@ -320,7 +304,7 @@ def on_chk_nightdone(evt, var):
|
|||||||
evt.data["actedcount"] += len(KILLS)
|
evt.data["actedcount"] += len(KILLS)
|
||||||
evt.data["nightroles"].append(users.FakeUser.from_nick("@WolvesAgree@"))
|
evt.data["nightroles"].append(users.FakeUser.from_nick("@WolvesAgree@"))
|
||||||
# check if wolves are actually agreeing or not;
|
# check if wolves are actually agreeing or not;
|
||||||
# only count agreement_user if they are
|
# only add to count if they actually agree
|
||||||
# (this is *slighty* less hacky than deducting 1 from actedcount as we did previously)
|
# (this is *slighty* less hacky than deducting 1 from actedcount as we did previously)
|
||||||
kills = set()
|
kills = set()
|
||||||
for ls in KILLS.values():
|
for ls in KILLS.values():
|
||||||
|
@ -25,23 +25,10 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
|
|||||||
global ANGRY_WOLVES
|
global ANGRY_WOLVES
|
||||||
ANGRY_WOLVES = True
|
ANGRY_WOLVES = True
|
||||||
|
|
||||||
# wolf fires on priority 2, so we can add our extra messages now (at default priority 5)
|
@event_listener("new_role")
|
||||||
@event_listener("exchange_roles")
|
def on_new_role(evt, var, player, old_role):
|
||||||
def on_exchange(evt, var, actor, target, actor_role, target_role):
|
if ANGRY_WOLVES and evt.data["in_wolfchat"] and wolf.wolf_can_kill(var, player):
|
||||||
if not ANGRY_WOLVES:
|
evt.data["messages"].append(messages["angry_wolves"])
|
||||||
return
|
|
||||||
|
|
||||||
wcroles = var.WOLFCHAT_ROLES
|
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES:
|
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF:
|
|
||||||
wcroles = var.WOLF_ROLES
|
|
||||||
else:
|
|
||||||
wcroles = var.WOLF_ROLES | {"traitor"}
|
|
||||||
|
|
||||||
if target_role in wcroles and actor_role not in wcroles and wolf.wolf_can_kill(var, target):
|
|
||||||
evt.data["actor_messages"].append(messages["angry_wolves"])
|
|
||||||
elif actor_role in wcroles and target_role not in wcroles and wolf.wolf_can_kill(var, actor):
|
|
||||||
evt.data["target_messages"].append(messages["angry_wolves"])
|
|
||||||
|
|
||||||
@event_listener("transition_night_end", priority=3)
|
@event_listener("transition_night_end", priority=3)
|
||||||
def on_transition_night_end(evt, var):
|
def on_transition_night_end(evt, var):
|
||||||
|
@ -12,7 +12,7 @@ __all__ = ["pm", "is_fake_nick", "mass_mode", "mass_privmsg", "reply",
|
|||||||
"is_user_simple", "is_user_notice", "in_wolflist",
|
"is_user_simple", "is_user_notice", "in_wolflist",
|
||||||
"relay_wolfchat_command", "irc_lower", "irc_equals", "match_hostmask",
|
"relay_wolfchat_command", "irc_lower", "irc_equals", "match_hostmask",
|
||||||
"is_owner", "is_admin", "plural", "singular", "list_players",
|
"is_owner", "is_admin", "plural", "singular", "list_players",
|
||||||
"get_role", "get_roles", "change_role", "role_order", "break_long_message",
|
"get_role", "get_roles", "role_order", "break_long_message",
|
||||||
"complete_match", "complete_one_match", "get_victim", "InvalidModeException"]
|
"complete_match", "complete_one_match", "get_victim", "InvalidModeException"]
|
||||||
# message either privmsg or notice, depending on user settings
|
# message either privmsg or notice, depending on user settings
|
||||||
def pm(cli, target, message):
|
def pm(cli, target, message):
|
||||||
@ -316,16 +316,6 @@ def get_roles(*roles, rolemap=None):
|
|||||||
all_roles.append(rolemap[role])
|
all_roles.append(rolemap[role])
|
||||||
return [u.nick for u in itertools.chain(*all_roles)]
|
return [u.nick for u in itertools.chain(*all_roles)]
|
||||||
|
|
||||||
# TODO: move this to functions.py
|
|
||||||
def change_role(user, oldrole, newrole, set_final=True):
|
|
||||||
var.ROLES[oldrole].remove(user)
|
|
||||||
var.ROLES[newrole].add(user)
|
|
||||||
# only adjust MAIN_ROLES/FINAL_ROLES if we're changing the user's actual role
|
|
||||||
if var.MAIN_ROLES[user] == oldrole:
|
|
||||||
var.MAIN_ROLES[user] = newrole
|
|
||||||
if set_final:
|
|
||||||
var.FINAL_ROLES[user.nick] = newrole
|
|
||||||
|
|
||||||
role_order = lambda: var.ROLE_GUIDE
|
role_order = lambda: var.ROLE_GUIDE
|
||||||
|
|
||||||
def break_long_message(phrases, joinstr = " "):
|
def break_long_message(phrases, joinstr = " "):
|
||||||
|
201
src/wolfgame.py
201
src/wolfgame.py
@ -21,8 +21,9 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import itertools
|
|
||||||
import functools
|
import functools
|
||||||
|
import itertools
|
||||||
|
import json
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
@ -37,8 +38,8 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
from collections import defaultdict, deque, Counter
|
from collections import defaultdict, deque, Counter
|
||||||
import json
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from oyoyo.parse import parse_nick
|
from oyoyo.parse import parse_nick
|
||||||
@ -48,13 +49,19 @@ import src
|
|||||||
import src.settings as var
|
import src.settings as var
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import db, events, dispatcher, channels, users, hooks, logger, debuglog, errlog, plog
|
from src import db, events, dispatcher, channels, users, hooks, logger, debuglog, errlog, plog
|
||||||
from src.decorators import command, cmd, hook, handle_error, event_listener, COMMANDS
|
|
||||||
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
from src.containers import UserList, UserSet, UserDict, DefaultUserDict
|
||||||
from src.functions import get_players, get_all_players, get_participants, get_main_role, get_all_roles, get_reveal_role, get_target
|
from src.decorators import command, cmd, hook, handle_error, event_listener, COMMANDS
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.warnings import *
|
from src.warnings import *
|
||||||
from src.context import IRCContext
|
from src.context import IRCContext
|
||||||
|
|
||||||
|
from src.functions import (
|
||||||
|
get_players, get_all_players, get_participants,
|
||||||
|
get_main_role, get_all_roles, get_reveal_role,
|
||||||
|
get_target, change_role,
|
||||||
|
)
|
||||||
|
|
||||||
# done this way so that events is accessible in !eval (useful for debugging)
|
# done this way so that events is accessible in !eval (useful for debugging)
|
||||||
Event = events.Event
|
Event = events.Event
|
||||||
|
|
||||||
@ -2109,8 +2116,6 @@ def stop_game(var, winner="", abort=False, additional_winners=None, log=True):
|
|||||||
teams = {"monster":"monsters", "demoniac":"demoniacs"}
|
teams = {"monster":"monsters", "demoniac":"demoniacs"}
|
||||||
if rol in teams and winner == teams[rol]:
|
if rol in teams and winner == teams[rol]:
|
||||||
won = True
|
won = True
|
||||||
elif rol == "turncoat" and splr in var.TURNCOATS and var.TURNCOATS[splr][0] != "none":
|
|
||||||
won = (winner == var.TURNCOATS[splr][0])
|
|
||||||
elif rol == "fool" and "@" + splr == winner:
|
elif rol == "fool" and "@" + splr == winner:
|
||||||
won = True
|
won = True
|
||||||
|
|
||||||
@ -2735,8 +2740,7 @@ def rename_player(var, user, prefix):
|
|||||||
dictvar.update(kvp)
|
dictvar.update(kvp)
|
||||||
if prefix in dictvar.keys():
|
if prefix in dictvar.keys():
|
||||||
del dictvar[prefix]
|
del dictvar[prefix]
|
||||||
for dictvar in (var.FINAL_ROLES, var.TURNCOATS,
|
for dictvar in (var.FINAL_ROLES, var.DOCTORS, var.BITTEN_ROLES, var.LYCAN_ROLES):
|
||||||
var.DOCTORS, var.BITTEN_ROLES, var.LYCAN_ROLES):
|
|
||||||
if prefix in dictvar.keys():
|
if prefix in dictvar.keys():
|
||||||
dictvar[nick] = dictvar.pop(prefix)
|
dictvar[nick] = dictvar.pop(prefix)
|
||||||
# defaultdict(list), where keys are nicks and items in list do not matter
|
# defaultdict(list), where keys are nicks and items in list do not matter
|
||||||
@ -3246,28 +3250,9 @@ def transition_day(gameid=0):
|
|||||||
if vrole not in var.WOLFCHAT_ROLES:
|
if vrole not in var.WOLFCHAT_ROLES:
|
||||||
revt.data["message"].append(messages["new_wolf"])
|
revt.data["message"].append(messages["new_wolf"])
|
||||||
var.EXTRA_WOLVES += 1
|
var.EXTRA_WOLVES += 1
|
||||||
victim.send(messages["lycan_turn"])
|
|
||||||
var.LYCAN_ROLES[victim.nick] = vrole
|
var.LYCAN_ROLES[victim.nick] = vrole
|
||||||
change_role(victim, vrole, "wolf")
|
change_role(var, victim, vrole, "wolf", message="lycan_turn")
|
||||||
var.ROLES["lycan"].discard(victim) # in the event lycan was a template, we want to ensure it gets purged
|
var.ROLES["lycan"].discard(victim) # 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
|
|
||||||
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(var, wolf, victim)
|
|
||||||
tags = " ".join(wevt.data["tags"])
|
|
||||||
if tags:
|
|
||||||
tags += " "
|
|
||||||
to_send.append("\u0002{0}\u0002 ({1}{2})".format(wolf, tags, role))
|
|
||||||
|
|
||||||
if wolves:
|
|
||||||
wolf.send_messages()
|
|
||||||
|
|
||||||
victim.send(messages["wolves_list"].format(", ".join(to_send)))
|
|
||||||
revt.data["novictmsg"] = False
|
revt.data["novictmsg"] = False
|
||||||
elif victim not in revt.data["dead"]: # not already dead via some other means
|
elif victim not in revt.data["dead"]: # not already dead via some other means
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
@ -3368,29 +3353,28 @@ def transition_day(gameid=0):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
newrole = "wolf"
|
newrole = "wolf"
|
||||||
|
to_send = "bitten_turn"
|
||||||
if chumprole == "guardian angel":
|
if chumprole == "guardian angel":
|
||||||
chump.send(messages["fallen_angel_turn"])
|
to_send = "fallen_angel_turn"
|
||||||
# fallen angels also automatically gain the assassin template if they don't already have it
|
# fallen angels also automatically gain the assassin template if they don't already have it
|
||||||
newrole = "fallen angel"
|
newrole = "fallen angel"
|
||||||
var.ROLES["assassin"].add(chump)
|
var.ROLES["assassin"].add(chump)
|
||||||
debuglog("{0} (guardian angel) TURNED FALLEN ANGEL".format(chump))
|
debuglog("{0} (guardian angel) TURNED FALLEN ANGEL".format(chump))
|
||||||
elif chumprole in ("seer", "oracle", "augur"):
|
elif chumprole in ("seer", "oracle", "augur"):
|
||||||
chump.send(messages["seer_turn"])
|
to_send = "seer_turn"
|
||||||
newrole = "doomsayer"
|
newrole = "doomsayer"
|
||||||
debuglog("{0} ({1}) TURNED DOOMSAYER".format(chump, chumprole))
|
debuglog("{0} ({1}) TURNED DOOMSAYER".format(chump, chumprole))
|
||||||
elif chumprole in var.TOTEM_ORDER:
|
elif chumprole in var.TOTEM_ORDER:
|
||||||
chump.send(messages["shaman_turn"])
|
to_send = "shaman_turn"
|
||||||
newrole = "wolf shaman"
|
newrole = "wolf shaman"
|
||||||
debuglog("{0} ({1}) TURNED WOLF SHAMAN".format(chump, chumprole))
|
debuglog("{0} ({1}) TURNED WOLF SHAMAN".format(chump, chumprole))
|
||||||
elif chumprole == "harlot":
|
elif chumprole == "harlot":
|
||||||
chump.send(messages["harlot_turn"])
|
to_send = "harlot_turn"
|
||||||
debuglog("{0} (harlot) TURNED WOLF".format(chump))
|
debuglog("{0} (harlot) TURNED WOLF".format(chump))
|
||||||
else:
|
else:
|
||||||
chump.send(messages["bitten_turn"])
|
|
||||||
debuglog("{0} ({1}) TURNED WOLF".format(chump, chumprole))
|
debuglog("{0} ({1}) TURNED WOLF".format(chump, chumprole))
|
||||||
var.BITTEN_ROLES[chump.nick] = chumprole
|
var.BITTEN_ROLES[chump.nick] = chumprole
|
||||||
change_role(chump, chumprole, newrole)
|
change_role(var, chump, chumprole, newrole, message=to_send)
|
||||||
relay_wolfchat_command(chump.client, chump.nick, messages["wolfchat_new_member"].format(chump, newrole), var.WOLF_ROLES, is_wolf_command=True, is_kill_command=True)
|
|
||||||
|
|
||||||
killer_role = {}
|
killer_role = {}
|
||||||
for deadperson in dead:
|
for deadperson in dead:
|
||||||
@ -3427,8 +3411,6 @@ def chk_nightdone():
|
|||||||
if var.PHASE != "night":
|
if var.PHASE != "night":
|
||||||
return
|
return
|
||||||
|
|
||||||
pl = get_players()
|
|
||||||
spl = set(pl)
|
|
||||||
actedcount = sum(map(len, (var.PASSED, var.OBSERVED, var.HEXED, var.CURSED)))
|
actedcount = sum(map(len, (var.PASSED, var.OBSERVED, var.HEXED, var.CURSED)))
|
||||||
|
|
||||||
nightroles = list(get_all_players(("sorcerer", "hag", "warlock", "werecrow")))
|
nightroles = list(get_all_players(("sorcerer", "hag", "warlock", "werecrow")))
|
||||||
@ -3438,19 +3420,6 @@ def chk_nightdone():
|
|||||||
nightroles.extend(get_all_players(("alpha wolf",)))
|
nightroles.extend(get_all_players(("alpha wolf",)))
|
||||||
actedcount += len([p for p in var.ALPHA_WOLVES if p in get_roles("alpha wolf")]) # FIXME
|
actedcount += len([p for p in var.ALPHA_WOLVES if p in get_roles("alpha wolf")]) # FIXME
|
||||||
|
|
||||||
# add in turncoats who should be able to act -- if they passed they're already in var.PASSED
|
|
||||||
# but if they can act they're in var.TURNCOATS where the second tuple item is the current night
|
|
||||||
# (if said tuple item is the previous night, then they are not allowed to act tonight)
|
|
||||||
for tc, tu in var.TURNCOATS.items():
|
|
||||||
user = users._get(tc) # FIXME
|
|
||||||
if user not in pl:
|
|
||||||
continue
|
|
||||||
if tu[1] == var.NIGHT_COUNT:
|
|
||||||
nightroles.append(user)
|
|
||||||
actedcount += 1
|
|
||||||
elif tu[1] < var.NIGHT_COUNT - 1:
|
|
||||||
nightroles.append(user)
|
|
||||||
|
|
||||||
event = Event("chk_nightdone", {"actedcount": actedcount, "nightroles": nightroles, "transition_day": transition_day})
|
event = Event("chk_nightdone", {"actedcount": actedcount, "nightroles": nightroles, "transition_day": transition_day})
|
||||||
event.dispatch(var)
|
event.dispatch(var)
|
||||||
actedcount = event.data["actedcount"]
|
actedcount = event.data["actedcount"]
|
||||||
@ -3603,6 +3572,11 @@ def choose_target(actor, nick):
|
|||||||
# returns true if a swap happened
|
# returns true if a swap happened
|
||||||
# check for that to short-circuit the nightrole
|
# check for that to short-circuit the nightrole
|
||||||
def check_exchange(cli, actor, nick):
|
def check_exchange(cli, actor, nick):
|
||||||
|
# July 2nd, 2018 - The exchanging mechanic has been updated and no longer handles
|
||||||
|
# some forms of exchanging properly. As a result, we are disabling exchanging until
|
||||||
|
# role classes are implemented, which needs all roles to be fully split first.
|
||||||
|
# Until then, this function is a no-op. -Vgr & woffle
|
||||||
|
return False
|
||||||
#some roles can act on themselves, ignore this
|
#some roles can act on themselves, ignore this
|
||||||
if actor == nick:
|
if actor == nick:
|
||||||
return False
|
return False
|
||||||
@ -3636,8 +3610,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
var.ALPHA_WOLVES.discard(actor)
|
var.ALPHA_WOLVES.discard(actor)
|
||||||
elif actor_role == "warlock":
|
elif actor_role == "warlock":
|
||||||
var.CURSED.discard(actor)
|
var.CURSED.discard(actor)
|
||||||
elif actor_role == "turncoat":
|
|
||||||
del var.TURNCOATS[actor]
|
|
||||||
|
|
||||||
|
|
||||||
# var.PASSED is used by many roles
|
# var.PASSED is used by many roles
|
||||||
@ -3660,17 +3632,20 @@ def check_exchange(cli, actor, nick):
|
|||||||
var.ALPHA_WOLVES.discard(nick)
|
var.ALPHA_WOLVES.discard(nick)
|
||||||
elif nick_role == "warlock":
|
elif nick_role == "warlock":
|
||||||
var.CURSED.discard(nick)
|
var.CURSED.discard(nick)
|
||||||
elif nick_role == "turncoat":
|
|
||||||
del var.TURNCOATS[nick]
|
|
||||||
|
|
||||||
evt = Event("exchange_roles", {"actor_messages": [], "target_messages": [], "actor_role": actor_role, "target_role": nick_role})
|
evt = Event("exchange_roles", {"actor_messages": [], "target_messages": [], "actor_role": actor_role, "target_role": nick_role})
|
||||||
evt.dispatch(var, user, target, actor_role, nick_role)
|
evt.dispatch(var, user, target, actor_role, nick_role) # FIXME: Deprecated, change in favor of new_role and swap_role_state
|
||||||
|
|
||||||
actor_role = evt.data["actor_role"]
|
nick_role = change_role(var, user, actor_role, nick_role, inherit_from=target)
|
||||||
nick_role = evt.data["target_role"]
|
actor_role = change_role(var, target, nick_role, actor_role, inherit_from=user)
|
||||||
|
|
||||||
|
if nick_role == actor_role: # make sure that two players with the same role exchange their role state properly (e.g. dullahan)
|
||||||
|
evt_same = Event("swap_role_state", {"actor_messages": [], "target_messages": []})
|
||||||
|
evt_same.dispatch(var, user, target, actor_role)
|
||||||
|
|
||||||
|
user.send(*evt_same.data["actor_messages"])
|
||||||
|
target.send(*evt_same.data["target_messages"])
|
||||||
|
|
||||||
change_role(user, actor_role, nick_role)
|
|
||||||
change_role(target, nick_role, actor_role)
|
|
||||||
if actor in var.BITTEN_ROLES.keys():
|
if actor in var.BITTEN_ROLES.keys():
|
||||||
if nick in var.BITTEN_ROLES.keys():
|
if nick in var.BITTEN_ROLES.keys():
|
||||||
var.BITTEN_ROLES[actor], var.BITTEN_ROLES[nick] = var.BITTEN_ROLES[nick], var.BITTEN_ROLES[actor]
|
var.BITTEN_ROLES[actor], var.BITTEN_ROLES[nick] = var.BITTEN_ROLES[nick], var.BITTEN_ROLES[actor]
|
||||||
@ -3691,25 +3666,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
var.LYCAN_ROLES[actor] = var.LYCAN_ROLES[nick]
|
var.LYCAN_ROLES[actor] = var.LYCAN_ROLES[nick]
|
||||||
del var.LYCAN_ROLES[nick]
|
del var.LYCAN_ROLES[nick]
|
||||||
|
|
||||||
actor_rev_role = actor_role
|
|
||||||
if actor_role in var.HIDDEN_ROLES:
|
|
||||||
actor_rev_role = var.DEFAULT_ROLE
|
|
||||||
elif actor_role in var.HIDDEN_VILLAGERS:
|
|
||||||
actor_rev_role = "villager"
|
|
||||||
|
|
||||||
nick_rev_role = nick_role
|
|
||||||
if nick_role in var.HIDDEN_ROLES:
|
|
||||||
nick_rev_role = var.DEFAULT_ROLE
|
|
||||||
elif actor_role in var.HIDDEN_VILLAGERS:
|
|
||||||
nick_rev_role = "villager"
|
|
||||||
|
|
||||||
# don't say who, since misdirection/luck totem may have switched it
|
|
||||||
# and this makes life far more interesting
|
|
||||||
user.send(messages["role_swap"].format(nick_rev_role))
|
|
||||||
target.send(messages["role_swap"].format(actor_rev_role))
|
|
||||||
user.send(*evt.data["actor_messages"])
|
|
||||||
target.send(*evt.data["target_messages"])
|
|
||||||
|
|
||||||
wcroles = var.WOLFCHAT_ROLES
|
wcroles = var.WOLFCHAT_ROLES
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES:
|
if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES:
|
||||||
if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF:
|
if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF:
|
||||||
@ -3726,8 +3682,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
if player in get_roles("cursed villager"): # FIXME
|
if player in get_roles("cursed villager"): # FIXME
|
||||||
pl[i] = player + " (cursed)"
|
pl[i] = player + " (cursed)"
|
||||||
pm(cli, actor, messages["players_list"].format(", ".join(pl)))
|
pm(cli, actor, messages["players_list"].format(", ".join(pl)))
|
||||||
elif nick_role == "turncoat":
|
|
||||||
var.TURNCOATS[actor] = ("none", -1)
|
|
||||||
|
|
||||||
if actor_role not in wcroles and actor_role == "warlock":
|
if actor_role not in wcroles and actor_role == "warlock":
|
||||||
# this means warlock isn't in wolfchat, so only give cursed list
|
# this means warlock isn't in wolfchat, so only give cursed list
|
||||||
@ -3738,8 +3692,6 @@ def check_exchange(cli, actor, nick):
|
|||||||
if player in get_roles("cursed villager"): # FIXME
|
if player in get_roles("cursed villager"): # FIXME
|
||||||
pl[i] = player + " (cursed)"
|
pl[i] = player + " (cursed)"
|
||||||
pm(cli, nick, messages["players_list"].format(", ".join(pl)))
|
pm(cli, nick, messages["players_list"].format(", ".join(pl)))
|
||||||
elif actor_role == "turncoat":
|
|
||||||
var.TURNCOATS[nick] = ("none", -1)
|
|
||||||
|
|
||||||
var.EXCHANGED_ROLES.append((actor, nick))
|
var.EXCHANGED_ROLES.append((actor, nick))
|
||||||
return True
|
return True
|
||||||
@ -3994,15 +3946,14 @@ def immunize(cli, nick, chan, rest):
|
|||||||
var.DISEASED.remove(victim)
|
var.DISEASED.remove(victim)
|
||||||
if victim in get_roles("lycan"): # FIXME
|
if victim in get_roles("lycan"): # FIXME
|
||||||
lycan = True
|
lycan = True
|
||||||
lycan_message = (messages["lycan_cured"])
|
|
||||||
if get_role(victim) == "lycan":
|
if get_role(victim) == "lycan":
|
||||||
change_role(users._get(victim), "lycan", "villager") # FIXME
|
change_role(var, users._get(victim), "lycan", "villager", message="lycan_cured") # FIXME
|
||||||
else:
|
else:
|
||||||
var.ROLES["lycan"].remove(users._get(victim)) # FIXME
|
var.ROLES["lycan"].remove(users._get(victim)) # FIXME
|
||||||
var.CURED_LYCANS.add(victim)
|
var.CURED_LYCANS.add(victim)
|
||||||
else:
|
else:
|
||||||
lycan_message = messages[evt.data["message"]]
|
lycan_message = messages[evt.data["message"]]
|
||||||
pm(cli, victim, (messages["immunization_success"]).format(lycan_message))
|
pm(cli, victim, (messages["immunization_success"]).format(lycan_message))
|
||||||
if evt.data["success"]:
|
if evt.data["success"]:
|
||||||
var.IMMUNIZED.add(victim)
|
var.IMMUNIZED.add(victim)
|
||||||
var.DOCTORS[nick] -= 1
|
var.DOCTORS[nick] -= 1
|
||||||
@ -4040,57 +3991,18 @@ def bite_cmd(cli, nick, chan, rest):
|
|||||||
relay_wolfchat_command(cli, nick, messages["alpha_bite_wolfchat"].format(nick, victim), ("alpha wolf",), is_wolf_command=True)
|
relay_wolfchat_command(cli, nick, messages["alpha_bite_wolfchat"].format(nick, victim), ("alpha wolf",), is_wolf_command=True)
|
||||||
debuglog("{0} ({1}) BITE: {2} ({3})".format(nick, get_role(nick), actual, get_role(actual)))
|
debuglog("{0} ({1}) BITE: {2} ({3})".format(nick, get_role(nick), actual, get_role(actual)))
|
||||||
|
|
||||||
@cmd("pass", chan=False, pm=True, playing=True, phases=("night",), roles=("turncoat", "warlock"))
|
@cmd("pass", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("warlock",))
|
||||||
def pass_cmd(cli, nick, chan, rest):
|
def pass_cmd(cli, nick, chan, rest):
|
||||||
"""Decline to use your special power for that night."""
|
"""Decline to use your special power for that night."""
|
||||||
nickrole = get_role(nick)
|
if nick in var.CURSED:
|
||||||
|
pm(cli, nick, messages["already_cursed"])
|
||||||
# turncoats can change roles and pass even if silenced
|
|
||||||
if nickrole != "turncoat" and nick in var.SILENCED:
|
|
||||||
if chan == nick:
|
|
||||||
pm(cli, nick, messages["silenced"])
|
|
||||||
else:
|
|
||||||
cli.notice(nick, messages["silenced"])
|
|
||||||
return
|
return
|
||||||
|
pm(cli, nick, messages["warlock_pass"])
|
||||||
if nickrole == "turncoat":
|
relay_wolfchat_command(cli, nick, messages["warlock_pass_wolfchat"].format(nick), ("warlock",))
|
||||||
if var.TURNCOATS[nick][1] == var.NIGHT_COUNT:
|
var.PASSED.add(nick)
|
||||||
# theoretically passing would revert them to how they were before, but
|
|
||||||
# we aren't tracking that, so just tell them to change it back themselves.
|
|
||||||
pm(cli, nick, messages["turncoat_fail"])
|
|
||||||
return
|
|
||||||
pm(cli, nick, messages["turncoat_pass"])
|
|
||||||
if var.TURNCOATS[nick][1] == var.NIGHT_COUNT - 1:
|
|
||||||
# don't add to var.PASSED since we aren't counting them anyway for nightdone
|
|
||||||
# let them still use !pass though to make them feel better or something
|
|
||||||
return
|
|
||||||
var.PASSED.add(nick)
|
|
||||||
elif nickrole == "warlock":
|
|
||||||
if nick in var.CURSED:
|
|
||||||
pm(cli, nick, messages["already_cursed"])
|
|
||||||
return
|
|
||||||
pm(cli, nick, messages["warlock_pass"])
|
|
||||||
relay_wolfchat_command(cli, nick, messages["warlock_pass_wolfchat"].format(nick), ("warlock",))
|
|
||||||
var.PASSED.add(nick)
|
|
||||||
|
|
||||||
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
|
debuglog("{0} ({1}) PASS".format(nick, get_role(nick)))
|
||||||
|
|
||||||
@cmd("side", chan=False, pm=True, playing=True, phases=("night",), roles=("turncoat",))
|
|
||||||
def change_sides(cli, nick, chan, rest, sendmsg=True):
|
|
||||||
if var.TURNCOATS[nick][1] == var.NIGHT_COUNT - 1:
|
|
||||||
pm(cli, nick, messages["turncoat_already_turned"])
|
|
||||||
return
|
|
||||||
|
|
||||||
team = re.split(" +", rest)[0]
|
|
||||||
team = complete_one_match(team, ("villagers", "wolves"))
|
|
||||||
if not team:
|
|
||||||
pm(cli, nick, messages["turncoat_error"])
|
|
||||||
return
|
|
||||||
|
|
||||||
pm(cli, nick, messages["turncoat_success"].format(team))
|
|
||||||
var.TURNCOATS[nick] = (team, var.NIGHT_COUNT)
|
|
||||||
debuglog("{0} ({1}) SIDE {2}".format(nick, get_role(nick), team))
|
|
||||||
|
|
||||||
@cmd("hex", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hag",))
|
@cmd("hex", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("hag",))
|
||||||
def hex_target(cli, nick, chan, rest):
|
def hex_target(cli, nick, chan, rest):
|
||||||
"""Hex someone, preventing them from acting the next day and night."""
|
"""Hex someone, preventing them from acting the next day and night."""
|
||||||
@ -4437,21 +4349,6 @@ def transition_night():
|
|||||||
else:
|
else:
|
||||||
lycan.send(messages["lycan_notify"])
|
lycan.send(messages["lycan_notify"])
|
||||||
|
|
||||||
for turncoat in get_all_players(("turncoat",)):
|
|
||||||
# they start out as unsided, but can change n1
|
|
||||||
if turncoat.nick not in var.TURNCOATS:
|
|
||||||
var.TURNCOATS[turncoat.nick] = ("none", -1)
|
|
||||||
|
|
||||||
if turncoat.prefers_simple():
|
|
||||||
turncoat.send(messages["turncoat_simple"].format(var.TURNCOATS[turncoat.nick][0]))
|
|
||||||
else:
|
|
||||||
message = messages["turncoat_notify"]
|
|
||||||
if var.TURNCOATS[turncoat.nick][0] != "none":
|
|
||||||
message += messages["turncoat_current_team"].format(var.TURNCOATS[turncoat.nick][0])
|
|
||||||
else:
|
|
||||||
message += messages["turncoat_no_team"]
|
|
||||||
turncoat.send(message)
|
|
||||||
|
|
||||||
for priest in get_all_players(("priest",)):
|
for priest in get_all_players(("priest",)):
|
||||||
if priest.prefers_simple():
|
if priest.prefers_simple():
|
||||||
priest.send(messages["priest_simple"])
|
priest.send(messages["priest_simple"])
|
||||||
@ -4738,7 +4635,6 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
var.BITTEN_ROLES = {}
|
var.BITTEN_ROLES = {}
|
||||||
var.LYCAN_ROLES = {}
|
var.LYCAN_ROLES = {}
|
||||||
var.ACTIVE_PROTECTIONS = defaultdict(list)
|
var.ACTIVE_PROTECTIONS = defaultdict(list)
|
||||||
var.TURNCOATS = {}
|
|
||||||
var.EXCHANGED_ROLES = []
|
var.EXCHANGED_ROLES = []
|
||||||
var.EXTRA_WOLVES = 0
|
var.EXTRA_WOLVES = 0
|
||||||
var.PRIESTS = set()
|
var.PRIESTS = set()
|
||||||
@ -4857,8 +4753,10 @@ def start(cli, nick, chan, forced = False, restart = ""):
|
|||||||
var.LAST_TIME = None
|
var.LAST_TIME = None
|
||||||
var.LAST_VOTES = None
|
var.LAST_VOTES = None
|
||||||
|
|
||||||
event = Event("role_assignment", {})
|
for role, players in var.ROLES.items():
|
||||||
event.dispatch(var, var.CURRENT_GAMEMODE.name, get_players())
|
for player in players:
|
||||||
|
evt = Event("new_role", {"messages": [], "role": role}, inherit_from=None)
|
||||||
|
evt.dispatch(var, player, None)
|
||||||
|
|
||||||
if not restart:
|
if not restart:
|
||||||
gamemode = var.CURRENT_GAMEMODE.name
|
gamemode = var.CURRENT_GAMEMODE.name
|
||||||
@ -5567,10 +5465,6 @@ def myrole(var, wrapper, message):
|
|||||||
for msg in evt.data["messages"]:
|
for msg in evt.data["messages"]:
|
||||||
wrapper.pm(msg)
|
wrapper.pm(msg)
|
||||||
|
|
||||||
# Remind turncoats of their side
|
|
||||||
if role == "turncoat":
|
|
||||||
wrapper.pm(messages["turncoat_side"].format(var.TURNCOATS.get(wrapper.source.nick, "none")[0]))
|
|
||||||
|
|
||||||
# Check for gun/bullets
|
# Check for gun/bullets
|
||||||
if wrapper.source not in var.ROLES["amnesiac"] and wrapper.source in var.GUNNERS and var.GUNNERS[wrapper.source]:
|
if wrapper.source not in var.ROLES["amnesiac"] and wrapper.source in var.GUNNERS and var.GUNNERS[wrapper.source]:
|
||||||
role = "gunner"
|
role = "gunner"
|
||||||
@ -6041,9 +5935,6 @@ def revealroles(var, wrapper, message):
|
|||||||
# print how many bullets normal gunners have
|
# print how many bullets normal gunners have
|
||||||
if (role == "gunner" or role == "sharpshooter") and user in var.GUNNERS:
|
if (role == "gunner" or role == "sharpshooter") and user in var.GUNNERS:
|
||||||
special_case.append("{0} bullet{1}".format(var.GUNNERS[user], "" if var.GUNNERS[user] == 1 else "s"))
|
special_case.append("{0} bullet{1}".format(var.GUNNERS[user], "" if var.GUNNERS[user] == 1 else "s"))
|
||||||
elif role == "turncoat" and user.nick in var.TURNCOATS:
|
|
||||||
special_case.append("currently with \u0002{0}\u0002".format(var.TURNCOATS[user.nick][0])
|
|
||||||
if var.TURNCOATS[user.nick][0] != "none" else "not currently on any side")
|
|
||||||
|
|
||||||
evt = Event("revealroles_role", {"special_case": special_case})
|
evt = Event("revealroles_role", {"special_case": special_case})
|
||||||
evt.dispatch(var, user, role)
|
evt.dispatch(var, user, role)
|
||||||
|
Loading…
Reference in New Issue
Block a user