Acro: ported to ircbot v2. deleted
This commit is contained in:
parent
8fe5dbc0d3
commit
fccb5f3fb3
@ -1,365 +0,0 @@
|
||||
"""
|
||||
Acro - An acromania style game for IRC
|
||||
Copyright (C) 2012 Brian S. Stephan
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import random
|
||||
import re
|
||||
import thread
|
||||
import time
|
||||
|
||||
from extlib import irclib
|
||||
|
||||
from Module import Module
|
||||
|
||||
class Acro(Module):
|
||||
|
||||
class AcroGame(object):
|
||||
|
||||
"""Track game details."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize basic stuff."""
|
||||
|
||||
# running state
|
||||
self.state = 0
|
||||
self.quit = False
|
||||
self.scores = dict()
|
||||
self.rounds = []
|
||||
self.channel = ''
|
||||
|
||||
class AcroRound(object):
|
||||
|
||||
"""Track a particular round of a game."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize basic stuff."""
|
||||
|
||||
self.acro = ""
|
||||
self.submissions = dict()
|
||||
self.sub_shuffle = []
|
||||
self.votes = dict()
|
||||
|
||||
# default options
|
||||
self.seconds_to_submit = 60
|
||||
self.seconds_to_vote = 45
|
||||
self.seconds_to_submit_step = 10
|
||||
self.seconds_to_pause = 5
|
||||
|
||||
"""
|
||||
Play a game where users come up with silly definitions for randomly-generated
|
||||
acronyms.
|
||||
"""
|
||||
|
||||
def __init__(self, irc, config):
|
||||
"""Set up the game tracking and such."""
|
||||
|
||||
# build regexes
|
||||
acroprefix = r"!acro"
|
||||
statuscmd = r"status"
|
||||
startcmd = r"start"
|
||||
submitcmd = r"submit"
|
||||
votecmd = r"vote"
|
||||
quitcmd = r"quit"
|
||||
|
||||
self.statusre = re.compile(r"^{0:s}\s+{1:s}$".format(acroprefix, statuscmd))
|
||||
self.startre = re.compile(r"^{0:s}\s+{1:s}$".format(acroprefix, startcmd))
|
||||
self.submitre = re.compile(r"^{0:s}\s+{1:s}\s+(.*)$".format(acroprefix, submitcmd))
|
||||
self.votere = re.compile(r"^{0:s}\s+{1:s}\s+(\d+)$".format(acroprefix, votecmd))
|
||||
self.quitre = re.compile(r"^{0:s}\s+{1:s}$".format(acroprefix, quitcmd))
|
||||
|
||||
# game state
|
||||
self.game = self.AcroGame()
|
||||
|
||||
Module.__init__(self, irc, config)
|
||||
|
||||
def do(self, connection, event, nick, userhost, what, admin_unlocked):
|
||||
"""Handle commands and inputs."""
|
||||
|
||||
target = event.target()
|
||||
|
||||
if self.statusre.search(what):
|
||||
return self.irc.reply(event, self.do_status(what))
|
||||
if self.startre.search(what):
|
||||
return self.irc.reply(event, self.do_start(target, what))
|
||||
if self.submitre.search(what):
|
||||
match = self.submitre.search(what)
|
||||
return self.irc.reply(event, self.do_submit(nick, match.group(1)))
|
||||
if self.votere.search(what):
|
||||
match = self.votere.search(what)
|
||||
return self.irc.reply(event, self.do_vote(nick, match.group(1)))
|
||||
if self.quitre.search(what):
|
||||
return self.irc.reply(event, self.do_quit(what))
|
||||
|
||||
def do_status(self, what):
|
||||
"""Return the status of the currently-running game, if there is one."""
|
||||
|
||||
if self.game.state == 0:
|
||||
return "there currently isn't a game running."
|
||||
else:
|
||||
return "the game is running."
|
||||
|
||||
def do_start(self, target, what):
|
||||
"""Start the game, notify the channel, and begin timers."""
|
||||
|
||||
if self.game.state != 0:
|
||||
return "the game is alredy running."
|
||||
else:
|
||||
if irclib.is_channel(target):
|
||||
self._start_new_game(target)
|
||||
else:
|
||||
return "you must start the game from a channel."
|
||||
|
||||
def do_submit(self, nick, what):
|
||||
"""Take a submission for an acro."""
|
||||
|
||||
return self._take_acro_submission(nick, what)
|
||||
|
||||
def do_vote(self, nick, what):
|
||||
"""Take a vote for an acro."""
|
||||
|
||||
return self._take_acro_vote(nick, what)
|
||||
|
||||
def do_quit(self, what):
|
||||
"""Quit the game after the current round ends."""
|
||||
|
||||
if self.game.state != 0:
|
||||
self.game.quit = True
|
||||
return "the game will end after the current round."
|
||||
|
||||
def thread_do_process_submissions(self, sleep_time):
|
||||
"""Wait for players to provide acro submissions, and then kick off voting."""
|
||||
|
||||
time.sleep(sleep_time)
|
||||
self._start_voting()
|
||||
|
||||
def thread_do_process_votes(self):
|
||||
"""Wait for players to provide votes, and then continue or quit."""
|
||||
|
||||
time.sleep(self.game.rounds[-1].seconds_to_vote)
|
||||
self._end_current_round()
|
||||
|
||||
def _start_new_game(self, channel):
|
||||
"""Begin a new game, which will have multiple rounds."""
|
||||
|
||||
self.game.state = 1
|
||||
self.game.channel = channel
|
||||
self.sendmsg(self.game.channel,
|
||||
"starting a new game of acro. it will run until you tell it to quit.")
|
||||
|
||||
self._start_new_round()
|
||||
|
||||
def _start_new_round(self):
|
||||
"""Start a new round for play."""
|
||||
|
||||
self.game.state = 2
|
||||
self.game.rounds.append(self.AcroRound())
|
||||
acro = self._generate_acro()
|
||||
self.game.rounds[-1].acro = acro
|
||||
sleep_time = self.game.rounds[-1].seconds_to_submit + (self.game.rounds[-1].seconds_to_submit_step * (len(acro)-3))
|
||||
|
||||
self.sendmsg(self.game.channel,
|
||||
"the round has started! your acronym is '{0:s}'. ".format(acro) +
|
||||
"submit within {0:d} seconds via !acro submit [meaning]".format(sleep_time))
|
||||
|
||||
thread.start_new_thread(self.thread_do_process_submissions, (sleep_time,))
|
||||
|
||||
def _generate_acro(self):
|
||||
"""
|
||||
Generate an acro to play with.
|
||||
|
||||
Letter frequencies pinched from
|
||||
http://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html
|
||||
"""
|
||||
|
||||
acro = []
|
||||
# generate acro 3-8 characters long
|
||||
for i in range(1, random.randint(4, 9)):
|
||||
letter = random.randint(1, 182303)
|
||||
if letter <= 21912:
|
||||
acro.append('E')
|
||||
elif letter <= 38499:
|
||||
acro.append('T')
|
||||
elif letter <= 53309:
|
||||
acro.append('A')
|
||||
elif letter <= 67312:
|
||||
acro.append('O')
|
||||
elif letter <= 80630:
|
||||
acro.append('I')
|
||||
elif letter <= 93296:
|
||||
acro.append('N')
|
||||
elif letter <= 104746:
|
||||
acro.append('S')
|
||||
elif letter <= 115723:
|
||||
acro.append('R')
|
||||
elif letter <= 126518:
|
||||
acro.append('H')
|
||||
elif letter <= 134392:
|
||||
acro.append('D')
|
||||
elif letter <= 141645:
|
||||
acro.append('L')
|
||||
elif letter <= 146891:
|
||||
acro.append('U')
|
||||
elif letter <= 151834:
|
||||
acro.append('C')
|
||||
elif letter <= 156595:
|
||||
acro.append('M')
|
||||
elif letter <= 160795:
|
||||
acro.append('F')
|
||||
elif letter <= 164648:
|
||||
acro.append('Y')
|
||||
elif letter <= 168467:
|
||||
acro.append('W')
|
||||
elif letter <= 172160:
|
||||
acro.append('G')
|
||||
elif letter <= 175476:
|
||||
acro.append('P')
|
||||
elif letter <= 178191:
|
||||
acro.append('B')
|
||||
elif letter <= 180210:
|
||||
acro.append('V')
|
||||
elif letter <= 181467:
|
||||
acro.append('K')
|
||||
elif letter <= 181782:
|
||||
acro.append('X')
|
||||
elif letter <= 181987:
|
||||
acro.append('Q')
|
||||
elif letter <= 182175:
|
||||
acro.append('J')
|
||||
elif letter <= 182303:
|
||||
acro.append('Z')
|
||||
|
||||
return "".join(acro)
|
||||
|
||||
def _take_acro_submission(self, nick, submission):
|
||||
"""Take an acro submission and record it."""
|
||||
|
||||
if self.game.state == 2:
|
||||
sub_acro = self._turn_text_into_acro(submission)
|
||||
|
||||
if sub_acro == self.game.rounds[-1].acro:
|
||||
self.game.rounds[-1].submissions[nick] = submission
|
||||
return "your submission has been recorded. it replaced any old submission for this round."
|
||||
else:
|
||||
return "the current acro is '{0:s}', not '{1:s}'".format(self.game.rounds[-1].acro, sub_acro)
|
||||
|
||||
def _turn_text_into_acro(self, text):
|
||||
"""Turn text into an acronym."""
|
||||
|
||||
words = text.split()
|
||||
acro = []
|
||||
for w in words:
|
||||
acro.append(w[0].upper())
|
||||
return "".join(acro)
|
||||
|
||||
def _start_voting(self):
|
||||
"""Begin the voting period."""
|
||||
|
||||
self.game.state = 3
|
||||
self.game.rounds[-1].sub_shuffle = self.game.rounds[-1].submissions.keys()
|
||||
random.shuffle(self.game.rounds[-1].sub_shuffle)
|
||||
self.sendmsg(self.game.channel,
|
||||
"here are the results. vote with !acro vote [number]")
|
||||
self._print_round_acros()
|
||||
|
||||
thread.start_new_thread(self.thread_do_process_votes, ())
|
||||
|
||||
def _print_round_acros(self):
|
||||
"""Take the current round's acros and spit them to the channel."""
|
||||
|
||||
i = 0
|
||||
for s in self.game.rounds[-1].sub_shuffle:
|
||||
self.log.debug(str(i) + " is " + s)
|
||||
self.sendmsg(self.game.channel,
|
||||
" {0:d}: {1:s}".format(i+1, self.game.rounds[-1].submissions[s]))
|
||||
i += 1
|
||||
|
||||
def _take_acro_vote(self, nick, vote):
|
||||
"""Take an acro vote and record it."""
|
||||
|
||||
if self.game.state == 3:
|
||||
acros = self.game.rounds[-1].submissions
|
||||
if int(vote) > 0 and int(vote) <= len(acros):
|
||||
self.log.debug(vote + " is " + self.game.rounds[-1].sub_shuffle[int(vote)-1])
|
||||
key = self.game.rounds[-1].sub_shuffle[int(vote)-1]
|
||||
|
||||
if key != nick:
|
||||
self.game.rounds[-1].votes[nick] = key
|
||||
return "your vote has been recorded. it replaced any old vote for this round."
|
||||
else:
|
||||
return "you can't vote for yourself!"
|
||||
else:
|
||||
return "you must vote for 1-{0:d}".format(len(acros))
|
||||
|
||||
def _end_current_round(self):
|
||||
"""Clean up and output for ending the current round."""
|
||||
|
||||
self.game.state = 4
|
||||
self.sendmsg(self.game.channel,
|
||||
"voting's over! here are the scores for the round:")
|
||||
self._print_round_scores()
|
||||
self._add_round_scores_to_game_scores()
|
||||
|
||||
# delay a bit
|
||||
time.sleep(self.game.rounds[-1].seconds_to_pause)
|
||||
self._continue_or_quit()
|
||||
|
||||
def _print_round_scores(self):
|
||||
"""For the acros in the round, find the votes for them."""
|
||||
|
||||
i = 0
|
||||
for s in self.game.rounds[-1].submissions.keys():
|
||||
votes = filter(lambda x: x == s, self.game.rounds[-1].votes.values())
|
||||
self.sendmsg(self.game.channel,
|
||||
" {0:d} ({1:s}): {2:d}".format(i+1, s, len(votes)))
|
||||
i += 1
|
||||
|
||||
def _add_round_scores_to_game_scores(self):
|
||||
"""Apply the final round scores to the totall scores for the game."""
|
||||
|
||||
for s in self.game.rounds[-1].votes.values():
|
||||
votes = filter(lambda x: x == s, self.game.rounds[-1].votes.values())
|
||||
if s in self.game.scores.keys():
|
||||
self.game.scores[s] = self.game.scores[s] + len(votes)
|
||||
else:
|
||||
self.game.scores[s] = len(votes)
|
||||
|
||||
def _continue_or_quit(self):
|
||||
"""Decide whether the game should continue or quit."""
|
||||
|
||||
if self.game.state == 4:
|
||||
if self.game.quit == True:
|
||||
self._end_game()
|
||||
else:
|
||||
self._start_new_round()
|
||||
|
||||
def _end_game(self):
|
||||
"""Clean up the entire game."""
|
||||
|
||||
self.game.state = 0
|
||||
self.game.quit = False
|
||||
self.sendmsg(self.game.channel,
|
||||
"game's over! here are the final scores:")
|
||||
self._print_game_scores()
|
||||
|
||||
def _print_game_scores(self):
|
||||
"""Print the final calculated scores."""
|
||||
|
||||
for s in self.game.scores.keys():
|
||||
self.sendmsg(self.game.channel,
|
||||
" {0:s}: {1:d}".format(s, self.game.scores[s]))
|
||||
|
||||
# vi:tabstop=4:expandtab:autoindent
|
Loading…
Reference in New Issue
Block a user