# Game commands and socials from util import * import gzip,event,core cmds = [] helpd = {} def D(**data): # register command with data/flags def d(f): cmds.append((f.func_name,f,data)); return f return d C = lambda f: D()(f) # short form for no args # if this decorator is used, l is parsed into v def arg(f,req=1,w=0): def z(S,l): v = 0 if l or req: if req and not l: return S.sendl(cap(f.func_name) + " what?") v = S.find(l,w) if not v: return S.sendl("You don't see that here.") f(S,v) z.orig = f z.func_name = f.func_name return z optarg = lambda f: arg(f,0) warg = lambda w: lambda f: arg(f,1,w) # ugly, eh? # handle a command def do(a,l): if not l: return if l[0] == ",": # special handling for abbreviated form of say if a.foe: l = "say %s, %s" % (a.foe.name,l[1:].lstrip()) else: l = "say %s" % l[1:].lstrip() x = l.split(" ", 1) for c,f,d in cmds: if c.startswith(x[0]): if "nabbr" in d and c != x[0]: if "hide" in d: continue return a.sendl("Must spell out %s." % c) if "admin" in d and not a.admin: return a.sendl("Must be admin.") f(a, (len(x) > 1 and x[1]) or "") return else: a.sendl("Huh?") # commands @C def help(S,l): if l: if l in helpd: S.write(helpd[l]) else: S.sendl("No such topic.") else: S.sendl('Also try typing "commands".\r\n\r\nHelp topics:') for t in sorted(helpd): S.sendl(" "+t) # soc = if true, show socials, otherwise show commands def clist(S,soc): i=0 for c,f,d in sorted(cmds): if soc ^ ("soc" in d) or "hide" in d: continue x = "%s%s" % (c, ("admin" in d and "*" or "")) S.write("%-18s" % x) if i % 4 == 3: S.sendl() i += 1 S.sendl() @C def north(S,l): S.go("north") @C def south(S,l): S.go("south") @C def west(S,l): S.go("west") @C def east(S,l): S.go("east") @C def up(S,l): S.go("up") @C def down(S,l): S.go("down") @D(nabbr=1) def quit(S,l): if S.foe: return S.sendl("Not during combat.") else: S.c.handle_close() @C def commands(S,l): clist(S, 0) @C def socials(S,l): clist(S, 1) @C @optarg def look(S,v): if v: examine.orig(S,v) else: S.sendl(S.room.descTo(S)) S.sendl("{GExits{x: "+', '.join(S.room.ex)) @C @arg def examine(S,v): Act(S,v).subj("You look at $VN.").vict("$SN looks at you.") S.sendl(v.desc) if is_a(v,core.Actor): S.sendl("\r\n"+v.status()) if v.worn: S.sendl("%s is wearing %s."%(cap(v.SE)," and ".join([x.name for x in v.worn.values()]))) @C @warg(1) # room only def get(S,v): v.on_get(S) @C @warg(2) # inv only def drop(S,v): v.on_drop(S) @C @warg(2) # inv only def wear(S,v): v.on_wear(S) @C @warg(2) # inv only def remove(S,v): v.on_remove(S) @C def give(S,l): lv,lto = fit(xarg(l)) if not lv or not lto or lto=="to": return S.sendl("Syntax: give <item> <person>") v,to = S.find(lv),S.find(lto) if not v: S.sendl("No such item here.") elif not to: S.sendl("No such person here.") else: v.on_give(S,to) @C def lists(S,l): ss = S.room.shops if not ss: S.sendl("No shops here.") for s in ss: s.show(S) @C def buy(S,l): if not l: return lists(S,l) for s in S.room.shops: z = s.find(l) if z: break else: return S.sendl("Not for sale here.") S.buy(s,z) @C @arg def drink(S,v): v.on_drink(S) @C # throw something def throw(S,l): lv,lat = fit(xarg(l)) if not lv or lat=="at": return S.sendl("Syntax: throw <item> [victim]") v,at = S.find(lv,2),S.find(lat) if not v: S.sendl("No such item.") elif lat and not at: S.sendl("No such person here.") else: if not S.foe: S.ks = 1 if not S.fight(at): return if not S.ks: return S.sendl("You're not ready to attack yet.") v.on_throw(S,S.foe) @C def who(S,l): S.sendl("{YOnline players:{x") for p in cplayers(): ip = (S.admin and p.c.addr[0]) or "" S.sendl(" %-15s %s" % (p.name,ip)) @C def say(S,l): if not l: return S.sendl("Say what?") Act(S, 0, cap(l)).subj('You say, "{m$OT{x"').room('$SN says, "{m$OT{x"') # battle insults if S.foe and find(l.split(',')[0].lower(),[S.foe]): # UGLY but safer if not S.ks: Act(S).subj("{BYou botched the insult due to bad timing.{x").room( "$SN botched the insult to bad timing.") return # This would be a good place to check for lame/awesome insults # namely, check for shortness, repeats, or unpronounceable nonsense # conversely, would it be a good idea to reward rhyming insults? S.rhit(8,'insult') @C def ooc(S,l): Act(S, 0, l).subj('You OOC: {M$OT{x').world('$SN OOCs: {M$OT{x') @C def mydesc(S,l): def cb(t): S.desc = t from mud import EditUI S.c.ui = EditUI(S.c, S.desc, cb) @C def tell(S,l): lv,l = fit(l.split(None,1)) if not lv: return S.sendl("Tell whom what?") for p in cplayers(): if p.name.startswith(fcap(lv)): break else: return S.sendl("No such player online.") Act(S,p,l).subj("You tell $VN: {c$OT{x").vict("$SN tells you: {c$OT{x") @C @arg def fight(S,v): S.fight(v) @C @optarg def hit(S,v): if not S.foe: S.ks = 1 # one free attack if not S.fight(v): return if not v and S.foe: v = S.foe if not S.ks: return S.sendl("You're not ready to attack yet.") x = S.worn.get("in grasp",S.FISTS) # weapon (if available) or fists Act(S,x,v).subj("You swing $VN at $ON.").vict("$SN swings $VN at you.").room("$SN swings $VN at $ON.") S.hit(x.dam) @C def flee(S,l): Act(S).subj("You try to flee!").room("$SN tries to flee!") if S.foe: S.rpc -= S.rpm/10 S.checklose() if randint(0,5) < 3: S.flee() @C def rname(S,l): if not S.room.try_edit(S): return if not l: return S.sendl("Set room name to what?") S.room.name = l S.sendl("Room name changed to " + l) @C def rdesc(S,l): if not S.room.try_edit(S): return def cb(t): S.room.desc = t from mud import EditUI S.c.ui = EditUI(S.c, S.room.desc, cb) ztypes = {"smbiz":["lemonade"],"biz":["coffee"],"night":["beer"],"res-high":["apartment"]} @C def rent(S,l): b = S.room.biz if b.owner: return S.sendl("Not available for rent.") dep = b.rent * 3 + 10 if not l: S.sendl('Land for rent (type "rent apply <type>" to rent)'+ "\r\nZoning: %s (valid types: %s)" % (b.zone,ztypes[b.zone])+ "\r\nDeposit+fee: $%d" % dep+ "\r\nHourly rent: $%d" % b.rent) return la,l = xarg(l) if not l or la != "apply": return S.sendl("rent apply <type>") if dep > S.cash: return S.sendl("Not enough cash.") if l not in ztypes[b.zone]: return S.sendl("Wrong type.") S.cash -= dep b.owner = S.name b.type = l S.sendl("You rent the property. Rent will be taken from your cash hourly.") @C def shop(S,l): biz = S.room.biz if biz.owner != S.name: return S.sendl("Not your property.") o,l = fit(xarg(l)) if not o: return S.sendl("Options: new, add <flavors>, sample <flavor>, price '<item>' <price>, restock") shop = S.room.shop if o == "new": if shop: S.sendl("Already got one.") else: S.room.shop = core.BevShop(biz.type); S.sendl("Created. Sales revenue paid hourly.") return if not shop: return S.sendl('Create a shop first.') if o == "add": import world fls = sorted(sxarg(l)) if not l or not set(fls) <= set(shop.fls): # shop has chosen flavors? return S.sendl("Valid flavors: "+' '.join(shop.fls)) x = world.Drink() x.fls = fls+[shop.type] x.name = "a glass of "+l+" "+shop.type shop.inv += [[x,1,10]] S.sendl("Added %s." % x.name) if o == "sample": x = S.find(l,2) if not x: return S.sendl("You don't have that.") if not is_a(x,core.Sample): return S.sendl("Not a flavor sample.") shop.fls += [x.fl] S.sendl("Sampled %s." % x.fl) x.goto(0) if o == "restock": S.sendl("Restocked at a cost of $%s." % shop.restock()) if o == "price": l,tpr = fit(l.rsplit(None,1)) x = shop.find(l) if not x: return S.sendl("No such item in shop.") if not tpr.isdigit() or int(tpr) <= 0: return S.sendl("Price must be a positive number.") x[2] = int(tpr) S.sendl("Price set.") @C def inventory(S,l): S.sendl("You're carrying:") for x in S.inv: w = (x.wloc and x.worn and " (worn %s)" % x.wloc) or "" S.sendl(" %s%s" % (x.name, w)) @C def prompt(S,l): if l == "reset": del S.pro elif l: S.pro = l; S.sendl("Prompt set.") else: S.sendl("{cCurrent prompt{x: "+S.pro.replace("{","{{")) S.sendl('Type "{Wprompt reset{x" to restore the default.') @C def save(S,l): S.save(); S.sendl("Saved.") @D(admin=1) def rdig(S,l): if not l in core.dirs: return S.sendl("Bad dir.") r = core.Room() S.room.ex[l] = r r.ex[core.rdirs[core.dirs.index(l)]] = S.room S.sendl("Dug.") @D(admin=1) def rlink(S,l): sr = S.room rd = core.rdirs[core.dirs.index(d)] # reverse direction d,l = fit(xarg(l)) if not l or not d in core.dirs: return S.sendl("rlink <dir> [<dest>|none]") if l == "none": # DOES NOT REMOVE OTHER EXIT if d in sr.ex: del sr.ex[d]; return dest = find(l,[r for r in core.Thing.all if is_a(r,core.Room)]) if not dest: return S.sendl("Room not found.") sr.ex[d] = dest dest.ex[core.rdirs[rd]] = sr S.sendl("Linked.") # reloads this module, updating commands and socials @D(admin=1) def creload(S,l): import cmd reload(cmd) S.sendl("cmd.py reloaded.") @D(admin=1) def goto(S,l): v = find(l,core.Thing.all) if not v: S.sendl("Not found.") elif not v.room: S.sendl("Goes nowhere.") else: if S.foe: S.unfight() Act(S).room("{W$SN{x vanishes in a *{Wfoop{x*.") S.goto(v.room) Act(S).subj("{WPoof{x.").room("{W$SN{x appears in a *{Wpoof{x*.") look(S,"") @D(admin=1) def lease(S,l): o,l = fit(xarg(l)) if not o: return S.sendl("Options: new, evict, condemn, rent <$>, zone <type>") if o == "new": S.room.biz = core.Biz(); return biz = S.room.biz if biz == core.CITY: return S.sendl("No. City property.") if o == "rent": # Set hourly rent if not l.isdigit(): S.sendl("In dollars.") else: biz.rent = int(l) elif o == "zone": # Set room zoning if l not in ztypes: S.sendl("Valid zones: "+' '.join(ztypes)) else: biz.zone = l elif o == "evict": biz.owner = "" # kick out owner and make rentable again elif o == "condemn": biz.owner = "CITY" # return property to city ownership else: S.sendl("Bad option.") # Another admin command for misc things @D(admin=1) def frotz(S,l): if l == '$': S.cash += 5000 # gives you money elif l == "wsave": core.wsave() # save the world else: S.sendl("Options: $, wsave") @D(nabbr=1,hide=1) @optarg def xyzzy(S,v): # makes you an admin if not S.admin and S.c.addr[0] != '127.0.0.1': return S.sendl("Nothing happens.") if v and v.npc: return S.sendl("Players only.") x = v or S x.admin ^= 1 t = x.admin and "now" or "no longer" if v: S.sendl("%s is %s an admin." % (x.name,t)) x.sendl("You are %s an admin." % t) # quick and dirty shutdown! @D(nabbr=1,admin=1) def shutdown(S, l): Act().world("{RSHUTTING DOWN.{x") for p in cplayers(): p.save() frotz(S,'wsave') import asyncore; asyncore.loop(0.1, 1, count=1); asyncore.close_all() import sys; sys.exit(1) # adds a social to the command table # args: subj sans target, room sans target, subj/room/vict with a target def addsoc(n,ts,tr,tds,tdv,tdr): def f(S, l): v = 0 if l: v = S.find(l) if not v: return S.sendl("No such person.") if not v and S.foe: v = S.foe # in combat, auto-target foe if v and v == S.foe and not S.ks: return S.sendl("You're not ready yet.") a = Act(S,v) if v: a.subj(tds); a.vict(tdv); a.room(tdr) else: a.subj(ts); a.room(tr) if v and v == S.foe: # a (potentially) insulting attack S.rhit(6,n) cmds.append((n,f,{"soc":1})) def load_soc(): x = [] for l in gzip.open("socials.txt.gz", "r"): l = l.strip() if l == '~': # end of a social addsoc(*fit(x,6,'')); x = [] else: x += [l] def load_help(): x = n = "" f = gzip.open("help.txt.gz","r") for l in f: l = l.rstrip() if not n: n = l; continue if l == "~": helpd[n] = x x = ""; n = 0 else: x += l+"\r\n" load_soc() load_help()