Code: Select all
from collections import defaultdict
PLAYERS = ['Feirei', 'Honey bee', 'ika', 'Klazam', 'mathcam', 'MTD', 'Natirasha', 'Save the Dragons', 'Untrod Tripod', 'Wolfy', 'xRECKONERx']
MAFIA = ['Feirei', 'Klazam', 'MTD']
PLAYER_BALLOTS = [('Mafia',
['ika', 'Save the Dragons', 'Natirasha', 'Honey bee', 'Wolfy', 'xRECKONERx', 'mathcam', 'Untrod Tripod', 'Feirei', 'MTD', 'Klazam']),
('xRECKONERx',
['ika', 'Untrod Tripod', 'Feirei', 'Wolfy', 'Natirasha', 'Honey bee', 'Klazam', 'mathcam', 'MTD', 'Save the Dragons', 'xRECKONERx']),
('Untrod Tripod',
['Save the Dragons', 'Wolfy', 'Feirei', 'Honey bee', 'Klazam', 'mathcam', 'MTD', 'ika', 'Natirasha', 'xRECKONERx', 'Untrod Tripod']),
('Honey bee',
['Feirei', 'MTD', 'Wolfy', 'mathcam', 'Untrod Tripod', 'Klazam', 'xRECKONERx', 'Save the Dragons', 'Natirasha', 'ika', 'Honey bee']),
('Natirasha',
['Untrod Tripod', 'ika', 'MTD', 'Save the Dragons', 'Feirei', 'Wolfy', 'xRECKONERx', 'Klazam', 'Honey bee', 'mathcam', 'Natirasha']),
('ika',
['Feirei', 'Honey bee', 'Save the Dragons', 'Klazam', 'mathcam', 'Natirasha', 'MTD', 'Untrod Tripod', 'Wolfy', 'xRECKONERx', 'ika']),
('mathcam',
['Feirei', 'ika', 'MTD', 'Honey bee', 'Klazam', 'Natirasha', 'Untrod Tripod', 'Wolfy', 'xRECKONERx', 'Save the Dragons', 'mathcam']),
('Save the Dragons',
['xRECKONERx', 'Untrod Tripod', 'Wolfy', 'MTD', 'Klazam', 'Natirasha', 'Honey bee', 'mathcam', 'Feirei', 'ika', 'Save the Dragons']),
('Wolfy',
['Untrod Tripod', 'ika', 'Save the Dragons', 'mathcam', 'Natirasha', 'Feirei', 'xRECKONERx', 'Klazam', 'MTD', 'Honey bee', 'Wolfy']),
]
def verify_ballots(player_list, ballots):
vote_error = '{0} is voting for "{1}", who does not appear to be in the game.'
length_error = '{0} does not appear to be voting for the correct number of players.'
errors = []
for voter, votees in ballots:
errors += [vote_error.format(voter, x) for x in votees \
if x not in player_list]
if (len(votees) != 11) or (len(set(votees)) != 11):
errors.append(length_error.format(voter))
return errors
def tablefy_ballots(ballots, eliminated_players, dead_players):
ignored_players = eliminated_players + dead_players
header_list = ['[header]{}[/header]'.format(x[0]) for x in ballots \
if x[0] not in dead_players]
header = '[row]{}[/row]'.format(''.join(header_list))
votes_list = [[x for x in ballot[1] if x not in ignored_players] \
for ballot in ballots if ballot[0] not in dead_players]
flipped_votes_list = zip(*votes_list)
rows = [['[cell]{}[/cell]'.format(x) for x in row] for row in flipped_votes_list]
flattened = ['[row]{}[/row]'.format(''.join(row)) for row in rows]
body = ''.join(flattened)
table = '[table]{header}{body}[/table]'.format(header=header, body=body)
return table
class IRV_Game:
def __init__(self, player_list, ballots):
errors = verify_ballots(player_list + ['Mafia'], ballots)
if errors:
print errors
raise Exception('There were errors in the ballots. Please try again.')
self.player_list = player_list
self.ballots = ballots
self.eliminated_players = []
self.dead_players = []
self.log = []
@property
def vote_table(self):
return tablefy_ballots(self.ballots, self.eliminated_players, \
self.dead_players)
@property
def current_vote_count(self):
ignored_players = self.eliminated_players + self.dead_players
votes = {ballot[0]: [x for x in ballot[1] if x not in ignored_players][0] \
for ballot in self.ballots if ballot[0] not in self.dead_players}
vote_count_dict = defaultdict(list)
for k, v in votes.iteritems():
vote_count_dict[v].append(k)
vcl = sorted(vote_count_dict.items(), key=lambda x: len(x[1]), reverse=True)
header = "[b][u]Vote Count[/u][/b]\n"
body = '\n'.join(['[b]{votee}[/b] ({num}): {voters}'.format(votee=x[0],
num=len(x[1]),
voters=', '.join(x[1])) for x in vcl])
return header + body
@property
def status(self):
return self.vote_table + '\n' + self.current_vote_count
@property
def condorcet(self):
votes = [[x for x in ballot[1] if x not in ignored_players] \
for ballot in self.ballots if ballot[0] not in self.dead_players]
result = ''
for vote in votes:
result += '>'.join(vote) + '\n'
return result
def log_message(self, message, include_vc=False):
self.log.append(message)
print message
if include_vc:
self.log.append(self.vote_table + '/n' + self.current_vote_count)
def kill_player(self, player_name):
if player_name in self.player_list:
self.dead_players.append(player_name)
self.eliminated_players = []
self.log_message('The dead players are now: {}'.format(', '.join(self.dead_players)))
else:
raise Exception('That player is not in the game. Player not killed.')
def eliminate_player(self, player_name):
if player_name in self.player_list:
self.eliminated_players.append(player_name)
self.log_message('The players eliminated from voting contention are now: {}'.format(', '.join(self.eliminated_players)), include_vc=True)
else:
raise Exception('That player is not in the game. Player not eliminated.')
def eliminate_all_but(self, *all_but_list):
for player in all_but_list:
if player not in self.player_list:
raise Exception('{} is not in the list of players.'.format(player))
self.eliminated_players = [x for x in self.player_list if x not in all_but_list]
self.log_message('The players eliminated from voting contention are now: {}'.format(', '.join(self.eliminated_players)), include_vc=True)
def reset(self):
self.eliminated_players = []
self.dead_players = []
self.log = []
game = IRV_Game(PLAYERS, PLAYER_BALLOTS)