diff --git a/messages/en.json b/messages/en.json index 7d5dccf..18adca6 100644 --- a/messages/en.json +++ b/messages/en.json @@ -753,7 +753,6 @@ "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.", "entranced_revert_win": "You are no longer entranced. \u0002Your win conditions have reset to normal.\u0002", - "succubus_die_kill": "As the last remaining succubus dies, a foul curse causes {0} to wither away and die in front of the astonished village.", "player_sick": "You woke up today not feeling very well, you think it best to stay home for the remainder of the day and night.", "consecrating_no_vote": "You are consecrating someone today and cannot participate in the vote.", "illness_no_vote": "You are staying home due to your illness and cannot participate in the vote.", @@ -763,7 +762,6 @@ "blessed_notify_target": "You suddenly feel very safe.", "consecrate_fail": "\u0002{0}\u0002 is not currently playing or is not dead.", "consecrate_success": "You have consecrated the body of \u0002{0}\u0002.", - "no_acting_on_succubus": "You may not {0} a succubus.", "coin_toss": "\u0002{0}\u0002 tosses a coin into the air...", "coin_land": "The coin lands on \u0002{0}\u0002.", "coin_choices": [ diff --git a/src/roles/_shaman_helper.py b/src/roles/_shaman_helper.py index 8be1ab3..af92200 100644 --- a/src/roles/_shaman_helper.py +++ b/src/roles/_shaman_helper.py @@ -48,14 +48,13 @@ brokentotem = set() # type: Set[users.User] # 1. Expand var.TOTEM_ORDER and upate var.TOTEM_CHANCES to account for the new width # 2. Add the role to var.ROLE_GUIDE # 3. Add the role to whatever other holding vars are necessary based on what it does -# 4. Setup initial variables and events with setup_variables(rolename, knows_totem, get_tags) -# knows_totem is a bool and keyword-only. get_tags is a function in the form get_tags(var, totem) -# and should return a set +# 4. Setup initial variables and events with setup_variables(rolename, knows_totem) +# knows_totem is a bool and keyword-only # 5. Implement custom events if the role does anything else beyond giving totems. # # Modifying this file to add new totems or new shaman roles is generally never required -def setup_variables(rolename, *, knows_totem, get_tags): +def setup_variables(rolename, *, knows_totem): """Setup role variables and shared events.""" TOTEMS = UserDict() # type: Dict[users.User, str] LASTGIVEN = UserDict() # type: Dict[users.User, users.User] @@ -178,14 +177,6 @@ def setup_variables(rolename, *, knows_totem, get_tags): evt.data["target_messages"].append(messages["shaman_totem"].format(actor_totem)) TOTEMS[target] = actor_totem - @event_listener("succubus_visit") - def on_succubus_visit(evt, var, succubus, target): - if target in SHAMANS and SHAMANS[target][1] in get_all_players(("succubus",)): - tags = get_tags(var, TOTEMS[target]) - if "beneficial" not in tags: - target.send(messages["retract_totem_succubus"].format(SHAMANS[target][1])) - del SHAMANS[target] - if knows_totem: @event_listener("myrole") def on_myrole(evt, var, user): @@ -206,16 +197,14 @@ def get_totem_target(var, wrapper, message, lastgiven): return target -def give_totem(var, wrapper, target, prefix, tags, role, msg): +def give_totem(var, wrapper, target, prefix, role, msg): """Give a totem to a player. Return the value of SHAMANS[user].""" orig_target = target orig_role = get_main_role(orig_target) - evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}, - action="give a totem{0} to".format(msg)) - - if not evt.dispatch(var, "totem", wrapper.source, target, frozenset(tags)): + evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) + if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] diff --git a/src/roles/angel.py b/src/roles/angel.py index de4baa7..806e6bd 100644 --- a/src/roles/angel.py +++ b/src/roles/angel.py @@ -41,7 +41,7 @@ def guard(cli, nick, chan, rest): # self-guard ignores luck/misdirection/exchange totem 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"})): + if not evt.dispatch(var, angel, target): return victim = evt.data["target"].nick GUARDED[nick] = victim diff --git a/src/roles/assassin.py b/src/roles/assassin.py index 953c1e2..8f8efa3 100644 --- a/src/roles/assassin.py +++ b/src/roles/assassin.py @@ -27,7 +27,7 @@ def target(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - if not evt.dispatch(var, "target", wrapper.source, target, frozenset({"detrimental"})): + if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] @@ -132,17 +132,6 @@ def on_del_player(evt, var, player, mainrole, allroles, death_triggers): evt.params.del_player(target, end_game=False, killer_role=mainrole, deadlist=evt.params.deadlist, original=evt.params.original, ismain=False) evt.data["pl"] = evt.params.refresh_pl(aevt.data["pl"]) -@event_listener("succubus_visit") -def on_succubus_visit(evt, var, actor, target): - if target in TARGETED and TARGETED[target] in get_all_players(("succubus",)): - msg = messages["no_target_succubus"].format(TARGETED[target]) - del TARGETED[target] - 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) - TARGETED[target] = victim - target.send(msg) - @event_listener("myrole") def on_myrole(evt, var, user): if user in get_all_players(("assassin",)): diff --git a/src/roles/augur.py b/src/roles/augur.py index aa83d53..b58fe39 100644 --- a/src/roles/augur.py +++ b/src/roles/augur.py @@ -26,7 +26,7 @@ def see(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - if not evt.dispatch(var, "identify", wrapper.source, target, frozenset({"info", "immediate"})): + if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] diff --git a/src/roles/crazedshaman.py b/src/roles/crazedshaman.py index 95b4a76..e3802c2 100644 --- a/src/roles/crazedshaman.py +++ b/src/roles/crazedshaman.py @@ -15,10 +15,7 @@ from src.events import Event from src.roles._shaman_helper import setup_variables, get_totem_target, give_totem -def get_tags(var, totem): - return set() - -TOTEMS, LASTGIVEN, SHAMANS = setup_variables("crazed shaman", knows_totem=False, get_tags=get_tags) +TOTEMS, LASTGIVEN, SHAMANS = setup_variables("crazed shaman", knows_totem=False) @command("give", "totem", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("crazed shaman",)) def crazed_shaman_totem(var, wrapper, message): @@ -28,9 +25,7 @@ def crazed_shaman_totem(var, wrapper, message): if not target: return - totem = TOTEMS[wrapper.source] - - SHAMANS[wrapper.source] = give_totem(var, wrapper, target, prefix="You", tags=get_tags(var, totem), role="crazed shaman", msg="") + SHAMANS[wrapper.source] = give_totem(var, wrapper, target, prefix="You", role="crazed shaman", msg="") @event_listener("player_win") def on_player_win(evt, var, user, role, winner, survived): @@ -47,16 +42,11 @@ def on_transition_day_begin(evt, var): if shaman in LASTGIVEN: if LASTGIVEN[shaman] in ps: ps.remove(LASTGIVEN[shaman]) - levt = Event("get_random_totem_targets", {"targets": ps}) - levt.dispatch(var, shaman) - ps = levt.data["targets"] if ps: target = random.choice(ps) dispatcher = MessageDispatcher(shaman, shaman) - tags = get_tags(var, TOTEMS[shaman]) - - SHAMANS[shaman] = give_totem(var, dispatcher, target, prefix=messages["random_totem_prefix"], tags=tags, role="crazed shaman", msg="") + SHAMANS[shaman] = give_totem(var, dispatcher, target, prefix=messages["random_totem_prefix"], role="crazed shaman", msg="") else: LASTGIVEN[shaman] = None elif shaman not in SHAMANS: diff --git a/src/roles/detective.py b/src/roles/detective.py index c5a3521..bbc6f00 100644 --- a/src/roles/detective.py +++ b/src/roles/detective.py @@ -25,7 +25,7 @@ def investigate(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - if not evt.dispatch(var, "identify", wrapper.source, target, frozenset({"info", "immediate"})): + if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] diff --git a/src/roles/doomsayer.py b/src/roles/doomsayer.py index e90ecab..017f670 100644 --- a/src/roles/doomsayer.py +++ b/src/roles/doomsayer.py @@ -31,7 +31,7 @@ def see(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - evt.dispatch(var, "see", wrapper.source, target, frozenset({"detrimental", "immediate"})) + evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return diff --git a/src/roles/dullahan.py b/src/roles/dullahan.py index 619726e..0d2ee6e 100644 --- a/src/roles/dullahan.py +++ b/src/roles/dullahan.py @@ -28,7 +28,7 @@ def dullahan_kill(var, wrapper, message): orig = target evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) + evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return target = evt.data["target"] @@ -186,12 +186,10 @@ def on_role_assignment(evt, var, gamemode, pl): @event_listener("succubus_visit") def on_succubus_visit(evt, var, succubus, target): - if target in TARGETS and succubus in TARGETS[target]: - TARGETS[target].remove(succubus) + succubi = get_all_players(("succubus",)) + if target in TARGETS and TARGETS[target].intersection(succubi): + TARGETS[target].difference_update(succubi) 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 b3015e7..ffc4bca 100644 --- a/src/roles/harlot.py +++ b/src/roles/harlot.py @@ -28,7 +28,7 @@ def hvisit(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - evt.dispatch(var, "visit", wrapper.source, target, frozenset({"immediate"})) + evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return target = evt.data["target"] diff --git a/src/roles/hunter.py b/src/roles/hunter.py index 02c2b49..061149a 100644 --- a/src/roles/hunter.py +++ b/src/roles/hunter.py @@ -26,7 +26,7 @@ def hunter_kill(var, wrapper, message): orig = target evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) + evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return @@ -125,13 +125,6 @@ def on_transition_night_end(evt, var): to_send = "hunter_simple" hunter.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n") -@event_listener("succubus_visit") -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): KILLS.clear() diff --git a/src/roles/investigator.py b/src/roles/investigator.py index c0c23a2..c2c2cb4 100644 --- a/src/roles/investigator.py +++ b/src/roles/investigator.py @@ -38,13 +38,13 @@ def investigate(var, wrapper, message): return evt = Event("targeted_command", {"target": target1, "misdirection": True, "exchange": True}) - evt.dispatch(var, "identify", wrapper.source, target1, frozenset({"info", "immediate"})) + evt.dispatch(var, wrapper.source, target1) if evt.prevent_default: return target1 = evt.data["target"] evt = Event("targeted_command", {"target": target2, "misdirection": True, "exchange": True}) - evt.dispatch(var, "identify", wrapper.source, target2, frozenset({"info", "immediate"})) + evt.dispatch(var, wrapper.source, target2) if evt.prevent_default: return target2 = evt.data["target"] diff --git a/src/roles/oracle.py b/src/roles/oracle.py index 5bef959..c1a5a41 100644 --- a/src/roles/oracle.py +++ b/src/roles/oracle.py @@ -26,7 +26,7 @@ def see(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - if not evt.dispatch(var, "see", wrapper.source, target, frozenset({"info", "immediate"})): + if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] diff --git a/src/roles/piper.py b/src/roles/piper.py index 9f6f9e2..02a8d90 100644 --- a/src/roles/piper.py +++ b/src/roles/piper.py @@ -43,14 +43,14 @@ def charm(var, wrapper, message): orig2 = target2 evt1 = Event("targeted_command", {"target": target1, "misdirection": True, "exchange": True}) - evt1.dispatch(var, "charm", wrapper.source, target1, frozenset({"detrimental"})) + evt1.dispatch(var, wrapper.source, target1) if evt1.prevent_default: return target1 = evt1.data["target"] if target2 is not None: evt2 = Event("targeted_command", {"target": target2, "misdirection": True, "exchange": True}) - evt2.dispatch(var, "charm", wrapper.source, target2, frozenset({"detrimental"})) + evt2.dispatch(var, wrapper.source, target2) if evt2.prevent_default: return target2 = evt2.data["target"] diff --git a/src/roles/seer.py b/src/roles/seer.py index c8eb7ec..5b5ad02 100644 --- a/src/roles/seer.py +++ b/src/roles/seer.py @@ -26,7 +26,7 @@ def see(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - if not evt.dispatch(var, "see", wrapper.source, target, frozenset({"info", "immediate"})): + if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] diff --git a/src/roles/shaman.py b/src/roles/shaman.py index a5ab0d3..0db9642 100644 --- a/src/roles/shaman.py +++ b/src/roles/shaman.py @@ -15,13 +15,7 @@ from src.events import Event from src.roles._shaman_helper import setup_variables, get_totem_target, give_totem -def get_tags(var, totem): - tags = set() - if totem in var.BENEFICIAL_TOTEMS: - tags.add("beneficial") - return tags - -TOTEMS, LASTGIVEN, SHAMANS = setup_variables("shaman", knows_totem=True, get_tags=get_tags) +TOTEMS, LASTGIVEN, SHAMANS = setup_variables("shaman", knows_totem=True) @command("give", "totem", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("shaman",)) def shaman_totem(var, wrapper, message): @@ -31,9 +25,7 @@ def shaman_totem(var, wrapper, message): if not target: return - totem = TOTEMS[wrapper.source] - - SHAMANS[wrapper.source] = give_totem(var, wrapper, target, prefix="You", tags=get_tags(var, totem), role="shaman", msg=" of {0}".format(totem)) + SHAMANS[wrapper.source] = give_totem(var, wrapper, target, prefix="You", role="shaman", msg=" of {0}".format(TOTEMS[wrapper.source])) @event_listener("transition_day_begin", priority=4) def on_transition_day_begin(evt, var): @@ -45,16 +37,11 @@ def on_transition_day_begin(evt, var): if shaman in LASTGIVEN: if LASTGIVEN[shaman] in ps: ps.remove(LASTGIVEN[shaman]) - levt = Event("get_random_totem_targets", {"targets": ps}) - levt.dispatch(var, shaman) - ps = levt.data["targets"] if ps: target = random.choice(ps) dispatcher = MessageDispatcher(shaman, shaman) - tags = get_tags(var, TOTEMS[shaman]) - - SHAMANS[shaman] = give_totem(var, dispatcher, target, prefix=messages["random_totem_prefix"], tags=tags, role="shaman", msg=" of {0}".format(TOTEMS[shaman])) + SHAMANS[shaman] = give_totem(var, dispatcher, target, prefix=messages["random_totem_prefix"], role="shaman", msg=" of {0}".format(TOTEMS[shaman])) else: LASTGIVEN[shaman] = None elif shaman not in SHAMANS: diff --git a/src/roles/succubus.py b/src/roles/succubus.py index 7e4de7b..b2947e9 100644 --- a/src/roles/succubus.py +++ b/src/roles/succubus.py @@ -14,7 +14,6 @@ from src.messages import messages from src.events import Event ENTRANCED = UserSet() # type: Set[users.User] -ENTRANCED_DYING = UserSet() # type: Set[users.User] VISITED = UserDict() # type: Dict[users.User, users.User] PASSED = UserSet() # type: Set[users.User] ALL_SUCC_IDLE = True @@ -32,7 +31,7 @@ def hvisit(var, wrapper, message): return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": False}) - evt.dispatch(var, "visit", wrapper.source, target, frozenset({"detrimental", "immediate"})) + evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return target = evt.data["target"] @@ -55,16 +54,6 @@ def hvisit(var, wrapper, message): revt = Event("succubus_visit", {}) revt.dispatch(var, wrapper.source, target) - # TODO: split these into hag and alpha wolf when they are split off - 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] - 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",)) @@ -85,58 +74,6 @@ def on_harlot_visit(evt, var, harlot, victim): victim.send(messages["succubus_harlot_success"].format(harlot)) ENTRANCED.add(harlot) -@event_listener("get_random_totem_targets") -def on_get_random_totem_targets(evt, var, shaman): - if shaman in ENTRANCED: - for succubus in get_all_players(("succubus",)): - if succubus in evt.data["targets"]: - evt.data["targets"].remove(succubus) - -@event_listener("chk_decision") -def on_chk_decision(evt, var, force): - for votee, voters in evt.data["votelist"].items(): - if votee in get_all_players(("succubus",)): - for vtr in ENTRANCED: - if vtr in voters: - evt.data["numvotes"][votee] -= evt.data["weights"][votee][vtr] - evt.data["weights"][votee][vtr] = 0 - -def _kill_entranced_voters(var, votelist, not_lynching, votee): - voters = set(itertools.chain(*votelist.values())) - if not get_all_players(("succubus",)) & (voters | not_lynching): - # 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 - for x in ENTRANCED: - if x.nick not in var.DEAD: - ENTRANCED_DYING.add(x) - - for other_votee, other_voters in votelist.items(): - if get_all_players(("succubus",)) & set(other_voters): - if votee is other_votee: - ENTRANCED_DYING.clear() - return - - ENTRANCED_DYING.difference_update(other_voters) - - if get_all_players(("succubus",)) & not_lynching: - if votee is None: - ENTRANCED_DYING.clear() - return - - ENTRANCED_DYING.difference_update(not_lynching) - -@event_listener("chk_decision_lynch", priority=5) -def on_chk_decision_lynch(evt, var, voters): - # a different event may override the original votee, but people voting along with succubus - # won't necessarily know that, so base whether or not they risk death on the person originally voted - _kill_entranced_voters(var, evt.params.votelist, evt.params.not_lynching, evt.params.original_votee) - -@event_listener("chk_decision_abstain") -def on_chk_decision_abstain(evt, 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) @event_listener("player_win", priority=6) def on_player_win(evt, var, user, role, winner, survived): @@ -153,15 +90,23 @@ def on_player_win(evt, var, user, role, winner, survived): def on_chk_win(evt, var, rolemap, mainroles, lpl, lwolves, lrealwolves): lsuccubi = len(rolemap.get("succubus", ())) lentranced = len([x for x in ENTRANCED if x.nick not in var.DEAD]) - if lsuccubi and var.PHASE == "day" and lpl - lsuccubi == lentranced: + if 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, actor, target): - if actor in get_all_players(("succubus",)) or target in get_all_players(("succubus",)): - evt.prevent_default = True - evt.stop_processing = True +@event_listener("exchange_roles") +def on_exchange_roles(evt, var, actor, target, actor_role, target_role): + del VISITED[:actor:] + del VISITED[:target:] + PASSED.discard(actor) + PASSED.discard(target) + + if actor in ENTRANCED: + ENTRANCED.remove(actor) + actor.send(messages["no_longer_entranced"]) + if target in ENTRANCED: + ENTRANCED.remove(target) + target.send(messages["no_longer_entranced"]) @event_listener("del_player") def on_del_player(evt, var, user, mainrole, allroles, death_triggers): @@ -173,13 +118,10 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers): if var.PHASE == "night" and var.GAMEPHASE == "night": 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 - # 2. otherwise, kill all entranced people immediately, they still remain entranced (and therefore lose) + # if all succubi idled out (every last one of them), un-entrance people # death_triggers is False for an idle-out, so we use that to determine which it is if death_triggers: ALL_SUCC_IDLE = False @@ -189,36 +131,6 @@ def on_del_player(evt, var, user, mainrole, allroles, death_triggers): while ENTRANCED: e = ENTRANCED.pop() 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 - # kill any of them off (if we killed off first, the message order would be wrong wrt death chains) - comma = "" - if var.ROLE_REVEAL in ("on", "team"): - comma = "," - for e in entranced_alive: - if var.ROLE_REVEAL in ("on", "team"): - role = get_reveal_role(e) - an = "n" if role.startswith(("a", "e", "i", "o", "u")) else "" - msg.append("\u0002{0}\u0002, a{1} \u0002{2}\u0002".format(e, an, role)) - else: - msg.append("\u0002{0}\u0002".format(e)) - if len(msg) == 1: - channels.Main.send(messages["succubus_die_kill"].format(msg[0] + comma)) - elif len(msg) == 2: - channels.Main.send(messages["succubus_die_kill"].format(msg[0] + comma + " and " + msg[1] + comma)) - else: - channels.Main.send(messages["succubus_die_kill"].format(", ".join(msg[:-1]) + ", and " + msg[-1] + comma)) - for e in entranced_alive: - # to ensure we do not double-kill someone, notify all child deaths that we'll be - # killing off everyone else that is entranced so they don't need to bother - dlc = list(evt.params.deadlist) - dlc.extend(entranced_alive - {e}) - debuglog("{0} (succubus) SUCCUBUS DEATH KILL: {1} ({2})".format(user, e, get_main_role(e))) - evt.params.del_player(e, end_game=False, killer_role="succubus", - deadlist=dlc, original=evt.params.original, ismain=False) - evt.data["pl"] = evt.params.refresh_pl(evt.data["pl"]) - ENTRANCED_DYING.clear() @event_listener("transition_day_resolve", priority=1) def on_transition_day_resolve(evt, var, victim): @@ -255,17 +167,6 @@ def on_chk_nightdone(evt, var): evt.data["actedcount"] += len(VISITED) + len(PASSED) evt.data["nightroles"].extend(get_all_players(("succubus",))) -@event_listener("targeted_command") -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 = name - actor.send(messages["no_acting_on_succubus"].format(what)) - evt.stop_processing = True - evt.prevent_default = True - @event_listener("transition_night_end", priority=2) def on_transition_night_end(evt, var): succubi = get_all_players(("succubus",)) @@ -287,17 +188,8 @@ def on_transition_night_end(evt, var): @event_listener("begin_day") 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: - 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") def on_get_special(evt, var): evt.data["win_stealers"].update(get_players(("succubus",))) @@ -318,7 +210,6 @@ def on_reset(evt, var): global ALL_SUCC_IDLE ALL_SUCC_IDLE = True ENTRANCED.clear() - ENTRANCED_DYING.clear() VISITED.clear() PASSED.clear() @@ -327,7 +218,4 @@ def on_revealroles(evt, var, wrapper): if 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(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 a53c4b9..9d621bd 100644 --- a/src/roles/vengefulghost.py +++ b/src/roles/vengefulghost.py @@ -40,7 +40,7 @@ def vg_kill(var, wrapper, message): orig = target evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": False}) - evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) + evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return target = evt.data["target"] diff --git a/src/roles/vigilante.py b/src/roles/vigilante.py index 60024f7..796f0de 100644 --- a/src/roles/vigilante.py +++ b/src/roles/vigilante.py @@ -21,7 +21,7 @@ def vigilante_kill(var, wrapper, message): orig = target evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - evt.dispatch(var, "kill", wrapper.source, target, frozenset({"detrimental"})) + evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return target = evt.data["target"] @@ -107,12 +107,6 @@ def on_transition_night_end(evt, var): to_send = "vigilante_simple" vigilante.send(messages[to_send], "Players: " + ", ".join(p.nick for p in pl), sep="\n") -@event_listener("succubus_visit") -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): KILLS.clear() diff --git a/src/roles/wolf.py b/src/roles/wolf.py index 9d41934..8630b40 100644 --- a/src/roles/wolf.py +++ b/src/roles/wolf.py @@ -74,7 +74,7 @@ def wolf_kill(cli, nick, chan, rest): target = users._get(victim) # FIXME evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - evt.dispatch(var, "kill", wolf, target, frozenset({"detrimental"})) + evt.dispatch(var, wolf, target) if evt.prevent_default: return victim = evt.data["target"].nick @@ -437,16 +437,6 @@ def on_transition_night_end(evt, var): if var.ALPHA_ENABLED and role == "alpha wolf" and wolf.nick not in var.ALPHA_WOLVES: # FIXME: Fix once var.ALPHA_WOLVES holds User instances wolf.send(messages["wolf_bite"]) -@event_listener("succubus_visit") -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): KILLS.clear() diff --git a/src/roles/wolfshaman.py b/src/roles/wolfshaman.py index 7c11866..e44654f 100644 --- a/src/roles/wolfshaman.py +++ b/src/roles/wolfshaman.py @@ -15,13 +15,7 @@ from src.events import Event from src.roles._shaman_helper import setup_variables, get_totem_target, give_totem -def get_tags(var, totem): - tags = set() - if totem in var.BENEFICIAL_TOTEMS: - tags.add("beneficial") - return tags - -TOTEMS, LASTGIVEN, SHAMANS = setup_variables("wolf shaman", knows_totem=True, get_tags=get_tags) +TOTEMS, LASTGIVEN, SHAMANS = setup_variables("wolf shaman", knows_totem=True) @command("give", "totem", chan=False, pm=True, playing=True, silenced=True, phases=("night",), roles=("wolf shaman",)) def wolf_shaman_totem(var, wrapper, message): @@ -31,9 +25,7 @@ def wolf_shaman_totem(var, wrapper, message): if not target: return - totem = TOTEMS[wrapper.source] - - SHAMANS[wrapper.source] = give_totem(var, wrapper, target, prefix="You", tags=get_tags(var, totem), role="wolf shaman", msg=" of {0}".format(totem)) + SHAMANS[wrapper.source] = give_totem(var, wrapper, target, prefix="You", role="wolf shaman", msg=" of {0}".format(TOTEMS[wrapper.source])) relay_wolfchat_command(wrapper.client, wrapper.source.nick, messages["shaman_wolfchat"].format(wrapper.source, target), ("wolf shaman",), is_wolf_command=True) @@ -47,16 +39,11 @@ def on_transition_day_begin(evt, var): if shaman in LASTGIVEN: if LASTGIVEN[shaman] in ps: ps.remove(LASTGIVEN[shaman]) - levt = Event("get_random_totem_targets", {"targets": ps}) - levt.dispatch(var, shaman) - ps = levt.data["targets"] if ps: target = random.choice(ps) dispatcher = MessageDispatcher(shaman, shaman) - tags = get_tags(var, TOTEMS[shaman]) - - SHAMANS[shaman] = give_totem(var, dispatcher, target, prefix=messages["random_totem_prefix"], tags=tags, role="wolf shaman", msg=" of {0}".format(TOTEMS[shaman])) + SHAMANS[shaman] = give_totem(var, dispatcher, target, prefix=messages["random_totem_prefix"], role="wolf shaman", msg=" of {0}".format(TOTEMS[shaman])) relay_wolfchat_command(shaman.client, shaman.nick, messages["shaman_wolfchat"].format(shaman, target), ("wolf shaman",), is_wolf_command=True) else: LASTGIVEN[shaman] = None diff --git a/src/wolfgame.py b/src/wolfgame.py index 7202433..d9df552 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -3717,9 +3717,6 @@ def check_exchange(cli, actor, nick): user = users._get(actor) # FIXME target = users._get(nick) # FIXME - event = Event("can_exchange", {}) - if not event.dispatch(var, user, target): - return False # some roles such as succubus cannot be affected by exchange totem if nick in var.EXCHANGED: var.EXCHANGED.remove(nick) actor_role = get_role(actor) @@ -3926,7 +3923,7 @@ def shoot(var, wrapper, message): # get actual victim evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) - if not evt.dispatch(var, "shoot", wrapper.source, target, frozenset({"detrimental"})): + if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] @@ -3995,12 +3992,6 @@ def shoot(var, wrapper, message): wrapper.send(messages["gunner_suicide_no_reveal"].format(wrapper.source)) del_player(wrapper.source, killer_role="villager") # blame explosion on villager's shoddy gun construction or something -def is_safe(nick, victim): # replace calls to this with targeted_command event when splitting roles - from src.roles import succubus - user = users._get(nick) # FIXME - target = users._get(victim) # FIXME - return user in succubus.ENTRANCED and target in get_all_players(("succubus",)) - @cmd("bless", chan=False, pm=True, playing=True, silenced=True, phases=("day",), roles=("priest",)) def bless(cli, nick, chan, rest): """Bless a player, preventing them from being killed for the remainder of the game.""" @@ -4083,9 +4074,6 @@ def observe(cli, nick, chan, rest): else: pm(cli, nick, messages["no_observe_wolf"]) return - if is_safe(nick, victim): - pm(cli, nick, messages["no_acting_on_succubus"].format("observe")) - return victim = choose_target(nick, victim) if check_exchange(cli, nick, victim): return @@ -4263,9 +4251,6 @@ def bite_cmd(cli, nick, chan, rest): if not victim: pm(cli, nick, messages["bite_error"]) return - if is_safe(nick, victim): - pm(cli, nick, messages["no_acting_on_succubus"].format("bite")) - return vrole = get_role(victim) actual = choose_target(nick, victim) @@ -4351,10 +4336,6 @@ def hex_target(cli, nick, chan, rest): pm(cli, nick, messages["no_multiple_hex"].format(victim)) return - if is_safe(nick, victim): - pm(cli, nick, messages["no_acting_on_succubus"].format("hex")) - return - victim = choose_target(nick, victim) if in_wolflist(nick, victim): pm(cli, nick, messages["no_hex_wolf"]) @@ -4386,10 +4367,6 @@ def curse(cli, nick, chan, rest): victim = get_victim(cli, nick, re.split(" +",rest)[0], False) if not victim: return - if is_safe(nick, victim): - pm(cli, nick, messages["no_acting_on_succubus"].format("curse")) - return - # There may actually be valid strategy in cursing other wolfteam members, # but for now it is not allowed. If someone seems suspicious and shows as # villager across multiple nights, safes can use that as a tell that the @@ -4461,7 +4438,7 @@ def clone(cli, nick, chan, rest): var.ROLE_COMMAND_EXCEPTIONS.add("clone") @event_listener("targeted_command", priority=9) -def on_targeted_command(evt, var, name, actor, orig_target, tags): +def on_targeted_command(evt, var, actor, orig_target): if evt.data["misdirection"]: evt.data["target"] = users._get(choose_target(actor.nick, evt.data["target"].nick)) # FIXME