# Misc functions
from string import lower,printable,Template,capitalize as fcap
import re,shlex
import asyncore as ac
from random import *
NL = "\r\n"
is_a = isinstance
cap = lambda x: x[:1].upper() + x[1:] # capitalize first letter
sxarg = shlex.split
# split with quote handling
def sxarg(x):
try: return shlex.split(x) # shlex.split has trouble with improper quotes
except: return x.split()
# Sort of like MERC's one_arg, except much much stupider
def xarg(t):
ts = sxarg(t)
return ts and [ts[0]," ".join(ts[1:])] or ts
# does t match any of the names in ns?
def nmatch(t,ns):
for x in ns:
if x.startswith(t): return 1
# split up a string into keywords
tok = lambda t: map(lower,t.strip().split())
# connected players
def cplayers():
return [c.p for c in ac.socket_map.itervalues() if c.p]
# n = name to find, xs = list to search, gn = extract obj
def find(n,xs,gn=lambda x:x):
skip = 0
ns = tok(n)
if not ns: return 0
if ns[-1].isdigit(): # "green tea 2" gets the second green tea
skip = max(int(ns[-1])-1,0)
del ns[-1]
for z in xs:
x = gn(z)
if not x.names: x.names = tok(x.name)
for n in ns:
if not nmatch(n,x.names): break
else:
if skip: skip -= 1
else: return z
# fix dangling color '{'
def cfix(r):
if r and r[-1] == '{' and (len(r) == 1 or r[-2] != '{'): r += '{'
return r
# fits a list to a certain size, filling empty spaces with g
def fit(x,z=2,g=''): return x[:z] + [g] * (z-len(x))
# respect descriptions
rscale = ("hellishly vile",20,"utterly pathetic",30,"mildly idiotic",
50,"rather frumpish",70,"slightly unkempt",85,"decent",99,"respectable",
275,"very respectable",350,"trendy",650,"stunning",750,"debonair",999,"awesome")
# health descs (by percent)
hscale = ("near death",10,"horribly disfigured",20,"ghastly pale",
30,"terribly wounded",50,"badly bruised",70,"bruised",80,"slightly scratched",
95,"pretty good shape",100,"in perfect health")
def scale(s,m):
r = 0
for x in s:
if is_a(x,int) and m < x: break
r = x
return r
# broadcast messages
# uses format strings like $SN (subj name)
# targets: S for subj, V for vict, O for obj
# formats: N for name, T for text, E for he/she/it,
# M for him/her/it, S for his/her/its
#
# broadcats functions:
# room - third-party bystanders excluding subj and vict in subj's room
# subj - subj only
# vict - vict only
# all - everyone in subj's room
# world - global except subj
# It's a "class act"! Get it? Ahahaha - okay, sorry, no more puns
class Act(object):
def __init__(S,subj=0,vict=0,obj=0):
S._s = subj; S._v = vict; S._o = obj
def repl(S, m):
x, y = m.group(1, 2)
r = {'S':S._s,'V':S._v,'O':S._o}[x]
if y == 'N': t = r.name
if y == 'T': t = cfix(r)
if y == 'E': t = r.SE
if y == 'M': t = r.SM
if y == 'S': t = r.SS
return t
room = lambda S,t: S.act(t, S._s.room.people, [S._s,S._v,S._o])
subj = lambda S,t: S.act(t, [S._s])
vict = lambda S,t: S.act(t, [S._v], [S._s])
obj = lambda S,t: S.act(t, [S._o], [S._s,S._v])
all = lambda S,t: S.act(t, S._s.room.people)
world = lambda S,t: S.act(t, cplayers(), [S._s])
# text, seq of viewers, seq to exclude
def act(S,t,vs,ex=[]):
if not t: return S
x = cap(re.sub("\$([SVO])([NTEMS])",S.repl,t))
for v in (y for y in vs if y not in ex): v.sendl(x)
return S # allow chaining