def on_del_player(evt, var, player, all_roles, death_triggers): if not death_triggers or "mad scientist" not in all_roles: return target1, target2 = _get_targets(var, get_players(), player) prots1 = try_protection(var, target1, player, "mad scientist", "mad_scientist_fail") prots2 = try_protection(var, target2, player, "mad scientist", "mad_scientist_fail") if prots1: channels.Main.send(*prots1) if prots2: channels.Main.send(*prots2) kill1 = prots1 is None and add_dying(var, target1, killer_role="mad scientist", reason="mad_scientist") kill2 = prots2 is None and target1 is not target2 and add_dying(var, target2, killer_role="mad scientist", reason="mad_scientist") if kill1: if kill2: if var.ROLE_REVEAL in ("on", "team"): r1 = get_reveal_role(target1) an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else "" r2 = get_reveal_role(target2) an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else "" tmsg = messages["mad_scientist_kill"].format(player, target1, an1, r1, target2, an2, r2) else: tmsg = messages["mad_scientist_kill_no_reveal"].format(player, target1, target2) channels.Main.send(tmsg) debuglog(player.nick, "(mad scientist) KILL: {0} ({1}) - {2} ({3})".format(target1, get_main_role(target1), target2, get_main_role(target2))) else: if var.ROLE_REVEAL in ("on", "team"): r1 = get_reveal_role(target1) an1 = "n" if r1.startswith(("a", "e", "i", "o", "u")) else "" tmsg = messages["mad_scientist_kill_single"].format(player, target1, an1, r1) else: tmsg = messages["mad_scientist_kill_single_no_reveal"].format(player, target1) channels.Main.send(tmsg) debuglog(player.nick, "(mad scientist) KILL: {0} ({1})".format(target1, get_main_role(target1))) else: if kill2: if var.ROLE_REVEAL in ("on", "team"): r2 = get_reveal_role(target2) an2 = "n" if r2.startswith(("a", "e", "i", "o", "u")) else "" tmsg = messages["mad_scientist_kill_single"].format(player, target2, an2, r2) else: tmsg = messages["mad_scientist_kill_single_no_reveal"].format(player, target2) channels.Main.send(tmsg) debuglog(player.nick, "(mad scientist) KILL: {0} ({1})".format(target2, get_main_role(target2))) else: tmsg = messages["mad_scientist_fail"].format(player) channels.Main.send(tmsg) debuglog(player.nick, "(mad scientist) KILL FAIL")
def hex_cmd(var, wrapper, message): """Hex someone, preventing them from acting the next day and night.""" if wrapper.source in HEXED: wrapper.pm(messages["already_hexed"]) return target = get_target(var, wrapper, re.split(" +", message)[0]) if not target: return if LASTHEXED.get(wrapper.source) is target: wrapper.pm(messages["no_multiple_hex"].format(target)) return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return if is_known_wolf_ally(var, wrapper.source, target): wrapper.pm(messages["no_hex_wolf"]) return HEXED[wrapper.source] = target wrapper.pm(messages["hex_success"].format(target)) send_wolfchat_message(var, wrapper.source, messages["hex_success_wolfchat"].format(wrapper.source, target), {"hag"}, role="hag", command="hex") debuglog("{0} (hag) HEX: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def immunize(var, wrapper, message): """Immunize a player, preventing them from turning into a wolf.""" if not DOCTORS[wrapper.source]: wrapper.pm(messages["doctor_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], allow_self=True) if not target: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return doctor_evt = Event("doctor_immunize", {"message": "villager_immunized"}) doctor_evt.dispatch(var, wrapper.source, target) wrapper.pm(messages["doctor_success"].format(target)) target.send(messages["immunization_success"].format(messages[doctor_evt.data["message"]])) IMMUNIZED.add(target) DOCTORS[wrapper.source] -= 1 remove_lycanthropy(var, target) remove_disease(var, target) debuglog("{0} (doctor) IMMUNIZE: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def hvisit(var, wrapper, message): """Entrance a player, converting them to your team.""" if VISITED.get(wrapper.source): wrapper.send(messages["succubus_already_visited"].format(VISITED[wrapper.source])) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="succubus_not_self") if not target: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return 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: 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: target.send(messages["harlot_success"].format(wrapper.source)) revt = Event("succubus_visit", {}) revt.dispatch(var, wrapper.source, target) debuglog("{0} (succubus) VISIT: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def guard(var, wrapper, message): """Guard a player, preventing them from being killed that night.""" if wrapper.source in GUARDED: wrapper.pm(messages["already_protecting"]) return target = get_target(var, wrapper, re.split(" +", message)[0], allow_self=var.GUARDIAN_ANGEL_CAN_GUARD_SELF, not_self_message="cannot_guard_self") if not target: return if LASTGUARDED.get(wrapper.source) is target: wrapper.pm(messages["guardian_target_another"].format(target)) return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return add_protection(var, target, wrapper.source, "guardian angel") GUARDED[wrapper.source] = target LASTGUARDED[wrapper.source] = target if wrapper.source is target: wrapper.pm(messages["guardian_guard_self"]) else: wrapper.pm(messages["protecting_target"].format(target)) target.send(messages["target_protected"]) debuglog("{0} (guardian angel) GUARD: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return targrole = get_main_role(target) trole = targrole # keep a copy for logging evt = Event("investigate", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] aura = "blue" if targrole in Wolfteam: aura = "red" elif targrole in Neutral: aura = "grey" wrapper.send(messages["augur_success"].format(target, aura)) debuglog("{0} (augur) SEE: {1} ({2}) as {3} ({4} aura)".format(wrapper.source, target, trole, targrole, aura)) SEEN.add(wrapper.source)
def on_transition_day_resolve_end(evt, var, victims): evt2 = Event("get_role_metadata", {}) evt2.dispatch(var, "lycanthropy_role") for victim in victims: if victim in LYCANTHROPES and evt.data["killers"][victim] == ["@wolves"] and victim in evt.data["dead"]: vrole = get_main_role(victim) if vrole not in Wolf: new_role = "wolf" prefix = LYCANTHROPES[victim] if vrole in evt2.data: if "role" in evt2.data[vrole]: new_role = evt2.data[vrole]["role"] if "prefix" in evt2.data[vrole]: prefix = evt2.data[vrole]["prefix"] for sec_role in evt2.data[vrole].get("secondary_roles", ()): var.ROLES[sec_role].add(victim) to_send = "{0}_{1}".format(sec_role.replace(" ", "_"), "simple" if victim.prefers_simple() else "notify") victim.send(messages[to_send]) # FIXME: Not every role has proper message keys, such as shamans change_role(var, victim, vrole, new_role, message=prefix + "_turn") evt.data["howl"] += 1 evt.data["novictmsg"] = False evt.data["dead"].remove(victim) evt.data["killers"][victim].remove("@wolves") del evt.data["message"][victim] debuglog("{0} ({1}) TURN {2}".format(victim, vrole, new_role))
def see(var, wrapper, message): """Use your paranormal senses to determine a player's doom.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if not target: return if is_known_wolf_ally(var, wrapper.source, target): wrapper.send(messages["no_see_wolf"]) return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return targrole = get_main_role(target) mode, mapping = random.choice(_mappings) wrapper.send(messages["doomsayer_{0}".format(mode)].format(target)) mapping[wrapper.source] = target debuglog("{0} (doomsayer) SEE: {1} ({2}) - {3}".format(wrapper.source, target, targrole, mode.upper())) relay_wolfchat_command(wrapper.client, wrapper.source.nick, messages["doomsayer_wolfchat"].format(wrapper.source, target), ("doomsayer",), is_wolf_command=True) SEEN.add(wrapper.source)
def on_player_win(evt, var, player, role, winner, survived): from src.roles.fool import VOTED if player in LOVERS: evt.data["special"].append("lover") if winner == "lovers" and player in LOVERS: evt.data["iwon"] = True elif player in LOVERS and survived and LOVERS[player].intersection(get_players()): for lvr in LOVERS[player]: if lvr not in get_players(): # cannot win with dead lover (lover idled out) continue lover_role = get_main_role(lvr) if singular(winner) not in Win_Stealer: evt.data["iwon"] = True break elif winner == "fool": if lvr is VOTED: evt.data["iwon"] = True break elif singular(winner) in Win_Stealer and lover_role == singular(winner): evt.data["iwon"] = True break
def hvisit(var, wrapper, message): """Visit a player. You will die if you visit a wolf or a target of the wolves.""" if VISITED.get(wrapper.source): wrapper.pm(messages["harlot_already_visited"].format(VISITED[wrapper.source])) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="harlot_not_self") if not target: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return vrole = get_main_role(target) VISITED[wrapper.source] = target PASSED.discard(wrapper.source) wrapper.pm(messages["harlot_success"].format(target)) if target is not wrapper.source: target.send(messages["harlot_success"].format(wrapper.source)) revt = Event("harlot_visit", {}) revt.dispatch(var, wrapper.source, target) debuglog("{0} (harlot) VISIT: {1} ({2})".format(wrapper.source, target, vrole))
def curse(var, wrapper, message): target = get_target(var, wrapper, re.split(" +", message)[0]) if not target: return if target in get_all_players(("cursed villager",)): wrapper.pm(messages["target_already_cursed"].format(target)) 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 # person is likely wolf-aligned. if is_known_wolf_ally(var, wrapper.source, target): wrapper.pm(messages["no_curse_wolf"]) return orig = target target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return CURSED[wrapper.source] = target PASSED.discard(wrapper.source) wrapper.pm(messages["curse_success"].format(orig)) send_wolfchat_message(var, wrapper.source, messages["curse_success_wolfchat"].format(wrapper.source, orig), {"warlock"}, role="warlock", command="curse") debuglog("{0} (warlock) CURSE: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def observe(var, wrapper, message): """Observe a player to obtain various information.""" target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_observe_self") if not target: return if wrapper.source in OBSERVED: wrapper.pm(messages["already_observed"]) return if is_known_wolf_ally(var, wrapper.source, target): wrapper.pm(messages["no_observe_wolf"]) return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return OBSERVED.add(wrapper.source) targrole = get_main_role(target) if targrole == "amnesiac": from src.roles.amnesiac import ROLES as amn_roles targrole = amn_roles[target] an = "" key = "sorcerer_fail" if targrole in Spy: if targrole.startswith(("a", "e", "i", "o", "u")): an = "n" key = "sorcerer_success" wrapper.pm(messages[key].format(target, an, targrole)) send_wolfchat_message(var, wrapper.source, messages["sorcerer_success_wolfchat"].format(wrapper.source, target), {"sorcerer"}, role="sorcerer", command="observe") debuglog("{0} (sorcerer) OBSERVE: {1} ({2})".format(wrapper.source, target, targrole))
def on_begin_day(evt, var): wroles = get_wolfchat_roles(var) for warlock, target in CURSED.items(): if get_main_role(target) not in wroles: var.ROLES["cursed villager"].add(target) CURSED.clear() PASSED.clear()
def on_new_role(evt, var, player, old_role): wcroles = get_wolfchat_roles(var) if old_role is None: # initial role assignment; don't do all the logic below about notifying other wolves and such if evt.data["role"] in wcroles: evt.data["in_wolfchat"] = True return sayrole = evt.data["role"] if sayrole in Hidden: sayrole = var.HIDDEN_ROLE an = "n" if sayrole.startswith(("a", "e", "i", "o", "u")) else "" if player in KILLS: del KILLS[player] if old_role not in wcroles and evt.data["role"] in wcroles: # a new wofl has joined the party, give them tummy rubs and the wolf list # and let the other wolves know to break out the confetti and villager steaks wofls = get_players(wcroles) evt.data["in_wolfchat"] = True if wofls: new_wolves = [] for wofl in wofls: wofl.queue_message(messages["wolfchat_new_member"].format(player, an, sayrole)) wofl.send_messages() else: return # no other wolves, nothing else to do pl = get_players() if player in pl: pl.remove(player) random.shuffle(pl) pt = [] wevt = Event("wolflist", {"tags": set()}) for p in pl: prole = get_main_role(p) wevt.data["tags"].clear() wevt.dispatch(var, p, player) tags = " ".join(wevt.data["tags"]) if prole in wcroles: if tags: tags += " " pt.append("\u0002{0}\u0002 ({1}{2})".format(p, tags, prole)) elif tags: pt.append("{0} ({1})".format(p, tags)) else: pt.append(p.nick) evt.data["messages"].append(messages["players_list"].format(", ".join(pt))) if var.PHASE == "night" and evt.data["role"] in Wolf & Killer: # inform the new wolf that they can kill and stuff nevt = Event("wolf_numkills", {"numkills": 1, "message": ""}) nevt.dispatch(var) if not nevt.data["numkills"] and nevt.data["message"]: evt.data["messages"].append(messages[nevt.data["message"]])
def on_transition_day(evt, var): for vigilante, target in list(KILLS.items()): evt.data["victims"].append(target) evt.data["killers"][target].append(vigilante) # important, otherwise our del_player listener lets hunter kill again del KILLS[vigilante] if get_main_role(target) not in Wolf | Win_Stealer: add_dying(var, vigilante, "vigilante", "night_kill")
def on_del_player(evt, var, player, all_roles, death_triggers): del IDOLS[:player:] if not death_triggers: return for child in get_all_players(("wild child",)): if IDOLS.get(child) is player: # Change their main role to wolf change_role(var, child, get_main_role(child), "wolf", message="wild_child_idol_died") var.ROLES["wild child"].add(child)
def try_exchange(var, actor, target): """Check if an exchange is happening. Return True if the exchange occurs.""" if actor is target or target not in EXCHANGE: return False EXCHANGE.remove(target) role = get_main_role(actor) target_role = get_main_role(target) actor_role = change_role(var, actor, role, target_role, inherit_from=target) target_role = change_role(var, target, target_role, role, inherit_from=actor) if actor_role == target_role: # swap state of two players with the same role evt = Event("swap_role_state", {"actor_messages": [], "target_messages": []}) evt.dispatch(var, actor, target, actor_role) actor.send(*evt.data["actor_messages"]) target.send(*evt.data["target_messages"]) return True
def on_transition_day_begin(evt, var): if not var.START_WITH_DAY or not var.FIRST_DAY: for child in get_all_players(("wild child",)): if child not in IDOLS: players = get_players() players.remove(child) if players: idol = random.choice(players) IDOLS[child] = idol child.send(messages["wild_child_random_idol"].format(idol)) idol_role = get_main_role(idol) debuglog("{0} (wild child) IDOLIZE RANDOM: {1} ({2})".format(child, idol, idol_role))
def choose_idol(var, wrapper, message): """Pick your idol, if they die, you'll become a wolf!""" if wrapper.source in IDOLS: wrapper.pm(messages["wild_child_already_picked"]) return idol = get_target(var, wrapper, re.split(" +", message)[0]) if not idol: return IDOLS[wrapper.source] = idol wrapper.send(messages["wild_child_success"].format(idol)) debuglog("{0} (wild child) IDOLIZE: {1} ({2})".format(wrapper.source, idol, get_main_role(idol)))
def vigilante_kill(var, wrapper, message): """Kill someone at night, but you die too if they aren't a wolf or win stealer!""" target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_suicide") orig = target target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return KILLS[wrapper.source] = target PASSED.discard(wrapper.source) wrapper.send(messages["player_kill"].format(orig)) debuglog("{0} (vigilante) KILL: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def choose_idol(var, wrapper, message): """Pick your idol, if they die, you'll become a wolf!""" if not var.FIRST_NIGHT: return if wrapper.source in IDOLS: wrapper.pm(messages["wild_child_already_picked"]) return idol = get_target(var, wrapper, re.split(" +", message)[0]) if not idol: return IDOLS[wrapper.source] = idol wrapper.send(messages["wild_child_success"].format(idol)) debuglog("{0} (wild child) IDOLIZE: {1} ({2})".format(wrapper.source, idol, get_main_role(idol)))
def on_del_player(evt, var, player, all_roles, death_triggers): MATCHMAKERS.discard(player) if death_triggers and player in LOVERS: lovers = set(LOVERS[player]) for lover in lovers: if lover not in get_players(): continue # already died somehow if var.ROLE_REVEAL in ("on", "team"): role = get_reveal_role(lover) an = "n" if role.startswith(("a", "e", "i", "o", "u")) else "" message = messages["lover_suicide"].format(lover, an, role) else: message = messages["lover_suicide_no_reveal"].format(lover) channels.Main.send(message) debuglog("{0} ({1}) LOVE SUICIDE: {2} ({3})".format(lover, get_main_role(lover), player, evt.params.main_role)) add_dying(var, lover, killer_role=evt.params.killer_role, reason="lover_suicide")
def on_del_player(evt, var, player, mainrole, allroles, death_triggers): if death_triggers and player in LOVERS: lovers = set(LOVERS[player]) for lover in lovers: if lover not in evt.data["pl"]: continue # already died somehow if var.ROLE_REVEAL in ("on", "team"): role = get_reveal_role(lover) an = "n" if role.startswith(("a", "e", "i", "o", "u")) else "" message = messages["lover_suicide"].format(lover, an, role) else: message = messages["lover_suicide_no_reveal"].format(lover) channels.Main.send(message) debuglog("{0} ({1}) LOVE SUICIDE: {2} ({3})".format(lover, get_main_role(lover), player, mainrole)) evt.params.del_player(lover, end_game=False, killer_role=evt.params.killer_role, deadlist=evt.params.deadlist, original=evt.params.original, ismain=False) evt.data["pl"] = evt.params.refresh_pl(evt.data["pl"])
def on_del_player(evt, var, player, all_roles, death_triggers): del IDOLS[:player:] CAN_ACT.discard(player) ACTED.discard(player) if not death_triggers: return for child in get_all_players(("wild child", )): if IDOLS.get(child) is player: # Change their main role to wolf change_role(var, child, get_main_role(child), "wolf", message="wild_child_idol_died") var.ROLES["wild child"].add(child)
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return evt = Event("targeted_command", { "target": target, "misdirection": True, "exchange": True }) if not evt.dispatch(var, "see", wrapper.source, target, frozenset({"info", "immediate"})): return target = evt.data["target"] targrole = get_main_role(target) trole = targrole # keep a copy for logging if targrole in var.SEEN_WOLF and targrole not in var.SEEN_DEFAULT: targrole = "wolf" elif targrole in var.SEEN_DEFAULT: targrole = var.DEFAULT_ROLE if var.DEFAULT_SEEN_AS_VILL: targrole = "villager" evt = Event("see", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] iswolf = False if targrole in var.SEEN_WOLF and targrole not in var.SEEN_DEFAULT: iswolf = True wrapper.send(messages["oracle_success"].format( target, "" if iswolf else "\u0002not\u0002 ", "\u0002" if iswolf else "")) debuglog("{0} (oracle) SEE: {1} ({2}) (Wolf: {3})".format( wrapper.source, target, trole, str(iswolf))) SEEN.add(wrapper.source)
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return targrole = get_main_role(target) trole = targrole # keep a copy for logging for i in range(2): # need to go through loop twice iswolf = False if targrole in Cursed: targrole = "wolf" iswolf = True elif targrole in Safe | Innocent: targrole = var.HIDDEN_ROLE elif targrole in Wolf: targrole = "wolf" iswolf = True else: targrole = var.HIDDEN_ROLE if i: break evt = Event("see", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] wrapper.send(messages["oracle_success"].format( target, "" if iswolf else "\u0002not\u0002 ", "\u0002" if iswolf else "")) debuglog("{0} (oracle) SEE: {1} ({2}) (Wolf: {3})".format( wrapper.source, target, trole, str(iswolf))) SEEN.add(wrapper.source)
def clone(var, wrapper, message): """Clone another player. You will turn into their role if they die.""" if wrapper.source in CLONED: wrapper.pm(messages["already_cloned"]) return params = re.split(" +", message) target = get_target(var, wrapper, params[0]) if target is None: return CLONED[wrapper.source] = target ACTED.add(wrapper.source) wrapper.pm(messages["clone_target_success"].format(target)) debuglog("{0} (clone) CLONE: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def kill_players(var, *, end_game: bool = True) -> bool: """ Kill all players marked as dying. This function is not re-entrant; do not call it inside of a del_player or kill_players event listener. This function does not print anything to the channel; code which calls add_dying should print things as appropriate. :param var: The game state :param end_game: Whether or not to check for win conditions and perform state transitions (temporary) :returns: True if the game is ending (temporary) """ t = time.time() with var.GRAVEYARD_LOCK: # FIXME if not var.GAME_ID or var.GAME_ID > t: # either game ended, or a new game has started return dead = set() while DYING: player, (killer_role, reason, death_triggers) = DYING.popitem() main_role = get_main_role(player) reveal_role = get_reveal_role(player) all_roles = get_all_roles(player) # kill them off del var.MAIN_ROLES[player] for role in all_roles: var.ROLES[role].remove(player) dead.add(player) var.DEAD.add(player) # notify listeners that the player died for possibility of chained deaths evt = Event("del_player", {}, killer_role=killer_role, main_role=main_role, reveal_role=reveal_role, reason=reason) evt_death_triggers = death_triggers and var.PHASE in var.GAME_PHASES evt.dispatch(var, player, all_roles, evt_death_triggers) # notify listeners that all deaths have resolved # FIXME: end_game is a temporary hack until we move state transitions into the event loop # (priority 10 listener sets prevent_default if end_game=True and game is ending; that's another temporary hack) # Once hacks are removed, this function will not have any return value and the end_game kwarg will go away evt = Event("kill_players", {}, end_game=end_game) return not evt.dispatch(var, dead)
def on_del_player(evt, var, user, mainrole, allroles, death_triggers): if var.PHASE not in var.GAME_PHASES: return for child in get_all_players(("wild child", )): if child in evt.params.deadlist or IDOLS.get( child) not in evt.params.deadlist: continue # Change their main role to wolf WILD_CHILDREN.add(child) change_role(var, child, get_main_role(child), "wolf", message="wild_child_idol_died") var.ROLES["wild child"].discard(child)
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return evt = Event("targeted_command", { "target": target, "misdirection": True, "exchange": True }) if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] targrole = get_main_role(target) trole = targrole # keep a copy for logging if targrole in Cursed: targrole = "wolf" elif targrole in Safe: pass # Keep the same role elif targrole in Innocent: targrole = var.HIDDEN_ROLE elif targrole in Wolf: targrole = "wolf" else: targrole = var.HIDDEN_ROLE evt = Event("see", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] wrapper.send(messages["seer_success"].format(target, targrole)) debuglog("{0} (seer) SEE: {1} ({2}) as {3}".format(wrapper.source, target, trole, targrole)) SEEN.add(wrapper.source)
def on_transition_night_end(evt, var): wolves = get_players(Wolfchat) # roles allowed to talk in wolfchat talkroles = get_talking_roles(var) # condition imposed on talking in wolfchat (only during day/night, or no talking) # 0 = no talking # 1 = normal # 2 = only during day # 3 = only during night wccond = 1 if var.RESTRICT_WOLFCHAT & var.RW_DISABLE_NIGHT: if var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: wccond = 0 else: wccond = 2 elif var.RESTRICT_WOLFCHAT & var.RW_DISABLE_DAY: wccond = 3 cursed = get_all_players(("cursed villager", )) for wolf in wolves: role = get_main_role(wolf) msg = "{0}_notify".format(role.replace( " ", "_")) # FIXME: Split into each role file wolf.send(messages[msg]) if len(wolves) > 1 and role in talkroles: wolf.send(messages["wolfchat_notify_{0}".format(wccond)]) if wolf in cursed: wolf.send(messages["cursed_notify"]) if wolf not in KNOWS_MINIONS: minions = len(get_all_players(("minion", ))) if minions > 0: wolf.send(messages["has_minions"].format(minions)) KNOWS_MINIONS.add(wolf) wolf.send(messages["players_list"].format(get_wolflist(var, wolf))) nevt = Event("wolf_numkills", {"numkills": 1, "message": ""}) nevt.dispatch(var) if role in Wolf & Killer and not nevt.data["numkills"] and nevt.data[ "message"]: wolf.send(messages[nevt.data["message"]])
def vigilante_kill(var, wrapper, message): """Kill someone at night, but you die too if they aren't a wolf or win stealer!""" target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_suicide") orig = target 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 = evt.data["target"] KILLS[wrapper.source] = target PASSED.discard(wrapper.source) wrapper.send(messages["player_kill"].format(orig)) debuglog("{0} (vigilante) KILL: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def hvisit(var, wrapper, message): """Entrance a player, converting them to your team.""" if VISITED.get(wrapper.source): wrapper.send(messages["succubus_already_visited"].format( VISITED[wrapper.source])) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="succubus_not_self") if not target: return evt = Event("targeted_command", { "target": target, "misdirection": True, "exchange": True }) if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] 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: 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: target.send(messages["harlot_success"].format(wrapper.source)) revt = Event("succubus_visit", {}) revt.dispatch(var, wrapper.source, target) debuglog("{0} (succubus) VISIT: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def on_transition_night_end(evt, var): max_totems = defaultdict(int) ps = get_players() shamans = list_players(var.TOTEM_ORDER) # FIXME: Need to convert alongside the entire role for ix in range(len(var.TOTEM_ORDER)): for c in var.TOTEM_CHANCES.values(): max_totems[var.TOTEM_ORDER[ix]] += c[ix] for s in list(LASTGIVEN.keys()): if s not in shamans: del LASTGIVEN[s] for shaman in get_players(var.TOTEM_ORDER): pl = ps[:] random.shuffle(pl) if LASTGIVEN.get(shaman.nick): user = users._get(LASTGIVEN[shaman.nick]) # FIXME if user in pl: pl.remove(user) role = get_main_role(shaman) # FIXME: don't use get_main_role here once split into one file per role indx = var.TOTEM_ORDER.index(role) target = 0 rand = random.random() * max_totems[var.TOTEM_ORDER[indx]] for t in var.TOTEM_CHANCES.keys(): target += var.TOTEM_CHANCES[t][indx] if rand <= target: TOTEMS[shaman.nick] = t # FIXME: Fix once shaman is converted break if shaman.prefers_simple(): if role not in var.WOLFCHAT_ROLES: shaman.send(messages["shaman_simple"].format(role)) if role != "crazed shaman": shaman.send(messages["totem_simple"].format(TOTEMS[shaman.nick])) # FIXME else: if role not in var.WOLFCHAT_ROLES: shaman.send(messages["shaman_notify"].format(role, "random " if shaman.nick in var.ROLES["crazed shaman"] else "")) # FIXME if role != "crazed shaman": totem = TOTEMS[shaman.nick] # FIXME tmsg = messages["shaman_totem"].format(totem) try: tmsg += messages[totem + "_totem"] except KeyError: tmsg += messages["generic_bug_totem"] shaman.send(tmsg) if role not in var.WOLFCHAT_ROLES: shaman.send("Players: " + ", ".join(p.nick for p in pl))
def observe(var, wrapper, message): """Observe a player to obtain various information.""" target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_observe_self") if not target: return if wrapper.source in OBSERVED: wrapper.pm(messages["already_observed"]) return if is_known_wolf_ally(var, wrapper.source, target): wrapper.pm(messages["no_observe_wolf"]) return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return OBSERVED.add(wrapper.source) targrole = get_main_role(target) if targrole == "amnesiac": from src.roles.amnesiac import ROLES as amn_roles targrole = amn_roles[target] an = "" key = "sorcerer_fail" if targrole in Spy: if targrole.startswith(("a", "e", "i", "o", "u")): an = "n" key = "sorcerer_success" wrapper.pm(messages[key].format(target, an, targrole)) send_wolfchat_message(var, wrapper.source, messages["sorcerer_success_wolfchat"].format( wrapper.source, target), {"sorcerer"}, role="sorcerer", command="observe") debuglog("{0} (sorcerer) OBSERVE: {1} ({2})".format( wrapper.source, target, targrole))
def on_del_player(evt, var, player, all_roles, death_triggers): MATCHMAKERS.discard(player) ACTED.discard(player) if death_triggers and player in LOVERS: lovers = set(LOVERS[player]) for lover in lovers: if lover not in get_players(): continue # already died somehow to_send = "lover_suicide_no_reveal" if var.ROLE_REVEAL in ("on", "team"): to_send = "lover_suicide" channels.Main.send(messages[to_send].format( lover, get_reveal_role(lover))) debuglog("{0} ({1}) LOVE SUICIDE: {2} ({3})".format( lover, get_main_role(lover), player, evt.params.main_role)) add_dying(var, lover, killer_role=evt.params.killer_role, reason="lover_suicide")
def bless(var, wrapper, message): """Bless a player, preventing them from being killed for the remainder of the game.""" if wrapper.source in PRIESTS: wrapper.pm(messages["already_blessed"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_bless_self") if not target: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return PRIESTS.add(wrapper.source) var.ROLES["blessed villager"].add(target) wrapper.pm(messages["blessed_success"].format(target)) target.send(messages["blessed_notify_target"]) debuglog("{0} (priest) BLESS: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def bless(var, wrapper, message): """Bless a player, preventing them from being killed for the remainder of the game.""" if wrapper.source in PRIESTS: wrapper.pm(messages["already_blessed"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_bless_self") if not target: return evt = Event("targeted_command", {"target": target, "exchange": True, "misdirection": True}) if not evt.dispatch(var, wrapper.source, target): return PRIESTS.add(wrapper.source) var.ROLES["blessed villager"].add(target) wrapper.pm(messages["blessed_success"].format(target)) target.send(messages["blessed_notify_target"]) debuglog("{0} (priest) BLESS: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def on_transition_day_resolve6(evt, var, victims): for victim in victims: if victim in RETRIBUTION: killers = list(evt.data["killers"].get(victim, [])) loser = None while killers: loser = random.choice(killers) if loser in evt.data["dead"] or victim is loser: killers.remove(loser) continue break if loser in evt.data["dead"] or victim is loser: loser = None ret_evt = Event("retribution_kill", { "target": loser, "message": [] }) ret_evt.dispatch(var, victim, loser) loser = ret_evt.data["target"] evt.data["message"][loser].extend(ret_evt.data["message"]) if loser in evt.data["dead"] or victim is loser: loser = None if loser is not None: protected = try_protection(var, loser, victim, get_main_role(victim), "retribution_totem") if protected is not None: channels.Main.send(*protected) return evt.data["dead"].append(loser) if var.ROLE_REVEAL in ("on", "team"): role = get_reveal_role(loser) an = "n" if role.startswith( ("a", "e", "i", "o", "u")) else "" evt.data["message"][loser].append( messages["totem_death"].format(victim, loser, an, role)) else: evt.data["message"][loser].append( messages["totem_death_no_reveal"].format( victim, loser))
def see(var, wrapper, message): """Use your paranormal senses to determine a player's doom.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if not target: return if is_known_wolf_ally(wrapper.source, target): wrapper.send(messages["no_see_wolf"]) return evt = Event("targeted_command", { "target": target, "misdirection": True, "exchange": True }) evt.dispatch(var, wrapper.source, target) if evt.prevent_default: return target = evt.data["target"] targrole = get_main_role(target) mode, mapping = random.choice(_mappings) wrapper.send(messages["doomsayer_{0}".format(mode)].format(target)) if mode != "sick" or wrapper.source.nick not in var.IMMUNIZED: mapping[wrapper.source] = target debuglog("{0} (doomsayer) SEE: {1} ({2}) - {3}".format( wrapper.source, target, targrole, mode.upper())) relay_wolfchat_command(wrapper.client, wrapper.source.nick, messages["doomsayer_wolfchat"].format( wrapper.source, target), ("doomsayer", ), is_wolf_command=True) SEEN.add(wrapper.source)
def on_del_player(evt, var, player, all_roles, death_triggers): MATCHMAKERS.discard(player) if death_triggers and player in LOVERS: lovers = set(LOVERS[player]) for lover in lovers: if lover not in get_players(): continue # already died somehow if var.ROLE_REVEAL in ("on", "team"): role = get_reveal_role(lover) an = "n" if role.startswith(("a", "e", "i", "o", "u")) else "" message = messages["lover_suicide"].format(lover, an, role) else: message = messages["lover_suicide_no_reveal"].format(lover) channels.Main.send(message) debuglog("{0} ({1}) LOVE SUICIDE: {2} ({3})".format( lover, get_main_role(lover), player, evt.params.main_role)) add_dying(var, lover, killer_role=evt.params.killer_role, reason="lover_suicide")
def target(var, wrapper, message): """Pick a player as your target, killing them if you die.""" if wrapper.source in PREV_ACTED: wrapper.send(messages["assassin_already_targeted"]) return target = get_target(var, wrapper, re.split(" +", message)[0]) if not target: return orig = target target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return TARGETED[wrapper.source] = target wrapper.send(messages["assassin_target_success"].format(orig)) debuglog("{0} (assassin) TARGET: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def dullahan_kill(var, wrapper, message): """Kill someone at night as a dullahan until everyone on your list is dead.""" if not TARGETS[wrapper.source] & set(get_players()): wrapper.pm(messages["dullahan_targets_dead"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_suicide") if not target: return orig = target target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return KILLS[wrapper.source] = target wrapper.pm(messages["player_kill"].format(orig)) debuglog("{0} (dullahan) KILL: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def target(var, wrapper, message): """Pick a player as your target, killing them if you die.""" if wrapper.source in PREV_ACTED: wrapper.send(messages["assassin_already_targeted"]) return target = get_target(var, wrapper, re.split(" +", message)[0]) if not target: return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] TARGETED[wrapper.source] = target wrapper.send(messages["assassin_target_success"].format(target)) debuglog("{0} (assassin) TARGET: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def see(var, wrapper, message): """Use your paranormal senses to determine a player's doom.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if not target: return if is_known_wolf_ally(var, wrapper.source, target): wrapper.send(messages["no_see_wolf"]) return if LASTSEEN.get(wrapper.source) is target: wrapper.send(messages["no_see_same"]) return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return targrole = get_main_role(target) mode, mapping = random.choice(_mappings) wrapper.send(messages["doomsayer_{0}".format(mode)].format(target)) mapping[wrapper.source] = target debuglog("{0} (doomsayer) SEE: {1} ({2}) - {3}".format( wrapper.source, target, targrole, mode.upper())) send_wolfchat_message(var, wrapper.source, messages["doomsayer_wolfchat"].format( wrapper.source, target), ("doomsayer", ), role="doomsayer", command="see") SEEN.add(wrapper.source) LASTSEEN[wrapper.source] = target
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return targrole = get_main_role(target) trole = targrole # keep a copy for logging for i in range(2): # need to go through loop twice iswolf = False if targrole in Cursed: targrole = "wolf" iswolf = True elif targrole in Safe | Innocent: targrole = var.HIDDEN_ROLE elif targrole in Wolf: targrole = "wolf" iswolf = True else: targrole = var.HIDDEN_ROLE if i: break evt = Event("see", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] wrapper.send(messages["oracle_success"].format(target, "" if iswolf else "\u0002not\u0002 ", "\u0002" if iswolf else "")) debuglog("{0} (oracle) SEE: {1} ({2}) (Wolf: {3})".format(wrapper.source, target, trole, str(iswolf))) SEEN.add(wrapper.source)
def investigate(var, wrapper, message): """Investigate a player to determine their exact role.""" if wrapper.source in INVESTIGATED: wrapper.send(messages["already_investigated"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_investigate_self") if target is None: return evt = Event("targeted_command", {"target": target, "misdirection": True, "exchange": True}) if not evt.dispatch(var, "identify", wrapper.source, target, frozenset({"info", "immediate"})): return target = evt.data["target"] targrole = get_main_role(target) evt = Event("investigate", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] INVESTIGATED.add(wrapper.source) wrapper.send(messages["investigate_success"].format(target, targrole)) debuglog("{0} (detective) ID: {1} ({2})".format(wrapper.source, target, targrole)) if random.random() < var.DETECTIVE_REVEALED_CHANCE: # a 2/5 chance (should be changeable in settings) # The detective's identity is compromised! wcroles = var.WOLFCHAT_ROLES if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: wcroles = var.WOLF_ROLES else: wcroles = var.WOLF_ROLES | {"traitor"} wolves = get_all_players(wcroles) if wolves: for wolf in wolves: wolf.queue_message(messages["detective_reveal"].format(wrapper.source)) wolf.send_messages() debuglog("{0} (detective) PAPER DROP".format(wrapper.source))
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return evt = Event("targeted_command", { "target": target, "misdirection": True, "exchange": True }) if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] targrole = get_main_role(target) trole = targrole # keep a copy for logging if targrole in var.SEEN_WOLF and targrole not in var.SEEN_DEFAULT: targrole = "wolf" elif targrole in var.SEEN_DEFAULT: targrole = var.DEFAULT_ROLE if var.DEFAULT_SEEN_AS_VILL: targrole = "villager" evt = Event("see", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] wrapper.send(messages["seer_success"].format(target, targrole)) debuglog("{0} (seer) SEE: {1} ({2}) as {3}".format(wrapper.source, target, trole, targrole)) SEEN.add(wrapper.source)
def guard(var, wrapper, message): """Guard a player, preventing them from being killed that night.""" if wrapper.source in GUARDED: wrapper.pm(messages["already_protecting"]) return target = get_target(var, wrapper, re.split(" +", message)[0], allow_self=var.GUARDIAN_ANGEL_CAN_GUARD_SELF, not_self_message="cannot_guard_self") if not target: return if LASTGUARDED.get(wrapper.source) is target: wrapper.pm(messages["guardian_target_another"].format(target)) return target_other = wrapper.source is not target evt = Event("targeted_command", { "target": target, "misdirection": target_other, "exchange": target_other }) if not evt.dispatch(var, wrapper.source, target): return target = evt.data["target"] status.add_protection(var, target, wrapper.source, "guardian angel") GUARDED[wrapper.source] = target LASTGUARDED[wrapper.source] = target if wrapper.source is target: wrapper.pm(messages["guardian_guard_self"]) else: wrapper.pm(messages["protecting_target"].format(target)) target.send(messages["target_protected"]) debuglog("{0} (guardian angel) GUARD: {1} ({2})".format( wrapper.source, target, get_main_role(target)))
def guard(var, wrapper, message): """Guard a player, preventing them from being killed that night.""" if wrapper.source in GUARDED: wrapper.pm(messages["already_protecting"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="cannot_guard_self") if not target: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return add_protection(var, target, wrapper.source, "bodyguard") GUARDED[wrapper.source] = target wrapper.pm(messages["protecting_target"].format(target)) target.send(messages["target_protected"]) debuglog("{0} (bodyguard) GUARD: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def hunter_kill(var, wrapper, message): """Kill someone once per game.""" if wrapper.source in HUNTERS and wrapper.source not in KILLS: wrapper.pm(messages["hunter_already_killed"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_suicide") if not target: return orig = target target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return KILLS[wrapper.source] = target HUNTERS.add(wrapper.source) PASSED.discard(wrapper.source) wrapper.pm(messages["player_kill"].format(orig)) debuglog("{0} (hunter) KILL: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def feed(self, var, wrapper, message): """Give your totem to the tribe members.""" from src.roles.shaman import TOTEMS as s_totems, SHAMANS as s_shamans from src.roles.wolfshaman import TOTEMS as ws_totems, SHAMANS as ws_shamans pieces = re.split(" +", message) valid = ("sustenance", "hunger") state_vars = ((s_totems, s_shamans), (ws_totems, ws_shamans)) for TOTEMS, SHAMANS in state_vars: if wrapper.source not in TOTEMS: continue totem_types = list(TOTEMS[wrapper.source].keys()) given = complete_one_match(pieces[0], totem_types) if not given and TOTEMS[wrapper.source].get( "sustenance", 0) + TOTEMS[wrapper.source].get("hunger", 0) > 1: wrapper.send(messages["boreal_ambiguous_feed"]) return for totem in valid: if (given and totem != given) or TOTEMS[wrapper.source].get( totem, 0) == 0: continue # doesn't have a totem that can be used to feed tribe SHAMANS[wrapper.source][totem].append(users.Bot) if len(SHAMANS[wrapper.source][totem]) > TOTEMS[ wrapper.source][totem]: SHAMANS[wrapper.source][totem].pop(0) nick = wrapper.source role = get_main_role(nick) wrapper.pm(messages["boreal_feed_success"].format(totem)) if role == "wolf shaman": wolves.send_wolfchat_message( var=var, user=wrapper.source, message=messages["boreal_wolf_feed_success"].format( nick, totem), roles="wolf shaman") return
def vg_kill(var, wrapper, message): """Take revenge on someone each night after you die.""" if GHOSTS[wrapper.source][0] == "!": return target = get_target(var, wrapper, re.split(" +", message)[0]) if not target: return if target is wrapper.source: wrapper.pm(messages["player_dead"]) return wolves = get_players(var.WOLFTEAM_ROLES) if GHOSTS[wrapper.source] == "wolves" and target not in wolves: wrapper.pm(messages["vengeful_ghost_wolf"]) return elif GHOSTS[wrapper.source] == "villagers" and target in wolves: wrapper.pm(messages["vengeful_ghost_villager"]) 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"})) if evt.prevent_default: return target = users._get(evt.data["target"]) # FIXME KILLS[wrapper.source] = target wrapper.pm(messages["player_kill"].format(orig)) debuglog("{0} (vengeful ghost) KILL: {1} ({2})".format( wrapper.source.nick, target, get_main_role(target))) chk_nightdone(wrapper.source.client)
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return evt = Event("targeted_command", { "target": target, "misdirection": True, "exchange": True }) if not evt.dispatch(var, "identify", wrapper.source, target, frozenset({"info", "immediate"})): return target = evt.data["target"] targrole = get_main_role(target) trole = targrole # keep a copy for logging evt = Event("investigate", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] aura = "blue" if targrole in var.WOLFTEAM_ROLES: aura = "red" elif targrole in var.TRUE_NEUTRAL_ROLES: aura = "grey" wrapper.send(messages["augur_success"].format(target, aura)) debuglog("{0} (augur) SEE: {1} ({2}) as {3} ({4} aura)".format( wrapper.source, target, trole, targrole, aura)) SEEN.add(wrapper.source)
def investigate(var, wrapper, message): """Investigate a player to determine their exact role.""" if wrapper.source in INVESTIGATED: wrapper.send(messages["already_investigated"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_investigate_self") if target is None: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return targrole = get_main_role(target) evt = Event("investigate", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] INVESTIGATED.add(wrapper.source) wrapper.send(messages["investigate_success"].format(target, targrole)) debuglog("{0} (detective) ID: {1} ({2})".format(wrapper.source, target, targrole)) if random.random() < var.DETECTIVE_REVEALED_CHANCE: # a 2/5 chance (should be changeable in settings) # The detective's identity is compromised! wcroles = Wolfchat if var.RESTRICT_WOLFCHAT & var.RW_REM_NON_WOLVES: if var.RESTRICT_WOLFCHAT & var.RW_TRAITOR_NON_WOLF: wcroles = Wolf else: wcroles = Wolf | {"traitor"} wolves = get_all_players(wcroles) if wolves: for wolf in wolves: wolf.queue_message(messages["detective_reveal"].format(wrapper.source)) wolf.send_messages() debuglog("{0} (detective) PAPER DROP".format(wrapper.source))
def observe(var, wrapper, message): """Turn a player into a wolf!""" if not ENABLED: wrapper.pm(messages["alpha_no_bite"]) return if wrapper.source in ALPHAS: wrapper.pm(messages["alpha_already_bit"]) return target = get_target(var, wrapper, re.split(" +", message)[0]) if not target: return if is_known_wolf_ally(var, wrapper.source, target): wrapper.pm(messages["alpha_no_bite_wolf"]) return orig = target target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return BITTEN[wrapper.source] = target wrapper.pm(messages["alpha_bite_target"].format(orig)) send_wolfchat_message(var, wrapper.source, messages["alpha_bite_wolfchat"].format(wrapper.source, target), {"alpha wolf"}, role="alpha wolf", command="bite") debuglog("{0} (alpha wolf) BITE: {1} ({2})".format(wrapper.source, target, get_main_role(target)))
def see(var, wrapper, message): """Use your paranormal powers to determine the role or alignment of a player.""" if wrapper.source in SEEN: wrapper.send(messages["seer_fail"]) return target = get_target(var, wrapper, re.split(" +", message)[0], not_self_message="no_see_self") if target is None: return target = try_misdirection(var, wrapper.source, target) if try_exchange(var, wrapper.source, target): return targrole = get_main_role(target) trole = targrole # keep a copy for logging if targrole in Cursed: targrole = "wolf" elif targrole in Safe: pass # Keep the same role elif targrole in Innocent: targrole = var.HIDDEN_ROLE elif targrole in Wolf: targrole = "wolf" else: targrole = var.HIDDEN_ROLE evt = Event("see", {"role": targrole}) evt.dispatch(var, wrapper.source, target) targrole = evt.data["role"] wrapper.send(messages["seer_success"].format(target, targrole)) debuglog("{0} (seer) SEE: {1} ({2}) as {3}".format(wrapper.source, target, trole, targrole)) SEEN.add(wrapper.source)