1010from cloudbot import hook
1111from cloudbot .event import EventType
1212from cloudbot .util import database
13+ from cloudbot .util .formatting import pluralize
1314
1415duck_tail = "・゜゜・。。・゜゜"
1516duck = ["\_o< " , "\_O< " , "\_0< " , "\_\u00f6 < " , "\_\u00f8 < " , "\_\u00f3 < " ]
@@ -123,7 +124,7 @@ def incrementMsgCounter(event, conn):
123124
124125
125126@hook .command ("starthunt" , autohelp = False , permissions = ["chanop" , "op" , "botcontrol" ])
126- def start_hunt (bot , chan , message , conn ):
127+ def start_hunt (chan , message , conn ):
127128 """- This command starts a duckhunt in your channel, to stop the hunt use .stophunt"""
128129 global game_status
129130 if chan in opt_out :
@@ -166,7 +167,7 @@ def stop_hunt(chan, conn):
166167
167168
168169@hook .command ("duckkick" , permissions = ["chanop" , "op" , "botcontrol" ])
169- def no_duck_kick (text , chan , conn , notice ):
170+ def no_duck_kick (text , chan , conn , notice_doc ):
170171 """<enable|disable> - If the bot has OP or half-op in the channel you can specify .duckkick enable|disable so that people are kicked for shooting or befriending a non-existent goose. Default is off."""
171172 global game_status
172173 if chan in opt_out :
@@ -178,7 +179,7 @@ def no_duck_kick(text, chan, conn, notice):
178179 game_status [conn .name ][chan ]['no_duck_kick' ] = 0
179180 return "kicking for non-existent ducks has been disabled."
180181 else :
181- notice ( no_duck_kick . __doc__ )
182+ notice_doc ( )
182183 return
183184
184185
@@ -192,11 +193,11 @@ def generate_duck():
192193 dnoise = random .choice (duck_noise )
193194 rn = random .randint (1 , len (dnoise ) - 1 )
194195 dnoise = dnoise [:rn ] + u'\u200b ' + dnoise [rn :]
195- return ( dtail , dbody , dnoise )
196+ return dtail , dbody , dnoise
196197
197198
198199@hook .periodic (11 , initial_interval = 11 )
199- def deploy_duck (message , bot ):
200+ def deploy_duck (bot ):
200201 global game_status
201202 for network in game_status :
202203 if network not in bot .connections :
@@ -210,17 +211,13 @@ def deploy_duck(message, bot):
210211 next_duck = game_status [network ][chan ]['next_duck_time' ]
211212 chan_messages = game_status [network ][chan ]['messages' ]
212213 chan_masks = game_status [network ][chan ]['masks' ]
213- if active == 1 and duck_status == 0 and next_duck <= time () and chan_messages >= MSG_DELAY and len (chan_masks ) >= MASK_REQ :
214+ if active == 1 and duck_status == 0 and next_duck <= time () and chan_messages >= MSG_DELAY and len (
215+ chan_masks ) >= MASK_REQ :
214216 # deploy a duck to channel
215217 game_status [network ][chan ]['duck_status' ] = 1
216218 game_status [network ][chan ]['duck_time' ] = time ()
217219 dtail , dbody , dnoise = generate_duck ()
218220 conn .message (chan , "{}{}{}" .format (dtail , dbody , dnoise ))
219- # Leave this commented out for now. I haven't decided how to make ducks leave.
220- # if active == 1 and duck_status == 1 and game_status[network][chan]['flyaway'] <= int(time()):
221- # conn.message(chan, "The duck flew away.")
222- # game_status[network][chan]['duck_status'] = 2
223- # set_ducktime(chan, conn)
224221 continue
225222 continue
226223
@@ -277,139 +274,113 @@ def dbupdate(nick, chan, db, conn, shoot, friend):
277274 db .commit ()
278275
279276
280- @hook .command ("bang" , autohelp = False )
281- def bang (nick , chan , message , db , conn , notice ):
282- """- when there is a duck on the loose use this command to shoot it."""
283- global game_status , scripters
284- if chan in opt_out :
285- return
286- network = conn .name
287- score = ""
288- out = ""
289- miss = ["WHOOSH! You missed the duck completely!" , "Your gun jammed!" , "Better luck next time." ,
290- "WTF?! Who are you, Kim Jong Un firing missiles? You missed." ]
291- if not game_status [network ][chan ]['game_on' ]:
292- return "There is no activehunt right now. Use .starthunt to start a game."
293- elif game_status [network ][chan ]['duck_status' ] != 1 :
294- if game_status [network ][chan ]['no_duck_kick' ] == 1 :
295- out = "KICK {} {} :There is no duck! What are you shooting at?" .format (chan , nick )
296- conn .send (out )
297- return
298- return "There is no duck. What are you shooting at?"
277+ def update_score (nick , chan , db , conn , shoot = 0 , friend = 0 ):
278+ score = db .execute (select ([table .c .shot , table .c .befriend ])
279+ .where (table .c .network == conn .name )
280+ .where (table .c .chan == chan .lower ())
281+ .where (table .c .name == nick .lower ())).fetchone ()
282+ if score :
283+ score = score [0 ]
284+ score += 1
285+ dbupdate (nick , chan , db , conn , score [0 ] + shoot , score [1 ] + friend )
299286 else :
300- game_status [network ][chan ]['shoot_time' ] = time ()
301- deploy = game_status [network ][chan ]['duck_time' ]
302- shoot = game_status [network ][chan ]['shoot_time' ]
303- if nick .lower () in scripters :
304- if scripters [nick .lower ()] > shoot :
305- notice ("You are in a cool down period, you can try again in {} seconds." .format (
306- str (scripters [nick .lower ()] - shoot )))
307- return
308- chance = hit_or_miss (deploy , shoot )
309- if not random .random () <= chance and chance > .05 :
310- out = random .choice (miss ) + " You can try again in 7 seconds."
311- scripters [nick .lower ()] = shoot + 7
312- return out
313- if chance == .05 :
314- out += "You pulled the trigger in {} seconds, that's mighty fast. Are you sure you aren't a script? Take a 2 hour cool down." .format (
315- str (shoot - deploy ))
316- scripters [nick .lower ()] = shoot + 7200
317- if not random .random () <= chance :
318- return random .choice (miss ) + " " + out
319- else :
320- message (out )
321- game_status [network ][chan ]['duck_status' ] = 2
322- try :
323- score = db .execute (select ([table .c .shot ])
324- .where (table .c .network == conn .name )
325- .where (table .c .chan == chan .lower ())
326- .where (table .c .name == nick .lower ())).fetchone ()
327- if score :
328- score = score [0 ]
329- score += 1
330- dbupdate (nick , chan , db , conn , score , 0 )
331- else :
332- score = 1
333- dbadd_entry (nick , chan , db , conn , score , 0 )
334- except DatabaseError :
335- game_status [network ][chan ]['duck_status' ] = 1
336- raise
337-
338- timer = "{:.3f}" .format (shoot - deploy )
339- duck = "duck" if score == 1 else "ducks"
340- message ("{} you shot a duck in {} seconds! You have killed {} {} in {}." .format (nick , timer , score , duck , chan ))
341- set_ducktime (chan , conn .name )
287+ dbadd_entry (nick , chan , db , conn , shoot , friend )
342288
343289
344- @hook .command ("befriend" , autohelp = False )
345- def befriend (nick , chan , message , db , conn , notice ):
346- """- when there is a duck on the loose use this command to befriend it before someone else shoots it."""
290+ def attack (nick , chan , message , db , conn , notice , attack ):
347291 global game_status , scripters
348292 if chan in opt_out :
349293 return
294+
350295 network = conn .name
296+ status = game_status [network ][chan ]
297+
351298 out = ""
352- score = ""
353- miss = ["The duck didn't want to be friends, maybe next time." ,
299+ if attack == "shoot" :
300+ miss = [
301+ "WHOOSH! You missed the duck completely!" , "Your gun jammed!" ,
302+ "Better luck next time." ,
303+ "WTF?! Who are you, Kim Jong Un firing missiles? You missed."
304+ ]
305+ no_duck = "There is no duck! What are you shooting at?"
306+ msg = "{} you shot a duck in {:.3f} seconds! You have killed {} in {}."
307+ scripter_msg = "You pulled the trigger in {:.3f} seconds, that's mighty fast. Are you sure you aren't a script? Take a 2 hour cool down."
308+ attack_type = "shoot"
309+ else :
310+ miss = [
311+ "The duck didn't want to be friends, maybe next time." ,
354312 "Well this is awkward, the duck needs to think about it." ,
355313 "The duck said no, maybe bribe it with some pizza? Ducks love pizza don't they?" ,
356- "Who knew ducks could be so picky?" ]
357- if not game_status [network ][chan ]['game_on' ]:
314+ "Who knew ducks could be so picky?"
315+ ]
316+ no_duck = "You tried befriending a non-existent duck. That's freaking creepy."
317+ msg = "{} you befriended a duck in {:.3f} seconds! You have made friends with {} in {}."
318+ scripter_msg = "You tried friending that duck in {:.3f} seconds, that's mighty fast. Are you sure you aren't a script? Take a 2 hour cool down."
319+ attack_type = "friend"
320+
321+ if not status ['game_on' ]:
358322 return "There is no hunt right now. Use .starthunt to start a game."
359- elif game_status [network ][chan ]['duck_status' ] != 1 :
360- if game_status [network ][chan ]['no_duck_kick' ] == 1 :
361- out = "KICK {} {} :You tried befriending a non-existent duck. That's fucking creepy." .format (chan , nick )
362- conn .send (out )
323+ elif status ['duck_status' ] != 1 :
324+ if status ['no_duck_kick' ] == 1 :
325+ conn .cmd ("KICK" , chan , nick , no_duck )
363326 return
364- return "You tried befriending a non-existent duck. That's freaking creepy."
327+
328+ return no_duck
365329 else :
366- game_status [ network ][ chan ] ['shoot_time' ] = time ()
367- deploy = game_status [ network ][ chan ] ['duck_time' ]
368- shoot = game_status [ network ][ chan ] ['shoot_time' ]
330+ status ['shoot_time' ] = time ()
331+ deploy = status ['duck_time' ]
332+ shoot = status ['shoot_time' ]
369333 if nick .lower () in scripters :
370334 if scripters [nick .lower ()] > shoot :
371- notice ("You are in a cool down period, you can try again in {} seconds." .format (
372- str (scripters [nick .lower ()] - shoot )))
335+ notice (
336+ "You are in a cool down period, you can try again in {:.3f} seconds." .format (
337+ scripters [nick .lower ()] - shoot
338+ )
339+ )
373340 return
341+
374342 chance = hit_or_miss (deploy , shoot )
375343 if not random .random () <= chance and chance > .05 :
376344 out = random .choice (miss ) + " You can try again in 7 seconds."
377345 scripters [nick .lower ()] = shoot + 7
378346 return out
347+
379348 if chance == .05 :
380- out += "You tried friending that duck in {} seconds, that's mighty fast. Are you sure you aren't a script? Take a 2 hour cool down." .format (
381- str (shoot - deploy ))
349+ out += scripter_msg .format (shoot - deploy )
382350 scripters [nick .lower ()] = shoot + 7200
383351 if not random .random () <= chance :
384352 return random .choice (miss ) + " " + out
385353 else :
386354 message (out )
387355
388- game_status [ network ][ chan ] ['duck_status' ] = 2
356+ status ['duck_status' ] = 2
389357 try :
390- score = db .execute (select ([table .c .befriend ])
391- .where (table .c .network == conn .name )
392- .where (table .c .chan == chan .lower ())
393- .where (table .c .name == nick .lower ())).fetchone ()
394- if score :
395- score = score [0 ]
396- score += 1
397- dbupdate (nick , chan , db , conn , 0 , score )
398- else :
399- score = 1
400- dbadd_entry (nick , chan , db , conn , 0 , score )
358+ score = 1
359+ args = {
360+ attack_type : score
361+ }
362+
363+ update_score (nick , chan , db , conn , ** args )
401364 except DatabaseError :
402- game_status [ network ][ chan ] ['duck_status' ] = 1
365+ status ['duck_status' ] = 1
403366 raise
404367
405- duck = "duck" if score == 1 else "ducks"
406- timer = "{:.3f}" .format (shoot - deploy )
407- message (
408- "{} you befriended a duck in {} seconds! You have made friends with {} {} in {}." .format (nick , timer , score ,
409- duck , chan ))
368+ message (msg .format (nick , shoot - deploy , pluralize (score , "duck" ), chan ))
410369 set_ducktime (chan , conn .name )
411370
412371
372+ @hook .command ("bang" , autohelp = False )
373+ def bang (nick , chan , message , db , conn , notice ):
374+ """- when there is a duck on the loose use this command to shoot it."""
375+ return attack (nick , chan , message , db , conn , notice , "shoot" )
376+
377+
378+ @hook .command ("befriend" , autohelp = False )
379+ def befriend (nick , chan , message , db , conn , notice ):
380+ """- when there is a duck on the loose use this command to befriend it before someone else shoots it."""
381+ return attack (nick , chan , message , db , conn , notice , "befriend" )
382+
383+
413384def smart_truncate (content , length = 320 , suffix = '...' ):
414385 if len (content ) <= length :
415386 return content
0 commit comments