Split Mad Scientist (#295)
* Split Mad Scientist Related changes: - MS now honors all protections instead of only caring about blessed villagers - Allow FA to bypass protection even if FA is applied as a template - Make bodyguard swap themselves in as the assassination target rather than blocking the attempt outright and suiciding. This means that active protections on the bodyguard have a chance to save them as well. - Redo some messages to make the above sound nice in the bot. - Add some additional params to the assassinate event to see WHY the assassination is happening (source) and WHO is doing the assassination (killer; currently a nick but should be a user sometime in the future). - Add a target data item to teh assassinate event so that listeners can change who is being assassinated. Protection boilerplate has been adjusted to account for this. - Add helper function to get the targets, avoiding code duplication
This commit is contained in:
parent
ef3c670a0d
commit
4bfa5f16f6
@ -198,7 +198,7 @@
|
|||||||
"lover_suicide_no_reveal": "Saddened by the loss of their lover, \u0002{0}\u0002 commits suicide.",
|
"lover_suicide_no_reveal": "Saddened by the loss of their lover, \u0002{0}\u0002 commits suicide.",
|
||||||
"assassin_fail_totem": "Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; however, {1}'s totem emits a brilliant flash of light, causing the attempt to miss.",
|
"assassin_fail_totem": "Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; however, {1}'s totem emits a brilliant flash of light, causing the attempt to miss.",
|
||||||
"assassin_fail_angel": "Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; however, a guardian angel was on duty and able to foil the attempt.",
|
"assassin_fail_angel": "Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; however, a guardian angel was on duty and able to foil the attempt.",
|
||||||
"assassin_fail_bodyguard": "Before dying, \u0002{0}\u0002 quickly attempts to slit \u0002{1}\u0002's throat; however, \u0002{2}\u0002, a bodyguard, sacrificed their life to protect them.",
|
"assassin_fail_bodyguard": "Sensing danger, \u0002{2}\u0002 shoves \u0002{1}\u0002 aside to save them from \u0002{0}\u0002.",
|
||||||
"assassin_success": "Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat. The village mourns the loss of a{2} \u0002{3}\u0002.",
|
"assassin_success": "Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat. The village mourns the loss of a{2} \u0002{3}\u0002.",
|
||||||
"assassin_success_no_reveal": "Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat.",
|
"assassin_success_no_reveal": "Before dying, \u0002{0}\u0002 quickly slits \u0002{1}\u0002's throat.",
|
||||||
"time_lord_dead": "Tick tock! Since the time lord has died, day will now only last {0} seconds and night will now only last {1} seconds!",
|
"time_lord_dead": "Tick tock! Since the time lord has died, day will now only last {0} seconds and night will now only last {1} seconds!",
|
||||||
@ -209,6 +209,9 @@
|
|||||||
"mad_scientist_kill_single": "\u0002{0}\u0002 throws a potent chemical concoction into the crowd. \u0002{1}\u0002, a{2} \u0002{3}\u0002, gets hit by the chemicals and dies.",
|
"mad_scientist_kill_single": "\u0002{0}\u0002 throws a potent chemical concoction into the crowd. \u0002{1}\u0002, a{2} \u0002{3}\u0002, gets hit by the chemicals and dies.",
|
||||||
"mad_scientist_kill_single_no_reveal": "\u0002{0}\u0002 throws a potent chemical concoction into the crowd. \u0002{1}\u0002 gets hit by the chemicals and dies.",
|
"mad_scientist_kill_single_no_reveal": "\u0002{0}\u0002 throws a potent chemical concoction into the crowd. \u0002{1}\u0002 gets hit by the chemicals and dies.",
|
||||||
"mad_scientist_fail": "\u0002{0}\u0002 throws a potent chemical concoction into the crowd. Thankfully, nobody seems to have gotten hit.",
|
"mad_scientist_fail": "\u0002{0}\u0002 throws a potent chemical concoction into the crowd. Thankfully, nobody seems to have gotten hit.",
|
||||||
|
"mad_scientist_fail_totem": "Sensing danger, \u0002{1}\u0002's totem emits a brilliant flash of light, teleporting them away from \u0002{0}\u0002.",
|
||||||
|
"mad_scientist_fail_angel": "Sensing danger, a guardian angel whisks \u0002{1}\u0002 away from \u0002{0}\u0002.",
|
||||||
|
"mad_scientist_fail_bodyguard": "Sensing danger, \u0002{2}\u0002 shoves \u0002{1}\u0002 aside to save them from \u0002{0}\u0002.",
|
||||||
"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.",
|
||||||
@ -726,7 +729,7 @@
|
|||||||
"succubus_win": "Game over! The {0} {1} completely enthralled the village, making them officers in an ever-growing army set on spreading their {2} control and influence throughout the entire world.",
|
"succubus_win": "Game over! The {0} {1} completely enthralled the village, making them officers in an ever-growing army set on spreading their {2} control and influence throughout the entire world.",
|
||||||
"dullahan_die_totem": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002; however, {1}'s totem emits a brilliant flash of light, causing the attempt to miss.",
|
"dullahan_die_totem": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002; however, {1}'s totem emits a brilliant flash of light, causing the attempt to miss.",
|
||||||
"dullahan_die_angel": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002; however, a guardian angel was on duty and able to foil the attempt.",
|
"dullahan_die_angel": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002; however, a guardian angel was on duty and able to foil the attempt.",
|
||||||
"dullahan_die_bodyguard": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002; however, \u0002{2}\u0002, a bodyguard, sacrificed their life to protect them.",
|
"dullahan_die_bodyguard": "Sensing danger, \u0002{2}\u0002 shoves \u0002{1}\u0002 aside to save them from \u0002{0}\u0002.",
|
||||||
"assassin_fail_blessed": "\u0002{0}\u0002 seems to be blessed, causing your assassination attempt to fail.",
|
"assassin_fail_blessed": "\u0002{0}\u0002 seems to be blessed, causing your assassination attempt to fail.",
|
||||||
"dullahan_die_success": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002, killing them. The village mourns the loss of a{2} \u0002{3}\u0002.",
|
"dullahan_die_success": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002, killing them. The village mourns the loss of a{2} \u0002{3}\u0002.",
|
||||||
"dullahan_die_success_noreveal": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002, killing them.",
|
"dullahan_die_success_noreveal": "Before dying, \u0002{0}\u0002 snaps a whip made of a human spine at \u0002{1}\u0002, killing them.",
|
||||||
|
@ -7,7 +7,7 @@ from collections import defaultdict
|
|||||||
import botconfig
|
import botconfig
|
||||||
import src.settings as var
|
import src.settings as var
|
||||||
from src.utilities import *
|
from src.utilities import *
|
||||||
from src import debuglog, errlog, plog
|
from src import users, debuglog, errlog, plog
|
||||||
from src.decorators import cmd, event_listener
|
from src.decorators import cmd, event_listener
|
||||||
from src.messages import messages
|
from src.messages import messages
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
@ -277,8 +277,8 @@ def on_assassinate(evt, cli, var, nick, target, prot):
|
|||||||
for bg in var.ROLES["bodyguard"]:
|
for bg in var.ROLES["bodyguard"]:
|
||||||
if GUARDED.get(bg) == target:
|
if GUARDED.get(bg) == target:
|
||||||
cli.msg(botconfig.CHANNEL, messages[evt.params.message_prefix + "bodyguard"].format(nick, target, bg))
|
cli.msg(botconfig.CHANNEL, messages[evt.params.message_prefix + "bodyguard"].format(nick, target, bg))
|
||||||
evt.params.del_player(cli, bg, True, end_game=False, killer_role=evt.params.nickrole, deadlist=evt.params.deadlist, original=evt.params.original, ismain=False)
|
# redirect the assassination to the bodyguard
|
||||||
evt.data["pl"] = evt.params.refresh_pl(evt.data["pl"])
|
evt.data["target"] = users._get(bg) # FIXME
|
||||||
break
|
break
|
||||||
|
|
||||||
@event_listener("begin_day")
|
@event_listener("begin_day")
|
||||||
|
@ -70,25 +70,34 @@ def on_del_player(evt, cli, var, nick, mainrole, allroles, death_triggers):
|
|||||||
pl = evt.data["pl"]
|
pl = evt.data["pl"]
|
||||||
targets = TARGETS[users._get(nick)].intersection(users._get(x) for x in pl) # FIXME
|
targets = TARGETS[users._get(nick)].intersection(users._get(x) for x in pl) # FIXME
|
||||||
if targets:
|
if targets:
|
||||||
target = random.choice(list(targets)).nick
|
target = random.choice(list(targets))
|
||||||
prots = deque(var.ACTIVE_PROTECTIONS[target])
|
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
||||||
aevt = Event("assassinate", {"pl": evt.data["pl"]},
|
aevt = Event("assassinate", {"pl": evt.data["pl"], "target": target},
|
||||||
del_player=evt.params.del_player,
|
del_player=evt.params.del_player,
|
||||||
deadlist=evt.params.deadlist,
|
deadlist=evt.params.deadlist,
|
||||||
original=evt.params.original,
|
original=evt.params.original,
|
||||||
refresh_pl=evt.params.refresh_pl,
|
refresh_pl=evt.params.refresh_pl,
|
||||||
message_prefix="dullahan_die_",
|
message_prefix="dullahan_die_",
|
||||||
|
source="dullahan",
|
||||||
|
killer=nick,
|
||||||
killer_mainrole=mainrole,
|
killer_mainrole=mainrole,
|
||||||
killer_allroles=allroles,
|
killer_allroles=allroles,
|
||||||
prots=prots)
|
prots=prots)
|
||||||
while len(prots) > 0:
|
while len(prots) > 0:
|
||||||
# an event can read the current active protection and cancel the totem
|
# an event can read the current active protection and cancel or redirect the assassination
|
||||||
# if it cancels, it is responsible for removing the protection from var.ACTIVE_PROTECTIONS
|
# if it cancels, it is responsible for removing the protection from var.ACTIVE_PROTECTIONS
|
||||||
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
||||||
if not aevt.dispatch(cli, var, nick, target, prots[0]):
|
if not aevt.dispatch(cli, var, nick, target.nick, prots[0]):
|
||||||
evt.data["pl"] = aevt.data["pl"]
|
evt.data["pl"] = aevt.data["pl"]
|
||||||
|
if target is not aevt.data["target"]:
|
||||||
|
target = aevt.data["target"]
|
||||||
|
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
||||||
|
aevt.params.prots = prots
|
||||||
|
continue
|
||||||
return
|
return
|
||||||
prots.popleft()
|
prots.popleft()
|
||||||
|
|
||||||
|
target = target.nick # FIXME
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
role = get_reveal_role(target)
|
role = get_reveal_role(target)
|
||||||
an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
|
an = "n" if role.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
@ -44,7 +44,7 @@ def on_transition_day(evt, cli, var):
|
|||||||
def on_assassinate(evt, cli, var, nick, target, prot):
|
def on_assassinate(evt, cli, var, nick, target, prot):
|
||||||
# bypass all protection if FA is doing the killing
|
# bypass all protection if FA is doing the killing
|
||||||
# we do this by stopping propagation, meaning future events won't fire
|
# we do this by stopping propagation, meaning future events won't fire
|
||||||
if evt.params.nickrole == "fallen angel":
|
if "fallen angel" in evt.params.killer_allroles:
|
||||||
evt.params.prots.clear()
|
evt.params.prots.clear()
|
||||||
evt.stop_processing = True
|
evt.stop_processing = True
|
||||||
evt.prevent_default = True
|
evt.prevent_default = True
|
||||||
|
162
src/roles/madscientist.py
Normal file
162
src/roles/madscientist.py
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import re
|
||||||
|
import random
|
||||||
|
import itertools
|
||||||
|
import math
|
||||||
|
from collections import defaultdict, deque
|
||||||
|
|
||||||
|
import botconfig
|
||||||
|
import src.settings as var
|
||||||
|
from src.utilities import *
|
||||||
|
from src import channels, users, debuglog, errlog, plog
|
||||||
|
from src.decorators import command, event_listener
|
||||||
|
from src.messages import messages
|
||||||
|
from src.events import Event
|
||||||
|
|
||||||
|
def _get_targets(var, pl, nick):
|
||||||
|
"""Gets the mad scientist's targets.
|
||||||
|
|
||||||
|
var - settings module
|
||||||
|
pl - list of alive players
|
||||||
|
nick - nick of the mad scientist"""
|
||||||
|
for index, user in enumerate(var.ALL_PLAYERS):
|
||||||
|
if user.nick == nick: # FIXME
|
||||||
|
break
|
||||||
|
|
||||||
|
num_players = len(var.ALL_PLAYERS)
|
||||||
|
target1 = var.ALL_PLAYERS[index - 1]
|
||||||
|
target2 = var.ALL_PLAYERS[(index + 1) % num_players]
|
||||||
|
if num_players >= var.MAD_SCIENTIST_SKIPS_DEAD_PLAYERS:
|
||||||
|
# determine left player
|
||||||
|
i = index
|
||||||
|
while True:
|
||||||
|
i = (i - 1) % num_players
|
||||||
|
if var.ALL_PLAYERS[i].nick in pl or var.ALL_PLAYERS[i].nick == nick:
|
||||||
|
target1 = var.ALL_PLAYERS[i]
|
||||||
|
break
|
||||||
|
# determine right player
|
||||||
|
i = index
|
||||||
|
while True:
|
||||||
|
i = (i + 1) % num_players
|
||||||
|
if var.ALL_PLAYERS[i].nick in pl or var.ALL_PLAYERS[i].nick == nick:
|
||||||
|
target2 = var.ALL_PLAYERS[i]
|
||||||
|
break
|
||||||
|
|
||||||
|
return (target1, target2)
|
||||||
|
|
||||||
|
|
||||||
|
@event_listener("del_player")
|
||||||
|
def on_del_player(evt, cli, var, nick, mainrole, allroles, death_triggers):
|
||||||
|
if not death_triggers or "mad scientist" not in allroles:
|
||||||
|
return
|
||||||
|
|
||||||
|
pl = evt.data["pl"]
|
||||||
|
target1, target2 = _get_targets(var, pl, nick)
|
||||||
|
|
||||||
|
# apply protections (if applicable)
|
||||||
|
prots1 = deque(var.ACTIVE_PROTECTIONS[target1.nick])
|
||||||
|
prots2 = deque(var.ACTIVE_PROTECTIONS[target2.nick])
|
||||||
|
# for this event, we don't tell the event that the other side is dying
|
||||||
|
# this allows, e.g. a bodyguard and the person they are guarding to get splashed,
|
||||||
|
# and the bodyguard to still sacrifice themselves to guard the other person
|
||||||
|
aevt = Event("assassinate", {"pl": pl, "target": target1},
|
||||||
|
del_player=evt.params.del_player,
|
||||||
|
deadlist=evt.params.deadlist,
|
||||||
|
original=evt.params.original,
|
||||||
|
refresh_pl=evt.params.refresh_pl,
|
||||||
|
message_prefix="mad_scientist_fail_",
|
||||||
|
source="mad scientist",
|
||||||
|
killer=nick,
|
||||||
|
killer_mainrole=mainrole,
|
||||||
|
killer_allroles=allroles,
|
||||||
|
prots=prots1)
|
||||||
|
while len(prots1) > 0:
|
||||||
|
# events may be able to cancel this kill
|
||||||
|
if not aevt.dispatch(cli, var, nick, target1.nick, prots1[0]):
|
||||||
|
pl = aevt.data["pl"]
|
||||||
|
if target1 is not aevt.data["target"]:
|
||||||
|
target1 = aevt.data["target"]
|
||||||
|
prots1 = deque(var.ACTIVE_PROTECTIONS[target1.nick])
|
||||||
|
aevt.params.prots = prots1
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
prots1.popleft()
|
||||||
|
aevt.data["target"] = target2
|
||||||
|
aevt.params.prots = prots2
|
||||||
|
while len(prots2) > 0:
|
||||||
|
# events may be able to cancel this kill
|
||||||
|
if not aevt.dispatch(cli, var, nick, target2.nick, prots2[0]):
|
||||||
|
pl = aevt.data["pl"]
|
||||||
|
if target2 is not aevt.data["target"]:
|
||||||
|
target2 = aevt.data["target"]
|
||||||
|
prots2 = deque(var.ACTIVE_PROTECTIONS[target2.nick])
|
||||||
|
aevt.params.prots = prots2
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
prots2.popleft()
|
||||||
|
|
||||||
|
kill1 = target1.nick in pl and len(prots1) == 0
|
||||||
|
kill2 = target2.nick in pl and len(prots2) == 0 and target1 is not target2
|
||||||
|
|
||||||
|
if kill1:
|
||||||
|
if kill2:
|
||||||
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
|
r1 = get_reveal_role(target1.nick)
|
||||||
|
an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
r2 = get_reveal_role(target2.nick)
|
||||||
|
an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
tmsg = messages["mad_scientist_kill"].format(nick, target1, an1, r1, target2, an2, r2)
|
||||||
|
else:
|
||||||
|
tmsg = messages["mad_scientist_kill_no_reveal"].format(nick, target1, target2)
|
||||||
|
cli.msg(botconfig.CHANNEL, tmsg)
|
||||||
|
debuglog(nick, "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(target1, get_role(target1.nick), target2, get_role(target2.nick)))
|
||||||
|
# here we DO want to tell that the other one is dying already so chained deaths don't mess things up
|
||||||
|
deadlist1 = evt.params.deadlist[:]
|
||||||
|
deadlist1.append(target2)
|
||||||
|
deadlist2 = evt.params.deadlist[:]
|
||||||
|
deadlist2.append(target1)
|
||||||
|
evt.params.del_player(cli, target1.nick, True, end_game=False, killer_role="mad scientist", deadlist=deadlist1, original=evt.params.original, ismain=False)
|
||||||
|
evt.params.del_player(cli, target2.nick, True, end_game=False, killer_role="mad scientist", deadlist=deadlist2, original=evt.params.original, ismain=False)
|
||||||
|
pl = evt.params.refresh_pl(pl)
|
||||||
|
else:
|
||||||
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
|
r1 = get_reveal_role(target1.nick)
|
||||||
|
an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
tmsg = messages["mad_scientist_kill_single"].format(nick, target1, an1, r1)
|
||||||
|
else:
|
||||||
|
tmsg = messages["mad_scientist_kill_single_no_reveal"].format(nick, target1)
|
||||||
|
cli.msg(botconfig.CHANNEL, tmsg)
|
||||||
|
debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target1, get_role(target1.nick)))
|
||||||
|
evt.params.del_player(cli, target1.nick, True, end_game=False, killer_role="mad scientist", deadlist=evt.params.deadlist, original=evt.params.original, ismain=False)
|
||||||
|
pl = evt.params.refresh_pl(pl)
|
||||||
|
else:
|
||||||
|
if kill2:
|
||||||
|
if var.ROLE_REVEAL in ("on", "team"):
|
||||||
|
r2 = get_reveal_role(target2.nick)
|
||||||
|
an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
|
||||||
|
tmsg = messages["mad_scientist_kill_single"].format(nick, target2, an2, r2)
|
||||||
|
else:
|
||||||
|
tmsg = messages["mad_scientist_kill_single_no_reveal"].format(nick, target2)
|
||||||
|
cli.msg(botconfig.CHANNEL, tmsg)
|
||||||
|
debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target2, get_role(target2.nick)))
|
||||||
|
evt.params.del_player(cli, target2.nick, True, end_game=False, killer_role="mad scientist", deadlist=evt.params.deadlist, original=evt.params.original, ismain=False)
|
||||||
|
pl = evt.params.refresh_pl(pl)
|
||||||
|
else:
|
||||||
|
tmsg = messages["mad_scientist_fail"].format(nick)
|
||||||
|
cli.msg(botconfig.CHANNEL, tmsg)
|
||||||
|
debuglog(nick, "(mad scientist) KILL FAIL")
|
||||||
|
|
||||||
|
evt.data["pl"] = pl
|
||||||
|
|
||||||
|
@event_listener("transition_night_end", priority=2)
|
||||||
|
def on_transition_night_end(evt, cli, var):
|
||||||
|
for ms in var.ROLES["mad scientist"]:
|
||||||
|
pl = list_players()
|
||||||
|
target1, target2 = _get_targets(var, pl, ms)
|
||||||
|
|
||||||
|
if ms in var.PLAYERS and not is_user_simple(ms):
|
||||||
|
pm(cli, ms, messages["mad_scientist_notify"].format(target1, target2))
|
||||||
|
else:
|
||||||
|
pm(cli, ms, messages["mad_scientist_simple"].format(target1, target2))
|
||||||
|
|
||||||
|
|
||||||
|
# vim: set sw=4 expandtab:
|
123
src/wolfgame.py
123
src/wolfgame.py
@ -2487,13 +2487,16 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
|||||||
target = var.TARGETED[nick]
|
target = var.TARGETED[nick]
|
||||||
del var.TARGETED[nick]
|
del var.TARGETED[nick]
|
||||||
if target is not None and target in pl:
|
if target is not None and target in pl:
|
||||||
|
targuser = users._get(target) # FIXME
|
||||||
prots = deque(var.ACTIVE_PROTECTIONS[target])
|
prots = deque(var.ACTIVE_PROTECTIONS[target])
|
||||||
aevt = Event("assassinate", {"pl": pl},
|
aevt = Event("assassinate", {"pl": pl, "target": targuser},
|
||||||
del_player=del_player,
|
del_player=del_player,
|
||||||
deadlist=deadlist,
|
deadlist=deadlist,
|
||||||
original=original,
|
original=original,
|
||||||
refresh_pl=refresh_pl,
|
refresh_pl=refresh_pl,
|
||||||
message_prefix="assassin_fail_",
|
message_prefix="assassin_fail_",
|
||||||
|
source="assassin",
|
||||||
|
killer=nick,
|
||||||
killer_mainrole=nickrole,
|
killer_mainrole=nickrole,
|
||||||
killer_allroles=allroles,
|
killer_allroles=allroles,
|
||||||
prots=prots)
|
prots=prots)
|
||||||
@ -2503,6 +2506,12 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
|||||||
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
# so that it cannot be used again (if the protection is meant to be usable once-only)
|
||||||
if not aevt.dispatch(cli, var, nick, target, prots[0]):
|
if not aevt.dispatch(cli, var, nick, target, prots[0]):
|
||||||
pl = aevt.data["pl"]
|
pl = aevt.data["pl"]
|
||||||
|
if targuser is not aevt.data["target"]:
|
||||||
|
targuser = aevt.data["target"]
|
||||||
|
target = targuser.nick
|
||||||
|
prots = deque(var.ACTIVE_PROTECTIONS[target])
|
||||||
|
aevt.params.prots = prots
|
||||||
|
continue
|
||||||
break
|
break
|
||||||
prots.popleft()
|
prots.popleft()
|
||||||
if len(prots) == 0:
|
if len(prots) == 0:
|
||||||
@ -2513,7 +2522,7 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
|||||||
else:
|
else:
|
||||||
message = messages["assassin_success_no_reveal"].format(nick, target)
|
message = messages["assassin_success_no_reveal"].format(nick, target)
|
||||||
cli.msg(botconfig.CHANNEL, message)
|
cli.msg(botconfig.CHANNEL, message)
|
||||||
debuglog("{0} ({1}) ASSASSINATE: {2} ({3})".format(nick, nickrole, target, get_role(target)))
|
debuglog("{0} (assassin) ASSASSINATE: {1} ({2})".format(nick, target, get_role(target)))
|
||||||
del_player(cli, target, True, end_game=False, killer_role=nickrole, deadlist=deadlist, original=original, ismain=False)
|
del_player(cli, target, True, end_game=False, killer_role=nickrole, deadlist=deadlist, original=original, ismain=False)
|
||||||
pl = refresh_pl(pl)
|
pl = refresh_pl(pl)
|
||||||
if nickrole == "time lord":
|
if nickrole == "time lord":
|
||||||
@ -2567,86 +2576,6 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
|||||||
|
|
||||||
debuglog(nick, "(time lord) TRIGGER")
|
debuglog(nick, "(time lord) TRIGGER")
|
||||||
|
|
||||||
if nickrole == "mad scientist":
|
|
||||||
# kills the 2 players adjacent to them in the original players listing (in order of !joining)
|
|
||||||
# if those players are already dead, nothing happens
|
|
||||||
for index, user in enumerate(var.ALL_PLAYERS):
|
|
||||||
if user.nick == nick: # FIXME
|
|
||||||
break
|
|
||||||
targets = []
|
|
||||||
target1 = var.ALL_PLAYERS[index - 1]
|
|
||||||
target2 = var.ALL_PLAYERS[index + 1 if index < len(var.ALL_PLAYERS) - 1 else 0]
|
|
||||||
if len(var.ALL_PLAYERS) >= var.MAD_SCIENTIST_SKIPS_DEAD_PLAYERS:
|
|
||||||
# determine left player
|
|
||||||
i = index
|
|
||||||
while True:
|
|
||||||
i -= 1
|
|
||||||
if var.ALL_PLAYERS[i].nick in pl or var.ALL_PLAYERS[i].nick == nick:
|
|
||||||
target1 = var.ALL_PLAYERS[i]
|
|
||||||
break
|
|
||||||
# determine right player
|
|
||||||
i = index
|
|
||||||
while True:
|
|
||||||
i += 1
|
|
||||||
if i >= len(var.ALL_PLAYERS):
|
|
||||||
i = 0
|
|
||||||
if var.ALL_PLAYERS[i].nick in pl or var.ALL_PLAYERS[i].nick == nick:
|
|
||||||
target2 = var.ALL_PLAYERS[i]
|
|
||||||
break
|
|
||||||
|
|
||||||
# do not kill blessed players, they had a premonition to step out of the way before the chemicals hit
|
|
||||||
if target1.nick in var.ROLES["blessed villager"]:
|
|
||||||
target1 = None
|
|
||||||
if target2.nick in var.ROLES["blessed villager"]:
|
|
||||||
target2 = None
|
|
||||||
|
|
||||||
if target1.nick in pl:
|
|
||||||
if target2.nick in pl and target1 is not target2:
|
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
|
||||||
r1 = get_reveal_role(target1.nick)
|
|
||||||
an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
|
|
||||||
r2 = get_reveal_role(target2.nick)
|
|
||||||
an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
|
|
||||||
tmsg = messages["mad_scientist_kill"].format(nick, target1, an1, r1, target2, an2, r2)
|
|
||||||
else:
|
|
||||||
tmsg = messages["mad_scientist_kill_no_reveal"].format(nick, target1, target2)
|
|
||||||
cli.msg(botconfig.CHANNEL, tmsg)
|
|
||||||
debuglog(nick, "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(target1, get_role(target1.nick), target2, get_role(target2.nick)))
|
|
||||||
deadlist1 = copy.copy(deadlist)
|
|
||||||
deadlist1.append(target2)
|
|
||||||
deadlist2 = copy.copy(deadlist)
|
|
||||||
deadlist2.append(target1)
|
|
||||||
del_player(cli, target1.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist1, original = original, ismain = False)
|
|
||||||
del_player(cli, target2.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist2, original = original, ismain = False)
|
|
||||||
pl = refresh_pl(pl)
|
|
||||||
else:
|
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
|
||||||
r1 = get_reveal_role(target1.nick)
|
|
||||||
an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else ""
|
|
||||||
tmsg = messages["mad_scientist_kill_single"].format(nick, target1, an1, r1)
|
|
||||||
else:
|
|
||||||
tmsg = messages["mad_scientist_kill_single_no_reveal"].format(nick, target1)
|
|
||||||
cli.msg(botconfig.CHANNEL, tmsg)
|
|
||||||
debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target1, get_role(target1.nick)))
|
|
||||||
del_player(cli, target1.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist, original = original, ismain = False)
|
|
||||||
pl = refresh_pl(pl)
|
|
||||||
else:
|
|
||||||
if target2.nick in pl:
|
|
||||||
if var.ROLE_REVEAL in ("on", "team"):
|
|
||||||
r2 = get_reveal_role(target2.nick)
|
|
||||||
an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else ""
|
|
||||||
tmsg = messages["mad_scientist_kill_single"].format(nick, target2, an2, r2)
|
|
||||||
else:
|
|
||||||
tmsg = messages["mad_scientist_kill_single_no_reveal"].format(nick, target2)
|
|
||||||
cli.msg(botconfig.CHANNEL, tmsg)
|
|
||||||
debuglog(nick, "(mad scientist) KILL: {0} ({1})".format(target2, get_role(target2.nick)))
|
|
||||||
del_player(cli, target2.nick, True, end_game = False, killer_role = "mad scientist", deadlist = deadlist, original = original, ismain = False)
|
|
||||||
pl = refresh_pl(pl)
|
|
||||||
else:
|
|
||||||
tmsg = messages["mad_scientist_fail"].format(nick)
|
|
||||||
cli.msg(botconfig.CHANNEL, tmsg)
|
|
||||||
debuglog(nick, "(mad scientist) KILL FAIL")
|
|
||||||
|
|
||||||
pl = refresh_pl(pl)
|
pl = refresh_pl(pl)
|
||||||
# i herd u liek parameters
|
# i herd u liek parameters
|
||||||
evt_death_triggers = death_triggers and var.PHASE in var.GAME_PHASES
|
evt_death_triggers = death_triggers and var.PHASE in var.GAME_PHASES
|
||||||
@ -5331,36 +5260,6 @@ def transition_night(cli):
|
|||||||
else:
|
else:
|
||||||
pm(cli, drunk, messages["drunk_simple"])
|
pm(cli, drunk, messages["drunk_simple"])
|
||||||
|
|
||||||
for ms in var.ROLES["mad scientist"]:
|
|
||||||
pl = ps[:]
|
|
||||||
for index, user in enumerate(var.ALL_PLAYERS):
|
|
||||||
if user.nick == ms:
|
|
||||||
break
|
|
||||||
targets = []
|
|
||||||
target1 = var.ALL_PLAYERS[index - 1]
|
|
||||||
target2 = var.ALL_PLAYERS[index + 1 if index < len(var.ALL_PLAYERS) - 1 else 0]
|
|
||||||
if len(var.ALL_PLAYERS) >= var.MAD_SCIENTIST_SKIPS_DEAD_PLAYERS:
|
|
||||||
# determine left player
|
|
||||||
i = index
|
|
||||||
while True:
|
|
||||||
i -= 1
|
|
||||||
if var.ALL_PLAYERS[i].nick in pl or var.ALL_PLAYERS[i].nick == ms:
|
|
||||||
target1 = var.ALL_PLAYERS[i]
|
|
||||||
break
|
|
||||||
# determine right player
|
|
||||||
i = index
|
|
||||||
while True:
|
|
||||||
i += 1
|
|
||||||
if i >= len(var.ALL_PLAYERS):
|
|
||||||
i = 0
|
|
||||||
if var.ALL_PLAYERS[i].nick in pl or var.ALL_PLAYERS[i].nick == ms:
|
|
||||||
target2 = var.ALL_PLAYERS[i]
|
|
||||||
break
|
|
||||||
if ms in var.PLAYERS and not is_user_simple(ms):
|
|
||||||
pm(cli, ms, messages["mad_scientist_notify"].format(target1, target2))
|
|
||||||
else:
|
|
||||||
pm(cli, ms, messages["mad_scientist_simple"].format(target1, target2))
|
|
||||||
|
|
||||||
for doctor in var.ROLES["doctor"]:
|
for doctor in var.ROLES["doctor"]:
|
||||||
if doctor in var.DOCTORS and var.DOCTORS[doctor] > 0: # has immunizations remaining
|
if doctor in var.DOCTORS and var.DOCTORS[doctor] > 0: # has immunizations remaining
|
||||||
pl = ps[:]
|
pl = ps[:]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user