Ejemplo n.º 1
0
def chk_decision(var, *, timeout=False):
    with var.GRAVEYARD_LOCK:
        players = set(get_players()) - get_absent(var)
        avail = len(players)
        needed = avail // 2 + 1

        to_vote = []

        for votee, voters in VOTES.items():
            votes = (set(voters)
                     | get_forced_votes(var, votee)) - get_forced_abstains(var)
            if sum(get_vote_weight(var, x) for x in votes) >= needed:
                to_vote.append(votee)
                break

        behaviour_evt = Event("lynch_behaviour", {
            "num_lynches": 1,
            "kill_ties": False,
            "force": timeout
        },
                              votes=VOTES,
                              players=avail)
        behaviour_evt.dispatch(var)

        num_lynches = behaviour_evt.data["num_lynches"]
        kill_ties = behaviour_evt.data["kill_ties"]
        force = behaviour_evt.data["force"]

        abstaining = False
        if not to_vote:
            if len(ABSTAINS | get_forced_abstains(var)) >= avail / 2:
                abstaining = True
            elif force:
                voting = []
                if VOTES:
                    plurality = [(x, len(y)) for x, y in VOTES.items()]
                    plurality.sort(key=lambda x: x[1])
                    votee, value = plurality.pop()
                    max_value = value
                    # Fetch all of the highest ties, exit out if we find someone lower
                    # If everyone is tied, then at some point plurality will be empty,
                    # but the values will still be at the max. Everything's fine, just break
                    while value == max_value:
                        voting.append(votee)
                        if not plurality:
                            break
                        votee, value = plurality.pop()

                if len(voting) == 1:
                    to_vote.append(voting[0])
                elif voting and kill_ties:
                    if set(voting) == set(
                            get_players()
                    ):  # killing everyone off? have you considered not doing that
                        abstaining = True
                    else:
                        to_vote.extend(voting)
                else:
                    abstaining = True

        if abstaining:
            for forced_abstainer in get_forced_abstains(var):
                if forced_abstainer not in ABSTAINS:  # did not explicitly abstain
                    channels.Main.send(messages["player_meek_abstain"].format(
                        forced_abstainer))

            abstain_evt = Event("abstain", {})
            abstain_evt.dispatch(var, ABSTAINS | get_forced_abstains(var))

            global ABSTAINED
            ABSTAINED = True
            channels.Main.send(messages["village_abstain"])

            from src.wolfgame import transition_night
            transition_night()

        if to_vote:
            global LYNCHED
            LYNCHED += len(
                to_vote)  # track how many people we've lynched today

            if timeout:
                channels.Main.send(messages["sunset_lynch"])

            for votee in to_vote:
                voters = list(VOTES[votee])
                for forced_voter in get_forced_votes(var, votee):
                    if forced_voter not in voters:  # did not explicitly vote
                        channels.Main.send(messages["impatient_vote"].format(
                            forced_voter, votee))
                        voters.append(
                            forced_voter
                        )  # they need to be counted as voting for them still

                if not try_lynch_immunity(var, votee):
                    lynch_evt = Event("lynch", {}, players=avail)
                    if lynch_evt.dispatch(var, votee, voters):
                        if var.ROLE_REVEAL in ("on", "team"):
                            rrole = get_reveal_role(votee)
                            an = "n" if rrole.startswith(
                                ("a", "e", "i", "o", "u")) else ""
                            lmsg = random.choice(
                                messages["lynch_reveal"]).format(
                                    votee, an, rrole)
                        else:
                            lmsg = random.choice(
                                messages["lynch_no_reveal"]).format(votee)
                        channels.Main.send(lmsg)
                        add_dying(var, votee, "villager", "lynch")

            kill_players(var, end_game=False)  # FIXME

        elif timeout:
            channels.Main.send(messages["sunset"])

        from src.wolfgame import chk_win
        if chk_win():
            return  # game ended, just exit out

        if timeout or LYNCHED >= num_lynches:
            from src.wolfgame import transition_night
            transition_night()
Ejemplo n.º 2
0
def chk_decision(var, *, timeout=False):
    with var.GRAVEYARD_LOCK:
        players = set(get_players()) - get_absent(var)
        avail = len(players)
        needed = avail // 2 + 1

        to_vote = []

        for votee, voters in VOTES.items():
            votes = (set(voters) | get_forced_votes(var, votee)) - get_forced_abstains(var)
            if sum(get_vote_weight(var, x) for x in votes) >= needed:
                to_vote.append(votee)
                break

        behaviour_evt = Event("lynch_behaviour", {"num_lynches": 1, "kill_ties": False, "force": timeout}, votes=VOTES, players=avail)
        behaviour_evt.dispatch(var)

        num_lynches = behaviour_evt.data["num_lynches"]
        kill_ties = behaviour_evt.data["kill_ties"]
        force = behaviour_evt.data["force"]

        abstaining = False
        if not to_vote:
            if len(ABSTAINS | get_forced_abstains(var)) >= avail / 2:
                abstaining = True
            elif force:
                voting = []
                if VOTES:
                    plurality = [(x, len(y)) for x, y in VOTES.items()]
                    plurality.sort(key=lambda x: x[1])
                    votee, value = plurality.pop()
                    max_value = value
                    # Fetch all of the highest ties, exit out if we find someone lower
                    # If everyone is tied, then at some point plurality will be empty,
                    # but the values will still be at the max. Everything's fine, just break
                    while value == max_value:
                        voting.append(votee)
                        if not plurality:
                            break
                        votee, value = plurality.pop()

                if len(voting) == 1:
                    to_vote.append(voting[0])
                elif voting and kill_ties:
                    if set(voting) == set(get_players()): # killing everyone off? have you considered not doing that
                        abstaining = True
                    else:
                        to_vote.extend(voting)
                else:
                    abstaining = True

        if abstaining:
            for forced_abstainer in get_forced_abstains(var):
                if forced_abstainer not in ABSTAINS: # did not explicitly abstain
                    channels.Main.send(messages["player_meek_abstain"].format(forced_abstainer))

            abstain_evt = Event("abstain", {})
            abstain_evt.dispatch(var, ABSTAINS | get_forced_abstains(var))

            global ABSTAINED
            ABSTAINED = True
            channels.Main.send(messages["village_abstain"])

            from src.wolfgame import transition_night
            transition_night()

        if to_vote:
            global LYNCHED
            LYNCHED += len(to_vote) # track how many people we've lynched today

            if timeout:
                channels.Main.send(messages["sunset_lynch"])

            for votee in to_vote:
                voters = list(VOTES[votee])
                for forced_voter in get_forced_votes(var, votee):
                    if forced_voter not in voters: # did not explicitly vote
                        channels.Main.send(messages["impatient_vote"].format(forced_voter, votee))
                        voters.append(forced_voter) # they need to be counted as voting for them still

                if not try_lynch_immunity(var, votee):
                    lynch_evt = Event("lynch", {}, players=avail)
                    if lynch_evt.dispatch(var, votee, voters):
                        if var.ROLE_REVEAL in ("on", "team"):
                            rrole = get_reveal_role(votee)
                            an = "n" if rrole.startswith(("a", "e", "i", "o", "u")) else ""
                            lmsg = random.choice(messages["lynch_reveal"]).format(votee, an, rrole)
                        else:
                            lmsg = random.choice(messages["lynch_no_reveal"]).format(votee)
                        channels.Main.send(lmsg)
                        add_dying(var, votee, "villager", "lynch")

            kill_players(var, end_game=False) # FIXME

        elif timeout:
            channels.Main.send(messages["sunset"])

        from src.wolfgame import chk_win
        if chk_win():
            return # game ended, just exit out

        if timeout or LYNCHED >= num_lynches:
            from src.wolfgame import transition_night
            transition_night()
Ejemplo n.º 3
0
def show_votes(var, wrapper, message):
    """Show the current votes."""
    pl = get_players()
    if var.PHASE == "join":
        # get gamemode votes in a dict of {mode: number of votes}
        gm_votes = list(Counter(var.GAMEMODE_VOTES.values()).items())
        gm_votes.sort(key=lambda x: x[1],
                      reverse=True)  # sort from highest to lowest

        votelist = []
        majority = False
        for gamemode, num_votes in gm_votes:
            # We bold the game mode if:
            # - The number of players is within the bounds of the game mode
            # - This game mode has a majority of votes
            # - It can be randomly picked
            # - No other game mode has a majority
            if (var.GAME_MODES[gamemode][1] <= len(pl) <=
                    var.GAME_MODES[gamemode][2]
                    and (not majority or num_votes >= len(pl) / 2) and
                (var.GAME_MODES[gamemode][3] > 0 or num_votes >= len(pl) / 2)):
                votelist.append("\u0002{0}\u0002: {1}".format(
                    gamemode, num_votes))
                if num_votes >= len(pl) / 2:
                    majority = True
            else:
                votelist.append("{0}: {1}".format(gamemode, num_votes))

        msg = ", ".join(votelist)
        if len(pl) >= var.MIN_PLAYERS:
            msg += messages["majority_votes"].format("; " if votelist else "",
                                                     math.ceil(len(pl) / 2))

        with var.WARNING_LOCK:
            if var.START_VOTES:
                msg += messages["start_votes"].format(
                    len(var.START_VOTES),
                    ", ".join(p.nick for p in var.START_VOTES))

        wrapper.send(msg)
        return

    if var.PHASE == "night":
        wrapper.pm(messages["voting_daytime_only"])
        return

    global LAST_VOTES

    if (wrapper.public and LAST_VOTES and var.VOTES_RATE_LIMIT
            and LAST_VOTES + timedelta(seconds=var.VOTES_RATE_LIMIT) >
            datetime.now()):
        wrapper.pm(messages["command_ratelimited"])
        return

    if wrapper.public and wrapper.source in pl:
        LAST_VOTES = datetime.now()

    if not VOTES:
        msg = messages["no_votes"]
        if wrapper.source in pl:
            LAST_VOTES = None  # reset

    else:
        votelist = []
        for votee, voters in VOTES.items():
            votelist.append("{0}: {1} ({2})".format(
                votee, len(voters), ", ".join(p.nick for p in voters)))
        msg = ", ".join(votelist)

    wrapper.reply(msg, prefix_nick=True)

    avail = len(pl) - len(get_absent(var))
    votesneeded = avail // 2 + 1
    abstaining = len(ABSTAINS)
    if abstaining == 1:  # *i18n* hardcoded English
        plural = " has"
    else:
        plural = "s have"

    to_send = messages["vote_stats"].format(len(pl), votesneeded, avail)
    if var.ABSTAIN_ENABLED:
        to_send += messages["vote_stats_abstain"].format(abstaining, plural)

    wrapper.reply(to_send, prefix_nick=True)
Ejemplo n.º 4
0
def show_votes(var, wrapper, message):
    """Show the current votes."""
    pl = get_players()
    if var.PHASE == "join":
        # get gamemode votes in a dict of {mode: number of votes}
        gm_votes = list(Counter(var.GAMEMODE_VOTES.values()).items())
        gm_votes.sort(key=lambda x: x[1], reverse=True) # sort from highest to lowest

        votelist = []
        majority = False
        for gamemode, num_votes in gm_votes:
            # We bold the game mode if:
            # - The number of players is within the bounds of the game mode
            # - This game mode has a majority of votes
            # - It can be randomly picked
            # - No other game mode has a majority
            if (var.GAME_MODES[gamemode][1] <= len(pl) <= var.GAME_MODES[gamemode][2] and
                (not majority or num_votes >= len(pl) / 2) and (var.GAME_MODES[gamemode][3] > 0 or num_votes >= len(pl) / 2)):
                votelist.append("\u0002{0}\u0002: {1}".format(gamemode, num_votes))
                if num_votes >= len(pl) / 2:
                    majority = True
            else:
                votelist.append("{0}: {1}".format(gamemode, num_votes))

        msg = ", ".join(votelist)
        if len(pl) >= var.MIN_PLAYERS:
            msg += messages["majority_votes"].format("; " if votelist else "", math.ceil(len(pl) / 2))

        with var.WARNING_LOCK:
            if pregame.START_VOTES:
                msg += messages["start_votes"].format(len(pregame.START_VOTES), ", ".join(p.nick for p in pregame.START_VOTES))

        wrapper.send(msg)
        return

    if var.PHASE == "night":
        wrapper.pm(messages["voting_daytime_only"])
        return

    global LAST_VOTES

    if (wrapper.public and LAST_VOTES and var.VOTES_RATE_LIMIT and
            LAST_VOTES + timedelta(seconds=var.VOTES_RATE_LIMIT) > datetime.now()):
        wrapper.pm(messages["command_ratelimited"])
        return

    if wrapper.public and wrapper.source in pl:
        LAST_VOTES = datetime.now()

    if not VOTES:
        msg = messages["no_votes"]
        if wrapper.source in pl:
            LAST_VOTES = None # reset

    else:
        votelist = []
        for votee, voters in VOTES.items():
            votelist.append("{0}: {1} ({2})".format(votee, len(voters), ", ".join(p.nick for p in voters)))
        msg = ", ".join(votelist)

    wrapper.reply(msg, prefix_nick=True)

    avail = len(pl) - len(get_absent(var))
    votesneeded = avail // 2 + 1
    abstaining = len(ABSTAINS)
    if abstaining == 1: # *i18n* hardcoded English
        plural = " has"
    else:
        plural = "s have"

    to_send = messages["vote_stats"].format(len(pl), votesneeded, avail)
    if var.ABSTAIN_ENABLED:
        to_send += messages["vote_stats_abstain"].format(abstaining, plural)

    wrapper.reply(to_send, prefix_nick=True)