From a2be87b85afd614634734c8acbbab75542e80021 Mon Sep 17 00:00:00 2001 From: Em Barry Date: Wed, 10 Jan 2018 09:51:45 -0500 Subject: [PATCH] Convert succubus (#311) Convert succubus to new API along with (un)related fixes. --- src/roles/angel.py | 10 +- src/roles/detective.py | 9 +- src/roles/doomsayer.py | 9 +- src/roles/dullahan.py | 26 ++-- src/roles/harlot.py | 6 +- src/roles/hunter.py | 17 ++- src/roles/piper.py | 12 +- src/roles/seer.py | 9 +- src/roles/shaman.py | 21 +-- src/roles/succubus.py | 261 +++++++++++++++++++------------------ src/roles/vengefulghost.py | 6 +- src/roles/vigilante.py | 16 +-- src/roles/wolf.py | 27 ++-- src/wolfgame.py | 13 +- 14 files changed, 234 insertions(+), 208 deletions(-) diff --git a/src/roles/angel.py b/src/roles/angel.py index 6088e4f..f8d3988 100644 --- a/src/roles/angel.py +++ b/src/roles/angel.py @@ -34,11 +34,15 @@ def guard(cli, nick, chan, rest): if role == "guardian angel" and LASTGUARDED.get(nick) == victim: pm(cli, nick, messages["guardian_target_another"].format(victim)) return + + angel = users._get(nick) # FIXME + target = users._get(victim) # FIXME + # self-guard ignores luck/misdirection/exchange totem - evt = Event("targeted_command", {"target": victim, "misdirection": victim != nick, "exchange": victim != nick}) - if not evt.dispatch(cli, var, "guard", nick, victim, frozenset({"beneficial"})): + evt = Event("targeted_command", {"target": target, "misdirection": (angel is not target), "exchange": (angel is not target)}) + if not evt.dispatch(var, "guard", angel, target, frozenset({"beneficial"})): return - victim = evt.data["target"] + victim = evt.data["target"].nick GUARDED[nick] = victim LASTGUARDED[nick] = victim if victim == nick: diff --git a/src/roles/detective.py b/src/roles/detective.py index 03b031e..453d5f1 100644 --- a/src/roles/detective.py +++ b/src/roles/detective.py @@ -26,11 +26,14 @@ def investigate(cli, nick, chan, rest): pm(cli, nick, messages["no_investigate_self"]) return - evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}) - evt.dispatch(cli, var, "see", nick, victim, frozenset({"info", "immediate"})) + det = users._get(nick) # FIXME + target = users._get(victim) # FIXME + + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "identify", det, target, frozenset({"info", "immediate"})) if evt.prevent_default: return - victim = evt.data["target"] + victim = evt.data["target"].nick vrole = get_role(victim) if vrole == "amnesiac": vrole = var.AMNESIAC_ROLES[victim] diff --git a/src/roles/doomsayer.py b/src/roles/doomsayer.py index fe91570..1dd1d6c 100644 --- a/src/roles/doomsayer.py +++ b/src/roles/doomsayer.py @@ -34,11 +34,14 @@ def see(cli, nick, chan, rest): pm(cli, nick, messages["no_see_wolf"]) return - evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}) - evt.dispatch(cli, var, "see", nick, victim, frozenset({"detrimental", "immediate"})) + doomsayer = users._get(nick) # FIXME + target = users._get(victim) # FIXME + + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "see", doomsayer, target, frozenset({"detrimental", "immediate"})) if evt.prevent_default: return - victim = evt.data["target"] + victim = evt.data["target"].nick victimrole = get_role(victim) mode, mapping = random.choice(_mappings) diff --git a/src/roles/dullahan.py b/src/roles/dullahan.py index 9c2d8af..a14ae2d 100644 --- a/src/roles/dullahan.py +++ b/src/roles/dullahan.py @@ -26,11 +26,11 @@ def dullahan_kill(var, wrapper, message): return orig = target - evt = Event("targeted_command", {"target": target.nick, "misdirection": True, "exchange": True}) - evt.dispatch(wrapper.client, var, "kill", wrapper.source.nick, target.nick, frozenset({"detrimental"})) + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) if evt.prevent_default: return - target = users._get(evt.data["target"]) # FIXME: Need to fix once targeted_command uses the new API + target = evt.data["target"] KILLS[wrapper.source] = target @@ -192,19 +192,13 @@ def on_role_assignment(evt, cli, var, gamemode, pl, restart): ts.add(target) @event_listener("succubus_visit") -def on_succubus_visit(evt, cli, var, nick, victim): - user = users._get(victim) # FIXME - if user in TARGETS: - succ_target = False - for target in set(TARGETS[user]): - if target in var.ROLES["succubus"]: - TARGETS[user].remove(target) - succ_target = True - if succ_target: - pm(cli, victim, messages["dullahan_no_kill_succubus"]) - if user in KILLS and KILLS[user] in var.ROLES["succubus"]: - pm(cli, victim, messages["no_kill_succubus"].format(KILLS[user])) - del KILLS[user] +def on_succubus_visit(evt, var, succubus, target): + if target in TARGETS and succubus in TARGETS[target]: + TARGETS[target].remove(succubus) + target.send(messages["dullahan_no_kill_succubus"]) + if target in KILLS and KILLS[target] in get_all_players(("succubus",)): + target.send(messages["no_kill_succubus"].format(KILLS[target])) + del KILLS[target] @event_listener("myrole") def on_myrole(evt, var, user): diff --git a/src/roles/harlot.py b/src/roles/harlot.py index fed2f5c..463fb39 100644 --- a/src/roles/harlot.py +++ b/src/roles/harlot.py @@ -27,11 +27,11 @@ def hvisit(var, wrapper, message): if not target: return - evt = Event("targeted_command", {"target": target.nick, "misdirection": True, "exchange": True}) - evt.dispatch(wrapper.client, var, "visit", wrapper.source.nick, target.nick, frozenset({"immediate"})) + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "visit", wrapper.source, target, frozenset({"immediate"})) if evt.prevent_default: return - target = users._get(evt.data["target"]) # FIXME + target = evt.data["target"] vrole = get_main_role(target) VISITED[wrapper.source] = target diff --git a/src/roles/hunter.py b/src/roles/hunter.py index 4d6b4e7..335d64a 100644 --- a/src/roles/hunter.py +++ b/src/roles/hunter.py @@ -25,12 +25,12 @@ def hunter_kill(var, wrapper, message): return orig = target - evt = Event("targeted_command", {"target": target.nick, "misdirection": True, "exchange": True}) - evt.dispatch(wrapper.client, var, "kill", wrapper.source.nick, target.nick, frozenset({"detrimental"})) + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) if evt.prevent_default: return - target = users._get(evt.data["target"]) # FIXME: Need to fix once targeted_command uses the new API + target = evt.data["target"] KILLS[wrapper.source] = target HUNTERS.add(wrapper.source) @@ -136,12 +136,11 @@ def on_transition_night_end(evt, var): hunter.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n") @event_listener("succubus_visit") -def on_succubus_visit(evt, cli, var, nick, victim): - user = users._get(victim) # FIXME - if user in KILLS and KILLS[user] in var.ROLES["succubus"]: - user.send(messages["no_kill_succubus"].format(KILLS[user])) - del KILLS[user] - HUNTERS.discard(user) +def on_succubus_visit(evt, var, succubus, target): + if target in KILLS and KILLS[target] in get_all_players(("succubus",)): + target.send(messages["no_kill_succubus"].format(KILLS[target])) + del KILLS[target] + HUNTERS.discard(target) @event_listener("begin_day") def on_begin_day(evt, var): diff --git a/src/roles/piper.py b/src/roles/piper.py index 7dfced7..b3815a8 100644 --- a/src/roles/piper.py +++ b/src/roles/piper.py @@ -41,18 +41,18 @@ def charm(var, wrapper, message): orig1 = target1 orig2 = target2 - evt1 = Event("targeted_command", {"target": target1.nick, "misdirection": True, "exchange": True}) - evt1.dispatch(wrapper.client, var, "charm", wrapper.source.nick, target1.nick, frozenset({"detrimental"})) + evt1 = Event("targeted_command", {"target": target1, "misdirection": True, "exchange": True}) + evt1.dispatch(var, "charm", wrapper.source, target1, frozenset({"detrimental"})) if evt1.prevent_default: return - target1 = users._get(evt1.data["target"]) # FIXME: need to make targeted_command use users + target1 = evt1.data["target"] if target2 is not None: - evt2 = Event("targeted_command", {"target": target2.nick, "misdirection": True, "exchange": True}) - evt2.dispatch(wrapper.client, var, "charm", wrapper.source.nick, target2.nick, frozenset({"detrimental"})) + evt2 = Event("targeted_command", {"target": target2, "misdirection": True, "exchange": True}) + evt2.dispatch(var, "charm", wrapper.source, target2, frozenset({"detrimental"})) if evt2.prevent_default: return - target2 = users._get(evt2.data["target"]) # FIXME + target2 = evt2.data["target"] # Do these checks based on original targets, so piper doesn't know to change due to misdirection/luck totem if orig1 is orig2: diff --git a/src/roles/seer.py b/src/roles/seer.py index c7a2892..5bf4553 100644 --- a/src/roles/seer.py +++ b/src/roles/seer.py @@ -27,11 +27,14 @@ def see(cli, nick, chan, rest): pm(cli, nick, messages["no_see_self"]) return - evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}) - evt.dispatch(cli, var, "see", nick, victim, frozenset({"info", "immediate"})) + seer = users._get(nick) # FIXME + target = users._get(victim) # FIXME + + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "see", seer, target, frozenset({"info", "immediate"})) if evt.prevent_default: return - victim = evt.data["target"] + victim = evt.data["target"].nick victimrole = get_role(victim) vrole = victimrole # keep a copy for logging diff --git a/src/roles/shaman.py b/src/roles/shaman.py index ae4dacd..0267948 100644 --- a/src/roles/shaman.py +++ b/src/roles/shaman.py @@ -7,7 +7,7 @@ import botconfig import src.settings as var from src.utilities import * from src import debuglog, errlog, plog, users, channels -from src.functions import get_players, get_main_role +from src.functions import get_players, get_all_players, get_main_role from src.decorators import cmd, event_listener from src.messages import messages from src.events import Event @@ -74,12 +74,15 @@ def totem(cli, nick, chan, rest, prefix="You"): # XXX: The transition_day_begin if role != "crazed shaman" and TOTEMS[nick] in var.BENEFICIAL_TOTEMS: tags.add("beneficial") - evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}, + shaman = users._get(nick) # FIXME + target = users._get(victim) # FIXME + + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}, action="give a totem{0} to".format(totem)) - evt.dispatch(cli, var, "totem", nick, victim, frozenset(tags)) + evt.dispatch(var, "totem", shaman, target, frozenset(tags)) if evt.prevent_default: return - victim = evt.data["target"] + victim = evt.data["target"].nick victimrole = get_role(victim) pm(cli, nick, messages["shaman_success"].format(prefix, totem, original_victim)) @@ -585,11 +588,11 @@ def on_assassinate(evt, var, killer, target, prot): channels.Main.send(messages[evt.params.message_prefix + "totem"].format(killer, target)) @event_listener("succubus_visit") -def on_succubus_visit(evt, cli, var, nick, victim): - if (users._get(SHAMANS.get(victim, (None, None))[1], allow_none=True) in var.ROLES["succubus"] and - (get_role(victim) == "crazed shaman" or TOTEMS[victim] not in var.BENEFICIAL_TOTEMS)): - pm(cli, victim, messages["retract_totem_succubus"].format(SHAMANS[victim])) - del SHAMANS[victim] +def on_succubus_visit(evt, var, succubus, target): + if (users._get(SHAMANS.get(target.nick, (None, None))[1], allow_none=True) in get_all_players(("succubus",)) and # FIXME + (get_main_role(target) == "crazed shaman" or TOTEMS[target.nick] not in var.BENEFICIAL_TOTEMS)): + target.send(messages["retract_totem_succubus"].format(SHAMANS[target.nick][1])) + del SHAMANS[target.nick] @event_listener("myrole") def on_myrole(evt, var, user): diff --git a/src/roles/succubus.py b/src/roles/succubus.py index ef6a351..2366a82 100644 --- a/src/roles/succubus.py +++ b/src/roles/succubus.py @@ -8,90 +8,95 @@ import botconfig import src.settings as var from src.utilities import * from src import channels, users, debuglog, errlog, plog -from src.functions import get_players, get_all_players, get_main_role -from src.decorators import cmd, event_listener +from src.functions import get_players, get_all_players, get_main_role, get_target +from src.decorators import command, event_listener from src.messages import messages from src.events import Event -ENTRANCED = set() -ENTRANCED_DYING = set() -VISITED = {} +ENTRANCED = set() # type: Set[users.User] +ENTRANCED_DYING = set() # type: Set[users.User] +VISITED = {} # type: Dict[users.User, users.User] +PASSED = set() # type: Set[users.User] ALL_SUCC_IDLE = True -@cmd("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("succubus",)) -def hvisit(cli, nick, chan, rest): +@command("visit", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("succubus",)) +def hvisit(var, wrapper, message): """Entrance a player, converting them to your team.""" - if VISITED.get(nick): - pm(cli, nick, messages["succubus_already_visited"].format(VISITED[nick])) + if VISITED.get(wrapper.source): + wrapper.send(messages["succubus_already_visited"].format(VISITED[wrapper.source])) return - victim = get_victim(cli, nick, re.split(" +",rest)[0], False, True) - if not victim: + + target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="succubus_not_self") + + if not target: return - if nick == victim: - pm(cli, nick, messages["succubus_not_self"]) - return - evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": False}) - evt.dispatch(cli, var, "visit", nick, victim, frozenset({"detrimental", "immediate"})) + + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": False}) + evt.dispatch(var, "visit", wrapper.source, target, frozenset({"detrimental", "immediate"})) if evt.prevent_default: return - victim = evt.data["target"] + target = evt.data["target"] - VISITED[nick] = victim - if victim not in var.ROLES["succubus"]: - ENTRANCED.add(victim) - pm(cli, nick, messages["succubus_target_success"].format(victim)) + VISITED[wrapper.source] = target + PASSED.discard(wrapper.source) + + if target not in get_all_players(("succubus",)): + ENTRANCED.add(target) + wrapper.send(messages["succubus_target_success"].format(target)) else: - pm(cli, nick, messages["harlot_success"].format(victim)) - if nick != victim: - if victim not in var.ROLES["succubus"]: - pm(cli, victim, messages["notify_succubus_target"].format(nick)) + wrapper.send(messages["harlot_success"].format(target)) + + if wrapper.source is not target: + if target not in get_all_players(("succubus",)): + target.send(messages["notify_succubus_target"].format(wrapper.source)) else: - pm(cli, victim, messages["harlot_success"].format(nick)) + target.send(messages["harlot_success"].format(wrapper.source)) + revt = Event("succubus_visit", {}) - revt.dispatch(cli, var, nick, victim) + revt.dispatch(var, wrapper.source, target) # TODO: split these into assassin, hag, and alpha wolf when they are split off - if var.TARGETED.get(victim) in var.ROLES["succubus"]: - msg = messages["no_target_succubus"].format(var.TARGETED[victim]) - del var.TARGETED[victim] - if victim in var.ROLES["village drunk"]: - target = random.choice(list(set(list_players()) - var.ROLES["succubus"] - {victim})) - msg += messages["drunk_target"].format(target) - var.TARGETED[victim] = target - pm(cli, victim, nick) - if victim in var.HEXED and var.LASTHEXED[victim] in var.ROLES["succubus"]: - pm(cli, victim, messages["retract_hex_succubus"].format(var.LASTHEXED[victim])) - var.TOBESILENCED.remove(nick) - var.HEXED.remove(victim) - del var.LASTHEXED[victim] - if var.BITE_PREFERENCES.get(victim) in var.ROLES["succubus"]: - pm(cli, victim, messages["no_kill_succubus"].format(var.BITE_PREFERENCES[victim])) - del var.BITE_PREFERENCES[victim] + if users._get(var.TARGETED.get(target.nick), allow_none=True) in get_all_players(("succubus",)): # FIXME + msg = messages["no_target_succubus"].format(var.TARGETED[target.nick]) + del var.TARGETED[target.nick] + if target in get_all_players(("village drunk",)): + victim = random.choice(list(get_all_players() - get_all_players(("succubus",)) - {target})) + msg += messages["drunk_target"].format(victim) + var.TARGETED[target.nick] = victim.nick + target.send(msg) - debuglog("{0} (succubus) VISIT: {1} ({2})".format(nick, victim, get_role(victim))) - chk_nightdone(cli) + if target.nick in var.HEXED and users._get(var.LASTHEXED[target.nick]) in get_all_players(("succubus",)): # FIXME + target.send(messages["retract_hex_succubus"].format(var.LASTHEXED[target.nick])) + var.TOBESILENCED.remove(wrapper.source.nick) + var.HEXED.remove(target.nick) + del var.LASTHEXED[target.nick] + if users._get(var.BITE_PREFERENCES.get(target.nick), allow_none=True) in get_all_players(("succubus",)): # FIXME + target.send(messages["no_kill_succubus"].format(var.BITE_PREFERENCES[target.nick])) + del var.BITE_PREFERENCES[target.nick] -@cmd("pass", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("succubus",)) -def pass_cmd(cli, nick, chan, rest): + debuglog("{0} (succubus) VISIT: {1} ({2})".format(wrapper.source, target, get_main_role(target))) + +@command("pass", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("succubus",)) +def pass_cmd(var, wrapper, message): """Do not entrance someone tonight.""" - if VISITED.get(nick): - pm(cli, nick, messages["succubus_already_visited"].format(VISITED[nick])) + if VISITED.get(wrapper.source): + wrapper.send(messages["succubus_already_visited"].format(VISITED[wrapper.source])) return - VISITED[nick] = None - pm(cli, nick, messages["succubus_pass"]) - debuglog("{0} (succubus) PASS".format(nick)) - chk_nightdone(cli) + + PASSED.add(wrapper.source) + wrapper.send(messages["succubus_pass"]) + debuglog("{0} (succubus) PASS".format(wrapper.source)) @event_listener("harlot_visit") def on_harlot_visit(evt, var, harlot, victim): - if victim.nick in var.ROLES["succubus"]: + if victim in get_all_players(("succubus",)): harlot.send(messages["notify_succubus_target"].format(victim)) victim.send(messages["succubus_harlot_success"].format(harlot)) - ENTRANCED.add(harlot.nick) + ENTRANCED.add(harlot) @event_listener("get_random_totem_targets") def on_get_random_totem_targets(evt, var, shaman): - if shaman.nick in ENTRANCED: + if shaman in ENTRANCED: for succubus in get_all_players(("succubus",)): if succubus in evt.data["targets"]: evt.data["targets"].remove(succubus) @@ -99,29 +104,39 @@ def on_get_random_totem_targets(evt, var, shaman): @event_listener("chk_decision", priority=0) def on_chk_decision(evt, cli, var, force): for votee, voters in evt.data["votelist"].items(): - if votee in var.ROLES["succubus"]: + if users._get(votee) in get_all_players(("succubus",)): # FIXME for vtr in ENTRANCED: - if vtr in voters: - voters.remove(vtr) + if vtr.nick in voters: + voters.remove(vtr.nick) def _kill_entranced_voters(var, votelist, not_lynching, votee): - if not var.ROLES["succubus"] & (set(itertools.chain(*votelist.values())) | not_lynching): + if not {p.nick for p in get_all_players(("succubus",))} & (set(itertools.chain(*votelist.values())) | not_lynching): # FIXME # none of the succubi voted (or there aren't any succubi), so short-circuit return # kill off everyone entranced that did not follow one of the succubi's votes or abstain # unless a succubus successfully voted the target, then people that didn't follow are spared - ENTRANCED_DYING.update(ENTRANCED - var.DEAD) + for x in ENTRANCED: + if x.nick not in var.DEAD: + ENTRANCED_DYING.add(x) + for other_votee, other_voters in votelist.items(): - if var.ROLES["succubus"] & set(other_voters): + if {p.nick for p in get_all_players(("succubus",))} & set(other_voters): # FIXME if votee == other_votee: ENTRANCED_DYING.clear() return - ENTRANCED_DYING.difference_update(other_voters) - if var.ROLES["succubus"] & not_lynching: + + for x in set(ENTRANCED_DYING): + if x.nick in other_voters: + ENTRANCED_DYING.remove(x) + + if {p.nick for p in get_all_players(("succubus",))} & not_lynching: # FIXME if votee is None: ENTRANCED_DYING.clear() return - ENTRANCED_DYING.difference_update(not_lynching) + + for x in set(ENTRANCED_DYING): + if x.nick in not_lynching: + ENTRANCED_DYING.remove(x) @event_listener("chk_decision_lynch", priority=5) def on_chk_decision_lynch(evt, cli, var, voters): @@ -134,15 +149,11 @@ def on_chk_decision_abstain(evt, cli, var, not_lynching): _kill_entranced_voters(var, evt.params.votelist, not_lynching, None) # entranced logic should run after team wins have already been determined (aka run last) -# we do not want to override the win conditions for neutral roles should they win while entranced -# For example, entranced monsters should win with other monsters should mosnters win, and be -# properly credited with a team win in that event. @event_listener("player_win", priority=6) def on_player_win(evt, var, user, role, winner, survived): - nick = user.nick - if nick in ENTRANCED: + if user in ENTRANCED: evt.data["special"].append("entranced") - if winner != "succubi" and role not in var.TRUE_NEUTRAL_ROLES: + if winner != "succubi": evt.data["won"] = False else: evt.data["iwon"] = True @@ -152,14 +163,14 @@ def on_player_win(evt, var, user, role, winner, survived): @event_listener("chk_win", priority=2) def on_chk_win(evt, cli, var, rolemap, mainroles, lpl, lwolves, lrealwolves): lsuccubi = len(rolemap.get("succubus", ())) - lentranced = len(ENTRANCED - var.DEAD) + lentranced = len([x for x in ENTRANCED if x.nick not in var.DEAD]) if lsuccubi and var.PHASE == "day" and lpl - lsuccubi == lentranced: evt.data["winner"] = "succubi" evt.data["message"] = messages["succubus_win"].format(plural("succubus", lsuccubi), plural("has", lsuccubi), plural("master's", lsuccubi)) @event_listener("can_exchange") -def on_can_exchange(evt, var, user, target): - if user.nick in var.ROLES["succubus"] or target.nick in var.ROLES["succubus"]: +def on_can_exchange(evt, var, actor, target): + if actor in get_all_players(("succubus",)) or target in get_all_players(("succubus",)): evt.prevent_default = True evt.stop_processing = True @@ -168,14 +179,14 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers): global ALL_SUCC_IDLE if "succubus" not in allroles: return - if user.nick in VISITED: + if user in VISITED: # if it's night, also unentrance the person they visited if var.PHASE == "night" and var.GAMEPHASE == "night": - if VISITED[user.nick] in ENTRANCED: - ENTRANCED.discard(VISITED[user.nick]) - ENTRANCED_DYING.discard(VISITED[user.nick]) - pm(user.client, VISITED[user.nick], messages["entranced_revert_win"]) - del VISITED[user.nick] + if VISITED[user] in ENTRANCED: + ENTRANCED.discard(VISITED[user]) + ENTRANCED_DYING.discard(VISITED[user]) + VISITED[user].send(messages["entranced_revert_win"]) + del VISITED[user] # if all succubi are dead, one of two things happen: # 1. if all succubi idled out (every last one of them), un-entrance people @@ -183,12 +194,12 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers): # death_triggers is False for an idle-out, so we use that to determine which it is if death_triggers: ALL_SUCC_IDLE = False - if len(var.ROLES["succubus"]) == 0: - entranced_alive = {users._get(x) for x in ENTRANCED}.difference(evt.params.deadlist).intersection(evt.data["pl"]) # FIXME + if not get_all_players(("succubus",)): + entranced_alive = ENTRANCED.difference(evt.params.deadlist).intersection(evt.data["pl"]) if ALL_SUCC_IDLE: while ENTRANCED: e = ENTRANCED.pop() - pm(user.client, e, messages["entranced_revert_win"]) + e.send(messages["entranced_revert_win"]) elif entranced_alive: msg = [] # Run in two loops so we can play the message for everyone dying at once before we actually @@ -222,7 +233,7 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers): @event_listener("transition_day_resolve", priority=1) def on_transition_day_resolve(evt, var, victim): - if victim.nick in var.ROLES["succubus"] and VISITED.get(victim.nick) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]: + if victim in get_all_players(("succubus",)) and VISITED.get(victim) and victim not in evt.data["dead"] and victim in evt.data["onlybywolves"]: # TODO: check if this is necessary for succubus, it's to prevent a message playing if alpha bites # a harlot that is visiting a wolf, since the bite succeeds in that case. if victim not in evt.data["bitten"]: @@ -234,36 +245,35 @@ def on_transition_day_resolve(evt, var, victim): @event_listener("transition_day_resolve_end", priority=1) def on_transition_day_resolve_end(evt, var, victims): for victim in victims + evt.data["bitten"]: - if victim in evt.data["dead"] and victim.nick in VISITED.values() and (victim in evt.data["bywolves"] or victim in evt.data["bitten"]): - for succ in VISITED: - user = users._get(succ) # FIXME - if VISITED[succ] == victim.nick and user not in evt.data["bitten"] and user not in evt.data["dead"]: + if victim in evt.data["dead"] and victim in VISITED.values() and (victim in evt.data["bywolves"] or victim in evt.data["bitten"]): + for succubus in VISITED: + if VISITED[succubus] is victim and succubus not in evt.data["bitten"] and succubus not in evt.data["dead"]: if var.ROLE_REVEAL in ("on", "team"): - evt.data["message"].append(messages["visited_victim"].format(succ, get_reveal_role(succ))) + evt.data["message"].append(messages["visited_victim"].format(succubus, get_reveal_role(succubus.nick))) else: - evt.data["message"].append(messages["visited_victim_noreveal"].format(succ)) - evt.data["bywolves"].add(user) - evt.data["onlybywolves"].add(user) - evt.data["dead"].append(user) + evt.data["message"].append(messages["visited_victim_noreveal"].format(succubus)) + evt.data["bywolves"].add(succubus) + evt.data["onlybywolves"].add(succubus) + evt.data["dead"].append(succubus) @event_listener("night_acted") -def on_night_acted(evt, var, user, actor): - if VISITED.get(user.nick): +def on_night_acted(evt, var, target, spy): + if VISITED.get(target): evt.data["acted"] = True @event_listener("chk_nightdone") def on_chk_nightdone(evt, var): - evt.data["actedcount"] += len(VISITED) + evt.data["actedcount"] += len(VISITED) + len(PASSED) evt.data["nightroles"].extend(get_all_players(("succubus",))) @event_listener("targeted_command") -def on_targeted_command(evt, cli, var, cmd, actor, orig_target, tags): - if "beneficial" not in tags and actor in ENTRANCED and evt.data["target"] in var.ROLES["succubus"]: +def on_targeted_command(evt, var, name, actor, orig_target, tags): + if "beneficial" not in tags and actor in ENTRANCED and evt.data["target"] in get_all_players(("succubus",)): try: what = evt.params.action except AttributeError: - what = cmd - pm(cli, actor, messages["no_acting_on_succubus"].format(what)) + what = name + actor.send(messages["no_acting_on_succubus"].format(what)) evt.stop_processing = True evt.prevent_default = True @@ -289,14 +299,14 @@ def on_transition_night_end(evt, var): def on_begin_day(evt, var): VISITED.clear() ENTRANCED_DYING.clear() + PASSED.clear() @event_listener("transition_day", priority=2) def on_transition_day(evt, var): for v in ENTRANCED_DYING: - user = users._get(v) # FIXME - var.DYING.add(user) # indicate that the death bypasses protections - evt.data["victims"].append(user) - evt.data["onlybywolves"].discard(user) + var.DYING.add(v) # indicate that the death bypasses protections + evt.data["victims"].append(v) + evt.data["onlybywolves"].discard(v) # we do not add to killers as retribution totem should not work on entranced not following succubus @event_listener("get_special") @@ -305,25 +315,27 @@ def on_get_special(evt, var): @event_listener("vg_kill") def on_vg_kill(evt, var, ghost, target): - if ghost.nick in ENTRANCED: - evt.data["pl"] -= var.ROLES["succubus"] + if ghost in ENTRANCED: + evt.data["pl"] -= get_all_players(("succubus",)) -@event_listener("rename_player") -def on_rename(evt, cli, var, prefix, nick): - if prefix in ENTRANCED: - ENTRANCED.remove(prefix) - ENTRANCED.add(nick) - if prefix in ENTRANCED_DYING: - ENTRANCED_DYING.remove(prefix) - ENTRANCED_DYING.add(nick) - kvp = {} - for a,b in VISITED.items(): - s = nick if a == prefix else a - t = nick if b == prefix else b - kvp[s] = t - VISITED.update(kvp) - if prefix in VISITED: - del VISITED[prefix] +@event_listener("swap_player") +def on_swap(evt, var, old_user, user): + if old_user in ENTRANCED: + ENTRANCED.remove(old_user) + ENTRANCED.add(user) + if old_user in ENTRANCED_DYING: + ENTRANCED_DYING.remove(old_user) + ENTRANCED_DYING.add(user) + + for succubus, target in set(VISITED.items()): + if old_user is succubus: + VISITED[user] = VISITED.pop(succubus) + if old_user is target: + VISITED[succubus] = user + + if old_user in PASSED: + PASSED.remove(old_user) + PASSED.add(user) @event_listener("reset") def on_reset(evt, var): @@ -332,13 +344,14 @@ def on_reset(evt, var): ENTRANCED.clear() ENTRANCED_DYING.clear() VISITED.clear() + PASSED.clear() @event_listener("revealroles") def on_revealroles(evt, var, wrapper): if ENTRANCED: - evt.data["output"].append("\u0002entranced players\u0002: {0}".format(", ".join(ENTRANCED))) + evt.data["output"].append("\u0002entranced players\u0002: {0}".format(", ".join(p.nick for p in ENTRANCED))) if ENTRANCED_DYING: - evt.data["output"].append("\u0002dying entranced players\u0002: {0}".format(", ".join(ENTRANCED_DYING))) + evt.data["output"].append("\u0002dying entranced players\u0002: {0}".format(", ".join(p.nick for p in ENTRANCED_DYING))) # vim: set sw=4 expandtab: diff --git a/src/roles/vengefulghost.py b/src/roles/vengefulghost.py index 5d36193..90cfcf3 100644 --- a/src/roles/vengefulghost.py +++ b/src/roles/vengefulghost.py @@ -39,11 +39,11 @@ def vg_kill(var, wrapper, message): return orig = target - evt = Event("targeted_command", {"target": target.nick, "misdirection": True, "exchange": False}) - evt.dispatch(wrapper.source.client, var, "kill", wrapper.source.nick, target.nick, frozenset({"detrimental"})) + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": False}) + evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) if evt.prevent_default: return - target = users._get(evt.data["target"]) # FIXME + target = evt.data["target"] KILLS[wrapper.source] = target diff --git a/src/roles/vigilante.py b/src/roles/vigilante.py index e271027..3723eb1 100644 --- a/src/roles/vigilante.py +++ b/src/roles/vigilante.py @@ -20,11 +20,11 @@ def vigilante_kill(var, wrapper, message): target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_suicide") orig = target - evt = Event("targeted_command", {"target": target.nick, "misdirection": True, "exchange": True}) - evt.dispatch(wrapper.client, var, "kill", wrapper.source.nick, target.nick, frozenset({"detrimental"})) + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) if evt.prevent_default: return - target = users._get(evt.data["target"]) # FIXME + target = evt.data["target"] KILLS[wrapper.source] = target PASSED.discard(wrapper.source) @@ -119,12 +119,10 @@ def on_transition_night_end(evt, var): vigilante.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n") @event_listener("succubus_visit") -def on_succubus_visit(evt, cli, var, nick, victim): - for vigilante, target in set(KILLS.items()): - if vigilante.nick == victim: - if target in var.ROLES["succubus"]: - vigilante.send(messages["no_kill_succubus"].format(target)) - del KILLS[vigilante] +def on_succubus_visit(evt, var, succubus, target): + if target in KILLS and KILLS[target] in get_all_players(("succubus",)): + target.send(messages["no_kill_succubus"].format(KILLS[target])) + del KILLS[target] @event_listener("begin_day") def on_begin_day(evt, var): diff --git a/src/roles/wolf.py b/src/roles/wolf.py index 0257fa8..ffaf52f 100644 --- a/src/roles/wolf.py +++ b/src/roles/wolf.py @@ -45,6 +45,8 @@ def wolf_kill(cli, nick, chan, rest): nevt.dispatch(var) num_kills = nevt.data["numkills"] + wolf = users._get(nick) # FIXME + i = 0 extra = 0 while i < num_kills + extra: @@ -67,11 +69,14 @@ def wolf_kill(cli, nick, chan, rest): pm(cli, nick, messages["wolf_no_target_wolf"]) return orig.append(victim) - evt = Event("targeted_command", {"target": victim, "misdirection": True, "exchange": True}) - evt.dispatch(cli, var, "kill", nick, victim, frozenset({"detrimental"})) + + target = users._get(victim) # FIXME + + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + evt.dispatch(var, "kill", wolf, target, frozenset({"detrimental"})) if evt.prevent_default: return - victim = evt.data["target"] + victim = evt.data["target"].nick victims.append(victim) i += 1 @@ -426,14 +431,14 @@ def on_transition_night_end(evt, var): wolf.send(messages["wolf_bite"]) @event_listener("succubus_visit") -def on_succubus_visit(evt, cli, var, nick, victim): - if var.ROLES["succubus"].intersection(users._get(x) for x in KILLS.get(victim, ())): # FIXME: once KILLS holds User instances - for s in var.ROLES["succubus"]: - if s.nick in KILLS[victim]: # FIXME - pm(cli, victim, messages["no_kill_succubus"].format(nick)) - KILLS[victim].remove(s.nick) # FIXME - if not KILLS[victim]: - del KILLS[victim] +def on_succubus_visit(evt, var, succubus, target): + if get_all_players(("succubus",)).intersection(users._get(x) for x in KILLS.get(target.nick, ())): # FIXME: once KILLS holds User instances + for s in get_all_players(("succubus",)): + if s.nick in KILLS[target.nick]: + target.send(messages["no_kill_succubus"].format(succubus)) + KILLS[target.nick].remove(s.nick) + if not KILLS[target.nick]: + del KILLS[target.nick] @event_listener("begin_day") def on_begin_day(evt, var): diff --git a/src/wolfgame.py b/src/wolfgame.py index 415668d..6350c3e 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -4808,11 +4808,11 @@ def clone(cli, nick, chan, rest): var.ROLE_COMMAND_EXCEPTIONS.add("clone") @event_listener("targeted_command", priority=9) -def on_targeted_command(evt, cli, var, cmd, actor, orig_target, tags): +def on_targeted_command(evt, var, name, actor, orig_target, tags): if evt.data["misdirection"]: - evt.data["target"] = choose_target(actor, evt.data["target"]) + evt.data["target"] = users._get(choose_target(actor.nick, evt.data["target"].nick)) # FIXME - if evt.data["exchange"] and check_exchange(cli, actor, evt.data["target"]): + if evt.data["exchange"] and check_exchange(actor.client, actor.nick, evt.data["target"].nick): evt.stop_processing = True evt.prevent_default = True @@ -5030,12 +5030,13 @@ def transition_night(cli): event = Event("amnesiac_turn", {}) if event.dispatch(var, amn, var.AMNESIAC_ROLES[amn]): amnrole = var.AMNESIAC_ROLES[amn] - change_role(users._get(amn), "amnesiac", amnrole) # FIXME + amnuser = users._get(amn) # FIXME + change_role(amnuser, "amnesiac", amnrole) var.AMNESIACS.add(amn) # TODO: turn into event when amnesiac is split from src.roles import succubus - if amnrole == "succubus" and amn in succubus.ENTRANCED: - succubus.ENTRANCED.remove(amn) + if amnrole == "succubus" and amnuser in succubus.ENTRANCED: + succubus.ENTRANCED.remove(amnuser) pm(cli, amn, messages["no_longer_entranced"]) if var.FIRST_NIGHT: # we don't need to tell them twice if they remember right away continue