Wingy's Snow MOO Programming Cheat Sheet (modified from numerous
authors)
A programmers guide for Sensemedia's Snow Moo User Programmers...
Last HTML Update October 3, 1998 by Zorro
Document compiled by Wingnut
A great guy by the way....
Mail him HERE...
Webbed (HTML) version compiled
by Bruce 'Zorro' Larrabee
Mail him HERE...
Updated and maintained by Bruce 'Zorro' Larrabee
Help included on the following utilities:
Types of data recognized:
TYPE ->type Example
-
NUM ->number 34
-
INT (same as NUM)
-
STR ->string "Hi, said John."
-
OBJ ->object #23
-
LIST ->list {34, "a string", {"a", "sublist", 3}, {}}
-
ERR ->error E_TYPE
-
FLOAT ->floating point number 2.24
Data type can be determined using typeof(data).
Typeof Variables and thier Values
| KEYWORD |
VALUE |
Description |
Visability |
| INT |
0 |
Integer |
YES |
| NUM |
0 |
Same as INT |
YES |
| OBJ |
1 |
Object |
YES |
| STR |
2 |
String |
YES |
| ERR |
3 |
Error |
YES |
| LIST |
4 |
Linked list |
YES |
| CLEAR |
5 |
Clear properties value slot |
NO |
| NONE |
6 |
Uninitialized variables |
NO |
| CATCH |
7 |
On-stack marker for an exception handler |
NO |
| FINALLY |
8 |
On-stack marker for a TRY-FINALLY clause |
NO |
| FLOAT |
9 |
Floating point numbers |
YES |
Errors
-
E_NONE no error
-
E_TYPE type mismatch
-
E_DIV divide by zero
-
E_RANGE invalid subscript (range error)
-
E_INVARG invalid argument
-
E_VARNF variable not found
-
E_PROPNF property not found
-
E_VERBNF verb not found
-
E_PERM permission denied
-
E_INVIND invalid (indirection) object number
-
E_MAXREC exceeded maximum recursion (verbs) depth
-
E_RECMOVE recursive move
-
E_ARGS wrong number of arguments
-
E_QUOTA resource linit exceeded
-
E_FLOAT floating point math error
-
E_NACC not accepted by database error
Subscripting
-
Everything is 1-based.
-
subscript lists or strings
-
s[expression] is lvalue and rvalue
-
s[expr..expr] does slices. Exprs must be in range.
-
@expr does list splicing for lists or arguments.
Special variables in functions
-
player an object, the player who typed the command
-
this an object, the object on which this verb was found
-
caller an object, the same as `player'
-
verb a string, the first word of the command
-
argstr a string, everything after the first word of the command
-
args a list of strings, the words in `argstr'
-
args[1..N] thus, will index into `argstr'
-
dobjstr a string, the direct object string found during parsing
-
dobj an object, the direct object value found during matching
-
prepstr a string, the prepositional phrase found during parsing
-
iobjstr a string, the indirect object string
-
iobj an object, the indirect object value
Expresions
Usual C stuff, except:
-
cond ? expr1 | expr2 conditional expressions
-
$foo #0.foo
-
"str" + "str" concatenation
-
expr in list list membership, returns index or 0 (false)
Strings comparisons are case-insensitive.
Statements
-
if (expr); ... elseif (expr); ... else; ... endif
-
for variable in (expression); ... endfor
-
for variable in (expression); ... break; endfor
-
for variable in (expression); ... continue; endfor
-
for variable in (expression); ... break variable; endfor
-
for variable in (expression); ... continue variable; endfor
-
for variable in [expr1..expr2]; ... endfor
-
for variable in [expr1..expr2]; ... break; endfor
-
for variable in [expr1..expr2]; ... continue; endfor
-
for variable in [expr1..expr2]; ... break variable; endfor
-
for variable in [expr1..expr2]; ... continue variable; endfor
-
while (expr); ... endwhile
-
while (expr); ... break; endwhile
-
while (expr); ... continue; endwhile
-
while (expr); ... break expr; endwhile
-
while (expr); ... continue expr; endwhile
-
fork (expr); ... endfork
-
fork name (expr); ... endfork
-
try; ... except variable; ... endtry
-
try; ... except variable; ... finally; ... endtry
CORE Commands...
Entries ending with (*) are wizard only...
-
pass(arg, ...) -- calling a verb defined on this object's parent
-
eval(string) -- parsing and executing strings as MOO code
-
notify(player, string) -- sending text to a player's terminal
-
read() -- reading a line of input from the player (*)
-
output_delimiters(player) -- return {prefix,suffix} set by PREFIX/SUFFIX
cmds
-
typeof(value) -- determining the data type of a value
-
tostr(value, ...) -- converting any set of values into a string
-
tonum(value) -- converting any non-list value into a number
-
toobj(value) -- converting any non-list value into an object
-
length(value) -- returns the length of a string or list
-
is_player(object) -- testing whether or not object is a player
-
players() -- a list of all players, active or not
-
connected_players() -- a list of all currently-connected players
-
idle_seconds(player) -- seconds since given player typed anything
-
connected_seconds(player) -- seconds given player has been logged in
-
boot_player(player) -- disconnect player from the MOO immediately*
-
set_player_flag(player, value) -- set/clear player bit; boot player if
clear*
-
connection_name(player) -- server-assigned name of player's connection
-
open_network_connection(@args) -- open a connection to another network
site
-
caller_perms() -- the player whose permissions your caller was using
-
set_task_perms(player) -- changing permissions of the running task *
-
callers() -- list of {obj, verb, owner, vloc, player}: this task's stack
-
suspend(secs) -- suspending the current task for a number of seconds
-
seconds_left() -- number of seconds left in the current task
-
ticks_left() -- number of ticks left in the current task
-
task_id() -- a random number representing the currently-running task
-
queued_tasks() -- list of {id,start,0,20000,owner,obj,verb,line,this}
-
kill_task(id) -- delete one of your tasks from the queue
-
server_log(string) -- add a comment to the server log file
-
server_version() -- a string of three numbers "major.minor.release"
-
memory_usage() -- {{blocksize, nused, nfree}, ...}, server's mem stats
-
shutdown(msg) -- print msg and kill the server *
-
dump_database() -- what it says *
CORE Commands
for Objects
Entries ending with (*) are wizard only...
-
valid(object) -- testing whether an object exists
-
create(parent [, owner(*)]) -- creating a new MOO object
-
recycle(object) -- destroying a MOO object
-
move(object, where) -- altering the object-containment hierarchy
-
chparent(object, new-parent) -- altering the object-inheritance hierarchy
-
parent(object) -- object's parent in inheritance hierarchy
-
children(object) -- object's children inheritance hierarchy
-
max_object() -- the highest-numbered object in the MOO
-
renumber(obj) -- changes object's number to lowest available one*
-
reset_max_object() -- resets max_object() to the largest valid object*
-
properties(object) -- a list of the properties defined on an object
-
add_property(object, prop-name, value, info) -- add a new property
-
delete_property(object, prop-name) -- remove a property
-
property_info(object, prop-name) -- {owner, perms} info on prop
-
set_property_info(object, prop-name, info) -- setting same
-
is_clear_property(object, prop-name) -- check if a prop. is "clear"
-
clear_property(object, prop-name) -- make a property "clear"
-
verbs(object) -- a list of the verbs defined on an object
-
add_verb(object, info, args) -- add a verb to an object
-
delete_verb(object, verb-name) -- remove a verb from an object
-
verb_info(object, verb-name) -- {owner, perms, names} info for verb defn.
-
verb_args(object, verb-name) -- {dobj, prep, iobj} argument info for verb
-
verb_code(object, verb-name [, fully-paren [, indent]]) -- program listing
-
set_verb_info(object, verb-name, {owner, perms, names})
-
set_verb_args(object, verb-name, {dobj, prep, iobj})
-
set_verb_code(object, verb-name, {line, line, ...})
CORE Commands for Strings
-
index(str1, str2 [, case-matters]) -- index of first str2 in str1
-
rindex(str1, str2 [, case-matters]) -- index of last str2 in str1
-
strcmp(str1, str2) -- case-sensitive string comparison
-
strsub(subject, what, with [, case-matters]) -- substitution in a string
-
crypt(string [, salt]) -- one-way string encryption
-
match()
Syntax: match (STR < subject >, STR < pattern > [, < case-matters
>]) = > LIST
The function `match()' searches for the first occurrence of the regular
expression < pattern > in the string < subject >. If < pattern
> is syntactically malformed, then E_INVARG is raised. The process of matching
can in some cases consume a great deal of memory in the server; should
this memory consumption become excessive, then the matching process is
aborted and E_QUOTA is raised. If no match is found, the empty list is
returned; otherwise, these functions return a list containing information
about the match (see below). By default, the search ignores upper/lower
case distinctions. If < case-matters > is provided and true, then case
is treated as significant in all comparisons. The list that `match()' returns
contains the details about the match made. The list is in the form: {<
start >, < end >, < replacements >, < subject >} where < start
> is the index in STRING of the beginning of the match, < end > is the
index of the end of the match, < replacements > is a list described
below, and < subject > is the same string that was given as the first
argument to the `match()' or `rmatch()'. The < replacements > list is
always nine items long, each item itself being a list of two numbers, the
start and end indices in < subject > matched by some parenthesized sub-pattern
of < pattern >. The first item in < replacements > carries the indices
for the first parenthesized sub-pattern, the second item carries those
for the second sub-pattern, and so on. If there are fewer than nine parenthesized
sub-patterns in < pattern >, or if some sub-pattern was not used in
the match, then the corresponding item in < replacements > is the list
{0, -1}. See the discussion of `%)' in `help regular-expressions', for
more information on parenthesized sub-patterns.
-
match("foo", "f*o") = > {1, 2, {{0, -1}, ...}, "foo"}
-
match("foo", "fo*") = > {1, 3, {{0, -1}, ...}, "foo"}
-
match("foobar", "o*b") = > {2, 4, {{0, -1}, ...}, "foobar"}
-
match("foobar", "f%(o*%)b") = > {1, 4, {{2, 3}, {0, -1}, ...}, "foobar"}
See `help regular-expressions' for information on the syntax and semantics
of patterns.
-
rmatch(str1, str2 [, case-matters]) -- match last pattern str2 in str1
-
substitute(template, subs) -- perform substitutions on template
-
string_hash (str text) -- returns a hexadecimal string encoding the result
of applying the MD5 cryptographically secure hash function to the contents
of the string text
-
binary_hash (str bin-string) -- returns a hexadecimal string encoding the
result of applying the MD5 cryptographically secure hash function to the
contents of the binary string
-
decode_binary(binary-str,[fully]) -- returns a list of strings and/or integers
representing the bytes in the binary string bin_string in order
-
encode_binary(arg, ...) -- returns the concatenation of all the substrings
into a single binary string
CORE Commands
for Math
-
min(n1, n2, ...) -- minimum of n1,n2,...
-
max(n1, n2, ...) -- maximum of n1,n2,...
-
abs(n) -- abs (num < x >)
Returns the absolute value of < x >. If < x > is negative, then
the result is `- < x >'; otherwise, the result is < x >. The number
x can be either integer or floating-point; the result is of the same kind.
-
sqrt(n) -- square root of n, rounded down
-
random(n) -- random integer between 1 and n inclusive
String Utilities
$string_utils
Conversion routines:
-
:from_list (list [,sep]) => "foo1foo2foo3"
-
:english_list (str-list[,none-str[,and-str[, sep]]])=> "foo1, foo2, and
foo3"
-
:title_list*c (obj-list[,none-str[,and-str[, sep]]])=> "foo1, foo2, and
foo3" or => "Foo1, foo2, and foo3"
-
:from_value (value [,quoteflag [,maxlistdepth]]) => "{foo1, foo2,foo3}"
-
:print (value) => value in string
-
:abbreviated_list (value, options) => short value in string
-
:to_value (string) => {success?, value or error message}
-
:prefix_to_value(string) => {rest of string, value} or {0, error message}
-
:english_number(42) => "forty-two"
-
:english_ordinal(42) => "forty-second"
-
:ordinal(42) => "42nd"
-
:group_number(42135 [,sep]) => "42,135"
-
:from_ASCII(65) => "A"
-
:to_ASCII("A") => 65
-
:from_seconds(number) => str of rough time passed in large increments
-
:name_and_number(obj [,sep]) => "ObjectName (#obj)"
-
:name_and_number_list({obj1,obj2} [,sep]) => "ObjectName1 (#obj1) and ObjectName2
(#obj2)"
-
:nn is an alias for :name_and_number.
-
:nn_list is an alias for :name_and_number_list.
Type checking:
-
:is_numeric (string) => return true if string is composed entirely of digits
Parsing:
-
:explode (string,char) -- str => list of words delimited by char
-
:words (string) -- str => list of words (as with command line parser)
-
:word_start (string) -- str => list of start-end pairs.
-
:first_word (string) -- str => list {first word, rest of string} or {}
-
:char_list (string) -- str => list of characters in string
-
parse_command (cmd_line [,player]) -- => mimics action of builtin parser
Matching:
-
:find_prefix (prefix, string-list) =>list index of element starting with
prefix
-
:index_delimited(string,target[,case])=>index of delimited string occurrence
-
:index_all (string, target string) => list of all matched positions
-
:common (first string, second string) => length of longest common prefix
-
:match (string, [obj-list, prop-name]+) => matching object
-
:match_player (string-list[,me-object]) => list of matching players
-
:match_object (string, location) => default object match...
-
:match_player_or_object (string, location) => object then player matching
-
:literal_object (string) => match against #xxx, $foo
-
:match_stringlist (string, targets) => match against static strings
-
:match_string (string, wildcard, options) => match against a wildcard
Pretty printing:
-
:space (n/string[,filler]) => n spaces
-
:left (string,width[,filler]) => left justified string in field
-
:right (string,width[,filler]) => right justified string in field
-
:center/re (string,width[,lfiller[,rfiller]]) => centered string in field
-
:columnize/se (list,n[,width]) => list of strings in n columns
Substitutions
-
:substitute (string,subst_list [,case]) -- general substitutions.
-
:substitute_delimited (string,subst_list [,case])
-- like subst, but uses index_delim
-
:pronoun_sub (string/list[,who[,thing[,location]]]) -- pronoun substitutions.
-
:pronoun_sub_secure (string[,who[,thing[,location]]],default) -- substitute
and check for names.
-
:pronoun_quote (string/list/subst_list) -- quoting for pronoun substitutions
Miscellaneous string munging:
-
:trim(string) => string with outside whitespace removed.
-
:triml(string) => string with leading whitespace removed.
-
:trimr(string) => string with trailing whitespace removed.
-
:strip_chars(string,chars) => string with all chars in `chars' removed.
-
:strip_all_but(string,chars) => string with all chars not in `chars' removed.
-
:capitalize/se(string) => string with first letter capitalized.
-
:uppercase/lowercase(string) => string with all letters upper or lowercase.
-
:names_of(list of OBJ) => string with names and object numbers of items
-
:a_or_an(word) => "a" or "an" as appropriate for that word.
-
:reverse(string) => "gnirts"
A useful property:
-
:alphabet => "abcdefghijklmnopqrstuvwxyz"
Suspended versions:
(with _suspended at end of name)
-
:print :from_value :columnize/se
Object Utilities
$object_utils
These are useful for finding out information about individual objects.
Examining everything an object has defined on it:
-
:all_verbs(object) => like it says
-
:all_properties(object) => likewise
-
:findable_properties(object) => tests to see if caller can "find" them
-
:owned_properties(object[, owner]) => tests for ownership
Investigating inheritance:
-
:ancestors(object[,object...]) => all ancestors
-
:descendants(object) => all descendants
-
:ordered_descendants(object) => descendants, in a different order
-
:leaves(object) => descendants with no children
-
:branches(object) => descendants with children
-
:isa(object,class) => true iff object is a descendant of class (or ==)
-
:property_conflicts(object,newparent) => can object chparent to newparent?
-
:isoneof(object,list) => true if object :isa class in list of parents
Considering containment:
-
:contains(obj1, obj2) => Does obj1 contain obj2 (nested)?
-
:all_contents(object) => return all the (nested) contents of object
-
:locations(object) => list of location hierarchy above object
Verifying verbs and properties:
(identify location and usable name of verb)
-
:has_property(object,pname) => false/true does object.(pname) exist?
-
:has_readable_property(object,pname) => false/true if prop exists and is
+r
-
:defines_property(object,pname) => does object *define* this property
-
:has_verb(object,vname) => false/{#obj} does object:(vname) exist?
-
:has_callable_verb => same, verb must be callable from a program
-
:defines_verb(object,vname) => does this object *define* this verb
-
:match_verb(object,vname) => false/{location, newvname}
Player checking:
-
:connected(object) => true if object is a player and is connected
Suspending:
(Many of the above verbs have ..._suspended versions to assist with
very large object hierarchies.)
The following exist:
-
:descendants_suspended
-
:branches_suspended
-
:leaves_suspended
-
:all_properties_suspended
-
:descendants_with_property_suspended
List Utilities
$list_utils
-
listinsert(list, value [, index]) -- adding an element at the head of list
-
listset(list, value, index) -- updating a list at some index
-
listdelete(list, index) -- removing an element from a list
-
setadd(list, element) -- add element to a set represented as a list
-
setremove(list, element) -- remove element from such a set
-
:append(list,list,..) => result of concatenating the given lists
-
:reverse(list) => reversed list
-
:remove_duplicates(list) => list with all duplicates removed
-
:compress(list) => list with consecutive duplicates removed
-
:setremove_all(list,elt) => list with all occurrences of elt removed
-
:find_insert(sortedlist,e) => index of first element > e in sortedlist
-
:sort(list[,keys]) => sorted list
-
:count(elt,list) => count of elt found in list.
-
:flatten(list) => flatten all recursive lists into 1 list
-
:make(n[,e]) => list of n copies of e
-
:range(m,n) => {m,m+1,...,n}
-
:arrayset (list,val,i[,j,k...]) => array modified so that list[i][j][k]
== val
Mapping functions:
(take a list and do something to each element):
-
:map_prop({o...},prop) => list of o.(prop) for all o
-
:map_verb({o...},verb[,args) => list of o:(verb)(@args) for all o
-
:map_arg([n,]obj,verb,{a...},args) => list of obj:(verb)(a,@args) for all
a
-
:map_builtin(objectlist, function) => applies function to all in objectlist
Association list functions:
(An association list (alist) is a list of pairs (2-element lists),
though the following functions have been generalized for lists of n-tuples
(n-element lists).
In each case i defaults to 1.)
-
:assoc(targ,alist[,i]) => 1st tuple in alist whose i-th elem. is targ
-
:iassoc(targ,alist[,i]) => index of same.
-
:assoc_prefix(targ,alist[,i]) => ... whose i-th element has targ as a prefix
-
:iassoc_prefix(targ,alist[,i]) => index of same.
-
:slice(alist[,i]) => list of i-th elements
-
:sort_alist(alist[,i]) => alist sorted on i-th elements.
Math Utilities
$math_utils
Trigonometric/Exponential functions:
-
:sin(a),cos(a),tan(a) -- returns 10000*(the value of the corresponding
trigonometric function) angle a is in degrees.
-
:arctan([x,]y) -- returns arctan(y/x) in degrees in the range -179..180.
x defaults to 10000. Quadrant is that of (x,y).
-
:exp(x[,n]) -- calculates e^x with an nth order taylor polynomial
Statistical functions:
-
:combinations(n,r) -- returns the number of combinations given n objects
taken r at a time.
-
:permutations(n,r) -- returns the number of permutations possible given
n objects taken r at a time.
Number decomposition:
-
:div(n,d) -- correct version of / (handles negative numbers correctly)
-
:mod(n,d) -- correct version of % (handles negative numbers correctly)
-
:divmod(n,d) -- {div(n,d),mod(n,d)} (combined div & mod)
-
:parts(n,q[,i]) -- returns list of two elements {integer,decimal,fraction}
Other math functions:
-
:sqrt(x) -- returns the largest integer n <= the square root of x
-
:pow(x,n) -- returns x^n
-
:factorial(x) -- returns x!
Series:
-
:fibonacci(n) -- returns the 1st n fibonacci numbers in a list
-
:geometric(x,n) -- returns the value of the nth order geometric series
at x
Integer Properties:
-
:gcd(a,b) -- find the greatest common divisor of the two numbers
-
:lcm(a,b) -- find the least common multiple of the two numbers
-
:are_relatively_prime(a,b) -- return 1 if a and b are relatively prime
-
:is_prime(n) -- returns 1 if the number is a prime and 0 otherwise
Miscellaneous:
-
:random(n) -- returns a random number from 0..n if n > 0 or n..0 if n <
0
-
:random_range(n[,mean]) -- returns a random number from mean - n..mean
+ n with mean defaulting to 0
-
:simpson({a,b},{f(a),f((a+b)/2),f(b)}) -- returns the numerical approxi-
mation of an integral using simpson's rule
Bitwise Arithmetic:
Time Utilities
$time_utils
-
:time() -- current time in seconds since midnight GMT, 1 Jan 70
-
:ctime([time]) -- time (or current time) converted to human-readable string
Converting from seconds-since-1970:
-
:dhms(time) => string ...DD:HH:MM:SS
-
:english_time(time[, reference time) => string of y, m, d, h, m, s
Converting to seconds:
-
:to_seconds("hh:mm:ss") => seconds since 00:00:00
-
:from_ctime(ctime) => corresponding time-since-1970
-
:from_day(day_of_week, which) => time-since-1970 for the given day*
-
:from_month(month, which) => time-since-1970 for the given month* (* the
first midnight of that day/month)
-
:parse_english_time_interval("n1 u1 n2 u2...") => seconds in interval
-
:seconds_until_time("hh:mm:ss") => number of seconds from now until then
-
:seconds_until_date("month",day,"hh:mm:ss",flag) => number of seconds from
now until then
Converting to some standard English formats:
-
:day([c]time) => what day it is
-
:month([c]time) => what month it is
-
:ampm([c]time[, precision]) => what time it is, with am or pm
-
:mmddyy([c]time) => date in format MM/DD/YY
-
:ddmmyy([c]time) => date in format DD/MM/YY
Substitution:
-
:time_sub(string, time) => substitute time information
Miscellaneous:
-
:sun([time]) => angle between sun and zenith
-
:dst_midnight(time)
Sequence Utilities
$seq_utils
(A sequence is a set of integers. integers in the range [$minint+1..$maxint].
The implementation depends on $minint never being included in a sequence.)
-
:add (seq,f,t) => seq with [f..t] interval added
-
:remove (seq,f,t) => seq with [f..t] interval removed
-
:range (f,t) => sequence corresponding to [f..t]
-
{} => empty sequence
-
:contains (seq,n) => n in seq
-
:size (seq) => number of elements in seq
-
:first (seq) => first integer in seq or E_NONE
-
:firstn (seq,n) => first n integers in seq (as a sequence)
-
:last (seq) => last integer in seq or E_NONE
-
:lastn (seq,n) => last n integers in seq (as a sequence)
-
:complement(seq) => sequence consisting of integers not in seq
-
:union (seq,seq,...) => union of all sequences
-
:intersect(seq,seq,...) => intersection of all sequences
-
:contract (seq,cseq) (see `help $seq_utils:contract')
-
:expand (seq,eseq[,include]) (see `help $seq_utils:expand')
-
:extract(seq,array) => array[@seq]
-
:for([n,]seq,obj,verb,@args) => for s in (seq) obj:verb(s,@args); endfor
-
:tolist(seq) => list corresponding to seq
-
:tostr(seq) => contents of seq as a string
-
:from_list(list) => sequence corresponding to list
-
:from_sorted_list(list) => sequence corresponding to list (assumed sorted)
-
:from_string(string) => sequence corresponding to string
For boolean expressions, note that the representation of the empty sequence
is {} (boolean FALSE)
and all non-empty sequences are represented as non- empty lists (boolean
TRUE).
The representation used works better than the usual list implementation
for sets consisting of long uninterrupted ranges of integers. For sparse
sets of integers the representation is decidedly non-optimal (though it
never takes more than double the space of the usual list representation).
Set Utilities
$set_utils
(This object is useful for operations that treat lists as sets.)
(i.e., without concern about order and assuming no duplication).
-
:union(set, set, ...) => union
-
:intersection(set, set, ...) => intersection
-
:intersection_preserve_case(base set, set, set, ...) => intersection with
the case of the base set's elements preserved
-
:diff*erence(set1, set2, ..., setn) => result of removing all elements
of sets 2..n from set 1.
-
:exclusive_or(set, set, set, ...) => all elements that are contained in
exactly one of the sets
-
:contains(set1, set2, ..., setn) => true if and only if all of sets 2..n
are subsets of set 1
-
:equal(set1, set2) => true if and only if set1 and set2 are equal
Command Utilities
$command_utils
Detecting and Handling Failures in Matching:
-
:object_match_failed(match_result, name) Test whether or not a :match_object()
call failed and print messages if so.
-
:player_match_failed(match_result, name) Test whether or not a :match_player()
call failed and print messages if so.
-
:player_match_result(match_results, names) ...similar to :player_match_failed,
but does a whole list at once.
Reading Input from the Player:
-
:read() -- Read one line of input from player and return it.
-
:yes_or_no([prompt]) -- Prompt for and read a `yes' or `no' answer.
-
:read_lines() -- Read zero or more lines of input from the player.
-
:dump_lines(lines) -- Return list of lines quoted so that feeding them
to
-
:read_lines() will reproduce the original lines.
Utilities for Suspending:
-
:running_out_of_time() -- Return true if we're low on ticks or seconds.
-
:suspend_if_needed(time) -- Suspend (and return true) if we're running
out of time.
Client Support for Lengthy Commands:
-
:suspend(args) -- Handle PREFIX and SUFFIX for clients in long commands.
Code Utilities
$code_utils
Parse verb and property references:
-
parse_propref("foo.bar") => {"foo","bar"} (or 0 if arg. isn't a property
ref.)
-
parse_verbref("foo:bar") => {"foo","bar"} (or 0 if arg. isn't a verb ref.)
-
parse_argspec("any","in","front","of","this","baz"...) => {{"any", "in
front of", "this"},{"baz"...}} (or string if args don't parse)
Conversion:
-
toint(string) => integer (or E_TYPE if string is not a integer)
-
toobj(string) => object (or E_TYPE if string is not an object)
-
toerr(integer or string) => error value (or 1 if out of range or unrecognized)
Integer to error name conversion:
-
error_name(error value) => name of error (e.g., error_name(E_PERM) => "E_PERM")
Preposition routines:
-
prepositions() => full list of prepostions.
-
full_prep("in") => "in/inside/into".
-
short_prep("into") => "in".
-
short_prep("in/inside/into") => "in".
-
get_prep("off", "of", "the", "table") => {"off of", "the", "table"}
Verb routines:
-
verb_perms() => the current task_perms (as set by set_task_perms()).
-
verb_location() => the object where the current verb is defined.
-
verb_frame() => callers()-style frame for the current verb.
-
verb_all_frames() => entire callers() stack including current verb.
-
verb_usage([object,verbname]) => returns first line of verb doc, usually
usage.
-
verb_documentation([object,verbname]) => documentation at beginning of
verb code, if any -- default is the calling verb.
-
set_verb_documentation(object,verbname,text) => sets text at beginning
of verb.
-
verbname_match(fullname,name) => can `name' be used to call `fullname'.
-
find_verb_named(object,name[,n]) => verb number or 0 if not found.
-
find_last_verb_named(object,name[,n]) => verb number of last verb match.
-
find_callable_verb_named(object,name[,n]) => verb number or 0 if not found.
-
find_verbs_containing(pattern[,object|objlist]) => does work for @grep.
-
find_verbs_matching(pattern[,object|objlist]) => does work for @egrep.
-
move_verb(from obj,name,to obj[,newname]) => move a verb from object to
object.
-
move_prop(from obj,name,to obj[,newname]) => move a property to another
object.
Verbs that do the actual dirty work for command lines verbs:
@show
-
show_object(object)
-
show_property(object,propname)
-
show_verbdef (object,verbname)
explain_syntax
-
explain_verb_syntax(thisname,verbname,@verbargs)
eval*-d
-
eval_d(code)
help
-
help_db_list([player])
-
help_db_search(string topic, dblist)
@who
-
show_who_listing(players [,more_players])
@check-full
-
display_callers([callers() output])
Random but useful verbs:
-
verb_or_property(object,name[,@args]) => result of verb or property call,or
E_PROPNF.
-
corify_object(object) => if the object is corified, returns $<name>.
-
task_valid(INT task_id) => returns true if task_id is currently running.
-
task_owner(INT task_id) => returns owner of task_id, if running.
-
owns_task(OBJ who,INT task_id) => returns whether who owns task_id (if
running).
-
argstr(verb,args[,argstr] => returns a corrected argstr (see full verb
help).
-
substitute(string,subs) => subs in form {{"target", "sub"}, {...}, ...}.
Building Utilities
$building_utils
-
:make_exit(spec,source,dest[,deek]) => a new exit spec is an exit-spec
as described in `help @dig'
-
:set_names (object, spec) => sets name and aliases for an object
-
:parse_names (spec) => list of {name, aliases}
(In both of these, spec is of the form[[,:],,...]
)
(as described in `help @rename')
-
:recreate(object, newparent) => effectively recycle and recreate object
as a child of newparent
Gender Utilities
$gender_utils
Defines the list of standard genders,
the default pronouns for each,
and routines for adding or setting
pronoun properties on any gendered object.
Properties:
-
.genders -- list of standard genders
-
.pronouns -- list of pronoun properties
-
.ps .po .pp .pq .pr .psc .poc .ppc .pqc .prc -- lists of pronouns for each
of the standard genders
If foo is of gender this.gender[n], then the default pronoun foo.p is
this.p[n] (where p is one of ps/po/pp/pq...)
Verbs:
-
:set(object,newgender) -- changes pronoun properties to match new gender.
-
:add(object[,perms[,owner]]) -- adds pronoun properties to object.
-
:get_pronoun (which,object) -- return pronoun for a given object
-
:get_conj*ugation(verbspec,object) -- return appropriately conjugated verb
Matching Utilities
$match_utils
-
:match(string, object-list) -- Return object in 'object-list' aliased to'string'.
Matches on a wide variety of syntax, including:
-
"5th axe" -- The fifth object matching "axe" in the object list.
-
"where's sai" -- The only object contained in 'where' matching "sai" (possible
$ambiguous_match).
-
"where's second staff" -- The second object contained in "where" matching
"staff".
-
"my third dagger" -- The third object in your inventory matching "dagger"
Ordinal matches are determined according to the match's position in 'object-list'
or,
if a possessive (such as "where" above) is given, then the ordinal
is the nth match
in that object's inventory.
-
:match_nth(string, objlist, n) -- Find the nth object in 'objlist' that
matches 'string'.
-
:match_verb(verbname, object) -- Looks for a command-line style verb named
<verbname> on <object> with current values of prepstr,dobjstr, dobj,
iobjstr, and iobj. If a match is made, the verb is called with @args[3]
as arguments and 1 is returned. Otherwise, 0 is returned.
-
:match_list(string, object_list) -- List of all matches.
-
:parse_ordref(string) - Parses strings referring to an 'nth' object.
returns => {INT n, STR object} where 'n' is the number the ordinal
represents, and 'object' is the rest of the string.
returns => 0 if the given string is not an ordinal reference.
Examples:
:parse_ordref("second broadsword") => {2, "broadsword"}
:parse_ordref("second") => 0
Note that there must be more to the string than the ordinal alone.
-
:parse_possessive_reference(string) -- Parses strings in a possessive format.
returns => {STR whose, STR object} Where 'whose' is the possessor of
'object'.
If the string consists only of a possessive string (ie: "my", or "yduJ's"),
then 'object' will be an empty string. => 0
If the given string is not a possessive reference.
Examples:
:parse_possessive_reference("joe's cat") => {"joe", "cat"}
:parse_possessive_reference("sis's",fish") => {"sis", "fish"}
Strings are returned as a value suitable for a :match routine, thus
'my' becoming 'me'.
:parse_possessive_reference("my dog") => {"me", "dog"}
-
:object_match_failed(object, string[, ambigs]) -- Prints a message if string
does not match object.
Generally used after object is derived from a :match_object(string). [ambigs]
is an optional list of the objects that were matched upon. If given, the
message printed will list the ambiguous among them as choices.
Lock Utilities
$lock_utils
These routines are used when locking objects,
and when testing an object's lock before allowing use
(such as in an exit).
-
:parse_keyexp(string keyexpression, object player) => returns an object
or list for the new key as defined by the keyexpression or a string describing
the error if it failed.
-
:eval_key (LIST|OBJ key, testobject) => returns true if the given testobject
satisfies the key.
-
:unparse_key (LIST|OBJ key) => returns a string describing the key in english/moo-code
terms.
Permissions Utilities
$perm_utils
Miscellaneous routines for permissions checking :
-
:controls(who,what) -- can who write on object what
-
:controls_property(who,what,propname) -- can who write on what.propname
These routines check write flags and also the wizardliness of `who':
-
:apply(permstring,mods) -- used by @chmod to apply changes (e.g., +x) to
a given permissions string
-
:caller() -- returns the first caller in the callers() stack distinct from
`this'
Generic BigList Utilities
This is a package for maintaining huge persistent (sorted) lists in a format
that is less likely to spam the server (which runs into a certain amount
of trouble dealing with long ordinary lists --- btw we use `biglist' to
refer to the huge data structure we're about to describe and `list' to
refer to ordinary MOO lists {...}). The biglist in question lives on a
particular object, to which we will refer in the discussion below as the
`home' object, and its various elements appear as leaves of a tree whose
nodes are kept in properties of the home object. It should be noted that
the home object does not need to be (and in fact should *not* be) a descendant
of this one; this object merely provides utilities for manipulating the
properties on the home object that are used in a particular biglist manipulation.
All of the utilities below refer to `caller' to locate the home object.
Thus verbs to manipulate a given biglist must be located on or inherited
by its home object itself. The home object needs to define the following
verbs
-
:_make(@args) => new property on home object with value args
-
:_kill(prop) delete a given property that was created by :_make
-
:_get(prop) => home.prop
-
:_put(prop,@args) set home.prop = args
-
:_ord(element) given something that is of the form of a biglist element
return the corresponding ordinal (for sorting purposes). If you never intend
to use :find_ord, then this can be a routine that always returns 0 or some
other random value.
See Generic Biglist Resident or $big_mail_recipient for examples.
Those of the following routines that take a biglist argument are expecting
either {} (empty biglist) or some biglist returned by one of the other
routines.
-
:length(biglist) => length(biglist) (i.e., number of elements)
-
:find_nth(biglist,n) => biglist[n]
-
:find_ord(biglist,k,comp) => n where n is the largest such that home:(comp)(k,home:_ord(biglist[n]))
is false, or the smallest such that home:(comp)(k,home:_ord(biglist[n+1]))
is true. Always returns a value between 0 and length(biglist) inclusive.
This assumes biglist to be sorted in order of increasing :_ord values with
respect to home:(comp)(). Standard situation is :_ord returns a number
and comp is a < verb.
-
:start(biglist,s,e) => {biglist[s..?],@handle} or {}
-
:next(@handle) => {biglist[?+1..??],@newhandle} or {}
These two are used for iterating over a range of elements of a biglist
The canonical incantation for doing...
for elt in (biglist[first..last]) ... endfor is handle = :start(biglist,first,last);
while(handle) for elt in (handle[1]) ... endfor handle = :next(@listdelete(handle,1));
endwhile
The following all destructively modify their biglist argument(s) L (and
M).
-
:set_nth(L,n,value) => L[n] = value replaces the indicated element
-
:insert_before(L,M,n) => {@L[1..n-1],@M,@L[n..length(L)]}
-
:insert_after (L,M,n) => {@L[1..n], @M,@L[n+1..length(L)]} takes two distinct
biglists, inserts one into the other at the given point & returns the
resulting consolidated biglist
-
:extract_range(L,m,n) => {{@L[1..m-1],@L[n+1..]}, L[m..n]} breaks the given
biglist into two distinct biglists.
-
:delete_range(L,m,n[,leafkiller]) => {@L[1..m-1],@L[n+1..]}
-
:keep_range (L,m,n[,leafkiller]) => L[m..n] like extract_range only we
destroy what we don't want.
-
:insertlast(L,value) => {@L,value} inserts a new element at the end of
biglist. If find_ord is to continue to work properly, it is assumed that
the home:_ord(elt) is greater (comp-wise) than all of the :_ord values
of elements currently in the biglist.
-
:kill(L[,leafkiller]) destroys all nodes used by biglist. Calls home:leafkiller
on each element.
NNTP Utilities
This is the NNTP utility package. See `help $nntp' for more details.
-
:open() - open a network connection to the NNTP server specified by this.host
and this.port.
-
:article (connection,article)
-
:head (connection,article)
-
:body (connection,article)
-
:check_id - checks to see if the argument (a string) is a valid article
indentifier. Article identifiers are one of the following forms:
-- with brackets groupname n -- where groupname is like
alt.pea.pickers and n is an article number groupname:n -- similar
For the first form, the message ID is returned as a string For the other
forms, it returns a list {groupname, n}, where groupname is the string
and n is the number.
-
:nntp_read - read an NNTP body, body being something that ends with a period
on a blank line. expects a connection to read from.
-
:close - quit from the NNTP server and close the passed connection.
-
:fetch_article (article_id)
-
:fetch_body (article_id)
-
:fetch_head (article_id)
This fetches the article referred to by article-id from an NNTP server.
The article-id may be any of the forms accepted by check_id. When fetching
headers or complete articles, it will often be useful to pass the header
of the article to :fixup_headers(), which will attempt to join multiline
headers into single lines.
-
:@update - Update the groups list stored on the NNTP object. This list
is used in determining which groups are valid for registration, and should
be run regularly. This command may take some time to execute.
-
:fixup_headers({header-text})
This function takes the header of an nntp article (as a list of strings)
and joins multiline headers into single lines. It does no cleanup on the
result, so there may be extra spaces in the output, which is a list of
strings. this may break if the first line isn't really a header.
-
:get_connection
$NNTP maintains a list of open, available connections. This verb returns
a connection from that list, and removes the connection from the list of
actives, adding it to a list of in-use connections. The maximum number
of connections is maintained by this.connect_max. If this.connect_max is
0, there is no limit to the number of connections. If no connections are
available, return E_RANGE.
-
:release_connection (connection)
Release_connection frees a connection obtained with get_connection().
It is assumed that any connection requested will eventually be released.
-
:post(newsgroup(s), subject, lines, distributions)
Post an article to news. Newsgroup(s) should either be a string or a
list of strings. Subject should be a string. Lines should be a list of
strings. Distributions should either be a string or a list of strings containing
valid distributions. Returns 0 if successful, otherwise error or error
string. Returns E_PERM if the posting verb is not wizardly or running with
the permissions of someone in $NNTP.posting_ok, or if $NNTP.posting_allowed
is 0.
-
:check_cache - cache maintenance for NNTP. Returns an item if it's in the
cache, {} otherwise. args[1] should be an article reference, args[2] one
of head, body, or article.
-
:reorder_cache - Cache maintenance for NNTP. On a hit, we move the item
to the head of the cache, so future lookups go faster.
-
:expire_cache - Called by the expiry task to remove dusty items from the
cache. Returns the number of items it removed.
-
:fetch_newnews(newsgroups, last-read)
Return a list of message-IDs posted to newsgroups since last-read. Newsgroups
is either a string containing a single newsgroup, or a list of strings.
last-read is a time.
-
:fetch_xhdr(header, messages)
Return a list of headers associated with the article identifier(s) passed.
Header is a valid header line, such as 'subject'. 'message' should either
be a message-id or a list of article identifiers.
Note that since many NNTP servers do not properly implement the XHDR
command (especially those running on a certain proprietary VAX operating
system which Shall Remain Nameless,) this command may be disabled. In that
case, this verb calls a much slower in-db implementation of the XHDR command,
which fetches each article's entire header, then parses out the header
line requested.
-
:xhdr(connection,header,articles)
Perform the actual XHDR command and clean up the results. This generally
shouldn't be called directly, unless you're deliberately bypassing the
fetch_xhdr command for some reason.
-
:time_from_date(date) - Convert an NNTP date to MOO time() format.
-
:debug(debugging-message) - if $nntp.debug is set to something other than
#-1, tell that object our arguments.
-
:@expire - Run the NNTP cache expiry procedure right away. Mostly useful
when the expiration task gets killed somehow.
-
:fake_xhdr(connection,header,articles)
A slow fake xhdr for NNTP servers which do not support (or perhaps properly
implement) the XHDR command.
-
:header_line(prefix, article-head)
Find the header line beginning with the passed prefix. In fact, this
is just an application of $string_utils:find_prefix, with the addition
of checking for prefixes ending in ':'. The additional checking for lines
ending in ':' here is mostly because (though i'm not sure if this is legal,)
it's conceivably possible to be searching for the 'Foo' header in a message
having both 'Foo:' and 'FooBar:' headers. $string_utils:find_prefix would
return $ambiguous_match in this case.
Byte Quota Utilities
$byte_quota_utils
Verbs for user programs:
-
:bi_create -- built-in create() call, takes same args.
-
:get_quota(who) -- just get the raw size_quota property.
-
:display_quota(who) -- prints to player the quota of who. If caller_perms()
controls who, include any secondary characters. Called by @quota.
-
:get_size_quota(who [allchars]) -- return the quota of who, if allchars
flag set, add info from all secondary chars, if caller_perms() permits.
-
:value_bytes(value) -- computes the size of the value.
-
:object_bytes(object) -- computes the size of the object and caches it.
-
:recent_object_bytes(object, days) -- computes and caches the size of object
only if cached value more than days old. Returns cached value.
-
:do_summary(user) -- prints out the results of summarize-one-user.
-
:summarize_one_user(user) -- summarizes and caches space usage for user.
See verb help for details.
Verbs the system calls:
-
:"creation_permitted verb_addition_permitted property_addition_permitted"(who)
-- returns true if who is permitted to build.
-
:initialize_quota(who) -- sets quota for newly created players.
-
:adjust_quota_for_programmer(who) -- empty; might add more quota to newly
@progged player.
-
:enable_create(who) -- sets .ownership_quota to 1.
-
:disable_create(who) -- sets .ownership_quota back to -1000 to prohibit
create().
-
:charge_quota(who, object) -- subtract the size of object from who's quota.
Manipulates the #-unmeasured if what is not currently measured. Called
by $wiz_utils:set_owner.
-
:reimburse_quota(who, object) -- add the size of object to who's quota.
Ditto.
-
:preliminary_reimburse_quota(who, object) -- Because the set_owner is done
*after* an object has been turned into $garbage, ordinary reimbursement
fails. So we use this verb in the $recycler.
-
:set_quota(who, howmuch)
-
:quota_remaining(who)
-
:display_quota_summary -- internal, called by display quota.
The measurement task:
-
:measurement_task() -- runs once every 24 hours measuring stuff, separated
from the scheduling in case you just want to run it once. Calls the body
and then reports via moomail.
-
:schedule_measurement_task() -- actually schedules it. Look here to change
the start time.
-
:measurement_task_body(timeout) -- does the real work, working for no longer
than timeout seconds.
Properties:
-
.task_time_limit -- integer number of seconds indicating for how long it
should run each day.
-
.working -- object indicating the player whom it is either working on now
(or if not running) will pick up working on when it commences tonight.
-
.cycle_days -- integer numbers indicating how long ago an object must have
been measured before it will be remeasured.
-
.repeat_cycle -- boolean. 0 means have a vanilla cycle (goes through all
players() exactly once measuring their objects measured more than .cycle_days
ago). 1 means to have a much more complex algorithm: The first cycle, it
only measures stuff owned by people who have logged in within .cycle_days.
If, in .task_time_limit seconds, it measures all objects not measured in
cycle_days owned by such people, it will run again measuring those objects
which have not been measured in cycle_days - 1, considering people who
have logged in within 4 * cycle_days, repeating until it has used up its
seconds. ("Doing some of tomorrow's work.") Selecting .repeat_cycle = 1
is appropriate only for large MOOs.
-
.exempted -- list of objects to never measure (useful if there are huge
objects). Suggested huge objects include $player_db and $site_db.
-
.measurement_task -- indicates the task_id() of the most recent measurement
task -- used to prevent duplicate invocation.
-
.report_recipients -- recipients of the daily reports. Set to {} to disable
reporting entirely.
Object Quota Utilities
$object_quota_utils
-
:bi_create - Calls built-in create.
-
:charge_quota - Charge args[1] for the quota required to own args[2]
-
:reimburse_quota - Reimburse args[1] for the quota required to own args[2]
-
:set_quota - Set args[1]'s quota to args[2]
-
:can_peek - Is args[1] permitted to examine args[2]'s quota info?
-
:can_touch - Is args[1] permitted to examine args[2]'s quota info?
Wizard Utilities
$wiz_utils
The following functions are substitutes for various server builtins.
Anytime one feel tempted to use one of the expressions on the right,
use the corresponding one on the left instead.
This will take care of various things that the server
(for whatever reason) does not handle.
-
:set_programmer(object) object.programmer = 1; chparent object to $prog
send mail to $prog_log
-
:set_player(object[,nochown]) set_player_flag(object,1); set player flag,
add name/aliases to $player_db, and maybe do a self chown.
-
:unset_player(object[,newowner]) set_player_flag(object,0); unset player
flag, remove name/aliases from $player_db chown to newowner if given
-
:set_owner(object, newowner) object.owner = newowner; change ownership
on object change ownership on all +c properties juggle .ownership_quotas
-
:set_property_owner(object, property, newowner) change owner on a given
property if this is a -c property, we change the owner on all descendants
for which this is also a -c property. Polite protest if property is +c
and newowner != object.owner.
-
:set_property_flags(object, property, flags) change the permissions on
a given property and propagate these to *all descendants*. property ownership
is changed on descendants where necessary.
Network Utilities
$net_utils
-
:parse_address -- Given an email address, return {userid, site}. Valid
addresses are of the form `userid[@site]'. At least for now, if [@site]
is left out, site will be returned as blank. Should be a default address
site, or something, somewhere.
-
:local_domain -- given a site, try to figure out what the `local' domain
is. if site has a @ or a % in it, give up and return E_INVARG. blank site
is returned as is; try this:local_domain(this.localhost) for the answer
you probably want.
-
:open(address, port, [connect-connection-to]) -- Open a network connection
to address/port. If the connect-connection-to is passed, then the connection
will be connected to that object when $login gets ahold of it. If not,
then the connection is just ignored by $login, i.e. not bothered by it
with $welcome_message etc. The object specified by connect-connection-to
has to be a player (though it need not be a $player). Returns the (initial)
connection or an error, as in open_network_connection
-
:sendmail(to, subject, line1, line2, ...) -- Sends mail to internet address
'to', with given subject. It fills in various fields, such as date, from
(from player), etc. The rest of the arguments are remaining lines of the
message, and may begin with additional header fields. (must match RFC822
specification). Requires $network.trust to call (no anonymous mail from
MOO). Returns 0 if successful, or else error condition or string saying
why not.
-
:rawsendmail(to, @lines) -- Sends mail without processing. Returns 0 if
successful, else reason why not.
-
:invalid_email_address(email) -- Checks if email looks like a valid email
address. Return reason why not.
-
:email_will_fail(email-address[, display?]) -- Makes sure the email-address
is one that can actually be used by $network:sendmail().
-
:read For trusted players, they can read from objects they own or open
connections
-
:is_open(object) Returns true if the object is somehow connected, false
otherwise.
-
:incoming_connection Peer at an incoming connection. Decide if it should
be connected to something, return that object. If it should be ignored
(outbound connection), return 1. Called only by #0:do_login_command
-
:return_address_for(player) => string of 'return address'. Currently inbound
mail doesn't work, so this is a bogus address.
-
:server_started -- called when restarting to clean out state.
-
:notify -- for trusted players, they can write to connections
-
:suspend_if_needed -- $command_utils:suspend_if_needed but chowned to player
-
:error(ERN, host, port) interpret open_network_connection(host, port) error
-
:ident_incoming_connection( [, [,]]) -- Attempt
to identify the remote username assoociated with an incoming connection
using the IDENT protocol (RFC 1413). Requires the ability (via $string_utils:connection_port)
to obtain the remote IP port of a given connection from the connection_name.
Returns a username string if successful, E_NACC if it couldn't connect
to an IDENT server on the remote machine, or E_TYPE if there was an error
finding the associated userid (either a reported error from the server
or a protocol error).
Note: This operation can take a while sometimes.. you'll probably want
to fork it.
-
:help_msg -- same as others.
Gopher Utilities
$gopher_utils
An interface to Gopher internet services.
Copyright (c) 1992,1993 Grump,JoeFeedback@LambdaMOO.
This object contains just the raw verbs for getting data from gopher
servers and parsing the results.
-
:get(site, port, selection) Get data from gopher server: returns a list
of strings, or an error if it couldn't connect. Results are cached.
-
:get_now(site, port, selection) Used by $gopher:get. Arguments are the
same: this actually gets the data without checking the cache. (Don't call
this, since the caching is important to reduce lag.)
-
:show_text(who, start, end, site, port, selection) Requires wiz-perms to
call. like who:notify_lines($gopher:get(..node..)[start..end])
-
:clear_cache() Erase the gopher cache.
-
:parse(string) Takes a directory line as returned by $gopher:get, and return
a list {host, port, selector, label} host, port, and selector are what
you send to :get. label is a string, where the first character is the type
code.
-
:type(char) returns the name of the gopher type indicated by the character,
e.g. $gopher:type("I") => "image"
WWW Utilities
$www_utils
-
:genref_obj(object, key[, name]) Generate an HTML reference from an object,
including the authorisation key if appropriate. The tag string for the
reference will be set to 'name' if it is specified, otherwise to the object's
name.
-
:string_to_html(string) Convert a text string to HTML - in other words,
substitute escape codes for "&", "<", ">" and "\"" characters in
the string.
-
:link_objects(line, key) Return a string with all object numbers in 'line'
replaced by references to those objects, including the authorisation key
of appropriate.
-
:note_to_html(text, key) Convert a text note (a list of strings) into HTML.
The text is wrapped in "<pre>" and "</pre>" and string_to_html()
and link_objects() are applied to each line of the text.
-
:generate_redirect(url) Return a MIME header redirecting a web browser
to the URL specified.
-
:www_default(url, key) Perform default actions for accessing an object
via the web. Basically, this means incrementing webhits and returning the
standard MIME header at the moment, but it could involve other actions
in the future.
-
:www_header(key) Generate and return the standard Sprawl web page header.
-
:www_trailer() Generate and return the standard Sprawl web page trailer.
-
:www_move(newLocation, key) If the web user is logged in through the authorisation
system and 'newLocation' is a room, attempt to move the user to that room.
The actual location of the user is returned to allow for checking that
the move succeeded (#-1 is returned for anonymous web users).
-
:www_exits(room, dest, key) Generate an HTML string listing all the exits
to 'room' with links to each. The 'dest' parameter controls the format
of the link descriptions: If dest is 0, each tag is set to the name of
the exit 1, each tag is set to the name of the destination room 2, y'get:
<a href=[URL]>[exitname]</a> (to [dest roomname])
-
:exits2urls(exits, dest, key) Translate a list of exit object numbers to
a list of HTML references. The 'dest' parameter is defined as for 'www_exits'.
-
:listExits(room) Return a list of exits to 'room'. The routine does its
best to find all exits, not just ones returned by the room's 'obvious_exits'
function.
-
:build_htext(key[, title[, body]]) Build and return an HTML page from the
hdesc property of the caller, the page is built with the standard Sprawl
web page header. The 'title' parameter can be a string to be used both
for the page title and page header or a two-element list: {page title,
page header}. If it is omitted, the name of the caller is used instead.
'body' if specified is used to set the page background, text colour and
link colours as defined in NetScape 1.1; the parameter should be a five
element list containing: {background, text colour, link colour, vlink colour,
alink colour}. The background may be either a colour or the URL of an image.
-
:build_description() Build and return a plain text description from the
hdesc property of the caller.
-
:path_to_list(path) Split a URL path into its components as a list.
-
:generate_mime(content_type) Return a MIME header with Content-type as
specified.
-
:http_status(status_code) Translate an HTTP status code to it's text equivalent.
-
:subst_esc(data) Substitute '%' escape codes for '<', '>' and '%'.
-
:subst_hex(data, flag) Substitute actual chars for '%' escape codes, "
" for line breaks. If 'flag' is TRUE, don't treat "%0A" and "%0D" in
isolation as line breaks.
-
:subst_hexand0a(data) As for subst_hex but translate just "%0A" to "".
-
:subst_hex_to_list(data) As for subst_hex but convert to a list at line
breaks."test
WEB Utilities
$web_utils
-
:okay_for_hit(object) -- Returns whether or not the object is valid for
access by the web server. Currently checks if it is a descendent of $html.
-
:error(place)
-
:error(string) -- Returns error in HTML format.
-
:log -- make a log of each hit.
-
:destroy - destroy web session???
-
:oust_brackets -- remove brackets (braces?) from args.
Misc Utilities
$misc_utils
-
:read() -- read one line of text prompting the player for it with Difference
from $command_utils:read is that it allows more flexibility in what form
the prompt takes.
-
:parse_table_options({header,justification,intercolumn-spacing})
-
:parse_table_options(header) -- Does the dirty parsing work for make_table.
parse_table_options({"Name","right"," "}) => {{"Name","----"},"right","
"} parse_table_options("Name") => {{"Name","----"},"left"," "}help #190:make_table
-
:make_table({header,justification,intercolumn-spacing},{stuff to tablify})
-
:make_table(header,{stuff to tablify})
Makes a table of the stuff given. Really handy.
Examples:
:make_table("Name",{"Joe","Jane"},"Age",{"10","15"})
Name Age
---- ---
Joe 10
Jane 15
:make_table({"Name","left"," "},{"Joe","Jane"},{"Age","right"," "},{"10","15"})
Name Age
---- ---
Joe 10
Jane 15
:make_table({"Name","left","| "},
{"Joe","Jane"},{"Age","right"," | "},{"10","15"},{"","left"," |"},{})
| Name | Age |
| ---- | --- |
| Joe | 10 |
| Jane | 15 |
:is_r_prop(object, prop) -- Returns 1 if the prop is readable or 0 otherwise.
:alt_columnize({items}, n [, space, indent, width]) -- Returns a list of
strings of items of n columns. 'width' is the last character that may be
occupied and it defaults to the standard screen width. An alternate use
might be to substitute the player's line-length value. This columnization
differs from that of $string_utils in that if an item is longer than the
column, it is continued on the next line of the column. Line breaks are
found using the value for SPACE (which defaults to a blank space) or, if
there is no space in the line before the end of the column, at the end
of the column. Each continuation of a column is indented with the string
INDENT which defaults to the null string. Items do not wrap around to the
top of the next column.
Net's Wizard Multiple
Utilities FO
-
:update_default_f*eatures udf {this none this} "rxd"
-
:@chownA*ll {any to any} "rxd"
-
:_chown {this none this} "rxd"
-
:_grant {this none this} "rx"
-
:@grantA*ll {any to any} "rxd"
-
:@grantmo*st {any to any} "rd"
-
:@grantobjs {any to any} "rxd"
Quinn's Utilities
$quinn_utils
-
:view_property(OBJ object, STR property) -- an attractive way to view values
-
:is_alphanumeric("character") => true if a character a-z, 0-9
-
:type_name(NUM type) => STR of datatype name. ie: STR => string
-
:in_stack(value, where, [callers_stack]) => index in callers() where found
-
:names_only - Converts a list of objects to a list of names. Simple!
-
:enlist(value) => returns value as a list
-
:match_exact match_object_exactly
-
:social_match(string) => matches on room's occupants, accepting exact matches
on an alias only.
-
:match(string [, obj-list, prop-name]*) ...like the $string_utils verb,
but will return first exact match...
-
:contents(what [, classes-included]) => contents of the given object If
optional args, will only list kids of those objects OLD VERSION! Please
use :class_list(what:contents(), @classes)
-
:seconds_since_midnight ssm
EXAMPLE: :ssm([STR hours_minutes_seconds || STR ctime || NUM time])
Seconds elapsed from 00:00:00 up to given time.
-
:degree_string(NUM percentage[, LIST degree_pairs])
-
:omessage(STR message, OBJ player) => message with all you-pronouns sub'd
with players
-
:eval_sub(STR eval_str[, OBJ object]) => eval_str specially sub'd for frame-evals.
`object' is the object performing the scene, and defaults to `caller'
#rt = random $thing in room #rc = random character/illuminati in
room #rp = random $player in room #t = the caller, or `object' #l = t's
location #p = actual player, as extracted from callers()
-
:map_eval(LIST values, STR eval) => performs an eval on each element of
`values', subbing "%#" with the element. Returns a list of successful results
and E_INVARGs (if an eval failed)
-
:true_eval(LIST values, STR eval) => forms an eval on each element of 'values',
subbing "%#" with the element. Returns all elements whose eval returned
a true value.
-
:verbs(OBJ what[, NUM no-E_PERMS]) => returns all verbs on `what' if second
`dummy' arg is given, unreadable verbs won't be included
-
:class_list(LIST list [, classes-included]) => The given list with all
non-kids of args[2..] removed.
-
:graph({headers}, {data} [, sort_column, {max_lengths}, center_data, {title,
footer, center_titles, space_titles}, linelen]) => a graph of given data
---- Explanation of Args
- headers : list of strings; the subject of each column - data
: list of lists; each a row of data ( all of the following arguments are
optional) - sort_column : number; the column on which to sort the graph
- max_lengths : list of numbers, each the maximum width of a column - centre_data
: number; true if you'd like the main graph centered - border_info : a
list of the following elements: : title -- string; text prepended to body
of graph : footer -- string; text appended to body of graph : center_titles
-- number; true means center title/footer : space_titles -- string; text
between title/footer & graph - linelen : number; linelength to use
for the width of graph
-
:to_percent(NUM cur[, NUM max]) => percent of cur/max If max is Zero, just
return cur.
-
:match_failed(object, string[, whatisit]) Prints a message if string does
not match object.
-
:verb_heritage(OBJ object, STR verbname) Returns a list of ancestors on
which the verb is defined.
-
:fans groupies
EXAMPLE: :fans(OBJ who) => List of players owning kids of who's
objects.
-
:cutl(value, num) => First `num' elements/characters of `val'.
-
:cutr(value, num) => Last `num' elements/characters of `val'.
-
:unroll(LIST list_of_lists) => LIST of all lists in given list `unrolled'
-
:random_word(NUM length)
Generate a random word of `length' characters. Alternates vowels and
consonants, for maximum pronounceability. Derived from $wiz_utils:random_password().
-
:hor*izontal_merge merge
EXAMPLE:
:merge([STR divider,]list, list, ...)
Places each list of strings beside the other, a split screen view. Spacing
between columns is determined by the divider argument.
-
:longest shortest - longest/shortest(value, value, value, ...)
Returns either the longest or the shortest value.
-
:sum(LIST numbers) => total of all elements in `numbers' added together
-
:assoc_array iassoc_array
-
:assoc_array(targ,list[,indx, indx, indx]) returns the first element of
`list' whose own indicated nested element contains target. Index defaults
to 1.
For example...
assoc_array("foo", {biglist}, 2, 3, 1) would search through all
elements of biglist[2][3][1] for the string "foo"
-
:time ctime english_time
-
:location(thing, [object_class]) => Finds the first child of `object_class'
which contains `thing'.
-
:english_encrypt(string[, casematters]) => Changes given string into a
syntactically similiar string, with consonants and vowels sub'd with same.
If `casematters', then capitalise returned text same as given. Default
ignores case.
-
:equal(set1, set2) => True if the two lists given contain the same elements.
-
:regexp_sub(STR match_string[, what]) -- subs the following #n -- what's
name #a -- what's aliases (`what' defaults to player)
-
:spoken(STR text) => 0 if text is not in the syntax of something being
spoken, else return said text.
-
:owned_by_class(player, {include}[, {exclude}])
-
:exclusive_list(objlist, {include-classes}[, {exclude-classes}])
Returns objlist (which should be a list of objects) stripped of all
objects not descended from `include_classes' or descended from `exclude_classes'.
-
:substitute(string, match-result)
As the primitive, but fixes any fudged results in the subs-element of
match-result. If the result is empty, return E_INVARG.
-
:byte_str*ing
-
:size_string(NUM bytes[, NUM places_past_decimal_point]) => Size in bytes,
kilobytes, megabytes, or gigabytes.
Does not round numbers as well as it should, but blame that on 9.
-
:literal_object(string) - As the verb on $string_utils, but allows friendly
parsing of cmd-line references to $local.
-
:parse_byteref(string) => NUM bytes referred to.
Eg: 10 Mb => 10000000 8k => 8000 100Gb => $maxint
-
:db_share(player) => Total Bytes used as record by .object_size.
-
:circular_add(circumference, @numbers)
Examples:
:circular_add(12, 5, 10) => 3 :circular_add(12, 5, 28) => 9 :circular_add(12,
5, 7) => 12 :circular_add(12, 12, -25) => 11
-
:emoted(string)
Returns true if the string is prepended by player's name or title and
followed by some meaningful (non-whitespace) text. $room:emote uses name
alone, so it should catch most instances. No checkng if player is the actual
player, mind you. Do your own security.
-
:chop(string, size) -> list Chop the given string up into 'size'-length
elements of a single list.
-
:name_and_number_list nn_list names_of
EXAMPLE: :name_and_number_list(object|list-of-objects[, @english-list-args])
-
:linesplit(line,len[,indent|spaces]) => List of substrings of line.
-
:abbreviated_time abbr_time
EXAMPLE: :abbr_time(NUM seconds) -> String such as 8s, 4m, 3h.
-
:args_with_quotes(cmdline_args) -> Return the arglist with argstr quotes
intact.
-
:same_type(list|object, type*) -> True if all elements of LIST are of the
given type(s).
-
:map_eval_suspended(LIST values, STR eval[, NUM interval]) -> See 'map_eval'.
'interval' is how many seconds to suspend.
-
:true_eval_suspended(LIST values, STR eval[, NUM interval]) -> See 'true_eval'.
'interval' is how many seconds to suspend.
-
:pluralize(STR singular-noun[, NUM quantity]) -> The plural version of
the given noun (if quantity merits a plural).
-
:verb_name(string) -> Namespec suitable as a verb_info() arg. EXAMPLE:
"v*erb method prog*ram" -> "verb"
-
:from_english_list ->
-
:from_english_list(string) -> Return the original list of strings, sans
commas and conjunctions. (Will take extra args same as $english_list when
I figger 'em out)
-
:unbreak(list) -> Attempt to fix the given list of strings so that one
string is one paragraph. Either an indention, or an unindented line preceding
an indention, are considered beginnings of paragraphs.
-
:names_from_header_list(string) -> Take the english list string of names
and object numbers in a standard mail message header and return them as
a list of names.
-
:short* -> This version returns the shortest names for each recipient,
crushing Petition, Ballot, etc.
-
:short_mail_name(string|object) -> Return a shorted version of the given
mail recipient('s) name, crushing Petition, Ballot, and Dispute appropriately.
-
:numbers_from_header_list(string) -> Take the english list string of names
and object numbers in a standard mail message header and return the objects
it specifies.
-
:format([linelen, ]string[, @items])
linelen -- Maximum length of final string. string -- Tokenized
string to format. items -- Items matching tokens in string.
Each token should be of the format "%", whereis the
number of spaces to left justify (or right justify, if negative) an 'item'
in the argument list. For example, an adjusted iteration of the following
line could be used to print test scores in a pretty format:
-
:format("%-3 %18 %-3%", 1, "Quinn", 98) -> " 1 Quinn 98%"
-
:help_msg -> help_msg is the verb that sets up the help you are reading
now.
Mickey's Utilities
A package of operations for using special operators to produce formatted
output. The following operators deal with plurals. If n is 1, the singular
column is used. If it is some other number, the plural column is used.
If n is not a number, length(n) is used.
==============================================
operator singular plural
==============================================
%s s
%this, %these this these
%that, %those that those
%is, %are is are
%was, %were was were
%has, %have has have
==============================================
The following ops deal with misc objects:
-
%n -- An object by name.
-
%nn -- An object by name and number.
These should probably go through write_self but presently do not. The
following ops deal with numbers:
-
%some -- Output "no" if n is 0; otherwise output
The following ops deal with lists:
-
%items -- Output items using $string_utils:english_list. If the items are
objects, they are processed instead.
-
%maybeitems -- Output "." if no items. Output ": " ++
"." otherwise.
If an op is not found, caller:(op) is tried with an argument of the
data. It should return a string or a list of strings. Ops are case-sensitive.
If you use %N or %Is or whatever, you'll get an initial capital in the
words that get used. If you use %n or %is or whatever the natural case
of the item will be used. Generally, you should use an uppercase op when
at the start of the sentence--as in "%Are %items ok?"
-
:write(who,datum1,datum2,...)
'who' may be a player or list of players. A :tell_lines() will be done
to those players. Each datum may be:
string -- to output datum as a string. object -- to output object:write_self()
if there is such a verb, or object.name otherwise. list -- to output specially,
see below. other -- to output tostr(object).
A list datum has the form {op, datum}.";
Examples:
:write(me,\"There \",{\"%are\",n},\" \",n,\"frob\",{\"%s\",n},\".\")";
-
if n is 1: There is 1 frob.";
-
if n is 2: There are 2 frobs.";
:write (me,\"There \",{\"%are\",n},\" \",{\"%some\",n},\"frob\",{\"%s\",n},\".\")"
-
if n is 0 or {}: There are no frobs.
-
if n is 1 or {4}: There is one frob.
-
if n is 2 or {4,5}: There are two frobs.
:write(me,"There ",{"%are",n}," ",{"%some",n},"frob",{"%s",n},{"%maybeitems",n})
-
if n is {}: There are no frobs.";
-
if n is {4}: There is one frob: 4.";
-
if n is {4,5}: There are two frobs: 4 and 5.";
-
:_write{this none this} "rxd"
-
:tonum{this none this} "rxd"
-
:parse_format_string{this none this} "rxd"
-
:parse_format_op{this none this} "rxd"
-
:format{this none this} "rxd"
EXAMPLE: :format(who,string,thing1,thing2,...)";
Finds the %xxx's in string and associates them with the corresponding
things that :write would want.
EXAMPLE: :format(me, "There %are %some foo%s%maybeitems", x,x,x,x)
-
if x is {}: There are no foos.";
-
if x is {"alpha"}: There is one foo: alpha.";
-
if x is {"alpha","beta"}: There are two foos: alpha and beta.";
-
:verify_user{this none this} "rxd"
-
:get_name{this none this} "rxd"
EXAMPLE: :get_name(object[,a/an?]) Returns the name of object,
which may be any kind of thing.
-
:format_string {this none this} "rxd"
-
:format_action {this none this} "rxd"
Regular Expresions
Regular expression matching allows you to test whether a string fits
into a specific syntactic shape. You can also search a string for a substring
that fits a pattern.
A regular expression describes a set of strings. The simplest case is
one that describes a particular string; for example, the string `foo' when
regarded as a regular expression matches `foo' and nothing else. Nontrivial
regular expressions use certain special constructs so that they can match
more than one string. For example, the regular expression `foo%|bar' matches
either the string `foo' or the string `bar'; the regular expression `c[ad]*r'
matches any of the strings `cr', `car', `cdr', `caar', `cadddar' and all
other such strings with any number of `a''s and `d''s.
Regular expressions have a syntax in which a few characters are special
constructs and the rest are ordinary. An ordinary character is a simple
regular expression that matches that character and nothing else. The special
characters are `$', `^', `.', `*', `+', `?', `[', `]' and `%'. Any other
character appearing in a regular expression is ordinary, unless a `%' precedes
it.
For example, `f' is not a special character, so it is ordinary, and
therefore `f' is a regular expression that matches the string `f' and no
other string. (It does not, for example, match the string `ff'.) Likewise,
`o' is a regular expression that matches only `o'.
Back Up To Menu...
Any two regular expressions a and b can be concatenated. The result
is a regular expression which matches a string if a matches some amount
of the beginning of that string and b matches the rest of the string.
As a simple example, we can concatenate the regular expressions `f'
and `o' to get the regular expression `fo', which matches only the string
`fo'. Still trivial.
The following are the characters and character sequences that have special
meaning within regular expressions. Any character not mentioned here is
not special; it stands for exactly itself for the purposes of searching
and matching.
-
`.'
is a special character that matches any single character. Using concatenation,
we can make regular expressions like `a.b', which matches any three-character
string that begins with `a' and ends with `b'.
-
`*'
is not a construct by itself; it is a suffix that means that the preceding
regular expression is to be repeated as many times as possible. In `fo*',
the `*' applies to the `o', so `fo*' matches `f' followed by any number
of `o''s. The case of zero `o''s is allowed: `fo*' does match `f'. `*'
always applies to the smallest possible preceding expression. Thus, `fo*'
has a repeating `o', not a repeating `fo'. The matcher processes a `*'
construct by matching, immediately, as many repetitions as can be found.
Then it continues with the rest of the pattern. If that fails, it backtracks,
discarding some of the matches of the `*''d construct in case that makes
it possible to match the rest of the pattern. For example, matching `c[ad]*ar'
against the string `caddaar', the `[ad]*' first matches `addaa', but this
does not allow the next `a' in the pattern to match. So the last of the
matches of `[ad]' is undone and the following `a' is tried again. Now it
succeeds.
Back Up To Menu...
-
`+'
`+' is like `*' except that at least one match for the preceding pattern
is required for `+'. Thus, `c[ad]+r' does not match `cr' but does match
anything else that `c[ad]*r' would match.
-
`?'
`?' is like `*' except that it allows either zero or one match for the
preceding pattern. Thus, `c[ad]?r' matches `cr' or `car' or `cdr', and
nothing else.
-
`[ ... ]'
`[' begins a character set, which is terminated by a `]'. In the simplest
case, the characters between the two brackets form the set. Thus, `[ad]'
matches either `a' or `d', and `[ad]*' matches any string of `a''s and
`d''s (including the empty string), from which it follows that `c[ad]*r'
matches `car', etc. Character ranges can also be included in a character
set, by writing two characters with a `-' between them. Thus, `[a-z]' matches
any lower-case letter. Ranges may be intermixed freely with individual
characters, as in `[a-z$%.]', which matches any lower case letter or `$',
`%' or period. Note that the usual special characters are not special any
more inside a character set. A completely different set of special characters
exists inside character sets: `]', `-' and `^'. To include a `]' in a character
set, you must make it the first character. For example, `[]a]' matches
`]' or `a'. To include a `-', you must use it in a context where it cannot
possibly indicate a range: that is, as the first character, or immediately
after a range.
Back Up To Menu...
-
`[^ ... ]'
`[^' begins a complement character set, which matches any character
except the ones specified. Thus,
-
`[^a-z0-9A-Z]'
matches all characters except letters and digits. `^' is not special
in a character set unless it is the first character. The character following
the `^' is treated as if it were first (it may be a `-' or a `]').
-
`^'
is a special character that matches the empty string -- but only if
at the beginning of the string being matched. Otherwise it fails to match
anything. Thus, `^foo' matches a `foo' which occurs at the beginning of
the string.
-
`$'
is similar to `^' but matches only at the end of the string. Thus, `xx*$'
matches a string of one or more `x''s at the end of the string.
-
'%'
has two functions: it quotes the above special characters (including
`%'), and it introduces additional special constructs. Because `%' quotes
special characters, `%$' is a regular expression that matches only `$'.
Back Up To Menu...
-
`%['
is a regular expression that matches only `[', and so on. For the most
part, `%' followed by any character matches only that character. However,
there are several exceptions: characters that, when preceded by `%', are
special constructs. Such characters are always ordinary when encountered
on their own. No new special characters will ever be defined. All extensions
to the regular expression syntax are made by defining new two-character
constructs that begin with `%'.
-
`%|'
specifies an alternative. Two regular expressions a and b with `%|'
in between form an expression that matches anything that either a or b
will match. Thus, `foo%|bar' matches either `foo' or `bar' but no other
string.
-
`%|'
applies to the largest possible surrounding expressions. Only a surrounding
`%( ... %)' grouping can limit the grouping power of `%|'. Full backtracking
capability exists for when multiple `%|''s are used.
Back Up To Menu...
-
`%( ... %)'
is a grouping construct that serves three purposes:
1.To enclose a set of `%|' alternatives for other operations. Thus,
`%(foo%|bar%)x' matches either `foox' or `barx'.
2.To enclose a complicated expression for a following `*', `+', or `?'
to operate on. Thus, `ba%(na%)*' matches `bananana', etc., with any number
of `na''s, including none.
3.To mark a matched substring for future reference. This last application
is not a consequence of the idea of a parenthetical grouping; it is a separate
feature that happens to be assigned as a second meaning to the same `%(
... %)' construct because there is no conflict in practice between the
two meanings.
Here is an explanation of this feature:
-
`%digit'
After the end of a `%( ... %)' construct, the matcher remembers the
beginning and end of the text matched by that construct. Then, later on
in the regular expression, you can use `%' followed by digit to mean "match
the same text matched by the digit'th `%( ... %)' construct in the pattern."
The `%( ... %)' constructs are numbered in the order that their `%(''s
appear in the pattern. The strings matching the first nine `%( ... %)'
constructs appearing in a regular expression are assigned numbers 1 through
9 in order of their beginnings. `%1' through `%9' may be used to refer
to the text matched by the corresponding `%( ... %)' construct. For example,
`%(.*%)%1' matches any string that is composed of two identical halves.
The `%(.*%)' matches the first half, which may be anything, but the `%1'
that follows must match the same exact text.
Back Up To Menu...
-
`%b'
matches the empty string, but only if it is at the beginning or end
of a word. Thus, `%bfoo%b' matches any occurrence of `foo' as a separate
word. `%bball%(s%|%)%b' matches `ball' or `balls' as a separate word. For
the purposes of this construct and the five that follow, a word is defined
to be a sequence of letters and/or digits.
-
`%B'
matches the empty string, provided it is not at the beginning or end
of a word.
-
`%<'
matches the empty string, but only if it is at the beginning of a word.
-
`%>'
matches the empty string, but only if it is at the end of a word.
-
`%w'
matches any word-constituent character (i.e., any letter or digit).
-
'%W'
matches any character that is not a word constituent.
Last Update: February 20, 1999 by Zorro
WEB Page Version by, Bruce Larrabee aka Zorro(bruce_l@efn.org)