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()
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()
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)
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)