improved admin-only command setting,
removed extra junk, added !wait + start time wait.
This commit is contained in:
parent
7a3cbe132d
commit
267d7104bc
@ -1,14 +1,20 @@
|
||||
from oyoyo.parse import parse_nick
|
||||
import botconfig;
|
||||
|
||||
def generate(fdict):
|
||||
def cmd(s, raw_nick=False):
|
||||
def cmd(s, raw_nick=False, admin_only=False):
|
||||
def dec(f):
|
||||
def innerf(*args):
|
||||
largs = list(args)
|
||||
largs[1] = parse_nick(largs[1])[0]
|
||||
if not raw_nick: largs[1] = parse_nick(largs[1])[0]
|
||||
if admin_only:
|
||||
if largs[1] in botconfig.ADMINS:
|
||||
return f(*largs)
|
||||
if raw_nick: fdict[s] = f
|
||||
else: fdict[s] = innerf
|
||||
else:
|
||||
largs[0].notice(largs[1], "You are not an admin.")
|
||||
return
|
||||
return f(*largs)
|
||||
fdict[s] = innerf
|
||||
return f
|
||||
return dec
|
||||
return cmd
|
@ -17,18 +17,9 @@
|
||||
|
||||
import logging
|
||||
import socket
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import time
|
||||
import threading
|
||||
import os
|
||||
import traceback
|
||||
|
||||
from oyoyo.parse import *
|
||||
from oyoyo.parse import parse_raw_irc_command
|
||||
from oyoyo.cmdhandler import CommandError
|
||||
import collections
|
||||
|
||||
|
||||
class IRCClientError(Exception):
|
||||
pass
|
||||
@ -201,89 +192,6 @@ class IRCClient:
|
||||
self.send("USER", uname, self.host, self.host,
|
||||
rname or uname)
|
||||
|
||||
class IRCApp:
|
||||
""" This class manages several IRCClient instances without the use of threads.
|
||||
(Non-threaded) Timer functionality is also included.
|
||||
"""
|
||||
|
||||
class _ClientDesc:
|
||||
def __init__(self, **kwargs):
|
||||
self.con = None
|
||||
self.autoreconnect = False
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
def __init__(self):
|
||||
self._clients = {}
|
||||
self._timers = []
|
||||
self.running = False
|
||||
self.sleep_time = 0.5
|
||||
|
||||
def addClient(self, client, autoreconnect=False):
|
||||
""" add a client object to the application. setting autoreconnect
|
||||
to true will mean the application will attempt to reconnect the client
|
||||
after every disconnect. you can also set autoreconnect to a number
|
||||
to specify how many reconnects should happen.
|
||||
|
||||
warning: if you add a client that has blocking set to true,
|
||||
timers will no longer function properly """
|
||||
logging.info('added client %s (ar=%s)' % (client, autoreconnect))
|
||||
self._clients[client] = self._ClientDesc(autoreconnect=autoreconnect)
|
||||
|
||||
def addTimer(self, seconds, cb):
|
||||
""" add a timed callback. accuracy is not specified, you can only
|
||||
garuntee the callback will be called after seconds has passed.
|
||||
( the only advantage to these timers is they dont use threads )
|
||||
"""
|
||||
assert isinstance(cb, collections.Callable)
|
||||
logging.info('added timer to call %s in %ss' % (cb, seconds))
|
||||
self._timers.append((time.time() + seconds, cb))
|
||||
|
||||
def run(self):
|
||||
""" run the application. this will block until stop() is called """
|
||||
# TODO: convert this to use generators too?
|
||||
self.running = True
|
||||
while self.running:
|
||||
found_one_alive = False
|
||||
|
||||
for client, clientdesc in self._clients.items():
|
||||
if clientdesc.con is None:
|
||||
clientdesc.con = client.connect()
|
||||
|
||||
try:
|
||||
next(clientdesc.con)
|
||||
except Exception as e:
|
||||
logging.error('client error %s' % e)
|
||||
logging.error(traceback.format_exc())
|
||||
if clientdesc.autoreconnect:
|
||||
clientdesc.con = None
|
||||
if isinstance(clientdesc.autoreconnect, (int, float)):
|
||||
clientdesc.autoreconnect -= 1
|
||||
found_one_alive = True
|
||||
else:
|
||||
clientdesc.con = False
|
||||
else:
|
||||
found_one_alive = True
|
||||
|
||||
if not found_one_alive:
|
||||
logging.info('nothing left alive... quiting')
|
||||
self.stop()
|
||||
|
||||
now = time.time()
|
||||
timers = self._timers[:]
|
||||
self._timers = []
|
||||
for target_time, cb in timers:
|
||||
if now > target_time:
|
||||
logging.info('calling timer cb %s' % cb)
|
||||
cb()
|
||||
else:
|
||||
self._timers.append((target_time, cb))
|
||||
|
||||
time.sleep(self.sleep_time)
|
||||
|
||||
def stop(self):
|
||||
""" stop the application """
|
||||
self.running = False
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -16,15 +16,9 @@
|
||||
# THE SOFTWARE.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from oyoyo.ircevents import *
|
||||
|
||||
# Python < 3 compatibility
|
||||
if sys.version_info < (3,):
|
||||
class bytes(object):
|
||||
def __new__(self, b='', encoding='utf8'):
|
||||
return str(b)
|
||||
from oyoyo.ircevents import generated_events, protocol_events,\
|
||||
all_events, numeric_events
|
||||
|
||||
|
||||
def parse_raw_irc_command(element):
|
||||
|
13
vars.py
13
vars.py
@ -1,12 +1,19 @@
|
||||
PING_WAIT = 300 # Seconds
|
||||
MINIMUM_WAIT = 60
|
||||
EXTRA_WAIT = 20
|
||||
MAXIMUM_WAITED = 2 # limit for amount of !wait's
|
||||
MAX_SHOTS = 2
|
||||
|
||||
# These change ingame
|
||||
ROLES = {"person" : []}
|
||||
ORIGINAL_ROLES = None
|
||||
PHASE = "none" # "join", "day", or "night"
|
||||
LAST_PING = 0
|
||||
PING_WAIT = 300 # Seconds
|
||||
WAIT = 60
|
||||
CURSED = "" # nickname of cursed villager
|
||||
GAME_START_TIME = 0
|
||||
CAN_START_TIME = 0
|
||||
WAITED = 0
|
||||
GUNNERS = {}
|
||||
MAX_SHOTS = 2
|
||||
|
||||
is_role = lambda plyr, rol: rol in ROLES and plyr in ROLES[rol]
|
||||
|
||||
|
161
wolfgame.py
161
wolfgame.py
@ -2,6 +2,8 @@ from oyoyo.parse import parse_nick
|
||||
import vars
|
||||
import botconfig
|
||||
import decorators
|
||||
import time
|
||||
import random
|
||||
|
||||
COMMANDS = {}
|
||||
PM_COMMANDS = {}
|
||||
@ -17,7 +19,6 @@ def connect_callback(cli):
|
||||
cli.identify(botconfig.PASS)
|
||||
cli.join(botconfig.CHANNEL)
|
||||
cli.msg("ChanServ", "op "+botconfig.CHANNEL)
|
||||
cli.msg(botconfig.CHANNEL, "\u0002Wolfbot2 is here.\u0002")
|
||||
|
||||
def reset_game():
|
||||
vars.ROLES = {"person" : []}
|
||||
@ -29,10 +30,10 @@ def say(cli, nick, rest): # To be removed later
|
||||
cli.msg(botconfig.CHANNEL, "{0} says: {1}".format(nick, rest))
|
||||
|
||||
|
||||
@pmcmd("!bye")
|
||||
@cmd("!bye")
|
||||
@pmcmd("!bye", admin_only=True)
|
||||
@cmd("!bye", admin_only=True)
|
||||
def forced_exit(cli, nick, *rest): # Admin Only
|
||||
if nick in botconfig.ADMINS:
|
||||
reset_game(cli, nick, rest[0], None)
|
||||
cli.quit("Forced quit from admin")
|
||||
raise SystemExit
|
||||
|
||||
@ -71,55 +72,165 @@ def pinger(cli, nick, chan, rest):
|
||||
@cmd("!join")
|
||||
def join(cli, nick, chan, rest):
|
||||
if vars.PHASE == "none":
|
||||
cli.mode(chan, "+v", nick, nick+"!*@*")
|
||||
vars.ROLES["person"].append(nick)
|
||||
vars.PHASE = "join"
|
||||
vars.CAN_START_TIME = time.time() + vars.MINIMUM_WAIT
|
||||
cli.msg(chan, '\u0002{0}\u0002 has started a game of Werewolf. \
|
||||
Type "!join" to join. Type "!start" to start the game. \
|
||||
Type "!wait" to increase join wait time.'.format(nick))
|
||||
elif nick in list_players():
|
||||
elif nick in vars.list_players():
|
||||
cli.notice(nick, "You're already playing!")
|
||||
elif vars.PHASE != "join":
|
||||
cli.notice(nick, "Sorry but the game is already running. Try again next time.")
|
||||
else:
|
||||
cli.mode(chan, "+v", nick, nick+"!*@*")
|
||||
vars.ROLES["person"].append(nick)
|
||||
cli.msg(chan, '\u0002{0}\u0002 has joined the game.'.format(nick))
|
||||
|
||||
@cmd("!stats")
|
||||
def stats(cli, nick, chan, rest):
|
||||
if vars.PHASE == "none":
|
||||
cli.notice(nick, "No game is currently running.")
|
||||
return
|
||||
pl = list_players()
|
||||
|
||||
pl = vars.list_players()
|
||||
if len(pl) > 1:
|
||||
cli.msg(chan, '{0}: {1} players: {2}'.format(nick,
|
||||
cli.msg(chan, '{0}: \u0002{1}\u0002 players: {2}'.format(nick,
|
||||
len(pl), ", ".join(pl)))
|
||||
else:
|
||||
cli.msg(chan, '{0}: 1 player: {1}'.format(nick, pl[0]))
|
||||
cli.msg(chan, '{0}: \u00021\u0002 player: {1}'.format(nick, pl[0]))
|
||||
|
||||
if vars.PHASE == "join":
|
||||
return
|
||||
|
||||
msg = []
|
||||
for role in vars.ROLES.keys():
|
||||
num = len(vars.ROLES[role])
|
||||
if num > 1:
|
||||
msg.append("{0} {1}".format(num, plural(role)))
|
||||
message = []
|
||||
for role in ("wolf", "seer", "harlot"):
|
||||
count = len(vars.ROLES.get(role,[]))
|
||||
if count > 1:
|
||||
message.append("\u0002(0}\u0002 {1}".format(count, vars.plural(role)))
|
||||
else:
|
||||
msg.append("{0} {1}".format(num, role))
|
||||
if len(msg) > 2: # More than 2 roles to say
|
||||
msg[-1] = "and "+msg[-1]+"."
|
||||
msg[0] = "{0}: There are ".format(nick) + msg[0]
|
||||
cli.msg(chan, ", ".join(msg))
|
||||
elif len(msg) == 2: # 2 roles to say
|
||||
cli.msg(chan, "{0}: There are ".format(nick) + msg[0],
|
||||
"and", msg[1] + ".")
|
||||
elif len(msg) == 1:
|
||||
cli.msg(chan, "{0}: There is ".format(nick) + msg[0] + ".")
|
||||
message.append("\u0002{0}\u0002 {1}".format(count, role))
|
||||
cli.msg(chan,
|
||||
"{0}: There are {1}, and {2}.".format(nick,
|
||||
", ".join(message[0:-1]),
|
||||
message[-1]))
|
||||
|
||||
def transition_night(cli, chan):
|
||||
vars.PHASE = "night"
|
||||
|
||||
@cmd("!start")
|
||||
def start(cli, nick, chan, rest):
|
||||
pl = list_players()
|
||||
pl = vars.list_players()
|
||||
if vars.PHASE == "none":
|
||||
cli.notice(nick, "No game is currently running.")
|
||||
return
|
||||
if vars.PHASE != "join":
|
||||
cli.notice(nick, "Werewolf is already in play.")
|
||||
return
|
||||
if nick not in pl:
|
||||
cli.notice(nick, "You're currently not playing.")
|
||||
return
|
||||
now = time.time()
|
||||
if vars.CAN_START_TIME > now:
|
||||
cli.msg(chan, "Please wait at least {0} more seconds.".format(
|
||||
int(vars.CAN_START_TIME - now)))
|
||||
return
|
||||
|
||||
if(len(pl)) < 4:
|
||||
if len(pl) < 4:
|
||||
cli.msg(chan, "{0}: Four or more players are required to play.".format(nick))
|
||||
return
|
||||
|
||||
vars.ROLES = {}
|
||||
nharlots = 0
|
||||
nseers = 0
|
||||
nwolves = 0
|
||||
ndrunk = 0
|
||||
ncursed = 0
|
||||
|
||||
if len(pl) >= 8:
|
||||
nharlots = 1
|
||||
nseers = 1
|
||||
nwolves = 2
|
||||
ndrunk = 1
|
||||
ncursed = 1
|
||||
elif(len(pl)) >= 6:
|
||||
nseers = 1
|
||||
nwolves = 1
|
||||
ndrunk = 1
|
||||
ncursed = 1
|
||||
else:
|
||||
nseers = 1
|
||||
nwolves = 1
|
||||
|
||||
seer = random.choice(pl)
|
||||
vars.ROLES["seer"] = [seer]
|
||||
pl.remove(seer)
|
||||
if nharlots:
|
||||
harlots = random.sample(pl, nharlots)
|
||||
vars.ROLES["harlot"] = harlots
|
||||
for h in harlots:
|
||||
pl.remove(h)
|
||||
if nwolves:
|
||||
wolves = random.sample(pl, nwolves)
|
||||
vars.ROLES["wolf"] = wolves
|
||||
for w in wolves:
|
||||
pl.remove(w)
|
||||
if ndrunk:
|
||||
drunk = random.choice(pl)
|
||||
vars.ROLES["village drunk"] = [drunk]
|
||||
pl.remove(drunk)
|
||||
vars.ROLES["villager"] = pl
|
||||
|
||||
if ncursed:
|
||||
CURSED = random.choice(var.ROLES["villager"] + \
|
||||
var.ROLES.get("harlot", []) +\
|
||||
var.ROLES.get("village drunk", []))
|
||||
|
||||
cli.msg(chan, "{0}: Welcome to Werewolf, the popular detective/social \
|
||||
party game (a theme of Mafia).".format(", ".join(vars.list_players())))
|
||||
cli.mode(chan, "+m")
|
||||
|
||||
vars.ORIGINAL_ROLES = dict(vars.ROLES) # Make a copy
|
||||
transition_night(cli, chan)
|
||||
|
||||
@cmd("!wait")
|
||||
def wait(cli, nick, chan, rest):
|
||||
pl = vars.list_players()
|
||||
if vars.PHASE == "none":
|
||||
cli.notice(nick, "No game is currently running.")
|
||||
return
|
||||
if vars.PHASE != "join":
|
||||
cli.notice(nick, "Werewolf is already in play.")
|
||||
return
|
||||
if nick not in pl:
|
||||
cli.notice(nick, "You're currently not playing.")
|
||||
return
|
||||
if vars.WAITED >= vars.MAXIMUM_WAITED:
|
||||
cli.msg(chan, "Limit has already been reached for extending the wait time.")
|
||||
return
|
||||
|
||||
now = time.time()
|
||||
if now > vars.CAN_START_TIME:
|
||||
vars.CAN_START_TIME = now + vars.EXTRA_WAIT
|
||||
else:
|
||||
vars.CAN_START_TIME += vars.EXTRA_WAIT
|
||||
vars.WAITED += 1
|
||||
cli.msg(chan, "{0} increased the wait \
|
||||
time by {1} seconds.".format(nick, vars.EXTRA_WAIT))
|
||||
|
||||
@cmd("!reset", admin_only = True)
|
||||
def reset_game(cli, nick, chan, rest):
|
||||
vars.PHASE = "none"
|
||||
cli.mode(chan, "-m")
|
||||
for pl in vars.list_players():
|
||||
cli.mode(chan, "-v", pl)
|
||||
|
||||
vars.ROLES = {"person" : []}
|
||||
vars.ORIGINAL_ROLES = None
|
||||
vars.CURSED = ""
|
||||
vars.GAME_START_TIME = 0
|
||||
vars.CAN_START_TIME = 0
|
||||
vars.GUNNERS = {}
|
||||
vars.WAITED = 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user