1### 2# Copyright (c) 2003-2005, Jeremiah Fincher 3# Copyright (c) 2010, James McCoy 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 9# * Redistributions of source code must retain the above copyright notice, 10# this list of conditions, and the following disclaimer. 11# * Redistributions in binary form must reproduce the above copyright notice, 12# this list of conditions, and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# * Neither the name of the author of this software nor the name of 15# contributors to this software may be used to endorse or promote products 16# derived from this software without specific prior written consent. 17# 18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28# POSSIBILITY OF SUCH DAMAGE. 29### 30 31import re 32import random 33 34 35import supybot.utils as utils 36from supybot.commands import * 37import supybot.ircmsgs as ircmsgs 38import supybot.ircutils as ircutils 39import supybot.callbacks as callbacks 40from supybot.i18n import PluginInternationalization, internationalizeDocstring 41_ = PluginInternationalization('Games') 42 43 44class Games(callbacks.Plugin): 45 """This plugin provides some small games like (Russian) roulette, 46 eightball, monologue, coin and dice.""" 47 @internationalizeDocstring 48 def coin(self, irc, msg, args): 49 """takes no arguments 50 51 Flips a coin and returns the result. 52 """ 53 if random.randrange(0, 2): 54 irc.reply(_('heads')) 55 else: 56 irc.reply(_('tails')) 57 coin = wrap(coin) 58 59 @internationalizeDocstring 60 def dice(self, irc, msg, args, m): 61 """<dice>d<sides> 62 63 Rolls a die with <sides> number of sides <dice> times. 64 For example, 2d6 will roll 2 six-sided dice; 10d10 will roll 10 65 ten-sided dice. 66 """ 67 (dice, sides) = list(map(int, m.groups())) 68 if dice > 1000: 69 irc.error(_('You can\'t roll more than 1000 dice.')) 70 elif sides > 100: 71 irc.error(_('Dice can\'t have more than 100 sides.')) 72 elif sides < 3: 73 irc.error(_('Dice can\'t have fewer than 3 sides.')) 74 else: 75 L = [0] * dice 76 for i in range(dice): 77 L[i] = random.randrange(1, sides+1) 78 irc.reply(format('%L', [str(x) for x in L])) 79 _dicere = re.compile(r'^(\d+)d(\d+)$') 80 dice = wrap(dice, [('matches', _dicere, 81 _('Dice must be of the form <dice>d<sides>'))]) 82 83 # The list of words and algorithm are pulled straight the mozbot 84 # MagicEightBall.bm module: http://tinyurl.com/7ytg7 85 _positive = _('It is possible.|Yes!|Of course.|Naturally.|Obviously.|' 86 'It shall be.|The outlook is good.|It is so.|' 87 'One would be wise to think so.|' 88 'The answer is certainly yes.') 89 _negative = _('In your dreams.|I doubt it very much.|No chance.|' 90 'The outlook is poor.|Unlikely.|' 91 'About as likely as pigs flying.|You\'re kidding, right?|' 92 'NO!|NO.|No.|The answer is a resounding no.') 93 _unknown = _('Maybe...|No clue.|_I_ don\'t know.|' 94 'The outlook is hazy, please ask again later.|' 95 'What are you asking me for?|Come again?|' 96 'You know the answer better than I.|' 97 'The answer is def-- oooh! shiny thing!') 98 99 def _checkTheBall(self, questionLength): 100 if questionLength % 3 == 0: 101 catalog = self._positive 102 elif questionLength % 3 == 1: 103 catalog = self._negative 104 else: 105 catalog = self._unknown 106 return utils.iter.choice(catalog.split('|')) 107 108 @internationalizeDocstring 109 def eightball(self, irc, msg, args, text): 110 """[<question>] 111 112 Ask a question and the answer shall be provided. 113 """ 114 if text: 115 irc.reply(self._checkTheBall(len(text))) 116 else: 117 irc.reply(self._checkTheBall(random.randint(0, 2))) 118 eightball = wrap(eightball, [additional('text')]) 119 120 _rouletteChamber = random.randrange(0, 6) 121 _rouletteBullet = random.randrange(0, 6) 122 @internationalizeDocstring 123 def roulette(self, irc, msg, args, spin): 124 """[spin] 125 126 Fires the revolver. If the bullet was in the chamber, you're dead. 127 Tell me to spin the chambers and I will. 128 """ 129 if spin: 130 self._rouletteBullet = random.randrange(0, 6) 131 irc.reply(_('*SPIN* Are you feeling lucky?'), prefixNick=False) 132 return 133 channel = msg.args[0] 134 if self._rouletteChamber == self._rouletteBullet: 135 self._rouletteBullet = random.randrange(0, 6) 136 self._rouletteChamber = random.randrange(0, 6) 137 if irc.nick in irc.state.channels[channel].ops or \ 138 irc.nick in irc.state.channels[channel].halfops: 139 irc.queueMsg(ircmsgs.kick(channel, msg.nick, 'BANG!')) 140 else: 141 irc.reply(_('*BANG* Hey, who put a blank in here?!'), 142 prefixNick=False) 143 irc.reply(_('reloads and spins the chambers.'), action=True) 144 else: 145 irc.reply(_('*click*')) 146 self._rouletteChamber += 1 147 self._rouletteChamber %= 6 148 roulette = wrap(roulette, ['public', additional(('literal', 'spin'))]) 149 150 @internationalizeDocstring 151 def monologue(self, irc, msg, args, channel): 152 """[<channel>] 153 154 Returns the number of consecutive lines you've sent in <channel> 155 without being interrupted by someone else (i.e. how long your current 156 'monologue' is). <channel> is only necessary if the message isn't sent 157 in the channel itself. 158 """ 159 i = 0 160 for m in reversed(irc.state.history): 161 if m.command != 'PRIVMSG': 162 continue 163 if not m.prefix: 164 continue 165 if not ircutils.strEqual(m.args[0], channel): 166 continue 167 if msg.prefix == m.prefix: 168 i += 1 169 else: 170 break 171 irc.reply(format(_('Your current monologue is at least %n long.'), 172 (i, _('line')))) 173 monologue = wrap(monologue, ['channel']) 174 175Class = Games 176 177 178# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: 179