2015-01-22 20:09:04 +00:00
#!/usr/bin/python
# http://wiki.shellium.org/w/Writing_an_IRC_bot_in_Python
# Import some necessary libraries.
import socket
import os
import sys
from optparse import OptionParser
import fileinput
import random
import time
import re
import operator
import inflect
2018-10-08 17:19:07 -04:00
import util
2015-01-22 20:09:04 +00:00
parser = OptionParser ()
2018-10-05 16:02:38 -04:00
parser . add_option (
"-s" ,
"--server" ,
dest = "server" ,
2018-10-08 17:19:07 -04:00
default = "127.0.0.1:6667" ,
2018-10-05 16:02:38 -04:00
help = "the server to connect to" ,
metavar = "SERVER" ,
)
parser . add_option (
"-c" ,
"--channel" ,
dest = "channel" ,
default = "#bot_test" ,
help = "the channel to join" ,
metavar = "CHANNEL" ,
)
parser . add_option (
"-n" ,
"--nick" ,
dest = "nick" ,
default = "numberwang_bot" ,
help = "the nick to use" ,
metavar = "NICK" ,
)
2015-01-22 20:09:04 +00:00
( options , args ) = parser . parse_args ()
p = inflect . engine ()
2016-01-06 14:08:25 -05:00
LIMIT_GUESSING = True
2015-01-23 17:42:11 +00:00
MIN_ROUNDS = 5
MAX_ROUNDS = 12
2015-01-22 20:09:04 +00:00
SCORE_FILE = "numberwangscores.txt"
SHOW_TOP_NUM = 5
2015-01-29 21:05:37 +00:00
GOOD_CHAN = "#bots"
2015-01-22 20:09:04 +00:00
roundsLeft = 0
bonusRound = 0
guesses = 0
lastGuesser = ""
currentScores = {}
2018-10-05 16:02:38 -04:00
2015-01-22 20:09:04 +00:00
def resetGlobals ():
2018-10-05 16:02:38 -04:00
global roundsLeft
global bonusRound
global guesses
global lastGuesser
global currentScores
roundsLeft = 0
bonusRound = 0
guesses = 0
lastGuesser = ""
currentScores . clear ()
2015-01-22 20:09:04 +00:00
def start_numberwang ( channel , user ):
2018-10-05 16:02:38 -04:00
if channel != "#bots" :
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock ,
channel ,
"Numberwang has been disabled in {} due to spamminess. Please join {} to start a game." . format (
channel , GOOD_CHAN
),
2018-10-05 16:02:38 -04:00
)
2015-01-29 21:05:37 +00:00
return
2018-10-05 16:02:38 -04:00
print ( user + " started a game" )
2015-01-22 20:09:04 +00:00
resetGlobals ()
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , "It's time for Numberwang!" )
2015-01-22 20:09:04 +00:00
time . sleep ( 1 )
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , "Here's how to play:" )
2015-01-22 20:09:04 +00:00
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , "1. There are 10 rounds" )
util . sendmsg (
ircsock , channel , "2. Each round lasts 10 seconds. You're up against the clock!"
2018-10-05 16:02:38 -04:00
)
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock , channel , "3. Play your numbers, as long as they're between 0 and 99."
2018-10-05 16:02:38 -04:00
)
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , "4. That's Numberwang!" )
2015-01-22 20:09:04 +00:00
time . sleep ( 2 )
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , "Let's get started!" )
2015-01-22 20:09:04 +00:00
global roundsLeft
global bonusRound
2018-10-05 16:02:38 -04:00
roundsLeft = random . randint ( MIN_ROUNDS , MAX_ROUNDS )
bonusRound = random . randint ( 2 , roundsLeft - 1 )
print (
2018-10-08 17:19:07 -04:00
"There will be {} rounds with the bonus on round {} " . format (
str ( roundsLeft ), str ( roundsLeft - bonusRound + 1 )
)
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
def print_scores ( channel ):
scoreStrs = []
first = True
for name in currentScores :
2018-10-05 16:02:38 -04:00
scoreStrs . append (
2018-10-08 17:19:07 -04:00
" {} is {} on {} " . format (
name ,
( "also " if not first and random . randint ( 1 , 3 ) == 3 else "" ),
currentScores [ name ],
)
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
first = False
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , p . join ( scoreStrs ))
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
2015-01-22 20:09:04 +00:00
def guess_numberwang ( channel , user , messageText ):
global guesses
global lastGuesser
global currentScores
global roundsLeft
2018-10-05 16:02:38 -04:00
print ( user + " guessed '" + messageText + "'" )
guess = re . sub (
"[^0-9]" , "" , messageText . split ()[ 0 ]
) # must have a number in the first 'word'
if guess :
if LIMIT_GUESSING and user == lastGuesser :
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock ,
channel ,
" {} , you just guessed! Give another player a try!" . format ( user ),
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
else :
guesses += 1
lastGuesser = user
###CORRECT GUESS###
2018-10-05 16:02:38 -04:00
if (
random . randint ( 0 , 10 ) > 10 - guesses
): # the more guesses, the higher the probability
2015-01-22 20:09:04 +00:00
guesses = 0
lastGuesser = ""
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , " {} : THAT'S NUMBERWANG!" . format ( user ))
2018-10-05 16:02:38 -04:00
points = random . randint ( 2 , 10 ) * (
random . randint ( 2 , 4 ) if roundsLeft == bonusRound else 1
)
2015-01-22 20:09:04 +00:00
if user in currentScores . keys ():
currentScores [ user ] += points
else :
currentScores [ user ] = points
roundsLeft -= 1
time . sleep ( 2 )
2018-10-05 16:02:38 -04:00
if roundsLeft == 0 :
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock ,
channel ,
"Numberwang is now over. Thank you for playing!" ,
2018-10-05 16:02:38 -04:00
)
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , "Final scores:" )
2015-01-22 20:09:04 +00:00
print_scores ( channel )
save_scores ()
else :
print_scores ( channel )
newRoundStr = ""
2018-10-05 16:02:38 -04:00
if roundsLeft == 1 :
2015-01-22 20:09:04 +00:00
newRoundStr += "The last round is Wangernumb!"
2018-10-05 16:02:38 -04:00
elif roundsLeft == bonusRound :
2015-01-22 20:09:04 +00:00
newRoundStr += "**Bonus Round!**"
else :
newRoundStr += "New Round!"
2018-10-05 16:02:38 -04:00
if random . randint ( 1 , 10 ) > 8 :
2015-01-22 20:09:04 +00:00
newRoundStr += " Let's rotate the board!"
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock , channel , " {} Start guessing!" . format ( newRoundStr )
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
###INCORRECT GUESS###
else :
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock ,
channel ,
" {} , {} , {} Numberwang!" . format (
random . choice ([ "Sorry" , "I'm sorry" , "No" , "Nope" ]),
user ,
random . choice (
[
"that's not" ,
"that is not" ,
"that isn't" ,
"that is not" ,
"that won't make" ,
"that will not make" ,
]
),
),
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
def stop_numberwang ( channel , user ):
2018-10-05 16:02:38 -04:00
print ( user + " stopped a game" )
2015-01-22 20:09:04 +00:00
resetGlobals ()
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock ,
channel ,
"Numberwang has been stopped. No points have been awarded. {} is such a party pooper!" . format (
user
),
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
def save_scores ():
with open ( SCORE_FILE , "r+" ) as scorefile :
scores = scorefile . readlines ()
scorefile . seek ( 0 )
scorefile . truncate ()
2015-01-23 17:42:11 +00:00
for line in scores :
for name in currentScores :
2015-01-22 20:09:04 +00:00
score = line . strip ( " \n " ) . split ( "&^%" )
2018-10-05 16:02:38 -04:00
if score [ 0 ] == name :
2018-10-08 17:19:07 -04:00
line = " {} &^% {} \n " . format (
score [ 0 ], int ( score [ 1 ]) + currentScores [ name ]
2018-10-05 16:02:38 -04:00
)
2015-10-13 08:23:17 -05:00
del currentScores [ name ]
2015-01-23 17:42:11 +00:00
break
scorefile . write ( line )
2018-10-05 16:02:38 -04:00
for name in currentScores : # new wangers
2018-10-08 17:19:07 -04:00
scorefile . write ( " {} &^% {} \n " . format ( name , currentScores [ name ]))
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
2015-01-22 20:09:04 +00:00
def show_highscores ( channel ):
with open ( SCORE_FILE , "r" ) as scorefile :
scores = []
for line in scorefile . readlines ():
sline = line . strip ( " \n " ) . split ( "&^%" )
scores . append (( int ( sline [ 1 ]), sline [ 0 ]))
scores = sorted ( scores , reverse = True )[: SHOW_TOP_NUM ]
2018-10-08 17:19:07 -04:00
util . sendmsg ( ircsock , channel , "====TOP WANGERS====" )
2015-01-22 20:09:04 +00:00
for score in scores :
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock , channel , " :== ~ {} ( {} points!) ==" . format ( score [ 1 ], score [ 0 ])
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
def show_user_score ( channel , user ):
with open ( SCORE_FILE , "r" ) as scorefile :
for line in scorefile . readlines ():
score = line . strip ( " \n " ) . split ( "&^%" )
2018-10-05 16:02:38 -04:00
if user == score [ 0 ]:
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock ,
channel ,
" {} : Your global numberwang score is {} !" . format ( user , score [ 1 ]),
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
return
2018-10-05 16:02:38 -04:00
# if we don't find a score line
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock , channel , " {} You haven't scored any points yet!" . format ( user )
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
def rollcall ( channel ):
2018-10-08 17:19:07 -04:00
util . sendmsg (
ircsock ,
channel ,
" :Is it time for Numberwang? It might be! Start a new game with !numberwang or stop a current game with !wangernumb Get your score with !myscore and the list of top wangers with !topwangers" ,
2018-10-05 16:02:38 -04:00
)
2015-01-22 20:09:04 +00:00
def get_user_from_message ( msg ):
2018-10-05 16:02:38 -04:00
try :
i1 = msg . index ( ":" ) + 1
i2 = msg . index ( "!" )
return msg [ i1 : i2 ]
except ValueError :
return ""
2015-01-22 20:09:04 +00:00
def listen ():
2018-10-05 16:02:38 -04:00
while 1 :
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
ircmsg = ircsock . recv ( 2048 )
ircmsg = ircmsg . strip ( " \n\r " )
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
if ircmsg [: 4 ] == "PING" :
ping ( ircmsg . split ( " " )[ 1 ])
2015-01-22 20:09:04 +00:00
2018-10-08 17:19:07 -04:00
formatted = util . format_message ( ircmsg )
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
if "" == formatted :
continue
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
# print formatted
2015-01-22 20:09:04 +00:00
2018-10-08 17:19:07 -04:00
time , user , command , channel , messageText = formatted . split ( " \t " )
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
if ircmsg . find ( ":!numberwang" ) != - 1 and roundsLeft == 0 :
start_numberwang ( channel , user )
2015-01-29 21:05:37 +00:00
2018-10-05 16:02:38 -04:00
if channel == GOOD_CHAN :
if ircmsg . find ( ":!wangernumb" ) != - 1 and roundsLeft > 0 :
stop_numberwang ( channel , user )
if roundsLeft > 0 :
guess_numberwang ( channel , user , messageText )
2015-01-29 21:05:37 +00:00
2018-10-05 16:02:38 -04:00
if ircmsg . find ( ":!topwangers" ) != - 1 :
show_highscores ( channel )
if ircmsg . find ( ":!myscore" ) != - 1 :
show_user_score ( channel , user )
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
if ircmsg . find ( ":!rollcall" ) != - 1 :
rollcall ( channel )
2015-01-22 20:09:04 +00:00
2018-10-05 16:02:38 -04:00
sys . stdout . flush ()
time . sleep ( 1 )
2015-01-22 20:09:04 +00:00
ircsock = socket . socket ( socket . AF_INET , socket . SOCK_STREAM )
2018-10-08 17:19:07 -04:00
util . connect ( ircsock , options )
2015-01-22 20:09:04 +00:00
listen ()