object #1
num proper_name = 0;
list dark_vars = {};
list light_vars = {};
str name = "Root Object";
list write_ok = {};
obj sublocation = #-1;
list owners = {#11};
num public = 1;
num dark = 0;
num safe = 0;
str aliases = "";
verb "@rename" : "to" = rename_verb;
method padl
var retstr, padchar;
ignore E_RANGE;
if (args[3])
padchar = args[3][1];
else
padchar = " ";
endif
if (lengthof(args[1]) > tonum(args[2]))
return pad(@args);
endif
retstr = pad(padchar, args[2] - lengthof(args[1]) - 1, padchar);
retstr = retstr + args[1];
return retstr;
endmethod
method list_method
var code, parent;
ignore E_METHODNF;
if (!this.can_read("", caller))
raise E_PERM;
endif
code = list_method(@args);
if (code || code == "")
return code;
endif
parent = find_method(args[1]);
if (parent)
code = parent.list_method(@args);
if (code || code == "")
return "That object does not define that method, but its ancestor " + parent.id + " does:\n" + code;
endif
endif
return "That object does not define that method.";
endmethod
method event_exit
return 0;
endmethod
method find_method
var code, parent;
ignore E_METHODNF;
if (!this.can_read("", caller))
raise E_PERM;
endif
code = list_method(@args);
if (code)
return toobj(this);
endif
parent = find_method(args[1]);
if (parent)
return toobj(parent);
endif
return #-1;
endmethod
method inamec
if (proper_name)
return name;
elseif (name[1] in "aeiou")
return "An " + name;
else
return "A " + name;
endif
endmethod
method destroy
var owner;
if (this.can_write("", caller))
for owner in (owners)
owner.rm_creation(this);
endfor
destroy();
else
raise E_PERM;
endif
endmethod
method id
return name + "(" + tostr(this) + ")";
endmethod
method rename_verb
var r;
ignore E_RANGE;
if (!this.match(args[2]))
return 1;
elseif (!this.can_write("name", caller))
player.tell("You can't rename that.");
return 0;
endif
r = this.set_name(args[4]);
if (r == E_RANGE)
player.tell("You can't use that new name.");
else
player.tell("Name set.");
endif
endmethod
method announce
return 0;
endmethod
method setvar
if (this.can_write(args[1], caller))
setvar(args[1], args[2]);
else
raise E_PERM;
endif
endmethod
method set_owners
raise E_PERM;
endmethod
method list_method_brackets
return list_method(args[1], 1, 1);
endmethod
method add_verb
if (!this.can_write("", caller))
raise E_PERM;
else
return add_verb(args[1], args[2], args[3]);
endif
endmethod
method english_list_str
var item, i, thelist, txt;
txt = "";
thelist = args[1];
txt = thelist[1];
for i in [2..lengthof(thelist)]
if (i == lengthof(thelist))
txt = txt + " and " + thelist[i];
else
txt = txt + ", " + thelist[i];
endif
endfor
return txt;
endmethod
method clone
var new;
if (!this.can_write("", caller))
raise E_PERM;
else
new = clone();
new.init;
if (args)
new.set_name(args[1]);
endif
return new;
endif
endmethod
method publish
if (!this.can_write("public", caller))
raise E_PERM;
else
public = 1;
endif
endmethod
method name
return name;
endmethod
method methods
if (this.can_read("", caller))
return methods();
else
raise E_PERM;
endif
endmethod
method add_owner
var dummy;
if (this.can_write("owners", caller))
owners = owners + args[1];
dummy = args[1].add_creation(this);
else
raise E_PERM;
endif
endmethod
method add_parent
if (this.can_write("parents", caller))
raise E_PERM;
else
chparents(parents + args[1]);
endif
endmethod
method chparents
if (!this.can_write("parents", caller))
raise E_PERM;
else
chparents(args[1]);
endif
endmethod
method init
if (this == $root)
this.add_owner(#11);
elseif (this.can_write("", caller))
owners = {};
else
raise E_PERM;
endif
endmethod
method rm_method
if (!this.can_write("", caller))
raise E_PERM;
else
return rm_method(args[1]);
endif
endmethod
method rm_var
if (!this.can_write(args[1], caller))
raise E_PERM;
else
return rm_var(args[1]);
endif
endmethod
method spew_method
var code;
ignore E_METHODNF;
if (!this.can_read("", caller))
raise E_PERM;
endif
code = spew_method(args[1]);
if (code == E_METHODNF)
return "That object does not define that method.";
else
return code;
endif
endmethod
method getvar
if (this.can_read(args[1], caller))
return getvar(args[1]);
else
raise E_PERM;
endif
endmethod
method sublocation
return sublocation;
endmethod
method rm_owner
var dummy;
if (this.can_write("owners", caller))
owners = owners - args[1];
dummy = args[1].rm_creation(this);
else
raise E_PERM;
endif
endmethod
method keys
var keylist, i;
keylist = {};
for i in (getvar(args[1]))
keylist = keylist + i;
endfor
return keylist;
endmethod
method sdesc
return "You see " + this.iname + " here.";
endmethod
method owners
return owners;
endmethod
method event_entry
return 0;
endmethod
method unpublish
if (!this.can_write("public", caller))
raise E_PERM;
else
public = 0;
endif
endmethod
method public
return public;
endmethod
method rm_verb
if (!this.can_write("", caller))
raise E_PERM;
else
return rm_verb(args[1]);
endif
endmethod
method decompile
if (!this.can_read("", caller))
return E_PERM;
endif
return decompile();
endmethod
method dark
return dark;
endmethod
method show
var vars, item, value, id;
ignore E_SERVERDN, E_OBJNF;
player.tell(this.id + " Size: " + tostr(objsize()) + " bytes");
if (parents)
player.tell("Parents: " + tostr(parents));
else
player.tell("No parents.");
endif
vars = sort(vars());
if (vars)
for item in (vars)
if (!this.can_read(item, caller))
continue;
endif
value = getvar(item);
if (typeof(value) == 2)
id = value.id;
if (typeof(id) == 0)
player.tell(" " + item + ": " + id);
else
player.tell(" " + item + ": " + tostr(value));
endif
else
player.tell(" " + item + ": " + tostr(value));
endif
endfor
else
player.tell("No vars.");
endif
endmethod
method dname
if (proper_name)
return name;
else
return "the " + name;
endif
endmethod
method dnamec
if (proper_name)
return name;
else
return "The " + name;
endif
endmethod
method set_aliases
if (!this.can_write("aliases", caller))
player.tell("You can set aliases on that!");
return 0;
endif
aliases = args[1];
player.tell("Aliases set.");
endmethod
method english_list
var item, i, thelist, txt;
txt = "";
thelist = args[1];
txt = thelist[1].name;
for i in [2..lengthof(thelist)]
if (i == lengthof(thelist))
txt = txt + " and " + thelist[i].name;
else
txt = txt + ", " + thelist[i].name;
endif
endfor
return txt;
endmethod
method can_write
var what_var, perm, temp, called_by;
ignore E_TYPE, E_RANGE, E_METHODNF, E_PERM;
what_var = args[1];
called_by = args[2];
if (caller == #0 || player == #0)
return 1;
endif
if (called_by == this)
return 1;
endif
if (player == this)
return 1;
endif
if (player in #0.wizards)
return 1;
endif
if (player in owners)
return 1;
endif
if (what_var in write_ok)
return 1;
endif
if (called_by == getvar("location") && safe == 0)
return 1;
endif
return 0;
endmethod
method set_sublocation
if (this.can_write("sublocation", caller))
sublocation = args[1];
else
raise E_PERM;
endif
endmethod
method implode
var i, thelist, txt;
txt = "";
thelist = args[1];
txt = thelist[1];
for i in [2..lengthof(thelist)]
txt = txt + args[2] + thelist[i];
endfor
return txt;
endmethod
method padc
var retstr, i, padchar;
ignore E_RANGE;
if (args[3])
padchar = args[3][1];
else
padchar = " ";
endif
if (lengthof(args[1]) >= tonum(args[2]))
return pad(@args);
endif
i = (tonum(args[2]) - lengthof(args[1])) / 2;
player.tell("i: " + tostr(i));
retstr = pad(padchar, i, padchar) + args[1] + pad(padchar, i, padchar);
retstr = pad(retstr, tonum(args[2]), padchar);
return retstr;
endmethod
method set_name
if (this.can_write("name", caller))
name = args[1];
else
raise E_PERM;
endif
endmethod
method compile
if (!this.can_write("", caller))
raise E_PERM;
endif
return !compile(this, args[1], args[2]);
endmethod
method isa
return hasparent(args[1]);
endmethod
method iname
if (proper_name)
return name;
elseif (!name)
return "an unnamed thing, how gauche";
elseif (name[1] in "aeiou")
return "an " + name;
else
return "a " + name;
endif
endmethod
method rm_parent
if (!this.can_write("parents", caller))
raise E_PERM;
else
chparents(parents - args[1]);
endif
endmethod
method verbs
if (this.can_read("", caller))
return verbs();
else
raise E_PERM;
endif
endmethod
method can_read
var what, what_var, perm, temp, called_by;
ignore E_TYPE, E_RANGE, E_METHODNF, E_PERM;
what_var = args[1];
called_by = args[2];
if (this.can_write(what_var, called_by))
return 1;
endif
if (called_by == #0)
return 1;
endif
if (what_var in light_vars)
return 1;
endif
if (public && !(what_var in dark_vars))
return 1;
endif
return 0;
endmethod
endobject
object #0
parents #1;
obj room = #6;
obj located_obj = #2;
obj builder = #9;
obj thing = #4;
str welcome_msg = " \n*** WELCOME TO CHAOS! ***\n \nCOOLMUD created by Stephen White. Damn fine program, too.\nChaos is run by Robin Powell.\nUse \"create <name> <password>\" to create a new character.\nUse \"connect <name> <password>\" to connect to an existing character.\nUse \"who\" or \"@who\" to get a list of users currently connected.\nUse \"quit\" or \"@quit\" to disconnect without connecting.\nUse help to repeat this message.\n-----------------------\nI'm working on a general help for playing on the MUD, look at 'help playing'. Also, 'help commands' is now usefully organized, and we have furniture.\nNOTE FOR WINDOWS USERS: I've fixed the server to deal with backspace from windows telnet properly. If it still doesn't work, use CTRL-H.\nYou can now have aliases for exits and players. See 'help @aliases'.\n-----------------------\n\n";
list connected_servers = {#0};
obj player_start = #13;
obj help_obj = #14;
obj root = #1;
obj container = #5;
obj player = #8;
str name = "The System Object";
list players = {#11};
obj network_tools = #12;
list connected_players = {#11};
list visitors = {};
obj global_help_obj = #15;
obj news_obj = #16;
list owners = {#11};
num public = 1;
obj wizard = #11;
num booted_at = 898288986;
obj puppet = #19;
obj exit = #7;
num dbtop;
obj programmer = #10;
obj furniture = #18;
obj global_news_obj = #17;
list wizards = {#11};
obj described_obj = #3;
method tell
var tempstr;
if (typeof(args[1]) == 0)
tempstr = args[1];
else
tempstr = tostr(args[1]);
endif
echo(tempstr);
endmethod
method find_connected_player
var dude;
for dude in (connected_players)
if (dude.match_full(args[1]))
return dude;
endif
endfor
for dude in (connected_players)
if (dude.match(args[1]))
return dude;
endif
endfor
return #-1;
endmethod
method rm_wizard
if (!(caller in wizards))
player.tell("Permission denied.");
else
wizards = wizards - args[1];
player.tell("Wizard removed.");
endif
endmethod
method connected_servers
return connected_servers;
endmethod
method sync
if (!(caller in #0.wizards))
raise E_PERM;
endif
at (0)
while (1)
sleep(300);
endwhile
endat
endmethod
method who
var dude, line, howmany;
if (args)
echo("Player Name On For Idle", args[1]);
else
player.tell("Player Name On For Idle");
endif
for dude in (connected_players)
line = pad(dude.name, 17) + " " + pad(this.convtime(time() - dude.connected_at), 11) + " " + pad(this.convtime(time() - dude.last_cmd_at), 11);
if (args)
echo(line, args[1]);
else
player.tell(line);
endif
endfor
howmany = lengthof(connected_players);
if (howmany == 1)
player.tell("1 player connected. Lonely.");
else
player.tell(tostr(howmany) + " players connected.");
endif
endmethod
method players
return players;
endmethod
method disconnect_server
connected_servers = connected_servers - args[1];
endmethod
method visitors
return visitors;
endmethod
method connected_players
return connected_players;
endmethod
method init
if (caller != #0)
raise E_PERM;
else
this.add_owner(#11);
endif
endmethod
method connect_player
var who, password;
ignore E_METHODNF;
if (caller != #0)
raise E_PERM;
elseif (lengthof(args[1]) < 2 || lengthof(args[1]) > 3)
echo("Usage: connect <username> <password>", args[2]);
else
who = #0.find_player(args[1][2]);
if (!who)
echo("Login incorrect.", args[2]);
writelog("Player \"" + args[1][2] + "\" failed connect on descriptor " + tostr(args[2]));
else
password = who.getvar("password");
if (password && crypt(args[1][3], password[1..2]) != password)
echo("Login incorrect.", args[2]);
writelog("Player \"" + args[1][2] + "\" failed connect on descriptor " + tostr(args[2]));
else
player = who;
if (who in connected_players)
who.tell("*** Punting for new connection ***");
who.quit_cmd;
set_parse(args[2], who);
who.tell("*** Punting old connection ***");
else
set_parse(args[2], who);
endif
connected_players = connected_players + who;
writelog("Player \"" + who.id + "\" connected on descriptor " + tostr(args[2]));
who.connect;
endif
endif
endif
endmethod
method resynch
var item, dummy;
if (caller != #0)
raise E_PERM;
endif
for item in (visitors)
if (serverof(item[1].location))
dummy = item[2].remove(item[1]);
visitors = visitors - item;
endif
endfor
endmethod
method convtime
var r, time, howmany;
if (lengthof(args) != 1)
raise E_RANGE;
elseif (typeof(args[1]) != 1)
raise E_TYPE;
else
time = args[1];
if (time > 24 * 60 * 60)
r = " day";
howmany = time / (24 * 60 * 60);
elseif (time > 60 * 60)
r = " hour";
howmany = time / (60 * 60);
elseif (time > 60)
r = " minute";
howmany = time / 60;
else
r = " second";
howmany = time;
endif
if (howmany != 1)
r = r + "s";
endif
return tostr(howmany) + r;
endif
endmethod
method connect
var who;
who = args[1];
echo(welcome_msg);
endmethod
method add_visitor
visitors = visitors + {};
endmethod
method add_wizard
if (!(caller in wizards))
player.tell("Permission denied.");
else
wizards = wizards + args[1];
player.tell("Wizard added.");
endif
endmethod
method find_player
var dude;
for dude in (players)
if (dude.match_full(args[1]))
return dude;
endif
endfor
for dude in (players)
if (dude.match(args[1]))
return dude;
endif
endfor
return #-1;
endmethod
method connect_server
connected_servers = connected_servers + args[1];
#0.resynch;
endmethod
method boot_server
if (caller != #0)
raise E_PERM;
endif
connected_players = {#11};
connected_servers = {#0};
booted_at = time();
endmethod
method parse
var who, c;
ignore E_RANGE;
who = args[2];
if (!args[1] || args[1] == "help")
echo(welcome_msg);
else
c = explode(args[1]);
if (c[1][1..2] == "co" && c[1] == "connect"[1..lengthof(c[1])])
this.connect_player(c, who);
elseif (c[1][1..2] == "cr" && c[1] == "create"[1..lengthof(c[1])])
this.create_player(c, who);
elseif (c[1] == "who" || c[1] == "@who")
#0.who(who);
elseif (c[1] == "quit" || c[1] == "@quit")
disconnect(args[2]);
else
echo("Invalid command. Valid commands are: connect, create, help, who, and quit.", who);
endif
endif
endmethod
method add_player
if (player in wizards || player == #0)
players = setadd(players, args[1]);
else
raise E_PERM;
endif
endmethod
method sanity_check
var item, n, c, creation, _exit, owner;
ignore E_OBJNF;
for n in [args[1]..args[2]]
item = toobj(n);
if (item.id != E_OBJNF)
if (item.isa($located_obj))
if (item.location != #-1 && item.location.id == E_OBJNF)
player.tell(item.id + ": thinks it's in " + tostr(item.location) + ", which was destroyed.");
endif
for c in (item.contents)
if (c.id == E_OBJNF)
player.tell(item.id + ": contents " + tostr(c) + " doesn't exist!");
elseif (!c.isa($located_obj))
player.tell(item.id + ": contains non-located thing " + tostr(c));
elseif (c.location != item)
player.tell(item.id + ": contents " + c.id + " thinks it's in " + c.location.id);
endif
endfor
endif
if (item.isa($player))
for creation in (item.creations)
if (creation.id == E_OBJNF)
player.tell(item.id + ": creation " + tostr(creation) + " doesn't exist!");
elseif (!(item in creation.owners))
player.tell(item.id + ": creation " + creation.id + " doesn't consider itself owned by " + item.id);
endif
endfor
endif
if (item.isa($room))
for _exit in (item.exits)
if (_exit.id == E_OBJNF)
player.tell(item.id + ": exit " + tostr(_exit) + " doesn't exist!");
elseif (_exit.source != item)
player.tell(item.id + ": exit " + _exit.id + " thinks its source is " + tostr(_exit.source));
endif
endfor
endif
if (item.isa($exit))
if (item.source.id != #-1 && item.source.id == E_OBJNF)
player.tell(item.id + " source is destroyed?!");
elseif (item.dest.id != #-1 && item.dest.id == E_OBJNF)
player.tell(item.id + " dest is destroyed?!");
endif
endif
for owner in (item.owners)
if (owner.id == E_OBJNF)
player.tell(item.id + ": owner " + owner.id + " doesn't exist!");
elseif (!owner.isa($player))
player.tell(item.id + ": owner " + owner.id + " is not a player.");
elseif (!(item in owner.creations))
player.tell(item.id + ": thinks it's owned by " + owner.id + ", who doesn't think so");
endif
endfor
endif
endfor
endmethod
method sanity_fix
var item, n, c, creation, _exit, owner;
ignore E_OBJNF;
for n in [args[1]..args[2]]
item = toobj(n);
if (item.id != E_OBJNF)
if (item.isa($located_obj))
if (item.location != #-1 && item.location.id == E_OBJNF)
player.tell(item.id + ": thinks it's in " + tostr(item.location) + ", which was destroyed.");
item.moveto(#-1);
player.tell("sent it to #-1");
endif
for c in (item.contents)
if (c.id == E_OBJNF)
player.tell(item.id + ": contents " + tostr(c) + " doesn't exist!");
item.remove(c);
player.tell("removed");
elseif (!c.isa($located_obj))
player.tell(item.id + ": contains non-located thing " + tostr(c));
item.remove(c);
player.tell("removed");
elseif (c.location != item)
player.tell(item.id + ": contents " + c.id + " thinks it's in " + c.location.id);
item.remove(c);
player.tell("removed");
endif
endfor
endif
if (item.isa($player))
for creation in (item.creations)
if (creation.id == E_OBJNF)
player.tell(item.id + ": creation " + tostr(creation) + " doesn't exist!");
item.rm_creation(creation);
player.tell("removed");
elseif (!(item in creation.owners))
player.tell(item.id + ": creation " + creation.id + " doesn't consider itself owned by " + item.id);
creation.add_owner(item);
player.tell("added");
endif
endfor
endif
if (item.isa($room))
for _exit in (item.exits)
if (_exit.id == E_OBJNF)
player.tell(item.id + ": exit " + tostr(_exit) + " doesn't exist!");
item.rm_exit(_exit);
player.tell("removed");
elseif (_exit.source != item)
player.tell(item.id + ": exit " + _exit.id + " thinks its source is " + tostr(_exit.source));
item.rm_exit(_exit);
player.tell("removed");
endif
endfor
endif
if (item.isa($exit))
if (item.source.id != #-1 && item.source.id == E_OBJNF)
player.tell(item.id + " source is destroyed?!");
item.set_dest(#-1);
player.tell("set to #-1");
elseif (item.dest.id != #-1 && item.dest.id == E_OBJNF)
player.tell(item.id + " dest is destroyed?!");
item.set_dest(#-1);
player.tell("set to #-1");
endif
endif
for owner in (item.owners)
if (owner.id == E_OBJNF)
player.tell(item.id + ": owner " + owner.id + " doesn't exist!");
item.rm_owner(owner);
player.tell("removed");
elseif (!owner.isa($player))
player.tell(item.id + ": owner " + owner.id + " is not a player.");
item.rm_owner(owner);
player.tell("removed");
elseif (!(item in owner.creations))
player.tell(item.id + ": thinks it's owned by " + owner.id + ", who doesn't think so");
owner.add_creation(item);
player.tell("added");
endif
endfor
endif
endfor
endmethod
method booted_at
return booted_at;
endmethod
method rm_visitor
visitors = visitors + {};
endmethod
method foo
var what;
for what in [0..tonum(dbtop)]
player.tell(toobj(what).id);
endfor
endmethod
method dbtop
return dbtop;
endmethod
method create_player
var who;
ignore E_METHODNF;
if (caller != #0)
raise E_PERM;
elseif (lengthof(args[1]) != 3)
echo("Usage: create <username> <password>", args[2]);
else
who = #0.find_player(args[1][2]);
if (who)
echo("That name is illegal, or already in use. Please choose another.", args[2]);
writelog("Player \"" + args[1][2] + "\" failed create on descriptor " + tostr(args[2]));
else
who = $player.clone(args[1][2]);
who.init;
who.setvar("password", crypt(args[1][3]));
set_parse(args[2], who);
player = who;
connected_players = connected_players + who;
players = players + who;
writelog("Player \"" + who.id + "\" created on descriptor " + tostr(args[2]));
who.connect;
endif
endif
endmethod
method rm_connected_player
connected_players = connected_players - caller;
endmethod
method wizards
return wizards;
endmethod
method rm_player
if (caller in wizards || caller == args[1])
players = players - args[1];
else
raise E_PERM;
endif
endmethod
method dump
var what, item;
ignore E_OBJNF;
for item in [0..tonum(dbtop)]
what = toobj(item);
if (what.id)
player.tell(what.decompile);
endif
endfor
endmethod
endobject
object #2
parents #1;
list contents = {};
str name = "Generic Located Object";
list owners = {#11};
num public = 1;
obj location = #-1;
method destroy
var thing, thome;
ignore E_METHODNF, E_SERVERDN, E_OBJNF;
if (this.can_write("", caller))
if (location)
location.remove(this);
endif
for thing in (contents)
thome = thing.home;
if (thome)
thing.moveto(thome);
else
thing.moveto(#-1);
endif
endfor
pass();
else
raise E_PERM;
endif
endmethod
method moveto
var dest, old_location;
ignore E_METHODNF, E_SERVERDN, E_OBJNF;
dest = args[1];
if (dest == location)
return 1;
elseif (dest == this)
return 0;
elseif (dest.contained_by(this))
return 0;
endif
lock("moveto");
if (dest && !dest.accept(this))
return 0;
endif
old_location = location;
location = dest;
if (old_location)
old_location.remove(this);
endif
return 1;
endmethod
method contents
return contents;
endmethod
method init
if (this == $located_obj)
this.add_owner(#11);
else
location = #-1;
contents = {};
pass();
endif
endmethod
method accept
var what, item;
what = args[1];
contents = contents + what;
if (serverof(what))
#0.add_visitor(what, this);
endif
for item in (contents)
item.event_entry(what);
endfor
return 1;
endmethod
method contained_by
if (location == args[1])
return 1;
elseif (!location)
return 0;
else
return location.contained_by(args[1]);
endif
endmethod
blocked method location
return location;
endmethod
method remove
var what, item;
what = args[1];
contents = contents - what;
if (serverof(what))
#0.rm_visitor(what, this);
endif
for item in (contents)
item.event_exit(what);
endfor
endmethod
method match_contents
var thing;
for thing in (contents)
if (thing.match(args[1]))
return thing;
endif
endfor
return #-1;
endmethod
blocked method set_contents
raise E_PERM;
endmethod
endobject
object #3
parents #1;
obj help_obj = #-1;
str name = "Generic Described Object";
list owners = {#11};
str desc = "";
num public = 1;
verb "l*ook ex*amine" = look_verb;
verb "@desc*ribe" : "as" = desc_verb;
method desc_verb
if (!this.match(args[2]))
return 1;
elseif (!this.can_write("desc", caller))
player.tell("Permission denied.");
else
desc = args[4];
player.tell("Description set.");
endif
endmethod
method init
if (this == $described_obj)
this.add_owner(#11);
else
pass();
endif
endmethod
method desc
return desc;
endmethod
method look_verb
if (!this.match(args[2]))
return 1;
endif
this.look;
endmethod
method help
ignore E_OBJNF;
return help_obj.help(args[1]);
endmethod
method match_full
var word, alias;
if (!args[1])
return 0;
elseif (args[1][1] == "#" && toobj(args[1]) == this)
return 1;
endif
if (aliases)
for alias in (explode(aliases, "\n"))
if (match_full(alias, args[1]))
return 1;
endif
endfor
endif
return match_full(name, args[1]);
endmethod
method look
if (this.desc)
player.tell(this.desc);
else
player.tell("You see nothing special.");
endif
endmethod
method match
var word, alias;
if (!args[1])
return 0;
elseif (args[1][1] == "#" && toobj(args[1]) == this)
return 1;
endif
if (aliases)
for alias in (explode(aliases, "\n"))
if (lengthof(explode(alias)) > 1)
if (match(alias, args[1]))
return 1;
endif
else
if (match_full(alias, args[1]))
return 1;
endif
endif
endfor
endif
return match(name, args[1]);
endmethod
endobject
object #4
parents #2, #3;
str name = "Generic Thing";
list owners = {#11};
num public = 1;
obj home = #-1;
verb "get take" = get;
verb "drop throw" = drop;
method drop
var result;
if (args[1] != "all" && !this.match(args[2]))
return 1;
elseif (location != player)
result = "You don't have that!";
elseif (this.moveto(player.location))
result = "Dropped.";
player.location.announce(player.name + " drops " + this.dname + ".", {player});
else
result = "You can't drop that.";
endif
if (args[1] == "all")
player.tell(name + ": " + result);
else
player.tell(result);
endif
endmethod
method id
return pass() to #3;
endmethod
method init
ignore E_METHODNF;
if (this == $thing)
this.add_owner(#11);
else
if (player.home)
home = player.home;
else
home = player;
endif
pass();
this.moveto(player);
endif
endmethod
method get
var result;
if (args[1] != "all" && !this.match(args[2]))
return 1;
elseif (location == player)
result = "You already have that!";
elseif (location != player.location)
result = "I don't see that here.";
elseif (this.moveto(player))
result = "Taken.";
player.location.announce(player.name + " takes " + this.dname + ".", {player});
else
result = "You can't get that.";
endif
if (args[1] == "all")
player.tell(name + ": " + result);
else
player.tell(result);
endif
endmethod
method accept
return 0;
endmethod
method location
return #-1;
endmethod
endobject
object #5
parents #4;
num transparent = 0;
list contents = {};
str name = "Generic Container";
list owners = {#11};
num public = 1;
num open = 1;
obj location = #-1;
num openable = 1;
obj home = #0;
verb "put place insert" : "in into" = put_in;
verb "l*ook" : "in into inside" = look_in;
verb "get remove take" : "from in out_of" = remove_from;
method remove_from
var what;
if (!this.match(args[4]))
return 1;
elseif (!open)
player.tell(this.dnamec + " is closed.");
return 0;
endif
what = this.match_contents(args[2]);
if (!what)
player.tell("That object is not inside " + this.dname + ".");
elseif (what.moveto(player))
player.tell("You remove " + what.iname + " from " + this.dname + ".");
else
player.tell("You can't remove that.");
endif
endmethod
method init
if (this == $container)
this.add_owner(#11);
endif
pass();
endmethod
method close
if (!this.match(args[2]))
return 1;
elseif (!openable)
player.tell("You can't close that!");
elseif (!open)
player.tell("It's already closed!");
else
open = 0;
player.tell("You close " + this.dname + ".");
location.announce(player.name + " closes " + this.dname + ".", {player});
endif
endmethod
method accept
return pass(args[1]) to #2;
endmethod
method put_in
var what;
if (!this.match(args[4]))
return 1;
endif
what = player.match_contents(args[2]);
if (!what)
player.tell("You don't have that.");
elseif (what.moveto(this))
player.tell("You put " + what.dname + " into " + this.dname + ".");
else
player.tell("You can't put " + what.dname + " into " + this.dname + ".");
endif
endmethod
method open
if (!this.match(args[2]))
return 1;
elseif (!openable)
player.tell("You can't open that!");
elseif (open)
player.tell("It's already open!");
else
open = 1;
player.tell("You open " + this.dname + ".");
location.announce(player.name + " opens " + this.dname + ".", {player});
endif
endmethod
method look_in
var thing;
if (!this.match(args[4]))
return 1;
endif
if (open || transparent)
if (contents)
player.tell("Inside " + this.dname + " you see:");
for thing in (contents)
player.tell(" " + thing.name);
endfor
else
player.tell("You see nothing inside " + this.dname + ".");
endif
else
player.tell("You can't look inside " + this.dname + ", it's closed.");
endif
endmethod
method look
var thing;
pass() to #3;
if (openable)
if (open)
player.tell("It is open.");
else
player.tell("It is closed.");
endif
endif
if (this.contents && (open || transparent))
player.tell("Containing:");
for thing in (this.contents)
player.tell(" " + thing.iname);
endfor
endif
endmethod
endobject
object #6
parents #2, #3;
str disconnect_oarrive = "%n appears from nowhere.";
str disconnect_leave = "You vanish into darkness.";
str disconnect_oleave = "%n falls unconcious and vanishes.";
list contents = {#12, #16};
obj help_obj = #15;
str disconnect_arrive = "";
str name = "Generic Room";
num open_ok = 0;
num link_ok = 0;
obj news_obj = #17;
list owners = {#11};
num public = 1;
list exits = {};
obj disconnect_to = #-1;
list invisible_contents = {};
verb "go move" = go_verb;
method disconnect_oarrive
return disconnect_oarrive;
endmethod
method destroy
var exit, thing;
ignore E_SERVERDN, E_OBJNF;
if (!(caller == this || caller in owners || caller in parents || caller == #0 || caller in #0.wizards || !owners))
raise E_PERM;
else
for exit in (exits)
exit.destroy;
endfor
pass();
endif
endmethod
method disconnect_leave
return disconnect_leave;
endmethod
method id
return pass() to #3;
endmethod
method announce
var dude;
ignore E_METHODNF, E_SERVERDN;
for dude in (contents)
if (lengthof(args) == 1 || !(dude in args[2]))
dude.tell(args[1]);
endif
endfor
endmethod
method disconnect_oleave
return disconnect_oleave;
endmethod
method disconnect_arrive
return disconnect_arrive;
endmethod
method go_verb
if (!args[2])
player.tell("Go where?");
elseif (this.go(args[2]))
player.tell("There is no passage in that direction.");
endif
endmethod
method open_ok
if (this.can_read("open_ok", caller))
return open_ok;
else
return 0;
endif
endmethod
method init
if (this == $room)
this.add_owner(#11);
elseif (this.can_write("", caller))
exits = {};
pass();
else
raise E_PERM;
endif
endmethod
method link_ok
if (this.can_read("link_ok", caller))
return link_ok;
else
return 0;
endif
endmethod
method set_exits
raise E_PERM;
endmethod
method go
var exit;
for exit in (exits)
if (exit.match_full(args[1]) && exit.dest)
exit.activate;
return 0;
endif
endfor
for exit in (exits)
if (exit.match(args[1]) && exit.dest)
exit.activate;
return 0;
endif
endfor
return -1;
endmethod
method help
var item, text;
ignore E_METHODNF;
text = help_obj.help(args[1]);
if (text)
return text;
else
for item in (contents)
text = item.help(args[1]);
if (text)
return text;
endif
endfor
endif
endmethod
method match_contents
var exit;
for exit in (exits)
if (exit.match(args[1]))
return exit;
endif
endfor
return pass(@args);
endmethod
method exits
return exits;
endmethod
method rm_exit
if (this.can_write("exits", caller))
exits = exits - args[1];
else
raise E_PERM;
endif
endmethod
method add_exit
if (this.can_write("exits", caller))
exits = exits + args[1];
else
raise E_PERM;
endif
endmethod
method news
var item, text;
ignore E_METHODNF;
return news_obj.news(args[1]);
endmethod
method disconnect_to
return disconnect_to;
endmethod
method look
var thing, nm;
ignore E_SERVERDN, E_OBJNF;
player.tell(this.name);
if (this.desc)
player.tell(this.desc);
endif
if (contents && !dark)
for thing in (contents)
if (thing != player && !thing.dark && !thing.sublocation)
nm = thing.sdesc;
if (nm == E_SERVERDN || nm == E_OBJNF)
player.tell("(Ghost of " + tostr(thing) + " is here.)");
else
player.tell(nm);
endif
endif
endfor
endif
if (exits && !dark)
player.tell("Exits:");
for thing in (exits)
if (thing.name)
player.tell(thing.name);
endif
endfor
endif
endmethod
method match_exit
var exit;
for exit in (exits)
if (exit.match(args[1]))
return exit;
endif
endfor
return #-1;
endmethod
method match
return args[1] == "here" && player.location == this;
endmethod
endobject
object #7
parents #3;
obj source = #-1;
str leave = "";
str oleave = "%n leaves through exit %exit.";
str name = "Generic Exit";
list owners = {#11};
num public = 1;
str arrive = "";
str oarrive = "%n arrives through exit %exit.";
obj dest = #-1;
method find_mate
var what;
for what in (dest.exits)
if (what.dest == source)
return what;
endif
endfor
return #-1;
endmethod
method source
return source;
endmethod
method destroy
ignore E_OBJNF;
if (this.can_write("", caller))
if (source && source.id != E_OBJNF)
source.rm_exit(this);
endif
pass();
else
raise E_PERM;
endif
endmethod
method name
if (dark < 1)
return name;
endif
endmethod
method init
if (this == #7)
this.add_owner(#11);
elseif (this.can_write("", caller))
source = #-1;
dest = #-1;
pass();
else
raise E_PERM;
endif
endmethod
method set_source
if (this.can_write("source", caller))
source = args[1];
else
raise E_PERM;
endif
endmethod
method activate
var pname;
ignore E_SERVERDN;
pname = player.name;
if (dest.name == E_SERVERDN)
player.tell("You can't go that way right now.");
return 0;
elseif (!player.moveto(dest, leave, oleave, arrive, oarrive))
player.tell("You can't go that way.");
return 0;
endif
endmethod
method set_dest
if (this.can_write("dest", caller))
dest = args[1];
else
raise E_PERM;
endif
endmethod
method dest
return dest;
endmethod
endobject
object #8
parents #2, #3;
str editing_type = "";
str editing_method = "";
num last_cmd_at = 0;
num proper_name = 1;
str editing_var = "";
str name = "Generic Player";
str gender = "";
str read_input = "";
obj editing_obj = #-1;
str password = "";
list owners = {#11};
str done_reading = "";
num public = 1;
num connected_at = 0;
num reading = 0;
obj home = #-1;
list editing_list = {};
list creations = {};
verb "dr*op th*row" = drop_cmd;
verb "get ta*ke" = get_cmd;
verb "help" = help_cmd;
verb "home" = gohome_cmd;
verb "i inv*entory" = inventory_cmd;
verb "l*ook" = look_cmd;
verb "news" = news_cmd;
verb "@password password" : "to" = password_cmd;
verb "@password password" = password_cmd;
verb "po*se" = pose_cmd;
verb "quit @quit" = quit_cmd;
verb "rwho" = rwho_cmd;
verb "sa*y" = say_cmd;
verb "who @who" = who_cmd;
verb "wh*isper" : "to" = whisper_cmd;
verb "wiz*ards" = wizards_cmd;
verb "edit_var" : "on" = edit_var_cmd;
verb "clear_edit" = clear_edit;
verb "list" = list_edit;
verb "insert" : "at" = insert;
verb "delete" = delete;
verb "save" = save;
verb "replace" : "with" = replace;
verb "rename" = rename;
verb "append" = append;
verb "@home" = home_cmd;
verb "@gender" = gender_cmd;
verb "exits" = exits_cmd;
verb "uptime" = uptime_cmd;
verb "blank" = blank;
verb "give" : "to" = give_verb;
verb "p*age" : "with" = page_cmd;
verb "p*age" = page_cmd;
verb "@aliases" : "to" = aliases_cmd;
verb "@cpvar" : "to" = cpvar_cmd;
method edit_var_cmd
var what, tl, i;
ignore E_TYPE, E_VARNF, E_MAPNF;
what = this.match_env(args[4]);
if (!what)
player.tell("I don't see that here.");
else
if (what.can_write("", caller))
editing_obj = what;
editing_type = "v";
editing_method = "";
editing_var = args[2];
tl = explode(editing_var);
if (lengthof(tl) > 1)
for i in [3..lengthof(tl)]
tl[2] = tl[2] + " " + tl[i];
endfor
if (lengthof(what.getvar(tl[1])) < 1)
what.compile("edit_temp_method", "setvar(\"" + tl[1] + "\",[\"" + tl[2] + "\" => \"\" ]);");
what.edit_temp_method;
what.rm_method("edit_temp_method");
endif
tl = what.getvar(tl[1])[tl[2]];
else
tl = what.getvar(editing_var);
endif
if (typeof(tl) != 0)
tl = tostr(tl);
endif
editing_list = explode(tl, "\n");
else
raise E_PERM;
endif
player.tell("Now editing variable " + args[2] + " on object " + tostr(what));
endif
endmethod
method drop_cmd
var thing;
ignore E_METHODNF, E_SERVERDN, E_OBJNF;
if (caller != this)
return 1;
elseif (args[2] == "all" || args[2] == "everything")
if (!contents)
echo("You are empty-handed.");
else
for thing in (contents)
if (thing.drop("all") == E_METHODNF)
echo(thing.name + ": You can't drop that.");
endif
endfor
endif
else
return 1;
endif
endmethod
method inventory_cmd
var item;
if (contents)
echo("You are carrying:");
this.inv;
else
echo("You are empty-handed.");
endif
endmethod
method destroy
var thing, tid;
ignore E_METHODNF, E_SERVERDN, E_OBJNF;
if (this.can_write("", caller))
for thing in (creations)
tid = thing.id;
if (tid == E_OBJNF || tid == E_SERVERDN)
continue;
endif
if (thing != this)
thing.rm_owner(this);
if (!thing.owners)
thing.destroy;
endif
endif
endfor
#0.rm_player(this);
pass();
else
raise E_PERM;
endif
endmethod
method id
return pass() to #3;
endmethod
method announce
if (lengthof(args) == 1 || !(this in args[2]))
this.tell("From inside you, " + args[1]);
endif
endmethod
method telln
var tempstr;
if (typeof(args[1]) == 0)
tempstr = args[1];
else
tempstr = tostr(args[1]);
endif
echon(tempstr);
endmethod
method moveto
var oldloc;
ignore E_RANGE, E_METHODNF;
oldloc = location;
if (pass(args[1]))
if (args[2])
echo(args[2]);
endif
if (oldloc)
if (args[3])
oldloc.announce(this.psub(args[3], ["exit" => caller.name]), {this, location});
endif
endif
this.look_around;
if (args[4])
echo(args[4]);
endif
if (location)
if (args[5])
if (caller.find_mate)
location.announce(this.psub(args[5], ["exit" => caller.find_mate.name]), {this, oldloc});
endif
endif
endif
return 1;
else
return 0;
endif
endmethod
method last_cmd_at
return last_cmd_at;
endmethod
method gender_cmd
if (caller != this)
return 1;
else
gender = args[2];
player.tell("Gender set.");
endif
endmethod
method input_to
if (caller != this && !(caller in #0.wizards))
raise E_PERM;
endif
reading = 1;
read_input = "";
done_reading = args[1];
endmethod
method password_cmd
if (caller != this)
return 1;
elseif (!args[2] || !args[4])
echo("Usage: @password <oldpasswd> to <newpasswd>");
elseif (crypt(args[2], password[1..2]) != password)
echo("Incorrect old password.");
else
password = crypt(args[4]);
echo("Password changed.");
endif
endmethod
method inv
var thing, nm;
ignore E_SERVERDN;
for thing in (contents)
nm = thing.iname;
if (nm == E_SERVERDN)
player.tell(" (Ghost of " + tostr(thing) + ")");
else
player.tell(" " + nm);
endif
endfor
endmethod
method help_cmd
var text;
ignore E_METHODNF;
if (caller != this)
return 1;
endif
text = location.help(args[2]);
if (text)
player.telln(text);
else
player.tell("No help found!");
endif
endmethod
method whisper_cmd
var who;
ignore E_METHODNF;
if (caller != this)
return 1;
endif
who = this.match_env(args[4]);
if (!who)
echo("I don't see that here.");
elseif (who.tell(name + " whispers, \"" + args[2] + "\"") == 0)
echo("You whisper, \"" + args[2] + "\" to " + who.name);
else
echo("You can't whisper to that!");
endif
endmethod
method blank
if (!args[2])
this.append("blank", " ");
else
this.insert("blank", " ", "at", args[2]);
endif
endmethod
method delete
editing_list = listdelete(editing_list, tonum(args[2]));
player.tell("Deleted line " + args[2]);
endmethod
method news_cmd
var text;
ignore E_METHODNF;
if (caller != this)
return 1;
endif
text = location.news(args[2]);
if (text)
player.telln(text);
else
player.tell("No news found!");
endif
endmethod
method gender
return gender;
endmethod
method rm_creation
creations = creations - args[1];
endmethod
method init
if (this == $player)
this.add_owner(#11);
elseif (this.can_write("", caller))
pass();
this.add_owner(this);
home = $player_start;
this.moveto(home);
last_cmd_at = time();
#0.add_player(this);
else
raise E_PERM;
endif
endmethod
method gohome_cmd
ignore E_SERVERDN;
if (caller != this)
return 1;
endif
this.moveto(home, "Click click click...", name + " goes home.", "", name + " comes home.");
endmethod
method wizards_cmd
var wiz;
echo("Your wizards are:");
for wiz in (#0.wizards)
player.tell(" " + wiz.name);
endfor
endmethod
method sdesc
if (this in #0.connected_players)
return name + " is here.";
else
return name + " is here, but is sleeping.";
endif
endmethod
method insert
var tempstr;
ignore E_RANGE;
if (typeof(args[2]) == 0)
tempstr = args[2];
else
tempstr = tostr(args[2]);
endif
if (tonum(args[4]) > lengthof(editing_list))
this.append(args[1], tempstr);
else
editing_list = listinsert(editing_list, tempstr, tonum(args[4]));
player.tell("Inserted " + tempstr + " before line " + args[4]);
endif
endmethod
method pose_cmd
if (caller != this)
return 1;
endif
if (args[2][1] == ":")
location.announce(name + args[2][2..]);
else
location.announce(name + " " + args[2]);
endif
endmethod
method home_cmd
var what;
what = this.match_env(args[2]);
if (!what)
player.tell("I don't see that here.");
else
home = what;
player.tell("Home set.");
endif
endmethod
method connect
echo("*** Connected ***");
connected_at = time();
this.look_around;
if (location)
location.announce(name + " has connected.", {player});
endif
endmethod
method rename
if (editing_type == "v")
editing_var = args[2];
else
editing_method = args[2];
endif
player.tell("Editing session renamed to " + args[2] + ", to take effect when saved.");
endmethod
method append
var tempstr;
if (typeof(args[2]) == 0)
tempstr = args[2];
else
tempstr = tostr(args[2]);
endif
editing_list = listappend(editing_list, tempstr);
player.tell("Appended " + tempstr);
endmethod
method list_edit
var count, loop, line;
if (lengthof(editing_list) < 1)
player.tell("Editing buffer currently empty.");
endif
count = 1;
for line in (editing_list)
if (!args[2])
line = tostr(count) + ": " + line;
for loop in [1..3 - lengthof(tostr(count))]
line = " " + line;
endfor
endif
count = count + 1;
player.tell(line);
endfor
endmethod
method match_env
var s, what, loc;
ignore E_VARNF, E_SERVERDN;
s = args[1];
if (!s)
return #-1;
elseif (s[1] == "#")
return toobj(s);
elseif (s == "me")
return player;
elseif (s == "here" && location)
return location;
elseif (s == "nowhere")
return #-1;
elseif (s[1] == "$" && lengthof(s) > 1)
what = #0.getvar(s[2..]);
if (what == E_VARNF || typeof(what) != 2)
return #-1;
else
return what;
endif
endif
what = this.match_contents(s);
if (what)
return what;
endif
if (location)
what = location.match_contents(s);
if (what)
return what;
endif
endif
return #-1;
endmethod
method replace
this.delete("", args[2]);
this.insert("", args[4], "", args[2]);
endmethod
method get_cmd
var cont, thing;
ignore E_METHODNF, E_SERVERDN, E_OBJNF;
if (this.match(args[2]))
player.tell("What do you think this is, a pick-up joint?");
elseif (caller != this)
return 1;
elseif (args[2] == "all" || args[2] == "everything")
cont = location.contents - this;
if (!cont)
echo("There's nothing here to get!");
else
for thing in (cont)
if (thing.get("all", "") == E_METHODNF)
echo(thing.name + ": You can't get that.");
endif
endfor
endif
else
return 1;
endif
endmethod
method look_cmd
if (!args[2])
this.look_around;
elseif (this.match(args[2]))
this.look;
else
return 1;
endif
endmethod
method parse
var thing, cmd, r;
ignore E_SERVERDN, E_TIMEOUT;
if (caller != this && !(caller in #0.wizards))
raise E_PERM;
endif
lock("parse");
last_cmd_at = time();
cmd = args[1];
if (reading)
if (cmd == ".")
reading = 0;
this.(done_reading)(read_input);
read_input = "";
else
read_input = read_input + cmd + "\n";
endif
return 0;
endif
if (!cmd)
return 0;
elseif (cmd[1] == "\"")
if (lengthof(cmd) > 1)
cmd = "say " + cmd[2..];
else
cmd = "say ";
endif
elseif (cmd[1] == ":")
if (lengthof(cmd) > 1)
cmd = "pose " + cmd[2..];
else
cmd = "pose ";
endif
elseif (cmd[1] == ";")
if (lengthof(cmd) > 1)
cmd = "eval " + cmd[2..];
else
cmd = "eval ";
endif
endif
if (!this.call_verb(cmd))
return 0;
endif
for thing in (contents)
if (thing.call_verb(cmd) == 0)
return 0;
endif
endfor
if (location)
if (location.call_verb(cmd) == 0)
return 0;
endif
for thing in (location.contents)
if (thing != this)
if (thing.call_verb(cmd) == 0)
return 0;
endif
endif
endfor
if (location.go(cmd) == 0)
return 0;
endif
for thing in (location.exits)
if (thing.call_verb(cmd) == 0)
return 0;
endif
endfor
endif
echo("I don't understand that.");
endmethod
method psub
var n, s, o, p, q, r, left, right, vartext, settext, retval, methodtext;
ignore E_RANGE;
n = name;
if (gender && gender[1] == "m")
s = "he";
o = "him";
p = "his";
q = "his";
r = "himself";
elseif (gender && gender[1] == "f")
s = "she";
o = "her";
p = "her";
q = "hers";
r = "herself";
else
s = "it";
o = "it";
p = "its";
q = "its";
r = "itself";
endif
vartext = "var n,s,o,p,q,r";
settext = "n=" + tostr(n) + ";s=" + tostr(s) + ";o=" + tostr(o) + ";p=" + tostr(p) + ";q=" + tostr(q) + ";r=" + tostr(r) + ";";
if (typeof(args[2]) == 4)
for left in (args[2])
if (typeof(left) == 0)
vartext = vartext + "," + left;
right = args[2][left];
if (typeof(right) != 0)
right = tostr(right);
endif
settext = settext + left + "=" + tostr(right) + ";";
endif
endfor
methodtext = vartext + "; " + settext + " return psub(" + tostr(args[1]) + ");";
compile(this, "psub_temp_method", methodtext);
retval = this.psub_temp_method;
this.rm_method("psub_temp_method");
return retval;
else
return psub(args[1]);
endif
endmethod
method who_cmd
if (caller != this)
return 1;
endif
#0.who;
endmethod
method teleport_cmd
var what, dest;
what = this.match_env(args[2]);
dest = this.match_env(args[4]);
if (!what)
echo("Teleport what?");
elseif (!dest && args[4] != "nowhere" && args[4] != "#-1")
echo("Teleport it where?");
elseif (!what.moveto(dest, "You feel a wrenching sensation.."))
echo("You can't teleport that.");
else
echo("Teleported.");
endif
endmethod
method save
var editstr, m, what, line, i;
what = editing_obj;
if (what.can_write("", caller))
editstr = editing_list[1];
if (lengthof(editing_list) > 1)
for line in (editing_list[2..])
editstr = editstr + "\n" + line;
endfor
endif
m = explode(editing_var);
if (lengthof(m) > 1)
for i in [3..lengthof(m)]
m[2] = m[2] + " " + m[i];
endfor
compile(what, "edit_temp_method", m[1] + "[\"" + m[2] + "\"] = " + tostr(editstr) + ";");
what.edit_temp_method;
what.rm_method("edit_temp_method");
else
editing_obj.setvar(editing_var, editstr);
endif
player.tell("Variable " + editing_var + " on object " + tostr(editing_obj) + " saved.");
else
raise E_PERM;
endif
endmethod
method page_cmd
var who, locname;
ignore E_METHODNF, E_SERVERDN, E_OBJNF;
if (caller != this)
return 1;
elseif (!args[2])
echo("Usage: page <player>");
echo(" page <player> with <message>");
return 0;
endif
locname = location.name;
who = #0.find_connected_player(args[2]);
if (!who)
echo("That player is not connected.");
elseif (args[4])
who.tell(name + " pages, \"" + args[4] + "\"");
echo("Your message has been sent.");
elseif (typeof(locname) == 0)
who.tell("You sense that " + name + " is looking for you in " + locname + ".");
echo("Your message has been sent.");
else
who.tell("You sense that " + name + " is looking for you.");
echo("Your message has been sent.");
endif
endmethod
method say_cmd
if (caller != this)
return 1;
endif
echo("You say, \"" + args[2] + "\"");
location.announce(name + " says, \"" + args[2] + "\"", {player});
endmethod
method uptime_cmd
if (caller != this)
return 1;
else
player.tell("Up for " + #0.convtime(time() - #0.booted_at));
endif
endmethod
method look
pass() to #3;
if (contents)
player.tell("Carrying:");
this.inv;
endif
endmethod
method look_around
var r;
ignore E_SERVERDN, E_OBJNF;
player = this;
r = location.look;
if (r == E_SERVERDN)
echo("The outlines of the room you are in have suddenly become hazy and indistinct. Going \"home\" might be useful about now.");
elseif (r == E_OBJNF)
echo("You're absolutely nowhere. Go home.");
endif
endmethod
method aliases_cmd
var what;
what = this.match_env(args[2]);
what.set_aliases(strsub(args[4], ";", "\n"));
endmethod
method set_name
var existing;
existing = #0.find_player(args[1]);
if (!this.can_write("name", caller))
raise E_PERM;
elseif (existing && existing != this)
raise E_RANGE;
else
pass(args[1]) to #3;
endif
endmethod
method rwho_cmd
var sysobj;
ignore E_SERVERDN;
for sysobj in (servers())
echo("Server \"" + servername(sysobj) + "\": ");
if (sysobj.who == E_SERVERDN)
echo(" Server down.");
else
echo("---");
endif
endfor
endmethod
method quit_cmd
if (caller != this && caller != #0 && !(caller in #0.wizards))
return 1;
endif
echo("*** Disconnected ***");
disconnect();
endmethod
method disconnect
#0.rm_connected_player(this);
if (location.disconnect_to)
this.moveto(location.disconnect_to, location.disconnect_leave, location.disconnect_oleave, location.disconnect_arrive, location.disconnect_oarrive);
else
location.announce(name + " has disconnected.", {player});
endif
endmethod
method connected_at
return connected_at;
endmethod
method clear_edit
if (caller == this || caller in owners || caller == #0 || caller in #0.wizards)
editing_method = "";
editing_obj = #-1;
editing_list = {};
editing_type = "";
editing_var = "";
player.tell("Cleared all editing data.");
else
raise E_PERM;
endif
endmethod
method match
if (args[1] == "me" && player == this)
return 1;
else
return pass(args[1]) to #3;
endif
endmethod
method give_verb
var who, what;
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4])
player.tell("Usage: give <object> to <player>");
return 0;
endif
what = this.match_env(args[2]);
who = this.match_env(args[4]);
if (!what)
player.tell("I don't see that here.");
elseif (what.location != this)
player.tell("You're not carrying that!");
elseif (!who)
player.tell("I don't see that player here.");
elseif (!who.isa($player))
player.tell("That's not a player!");
elseif (!what.moveto(who))
player.tell(who.name + " doesn't want it!");
else
player.tell("You give " + what.name + " to " + who.name + ".");
who.tell(player.name + " gives you " + what.name + ".");
endif
endmethod
method exits_cmd
var exit, exitname, spos, exitlist;
exitlist = {};
if (caller != this)
return 1;
else
for exit in (location.exits)
if (!exit.dark)
exitname = exit.name;
spos = ";" in exitname;
if (spos)
exitname = exitname[1..spos - 1];
endif
exitlist = listappend(exitlist, exitname);
endif
endfor
if (exitlist)
player.tell("Exits: " + #12.english_list_str(exitlist) + ".");
else
player.tell("No exits.");
endif
endif
endmethod
method home
return home;
endmethod
method add_creation
creations = creations + args[1];
endmethod
method tell
var tempstr;
if (typeof(args[1]) == 0)
tempstr = args[1];
else
tempstr = tostr(args[1]);
endif
echo(tempstr);
endmethod
method cpvar_cmd
var what, meth, towhat, tometh;
what = toobj(explode(args[2], ".")[1]);
meth = explode(args[2], ".")[2];
towhat = toobj(explode(args[4], ".")[1]);
tometh = explode(args[4], ".")[2];
if (!towhat.setvar(tometh, what.getvar(meth)))
player.tell("Variable copied.");
else
player.tell("Variable copy failed.");
endif
endmethod
method set_password
raise E_PERM;
endmethod
method creations
return creations;
endmethod
endobject
object #9
parents #8;
str name = "Generic Builder";
list owners = {#11};
num public = 1;
verb "@addo*wner" : "on to onto" = addowner_cmd;
verb "@addo*wner" = addowner_cmd;
verb "@addp*arent" : "on to onto" = addparent_cmd;
verb "@addp*arent" = addparent_cmd;
verb "@clone" : "named" = clone_cmd;
verb "@clone" = clone_cmd;
verb "@create" = create_cmd;
verb "@destroy" = destroy_cmd;
verb "@dig" = dig_cmd;
verb "@find" = find_cmd;
verb "@link" : "to" = link_cmd;
verb "@link" = link_cmd;
verb "@list" : "on" = list_cmd;
verb "@list" = list_cmd;
verb "@open" : "to" = open_cmd;
verb "@open" = open_cmd;
verb "@methods" = methods_cmd;
verb "@mutate" : "to into" = mutate_cmd;
verb "@mutate" = mutate_cmd;
verb "@pub*lish" = publish_cmd;
verb "@unpub*lish" = unpublish_cmd;
verb "@rmp*arent" : "from on to onto" = rmparent_cmd;
verb "@rmp*arent" = rmparent_cmd;
verb "@rmo*wner" : "from on to onto" = rmowner_cmd;
verb "@rmo*wner" = rmowner_cmd;
verb "@set" : "to" = set_cmd;
verb "@set" = set_cmd;
verb "@show" = show_cmd;
verb "@spew" : "on" = spew_cmd;
verb "@spew" = spew_cmd;
verb "@tel*eport" : "to" = teleport_cmd;
verb "@ve*rbs" = verbs_cmd;
verb "@decompile" = decompile_cmd;
verb "@rmvar" : "on" = rmvar_cmd;
verb "@rmvar" = rmvar_cmd;
method publish_cmd
var what;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Usage: @publish <thing>");
return 0;
endif
what = this.match_env(args[2]);
if (!what)
player.tell("I don't see that here.");
elseif (what.publish)
player.tell("You can't publish that.");
else
player.tell(what.id + " published.");
endif
endmethod
method addowner_cmd
var what, owner;
ignore E_PERM;
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4])
player.tell("Usage: @addowner <what> to <thing>");
return 0;
endif
owner = #0.find_player(args[2]);
what = this.match_env(args[4]);
if (!owner)
player.tell("\"" + args[2] + "\" is not the name of any player.");
elseif (!what)
player.tell("I don't see that here.");
elseif (what.add_owner(owner) == E_PERM)
player.tell("Permission denied.");
else
player.tell("Owner added.");
endif
endmethod
method link_cmd
var exit;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Link what?");
elseif (!args[3])
player.tell("Usage: @link <exit name> to <room #>");
else
exit = location.match_exit(args[2]);
if (!exit)
player.tell("I don't know what you want to link!");
else
this.link(exit, args[4]);
endif
endif
endmethod
method set_cmd
var r, dotpos, objname, propname, what, oldvalue, newvalue;
ignore E_METHODNF, E_VARNF;
dotpos = "." in args[2];
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4] || !dotpos || dotpos == 1 || dotpos == lengthof(args[2]))
player.tell("Usage: @set <thing>.<property> to <value>");
else
objname = args[2][..dotpos - 1];
propname = args[2][dotpos + 1..];
what = this.match_env(args[2][1..dotpos - 1]);
if (!what || what.name == E_OBJNF)
player.tell("I don't see that here.");
else
r = what.("set_" + propname)(args[4]);
if (r == E_METHODNF)
oldvalue = what.getvar(propname);
if (oldvalue == E_VARNF)
r = what.setvar(propname, args[4]);
elseif (typeof(oldvalue) == 0)
newvalue = args[4];
elseif (typeof(oldvalue) == 1)
newvalue = tonum(args[4]);
elseif (typeof(oldvalue) == 2)
newvalue = toobj(args[4]);
else
player.tell("Can't @set values of that type yet.");
return 0;
endif
r = what.setvar(propname, newvalue);
endif
if (typeof(r) != 5)
player.tell("Set.");
endif
endif
endif
endmethod
method create_cmd
var new;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Usage: @create <name>");
else
new = $thing.clone(args[2]);
new.add_owner(player);
player.tell("Thing created: " + new.id);
endif
endmethod
method test
#11.tell("caller: " + tostr(caller));
endmethod
method destroy_cmd
var what;
if (caller != this)
return 1;
endif
what = this.match_env(args[2]);
if (!what)
player.tell("What's a " + args[2] + "?");
else
what.destroy;
player.tell("Destroyed.");
endif
endmethod
method dig_cmd
var new;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Dig what?");
return 0;
endif
new = $room.clone(args[2]);
new.add_owner(player);
player.tell("Room dug: " + new.id);
endmethod
method decompile_cmd
var what;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Usage: @dump <object>");
else
what = this.match_env(args[2]);
if (!what)
player.tell("I don't see that here.");
else
player.tell(what.decompile);
endif
endif
endmethod
method methods_cmd
var what, m;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Usage: @methods <object>");
return 0;
endif
what = this.match_env(args[2]);
if (!what)
player.tell("I don't see that here.");
else
player.tell("Methods on " + what.id + ":");
for m in (sort(what.methods))
player.tell(" " + m);
endfor
player.tell("---");
endif
endmethod
method parent_result
if (args[1] == E_OBJNF)
player.tell("Parent does not exist.");
elseif (args[1] == E_INVIND)
player.tell("Parent must be local.");
elseif (args[1] == E_PERM)
player.tell("Parent permission denied.");
elseif (args[1] == E_RANGE)
player.tell("Object must have at least one parent.");
elseif (args[1] == E_MAXREC)
player.tell("New parent would cause a loop.");
else
player.tell("Parent invalid.");
endif
endmethod
method show_cmd
var r, what;
ignore E_METHODNF, E_SERVERDN, E_OBJNF;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Usage: @show <object>");
return 0;
endif
what = this.match_env(args[2]);
if (!what || what.name == E_OBJNF)
player.tell("I don't see that here.");
else
r = what.show(args[1], args[2]);
if (r == E_SERVERDN || r == E_METHODNF)
player.tell("You can't show that.");
endif
endif
endmethod
method addparent_cmd
var r, what, parent;
ignore E_RANGE, E_INVIND, E_MAXREC, E_PERM, E_OBJNF;
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4])
player.tell("Usage: @addparent <what> to <thing>");
return 0;
endif
what = this.match_env(args[4]);
parent = this.match_env(args[2]);
if (!what || !parent)
player.tell("I don't see that here.");
else
r = what.add_parent(parent);
if (typeof(r) == 5 && r != E_NONE)
this.parent_result(r);
else
player.tell("Parent added.");
endif
endif
endmethod
method find_cmd
var nm, thing;
ignore E_METHODNF;
if (caller != this)
return 1;
endif
for thing in (creations)
if (args[2])
if (thing.match(args[2]))
player.tell(thing.id);
endif
else
player.tell(thing.id);
endif
endfor
player.tell("---");
endmethod
method init
if (this == $builder)
this.add_owner(#11);
else
pass();
endif
endmethod
method rmparent_cmd
var r, what, parent;
ignore E_RANGE, E_INVIND, E_MAXREC, E_PERM, E_OBJNF;
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4])
player.tell("Usage: @rmparent <what> from <thing>");
return 0;
endif
what = this.match_env(args[4]);
parent = this.match_env(args[2]);
if (!what || !parent)
player.tell("I don't see that here.");
else
r = what.rm_parent(parent);
if (typeof(r) == 5 && r != E_NONE)
this.parent_result(r);
else
player.tell("Parent removed.");
endif
endif
endmethod
method unpublish_cmd
var what;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Usage: @unpublish <thing>");
return 0;
endif
what = this.match_env(args[2]);
if (!what)
player.tell("I don't see that here.");
elseif (what.unpublish)
player.tell("You can't publish that.");
else
player.tell(what.id + " unpublished.");
endif
endmethod
method rmowner_cmd
var what, owner;
ignore E_PERM;
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4])
player.tell("Usage: @rmowner <what> from <thing>");
return 0;
endif
owner = #0.find_player(args[2]);
what = this.match_env(args[4]);
if (!owner)
player.tell("\"" + args[2] + "\" is not the name of any player.");
elseif (!what)
player.tell("I don't see that here.");
elseif (what.rm_owner(owner) == E_PERM)
player.tell("Permission denied");
else
player.tell("Owner removed.");
endif
endmethod
method mutate_cmd
var r, what, newparent;
ignore E_RANGE, E_INVIND, E_MAXREC, E_PERM, E_OBJNF;
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4])
player.tell("Usage: @mutate <thing> into <what>");
return 0;
endif
what = this.match_env(args[2]);
newparent = this.match_env(args[4]);
if (!what || !newparent)
player.tell("I don't see that here.");
else
r = what.chparents({newparent});
if (typeof(r) == 5 && r != E_NONE)
this.parent_result(r);
else
player.tell("Mutated.");
endif
endif
endmethod
method save
pass(args);
endmethod
method clone_cmd
var parent, new;
if (caller != this)
return 1;
elseif (!args[2] || args[3] && !args[4])
player.tell("Usage: @clone <thing>");
player.tell(" @clone <thing> named <name>");
return 0;
endif
parent = this.match_env(args[2]);
if (!parent)
player.tell("I don't see that here.");
else
new = parent.clone(args[4]);
if (!new)
player.tell("You can't clone that.");
else
new.add_owner(player);
player.tell("New \"" + parent.name + "\" cloned: " + new.id);
endif
endif
endmethod
method list_cmd
var what, options, option, numbers, brackets, indent, methodname;
numbers = 1;
brackets = 0;
indent = 2;
if (caller != this)
return 1;
elseif (!args[2] || !args[4])
player.tell("Usage: @list [-b] [-n] <method> on <object>");
else
what = this.match_env(args[4]);
if (!what)
player.tell("I don't see that here.");
else
options = explode(args[2]);
if (lengthof(options) > 1)
for option in (options)
if (option == "-b")
brackets = 1;
elseif (option == "-n")
numbers = 0;
elseif (option[1..2] == "-i")
indent = tonum(option[3..]);
elseif (option[1] == "-")
player.tell("Usage: @list [-b] [-n] [-i<num> ] <method> on <object>");
return 0;
else
methodname = option;
endif
endfor
else
methodname = args[2];
endif
player.tell(what.list_method(methodname, numbers, brackets, indent));
endif
endif
endmethod
method spew_cmd
var what;
if (caller != this)
return 1;
elseif (!args[2] || !args[4])
player.tell("Usage: @spew <method> on <object>");
else
what = this.match_env(args[4]);
if (!what)
player.tell("I don't see that here.");
else
player.tell(what.spew_method(args[2]));
endif
endif
endmethod
method rmvar_cmd
var r, what;
ignore E_VARNF, E_PERM;
if (caller != this)
return 1;
endif
if (!args[2] || !args[3] || !args[4])
echo("Usage: @rmvar <var> on <obj>");
return 0;
endif
what = this.match_env(args[4]);
if (!what)
echo("I don't see that here.");
else
r = what.rm_var(args[2]);
if (typeof(r) == 5 && r != E_NONE)
echo(tostr(r) + ".");
else
echo("Variable removed.");
endif
endif
return 0;
endmethod
method link
var new_dest;
ignore E_METHODNF;
new_dest = this.match_env(args[2]);
if (!new_dest)
player.tell("Link to where?");
elseif (!new_dest.link_ok)
player.tell("You can't link to that!");
else
if (args[1].set_dest(new_dest))
player.tell("Linked.");
else
player.tell("Permission denied.");
endif
endif
endmethod
method open_cmd
var exit;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Open an exit in what direction?");
else
if (!location.open_ok)
player.tell("You can't open an exit here!");
else
exit = $exit.clone(args[2]);
exit.add_owner(player);
location.add_exit(exit);
exit.set_source(location);
player.tell("Exit " + exit.id + " opened.");
if (args[3])
this.link(exit, args[4]);
endif
endif
endif
endmethod
method verbs_cmd
var what, v;
if (caller != this)
return 1;
elseif (!args[2])
player.tell("Usage: @verbs <object>");
return 0;
endif
what = this.match_env(args[2]);
if (!what)
player.tell("I don't see that here.");
else
for v in (what.verbs)
if (v[2])
player.tell(" " + v[1] + " : " + v[2] + " = " + v[3]);
else
player.tell(" " + v[1] + " = " + v[3]);
endif
endfor
player.tell("---");
endif
endmethod
endobject
object #10
parents #9;
str name = "Generic Programmer";
list owners = {#11};
num public = 1;
str prog_method = "";
obj prog_obj = #-1;
verb "eval" = eval_cmd;
verb "@prog*ram" : "on" = program_cmd;
verb "@prog*ram" = program_cmd;
verb "@ps" = ps_cmd;
verb "@kill" = kill_cmd;
verb "@verb" : "on" = verb_cmd;
verb "@verb" = verb_cmd;
verb "@rmv*erb" : "on" = rmverb_cmd;
verb "@rmv*erb" = rmverb_cmd;
verb "@rmm*ethod" : "on" = rmmethod_cmd;
verb "@rmm*ethod" = rmmethod_cmd;
verb "edit_method" : "on" = edit_method_cmd;
verb "save" = save;
verb "@cpmethod" : "to" = cpmethod_cmd;
verb "@force" : "to" = force_cmd;
verb "@force" = force_cmd;
verb "pupdrop" = drop_cmd;
verb "pupget" = get_cmd;
method kill_cmd
var r, pid;
ignore E_PERM;
pid = tonum(args[2]);
r = kill(pid);
if (r == E_PERM)
echo("Permission denied.");
elseif (r != 0)
echo("No such process.");
else
echo("Killed.");
endif
endmethod
method test
#11.tell("caller: " + tostr(caller));
pass();
endmethod
method cpmethod_cmd
var what, meth, towhat, tometh;
what = toobj(explode(args[2], ".")[1]);
meth = explode(args[2], ".")[2];
towhat = toobj(explode(args[4], ".")[1]);
tometh = explode(args[4], ".")[2];
if (towhat.compile(tometh, what.list_method(meth, 0)))
player.tell("Method copied.");
else
player.tell("Method copy failed.");
endif
endmethod
method verb_cmd
var r, newargs, what, preplist, verblist;
if (caller != this)
return 1;
endif
newargs = explode(args[2]);
if (!args[2] || !args[3] || !args[4] || lengthof(newargs) < 2)
echo("Usage: @verb <verb> <method-to-call> on <obj>");
echo(" @verb <verb> <preposition> <method-to-call> on <obj>");
return 0;
endif
what = this.match_env(args[4]);
verblist = strsub(newargs[1], "/", " ");
if (lengthof(newargs) == 2)
preplist = "";
else
preplist = #1.implode(newargs[2..lengthof(newargs) - 1], " ");
endif
if (!what)
echo("I don't see that here.");
return 0;
endif
r = what.add_verb(verblist, preplist, newargs[lengthof(newargs)]);
if (r == E_PERM)
echo("Permission denied.");
else
echo("Verb added.");
endif
return 0;
endmethod
method edit_method_cmd
var what;
ignore E_METHODNF;
what = this.match_env(args[4]);
if (!what)
player.tell("I don't see that here.");
else
if (what.can_write("", caller))
what = what.find_method(args[2]);
if (!what)
what = this.match_env(args[4]);
editing_list = {"raise E_METHODNF;"};
else
editing_list = explode(what.list_method(args[2], 0), "\n");
endif
editing_obj = what;
editing_type = "m";
editing_var = "";
editing_method = args[2];
player.tell("Now editing method " + args[2] + " on object " + tostr(what));
else
raise E_PERM;
endif
endif
endmethod
method init
if (this == $programmer)
this.add_owner(#11);
else
pass();
endif
endmethod
method done_programming
if (prog_obj == #-1)
compile(args[1]);
else
if (!compile(prog_obj, prog_method, args[1]))
echo("Method programmed.");
else
raise E_PERM;
endif
endif
endmethod
method ps_cmd
var i, line, task;
echo("PID PLAYER METHOD STATUS TICKS AGE");
for task in (ps())
if (task[4] != this && !("a" in args[2]))
continue;
endif
line = pad(tostr(task[1]), 7) + " " + pad(task[4].id, 15) + " " + pad(tostr(task[6]) + "." + task[9], 15) + " ";
if (task[10] == 0)
line = line + "MSG ";
elseif (task[10] == 1)
line = line + "LOCK ";
elseif (task[10] == 2)
line = line + "TIMER ";
elseif (task[10] == 3)
line = line + "SYS_MSG";
endif
line = line + pad(tostr(task[3]), -7) + pad(tostr(task[2]), -5);
echo(line);
endfor
endmethod
method rmverb_cmd
var what, r;
ignore E_VERBNF, E_PERM;
if (caller != this)
return 1;
endif
if (!args[2] || !args[3] || !args[4])
echo("Usage: @rmverb <verb> on <obj>");
return 0;
endif
what = this.match_env(args[4]);
if (!what)
echo("I don't see that here.");
else
r = what.rm_verb(args[2]);
if (typeof(r) == 5 && r != E_NONE)
echo(tostr(r) + ".");
else
echo("Verb removed.");
endif
endif
return 0;
endmethod
method rmmethod_cmd
var r, what;
ignore E_METHODNF, E_PERM;
if (caller != this)
return 1;
endif
if (!args[2] || !args[3] || !args[4])
echo("Usage: @rmmethod <method> on <obj>");
return 0;
endif
what = this.match_env(args[4]);
if (!what)
echo("I don't see that here.");
else
r = what.rm_method(args[2]);
if (typeof(r) == 5 && r != E_NONE)
echo(tostr(r) + ".");
else
echo("Method removed.");
endif
endif
return 0;
endmethod
method program_cmd
var what;
ignore E_METHODNF;
if (caller != this)
return 1;
elseif (!args[2] && !args[3])
echo("Entering programming mode. Use \".\" to end");
prog_obj = #-1;
this.input_to("done_programming");
elseif (!args[2] || !args[3])
echo("Usage: @program <method> on <object>");
echo(" @program");
else
what = this.match_env(args[4]);
if (!what)
echo("I don't see that here.");
else
prog_obj = what;
prog_method = args[2];
echo("Programming " + args[2] + " on " + what.id);
echo("Entering programming mode. Use \".\" to end");
this.input_to("done_programming");
endif
endif
endmethod
method eval_cmd
if (caller != this)
return 1;
endif
if (!compile(this, "eval_tmp", args[2]))
echo("--> " + tostr(this.eval_tmp));
rm_method("eval_tmp");
endif
endmethod
method save
var compstr, line;
if (editing_obj.can_write("", caller))
if (editing_type == "v")
pass(args);
else
compstr = "";
for line in (editing_list)
compstr = compstr + line + "\n";
endfor
if (!compile(editing_obj, editing_method, compstr))
player.tell("Method " + editing_method + " on object " + tostr(editing_obj) + " compiled.");
endif
endif
else
raise E_PERM;
endif
endmethod
method force_cmd
var who;
if (caller != this)
return 1;
elseif (!args[2] || !args[3] || !args[4])
echo("Usage: @force <player> to <cmd>");
return 0;
endif
who = #0.find_player(args[2]);
if (!who)
echo("Force whom?");
else
player = who;
player.parse(args[4]);
endif
endmethod
endobject
object #11
parents #10;
str editing_type = "m";
str editing_method = "compile";
num last_cmd_at = 898288902;
list dark_vars = {};
list test = {#10, "test"};
list contents = {#19, #17, #15};
str editing_var = "";
str name = "Wizard";
str gender = "male";
str read_input = "";
obj editing_obj = #1;
str password = "AJHWPwNz7fdTs";
obj sublocation = #-1;
list owners = {#11};
str desc = "A short, aged guy with a pointy hat.";
str done_reading = "done_programming";
num public = 1;
str prog_method = "unsafe_cmd";
obj location = #13;
str exit = "test";
num connected_at = 898288988;
obj prog_obj = #8;
str aliases = "tz\n chaos lord tzeentch";
num reading = 0;
obj home = #13;
list editing_list = {"#11.tell(\"ARgs: \" + tostr(this) + \", \" + args[1] + \", \" + args[2] + \", \" + tostr(player) );", "if (!this.can_write(\"\", caller))", " raise E_PERM;", "endif", "return !compile(this, args[1], args[2]);"};
list creations = {#1, #0, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16, #17, #18, #19, #20, #21};
verb "@wiz*ard" = wiz_cmd;
verb "@dewiz*ard" = dewiz_cmd;
verb "@mem" = mem_cmd;
verb "@cachestats @cache_stats @cs" = cachestats_cmd;
verb "@vis*itors" = visitors_cmd;
verb "@boot" = boot_cmd;
verb "@shout" = shout_cmd;
verb "@shutdown" = shutdown_cmd;
verb "fixexits" = fixexits;
verb "@sync" = sync_cmd;
verb "scry_far" = scry;
verb "test" = test;
method dewiz_cmd
var who;
if (caller != this)
return 1;
elseif (!args[2])
echo("Usage: @dewizard <player>");
return 0;
endif
who = #0.find_player(args[2]);
if (!who)
echo("I couldn't find that player.");
elseif (!(who in #0.wizards))
echo("That's not a wizard.");
elseif (who == player)
echo("You can't dewiz yourself; ask another wizard.");
else
#0.rm_wizard(who);
endif
endmethod
method boot_cmd
var who;
if (caller != this)
return 1;
elseif (!args[2])
echo("Usage: @boot <player>");
return 0;
endif
who = #0.find_connected_player(args[2]);
if (!who)
echo("That player is not connected.");
else
if (who.quit_cmd)
echo("You can't boot that player.");
else
echo("Player booted.");
endif
endif
endmethod
method wiz_cmd
var who;
if (caller != this)
return 1;
elseif (!args[2])
echo("Usage: @wizard <player>");
return 0;
endif
who = #0.find_player(args[2]);
if (!who)
echo("I couldn't find that player.");
elseif (who in #0.wizards)
echo(who.name + " is already a wizard.");
elseif (!(who in #0.players))
echo("That's not a player.");
else
#0.add_wizard(who);
endif
endmethod
method visitors_cmd
var item, id;
ignore E_SERVERDN;
if (caller != this)
return 1;
endif
echo("Remote objects:");
for item in (#0.visitors)
id = item[1].id;
if (id == E_SERVERDN)
echo("(Ghost of " + tostr(item[1]) + ") is in " + item[2].id);
else
echo(item[1].id + " is in " + item[2].id);
endif
endfor
echo("---");
endmethod
method scry
var server, what, sname;
ignore E_METHODNF, E_OBJNF, E_TIMEOUT;
for server in (#0.connected_servers)
sname = "Wizard";
for what in [1..server.dbtop]
what = toobj("#" + tostr(what) + "@" + sname);
if (!what.name)
continue;
endif
if (match(what.name, args[2], "\n"))
what.show;
return 0;
endif
endfor
endfor
player.tell("The waters are cloudy.");
endmethod
method shout_cmd
var dude, msg;
if (caller != this)
return 1;
endif
msg = "Wizard";
for dude in (#0.connected_players)
dude.tell(msg);
endfor
endmethod
method init
if (this == $wizard)
name = "Wizard";
password = "AJHWPwNz7fdTs";
desc = "A short, aged guy with a pointy hat.";
this.add_owner(#11);
endif
pass() to #8;
endmethod
method shutdown_cmd
if (caller != this)
return 1;
endif
writelog("SHUTDOWN by " + this.id);
shutdown();
endmethod
method cachestats_cmd
echo(cache_stats());
endmethod
method sync_cmd
if (caller == this)
sync();
endif
endmethod
method parse
pass(@args);
endmethod
method match_full
if (args[1] == "me" && player == this)
return 1;
else
return pass(args[1]) to #3;
endif
endmethod
method mem_cmd
if (caller != this)
return 1;
endif
echo(checkmem());
endmethod
endobject
object #12
parents #4;
num proper_name = 1;
str name = "Network Tools";
str victim = "@localhost";
obj who = #31;
list owners = {#11};
str desc = "";
obj location = #6;
verb "finger" = finger;
method finger
var atpos, host;
atpos = "@" in args[2];
if (atpos)
if (atpos >= lengthof(args[2]))
player.tell("Usage: finger user [@host]");
return 0;
endif
victim = args[2][1..atpos - 1];
host = args[2][atpos + 1..];
who = player;
connect(host, 79);
else
who = #0.find_player(args[2]);
if (!who)
player.tell("I can't find that player.");
else
player.tell(who.id);
if (who in #0.connected_players)
player.tell("On since " + ctime(player.connected_at));
player.tell("Idle " + #0.convtime(player.last_cmd_at - time()));
player.tell("Location: " + who.location.id);
else
player.tell("Last connected at " + ctime(who.last_cmd_at));
endif
endif
endif
endmethod
method init
if (this == $network_tools)
this.add_owner(#11);
this.moveto(#11);
desc = "";
endif
endmethod
method connect
echo(victim);
desc = "";
endmethod
method parse
desc = desc + args[1] + "\n";
endmethod
method disconnect
at (time() + 1)
who.tell("------------------------ finger output ----------------------");
who.tell(desc);
who.tell("---------------------- end finger output --------------------");
endat
endmethod
endobject
object #14
parents #4;
list contents = {};
str name = "Generic Help Object";
list owners = {#11};
num public = 1;
obj location = #6;
map help_list = ["" => "No help defined!"];
obj home = #13;
verb "@sethelp" : "to" = sethelp;
verb "@listhelp" = listhelp;
verb "edit_help" = edit_help;
verb "rename_help" = rename_help;
method edit_help
player.edit_var_cmd(args[1], "help_list " + args[2], "on", tostr(this));
endmethod
method listhelp
if (!this.can_read("help_list", caller))
raise E_PERM;
else
player.tell(help_list[args[2]]);
endif
endmethod
method sethelp
if (!this.can_write("help_list", caller))
raise E_PERM;
else
help_list[args[2]] = args[4];
player.tell("Set help for topic " + tostr(args[2]) + " to " + tostr(args[4]));
endif
endmethod
method test
return help_list[1];
endmethod
method rename_help
player.rename(args[1], "help_list " + args[2]);
endmethod
method help
var last, cur;
ignore E_MAPNF;
cur = help_list[args[1]];
while (cur)
last = cur;
cur = help_list[cur];
endwhile
return last;
endmethod
endobject
object #15
parents #14;
list contents = {};
str name = "Global Help Object";
list owners = {#11};
obj location = #11;
map help_list = ["" => "intro", "sleep" => "sleep()", "whisper" => "Command: whisper <message> to <player>\n\nSend a private <message> to a <player> in the same room as you.\nIf the parser gives you grief, put your message in doublequotes, eg.,\nwhisper \"give that ugly mail bomb to ghond\" to joe\n\nSee also: say, pose, page, :, \"\n", "playing2" => " \nOther General Use Commands\n==========================\n \nnews: Another useful source of information besides help is news, which works in much the same way. News is used to provide up-to-date information about this particular server.\nhome: If you are lost, you can go back to your home by typing 'home'.\n@who/who: To find out who is on the server with you, type '@who'.\nrwho: To find out who is on the network of servers with you, type rwho.\n@quit/quit: To end your MUDding session, type '@quit'.\n@password: To change your password, type '@password <oldpass> to <newpass>'.\nwizards: To get a list of this server's wizards, type 'wizards'.\nuptime: To find out how long this server has been up, type 'uptime'.\n \n", "ps" => "ps()", "chparents" => "chparents()", "disconnect" => "Function: disconnect()\n\nSyntax: disconnect()\n\n\nDisconnect the current object.\n\n", "@teleport" => "Command: @teleport <object> to <destination>\n\nMove an object to a new location.\n\nSee also: @show, go, get, drop\n", "clear_edit" => " \nCommand: clear_edit\n \nClears all aspects of the current editing session.\n \nSee also: editing, editing commands", "examine" => "look", "talking" => " \nTalking\n=======\n \nTalking is the simplest and most basic form of communication you will engage in on the MUD. When someone is talking in the room you are in, you'll see something like, 'Turgul says, \"Hi!\"', and when you talk you'll see something like 'You say, \"Hi!\"'.\nTo talk, all you need to do is type 'say <stuff>', without the quotes, replacing <stuff> with what you want to say. Talk also has a short form, \", which works the same way (except you don't need the space), so 'talk hi' is the same as '\"hi'.\n \n", "getvar()" => "Function: getvar()\n\nSyntax: getvar( _str_ )\n\n\nGets the value of the variable named _str_ on the current object.\nNormally, one would just reference the variable in COOL code by name,\nbut getvar() allows the use of an arbitrary string to get the value of\na variable. Example:\n\ngetvar (\"abc\" + \"def\")\n\nwould return the value of the variable named abcdef on the current\nobject.\n\n", "writelog()" => "Function: writelog()\n\nSyntax: writelog(uncarg{str })\n\n\nWrite _str_ to the logfile. The string is prefixed by the current date\nand time.\n\n", "toerr()" => "Function: toerr()\n\nSyntax: toerr( _var_ )\n\n\nConvert a string, number, or object value into an error value. Strings\nare parsed, the same way parses errors (\"E_TYPE\" becomes E_TYPE).\nNumbers are converted by using the number as the internal error ID.\nObject values are converted by using the object ID portion as the error\nID.\n\n", "lock" => "lock()", "psub" => "psub()", "rm_var" => "rm_var()", "@aliases" => " \nCommand: @aliases <thing> to <string>\n \nSets aliases on <thing>. The aliases in <string> should be seperated by ;'s.\n \nSee also: @rename\n \n", "test" => "", "echo_file" => "echo_file()", "@mutate" => "Command: @mutate <object> to/into <parent>\n\nMake <parent> the only parent of <object>. Any existing variables attached\nto <object> will still remain attached. The \"init\" method is *not* called,\nso the object may not get the appropriate variables.\n\nSee also: @addparent, @rmparent, @clone, @destroy\n", "random()" => "Function: random()\n\nSyntax: random( _num_ )\n\n\nReturn a random number 1 .._num_\n\n", "echo_file()" => "Function: echo_file()\n\nSyntax: echo_file( _str_ )\n\n\nRead in the contents of the local file _str_, and echo them, one like\nat a time, to the current object. The file is located relative to\nRUNDIR (usu. bin/online) of the server's installation.\n\n", "@addwriteok" => " \nCommand: @addwriteok <variable> on <object>\n \nAdds <variable> to the list of world-writable variables on <object>.\n\nSee also: @addlight, @rmlight, @adddark, @rmdark, @rmwriteok, @publish\n \n", "eval" => "Command: eval <code>\n ; <code>\n\nEvaluate one or more statements of COOL code. The return value is displayed.\nEg.,\n\n ;return \"abc\" + \"def\";\n --> \"abcdef\"\n\nSee also: @program, compile()\n", "@kill" => "Command: @kill <task>\n\nHalt the task with ID <task>.\n\nSee also: @ps\n", "shutdown" => "shutdown()", "drop" => "Command: drop <object>\n throw <object>\n\nRemove an object from your inventory, and place it on the ground. \n\"drop all\" will empty your inventory.\n\nSee also: get\n", "getvar" => "getvar()", "\"" => "say", "strsub" => "strsub()", "commands" => " \nCommands\n========\n \nThe following sets of commands are available on this server. Those listed as player commands can only be used if you have the $player object as one of your ancestorys. Builder commands can only be used by descendents of $builder, and similarily for programmer commands and $programmer and wizard commands and $wizard. These are, generally, #8, #9, #10, and #11 respectively.\n \nplayer commands/commands1: General use commands.\nbuilder commands/commands2: Miscellaneous commands of use to all builders.\nprogrammer commands/commands3: Commands of use to all programmers.\nediting commands/commands4: The in-place editing facility.\nobject commands/commands5: Commands for particular classes of object.\npermissions commands/commands6: Commands for permission setting.\n \n", "padc" => "padc()", "password" => "Command: password <oldpasswd> to <newpasswd>\n @password <oldpasswd> to <newpasswd>\n\nChanges your password. You must specify your old password, <oldpasswd>,\nas well as your new password, <newpasswd>. Passwords in COOLMUD are stored\nin encrypted form.\n\nSee also: \n", "objsize" => "objsize()", "lengthof" => "lengthof()", "setremove()" => "Function: setremove()\n\nSyntax: setremove( _list_ , _value_ )\n\n\nRemove _value_ from _list_, anywhere in the list. Returns the new\nlist.\n\n", "list_method()" => "Function: list_method()\n\nSyntax: list_method( _str_ [ , _lineno_ [ , _fullbrackets_ [ ,\n_indent_ ] ] ] )\n\n\nReturns a string containing the decompiled code for method _str_. This\nworks by turning the stack machine code back into readable form. It\ndoes automatic indentation, line numbering, and smart bracketing (ie.,\nit will use the minimum number of brackets when decompiling an\nexpression). The three optional arguments are numeric arguments which\ncontrol the decompilation:\n\n", "@rmwriteok" => " \nCommand: @rmwriteok <variable> on <object>\n \nRemoves <variable> from the list of world-writable variables on <object>.\n\nSee also: @addlight, @rmlight, @adddark, @rmdark, @addwriteok, @publish\n \n", "padl" => "padl()", "tostr" => "tostr()", "rm_verb" => "rm_verb()", "editing commands" => " \nEditing Commands\n================\n \nPlayer Editing Commands\n-----------------------\n \nedit_var save append insert\nlist delete clear_edit rename\n \nProgrammer Editing Commands\n---------------------------\n \nedit_method\n \n", "listfuncs" => "#!/usr/bin/perl\n\n$started = 0;\nwhile(<>) {\n if (/subsubsection{func (.*)((.*))}/) {\n if ($started) {\n } else {\n $started = 1;\n }\n $name = $1;\n $args = $2;\n $name =~ s///;\n $args =~ s/{funcarg(W*)(S*)([^}]*)}/$1_$2_$3/g;\n $args =~ s/$//g;\n print \"$name()", "cache_stats" => "cache_stats()", "exits" => " \nCommand: exits\n \nLists all of the exits leading out of the room. Unless the room owner is hiding some...\n \n", "setadd" => "setadd()", "@rmmethod" => "Command: @rmmethod <method> on <object>\n\nRemove <method> from <object>. You must own <object>.\n\nSee also: @methods, @program\n", "list_method" => "list_method()", "stand" => " \nCommand: stand [up/up from] <furniture>\n \nStand up from the named piece of <furniture> you were sitting or lying on.\n \nSee also: sit, lie\n \n", "funclist" => "clone()\ndestroy()\nchparents()\nlock()\nadd_verb()\nrm_verb()\nrm_method()\nrm_var()\nunlock()\nverbs()\nvars()\nmethods()\ngetvar()\nsetvar()\nhasparent()\nfind_method()\nspew_method()\ndecompile()\nobjsize()\necho()\necho_file()\nquit()\nprogram()\ntypeof()\nlengthof()\nserverof()\nservername()\nservers()\nexplode()\ntime()\nctime()\ncrypt()\nmatch()\nmatch_full()\npsub()\nstrsub()\npad()\nrandom()\ncompile()\nsetadd()\nsetremove()\nlistdelete()\ntonum()\ntoobj()\ntostr()\ntoerr()\nsleep()\nkill()\nps()\nshutdown()\ndump()\nwritelog()\ncheckmem()\ncache_stats()\n", "give" => " \nCommand: give <thing> to <person>\n \nGives the named object in your inventory to the named person.\n \nSee also: get, drop, inventory\n \n", "lie" => " \nCommand: lie [on/down on] <furniture>\n \nLie down on the named piece of furniture.\n \nSee also: sit, stand\n \n", "compile" => "compile()", "pose" => " \nCommand: pose <message>\n : <message>\n \nDisplays <message> to everyone in the room, prepended with your name.\nFor example, if your name is \"Joe\" and you type \":smiles.\", everyone\nin the room would see \"Joe smiles.\"\nAlso, if <message> starts with ':', in either form, the space will be removed, so if you type \"::'s smiling.\", everyone in the room would see \"Joe's smiling.\".\n \nSee also: say, whisper, page, \", :\n\n ", "can_write()" => " \nFunction: #1.can_write\n \nSyntax: this.can_write(<var_name>, <caller> );\n \nTests whether the calling method can write the variable <var_name> on this object. Caller is sent explicitely as this function is likely to be called by getvar (or other functions) on this object, so by the time can_write is called the caller is wrong.\nTo test general writeability of the object, call this.can_write(\"\", caller). This will generally return 1 if the calling player owns the object.\nNote that the return value is guaranteed to be either 1 or 0.\n \nSee also: can_read().\n \n", "lengthof()" => "Function: lengthof()\n\nSyntax: lengthof( _var_ )\n\n\nReturns a number representing the length of _var_. _var_ must be a\nstring or list expression.\n\n", "setadd()" => "Function: setadd()\n\nSyntax: setadd( _list_ , _value_ )\n\n\nThis function adds _value_ to _list_, as long as it's not already\npresent. Returns the new list.\n\n", "echo()" => "Function: echo()\n\nSyntax: echo( _str_ )\n\n\nDisplay _str_ to the current object. Does nothing if the current\nobject is not a connected player.\n\n", "can_read()" => " \nFunction: #1.can_read\n \nSyntax: this.can_read(<var_name>, <caller> );\n \nTests whether the calling method can read the variable <var_name> on this object. Caller is sent explicitely as this function is likely to be called by getvar (or other functions) on this object, so by the time can_read is called the caller is wrong.\nTo test general readability of the object, call this.can_read(\"\", caller).\nNote that the return value is guaranteed to be either 1 or 0.\n \nSee also: can_write().\n \n", "keys()" => " \nFunction: #1.keys()\n \nSyntax: keys( <var name> )\n \nReturns the keys of the mapping referenced by the string <var name> on the given object.\n \n", ":" => "Command: pose <message>\n : <message>\n\nDisplays <message> to everyone in the room, prepended with your name.\nFor example, if your name is \"Joe\" and you type \":smiles.\", everyone\nin the room would see \"Joe smiles.\"\n\nSee also: say, whisper, page, \", :\n", ";" => "Command: eval <code>\n ; <code>\n\nEvaluate one or more statements of COOL code. The return value is displayed.\nEg.,\n\n ;return \"abc\" + \"def\";\n --> \"abcdef\"\n\nSee also: @program, compile()\n", "program" => "program()", "checkmem" => "checkmem()", "rwho" => "Command: rwho\n\nShow who is on all the coolmuds in the coolnet. Each of the servers\nis listed, together with a list of players who is on each one.\n\nSee also: who, wizards\n", "@ps" => "Command: @ps [ -a ]\n\nShow information about tasks running on the mud. By default, only\ntasks running under your control are displayed. With the -a option,\nall tasks are displayed.\n\nSee also: @kill\n", "object commands" => " \nGeneral Object Commands\n=======================\n \nThese commands will work on most object. @rename, in particular, works on every object in the database except the system object (#0).\n \n@rename @describe look/examine get/take drop/throw\n \nContainer Commands\n==================\n \nput/place/insert look get/remove/take\n \nFurniture Commands\n==================\n \nsit lie stand\nNot all of these commands will work on all pieces of furniture.\n \n \n", "@verbs" => "Command: @verbs <object>\n\nShow all the verbs on <object>, and the methods called.\n\nSee also: @show, @methods, @verb, @rmverb\n", "methods" => "methods()", "fixlist" => "#!/usr/bin/perl\n\n$count = 0;\n\nwhile(<>) {\n chop;\n printf \"%-15s\", $_;\n $count++;\n if (($count % 5) == 0) {\n print \"", "@cpmethod" => " \nCommand: @cpmethod <obj1>.<m1> to <obj2>.<m2>\n \nCopies the method <m1> on object <obj1> to the method <m2> on object <obj2>.\n \nSee also: @cpvar.\n \n", "typeof" => "typeof()", "disconnect()" => "Function: disconnect()\n\nSyntax: disconnect()\n\n\nDisconnect the current object.\n\n", "sleep()" => "Function: sleep()\n\nSyntax: sleep( _num_ )\n\n\nPause for _num_ seconds\n\n", "@link" => "Command: @link <exit> to <room>\n\nLink the exit named <exit> to the room <room> (usually specified by object #).\n\n\nSee also: @open, @dig, @create, @clone, @destroy\n", "match_full" => "match_full()", "listassign" => "listassign()", "@who" => "Command: who\n @who\n\nShow who is online, showing how long they've been connected to the mud\n(\"on for\") and how long since they last typed a command (\"idle\").\n\nSee also: rwho, wizards\n", "@verb" => " \nCommand: @verb <verb> <method> on <object>\n @verb <verb> <prepositions> <method> on <object>\n \nFirst form: Add a new verb named <verb> to <object>, which will call <method> when triggered.\nSecond form: As above, except the new verb will accept the given list of prepositions as syntactical markers (i.e. ways to tell to direct object from the indirect object). To give a list of prepositions, separate them with spaces. To use a preposition that consists of more than one word, replace spaces with _'s. For example, if you have a box with the method take_cmd and you want to be able to 'take <thing> out of/from box', you would use '@verb take out_of from take_cmd on box'.\nNB: <verb> above can actually be a list of verb names, separated by /'s. In the example above, if you also wanted to get <thing> out of box, you could use '@verb get/take out_of from take_cmd on box'.\n \nSee also: @rmverb, @verbs\n\n", "Programmer Commands" => " \nProgrammer Commands\n===================\n \nThese commands are available to all programmers.\n \neval @program @ps @kill @verb\n@rmverb @rmmethod @rmvar ; @cpmethod\n\n", "aliases" => " \nAliases\n=======\n \nThis help file describes the rules for alias matching and how to set up aliases.\nCurrently, aliasing only works for players and exits.\n \nFirst, the server checks all appropriate items it can find (in the room or on the whole server, as appropriate), and tries to match the argument against a full word in one of the aliases or the thing's name.\nIf this fails, it goes through them all again, this time for each alias, if the alias is more than one word, any substring can be matched, otherwise the whole word must be matched. After the aliases, the thing's name is checked, with any substring matching.\nNote that all of these searches are first-come, first-served.\n \n", "listappend" => "listappend()", "get" => " \nCommand: get <object>\n take <object>\n \nPick up an object, and put it in your inventory. Note that not all\nobjects can be picked up. \"get all\" will attempt to pick up everything\n(and everyone!) in the room.\nA second form of get and take, for containers, works just like remove.\n \nSee also: drop, remove\n\n", "listinsert" => "listinsert()", "@rmparent" => "Command: @rmparent <parent> from <object>\n\nRemove <parent> from the parents lists of <object>. <object> retains\nany variables inherited from <parent>.\n\nSee also: @addparent, @mutate\n", "page" => "Command: page <player>\n page <player> with <message>\n\nSends <message> to <player>, who does not have to be in the same room.\nIf no message is given, the player is informed that you are looking\nfor them and is given your current location.\n\nSee also: say, whisper, pose, \", :\n", "rename" => " \nCommand: rename <newname>\n \nChanges the name of the variable or method currently being edited. Note that editing something and then renaming and saving is an effective way of copying variables or methods on a particular object.\n \nSee also: editing, editing commands\n\n", "ps()" => "Function: ps()\n\nSyntax: ps()\n\n\nGet a list of all active threads on the MUD. Returns a list of lists,\nin which each element represents a thread in an 11-element list of the\nform:\n\n\n{ msgid, age, ticks, player, this, on, caller, args, methodname,\nblocked_on, timer }\n\n\n", "tostr()" => "Function: tostr()\n\nSyntax: tostr( _var_ )\n\n\nConvert a string, number, object, list or error type into a string\nvalue. Strings are converted by enclosing them in doublequotes, and\nescaping any control chars with a backslash (, , etc). Numbers and\nobject ID's are simply printed. Lists are evaluated recursively,\nprinting '{', followed by the list elements, separated by commas, and\nthen '}'. Errors are converted into a string representing the error\nidentifier (E_TYPE becomes \"E_TYPE\").\n\n", "rm_verb()" => "Function: rm_verb()\n\nSyntax: rm_verb( _str_ )\n\n\nRemove the first verb named _str_ from the current object. The\nargument may also be a string representing the number indexing the verb\nto be removed (indexed from 0). eg.,\nwould remove the 4th verb on the current object.\n\n", "dump()" => "Function: dump()\n\nSyntax: dump()\n\n\nDump the database.\n\n", "toobj" => "toobj()", "@adddark" => " \nCommand: @adddark <variable> on <object>\n \nIf <object> is set public, <variable> will be added to the list of variables that will not be world-readable regardless.\n \nSee also: @addlight, @rmlight, @rmdark, @addwriteok, @rmwriteok, @publish\n \n", "@shutdown" => "Command: @shutdown\n\nShut down the mud.\n\nSee also: @force\n", "vars" => "vars()", "@cachestats" => "Command: @cachestats/@cs\n\nShow object allocation and cache statistics for the mud.\n\nSee also: @mem, @visitors\n", "functions" => " \nFunctions\n=========\n \nbuiltin functions/functions1: A list of all the server provided functions.\nroot functions/functions2: A list of all the root object's functions.\n \n", "quit" => "quit()", "list" => " \nCommand: list [noline]\n \nLists the current editing buffer. If a second argument is given (any second argument, actually), the listing is done without presenting line numbers.\n \nSee also: editing, editing commands\n\n", "@set" => "Command: @set <object>.<variable> to <value>\n\nSet the variable <property> to <value>. You must own <object>.\n(Ed note: this syntax is grotty, since object.foo really means the\nmethod foo, not the variable foo). If <property> doesn't exist on\n<object>, it will be created as a string property.\n\nSee also: @show\n", "commands_old" => "player commands:\ndrop/throw get/take help home inventory\nlook/examine news page @password/password\npose quit/@quit rwho say who/@who\nwhisper wizards : \"\nobject-specific commands (may not work on all objects):\n@describe look/examine put remove\nbuilder commands:\n@addowner @addparent @clone @create @decompile\n@destroy @dig @find @link @list\n@open @methods @mutate @publish @unpublish\n@rmparent @rmowner @set @show @spew\n@teleport @verbs\nprogrammer commmands:\neval @program @ps @kill @verb\n@rmverb @rmmethod @rmvar ;\n\n\n\n\n", "home" => "Command: home\n\nSend yourself home. There's no place like home..\n\nSee also: @home\n", "save" => "\nCommand: save\n \nSaves the current editing session without resetting it.\n \nSee also: editing, editing commands\n \n", "explode" => "explode()", "playing" => " \nNew Player Information\n======================\n \nHi! Welcome to CoolMUD, the next generation of MUD servers.\n \nThis help file is here to help you get familiar with the basic commands you'll need to interact with other players and the mud environment.\nThe commands discussed here are mostly listed in the player commands/commands1 help file. Note that when I specify several things separated by /'s, that means any of them will work, so you could get the aforementioned information by typing 'help player commands' or 'help commands1'. You may also want to look at 'help commands' to see what is available to you.\n \nThe following list of help topics, which probably should be read in\norder, should give you the tools you need to explore the MUD.\n \nsetup: What to do to set up yourself for playing.\ntalking: How to talk to others on the MUD.\ncommunicating: Other ways of interacting with people besides talking.\neploring: How to move and look at thing.\nthings: How to deal with things you find on the MUD.\nplaying2: Other sundry commands that you can use.\n\n", "compile()" => "Function: compile()\n\nSyntax: compile( [ _obj_ , _method_ ], _str_ )\n\nCompile _str_ into an object or method\n\n", "say" => "Command: say <message>\n \"<message>\n\nSays a message to everyone in the room. You can also use the short-form\nversion, \".\n\nSee also: pose, whisper, page, :\n", "checkmem()" => "Function: checkmem()\n\nSyntax: checkmem()\n\n\nReturns a string showing the amount of memory dynamically allocated,\nand how many chunks it was allocated in. If the server was not\ncompiled with -DCHECKMEM, this function will return ``Memory checking\ndisabled.''\n\n", "l" => "Command: look\n look <object>\n examine <object>\n\nLooks around the room (first form), or examines a particular object\n(second form). Shows you the name, description, and contents.\n\nSee also: @describe\n", "permissions functions" => " \nPermissions Functions\n=====================\n \nThe primary two functions for permissions testing are can_read() and can_write(), both of which have their own help pages.\nIn particular, #1.getvar() and #1.setvar() are just basically wrappers for can_read and can_write, respectively.\n \n", "permissions" => " \nPermissions\n===========\n \nAs of this writing, this is a description of a system under development, so the actual code may not be consistent with this description.\n \npermissions overview: An overview of the design of the permissions system.\npermissions reading: A discussion of the default permissions for variable reading.\npermissions writing: A discussion of the default permissions for variable writing.\npermissions functions: A discussions of the functions that implement the basic permissions system and how to use them.\n \npermissions commands: A list of player commands for handling permissions.\n", "@addlight" => " \nCommand: @addlight <variable> on <object>\n \nIf <object> is set to non-public, <variable> will be added to the list of variables that will be world-readable regardless.\n \nSee also: @rmlight, @adddark, @rmdark, @addwriteok, @rmwriteok, @publish\n \n", "@boot" => "Command: @boot <player>\n\nDisconect <player> from the mud (give them the boot!).\n\nSee also: @force\n", "@rmlight" => " \nCommand: @rmlight <variable> on <object>\n \nIf <object> is set to non-public, <variable> will be removed from the list of variables that will be world-readable regardless.\n \nSee also: @addlight, @adddark, @rmdark, @addwriteok, @rmwriteok, @publish\n \n", "time" => "time()", "@dig" => "Command: @dig <name>\n\nCreate a new room, with the name <name>. Equivalent to:\n\n @clone $room named <name>\n\nSee also: @create, @clone, @open, @destroy\n", "padc()" => " \nFunction: #1.padc()\n \nSyntax: padc( str, length, [padchar] )\n \nPads str into the appropriate length using padchar, with str centered in the resulting string. In case of an even/odd conflict, an extra padchar is put at the end of the resulting string.\nPadchar defaults to \" \".\n \nSee also: pad, padl.\n", "servername()" => "Function: servername()\n\nSyntax: servername( _obj_ )\n\n\nReturns a string representing the server name part of _obj_.\n\n", "psub()" => "Function: psub()\n\nSyntax: psub( _str_ )\n\n\nThis function substitutes the value of the local (method) variable\n\"foo\" for each instance of \"%foo\" or \"%foo%\" in _str_. Example:\n\n\nfoo = \"system\"; n = #0; echo(psub(\"%n is the %foo object.\"));\n\nwould result in the output \"#0 is the system object\".\n\n", "match()" => " \nFunction: match()\n \nSyntax: match( <str>, <template>, [<sep>] )\n \nThis function matches _str_ to _template_. _str_ should be a 1-word\nstring which is compared against each word in _template_. If _str_\nmatches a substring of any word in _template_, 1 is returned, otherwise\n0 is returned. The optional third argument is the separator to use\nwhen matching (default is a blank).\nNote that match is case insensitive (i.e. lower case and upper case are treated the same way). Also, I just fixed the server so that it does true substring matching: before, if you did match( \"aabb\", \"aa\"), that would match but match( \"aabb\", \"bb\" ) wouldn't (it only matched substrings starting at the beginning of words).\n\n", "typeof()" => "Function: typeof()\n\nSyntax: typeof( _var_ )\n\n\nReturns a number representing the type of _var_. This value may be\nchecked against the pre-defined constants NUM, OBJ, STR, LIST and ERR.\n\n", "@destroy" => "Command: @destroy <object>\n\nDestroy an existing object.\n\nSee also: @create, @clone, @mutate\n", "unlock" => "unlock()", "go" => " \nCommand: go <exit>\n \nSends you through the named exit. Can be done more easily simply by typing the exit's name, and so isn't used much.\n \n", "@methods" => "Command: @methods <object>\n\nList all the methods on <object>, sorted alphabetically.\n\nSee also: @show, @verbs, @rmmethod, @list, @decompile\n", "player commands" => " \nPlayer Commands\n===============\n \nThese commands are available to all players.\n \ndrop/throw get/take help home inventory\nlook/examine news page @password pose\n@quit rwho say @who whisper\nwizards : \" @describe @rename\n@home @gender exits uptime give\ngo @aliases @cpvar\n\n", "verbs" => "verbs()", "perms" => "", "builder commands" => " \nBuilder Commands\n================\n \nThese commands are available to all builders.\n \n@addowner @addparent @clone @create @decompile\n@destroy @dig @find @link @list\n@open @methods @mutate @publish @unpublish\n@rmparent @rmowner @set @show @spew\n@teleport @verbs\n\n", "servers" => "servers()", "pad" => "pad()", "implode" => "implode()", "@publish" => "Command: @publish <object>\n\nSet <object> public, so that anyone may @show, @methods, @list, @clone\netc the object. Basically allows \"world read permission\" on the object.\nYou must own <object>.\n\nSee also: @unpublish, @show, @list, @methods, @verbs, @clone\n", "spew_method()" => "Function: spew_method()\n\nSyntax: spew_method( _str_ )\n\n\nReturns a string containing the internal stack-machine code for method\n_str_. This code is pretty unintelligible unless your brain works in\nRPN. Even then, some instructions are hard to figure out, and there's\nnot much point. Only for the habitually curious.\n\n", "rm_method()" => "Function: rm_method()\n\nSyntax: rm_method( _str_ )\n\n\nRemove _str_ from the current object. Note that has special provision\nto allow a method to remove itself and continue executing. It won't be\nactually destroyed until after the method finishes.\n\n", "tonum" => "tonum()", "random" => "random()", "@open" => "Command: @open <exit> [ to <room> ]\n\nOpen an exit, and optionally link it to <room>.\n\nSee also: @dig, @link, @create, @clone, @destroy\n", "who" => "Command: who\n @who\n\nShow who is online, showing how long they've been connected to the mud\n(\"on for\") and how long since they last typed a command (\"idle\").\n\nSee also: rwho, wizards\n", "functions1" => "builtin functions", "commands1" => "player commands", "commands2" => "builder commands", "builtin functions" => " \nBuiltin Functions\n=================\n \nadd_verb() cache_stats() checkmem() chparents() clone() \ncompile() crypt() ctime() decompile() destroy() \ndump() echo() echo_file() explode() find_method()\ngetvar() hasparent() kill() lengthof() list_method()\nlistappend() listassign() listdelete() listinsert() lock()\nmatch() match_full() methods() objsize() pad() \nprogram() ps() psub() quit() random()\nrm_method() rm_var() rm_verb() servername() serverof()\nservers() setadd() setremove() setvar() shutdown()\nsleep() spew_method() strsub() time() toerr()\ntonum() toobj() tostr() typeof() unlock() \nvars() verbs() writelog() \n \n", "commands3" => "programmer commands", "hasparent" => "hasparent()", "spew_method" => "spew_method()", "commands4" => "editing commands", "@rename" => " \nCommand: @rename <thing> to <name>\n \nChanges the name of <thing>, be it room, thing or player, to <name>.\n\nSee also: @gender, @describe, @home\n \n", "@describe" => "Command: @describe <object> as <description>\n\nGive a text description to an object, player or room. This description\nwill be displayed when the object is examined.\n\nSee also: look, examine\n", "setremove" => "setremove()", "delete" => " \nCommand: delete <line>\n \nDeletes the given line in the current editing buffer.\n \nSee also: editing, editing commands\n\n", "commands5" => "object commands", "commands6" => "permissions commands", "throw" => "drop", "verbs()" => "Function: verbs()\n\nSyntax: verbs()\n\n\nReturn a list of verbs on the current object. Each element of the list\nis in turn a 3-element list, consisting of 3 strings: the verb name,\nthe preposition, and the method to call.\n\n", "ctime()" => "Function: ctime()\n\nSyntax: ctime( [ _num_ ] )\n\n\nReturns a string representing the integer _num_ as an English date, or\nthe current time if no argument is given.\n\n", "intro" => " \nHello! Welcome to Chaos. The help here is undergoing some fairly radical\nalteration, so please let Tzeentch know if you notice anything missing or have\na suggestion for a new help topic.\n \nChaos runs on COOLMUD v2.2.2-alpha2, a distributed, multi-user, object-oriented, programmable worldbuilding environment. Help is available on the following topics:\n \nhelp intro - this file\nhelp commands - a list of commands which the mud understands\nhelp functions - a list of all the COOL built-in function\nhelp topics - a list of general help topics\n \nIndividual objects may also have their own help functions.\n\n", "@rmverb" => "Command: @rmverb <verb> on <object>\n\nRemove <verb> from <object>. You must own <object>.\n\nSee also: @verb, @verbs\n", "@quit" => "Command: quit\n @quit\n\nLogout and disconnect from the MUD.\n\nSee also:\n", "append" => "\nCommand: append <string>\n \nAppends a string to the current editing session. <string> should not be delimited by quotes unless you want them to be preserved.\n \nSee also: editing, editing commands\n\n", "@dewizard" => "Command: @dewizard <player>\n\nRevoke wizardly powers for <player>. You must be a wizard. You cannot\ndewizard your self.\n\nSee also: @wizard\n", "@list" => "Command: @list <method> on <object>\n\nList the source for the method named <method> on the given <object>.\n\nSee also: @decompile, @methods, @rmmethod, @spew\n", "@wizard" => "Command: @wizard <player>\n\nGive <player> wizardly powers. You must be a wizard.\n\nSee also: @dewizard\n", "edit_method" => " \nCommand: edit_method <name> on <obj>\n \nEdits the method <name> on the object <obj>.\n \nSee also: editing, editing commands\n\n", "@unsafe" => " \nCommand: @unsafe <object>\n \nIf an object is set unsafe, its location has write permissions on it. This is used to allow to do wierd things such as randomly teleport people in their areas or have wandering puppets that steal stuff from people.\n \nSee also: @safe, @publish, @unpublish, permissions commands\n \n", "@home" => " \nCommand: @home <where>\n \nSets your home to the named location.\n \nSee also: @gender, @describe, @rename\n \n", "listdelete" => "listdelete()", "@clone" => "Command: @clone <object> [ named <name> ]\n\nCreate a child of <object>, optionally with the name <name>. The newly-\ncreated object is passed the \"init\" message, with the argument <name>.\n\nSee also: @destroy, @create, @dig, @open, @mutate\n", "ctime" => "ctime()", "serverof" => "serverof()", "time()" => "Function: time()\n\nSyntax: time()\n\n\nReturns a numeric value representing the current date and time, given\nin seconds since 12:00 GMT, January 1, 1970.\n\n", "cache_stats()" => "Function: cache_stats()\n\nSyntax: cache_stats()\n\n\nReturns a string with embedded newlines containing the current\nstatistics of the object-paging cache. Currently the output looks like\nthis:\n\n\n\n", "kill()" => "Function: kill()\n\nSyntax: kill( _num_ )\n\n\nTerminate thread _num_\n\n", "quit()" => "Command: quit\n @quit\n\nLogout and disconnect from the MUD.\n\nSee also:\n", "echo" => "echo()", "setup" => " \nSetup\n=====\n \nThe following are things you can or should do to set your character up for playing.\n \n@describe: You should give your character a description, so that other people will see something interesting when they look at you. For example, you might type, '@describe me as A tall, blond geek with glasses.'.\n@gender: You'll want to let people know your gender. If it's male, type '@gender male', '@gender female' for female, and '@gender <something-that-doesn't-start-with-m-or-f>' if you want to be an 'it'.\n@rename: You may wish to change your name from the one you picked when you first created your character. Type '@rename me to <newname>', replacing <newname> with the name you want (don't type in the ' marks, of course).\n@home: The 'home' command instantly teleports you to your home. You may decide that you wish your home to be different than the one set for you when you first start on the mud. To change it, go to the place where you want your home to by and type '@home here'. Be sure to ask if it's not your room!\n \n", "add_verb" => "add_verb()", "@rmvar" => "Command: @rmvar <variable> on <object>\n\nRemove <variable> from <object>. You must own <object>.\n\nSee also: @set, @show\n", "permissions commands" => " \nPermissions Commands\n====================\n \n@addlight @rmlight @adddark @rmdark @addwriteok @rmwriteok\n@safe @unsafe\n \n", "@visitors" => "Command: @visitors\n\nShow all remote objects which are inside local objects.\n\nSee also: @mem, @cachestats\n", "insert" => "\nCommand: insert <string> at <line>\n \nInserts <string> into the current editing buffer above <line>. If <line> is greater than the number of lines in the editing buffer, appends instead. <string> can be delimited by quotes, and should if the word 'at' is present.\n \nSee also: editing, editing commands\n\n", "@safe" => " \nCommand: @safe <object>\n \nIf an object it set safe, then it's location does not have write permissions on it.\n \nSee also: @unsafe, @publish, @unpublish, permissions commands\n \n", "exploring" => " \nExploring\n=========\n \ngo: To go through a room's exit, to wherever it may happen to lead, type 'go <exit>', replacing <exit> with the exit name. Go isn't used much, however, as you can just type '<exit>' for the same effect.\nexits: To get a list of exits in the room you are in, just type exits.\nlook: To look around the room you are in, just type 'look'. This happens automatically when you enter a room. To look at a particular object, person or exit, type 'look <name>', where <name> is the name of the thing you want to look at.\n \n", "Editing" => "editing", "match" => "match()", "destroy" => "destroy()", "find_method()" => "Function: find_method()\n\nSyntax: find_method( _str_ )\n\n\nLocates the method named _str_ on the current object, if one exists.\nThis activates the same method-searching algorithm as used when\nactually sending an object a message. Returns the object ID of the\nobject defining the method, or #-1 if none is found. (This was useful\nin building the @list command, for instance).\n\n", "implode()" => " \nFunction: #1.implode()\n \nSyntax: implode( <list> [, <seperator>] )\n \nDoes the opposite of implode: takes <list> and places <seperator> between each element in list, returning the resulting string. <seperator> defaults to \" \".\n \nSee also: implode().\n \n", "vars()" => "Function: vars()\n\nSyntax: vars()\n\n\nReturn a list of variables (properties) on the current object. Each\nelement of the list is a string containing the name of the variable.\n\n", "@mem" => "Command: @mem\n\nShow memory usage of the mud.\n\nSee also: @cachestats, @visitors\n", "@cpvar" => " \nCommand: @cpvar <obj1>.<v1> to <obj2>.<v2>\n \nCopies the variable <v1> on object <obj1> to the variable <v2> on object <obj2>.\n \nSee also: @cpmethod.\n \n", "edit_var" => " \nCommand: edit_var <variable> on <object>\n edit_var <mapping> <entry> on <object>\n \nStarts an editing session on the given variable or mapping entry.\n \nSee also: editing, editing commands\n\n", "put" => "Command: put <object> in <container>\n\nPut an object inside a container.\n\nSee also: get, drop, remove\n", "find_method" => "find_method()", "decompile" => "decompile()", "uptime" => " \nCommand: uptime\n \nLists how long the server has been up.\n \n", "servername" => "servername()", "inv" => "Command: inv\n inventory\n\nShows the contents of your inventory.\n\nSee also: look\n", "permissions reading" => " \nReading Permissions\n===================\n \nFor reading, things are fairly easy. Clearly anyone with permission to write a variable should also be able to read it. If an object has publish set to 1, everything not in the dark_vars variable (which is a list) is readable. If an object has publish set to 0, only vars in the light_vars list are readable.\n \nSee also: permissions\n \n", "methods()" => "Function: methods()\n\nSyntax: methods()\n\n\nReturn a list of methods on the current object. Each element of the\nlist is a string containing the name of the method.\n\n", "serverof()" => "Function: serverof()\n\nSyntax: serverof( _obj_ )\n\n\nReturns a number representing the server ID of _obj_. This ID is used\ninternally by the server, and has no meaning except that ID zero is the\nlocal MUD. So the statement\n\nif (!serverof(thingy))\n ...\nendif\n\nwould evaluate to true if thingy is a local object.\n\n", "pad()" => "Function: pad()\n\nSyntax: pad( _str_ , _length_ [, _padchar_ ])\n\n\nPad/truncate a string.\n\n", "setvar()" => "Function: setvar()\n\nSyntax: setvar( _str_ , _value_ )\n\n\nSets the value of the variable named _str_ on the current object to\n_value_. Again, this would usually be accomplished with assignment\noperator, but in certain cases (eg., the name of the variable must\ncreated at run-time with an expression), this function must be used.\nIf the variable does not exist, it is created. Note that the type of\nthe new variable is determined by _value_, and may not later be\nchanged. Example:\n\nsetvar (\"abc\" + \"def\", 100);\n\nwould set the value of the variable named abcdef on the current object\nto the numeric value 100. If abcdef did not exist, it would be\ncreated.\n\n", "blank" => " \nCommand: blank [<num>]\n \nInserts a line containing a single space at line <num>, or, if <num> is not given, at the and of the editing buffer.\n \nSee also: editing commands, append, insert\n \n", "look" => " \nCommand: look\n look/examine <object>\n look in <object>\n \nLooks around the room (first form), or examines a particular object\n(second form). Shows you the name, description, and contents.\nThe third form is used to look in container objects.\n \nSee also: @describe\n\n", "funclist2" => "add_verb()\ncache_stats()\ncheckmem()\nchparents()\nclone()\ncompile()\ncrypt()\nctime()\ndecompile()\ndestroy()\ndump()\necho()\necho_file()\nexplode()\nfind_method()\ngetvar()\nhasparent()\nkill()\nlengthof()\nlistdelete()\nlock()\nmatch()\nmatch_full()\nmethods()\nobjsize()\npad()\nprogram()\nps()\npsub()\nquit()\nrandom()\nrm_method()\nrm_var()\nrm_verb()\nservername()\nserverof()\nservers()\nsetadd()\nsetremove()\nsetvar()\nshutdown()\nsleep()\nspew_method()\nstrsub()\ntime()\ntoerr()\ntonum()\ntoobj()\ntostr()\ntypeof()\nunlock()\nvars()\nverbs()\nwritelog()\n", "rm_method" => "rm_method()", "crypt" => "crypt()", "@force" => "Command: @force <player> to <command>\n\nForce <player> to execute <command>.\n\nSee also: @boot\n", "take" => "get", "@create" => "@create <name>\nCreate a Generic Thing, with the name <name>. Equivalent to:\n @clone $thing named <name>\n\nSee also: @destroy, @clone, @mutate, @dig, @open\n", "can_write" => "Mapping not found\n \nFunction: #1.can_write\nSyntax: <obj1>.can_write(<obj2>, <var_name>, <caller> );", "editing" => " \nGetting Started\n===============\n \nVariables: To start editing a variable, use the edit var command. For example, to edit your own description, type 'edit_var desc on me'.\nMethods: Only programmers can edit methods. To start editing a method, use the edit_method command. For example, to edit your own desc method, perhaps causing different people to see different things when they look at you, type 'edit_method desc on me'.\n \nCommands\n========\n \nOther than the above two commands, all of the editing procedure works the same way whether one is working on methods or variables.\nlist: Used to list the current editing buffer. If a second argument is given (any second argument, I use \"n\"), the buffer is listed with no line numbers.\ninsert: This command inserts a new line above a given line number in the current editing buffer. For example, 'insert foo at 1' inserts a new line containing the text \"foo\" above the first line, becoming the new line 1.\nblank: Inserts a blank line at the end of the input or at the given line. It is recommended that if you want a truly blank line at the end of your input (as opposed to the singe space that blank inserts) you do a single append before you save.\nappend: Slightly simpler form than insert, for appending lines to the end of the editing buffer.\ndelete: Deletes the given line number from the editing buffer.\nsave: Saves the current contents of the editing buffer under the current name.\nrename: Renames the place where the current editing buffer will be saved. Same format as edit_var/edit_method.\nclear_edit: Clears all of the editing information. Since this information is stored on your character object, you probably want to clear it before doing a @show me if you're editing a large buffer.\nreplace: Replaces a given line in the editing buffer with a new string.\n \nSee Also: editing commands\n\n", "@spew" => "Command: @spew <method> on <object>\n\nShow the internal stack machine code for the method <method> on <object>.\nReally only useful for trivia junkies.\n\nSee also: @list, @decompile, @methods, @rmmethod\n", "permissions overview" => " \nPermissions Overview\n====================\n \nAs of this writing, this is a description of a system under development, so the actual code may not be consistent with this description.\nBasically, there are two things of interest to a method when it tests whether it has permission to do something: caller and player. Caller is the object number of the object that actually called the current method (although it should be noted that pass does not modify caller) and player is the object number of the player that started the call chain.\nPossible relevant tests include whether one of the above (player or caller) is an owner, a wizard, #0, a parent or the current location of the relevant object.\nObviously, the owner of an object can do whatever ey wants, as can a wizard.\nIt is nescessary to allow #0 to do arbitrary things as well, for system maintenace purposes. In this cases, caller would be tested although, in general, this test is irrelevant as a test of player in (#0.wizards) should do the same thing. Someone who is not a wizard managing to get #0 to run a potentially destructive system maintenance routine with wizard permissions is a Bad Thing (tm), so this check is not used in the standard permission checking calls.\nThe exception to this is that if #0 cannot read certain attributes at log in, it cannot log people in, so it is given global read permissions.\nBeyond this, things get a little more muddy. We'll restrict the discussion to variable reading and writing, as anything else (cloning, destroying, etc.) are going to be handled specially if the owner/wizard test fails.\n \nSee also: permissions.\n \n", "permissions writing" => " \nWriting Permissions\n===================\n \nFor writing, as mentioned before, owners and wizards are automatically OK. Note that this is a player test, not caller test. The old code tested whether the caller was an owner or wizard, and you wouldn't believe the trouble this caused.\nThe current location should recieve special permissions, for the simple reason that area owners should be allowed to do wierd, strange things to you in their area. On the other hand, the destructive potential of this ability should be minimized.\nTherefore, the current location is normally a writer for player objects only, unless the object has safe set to 1. It is recommended that builders of areas that use this ability test the safe variable on entrances to their area, possibly restricting access if the variable isn't set, and in either case priting a warning is almost certainly a good idea. Note that location is a caller test, obviously.\nFinally, a variable in the write_ok list on an object can be written by anybody.\n \nSee also permissions.\n \n", "crypt()" => "Function: crypt()\n\nSyntax: crypt( _str_ [ , _salt_ ] )\n\n\nEncrypt a string. This function uses UNIX's crypt() routine to encrypt\na string. Useful for password checking, etc.\n\n", "strsub()" => " \nFunction: strsub()\n \nSyntax: strsub( <string>, <from>, <to> )\n \nReplaces all instances of the string <from> in <string> with the string <to>.\n\n", "match_full()" => " \nFunction: match_full()\n \nSyntax: match_full( <str>, <template>, [<sep>] )\n \nThis function matches _str_ to _template_ like match() except that <str>\nmust match an entire word in _template_, not just a substring.\n\nNote that the mach is case insensitive (i.e. lower case and upper case are treated the same way).\n\n", "shutdown()" => "Function: shutdown()\n\nSyntax: shutdown()\n\n\nShut down the MUD. The database is written, remote servers\ndisconnected, and the process terminates.\n\n", "hasparent()" => "Function: hasparent()\n\nSyntax: hasparent( _obj_ )\n\n\nReturns a positive value if the current object has _obj_ as a parent.\nThis function looks recursively on all parents of the current object,\nso it will return 1 if the object has _obj_ as a parent anywhere in its\ninheritance tree, and 0 otherwise.\n\n", "clone()" => "Function: clone()\n\nSyntax: clone()\n\n\nClone the current object. A new object is created, whose parent is the\ncurrent object. The new object's init method is called. Return\nvalue: The object ID of the new object. If the current object no\nlonger exists (ie., has been destroyed), #-1 is returned.\n\n", "program()" => "Function: program()\n\nSyntax: program([ _obj_ , _method_ ])\n\n\nEnter programming mode. This sets a flag on the player's descriptor\nsuch that all input from the player is diverted to a temporary file.\nWhen the player enters '.', the file is compiled, and then erased.\nThere can either be no arguments, in which case the server expects a\nseries of objects, or two arguments, which should be the object and\nmethod to program. In either case, the server currently uses a\nbuilt-in set of permissions checks to determine whether the player may\nreprogram that object: either they must be in the object's owners list,\nor in SYS_OBJ.wizards.\n\n", "listinsert()" => "Function: listinsert()\n\nSyntax: listinsert( _list_ , _value_ [ , _pos_ ] )\n\n\nInsert _value_ into _list_. By default, the new element is inserted at\nthe beginning of the list. If the optional numeric argument _pos_ is\ngiven, the element is inserted before position _pos_. Returns the new\nlist.\n\n", "@rmdark" => " \nCommand: @rmdark <variable> on <object>\n \nIf <object> is set public, <variable> will be removed from the list of variables that will not be world-readable regardless.\n \nSee also: @addlight, @rmlight, @adddark, @addwriteok, @rmwriteok, @publish\n \n", "dump" => "dump()", "@addowner" => "Command: @addowner <player> to <object>\n\nGive <player> ownership of <object>. You must be an owner of <object>.\n\nSee also: @rmowner\n", "@gender" => " \nCommand: @gender <string>\n \nSets your gender to the given string. Anything that starts with 'm' will cause you to be reffered to by masuline pronouns, 'f' gets feminine, and anything alse gets 'it'.\n \nSee also: @home, @describe, @rename\n \n", "setvar" => "setvar()", "@rmowner" => "Command: @rmowner <player> from <object>\n\nRemove ownership of <object> by <player>. You must own <object>.\nNote that once the last owner has been removed from an object,\nit may be manipulated/destroyed by anyone.\n\nSee also: @addowner\n", "sit" => " \nCommand: sit <furniture>\n sit on <furniture>\n sit down on <furniture>\n \nSit down on the named piece of furniture.\n \nSee also: lie, stand\n \n", "clone" => "clone()", "@show" => "Command: @show <object>\n\nShow the the parents list, and the values of all the variables on\n<object>. Note that any variables which are inherited from parents\nwill not be shown directly. You must own <object>, or it must be\npublic.\n\nSee also: @verbs @methods, @set\n", "@unpublish" => "Command: @unpublish <object>\n\nSet <object> non-public, so that only the owner(s) may @show, @methods,\n@list, etc it. You must own <object>.\n\nSee also: @publish, @show, @list, @methods, @verbs, @clone\n", "explode()" => "Function: explode()\n\nSyntax: explode( _str_ [, _sep_ ])\n\n\nBreak _str_ into a list of strings. By default, explode breaks on\nspaces; the optional second argument is the character to break on.\n\n", "listdelete()" => "Function: listdelete()\n\nSyntax: listdelete( _list_ , _pos_ )\n\n\nDeletes the element at position _pos_ in _list_. Returns the new\nlist.\n\n", "destroy()" => "Function: destroy()\n\nSyntax: destroy()\n\n\nDestroy the current object. The object itself is responsible for\ncleaning up any references to itself prior to this call. This might\ninclude removing any contained objects, re-parenting or destroying any\ninstances of it, etc.\n\n", "lock()" => "Function: lock()\n\nSyntax: lock( _str_ )\n\n\nThis function is used to lock an object, to prevent another execution\nthread from modifying the object before the current thread is finished\nwith it (see ``locking''). The argument _str_ is the name of the lock\nto place on the object. Locks placed by an execution thread remain in\neffect until a corresponding unlock() call, or until the method\nterminates.\n\n", "listappend()" => "Function: listappend()\n\nSyntax: listappend( _list_ , _value_ [ , _pos_ ] )\n\n\nAppends _value_ to the end of _list_, or after position _pos_, if\ngiven. Returns the new list.\n\n", "add_verb()" => "Function: add_verb()\n\nSyntax: add_verb( _verb_ , _prep_ , _method_ )\n\n\nAdd a verb to the current object. _verb_ is the name of the verb to\nadd. _prep_ is the preposition, or \"\" for none. _method_ is the name\nof the method to call in the current object when the verb gets\ntriggered. The verb is added to the end of the object's verb list,\nunless a verb with the same name and no preposition exists, in which\ncase it is inserted before that verb. This is to prevent a verb with\nno preposition masking one with a preposition.\n\n", "chparents()" => "Function: chparents()\n\nSyntax: chparents( _list_ )\n\n\nChange the parents of the current object to those specified in _list_.\nAll variables and methods on the object itself remain intact, however\nany variables or methods it inherited from its old parents parents it\nmay not inherit from the new. _list_ must be a non-empty list, and\nmust not cause any loops in the inheritance hierarchy (eg., an object\nmay not have itself or one of its children as a parent). Any children\nof the current object will also have their inheritance changed by this\ncall, such that the new parents specified in the list will be ancestors\nof the children as well.\n\n", "kill" => "kill()", "toerr" => "toerr()", "things" => " \nThings\n======\n \nget: To pick up an object, type 'get <object>'. Note that sometimes you won't be allowed to get an object that belongs to someone else.\ninventory: To see a list of objects you're carrying, type 'inventory', which can be abbreviated to 'i'.\ndrop: To put an object you're carrying into the room you're in, type 'drop <object>'.\ngive: To give something you're carrying to someone else, type 'give <thing> to <person>'. For example, if I'm carrying a couch and I want to give it to Joe, I'd type 'give couch to Joe'.\nput: To put something into a container, for example a marble into a bag, type 'put <thing> into <container>', e.g. 'put marble into bag'.\nremove: To take something out of a container, type 'get/remove/take <thing> from <container>'.\nlie: To lie down on furniture, type 'lie <furniture>'. You can also 'lie down on <furniture>'.\nsit: To sit on a piece of furniture, type 'sit <furniture>' or 'sit on <furniture>'.\nstand: To get up from furniture you are sitting or lying on, type stand or stand up.\nlook: To look at an object, type 'look <thing>', to look into a container, type 'look in <container>'.\n \n", "root functions" => " \nRoot Functions\n==============\n \nadd_owner add_parent add_verb announce chparents", "@password" => "Command: password <oldpasswd> to <newpasswd>\n @password <oldpasswd> to <newpasswd>\n\nChanges your password. You must specify your old password, <oldpasswd>,\nas well as your new password, <newpasswd>. Passwords in COOLMUD are stored\nin encrypted form.\n\nSee also: \n", "@shout" => "Command: @shout <message>\n\nSend <message> to all players on the mud.\n\nSee also: say, \", page\n", "@find" => "Command: @find [ <string> ]\n\nShow all objects you own, or all objects you own which match <string>.\n\nSee also: \n", "writelog" => "writelog()", "unlock()" => "Function: unlock()\n\nSyntax: unlock( _str_ )\n\n\nRemove the lock named _str_ from the current object. If any execution\nthreads are waiting for this lock to be removed, they will execute.\n\n", "decompile()" => "Function: decompile()\n\nSyntax: decompile()\n\n\nDecompiles the entire current object back to source. Returns a string,\ncontaining embedded newlines containing the source for the object.\nVariables are shown auto-initialized to their current values. This\nfunction can be *very* CPU-intensive, if the object is large.\n\n", "inventory" => "Command: inv\n inventory\n\nShows the contents of your inventory.\n\nSee also: look\n", "padl()" => " \nFunction: #1.padl()\n \nSyntax: padl( str, length, [padchar] )\n \nPads str into the appropriate length using padchar, with str left justified in the resulting string.\nPadchar defaults to \" \".\n \n See also: pad, padc.\n", "communication" => " \nCommunication\n=============\n \nThere are three other primary means besides talking to communicate with others on the MUD, posing, paging and whispering.\n \npose: Posing is a means of letting people know how you are feeling or standing or giving them information about body language. For example, to wave to someone you might type 'pose waves to Shar.', whereupon, assuming your name was Joe, everyone in the room would see 'Joe waves to Shar.'. Like say, pose has a short form, :, which works the same way. In either case, if the first character of the message you are posing is a :, the initial space will be remove, so '::'s sad.' would produce 'Joe's sad'.\npage: To let someone know where you are and that you are looking for them, just type 'page <person>'. To send someone a particular message, type 'page <person> with <message>'. Note that the person can be anywhere on the MUD.\nwhisper: To communicate with others in the same room privately, use 'whisper <stuff> to <player>'.\n\n", "help" => "Command: help [ <topic> ]\n\nGet some helpful information on a given topic. The help system is\ncurrently simply a collection of text files which the author of the\ncoolmud universe has cobbled together, so help may not be available on\nspecific object functions.\n\nSee also:\n", "news" => "Command: news [ <topic> ]\n\nGet some up-to-date information on a given topic. If no topic is\ngiven, current mud news is given. The news system is currently simply\na collection of text files which the author of the coolmud universe is\nbarely able to keep relevant. Cope.\n\nSee also: help\n", "topics" => " \nTopics\n======\n \nediting: A how-to on variable and method editing.\npermissions: A description of how the permission system works.\n \n", "permission commands" => "permissions commands", "wizards" => "Command: wizards\n\nShows the current list of wizards. You don't want to be one, trust me.\n\nSee also: who, rwho\n", "can_read" => "can_read()", "@addparent" => "Command: @addparent <object1> to <object2>\n\nAdd <object1> to the list of parents of <object2>. You must own <object2>.\nYou must own <object1> or <object1> must be public.\n\nSee also: @rmparent, @mutate\n", "remove" => " \nCommand: remove/get/take <object> from/in <container>\n \nRemove an object from inside a container.\n \nSee also: get, drop, put\n\n", "@decompile" => "Command: @decompile <object>\n\nDecompile the object <object> back into readable source form. This lists\nall variables (with initial values), verbs, and methods of the object.\nWarning: this can be quite large, especially for objects such as $player.\n\nSee also: @list\n", "listassign()" => "Function: listassign()\n\nSyntax: listassign( _list_ , _value_ , _pos_ )\n\n\nReplaces element at position _pos_ in _list_ with _value_. Returns the\nnew list.\n\n", "servers()" => "Function: servers()\n\nSyntax: servers()\n\n\nReturns a list corresponding to the system object (#0) at each remote\nserver (eg., #0@remotemud}, { #0@localmud, etc).\n\n", "toobj()" => "Function: toobj()\n\nSyntax: toobj( _var_ )\n\n\nConvert a num, string, or error value into an object ID value. Numbers\nare converted by using the number as the object ID portion of the new\nvalue, and the local server for the server ID portion. Strings are\nparsed, the same way itself parses: #3 or #3@foomud syntax. Errors\nare converted by using the internal ID of the error as the object ID\nportion, and the local server for the server ID portion.\n\n", "tonum()" => "Function: tonum()\n\nSyntax: tonum( _var_ )\n\n\nConvert an obj, string, or error value into a numeric value. Object\nvalues are converted by using the object ID portion as the new value.\nStrings are parsed like the UNIX function atoi(). Error values return\nthe internal ID of the error (which isn't much use except to trivia\naddicts).\n\n", "rm_var()" => "Function: rm_var()\n\nSyntax: rm_var( _str_ )\n\n\nRemove the variable (property) named _str_ from the current object.\n\n", "objsize()" => "Function: objsize()\n\nSyntax: objsize()\n\n\nReturns the size, on disc, of the current object. This reflects the\nideal size, and not the actual amount of memory or disc consumed by the\nobjecct, which are subject to malloc() tax, dbm tax, etc.\n\n", "@program" => "Command: @program [ <method> on <object> ]\n\nWith no arguments, the @program command accepts code for 1 or more COOL\nobjects. With arguments, it reprograms the method <method> on <object>.\nCode is accepted until a single line containing \".\" is entered. If\n<method> does not yet exist on <object>, it will be created.\n\nSee also: @list, @methods, @rmmethod, compile()\n"];
obj home = #13;
endobject
object #16
parents #4;
list contents = {};
str name = "Generic News Object";
list owners = {#11};
num public = 1;
obj location = #6;
map news_list = ["" => "No news defined!"];
obj home = #13;
verb "@setnews" : "to" = setnews;
verb "@listnews" = listnews;
verb "edit_news" = edit_news;
verb "rename_news" = rename_news;
method listnews
if (!this.can_read("news_list", caller))
raise E_PERM;
else
player.tell(news_list[args[2]]);
endif
endmethod
method rename_news
player.rename(args[1], "news_list " + args[2]);
endmethod
method edit_news
player.edit_var_cmd(args[1], "news_list " + args[2], "on", tostr(this));
endmethod
method setnews
if (!this.can_write("news_list", caller))
raise E_PERM;
else
news_list[args[2]] = args[4];
player.tell("Set news for topic " + tostr(args[2]) + " to " + tostr(args[4]));
endif
endmethod
method news
var last, cur;
ignore E_MAPNF;
cur = news_list[args[1]];
while (cur)
last = cur;
cur = news_list[cur];
endwhile
return last;
endmethod
endobject
object #17
parents #16;
list contents = {};
str name = "Global News Object";
list owners = {#11};
obj location = #11;
map news_list = ["" => "intro", "oldfeatures1" => "5 Mar: $furniture (in cooperation with $room) now lists you as\n \"sitting in the ...\" next to the room name. you can also only\n sit on one piece of furniture at a time.\n\n all online command should now be documented, at least briefly.\n online documentation for all functions has been massaged from\n the latex manual.\n\n6 Mar: sleep()'ing for 1 second or more will allow a task to run\n indefinitely (the recursion and maximum cpu limits will reset).\n so to do something ongoing, use:\n\n method foo\n while(1)\n ...\n sleep(1);\n endwhile\n endmethod\n\n WARNING: don't sleep() in a task that hasn't been at()'ed! this\n will cause the mud to totally ignore your input. (i hope to\n prevent this in future server versions..)\n\n so to initiate the above safely, do: at (0) object.foo; endat\n", "oldfeatures2" => "10 Mar: there is now a splice operator, @. so any moo programmers out\n there should be happier. \n the @list command now takes some flags:\n -n don't number lines\n -b full (pedantic) bracketing\n -i<num> indent code by <num> spaces\n10 Mar: the networking code should be a bit more reliable.\n the command on $network_utils has been changed to \"finger\"\n (from \"netfinger\"). if the username contains no @, the\n user on the mud with that name is fingered, otherwise a\n \"real\" network finger is done.\n\n", "features" => "May 13, 1998: Added aliases to exits and players.\n \nThe following was entered May 4, 1998, mostly done over the previous few weeks.\n \nRan the server through purify. Damn, that fixed a lot of bugs. Much, much, much less prone to crashes now.\nMoved all the help, news and the connection message into the database, because having them in flatfiles that I had to leave the mud to edit bothered me.\nAdded a new built-in function, echon(), which is just like echo except that it doesn't stick a newline at the end.\nAdded a _large_ suite of editing commandds for in-place (well, simulated in-place) editing of variables and methods. Damn, it makes stuff easier. As of this writing, help for these is not yet written, but it shouldn't be long.\n\n", "oldfeatures" => "5 Mar: $furniture (in cooperation with $room) now lists you as\n \"sitting in the ...\" next to the room name. you can also only\n sit on one piece of furniture at a time.\n\n all online command should now be documented, at least briefly.\n online documentation for all functions has been massaged from\n the latex manual.\n\n6 Mar: sleep()'ing for 1 second or more will allow a task to run\n indefinitely (the recursion and maximum cpu limits will reset).\n so to do something ongoing, use:\n\n method foo\n while(1)\n ...\n sleep(1);\n endwhile\n endmethod\n\n WARNING: don't sleep() in a task that hasn't been at()'ed! this\n will cause the mud to totally ignore your input. (i hope to\n prevent this in future server versions..)\n\n so to initiate the above safely, do: at (0) object.foo; endat\n", "intro" => "This is COOLMUD v2.2.2alpha2, a distributed, multi-user, object-oriented,\nprogrammable worldbuilding environment.\n \nNews lists information on server and core object updates and new features, as well as news about recent events on this server.\nCurrent items of news:\n\n features: Most recent list of new features.\n oldfeatures1: Least recent list of new features.\n oldfeatures2: Sligtly more recent list of new features.\n \n"];
obj home = #13;
endobject
object #18
parents #4;
str ositfailmsg = "%n tries to sit on the couch, but then realizes %s's already sitting on it!";
str ositmsg = "%n sits on the couch.";
list contents = {};
num sit = 1;
list liers = {};
str sitmsg = "You sit on the couch.";
str name = "Generic Furniture";
num lie = 1;
str oliemsg = "%n lies on the bed.";
list owners = {#11};
str liemsg = "You lie down on the couch.";
str oliefailmsg = "%n tries to lie on the bed, but is repelled by some mysterious force.";
list sitters = {};
obj location = #13;
str subname = "lounging on the bed";
str standmsg = "You stand up from the couch.";
obj home = #13;
str ostandmsg = "%n stands up from the couch.";
verb "stand" : "up up_from" = stand_verb;
verb "stand" = stand_verb;
verb "sit" : "on down_on" = sit_verb;
verb "sit" = sit_verb;
verb "lie" : "on down_on" = lie;
verb "lie" = lie;
method stand_verb
if (args[2] && args[2] != "up")
return 1;
elseif (!(player in sitters) && !(player in liers))
return 1;
else
if (player in sitters)
sitters = sitters - player;
elseif (player in liers)
liers = liers - player;
endif
player.set_sublocation(#-1);
player.tell(standmsg);
location.announce(player.psub(ostandmsg), {player});
endif
endmethod
method event_exit
var dummy;
if (args[1] in sitters)
dummy = args[1].tell("[Standing up from " + this.dname + " first.]");
location.announce(player.name + " stands up from " + this.dname + " suddenly.");
player.set_sublocation(#-1);
sitters = sitters - args[1];
endif
endmethod
method subremove
player.tell("[Standing up from " + this.name + " first.]");
location.announce(player.psub(ostandmsg), {player});
sitters = sitters - player;
player.set_sublocation(#-1);
endmethod
method lie
if (!lie)
player.tell("You can't lie down on that!");
endif
if (args[3])
if (!this.match(args[4]))
return 1;
endif
else
if (!this.match(args[2]))
return 1;
endif
endif
if (player in liers || player.sublocation == this)
player.tell("You're already lying on it!");
location.announce(player.psub(oliefailmsg), {player});
return 0;
endif
if (player.sublocation != #-1)
player.sublocation.subremove(player);
endif
liers = liers + player;
player.set_sublocation(this);
player.tell(liemsg);
location.announce(player.psub(oliemsg), {player});
endmethod
method sdesc
var txt;
txt = "You see " + this.iname + " here";
if (sitters)
txt = txt + ", with " + this.english_list(sitters) + " sitting on it";
if (liers)
txt = txt + ", and " + this.english_list(liers) + " lying on it";
endif
elseif (liers)
txt = txt + ", with " + this.english_list(liers) + " lying on it";
endif
txt = txt + ".";
return txt;
endmethod
method subname
return "sitting on " + this.dname;
endmethod
method look
pass();
if (!sitters)
player.tell("No-one is sitting on " + this.dname + " at the moment.");
elseif (lengthof(sitters) > 1)
player.tell(this.english_list(sitters) + " are sitting on " + this.dname + ".");
else
player.tell(sitters[1].name + " is sitting on " + this.dname + ", all alone.");
endif
if (!liers)
player.tell("No-one is lying on " + this.dname + " at the moment.");
elseif (lengthof(liers) > 1)
player.tell(this.english_list(liers) + " are lying on " + this.dname + ".");
else
player.tell(liers[1].name + " is lying on " + this.dname + ", all alone.");
endif
endmethod
method sit_verb
if (!sit)
player.tell("You can't sit down on that!");
endif
if (args[3] && !this.match(args[4]))
return 1;
elseif (!args[3] && !this.match(args[2]))
return 1;
elseif (player in sitters || player.sublocation == this)
player.tell("You're already sitting on it!");
location.announce(player.psub(ositfailmsg), {player});
return 0;
endif
if (player.sublocation != #-1)
player.sublocation.subremove(player);
endif
sitters = sitters + player;
player.set_sublocation(this);
player.tell(sitmsg);
location.announce(player.psub(ositmsg), {player});
endmethod
endobject
object #13@west
parents #6;
name = "Western Room";
desc = "Y'all are in the western room, cowboy.";
exits = { #19@west };
method init
this.add_owner(#11);
endmethod
endobject
object #19@west
parents #7;
name = "e;east";
leave = "You go east.";
oleave = "%n goes east.";
oarrive = "%n comes in from the west.";
source = #13@west;
dest = #13@east;
method init
this.add_owner(#11);
endmethod
endobject
object #20@west
parents #4;
home = #13@west;
name = "a punching bag";
desc = "A punching bag with a picture of Brian Mulroney taped to it.";
verb "hit punch smack whomp sock" = hit;
method init
this.moveto(home);
this.add_owner(#11);
endmethod
method sdesc
return ("There is " + name + " here, just waiting to be hit.");
endmethod
method hit
if (!this.match(args[2]))
return 1;
endif
player.tell("You sock the punching bag on da nose! How satisfying.");
location.announce(player.name +
" socks the punching bag on da nose!", {player});
at (time() + 5)
location.announce("The punching bag winds up..", {});
endat
at (time() + 10)
if (player.location == location)
player.tell("The punching bag whomps you on da shnozz!");
location.announce("The punching bag whomps "
+ player.name + " on da shnozz!", {player});
else
location.announce("The punching bag appears confused, as "
+ player.name + " has left the room.", {});
endif
endat
endmethod
endobject
object #21@west
parents #5;
name = "a brown paper bag";
desc = "A very ordinary-looking brown paper bag.";
home = #13@west;
method init
this.add_owner(#11);
this.moveto(home);
endmethod
endobject