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.",
|
||||
"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_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_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!",
|
||||
@ -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_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_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.",
|
||||
"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.",
|
||||
@ -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.",
|
||||
"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_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.",
|
||||
"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.",
|
||||
|
@ -7,7 +7,7 @@ from collections import defaultdict
|
||||
import botconfig
|
||||
import src.settings as var
|
||||
from src.utilities import *
|
||||
from src import debuglog, errlog, plog
|
||||
from src import users, debuglog, errlog, plog
|
||||
from src.decorators import cmd, event_listener
|
||||
from src.messages import messages
|
||||
from src.events import Event
|
||||
@ -277,8 +277,8 @@ def on_assassinate(evt, cli, var, nick, target, prot):
|
||||
for bg in var.ROLES["bodyguard"]:
|
||||
if GUARDED.get(bg) == target:
|
||||
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)
|
||||
evt.data["pl"] = evt.params.refresh_pl(evt.data["pl"])
|
||||
# redirect the assassination to the bodyguard
|
||||
evt.data["target"] = users._get(bg) # FIXME
|
||||
break
|
||||
|
||||
@event_listener("begin_day")
|
||||
|
@ -70,25 +70,34 @@ def on_del_player(evt, cli, var, nick, mainrole, allroles, death_triggers):
|
||||
pl = evt.data["pl"]
|
||||
targets = TARGETS[users._get(nick)].intersection(users._get(x) for x in pl) # FIXME
|
||||
if targets:
|
||||
target = random.choice(list(targets)).nick
|
||||
prots = deque(var.ACTIVE_PROTECTIONS[target])
|
||||
aevt = Event("assassinate", {"pl": evt.data["pl"]},
|
||||
target = random.choice(list(targets))
|
||||
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
||||
aevt = Event("assassinate", {"pl": evt.data["pl"], "target": target},
|
||||
del_player=evt.params.del_player,
|
||||
deadlist=evt.params.deadlist,
|
||||
original=evt.params.original,
|
||||
refresh_pl=evt.params.refresh_pl,
|
||||
message_prefix="dullahan_die_",
|
||||
source="dullahan",
|
||||
killer=nick,
|
||||
killer_mainrole=mainrole,
|
||||
killer_allroles=allroles,
|
||||
prots=prots)
|
||||
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
|
||||
# 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"]
|
||||
if target is not aevt.data["target"]:
|
||||
target = aevt.data["target"]
|
||||
prots = deque(var.ACTIVE_PROTECTIONS[target.nick])
|
||||
aevt.params.prots = prots
|
||||
continue
|
||||
return
|
||||
prots.popleft()
|
||||
|
||||
target = target.nick # FIXME
|
||||
if var.ROLE_REVEAL in ("on", "team"):
|
||||
role = get_reveal_role(target)
|
||||
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):
|
||||
# bypass all protection if FA is doing the killing
|
||||
# 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.stop_processing = 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:
|
125
src/wolfgame.py
125
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]
|
||||
del var.TARGETED[nick]
|
||||
if target is not None and target in pl:
|
||||
targuser = users._get(target) # FIXME
|
||||
prots = deque(var.ACTIVE_PROTECTIONS[target])
|
||||
aevt = Event("assassinate", {"pl": pl},
|
||||
aevt = Event("assassinate", {"pl": pl, "target": targuser},
|
||||
del_player=del_player,
|
||||
deadlist=deadlist,
|
||||
original=original,
|
||||
refresh_pl=refresh_pl,
|
||||
message_prefix="assassin_fail_",
|
||||
source="assassin",
|
||||
killer=nick,
|
||||
killer_mainrole=nickrole,
|
||||
killer_allroles=allroles,
|
||||
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)
|
||||
if not aevt.dispatch(cli, var, nick, target, prots[0]):
|
||||
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
|
||||
prots.popleft()
|
||||
if len(prots) == 0:
|
||||
@ -2513,8 +2522,8 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
||||
else:
|
||||
message = messages["assassin_success_no_reveal"].format(nick, target)
|
||||
cli.msg(botconfig.CHANNEL, message)
|
||||
debuglog("{0} ({1}) ASSASSINATE: {2} ({3})".format(nick, nickrole, target, get_role(target)))
|
||||
del_player(cli, target, True, end_game = False, killer_role = nickrole, deadlist = deadlist, original = original, ismain = False)
|
||||
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)
|
||||
pl = refresh_pl(pl)
|
||||
if nickrole == "time lord":
|
||||
if "DAY_TIME_LIMIT" not in var.ORIGINAL_SETTINGS:
|
||||
@ -2567,86 +2576,6 @@ def del_player(cli, nick, forced_death=False, devoice=True, end_game=True, death
|
||||
|
||||
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)
|
||||
# i herd u liek parameters
|
||||
evt_death_triggers = death_triggers and var.PHASE in var.GAME_PHASES
|
||||
@ -5331,36 +5260,6 @@ def transition_night(cli):
|
||||
else:
|
||||
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"]:
|
||||
if doctor in var.DOCTORS and var.DOCTORS[doctor] > 0: # has immunizations remaining
|
||||
pl = ps[:]
|
||||
|
Loading…
Reference in New Issue
Block a user