Пример #1
0
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")
Пример #2
0
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)))
Пример #3
0
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)))
Пример #4
0
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)))
Пример #5
0
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)))
Пример #6
0
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)
Пример #7
0
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))
Пример #8
0
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)
Пример #9
0
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
Пример #10
0
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))
Пример #11
0
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)))
Пример #12
0
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))
Пример #13
0
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()
Пример #14
0
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"]])
Пример #15
0
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")
Пример #16
0
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)
Пример #17
0
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
Пример #18
0
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))
Пример #19
0
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)))
Пример #20
0
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)))
Пример #21
0
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)))
Пример #22
0
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")
Пример #23
0
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"])
Пример #24
0
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)
Пример #25
0
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)
Пример #26
0
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)
Пример #27
0
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)))
Пример #28
0
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)
Пример #29
0
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)
Пример #30
0
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)
Пример #31
0
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)
Пример #32
0
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"]])
Пример #33
0
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)))
Пример #34
0
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)))
Пример #35
0
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)))
Пример #36
0
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))
Пример #37
0
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))
Пример #38
0
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")
Пример #39
0
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)))
Пример #40
0
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)))
Пример #41
0
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))
Пример #42
0
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)
Пример #43
0
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")
Пример #44
0
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)))
Пример #45
0
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)))
Пример #46
0
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)))
Пример #47
0
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
Пример #48
0
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)
Пример #49
0
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))
Пример #50
0
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)
Пример #51
0
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)))
Пример #52
0
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)))
Пример #53
0
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)))
Пример #54
0
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)))
Пример #55
0
    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
Пример #56
0
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)
Пример #57
0
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)
Пример #58
0
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))
Пример #59
0
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)))
Пример #60
0
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)