<html><head><title>
POO Reference
</title></head><body><center><h1>
POO Programmer's Reference
</h1></center>

<i><b>Purpose</b>: This document is intended for to be the central
repository of information needed by POO users for writing POO functions.

<p>
<b>Status</b>: This document is a work in progress, and rather behind
schedule.  But the information herein is believed to be accurate.
</i>

<ol>
<li><a href="#remarks">General Remarks</a>
<li><a href="#parser">The POO Parser</a>
<li><a href="#classes">POO classes and their methods</a>
	<ol>
	<li><a href="#Func">Func</a>
	<li><a href="#Property">Property</a>
	<li><a href="#Obj">Obj</a>
	<li><a href="#User">User (derived from Obj)</a>
	<li><a href="#Directory">Directory (derived from Obj)</a>
	<li><a href="#CmdDef">CmdDef</a>
	</ol>
<li><a href="#functions">POO global functions</a>
<li><a href="#keywords">POO special keywords & variables</a>
<li><a href="#pythonserv">available standard Python services</a>
<li><a href="#FAQ">POO coding FAQ</a>
</ul>

<hr><h3><a name="remarks">General Remarks</a></h3>

Everything in POO is an object -- places, exits, players, etc.  Each POO
object is internally represented as a Python object (of class
<strong>Obj</strong> or one of its descendants).  However, these are
specially designed objects with some properties not typical of generic
Python objects: 

<p>
<ul>
	<li><strong>Unique Identifiers</strong>: Every POO object has an
"id" property, which is a unique number identifying that object.  All
objects are stored in a global dictionary, gObjlist, by this number.  (A
few important objects are also stored by name, e.g. "thing".)  However,
it is often easier to refer to objects by their <i>logical pathname</i>,
explained under <a href="dirs.html">POO Directories</a>.
<h4></h4>

	<li><strong>Multiple Superinheritance</strong>: Every POO object
has a "parents" property, which is a list of objects from which it is
derived.  Unlike normal inheritance, in POO, objects actually inherit the
<i>values</i> of all the properties of its parent objects, unless
explicitly overridden.  So if an object A has a property p equal to 42
(A.p == 42), and B derives from A but does not have p defined, then
B.p==42.  Inherited properties are always equal unless overridden; if you
set A.p=45, then B.p==45 as well.
</ul>


<p><hr><h2><a name="parser">The POO Parser</a></h2>

Whenever you are interacting with POO, you are connected to a user object. 
This object may be in edit mode (as when editing a function, list, or
tuple), or in command mode (the more usual case).  In command mode, your
input is passed to the POO parser.  If the line you enter begins with '%'
or ';', the rest of the line is treated as plain Python code and executed
as such.  Otherwise, the parser attempts to match your input with some
command.

<p>
Commands are data structures defined on POO objects, indexed by the first
word (usually the verb).
  Each command has a
syntax definition and a function definition.  The parser first searches
your command for object references; these are anything that starts with
'$' or '#', or the name or alias of an object inside the user or the user's
location.  The user and the user's location are added to the list of
objects referenced in the command, to generate the object set.  Each 
object on the object set is searched for commands which might match the
input.  When multiple matches are possible, the POO parser will match
the one which appears more specific (e.g., matching "42" with an "&lt;int&gt;"
syntax tag is considered more specific than matching it with "&lt;str&gt;").

<p>Once the most specific matching command is found, that command is
invoked.  Tagged parts of the input (e.g., "42" tagged as "&lt;int&gt;") are
parsed and passed to the function, as defined in the command structure.

<p>
(More detail on defining commands will be provided soon!)

<p><hr><h3><a name="Func">Class: Func</a></h3>
<center><b>This class implements a POO function.  Objects of this class walk
	like functions, but they are pickleable and do permission checks.
</center></b><p>

POO functions (sometimes called methods) are actually implemented
internally as Python objects.  Each function has three important
properties, and two methods: 

<ul>
	<li><strong>name</strong>: a string defining the function (including arguments)
	<li><strong>source</strong>: a list of strings containing Python code
	<li><strong>desc</strong> (optional): a brief description string
	<li><strong>compile()</strong>: compiles the function
	<li><strong>unbind()</strong>: detaches the method from its POO object instance
</ul>

<P>Functions can be (indeed, must be) object properties, and are inherited
just like any other properties. 


<p><hr><h3><a name="Property">Class: Property</a></h3>
<center><b>
	This class implements a POO property.  These are used instead<br>
	of normal Python attributes to give us full access control.
</center></b><p>

<p><hr><h3><a name="Obj">Class: Obj</a></h3>
<center><b>
	This is the base class of any POO object -- rooms, users, <br>
	widgets, etc.  It implements a 'multiple superinheritance'.
</center></b><p>

All "nouns" (i.e., persons, places, or things) in a POO universe are
derived from the Obj class.  Not surprisingly, Obj is the biggest and
most complex class in the POO hierarchy.  The following methods are
documented for the Obj class.  Methods not documented here are subject
to change without notice, and should not be used in POO code.

<p><table border>
<tr><th colspan=2>Built-In Methods of Class Obj</th></tr>

<tr><th>
Obj.tell(*what)
</th><td>
		put the given string or list of strings in our auditory buffer.
		Terminate with a carriage return.
</td></tr>

<tr><th>
Obj.tell_noCR(*what)
</th><td>
		put the given string or list of strings in our auditory buffer.
		Do not terminate with a carriage return.
</td></tr>

<tr><th>
Obj.getprop(propname)
</th><td>
		return the Prop defined on this object or an ancestor with
		the specified name.
</td></tr>

<tr><th>
Obj.canAddOrDeleteProp(propname)
</th><td>
		return 1 if permHolder can add a property to this object
</td></tr>

<tr><th>
Obj.canWriteProp(propname, useCflag=1)
</th><td>
		return 1 if current permHolder can change the given property.
</td></tr>

<tr><th>
Obj.setParents(parents)
</th><td>
		change parents of this object to the given object or list.
</td></tr>

<tr><th>
Obj.do_cmd(cmd)
</th><td>
		attempt to execute the given POO command.
</td></tr>

<tr><th>
Obj.proplist()
</th><td>
		return a list of all property names.
</td></tr>

<tr><th>
Obj.isa(what)
</th><td>
		return 1 if <i>what</i> is an ancestor of self.
</td></tr>

<tr><th>
Obj.contents()
</th><td>
		return list of objects contained by self.
</td></tr>

<tr><th>
Obj.getCmdDef(verb, inherit=1 )
</th><td>
		This method returns a (possibly empty) tuple of commands which
		begin with the given verb from this object's command
		dictionary.
</td></tr>


<tr><th>
Obj.setCmdDef(verb, pattern, funcdef )
</th><td>
		This function sets a command definition in the global
		dictionary.
		If the given function call is None or an empty string, the
		command
		will be removed.  If the given pattern matches an existing one
		exactly, the existing one will be replaced.  This function
		requires wiz privs.
</td></tr>

</table>


<p>In addition to these built-in methods, there are some POO methods which
may be invoked by the engine, when they exist.  These can be defined and
overridden from within POO.  These methods are as follows: 

<p><table border>
<tr><th colspan=2>Method Hooks for Class Obj</th></tr>

<tr><th>
update(self)
</th><td>
		This method is called on an Obj if its .wantsUpdates property
		is true (e.g., set to 1).  It is called on every "tick" of
		the simulation clock.  <i>Use with extreme caution</i>, as
		misuse can slow the server down tremendously.
</td></tr>

<tr><th>
hear(self, msg)
</th><td>
		This method, when present, is called when the Obj is told some
		message (via the .tell(*) or .tell_noCR(*) methods) -- in other
		words, whenever the Obj hears something.  It can be used to
		make objects that respond to output.  <i>Use with extreme 
		caution</i>, since an infinite loop may be caused if an
		object responds to its own output (or if two objects respond
		to each other's output).
</td></tr>

<tr><th>
postEdit(self, obj, propname, saved)
</th><td>
		This method is called on when a user completes an editing
		operation (by saving or aborting).  It is passed the object
		on which the edited property was defined, the name of that
		property, and a flag that indicates whether the user saved
		changes.
</td></tr>

</table>

<p>There are also two special methods which are only called on object #0.
These methods are as follows:

<p><table border>
<tr><th colspan=2>Method Hooks for Obj #0</th></tr>

<tr><th>
login(self,who)
</th><td>
		This method is called when a person (identified by
		<tt>who</tt>) connects to
		it over the network (i.e., logs in).
</td></tr>

<tr><th>
logout(self,who)
</th><td>
		This method is called when a person (identified by
		<tt>who</tt>) disconnects (i.e., logs out).
</td></tr>
</table>



<p><hr><h3><a name="User">Class: User (derived from Obj)</a></h3>
<center><b>
	This subclass of Obj defines the class of Users in the game.  <br>
	They have all the properties of other POO objects, but also <br>
	have facilities for being connected via the network.
</center></b><p>

A User is a POO object that is connected to a real person via the
network; in other words, the "characters" of the virtual environment.

<p><table border>
<tr><th colspan=2>Built-In Methods of Class User</th></tr>

<tr><th>
User.connected()
</th><td>
		return 1 if this User is currently logged in.
</td></tr>

<tr><th>
User.startEdit(object,propname,postEdit=None)
</th><td>
		invoke the editor on the named object property.
		If present, postEdit should be a function which will receive
		the object reference, property name, and a "saved" parameter
		which will be 0 if user aborted, 1 if user saved changes.
</td></tr>

<tr><th>
User.enterFunc(object,funcname)
</th><td>
		start the editor on the given function, creating it if it
		does not already exist.
</td></tr>
</table>

<p><hr><h3><a name="Directory">Class: Directory (derived from Obj)</a></h3>
<center><b>
	This subclass of Obj defines the class of Directories in the game.
	These are POO objects which are only used for keeping references to
	other objects.  They have the special characteristic that contents
	are treated like properties; that is, if Directory "foo" contains
	an object called "bar", it can be referred to as "foo.bar".

<p>	Directories are severely restricted, so that they may be freely<br>
	used within a quota system (i.e., they won't take up much memory).
</center></b><p>

<p><hr><h3><a name="CmdDef">Class: CmdDef</a></h3>
<center><b>
	This class implements a pattern-matcher, where the pattern<br>
	is formed of words and tags.  It can compare its pattern<br>
	to a string and if it matches, return a list of words which<br>
	fit in for each tag.
</center></b><p>



<p><hr><h2><a name="functions">POO Global Functions</a></h2>

The following POO-specific functions are available (in immediate mode
or within a function).  Functions usable only by wizards are not shown.

<p><table border>
</td></tr><tr><th>destroy(obj)</th>
	<td>This function recycles the specified object.  Caller must be the
	owner of the object, or a wizard.  Whenever possible, use the @recycle
	command instead of calling this method directly.
</td></tr><tr><th>getObj(x)</th>
	<td>This returns a reference to the object specified by x.  If x is
	an integer, it returns the object whose id==x.  If x is a string
	that starts with "$", the rest of the string is taken as the name
	of a property on object 0 which refers to another object.  If x
	is a string beginning with "#", the rest of the string is converted
	to an integer and used as the object id.  If x=="ALL", then a list
	of all objects in the database is returned.
</td></tr><tr><th>globalkeys()</th>
	<td>This function returns the names of all global variables, functions,
		and datatypes.  Note that the standard Python <tt>globals()</tt>
		function is unavailable within POO for security reasons.
</td></tr><tr><th>help(topic)</th>
	<td>This function returns the help database entry for the given topic.
</td></tr><tr><th>open(filename)</th>
	<td>A restricted version of the <tt>open</tt> function is available.
	It accepts only simple filenames (no relative or absolute pathnames).
	Ask the POO administrator what files are available for reading.
</td></tr><tr><th>show(message, parties, broadcast=1)</th>
	<td>
	This function displays an effect involving several parties.  Each
	of the parties gets a customized message, and the first party's
	location gets a general message to its broadcast function (if any),
	unless the last parameter (broadcast) is 0.

	<p>
			message: string containing key tags,
			         e.g., "%1D %1:(gets) %2i."<br>
			parties: dictionary mapping keys to objects,
			         e.g., {1:caller, 2:dobj}<br>
			broadcast: key of object whose location also gets a message

</td></tr><tr><th>split(str)</th>
	<td>This function splits the given string into a list of tokens,
		treating quoted strings as unitary tokens.
</td></tr><tr><th>tostr(x)</th>
	<td>Converts x into a string; deals intelligently with object, property,
		and function references.
</td></tr><tr><th>users()</th>
	<td>Returns a list of all connected users.

</tr></table>

<hr><h3>Other Object Methods in the Core Database</h3>

The methods below are not built into the POO engine; rather, they are
functions that can be defined on POO objects and that have special
significance in the standard core database.

<p><table border>
<tr><th>description(looker)</th>
	<td>This function is called by the $user.look method (and possibly
		others), to get the description of the object.  The default
		method simply returns the contents of .desc (converting a list
		to a string if necessary).  This may be overridden to generate
		descriptions which vary according to time, objects present, etc.
		Create this function with:<br>
		<tt>@newfunc description(this,looker) on myobject</tt>
		
</td></tr><tr><th>hear(msg)</th>
	<td>This function is called when an object "hears" something in
		the room. Create this function with:
		<tt>@newfunc hear(this,msg) on myobject</tt>

</td></tr><tr><th>update()</th>
	<td>If defined on an object whose .wantsUpdates flag is set to 1,
		then this function is called on every update cycle.  Errors
		are reported to the object's owner.
		<b>CAUTION</b>: use this function sparingly!

</td></tr></table>

<p><hr><h2><a name="keywords">POO special keywords & variables</a></h2>

<P>In addition to any parameters, functions can access POO global 
variables.  An important one is <strong>gCmdLine</strong>, 
a string which contains the command line exactly as typed by the user.
Other globals can be found with the command 
<b><tt>;print globalkeys()</tt></b>.

<p>A few special globals are defined whenever a function is invoked.
These are for your information only; assigning to them has no effect.
The predefined function globals are:
<ul>

<li><b><tt>super</tt></b> -- this is the function which the currently
executing function has overridden (if any).  If you wish to call the
overridden function, simply call <tt>super</tt> with the same arguments
as were passed to the current function (except for <i>self</i>, which
should not be passed).  <tt>super</tt> can only be invoked from bound
methods, not unbound ones.

<li><b><tt>user</tt></b> -- this is the object which is currently
executing a command.

<li><b><tt>caller</tt></b> -- if this function was called from another
function, <tt>caller</tt> is the object to which that other function
was bound.  This is handy for security checks: if you have helper
functions which should only be called from your own code, you could
check for something like "if caller != self".

<li><b><tt>permHolder</tt></b> -- this is the object whose permissions
are currently in effect.  If the function has an owner, it will be that
owner; otherwise, it will be the caller's permHolder.

</ul>



<p><hr><h2><a name="pythonserv">Available Standard Python Services</a></h2>

Certain common standard Python modules are available from within POO.
These include the randint, time, and ctime functions, as well as the
entire string and md5 modules.

<p><hr><h2><a name="FAQ">POO coding FAQ</a></h2>

<b>How do I...</b>

<ul>
<li><h4>give output to the user?</h4>
	Simply use the <tt>print</tt> statement; this always goes to the user.
	Another method is to use <tt>user.tell(...)</tt>.
<h4></h4>

<li><h4>give output to the whole room?</h4>
	<tt>user.location.broadcast("Your message here." )</tt><br>
	If you don't want the caller to also receive the output, use:<br>
	<tt>user.location.broadcast("Your message here.", user )</tt><br>
	(<tt>broadcast</tt> is a function defined on all objects in the core
	database.)
	
	<p>Alternatively, use the <tt>show</tt> function:<br>
	<tt>show( "%1D %1:(bonks) %2i on the head.", {1:user, 2:dobj} )</tt>
	
<h4></h4>

<li><h4>move an object?</h4>
	Unless you're a wizard, you generally can't.  You can invoke the standard
	get/drop or exit.call functions, though; these may serve your purpose. 
	If not, ask a wizard for a function to do what you need.

<h4></h4>

<li><h4>check the class of an object?</h4>
	If you take a parameter and want to make sure it is what you think it
	is, use the standard type() function and the .__class__ property.
	For example, to make sure x is a Directory object, use:	
<pre>	if type(x) != InstanceType or x.__class__ != Directory:
		raise "ParamError", tostr(x) + " is not a Directory"
</pre>
	The object class might also be Obj, User, Func, or Prop.
	<p>
	If you know that x is an Obj (or one of its derivatives, User or 
	Directory), and want to see whether it is descended from some other
	POO object, use the .isa() function.  For example:
<pre>	if x.isa(getObj('$exit')): print "It's an exit all right!"
</pre>

<li><h4>extend an ancestral method?</h4>
	Often, you want to add some behavior to the base object's method,
	but you don't want to incorporate it completely.  For example,
	the standard room's .description(self,looker) method overrides the standard
	object's method, because we want to add a list of room contents.
	But we still want to get the normal description.  This is accomplished
	with the <tt>super</tt> keyword:
<pre>	stddesc = super(looker)		# first, get standard description
</pre>
	Notice that you don't specify <i>self</i> when invoking <tt>super</tt>;
	<tt>super</tt> knows what object it's being invoked from.  However,
	any other arguments which were passed to your function must be
	passed on to <tt>super</tt>.
	
<h4></h4>

</ul>

<p><hr><address>
http://www.strout.net/python/poo/pooref.html
<br>Last Updated:
11/09/97
. . . . . . <a href="http://www.strout.net/">Joe Strout</a>
</address></body></html>