2020-11-16 21:58:16 +00:00
import plugin , tasks , time , random , math
from bot import IRCLine
BOT = None
def respond ( event , msg , generic = False ) :
if not BOT : return None
target = event . target
prefix = " "
if target . startswith ( " # " ) :
prefix + = event . hostmask . nick
prefix + = " : "
else :
target = event . hostmask . nick
if generic : prefix = " "
BOT . socket . send ( IRCLine ( " PRIVMSG " , target , " : " + prefix + msg ) . line )
pool = tasks . TaskPool ( )
bungame_data = plugin . DictData ( " bungame.json " )
if " bun_active " not in bungame_data : bungame_data [ " bun_active " ] = False
if " bun_time " not in bungame_data : bungame_data [ " bun_time " ] = time . time ( )
if " buns " not in bungame_data : bungame_data [ " buns " ] = dict ( )
if " score_cache " not in bungame_data : bungame_data [ " score_cache " ] = dict ( )
if " association " not in bungame_data : bungame_data [ " association " ] = dict ( )
def check_bun_active ( channel ) :
""" Checks if a bun is active in channel.
Right now , this is a single - channel bot , but if I decide to make it a multichannel bot , this will make generalizing a lot easier . """
return bungame_data [ " bun_active " ]
def activate_bun ( channel ) :
""" Activates the bun in channel.
Again , just for generalizing if needed later . """
bungame_data [ " bun_time " ] = time . time ( )
bungame_data [ " bun_active " ] = True
def deactivate_bun ( channel ) :
""" Deactivates the bun in channel.
Again , just for generalizing if needed later . """
bungame_data [ " bun_time " ] = time . time ( )
bungame_data [ " bun_active " ] = False
2020-12-15 02:43:15 +00:00
# Base is such that b^(1 hour in seconds) = 3.
2020-11-17 01:35:53 +00:00
# 2020-11-16 - A 2 hour bun awards 6,322,008.86 points, base is lowered from b^(1 hour in seconds) = 1000.
2020-11-17 17:49:05 +00:00
# 2020-11-17 - A 4:46:01.66 bun awards 3 billion and a 6:08:09.27 awards over a trillion. Base is lowered from 100.
2020-12-03 15:34:43 +00:00
# 2020-12-03 - After some fun with really long buns, I decide enough is enough and lower the base even more. Base lowered from 10.
2020-12-15 02:43:15 +00:00
# 2020-12-14 - Late Monday night I decide to lower the base slightly, from 5.
2021-06-04 16:48:30 +00:00
# 2021-06-04 - I decide to lower the base from 3, after almost 6 months of just leaving it as-is.
2020-11-16 21:58:16 +00:00
# This is probably too much and too easily abused but hell we'll give it a shot.
2021-06-04 16:48:30 +00:00
BASE = 2 * * ( 1 / ( 60 * 60 ) )
2020-11-16 21:58:16 +00:00
def bun_score ( time_delta ) :
""" Generates the score for a bun. """
return BASE * * time_delta
def get_bun_time ( channel ) :
""" Returns the bun time of the channel. """
return bungame_data [ " bun_time " ]
def get_bun_score ( channel ) :
""" Gives the current score of the bun in channel. """
delta = time . time ( ) - get_bun_time ( channel )
return bun_score ( delta ) , delta
def redo_score_cache ( ) :
score_cache = dict ( )
for account in bungame_data [ " buns " ] . keys ( ) :
buns = bungame_data [ " buns " ] [ account ]
score = 0
for bun in buns :
# time delta is stored up to 4 digits precision
# really you shouldn't need more than that
score + = bun_score ( bun )
score_cache [ account ] = score
bungame_data [ " score_cache " ] = score_cache
def on_privmsg ( event ) :
# don't trigger on private messages
if not event . target . startswith ( " # " ) : return
# do association first, in case an error occurs elsewhere
2020-11-16 22:07:45 +00:00
if " account " in event . tags :
bungame_data [ " association " ] [ event . hostmask . nick ] = event . tags [ " account " ]
bungame_data . save ( )
2020-11-16 21:58:16 +00:00
if not check_bun_active ( event . target ) :
if random . random ( ) > ( 3 / 4 ) :
activate_bun ( event . target )
respond ( event , " A bun hops into the room. Hop, hop, hop, little bun! " , True )
def on_befriend ( event ) :
if not event . target . startswith ( " # " ) : return
if " account " not in event . tags :
respond ( event , " You need a NickServ account to participate in the bun game! (/msg NickServ help register) " )
return
if not check_bun_active ( event . target ) :
respond ( event , " You missed the bun! " )
return
account = event . tags [ " account " ]
score , final_delta = get_bun_score ( event . target )
deactivate_bun ( event . target )
first_bun = False
# add the bun to their account and regenerate the score cache
try :
bungame_data [ " buns " ] [ account ] . append ( final_delta )
except KeyError :
bungame_data [ " buns " ] [ account ] = [ final_delta ]
bungame_data . save ( )
redo_score_cache ( )
# now tell them about it
delta_r = round ( final_delta , 2 )
score_r = round ( score , 2 )
if first_bun :
2021-06-04 16:48:30 +00:00
respond ( event , f " Congratulations on your first bun! This bun has waited { delta_r : , } second(s), and is therefore worth { score_r : .2e } point(s)! " )
2020-11-16 21:58:16 +00:00
else :
2021-06-04 16:48:30 +00:00
respond ( event , f " This bun has waited { delta_r : , } second(s), and is therefore worth { score_r : .2e } point(s)! " )
2020-11-16 21:58:16 +00:00
def on_peek ( event ) :
if not event . target . startswith ( " # " ) : return
if not check_bun_active ( event . target ) :
respond ( event , " There is no bun active in this channel! " )
return
score , delta = get_bun_score ( event . target )
delta_r = round ( delta , 2 )
score_r = round ( score , 2 )
2021-06-04 16:48:30 +00:00
respond ( event , f " If you were to befriend the bun right now, it would have waited { delta_r : , } second(s), and would therefore be worth { score_r : .2e } point(s). " )
2020-11-16 21:58:16 +00:00
average = lambda l : sum ( l ) / len ( l )
def on_stats ( event ) :
if not event . target . startswith ( " # " ) : return
if " account " not in event . tags :
respond ( event , " You need a NickServ account to participate. (/msg NickServ help register) " )
return
account = event . tags [ " account " ]
buns = bungame_data [ " buns " ] . get ( account )
if not buns :
respond ( event , " You haven ' t befriended any buns! " )
return
bunc = len ( buns )
avg_bunt = average ( buns ) # *av*era*g*e *bun* *t*ime
2021-06-29 17:11:25 +00:00
stat_out = " You have befriended {:,} bun {} . Your average befriend time is {:,.02f} , and your current score is {:.2e} . " . format ( bunc , " s " if bunc != 1 else " " , avg_bunt , bungame_data [ " score_cache " ] . get ( account , 0 ) )
2020-11-16 21:58:16 +00:00
respond ( event , stat_out )
def on_top10 ( event ) :
mode = " score "
if event . parts and event . parts [ 0 ] in " score count time " . split ( ) :
mode = event . parts [ 0 ]
accounts = list ( bungame_data [ " buns " ] . keys ( ) )
if mode == " score " :
accounts . sort ( key = lambda k : bungame_data [ " score_cache " ] . get ( k , 0 ) , reverse = True )
accounts = [ ( bungame_data [ " association " ] . get ( account , account ) , bungame_data [ " score_cache " ] [ account ] ) for account in accounts [ : 10 ] ]
elif mode == " count " :
accounts . sort ( key = lambda k : len ( bungame_data [ " buns " ] . get ( k , [ ] ) ) , reverse = True )
accounts = [ ( bungame_data [ " association " ] . get ( account , account ) , len ( bungame_data [ " buns " ] . get ( account , [ ] ) ) ) for account in accounts [ : 10 ] ]
elif mode == " time " :
accounts . sort ( key = lambda k : average ( bungame_data [ " buns " ] . get ( k , [ 0 ] ) ) , reverse = True )
accounts = [ ( bungame_data [ " association " ] . get ( account , account ) , average ( bungame_data [ " buns " ] . get ( account , [ 0 ] ) ) ) for account in accounts [ : 10 ] ]
out = f " Top 10 in { mode } : "
for account in accounts :
if mode == " count " :
2020-11-17 01:33:30 +00:00
out + = " {act[0]} ( {act[1]:n} ) " . format ( act = account )
2020-11-16 21:58:16 +00:00
else :
2021-06-04 16:48:30 +00:00
out + = " {act[0]} ( {act[1]:.2e} ) " . format ( act = account )
2020-11-16 21:58:16 +00:00
out + = " , "
out = out [ : - 2 ]
respond ( event , out )
def admin_redocache ( event ) :
redo_score_cache ( )
respond ( event , " Score cache redone! " )
2021-06-30 07:53:30 +00:00
def admin_merge ( event ) :
try :
target , from_ = event . parts
except :
respond ( event , " Syntax: admin merge <target> <from> " )
return
bungame_data [ " buns " ] [ target ] . extend ( bungame_data [ " buns " ] [ from_ ] )
bungame_data . save ( )
del bungame_data [ " buns " ] [ from_ ]
bungame_data . save ( )
redo_score_cache ( )
respond ( event , " Should be merged now! " )
2020-11-16 21:58:16 +00:00
def register ( bot ) :
global BOT
BOT = bot
bot . event_manager . on ( " privmsg " , on_privmsg )
bot . event_manager . on ( " command_befriend " , on_befriend )
bot . event_manager . on ( " command_bef " , on_befriend )
bot . event_manager . on ( " command_hug " , on_befriend )
bot . event_manager . on ( " command_peek " , on_peek )
bot . event_manager . on ( " command_stats " , on_stats )
bot . event_manager . on ( " command_top10 " , on_top10 )
bot . event_manager . on ( " admin_redocache " , admin_redocache )
2021-06-30 07:53:30 +00:00
bot . event_manager . on ( " admin_merge " , admin_merge )