Esempio n. 1
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)))
Esempio n. 2
0
def on_transition_night_end(evt, var):
    for monster in get_all_players(("monster",)):
        add_protection(var, monster, protector=None, protector_role="monster", scope=Wolf)
        if monster.prefers_simple():
            monster.send(messages["monster_simple"])
        else:
            monster.send(messages["monster_notify"])
Esempio n. 3
0
def on_myrole(evt, var, user):
    if user in get_all_players(("minion",)):
        wolves = []
        for wolfrole in Wolf:
            for player in var.ORIGINAL_ROLES[wolfrole]:
                wolves.append(player.nick)
        evt.data["messages"].append(messages["original_wolves"].format(", ".join(wolves)))
Esempio n. 4
0
 def on_transition_night_end(evt, var):
     for gunner in get_all_players((rolename,)):
         if GUNNERS[gunner]:
             if gunner.prefers_simple(): # gunner and sharpshooter share the same key for simple
                 gunner.send(messages["gunner_simple"].format(rolename, GUNNERS[gunner], "s" if GUNNERS[gunner] > 1 else ""))
             else:
                 gunner.send(messages["{0}_notify".format(rolename)].format(botconfig.CMD_CHAR, GUNNERS[gunner], "s" if GUNNERS[gunner] > 1 else ""))
Esempio n. 5
0
def on_gun_chances(evt, var, user, role):
    if role != "sharpshooter" and user in get_all_players(("village drunk",)):
        hit, miss, headshot = var.DRUNK_GUN_CHANCES
        evt.data["hit"] = hit
        evt.data["miss"] = miss
        evt.data["headshot"] = headshot
        evt.stop_processing = True
Esempio n. 6
0
def on_assassin_target(evt, var, assassin, players):
    if evt.data["target"] is None and assassin in get_all_players(("village drunk",)):
        evt.data["target"] = random.choice(players)
        message = messages["drunken_assassin_notification"].format(evt.data["target"])
        if not assassin.prefers_simple():
            message += messages["assassin_info"]
        assassin.send(message)
Esempio n. 7
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)))
Esempio n. 8
0
    def on_transition_night_end(evt, var):
        pl = set()
        ctr = Counter()

        for t in types:
            cat = cats.get(t)
            players = get_players(cat)
            pl.update(players)
            ctr[t] += len(players)

        values = []
        plural = True
        for name in types:
            keyname = "mystic_" + name.lower().replace(" ", "_")
            l = ctr[name]
            if l:
                if not values and l == 1:
                    plural = False
            else:
                l = "no"
            values.append("\u0002{0}\u0002 {1}{2}".format(l, messages[keyname], "" if l == 1 else "s"))

        if len(values) > 2:
            value = " and ".join((", ".join(values[:-1]), values[-1]))
        else:
            value = " and ".join(values)
        msg = messages["mystic_info"].format("are" if plural else "is", value, " still", "")

        for mystic in get_all_players((rolename,)):
            LAST_COUNT[mystic] = (value, plural)
            if send_role:
                to_send = "{0}_{1}".format(role, ("simple" if mystic.prefers_simple() else "notify"))
                mystic.send(messages[to_send])
            mystic.send(msg)
Esempio n. 9
0
def on_transition_night_end(evt, var):
    if get_all_players(("doomsayer",)):
        status.add_lycanthropy_scope(var, All) # any role can transform if ds is in play
    for lycan in LYCANS.values():
        status.add_lycanthropy(var, lycan)

    LYCANS.clear()
    SICK.clear()
Esempio n. 10
0
def on_transition_night_end(evt, var):
    if not ENABLED:
        return
    can_bite = get_all_players(("alpha wolf",)) - ALPHAS
    if can_bite:
        for alpha in can_bite:
            alpha.queue_message(messages["wolf_bite"])
        alpha.send_messages()
Esempio n. 11
0
def on_get_role_metadata(evt, var, kind):
    if kind == "night_kills" and ENABLED:
        # biting someone has a chance of killing them instead of turning
        # and it can be guarded against, so it's close enough to a kill by that measure
        can_bite = get_all_players(("alpha wolf",)) - ALPHAS
        evt.data["alpha wolf"] = len(can_bite)
    elif kind == "role_categories":
        evt.data["alpha wolf"] = {"Wolf", "Wolfchat", "Wolfteam", "Killer", "Nocturnal"}
Esempio n. 12
0
def on_transition_day_begin(evt, var):
    pl = get_players()
    for mm in get_all_players(("matchmaker",)):
        if mm not in MATCHMAKERS:
            lovers = random.sample(pl, 2)
            MATCHMAKERS.add(mm)
            _set_lovers(*lovers)
            mm.send(messages["random_matchmaker"])
Esempio n. 13
0
def on_transition_night_end(evt, var):
    for blessed in get_all_players(("blessed villager",)):
        status.add_protection(var, blessed, blessed, "blessed villager")
        if var.NIGHT_COUNT == 1 or var.ALWAYS_PM_ROLE:
            to_send = "blessed_notify"
            if blessed.prefers_simple():
                to_send = "blessed_simple"
            blessed.send(messages[to_send])
Esempio n. 14
0
def on_transition_night_end(evt, var):
    wolves = get_players(get_wolfchat_roles(var))
    for child in get_all_players(("wild child",)):
        if child in wolves:
            continue
        if child.prefers_simple():
            child.send(messages["wild_child_simple"])
        else:
            child.send(messages["wild_child_notify"])
Esempio n. 15
0
def on_transition_night_end(evt, var):
    for harlot in get_all_players(("harlot",)):
        pl = get_players()
        random.shuffle(pl)
        pl.remove(harlot)
        to_send = "harlot_info"
        if harlot.prefers_simple():
            to_send = "harlot_simple"
        harlot.send(messages[to_send], messages["players_list"].format(", ".join(p.nick for p in pl)), sep="\n")
Esempio n. 16
0
def on_transition_night_end(evt, var):
    for ms in get_all_players(("mad scientist",)):
        pl = get_players()
        target1, target2 = _get_targets(var, pl, ms)

        to_send = "mad_scientist_notify"
        if ms.prefers_simple():
            to_send = "mad_scientist_simple"
        ms.send(messages[to_send].format(target1, target2))
Esempio n. 17
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)
Esempio n. 18
0
def on_transition_night_end(evt, var):
    ps = get_players()
    for vigilante in get_all_players(("vigilante",)):
        pl = ps[:]
        random.shuffle(pl)
        pl.remove(vigilante)
        to_send = "vigilante_notify"
        if vigilante.prefers_simple():
            to_send = "vigilante_simple"
        vigilante.send(messages[to_send], messages["players_list"].format(", ".join(p.nick for p in pl)), sep="\n")
Esempio n. 19
0
def on_transition_day_resolve_end(evt, var, victims):
    for gangel in get_all_players(("guardian angel",)):
        if GUARDED.get(gangel) in get_players(Wolf) and gangel not in evt.data["dead"]:
            r = random.random()
            if r < var.GUARDIAN_ANGEL_DIES_CHANCE:
                if var.ROLE_REVEAL == "on":
                    evt.data["message"][gangel].append(messages["guardian_angel_protected_wolf"].format(gangel))
                else: # off and team
                    evt.data["message"][gangel].append(messages["guardian_angel_protected_wolf_no_reveal"].format(gangel))
                evt.data["dead"].append(gangel)
Esempio n. 20
0
def on_transition_night_end(evt, var):
    lycans = get_all_players(("lycan",))
    if lycans:
        add_lycanthropy_scope(var, {"lycan"})
    for lycan in lycans:
        add_lycanthropy(var, lycan)
        if lycan.prefers_simple():
            lycan.send(messages["lycan_simple"])
        else:
            lycan.send(messages["lycan_notify"])
Esempio n. 21
0
def on_transition_night_end(evt, var):
    ps = set(get_players()) - CHARMED
    for piper in get_all_players(("piper",)):
        pl = list(ps)
        random.shuffle(pl)
        pl.remove(piper)
        to_send = "piper_notify"
        if piper.prefers_simple():
            to_send = "piper_simple"
        piper.send(messages[to_send], messages["players_list"].format(", ".join(p.nick for p in pl)), sep="\n")
Esempio n. 22
0
def on_transition_night_begin(evt, var):
    global STATS_FLAG
    if var.NIGHT_COUNT == var.AMNESIAC_NIGHTS:
        amnesiacs = get_all_players(("amnesiac",))
        if amnesiacs and not var.HIDDEN_AMNESIAC:
            STATS_FLAG = True

        for amn in amnesiacs:
            role = change_role(var, amn, "amnesiac", ROLES[amn], message="amnesia_clear")
            debuglog("{0} REMEMBER: {1}".format(amn, role))
Esempio n. 23
0
def on_transition_night_end(evt, var):
    for minion in get_all_players(("minion",)):
        if minion in RECEIVED_INFO and not var.ALWAYS_PM_ROLE:
            continue
        if minion.prefers_simple():
            to_send = "minion_simple"
        else:
            to_send = "minion_notify"
        minion.send(messages[to_send])
        minion.send(wolf_list(var))
        RECEIVED_INFO.add(minion)
Esempio n. 24
0
def on_transition_night_end(evt, var):
    ps = get_players()
    for doctor in get_all_players(("doctor",)):
        if DOCTORS[doctor]: # has immunizations remaining
            pl = ps[:]
            random.shuffle(pl)
            if doctor.prefers_simple():
                doctor.send(messages["doctor_simple"])
            else:
                doctor.send(messages["doctor_notify"])
            doctor.send(messages["doctor_immunizations"].format(DOCTORS[doctor], "s" if DOCTORS[doctor] > 1 else ""))
Esempio n. 25
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))
Esempio n. 26
0
def on_transition_night_end(evt, var):
    ps = get_players()
    for hunter in get_all_players(("hunter",)):
        if hunter in HUNTERS:
            continue # already killed
        pl = ps[:]
        random.shuffle(pl)
        pl.remove(hunter)
        to_send = "hunter_notify"
        if hunter.prefers_simple():
            to_send = "hunter_simple"
        hunter.send(messages[to_send], messages["players_list"].format(", ".join(p.nick for p in pl)), sep="\n")
Esempio n. 27
0
def on_transition_night_end(evt, var):
    ps = get_players()
    for mm in get_all_players(("matchmaker",)):
        if mm in MATCHMAKERS and not var.ALWAYS_PM_ROLE:
            continue
        pl = ps[:]
        random.shuffle(pl)
        if mm.prefers_simple():
            mm.send(messages["matchmaker_simple"])
        else:
            mm.send(messages["matchmaker_notify"])
        mm.send("Players: " + ", ".join(p.nick for p in pl))
Esempio n. 28
0
def on_transition_day_resolve_end(evt, var, victims):
    for bodyguard in DYING:
        evt.data["message"][bodyguard].clear()
    DYING.clear()
    for bodyguard in get_all_players(("bodyguard",)):
        if GUARDED.get(bodyguard) in get_players(Wolf) and bodyguard not in evt.data["dead"]:
            r = random.random()
            if r < var.BODYGUARD_DIES_CHANCE:
                if var.ROLE_REVEAL == "on":
                    evt.data["message"][bodyguard].append(messages["bodyguard_protected_wolf"].format(bodyguard))
                else: # off and team
                    evt.data["message"][bodyguard].append(messages["bodyguard_protection"].format(bodyguard))
                evt.data["dead"].append(bodyguard)
Esempio n. 29
0
File: fool.py Progetto: lykoss/lykos
def on_lynch(evt, var, votee, voters):
    global VOTED
    if votee in get_all_players(("fool",)):
        # ends game immediately, with fool as only winner
        # hardcode "fool" as the role since game is ending due to them being lynched,
        # so we want to show "fool" even if it's a template
        lmsg = random.choice(messages["lynch_reveal"]).format(votee, "", "fool")
        VOTED = votee
        channels.Main.send(lmsg)
        from src.wolfgame import chk_win
        chk_win(winner="fool")

        evt.prevent_default = True
        evt.stop_processing = True
Esempio n. 30
0
def on_transition_night_end(evt, var):
    for turncoat in get_all_players(("turncoat",)):
        # they start out as unsided, but can change n1
        if turncoat not in TURNCOATS:
            TURNCOATS[turncoat] = ("none", -1)

        if turncoat.prefers_simple():
            turncoat.send(messages["turncoat_simple"].format(TURNCOATS[turncoat][0]))
        else:
            message = messages["turncoat_notify"]
            if TURNCOATS[turncoat][0] != "none":
                message += messages["turncoat_current_team"].format(TURNCOATS[turncoat][0])
            else:
                message += messages["turncoat_no_team"]
            turncoat.send(message)
Esempio n. 31
0
def on_chk_nightdone(evt, var):
    nevt = Event("wolf_numkills", {"numkills": 1, "message": ""})
    nevt.dispatch(var)
    num_kills = nevt.data["numkills"]
    wofls = [
        x for x in get_all_players(Wolf & Killer) if not is_silent(var, x)
    ]
    if not num_kills or not wofls:
        return

    fake = users.FakeUser.from_nick("@WolvesAgree@")
    evt.data["nightroles"].extend(wofls)
    evt.data["acted"].extend(KILLS)
    evt.data["nightroles"].append(fake)

    kills = set()
    for ls in KILLS.values():
        kills.update(ls)
    # check if wolves are actually agreeing
    if len(kills) == num_kills:
        evt.data["acted"].append(fake)
Esempio n. 32
0
def on_transition_night_end(evt, var):
    for ass in get_all_players(("assassin",)):
        if ass in TARGETED:
            continue # someone already targeted

        pl = get_players()
        random.shuffle(pl)
        pl.remove(ass)

        ass_evt = Event("assassin_target", {"target": None})
        ass_evt.dispatch(var, ass, pl)

        if ass_evt.data["target"] is not None:
            TARGETED[ass] = ass_evt.data["target"]
            PREV_ACTED.add(ass)
        else:
            if ass.prefers_simple():
                ass.send(messages["assassin_simple"])
            else:
                ass.send(messages["assassin_notify"])
            ass.send(messages["players_list"].format(", ".join(p.nick for p in pl)))
Esempio n. 33
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))
Esempio n. 34
0
def on_del_player(evt, var, user, mainrole, allroles, death_triggers):
    global ALL_SUCC_IDLE
    if "succubus" not in allroles:
        return
    if user in VISITED:
        # if it's night, also unentrance the person they visited
        if var.PHASE == "night" and var.GAMEPHASE == "night":
            if VISITED[user] in ENTRANCED:
                ENTRANCED.discard(VISITED[user])
                VISITED[user].send(messages["entranced_revert_win"])
        del VISITED[user]

    # if all succubi idled out (every last one of them), un-entrance people
    # death_triggers is False for an idle-out, so we use that to determine which it is
    if death_triggers:
        ALL_SUCC_IDLE = False
    if not get_all_players(("succubus",)):
        entranced_alive = ENTRANCED.difference(evt.params.deadlist).intersection(evt.data["pl"])
        if ALL_SUCC_IDLE:
            while ENTRANCED:
                e = ENTRANCED.pop()
                e.send(messages["entranced_revert_win"])
Esempio n. 35
0
def on_transition_night_begin(evt, var):
    global STATS_FLAG
    if var.NIGHT_COUNT == var.AMNESIAC_NIGHTS:
        amnesiacs = get_all_players(("amnesiac", ))
        if amnesiacs and not var.HIDDEN_AMNESIAC:
            STATS_FLAG = True

        for amn in amnesiacs:
            role = ROLES[amn]
            change_role(amn, "amnesiac", role)
            evt = Event("new_role", {})
            evt.dispatch(var, amn, role)
            if var.FIRST_NIGHT:  # we don't need to tell them twice if they remember right away
                continue
            showrole = role
            if showrole in var.HIDDEN_VILLAGERS:
                showrole = "villager"
            elif showrole in var.HIDDEN_ROLES:
                showrole = var.DEFAULT_ROLE
            a = "a"
            if showrole.startswith(("a", "e", "i", "o", "u")):
                a = "an"
            amn.send(messages["amnesia_clear"].format(a, showrole))
            if is_known_wolf_ally(amn, amn):
                if role in var.WOLF_ROLES:
                    relay_wolfchat_command(amn.client,
                                           amn.nick,
                                           messages["amnesia_wolfchat"].format(
                                               amn, showrole),
                                           var.WOLF_ROLES,
                                           is_wolf_command=True,
                                           is_kill_command=True)
                else:
                    relay_wolfchat_command(
                        amn.client, amn.nick,
                        messages["amnesia_wolfchat"].format(amn, showrole),
                        var.WOLFCHAT_ROLES)

            debuglog("{0} REMEMBER: {1} as {2}".format(amn, role, showrole))
Esempio n. 36
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

    evt = Event("targeted_command", {
        "target": target,
        "exchange": True,
        "misdirection": True
    })
    if not evt.dispatch(var, wrapper.source, target):
        return

    CURSED[wrapper.source] = evt.data["target"]
    PASSED.discard(wrapper.source)

    wrapper.pm(messages["curse_success"].format(target))
    send_wolfchat_message(var,
                          wrapper.source,
                          messages["curse_success_wolfchat"].format(
                              wrapper.source, target), {"warlock"},
                          role="warlock",
                          command="curse")

    debuglog("{0} (warlock) CURSE: {1} ({2})".format(
        wrapper.source, evt.data["target"], get_main_role(evt.data["target"])))
Esempio n. 37
0
def on_transition_night_end(evt, var):
    wolves = get_all_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

    for wolf in wolves:
        can_talk = len(get_all_roles(wolf) & talkroles) > 0
        if len(wolves) > 1 and can_talk and wccond > 0:
            wolf.send(messages["wolfchat_notify_{0}".format(wccond)])
Esempio n. 38
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    global ALL_SUCC_IDLE
    if "succubus" not in all_roles:
        return
    if player in VISITED:
        # if it's night, also unentrance the person they visited
        if var.PHASE == "night" and var.GAMEPHASE == "night":
            if VISITED[player] in ENTRANCED:
                ENTRANCED.discard(VISITED[player])
                VISITED[player].send(messages["entranced_revert_win"])
        del VISITED[player]

    PASSED.discard(player)
    FORCE_PASSED.discard(player)

    # if all succubi idled out (every last one of them), un-entrance people
    # death_triggers is False for an idle-out, so we use that to determine which it is
    if death_triggers:
        ALL_SUCC_IDLE = False
    if ALL_SUCC_IDLE and not get_all_players(("succubus", )):
        while ENTRANCED:
            e = ENTRANCED.pop()
            e.send(messages["entranced_revert_win"])
Esempio n. 39
0
    def prolong_night(self, var, gameid, transition_day):
        nspecials = len(get_all_players(("seer", "harlot", "shaman", "crazed shaman")))
        rand = random.gauss(5, 1.5)
        if rand <= 0 and nspecials > 0:
            transition_day(gameid=gameid)
        else:
            # rejig the night ending timer to cleanup what we're doing
            # NOTE: this relies on implementation details in CPython and may not work across python versions
            # or with other python implementations. If this becomes problematic, we may want to use our own timer impl
            # rather than rely on threading.Timer; we can mostly just lift what CPython has for that
            if "night" in self.saved_timers:
                oldid = self.saved_timers["night"][0].kwargs["gameid"]
                self.saved_timers["night"][0].kwargs = {
                    "var": var,
                    "gameid": oldid,
                    "transition_day": transition_day
                }
                self.saved_timers["night"][0].function = self.prolong_night_end

            # bootstrap villagergame delay timer
            current = time.time()
            delay = abs(rand)
            t = threading.Timer(delay, self.prolong_night_end,
                                kwargs={"var": var, "gameid": gameid, "transition_day": transition_day})
            self.saved_timers["villagergame"] = (t, current, delay)

            # restart saved timers (they were cancelled before prolong_night was called)
            for name, t in self.saved_timers.items():
                elapsed = current - t[1]
                remaining = t[2] - elapsed
                if remaining > 0:
                    new_timer = threading.Timer(remaining, t[0].function, t[0].args, t[0].kwargs)
                    var.TIMERS[name] = (new_timer, t[1], t[2])
                    new_timer.daemon = True
                    new_timer.start()

            self.saved_timers = {}
Esempio n. 40
0
def on_del_player(evt, var, player, all_roles, death_triggers):
    # clone happens regardless of death_triggers being true or not
    if var.PHASE not in var.GAME_PHASES:
        return

    clones = get_all_players(("clone", ))
    mainrole = evt.params.main_role
    for clone in clones:
        if clone in CLONED:
            target = CLONED[clone]
            if player is target:
                # clone is cloning target, so clone becomes target's role
                # clone does NOT get any of target's templates (gunner/assassin/etc.)
                del CLONED[clone]
                mainrole = change_role(var,
                                       clone,
                                       "clone",
                                       mainrole,
                                       inherit_from=target)
                # if a clone is cloning a clone, clone who the old clone cloned
                if mainrole == "clone" and player in CLONED:
                    if CLONED[player] is clone:
                        clone.send(messages["forever_aclone"].format(player))
                    else:
                        CLONED[clone] = CLONED[player]
                        clone.send(messages["clone_success"].format(
                            CLONED[clone]))
                        debuglog("{0} (clone) CLONE: {1} ({2})".format(
                            clone, CLONED[clone],
                            get_main_role(CLONED[clone])))

                debuglog("{0} (clone) CLONE DEAD PLAYER: {1} ({2})".format(
                    clone, target, mainrole))

    del CLONED[:player:]
    CAN_ACT.discard(player)
    ACTED.discard(player)
Esempio n. 41
0
def on_transition_night_end(evt, var):
    ps = get_players()
    for gangel in get_all_players(("guardian angel", )):
        pl = ps[:]
        random.shuffle(pl)
        gself = messages["guardian_self_notification"]
        if not var.GUARDIAN_ANGEL_CAN_GUARD_SELF:
            pl.remove(gangel)
            gself = ""
        if gangel in LASTGUARDED:
            if LASTGUARDED[gangel] in pl:
                pl.remove(LASTGUARDED[gangel])
        chance = math.floor(var.GUARDIAN_ANGEL_DIES_CHANCE * 100)
        warning = ""
        if chance > 0:
            warning = messages["bodyguard_death_chance"].format(chance)

        to_send = "guardian_angel_notify"
        if gangel.prefers_simple():
            to_send = "guardian_angel_simple"
        gangel.send(messages[to_send].format(warning, gself),
                    messages["players_list"].format(", ".join(p.nick
                                                              for p in pl)),
                    sep="\n")
Esempio n. 42
0
def on_transition_day(evt, var):
    # figure out wolf target
    found = defaultdict(int)
    nevt = Event("wolf_numkills", {"numkills": 1})
    nevt.dispatch(var)
    num_kills = nevt.data["numkills"]
    for v in KILLS.values():
        for p in v:
            found[p] += 1
    for i in range(num_kills):
        maxc = 0
        dups = []
        for v, c in found.items():
            if c > maxc:
                maxc = c
                dups = [v]
            elif c == maxc:
                dups.append(v)
        if maxc and dups:
            target = random.choice(dups)
            evt.data["victims"].append(target)
            evt.data["bywolves"].add(target)
            evt.data["onlybywolves"].add(target)
            # special key to let us know to randomly select a wolf in case of retribution totem
            evt.data["killers"][target].append("@wolves")
            del found[target]

    # when monster is split, add protection to them if in onlybywolves
    # fallen angel will then remove that protection
    # TODO: when monster is split off
    if var.ROLES["fallen angel"]:
        for monster in get_all_players(("monster",)):
            if monster in evt.data["victims"]:
                evt.data["victims"].remove(monster)
                evt.data["bywolves"].discard(monster)
                evt.data["onlybywolves"].discard(monster)
Esempio n. 43
0
def on_transition_day_begin(evt, var):
    # Select random totem recipients if shamans didn't act
    pl = get_players()
    for shaman in get_all_players(("wolf shaman", )):
        if is_silent(var, shaman):
            continue

        ps = pl[:]
        for given in itertools.chain.from_iterable(LASTGIVEN[shaman].values()):
            if given in ps:
                ps.remove(given)
        for given in itertools.chain.from_iterable(SHAMANS[shaman].values()):
            if given in ps:
                ps.remove(given)
        for totem, count in TOTEMS[shaman].items():
            mustgive = count - len(SHAMANS[shaman][totem])
            for i in range(mustgive):
                if ps:
                    target = random.choice(ps)
                    ps.remove(target)
                    dispatcher = MessageDispatcher(shaman, shaman)
                    given = give_totem(var,
                                       dispatcher,
                                       target,
                                       totem,
                                       key="shaman_success_random_known",
                                       role="wolf shaman")
                    if given:
                        send_wolfchat_message(
                            var,
                            shaman,
                            messages["shaman_wolfchat"].format(shaman, target),
                            ("wolf shaman", ),
                            role="wolf shaman",
                            command="totem")
                        SHAMANS[shaman][totem].append(given[0])
Esempio n. 44
0
def on_transition_night_end(evt, var):
    for child in get_all_players(("wild child", )):
        to_send = "child_notify"
        if child.prefers_simple():
            to_send = "child_simple"
        child.send(messages[to_send])
Esempio n. 45
0
def on_chk_nightdone(evt, var):
    if var.FIRST_NIGHT:
        evt.data["actedcount"] += len(IDOLS.keys())
        evt.data["nightroles"].extend(get_all_players(("wild child", )))
Esempio n. 46
0
def on_chk_nightdone(evt, var):
    if not ENABLED:
        return
    can_act = get_all_players(("alpha wolf",)) - ALPHAS
    evt.data["acted"].extend(BITTEN)
    evt.data["nightroles"].extend(can_act)
Esempio n. 47
0
def on_harlot_visit(evt, var, harlot, victim):
    if victim in get_all_players(("succubus",)):
        harlot.send(messages["notify_succubus_target"].format(victim))
        victim.send(messages["succubus_harlot_success"].format(harlot))
        ENTRANCED.add(harlot)
Esempio n. 48
0
def on_chk_nightdone(evt, var):
    evt.data["actedcount"] += len(VISITED) + len(PASSED)
    evt.data["nightroles"].extend(get_all_players(("succubus",)))
Esempio n. 49
0
def on_chk_nightdone(evt, var):
    evt.data["actedcount"] += len(CURSED) + len(PASSED)
    evt.data["nightroles"].extend(get_all_players(("warlock", )))
Esempio n. 50
0
def on_chk_nightdone(evt, var):
    evt.data["nightroles"].extend(get_all_players(("prophet", )))
    evt.data["actedcount"] += len(PRAYED)
Esempio n. 51
0
def on_try_protection(evt, var, target, attacker, attacker_role, reason):
    if attacker_role == "wolf" and get_all_players(("fallen angel",)):
        status.remove_all_protections(var, target, attacker=None, attacker_role="fallen angel", reason="fallen_angel")
        evt.prevent_default = True
Esempio n. 52
0
def on_succubus_visit(evt, var, succubus, target):
    if target in KILLS and KILLS[target] in get_all_players(("succubus",)):
        target.send(messages["no_kill_succubus"].format(KILLS[target]))
        del KILLS[target]
Esempio n. 53
0
def on_chk_nightdone(evt, var):
    evt.data["actedcount"] += len(KILLS) + len(PASSED)
    evt.data["nightroles"].extend(get_all_players(("vigilante",)))
Esempio n. 54
0
def on_chk_nightdone(evt, var):
    evt.data["acted"].extend(OBSERVED)
    evt.data["nightroles"].extend(get_all_players(("werecrow", )))
Esempio n. 55
0
def on_transition_night_end(evt, var):
    for demoniac in get_all_players(("demoniac", )):
        if demoniac.prefers_simple():
            demoniac.send(messages["demoniac_simple"])
        else:
            demoniac.send(messages["demoniac_notify"])
Esempio n. 56
0
def pray(var, wrapper, message):
    """Receive divine visions of who has a role."""
    if wrapper.source in PRAYED:
        wrapper.pm(messages["already_prayed"])
        return

    what = re.split(" +", message)[0]
    if not what:
        wrapper.pm(messages["not_enough_parameters"])
        return

    # complete this as a match with other roles (so "cursed" can match "cursed villager" for instance)
    role = complete_one_match(
        what.lower(),
        {p
         for p in var.ROLE_GUIDE if p not in var.TEMPLATE_RESTRICTIONS})
    if role is None and what.lower() in var.ROLE_ALIASES:
        role = var.ROLE_ALIASES[what.lower()]
        if role in var.TEMPLATE_RESTRICTIONS:  # allow only main roles
            role = None
    if role is None:
        # typo, let them fix it
        wrapper.pm(messages["specific_invalid_role"].format(what))
        return

    # get a list of all roles actually in the game, including roles that amnesiacs will be turning into
    # (amnesiacs are special since they're also listed as amnesiac; that way a prophet can see both who the
    # amnesiacs themselves are as well as what they'll become)
    pl = get_players()
    from src.roles.amnesiac import ROLES as amn_roles
    valid_roles = {r
                   for p, r in amn_roles.items()
                   if p in pl}.union(var.MAIN_ROLES.values())

    PRAYED.add(wrapper.source)

    if role in valid_roles:
        # this sees through amnesiac, so the amnesiac's final role counts as their role
        # also, if we're the only person with that role, say so
        people = set(get_all_players((role, ))) | {
            p
            for p, r in amn_roles.items() if p in pl and r == role
        }
        if len(people) == 1 and wrapper.source in people:
            wrapper.pm(messages["vision_only_role_self"].format(role))
            PRAYED.add(wrapper.source)
            debuglog("{0} (prophet) PRAY {1} - ONLY".format(
                wrapper.source, role))
            return

        target = random.choice(list(people))
        part = random.sample([p for p in pl if p is not wrapper.source],
                             len(pl) // 3)
        if target not in part:
            part[0] = target
        random.shuffle(part)
        part = [p.nick for p in part]

        an = ""
        if role.startswith(("a", "e", "i", "o", "u")):
            an = "n"

        key = "vision_players"
        if len(part) == 1:
            key = "vision_role"

        if len(part) > 2:
            msg = "{0}, and {1}".format(", ".join(part[:-1]), part[-1])
        else:
            msg = " and ".join(part)

        wrapper.pm(messages[key].format(role, an, msg))
        debuglog("{0} (prophet) PRAY {1} ({2})".format(wrapper.source, role,
                                                       target))

    else:
        # role is not in this game, this still counts as a successful activation of the power!
        wrapper.pm(messages["vision_none"].format(plural(role)))
        debuglog("{0} (prophet) PRAY {1} - NONE".format(wrapper.source, role))
Esempio n. 57
0
def on_transition_night_end(evt, var):
    for pht in get_all_players(("prophet", )):
        if pht.prefers_simple():
            pht.send(messages["prophet_simple"])
        else:
            pht.send(messages["prophet_notify"])
Esempio n. 58
0
def on_visit(evt, var, visitor_role, visitor, visited):
    if visitor_role == "succubus":
        succubi = get_all_players(("succubus", ))
        if visited in TARGETS and TARGETS[visited].intersection(succubi):
            TARGETS[visited].difference_update(succubi)
            visited.send(messages["dullahan_no_kill_succubus"])
Esempio n. 59
0
def on_chk_nightdone(evt, var):
    evt.data["actedcount"] += len(KILLS) + len(PASSED)
    hunter_users = get_all_players(("hunter", ))
    evt.data["nightroles"].extend(
        [p for p in hunter_users if p not in HUNTERS or p in KILLS])
Esempio n. 60
0
def on_chk_nightdone(evt, var):
    evt.data["actedcount"] += len(HEXED)
    evt.data["nightroles"].extend(get_all_players(("hag", )))