Browse Source

full threading for the reaper function

master
jcao219 13 years ago
parent
commit
5336a4b795
  1. 1
      decorators.py
  2. 51
      oyoyo/client.py
  3. 4
      oyoyo/ircevents.py
  4. 2
      oyoyo/parse.py
  5. 4
      var.py
  6. 168
      wolfgame.py

1
decorators.py

@ -35,7 +35,6 @@ def generate(fdict, **kwargs):
if (fn.owner_only != owner_only or if (fn.owner_only != owner_only or
fn.admin_only != admin_only): fn.admin_only != admin_only):
raise Exception("Command: "+x+" has non-matching protection levels!") raise Exception("Command: "+x+" has non-matching protection levels!")
fdict[x].append(innerf) fdict[x].append(innerf)
innerf.owner_only = owner_only innerf.owner_only = owner_only
innerf.raw_nick = raw_nick innerf.raw_nick = raw_nick

51
oyoyo/client.py

@ -1,4 +1,4 @@
# Copyright (c) 2008 Duncan Fordyce # Copyright (c) 2011 Duncan Fordyce, Jimmy Cao
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights # in the Software without restriction, including without limitation the rights
@ -18,11 +18,11 @@
import logging import logging
import socket import socket
import time import time
import threading
import traceback
from oyoyo.parse import parse_raw_irc_command from oyoyo.parse import parse_raw_irc_command
class IRCClientError(Exception):
pass
# Adapted from http://code.activestate.com/recipes/511490-implementation-of-the-token-bucket-algorithm/ # Adapted from http://code.activestate.com/recipes/511490-implementation-of-the-token-bucket-algorithm/
@ -107,6 +107,7 @@ class IRCClient(object):
self.port = None self.port = None
self.connect_cb = None self.connect_cb = None
self.blocking = True self.blocking = True
self.lock = threading.RLock()
self.tokenbucket = TokenBucket(3, 1.63) self.tokenbucket = TokenBucket(3, 1.63)
self.__dict__.update(kwargs) self.__dict__.update(kwargs)
@ -128,25 +129,26 @@ class IRCClient(object):
str they will be converted to bytes with the encoding specified by the str they will be converted to bytes with the encoding specified by the
'encoding' keyword argument (default 'utf8'). 'encoding' keyword argument (default 'utf8').
""" """
# Convert all args to bytes if not already with self.lock:
encoding = kwargs.get('encoding') or 'utf_8' # Convert all args to bytes if not already
bargs = [] encoding = kwargs.get('encoding') or 'utf_8'
for i,arg in enumerate(args): bargs = []
if isinstance(arg, str): for i,arg in enumerate(args):
bargs.append(bytes(arg, encoding)) if isinstance(arg, str):
elif isinstance(arg, bytes): bargs.append(bytes(arg, encoding))
bargs.append(arg) elif isinstance(arg, bytes):
elif arg is None: bargs.append(arg)
continue elif arg is None:
else: continue
raise Exception(('Refusing to send arg at index {1} of the args from '+ else:
'provided: {0}').format(repr([(type(arg), arg) raise Exception(('Refusing to send arg at index {1} of the args from '+
for arg in args]), i)) 'provided: {0}').format(repr([(type(arg), arg)
for arg in args]), i))
msg = bytes(" ", "utf_8").join(bargs)
logging.info('---> send "{0}"'.format(msg)) msg = bytes(" ", "utf_8").join(bargs)
logging.info('---> send "{0}"'.format(msg))
self.socket.send(msg + bytes("\r\n", "utf_8"))
self.socket.send(msg + bytes("\r\n", "utf_8"))
def connect(self): def connect(self):
""" initiates the connection to the server set in self.host:self.port """ initiates the connection to the server set in self.host:self.port
@ -214,9 +216,8 @@ class IRCClient(object):
self.command_handler[command](self, prefix,*largs) self.command_handler[command](self, prefix,*largs)
elif "" in self.command_handler: elif "" in self.command_handler:
self.command_handler[""](self, prefix, command, *largs) self.command_handler[""](self, prefix, command, *largs)
finally: except Exception as e:
# error will of already been logged by the handler traceback.print_exc()
pass
yield True yield True
finally: finally:

4
oyoyo/ircevents.py

@ -1,4 +1,4 @@
# Copyright (c) 2008 Duncan Fordyce # Copyright (c) 2011 Duncan Fordyce, Jimmy Cao
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights # in the Software without restriction, including without limitation the rights
@ -15,8 +15,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. # THE SOFTWARE.
# taken from python irclib.. who took it from...
# Numeric table mostly stolen from the Perl IRC module (Net::IRC).
numeric_events = { numeric_events = {
b"001": "welcome", b"001": "welcome",
b"002": "yourhost", b"002": "yourhost",

2
oyoyo/parse.py

@ -1,4 +1,4 @@
# Copyright (c) 2008 Duncan Fordyce # Copyright (c) 2011 Duncan Fordyce, Jimmy Cao
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights # in the Software without restriction, including without limitation the rights

4
var.py

@ -8,8 +8,8 @@ DRUNK_SHOTS_MULTIPLIER = 3
NIGHT_TIME_LIMIT = 90 NIGHT_TIME_LIMIT = 90
DAY_TIME_LIMIT = 333 DAY_TIME_LIMIT = 333
START_WITH_DAY = False START_WITH_DAY = False
KILL_IDLE_TIME = 0 #300 KILL_IDLE_TIME = 300
WARN_IDLE_TIME = 0 #180 WARN_IDLE_TIME = 180
GAME_COMMAND_ADMIN_ONLY = True GAME_COMMAND_ADMIN_ONLY = True
# HIT MISS SUICIDE # HIT MISS SUICIDE

168
wolfgame.py

@ -69,8 +69,7 @@ def connect_callback(cli):
var.LAST_SAID_TIME = {} var.LAST_SAID_TIME = {}
var.GAME_START_TIME = datetime.now() # for idle checker only var.GAME_START_TIME = datetime.now() # for idle checker only
var.GRAVEYARD = [] var.GRAVEYARD_LOCK = threading.RLock()
var.GRAVEYARD_LOCK = threading.Lock()
prepare_stuff() prepare_stuff()
@ -111,6 +110,7 @@ def reset(cli):
if var.TIMERS[1]: if var.TIMERS[1]:
var.TIMERS[1].cancel() var.TIMERS[1].cancel()
var.TIMERS[1] = None var.TIMERS[1] = None
var.GAME_ID = 0
cli.mode(chan, "-m") cli.mode(chan, "-m")
cmodes = [] cmodes = []
@ -565,110 +565,107 @@ def del_player(cli, nick, forced_death = False):
Returns: False if one side won. Returns: False if one side won.
arg: forced_death = True when lynched. arg: forced_death = True when lynched.
""" """
t = timetime() # time
cmode = [] with var.GRAVEYARD_LOCK:
cmode.append(("-v", nick)) if not var.GAME_ID or var.GAME_ID > t:
var.del_player(nick) # either game ended, or a new game has started.
ret = True return False
if var.PHASE == "join": cmode = []
# Died during the joining process as a person cmode.append(("-v", nick))
mass_mode(cli, cmode) var.del_player(nick)
return not chk_win(cli) ret = True
if var.PHASE != "join" and ret: if var.PHASE == "join":
# Died during the game, so quiet! # Died during the joining process as a person
if not is_fake_nick(nick): mass_mode(cli, cmode)
cmode.append(("+q", nick)) return not chk_win(cli)
mass_mode(cli, cmode) if var.PHASE != "join" and ret:
var.DEAD.append(nick) # Died during the game, so quiet!
ret = not chk_win(cli) if not is_fake_nick(nick):
if var.PHASE in ("night", "day") and ret: cmode.append(("+q", nick))
# remove him from variables if he is in there mass_mode(cli, cmode)
if var.VICTIM == nick: var.DEAD.append(nick)
var.VICTIM = "" ret = not chk_win(cli)
for x in (var.OBSERVED, var.HVISITED, var.GUARDED): if var.PHASE in ("night", "day") and ret:
keys = list(x.keys()) # remove him from variables if he is in there
for k in keys: if var.VICTIM == nick:
if k == nick: var.VICTIM = ""
del x[k] for x in (var.OBSERVED, var.HVISITED, var.GUARDED):
elif x[k] == nick: keys = list(x.keys())
del x[k] for k in keys:
if nick in var.GUNNERS.keys(): if k == nick:
del var.GUNNERS[nick] del x[k]
if nick in var.CURSED: elif x[k] == nick:
var.CURSED.remove(nick) del x[k]
if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching if nick in var.GUNNERS.keys():
if nick in var.VOTES.keys(): del var.GUNNERS[nick]
del var.VOTES[nick] # Delete his votes if nick in var.CURSED:
for k in var.VOTES.keys(): var.CURSED.remove(nick)
if nick in var.VOTES[k]: if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching
var.VOTES[k].remove(nick) if nick in var.VOTES.keys():
chk_decision(cli) del var.VOTES[nick] # Delete his votes
return ret for k in var.VOTES.keys():
if nick in var.VOTES[k]:
var.VOTES[k].remove(nick)
chk_decision(cli)
return ret
@hook("ping") @hook("ping")
def on_ping(cli, prefix, server): def on_ping(cli, prefix, server):
cli.send('PONG', server) cli.send('PONG', server)
check_graveyard(cli)
def reaper(cli): def reaper(cli, gameid):
# check to see if idlers need to be killed. # check to see if idlers need to be killed.
var.IDLE_KILLED = []
var.IDLE_WARNED = [] var.IDLE_WARNED = []
if not var.WARN_IDLE_TIME or not var.KILL_IDLE_TIME: if not var.WARN_IDLE_TIME or not var.KILL_IDLE_TIME:
return return
while var.PHASE != "none": while gameid == var.GAME_ID:
to_warn = [] with var.GRAVEYARD_LOCK:
for nick in var.list_players(): to_warn = []
lst = var.LAST_SAID_TIME.get(nick, var.GAME_START_TIME) to_kill = []
tdiff = datetime.now() - lst for nick in var.list_players():
if (tdiff > timedelta(seconds=var.WARN_IDLE_TIME) and lst = var.LAST_SAID_TIME.get(nick, var.GAME_START_TIME)
nick not in var.IDLE_WARNED): tdiff = datetime.now() - lst
to_warn.append(nick) if (tdiff > timedelta(seconds=var.WARN_IDLE_TIME) and
var.IDLE_WARNED.append(nick) nick not in var.IDLE_WARNED):
var.LAST_SAID_TIME[nick] = (datetime.now() - to_warn.append(nick)
timedelta(seconds=var.KILL_IDLE_TIME)) # Give him a chance var.IDLE_WARNED.append(nick)
elif (tdiff > timedelta(seconds=var.KILL_IDLE_TIME) and var.LAST_SAID_TIME[nick] = (datetime.now() -
nick not in var.IDLE_KILLED): timedelta(seconds=var.WARN_IDLE_TIME)) # Give him a chance
with var.GRAVEYARD_LOCK: elif (tdiff > timedelta(seconds=var.KILL_IDLE_TIME) and
var.GRAVEYARD.append(("kill",nick)) nick in var.IDLE_WARNED):
var.IDLE_KILLED.append(nick) to_kill.append(nick)
if to_warn: print("WILL KILL "+nick)
with var.GRAVEYARD_LOCK: elif (tdiff < timedelta(seconds=var.WARN_IDLE_TIME) and
var.GRAVEYARD.append(("warn", to_warn)) nick in var.IDLE_WARNED):
sleep(10) var.IDLE_WARNED.remove(nick) # he saved himself from death
chan = botconfig.CHANNEL
for nck in to_kill:
if nck not in var.list_players():
def check_graveyard(cli):
if not var.GRAVEYARD: return
chan = botconfig.CHANNEL
with var.GRAVEYARD_LOCK:
for action, x in var.GRAVEYARD:
if action=="kill":
if x not in var.list_players():
continue continue
cli.msg(chan, ("\u0002{0}\u0002 didn't get out of bed "+ cli.msg(chan, ("\u0002{0}\u0002 didn't get out of bed "+
"for a very long time. S/He is declared dead. Appears "+ "for a very long time. S/He is declared dead. Appears "+
"(s)he was a \u0002{1}\u0002").format(x, var.get_role(x))) "(s)he was a \u0002{1}\u0002").format(nck, var.get_role(nck)))
del_player(cli, x) if not del_player(cli, nck):
elif action=="warn": return
pl = var.list_players() pl = var.list_players()
x = [a for a in x if a in pl] x = [a for a in to_warn if a in pl]
if x:
cli.msg(chan, ("{0}: \u0002You have been idling for a while. "+ cli.msg(chan, ("{0}: \u0002You have been idling for a while. "+
"Please remember to say something soon or you "+ "Please remember to say something soon or you "+
"might be declared dead.\u0002").format(", ".join(x))) "might be declared dead.\u0002").format(", ".join(x)))
var.GRAVEYARD = [] sleep(10)
@cmd("") # update last said @cmd("") # update last said
def update_last_said(cli, nick, *rest): def update_last_said(cli, nick, *rest):
if var.PHASE not in ("join", "none"): if var.PHASE not in ("join", "none"):
var.LAST_SAID_TIME[nick] = datetime.now() var.LAST_SAID_TIME[nick] = datetime.now()
check_graveyard(cli)
@ -1647,7 +1644,8 @@ def start(cli, nick, chan, rest):
transition_day(cli) transition_day(cli)
# DEATH TO IDLERS! # DEATH TO IDLERS!
reapertimer = threading.Thread(None, reaper, args=(cli,)) var.GAME_ID = timetime()
reapertimer = threading.Thread(None, reaper, args=(cli,var.GAME_ID))
reapertimer.daemon = True reapertimer.daemon = True
reapertimer.start() reapertimer.start()

Loading…
Cancel
Save