This is docs/design.info, produced by makeinfo version 4.6 from
docs/design.texinfo.

This manual is for MOZ (MOO in Oz) version 1.0.

   Copyright (C) 2002 Robin Lee Powell

     Permission is granted to distribute and modify as long as credit is
     given.  See the file license.txt in the main MOZ distribution for
     full copyright information.
   

File: design.info,  Node: Top,  Next: Requirements,  Up: (dir)



This is the design documentation for MOZ (Moo in OZ). MOO is Mud Object
Oriented.  MUD is Multi-User Dungeon or Dimension.  In general, a MUD is
a multi-user text-based virtual environment.  For information on MUDs in
general, see The MUD Resource Collection (http://www.godlike.com/muds/)
or your local search engine.  For information on MOOs, see The MOO-Cows
FAQ (http://www.moo.mud.org/moo-faq/).

   Oz is a multi-paradigmatic language that happens not to suck.  See
The Main Mozart-Oz Page (http://www.mozart-oz.org/).

   Note that the requirements document is also incorporated herein, and
that this document is changing in response to actual code decisions, and
hence is not strictly a design document.  Oh well.

* Menu:

* Requirements::	An informal requirements specification.
			Normally this would be a seperate document, but
			I wanted to be able to refer back to the
			requirements as appropriate.

* Security Overview::	MOZ uses capability security, which flies in the
			face of what most people think they know about
			security issues, especially people used to MOOs,
			even though the concepts are quite intuitive.  A
			basic description is given here, with URLs to
			longer explications.

			This section is first because otherwise the
			reader is likely to get confused later.

* One-Instance Classes::  There are a number of classes that are
			instantiated exactly once per MOZ server.  They
			are listed here, along with brief notes as to
			the sort of information they store.

* Ex-DB Design::	MOZ doesn't have much in the way of ex-db code,
			unless you count the Oz language itself.
			What it does have is detailed here.

* Class Definitions::	Description of the core classes.

* Storage Issues::	The Storage class is a one-instance class, and
			is complicated and important enough to deserve
			its own section.

* MOZ Records::		The Oz record type is used in the MOZ code
			fairly frequently.  In some cases the format of
			those records is quite important, and needs to be
			understood to write new classes.  Those records
			are discussed in detail here.

* Security In Detail::	Security in MOZ is capability-based, and hence
			rather different than every other MUD I'm aware
			of.  Please try to forget everything you know
			about security before reading this section.

* Unsorted::		Point-form notes that haven't been fully fleshed
			out.


File: design.info,  Node: Requirements,  Next: Security Overview,  Prev: Top,  Up: Top

Requirements
************

An informal requirements set for Moo in OZ.  Note that these are in no
particular order.  They are anchored for reference in those parts of the
design document that relate to them.

  1.  multiple muds can be joined together transparently

  2.  ability to make as many changes on the fly as possible

  3.  maximum simplicity for building and coding

  4.  not too slow or too memory-hoggy

  5.  number of connections limited only by physical issues (bandwidth,
     memory, etc)

  6.  robust access control, within the MOZ, of objects, of internal
     code, of objects characteristics, of processes, etc.

  7.  ability to handle various (spoken) languages

  8.  high potentiol for user enjoyment

  9.  fault tolerance

 10.  ease of debugging

 11.  user can see general information, including class code, about
     objects in the MOZ

 12.  ease of testing

 13.  ease of modification on the part of new admin, programmers, and
     builders



File: design.info,  Node: Security Overview,  Next: One-Instance Classes,  Prev: Requirements,  Up: Top

Security Overview
*****************

Capability security is a security model that is most likely entirely
different than what you're used to.  It is simple and elegant and fast.
The main drawbacks are that it has the potential to make it much easier
for users to do incredibly stupid things, but that really depends on how
the system is set up, and that it is very hard to bootstrap.  The latter
is solved by persistence, see *Note Persistence::.  The former is solved
in MOZ by simply not allowing the transfer of capabilities that are
innapropriate.

   OK, time to step back a bit and explain more about capability
security as a concept.  The type of security that you are most probably
used to I'm going to call ACL (Access Control List) security.  The way
this basically works is that if you want to, say, open a file, somewhere
buried in the operating system is a test that compares your user name to
a list of people allowed to open the file.  Or if you're in a MUD and
want to pick up an object, same thing: somewhere an if statement tests
if you should be allowed to do that.

   The basic idea with ACLs is that you can always find what it is that
you want to access.  File trees have ways to get listings of all the
file names, which you can then pass to an open command of some kind.
Rooms have a list of all the objects in them, which you can then pass
to a get command of some kind.

   Capability security is completely different.  Capability security is
based on the idea of a key to a vault: you either have the key, or you
don't.  If you don't have the key, you can't open the vault (at least,
not without a whole lot of time and effort; good cryptography, which MOZ
as of this writing only sort of uses, can make the time involved into
the trillions of years).

   Better still, in most cases in a capability system you can't even
_see_ the vault (again, without a lot of time and effort and access to
the data in some kind of raw form, such as access to the disk itself).
If you can't point to the vault or see it or touch it, it's ridiculous
to talk about opening it: you don't have the _capability_ to do so at
all (hence the name of this type of security).

   Basically, a capability is a reference to some kind of operation on
an object (i.e. generally it's a reference to a procedure).  If you
don't have the capability, and you can't forge the capability (because
you can't see the object it's acting or you can't guess the capability's
name/secret/key/whatever), then you can't access that aspect of the
object.

   Note that the key analogy holds in other ways: you can copy
capabilities, and you can give them to other objects.  This is what
leads to the first drawback mentioned above: players can quite easily
"give away the homeworld" Babylon 5 Quotes
(http://www.keri.paintedhippo.com/quotepage.html#b5).

   Some effort is made to make this difficult (note that requiring
actual Oz programming to transfer a capability is considered
'difficult'), but it's part of the nature of the system that this
cannot be stopped.

   On the other hand, capabilities can be revoked.  In fact, being able
to tell an object to revoke a capability is, itself, a capability in
MOZ!

   Which leads to one of the other nice things about capabilities:
they're arbitrarily extendable.  You want to make another one, you just
program it in and pass it on.  Quite trivial, whereas, in general,
ACL-based systems require reworking of at least some of the system code
to add a new ACL.

   Furthermore, you can pass around a procedure that has a capability
inside it that it will only use once.  Since procedures can't be opened
up or de-compiled in Oz, this is quite safe.

   An important aspect of capabilities is that, unlike ACL systems, an
object can, by default, do _nothing_.  At least, nothing that involves
other objects.  This is very important: hacks of ACL systems often
revolve around tricking the ACL into not activating, or believing a
user is someone they're not, or something.  This simply isn't possible
in a capability system: there's nothing to trick.  To even _ask_ for a
capability you don't have requires a capability!  This motivates the
next section, which defines an initial set of capabilities.

   For more information, see The Three Parts of Security
(http://www.erights.org/elib/capability/3parts.html), Introduction To
Capability Based Security
(http://www.skyhunter.com/marcs/capabilityIntro/index.html), and An Ode
to the Granovetter Diagram
(http://www.erights.org/elib/capability/ode/index.html).

   Note that almost all security in MOZ, is done from an in-language,
in-db perspective.  Some aspects of the security rely on ex-DB code (the
ActiveObject wrapper in particular), but these are the exception rather
than the rule.

   If it's important enough to you to break into a MOZ that you start
eavesdropping transmissions between MOZs to figure out how Oz encodes
its name information, you're welcome to hack the thing as far as I'm
concerned.  Go get laid or something, you're a loser.


File: design.info,  Node: One-Instance Classes,  Next: Ex-DB Design,  Prev: Security Overview,  Up: Top

One-Instance Classes
********************

There are a number of classes which are instantiated exactly once per
server, i.e. there is exactly one object of each of these classes on
each server.  These objects are used to store and manage server-wide
persistent values.  For example, the Storage object keeps track of all
the files that are used to store objects to disk.

   Because of this, I will often refer to the class and the object
interchangeably; the Storage class and the Storage object are largely
the same thing in practice, as there is only ever one Storage object
made from the Storage class.

   The one-instance classes are listed below, along with a brief
description of the types of data they store.

`The Storage Object'
     The Storage object stores information about the disk files used to
     store objects and classes.  It stores associations between Oz
     names and file numbers and object wrappers and other data.  *Note
     Storage Issues::

`The Server Object'
     The Server object stores a list of players and their associated
     passwords.

`The LanguageStrings Object'
     The LanguageStrings objects stores localized strings for
     everything that the core system classes need to output to the
     user.  This is so that people wishing to localize MOZ to a new
     language don't need to go looking for strings all over the place.

`The Help Object'
     The Help object stores all the basic help information of the MOZ.


File: design.info,  Node: Ex-DB Design,  Next: Class Definitions,  Prev: One-Instance Classes,  Up: Top

Ex-DB Design
************

The phrase "Ex-DB" refers to the idea that in MUD code, anything you can
change from within the MUD, without having to reset it or something, is
"In-DB", as in "in the database".  By extension, anything that you
cannot change from within the MUD is "Ex-DB", or "out of the database".

   MOZ is very different from other MUDs.  The server, as such, is
nearly non-existent; it's just a tiny bootstrap module (*note
R2::,*note R7::), plus a few accessory modules. This is because all
things in Oz, including classes and objects, are first-class values.
Even the the class of an object can be changed on the fly.

* Menu:

* The moz Program::	The operations performed by the actual moz
			binary are detailed here.

* The new_moz Program::	The operations performed by the new_moz
			binary are detailed here.

* The Parsing Module::	Describes an accessory module used for arbitrary
			string parsing.

* The EnhancedString Module::
			Describes an accessory module used for simple
			string processing (but less simple than the
			built-in String module).

* The Active Object Wrapper::
			Objects in MOZ are 'active'.  That is, there is
			a single thread for each object that deals with
			all aspects of that object.  This section
			discusses details of the design of the active
			object wrapper that implements that behaviour.

			It is very unlikely that any modifications to
			this code will be necessary.  Any modifications
			to this code are likely to break
			_everything_.

* The MozCompilation Module::
			Describes an accessory module used for easier
			access to the Oz compilation process

			It is very unlikely that any modifications to
			this code will be necessary.  Any modifications
			to this code are likely to break
			_everything_.

* Object References::   Dealing with the active object wrapper
			directly is difficult, due to having to keep
			track of a seperate list of capabilities, so
			we wrap it in an Oz object.


File: design.info,  Node: The moz Program,  Next: The new_moz Program,  Up: Ex-DB Design

The moz Program
===============

The main program binary, moz, performs the following functions:

  1. Compiles MozBase.class using MozCompilation

  2. Compiles Storage.class using MozCompilation

  3. Creates a new, empty Storage object by hand

  4. Uses Storage to load itself into itself

  5. Starts the Storage object

  6. Asks the Storage object where to find the Server object (i.e. what
     the Server object's file number is).

  7. Tells storage to load the server object

  8. Starts the Server object

  9. Holds until the server is shut down

 10. Ask Storage to write everything to disk

 11. Writes the Storage object to disk by hand.



File: design.info,  Node: The new_moz Program,  Next: The Parsing Module,  Prev: The moz Program,  Up: Ex-DB Design

The new_moz Program
===================

The new_moz program creates a bare, clean, and very boring MOZ instance.
It's just like the moz program except that it creates inital
instantiations of all of the one-instance classes, and it doesn't load
the Storage object from disk.


File: design.info,  Node: The Parsing Module,  Next: The EnhancedString Module,  Prev: The new_moz Program,  Up: Ex-DB Design

The Parsing Module
==================

The Parsing module is a set of monadic parser combinators, which can be
used to parse any CFG in a pretty simple, straight-forward way.  The may
be more expressive than CFGs with a bit of work, I don't know.  The code
is basically a re-write of the code at Monadic Parser Combinators
(http://www.cs.nott.ac.uk/~gmh/bib.html#monparsing), which is a lovely
tutorial on monadic parsing.

   This code will eventually be on MOGUL, when I manage to get around to
it.


File: design.info,  Node: The EnhancedString Module,  Next: The Active Object Wrapper,  Prev: The Parsing Module,  Up: Ex-DB Design

The EnhancedString Module
=========================

This is just a re-packaging of Duchier's MOGUL String Package
(http://www.mozart-oz.org/mogul/info/duchier/string.html), because it's
nice to have the better string handling capabilities around.


File: design.info,  Node: The Active Object Wrapper,  Next: The MozCompilation Module,  Prev: The EnhancedString Module,  Up: Ex-DB Design

The Active Object Wrapper
=========================

The active object wrapper that MOZ uses is one of the more complicated
pieces of code in the MOZ, as well as the piece that may seem oddest to
users of other object oriented langauges. Also, it is the largest piece
of ex-db code.

   The active object wrapper is actually a procedure that is passed an
object. It returns an object record with full capabilities.  An object
record consists of a wrapper procedure, the objects Oz name, and a
capability set.  All the wrapper procedure does is pass its one argument
to a port (an Oz port, _not_ a TCP/IP port).

   It's what's at the other end of that port that's interesting.  A
thread is created to process the stuff passed in the port.  Note that
this means that each object has exactly one thread associated with it,
and this thread is the only one that ever gets to affect the object
directly.  This make things much easier as far as multi-threading issues
go, as no locking needs to be done within object methods.

   This wrapper also gives insultion: no-one ever sees the object
directly except this thread, and this is what allows the capability
security system to work.

   Also, the thread can do other processing besides just calling the
method it has been passed.  The most important part of this processing
is capability processing.  Basically, what's passed to the port is not
the method name, it's a record with an Oz name for a label.  This label
is used to key a dictionary, and if a method name associated with it is
found, that method is called, if not, an error is returned.  For more
information, see *Note Capability Implementation::.

   Another, much cooler, thing that the wrapper thread does is handle
upgrade requests.  upgrade is a virtual method, in that it is called
just like any other method in the wrapper, using an Oz name capability,
but it doesn't exist in the object, rather it exists in the wrapper.  An
upgrade call takes a class name and actually swaps out the object it's
wrapping for one of that class!  It calls `toRecord' and `fromRecord' to
make sure information is preserved, and lets the Storage object know the
new class name.  Then it just goes back to processing the port like
nothing happened, and from the point of view of every other object in
the mud, nothing did!

   There are a couple of other miscellaneous things the wrapper does.
In particular, it inserts capability information into a `toRecord' call
and extracts it from a `fromRecord' call.

   When a new object is created, the capability dictionary is built
using the class's methodList feature, with the addition of the special
capability 'upgrade', and a bunch of new Oz names.  In many cases, these
are then overwritten by a `fromRecord' call.

   The object itself will often need to know about its wrapper and
capabilities, so that it can inform other objects.  This is handled by a
method on every object in the MOZ called activeObjectInform, which takes
those two pieces of information as arguments, generally to store on
attributes.  This method is called every time wrapper information is
changed.

   The Storage object is also informed of this information at the same
time.

   *Note General Class Issues::.


File: design.info,  Node: The MozCompilation Module,  Next: Object References,  Prev: The Active Object Wrapper,  Up: Ex-DB Design

The MozCompilation Module
=========================

The MozCompilation module exports a single procedure, `Compile', which
takes the file name to compile and the environment to compile it under.
If the file contains only an expression, such as a single functor,
that is returned.  The environment is given as a list of 2-tuples.  The
first part of each 2-tuple is an atom representing the variable name
under which that aspect of the environment will be visible in the
compilation.  The second part is the actual value being made so
visible.  Note that if one of the variables passed in to the compilation
is unbound, binding it in the compilation will effectively work as
output.

   If you didn't understand that, that's probably fine; this isn't a
user-servicable part of the code, and I don't really even understand it
myself.


File: design.info,  Node: Object References,  Prev: The MozCompilation Module,  Up: Ex-DB Design

Object References
=================

Dealing with the active object wrapper directly is difficult, due to
having to keep track of a seperate list of capabilities, so we wrap it
in an Oz object.  This wrapping is done, most of the time anyways, by
using the procedure MAKEOBJECTREFERENCE, supplied by ActiveObject.oz.

   For arguments, it takes an ActiveObject wrapper, a record of
capabilities, and the Oz name of the object (more for convenience than
anything else), and returns an object which runs the wrapper but also
implements the methods "wrapper", "capabilities", and "ozName", which
simply return the information passed to them in both the first argument
and the argument with the same label as the method name.


File: design.info,  Node: Class Definitions,  Next: Storage Issues,  Prev: Ex-DB Design,  Up: Top

Class Definitions
*****************

* Menu:

* General Class Issues::	Caveats for class creation, and a list
				of methods that every class should (re-)
				define.
* The Class Hierarchy::		I apologize for the lack of a pretty
				tree.  Deal.
* class MozBase::     		The bottom-level class.
* class Storage::     		The persistent storage class.
* class Server::     		The incoming TCP/IP handling class.
* class Described::		The basic described object.  Has no
				location.  Normally not instantiated.
* class Located::		Basic located object (i.e. has an
				intrinsic location).
* class Mobile::		Basic mobile object (i.e. has an
				intrinsic location that can be changed).
* class Location::		Basic location object (i.e. has
				contents).
* class Player::     		Takes parsed input and calls commands.
* class Wizard::		Just like Player, but with more
				capabilities, and hence some extra
				commands.
* class Puppet::		An automaton version of Player.
* class Container::		Combination of the features of Mobile and
				Location; a thing that can have things
				in it.
* class Exit::			A connector between Locations.  Has no
				location itself.
* class Gate::			Like Exit, but connects locations
				between two MOZs.
* class Terminus::		Like Location, but provides a
				connecting point for a Gate.
* class Connection::     	Handles TCP/IP connections.
* class Parser::     		Parses user input and deals with finding
				the right verbs to pass the user's input
				to.
* class Control::		Used to generate objects used to
				control other objects.
* class ClassControl::		Used to generate objects used to
				create and control new classes.


File: design.info,  Node: General Class Issues,  Next: The Class Hierarchy,  Up: Class Definitions

General Class Issues
====================

The `start' Method
------------------

Every class has a `start' method, which is run at the end of the
process of the object being loaded in by Storage.  Note that this is run
_any_ time the object is loaded, including as a result of upgrade
calls.  Therefore, `start' must not assume, well, _anything_.  For
example, the `start' method on a wandering puppet, that starts its
wandering from room to room, must not assume anything about what room
it starts in.

   Note that any initialization of anything that is not completely
permanent should happen using the `start' method, not the `init' method.

The `init' Method
-----------------

Every class has an `init' method, which is run by Storage as part of
the object creation and wrapping process.  The `init' method, as a
minimum, takes an object record for Storage and LanguageStrings and
takes the object's own Oz name.

   _NOTE_: The `init' method should only be called once for the
_entire_ lifetime of the object.  Anything that is not absolutely
permanent should not be passed to `init'.  Also, an `init' record can
be passed to createObject on Storage, but be aware that Storage will
change the name of the record to `init' and tack on three arguments at
the beginning for the Oz name and the Storage and LanguageStrings
object references.

The `toRecord' Method
---------------------

Every class has a `toRecord' method, which returns a record containing
all the aspects of the object that must be persistent (*note Loading
And Unloading::.  Note that reference to objects _must_ be converted to
their appropriate Oz names before being made part of the record,
because the actual object code cannot be stored on disk.  The names in
question are only used for persistence purposes, and knowing them
should give no privilege(1).

The `fromRecord' Method
-----------------------

Every class has a `fromRecord' method, which takes the output of
`toRecord' and applies the information therein to the object (*note
Loading And Unloading::).  Oz names representing objects are turned
back into object references as part of this process.

`toRecord', `fromRecord', and `exports'
---------------------------------------

The `toRecord' method uses a feature called `exports', which is a list
of 2-tuples of the format Name#Type, where both Name and Type are atoms.
The former is the attribute name to be saved, and the latter is the type
of the attribute.  Note that these types are specific to MOZ, and not Oz
itself.  The Type information is used to determine when special
processing is needed to be able to safely save an attribute to disk.
For example, `toRecord' uses the Type field to look for object
references, which need special processing.

   It is very important that the `export' list contain only the names
of attributes that contain non-stateful data, or else the save will
fail.  Stateful data is data that is specific to a particular invocation
of a running program, such as open file handles.  Oz programmers also
refer to stateful data as 'resources'.

   Simple records, atoms, Oz names, and procedures are all safe.

   Threads, file handles, and any other value that isn't guaranteed to
be persistent, are all unsafe to save.  Any attribute that stores this
form of data either must not be named in the `export' list, or there
must be special code in `toRecord' to deal with that Type, such as
there is for the type called `objectRef', which is for references to
objects.

   There is also an analogous `featExports' list for saving the value
of features.  Since features are write-once values, an object that has a
featExports list should only have fromRecord called on it once.  Any
subsequent calls once the features have been initialized will fail.

Recognized `exports' Types in `toRecord' and `fromRecord'
---------------------------------------------------------

Type values that currently mean somethng: `dict', `objectRefDict',
`notPersistent', and `objectRef'.  Anything else will be treated as in
no way special.  This means if it has non-persistent data, an error
will result.

   The standard `toRecord'/`fromRecord' methods have a Type `objectRef'
that has a fairly specialized format.  These attributes are used to
refer to other objects in the MOZ.  It expects the attribute to which
it refers to be a record with the field names `ozName', `wrapper' and
`capabilities' which point to the Oz name of the object, the active
object wrapper procedure and the capabilities that this object has on
the object being referenced.  The list of capabilities is a list of
methods on the object pointed to by the `objectRef'  that the holder of
the `objectRef' can use.

   Note that this means that an object cannot save persistently
information about an object whose Oz name it cannot retrieve, but this
should not be a limitation in general.

   The Type `notPersistent' is used to pass non-persistent data, such
as the output port for a Player object to send data to the player,
through upgrade calls.  It is not used for `toRecord' calls for data
destined to be writen to disk, as an error will result when trying to
store that type of data (as the concept makes very little sense).

Examples
........

Note that these examples are _not_ valid MOZ code, or even Oz code
really.  They are just intended to give a bit of a visual idea of how
`toRecord', `fromRecord', `exports' and `objectRef'-Type attributes
interact.

   * A simple object: DrinkingGlass173

     To store DrinkingGlass173 to disk when it is not being used, we use
     `toRecord'.  In turn, `toRecord' uses `exports' and the
     `objectRef' Type.  This is what part of the object it might look
     like:

          `exports' list:
              name#string
              description#string
              storageRef#objectRef

     Note that `name' is not a specially recognized attribute in Oz or
     MOZ; it is user-defined, and objects need not have it.  In MOZ,
     most objects do in fact have a `name', but it is not required.

     An `objectRef' is an Oz object itself, wrapping the ActiveObject
     wrapper for easier use. The information it contains consists of
     the wrapper for the object it refers to, the object's ozName, and
     some capabilities on that object, which we will represent like so:

              storageRef:
          	wrapper
          	ozName
          	capabilities: capabilities(
          	    createObject
          	    objectRefFromRecord
          	    getClass
          	    upgradeObject
          	)

     Note that every object that gets save to disk has at least one
     entry in its `exports' list that is of Type `objectRef':
     `storageRef', which is used to allow the object to create other
     objects and load class code and such.

   * A complex object: "Robin's Room"

     To store "Robin's Room" we use the same `toRecord' methed.  This
     is what part of the object it might look like:

          `exports' list:
              name#string
              description#string
              storageRef#objectRef
              contents#objectRefDict
          
              .
              .
              .
          
              Contents: contents(
          	blueChair
          	redChair
          	drinkingGlass173
              )
          
              .
              .
              .
          
              BlueChair: objectRef(
          	wrapper
          	ozName
          	capabilities: capabilities(
          	    getName
          	    getDescription
          	)
              )

`methodList'
------------

Every class has a `methodList' feature that is a list of all the method
names that are used outside the class.  This is used by the active
object wrapper, and is safe since nothing but the active object wrapper
ever talks directly to the object anyways.  Note that the `methodList'
feature _should not_ include upgrade, as this is added in by the active
object wrapper.

   All objects are dynamically upgradeable a la A
dynamically-extensible server
(http://www.mozart-oz.org/documentation/dstutorial/node3.html#label199)(2)

   ---------- Footnotes ----------

   (1) It is possible that the current method of doing `toRecord', in
that it is defined on MozBase, will turn out to be a security hole,
because objects can lie about themselves.  If so, it should be moved
onto ActiveObject.

   (2) Note that this also makes them stationary, which may cause
problems later (although I don't think so) and means that what's
actually being passed around are procedures, not objects.  For more
information, see *Note The Active Object Wrapper::.


File: design.info,  Node: The Class Hierarchy,  Next: class MozBase,  Prev: General Class Issues,  Up: Class Definitions

The Class Hierarchy
===================

This is a basic outline of which classes descend from which other
classes.

   * *Note class MozBase::
          	

        * *Note class Storage:: 	

        * *Note class Server:: 	

        * *Note class Described:: 	
               	

             * *Note class Location:: 	
                    		

                  * *Note class Container::, 		    also a child
                    of *Note class Mobile:: 		

                  * *Note class Player::, 		    also a child of
                    *Note class Mobile:: 		

                  * *Note class Terminus:: 	
               	

             * *Note class Located:: 	
                    		

                  * *Note class Mobile:: 		
                         		

                       * *Note class Container::, 		        also a child
                         of *Note class Location:: 		

                       * *Note class Player::, 			also a child of
                         *Note class Location:: 		
                              			

                            * *Note class Wizard:: 			

                            * *Note class Puppet:: 		
                         		

                       * *Note class Control:: 		

                       * *Note class ClassControl:: 		
                    	
               	

             * *Note class Exit:: 	
                    		

                  * *Note class Gate:: 	
               	
          	

        * *Note class Connection:: 	

        * *Note class Parser::


File: design.info,  Node: class MozBase,  Next: class Storage,  Prev: The Class Hierarchy,  Up: Class Definitions

class MozBase
=============

An extension of BaseObject, and an ancestor of _every_ other class.
MozBase has an 'ozname' feature, and the `init' call initializes
'ozname' to {NewName}, as well as storing a reference to the Storage
class.  MozBase also has a method 'ozname' that returns this name.  All
of the methods listed in *Note General Class Issues:: are first defined
in MozBase.

   MozBase will not usually be directly instantiated.


File: design.info,  Node: class Storage,  Next: class Server,  Prev: class MozBase,  Up: Class Definitions

class Storage
=============

class Storage deals with the saving and loading of classes and objects,
including doing Active Object wrapping (*note The Active Object
Wrapper::).  It also provides support for mapping between file names, Oz
names, and object references (*note Associations::).

   In fact, the Storage class does an awful lot of things.  It passes
initial capabilities to the object and remembers which class each object
belongs to (*note Initial Capabilities::).  It stores capabilitites on
each object for purposes of Wizardry (*note Wizardry::).  It runs the
`start', `init', `toRecord' and `fromRecord' methods on objects and is
usually the only object to do so.


File: design.info,  Node: class Server,  Next: class Described,  Prev: class Storage,  Up: Class Definitions

class Server
============

The Server object just (of which there is only one in each MOZ) sits and
watches the MOZ's TCP/Ip port.  When it recieves a connection, it
instantiates a new object of class Connection and calls the `start'
method on that object.  It also instantiates an object of class Parser.
It then connects both the Connection and Parser objects to the Player
object so that the player's commands can be processed.


File: design.info,  Node: class Described,  Next: class Located,  Prev: class Server,  Up: Class Definitions

class Described
===============

The Described class is not usually instantiated.  It adds name- and
description-related capabilities to MozBase.  It has no location or
contents attributes.


File: design.info,  Node: class Located,  Next: class Mobile,  Prev: class Described,  Up: Class Definitions

class Located
=============

The Located class expands upon the Described class to add location
information, and read-only operations upon that information.


File: design.info,  Node: class Mobile,  Next: class Location,  Prev: class Located,  Up: Class Definitions

class Mobile
============

The Mobile class expands upon the Located class to add write operations
on location information.


File: design.info,  Node: class Location,  Next: class Player,  Prev: class Mobile,  Up: Class Definitions

class Location
==============

The Location class expands upon the Located class to add contents
information, and operations upon that information.


File: design.info,  Node: class Player,  Next: class Wizard,  Prev: class Location,  Up: Class Definitions

class Player
============

The player object holds all the attributes, methods and verbs associated
with being a player of the MOZ.  The Parser object associated with each
player is given full capabilities on the Player object in question.


File: design.info,  Node: class Wizard,  Next: class Puppet,  Prev: class Player,  Up: Class Definitions

class Wizard
============

A Wizard is just a user with more extensive capabilities.  The Wizard
class provides commands to use those capabilities more effectively,
although being of the Wizard class does not give one Wizardly powers,
nor is the converse true.


File: design.info,  Node: class Puppet,  Next: class Container,  Prev: class Wizard,  Up: Class Definitions

class Puppet
============

The Puppet class expands the Player class into a form suitable for use
as an automaton, and includes some basic ability to respond to its
master's commands.


File: design.info,  Node: class Container,  Next: class Exit,  Prev: class Puppet,  Up: Class Definitions

class Container
===============

The Container class is a merging of the Mobile and Location classes,
i.e. a Mobile with contents.


File: design.info,  Node: class Exit,  Next: class Gate,  Prev: class Container,  Up: Class Definitions

class Exit
==========

The Exit class connects two locations.  Each Exit is a one-way pointer
to the `destination'.  An Exit object in a room will respond to verbs
such as 'go' and its own name, and put players through to the
destination location.

   Since it is both an important operation and one that exemplifies a
lot of issues, here's what happens when the player wants to move from
one location to another:

  1. The player's command is parsed and, eventually, a 'go' method (or
     whatever) is called on the exit.

  2. The exit asks the current location to give the player to the
     destination location.  The process goes something like this:

       1. Updates the player object's location information with a given
          argument.

       2. Gives capabilities on the player to the remote location.

       3. Removes the player from itself.

  3. The exit decides if it wants to allow the operation.  This may
     include examining the player's inventory for a key object of some
     kind.

  4. Note, however, that the exit itself does not have the capabilities
     on the player required to do the movement; those belong to the
     location itself.



File: design.info,  Node: class Gate,  Next: class Terminus,  Prev: class Exit,  Up: Class Definitions

class Gate
==========

The Gate class expands on the Exit class with the ability to use an Oz
ticket to connect to a room in another MOZ.  It gets this ticket from a
Terminus class object.

   A Gate must be blessed by a Wizard to be able to connect using
tickets.


File: design.info,  Node: class Terminus,  Next: class Connection,  Prev: class Gate,  Up: Class Definitions

class Terminus
==============

A Terminus class object is just a Location with the added ability to
generate an Oz ticket for itself, to be used by a Gate.

   A Terminus must be blessed by a Wizard to be able to produce tickets.


File: design.info,  Node: class Connection,  Next: class Parser,  Prev: class Terminus,  Up: Class Definitions

class Connection
================

Objects of class Connection have no Active Object wrapping, as they are
created on the fly be the server.

   They accept input solely from a TCP/IP port which they parse _very
lightly_ and pass to the parser object.  By 'parse' I mean, basically,
break into lines.  They also accept streams from the Server object,
which the Server treats as output strings and passes back out the TCP/IP
port.


File: design.info,  Node: class Parser,  Next: class Control,  Prev: class Connection,  Up: Class Definitions

class Parser
============

Objects of class Parser have no Active Object wrapping, as they are
created on the fly by the server.

   There is one Parser per player connection.  It accepts input from the
Connection object, parses it, and goes looking for verbs that match it,
which are then called with the parsed arguments.

   There are, however, situations in which entering new commands should
not be possible.  In particular, situations in which user input is
required to complete a command, such as a yes/no dialog.  For these
occurences, a procedure on the Parser object is passed down the call
chain.  This procedure can be used to suck additional input.  It uses a
simple capability which is revoked as soon as the procedure returns
back to the parser.


File: design.info,  Node: class Control,  Next: class ClassControl,  Prev: class Parser,  Up: Class Definitions

class Control
=============

This class is used to create an ohat can be used to control another
object.  Every time a player creates an object, another object of class
Control is also created Storage, and is given the ability to retrieve
perfect capabilities for the object the player asked for.  This control
object is then placed in the player's inventory, while the object the
player asked for is left unlocated.

   A second copy of the control rod is placed in Limbo, for Wizardly
use.

   Please note that Control is used to perform mutations, and as such
cannot itself be mutated.  This is quite deliberate: mutating a Control
class object could very easily give access to specialized capabilities.


File: design.info,  Node: class ClassControl,  Prev: class Control,  Up: Class Definitions

class ClassControl
==================

This class is used to write to and recompile classes created by users.
It is created when the player runs a "create class" command.

   Like the Control class, objects of the ClassControl class cannot,
and should not, be mutated.


File: design.info,  Node: Storage Issues,  Next: MOZ Records,  Prev: Class Definitions,  Up: Top

Storage Issues
**************

* Menu:

* Associations::	How files, object Oz names, and objects are
			associated.

* Loading And Unloading::  MOZ is disk based; that is, when started it
			loads only the minimum number of objects
			necessary and loads and saves things on the fly
			as the server runs.  This section is a basic
			description of how that works.


File: design.info,  Node: Loading And Unloading,  Prev: Associations,  Up: Storage Issues

Loading And Unloading
=====================

The Storage object for the MOZ is the first object to be run.  It loads
all the classes it can find when its `start' method is run and sets up
dictionaries and such so other objects can find each other.

   MOZ is disk based, that is, there is no loading of objects at the
beginning of the MOZ, besides some of the one-instance objects.

   This turns out to be quite trivial in Oz: when objects are loaded,
they are pointed to by a weak dictionary.  When they are no longer
pointed to by anything else, the weak dictionary facility is used to
save them to disk.

   After the main program loads the Storage object, it loads the Server
object and runs that.  Everything else is loaded from there as needed.

   When an object is loaded, any of its attributes that are of type
`objectRef' (as defined in the `exports' list) are instantiated not
with the appropriate object wrapper but with a procedure defined by the
Storage object that checks if the object is currently actually loaded
from disk.  If it is, the procedure returns the wrapper. If not, the
procedure loads the object from disk and then returns the wrapper if
not.

   A full-shutdown save process goes as follows (individual object saves
can be inferred):  for each entry in the dictionary that maps objects to
file names, call the object's `toRecord' and save the result of that to
the appropriately named file.

   Objects are stored in files named <num>.obj, where <num> is a number
that is only used internally.  These files are saved in direcories named
after the class of the object.


File: design.info,  Node: Associations,  Next: Loading And Unloading,  Up: Storage Issues

Associations
============

Objects and classes are stored in files, and must be stably accessible
between invocations of moz.  Therefore objects and classes must have
static names which are used to refer to them by other objects within the
MOZ, and there must be associations between those names and the objects
themselves (well, the active object wrappers really, see *Note The
Active Object Wrapper::), as well as between the file names the objects
are stored in and their MOz names (or the objects themselves).  All
these mappings should be two-way, but mappings cannot be made on
procedures or objects or classes, so in some cases large searches must
be performed.  Oh well.

   Since class Storage is in the best position to obtain this
information, and it has nothing else to do after startup anyways except
swap objects to and from disk and answer capability questions,
associations will be stored on the MOZs Storage object.

   As can be seen in the MozBase def, all objects have a stateless
NewName associated with them, which is set at object creation using a
name created by Storage, and passed to `init' on the object. class
Storage has a dictionary to associate this name with the actual objects:
'oznameObj'.

   Since there's no real point worrying about making up file names for
objects, and since I'd like to not require uniqueness of object 'names'
(distinct from the Oz-level name for the object), I decided to just have
the object files be named with incremental integers with a .obj suffix.
A dictionary 'fileOzName' associates these integers with the unique
object names.  It would have been an array, but arrays in Oz can't grow
without rather a lot of work.  A dictionary 'oznameFile' provides the
reverse mapping.

   Objects are stored as records (using `toRecord' and `fromRecord').
One of the things that is in those lists is the class identifier, which
we might as well have be a name.  That name must be unique.  The file
name the classes are stored in is just that name with a .class suffix.
The file does _not_ store a pickle of the class: it stores the actual
source of the class.  Otherwise it would be very difficult to present
users with the source of classes, since Oz does not appear to have a
decompilation feature.

   The association between class names and the classes themselves are
handled by the dictionary 'nameToClass'.

   It is useful in the extreme to store on Storage what class each
object belongs to, so that we can certify objects as being
instantiations of a known-safe class.  So, at load time and during
upgrades the class of any given object is store in the dictionary
'oznameToClassName'.

   Also, for wizardly purposes it is necessary for the Storage object to
store a list of the capabilities available on each object in the MOZ.
This are updated at load and upgrade time, and are stored in the
dictionary 'oznameToCapabilities'.

   It would be incredibly inneficient to actually trace these
dictionaries for every call to every method not on the local object,
and it would make things much more complicated when dealing with
objects from another MOZ *Note R1::, so these associations are, for the
most part, only used at load and save time.  `toRecord', `fromRecord'
and upgrade use these assocations, and that's pretty much it, except
for Wizardly usage, which is not discussed here.


File: design.info,  Node: MOZ Records,  Next: Security In Detail,  Prev: Storage Issues,  Up: Top

MOZ Records
***********

There are several home-grown record formats that are important to the
MOZ, and they are specified here.

* Menu:

* object records::		The object record type.  Used to pass
				around object wrapper and capability
				information.
* verbs records::		The record used to store verbs for
				objects, including dealing  with
				localization issues.
* string records::		The record used for output string
				localization.


File: design.info,  Node: object records,  Next: verbs records,  Up: MOZ Records

object records
==============

The object record type is fairly simple:

     object(
         wrapper: <P/2 Wrapper>
         ozName: <Name>
         capabilities: capabilities(
     	init: <Name> start: <Name> stop: <Name> ...
         )
     )

   It just holds the active object wrapper, the ozName associated with
the object, and the capability list.  The only reason for the ozName
field is that having that information handy is amazingly Useful for
storing the object record to disk.

   An example of how to make an object record, from within an object,
for giving to another object(1):

     object(
         wrapper: self.wrapper
         ozName: @ozName
         capabilities: capabilities(
     	createObject:
     	    self.capabilityDict.createObject
     	objectRefFromRecord:
     	    self.capabilityDict.objectRefFromRecord
     	getClass:
     	    self.capabilityDict.getClass
     	upgradeObject:
     	    self.capabilityDict.upgradeObject
         )
     )

   ---------- Footnotes ----------

   (1) This really belongs in the programmer's manual.


File: design.info,  Node: verbs records,  Next: string records,  Prev: object records,  Up: MOZ Records

verbs records
=============

Verbs records are rather complex:

     allVerbs(
         en: verbs(
     	get: verb(
     	    method: get
     	    parses: [
     		exampleParseName(
     		    leftMostPreposition: lmp(
     			prep: [ 'from' 'out of' ]
     			leftSide: lhs(
     			    objectName: getObject
     			)
     			rightSide: rhs(
     			    objectName: fromObject
     			)
     		    )
     		]
     	    )
     	)
         )
         lb: verbs(
     	cpacu: verb(
     	    method: get
     	    parses: [
     		exampleParseName(
     		    objectName: getObject
     		    objectName: fromObject
     		)
     	    ]
     	)
         )
     )

   The outermost record is rather like the strings record.  Each
language's sub-record contains one field for each known verb.  Each verb
record contains the method that verb is associated with and a list of
parse records(1), which contains instructions for parsing the user
input (less the first word, which is always the verb) and turning it
into arguments that the verb method will understand.

   The verb record is used as an index on a dictionary which is used to
store the parsing we have done and to make sure that we don't parse the
same input the same way more than once if we can avoid it.

   The example above would be appropriate on an object with a method
like this:

     meth get( getObject: GetObject fromObject: FromObject )
     ...
     end

   ---------- Footnotes ----------

   (1) The parse record part of the verb records is in such a drastic
state of flux right now that I'm not even going to try to document it.
It eventually needs its own section, but that might belong in the
programmer's manual.


File: design.info,  Node: string records,  Prev: verbs records,  Up: MOZ Records

string records
==============

String records are quite simple:

     string(
         en: "This is the initial room.  It is very boring."
         lb: "ti pamoi kumfa .i .a'ucu'i to'e cinri"
     )

   As you can see, one field for each supported language, with a string
in the field.  Nothing special.


File: design.info,  Node: Security In Detail,  Next: Unsorted,  Prev: MOZ Records,  Up: Top

Security In Detail
******************

* Menu:

* Initial Capabilities::
			An explanation of the basic capabilities that
			every object is created with.

* Getting More Capabilities::
			A discussion of how an object goes about getting
			capabilities beyond the initial set.

* Persistence::		For capabilities to really work, the system has
			to be persistent.  This should come as no
			surprise whatsoever to people used to MUDs, as
			it's standard, but it's discussed briefly
			anyways.
* Capability Implementation::
			A description of the structures and code used to
			implement capabilities in MOZ.

* Wizardry::		Being a Wizard turns out to be an amazingly
			simple thing from the MOZ server perspective,
			and in fact is the only reason that Storage
			saves capability information.


File: design.info,  Node: Initial Capabilities,  Next: Getting More Capabilities,  Up: Security In Detail

Initial Capabilities
====================

Note that this section is quite likely to vary depending on the design
of the specific MOZ in question.  What is described here is simply from
the perspective of the base MOZ server.

   In general, a created object should be passed, as an `init' argument,
the smallest number of capabilities possible.  At a minimum, this
consists of the following:

   * A list of capabilities on the Storage object, so that new objects
     can be created.  This would include a way to list class names as
     well as a direct object creation call.

   * A class testing capability from the Storage object.  This takes an
     object reference and returns true if and only if the object in
     question is an instance of one of the built-in or otherwise judged
     safe Oz classes.  This is used to warn players that they might be
     in trouble if they go into, say, rooms of other classes.  Note
     that Wizards can add to this list, and should only do so if
     they've read the code in question.

   * A listContents capability on the room the object is created in.
     Note that this returns a list of requestCapability capabilities on
     the contents, i.e. a set of functions that can be used to ask for
     other capabilities

   * A listExits capability on the room the object is created in.

   * A requestCapability capability on the room the object is created
     in.


   That's a pretty short list, but it is actually quite sufficient, as
we'll see in the next section.  Note that this glosses over some issues,
like the capabilities shared between the Player, Parser, and Connection
objects, but that's a little low level for this discussion.

   Note that the requestCapability capability on the starting room
allows the object to get the other capabilities on the starting room
that it starts with; they are provided initially simply to save time.


File: design.info,  Node: Getting More Capabilities,  Next: Persistence,  Prev: Initial Capabilities,  Up: Security In Detail

Getting More Capabilities
=========================

Note that this section is quite likely to vary depending on the design
on the specific MOZ in question.  This is simply from the perspective of
the base MOZ server.

   So, you're a newly created player in a MOZ, with the capablities
listed in the previous section.  You (or rather, the code underlying the
actions) want to say something.  Here are the steps involved:

   * Call listContents on the current room.  This returns a list of
     requestCapability capabilities for all objects in the current room.

   * Call each of those capabilities, requesting a 'tell' capability.
     Some of them will refuse.  That's fine; if they don't want to talk
     to you that's their business.

   * Run the tell capability on each of them with what it is that you
     have to say.


   Note that talking is _not_ handled by the room, in contrast to most
MUDs.  This is because in a capability based system, we want to avoid
testing as much as possible, the testing in this case being whether the
object wants to hear your tells or not.  This way you can cache the
capabilities for all the objects in the room you're in, so the test only
gets run once (when you request the capability).  Note, again, that
certain things are glossed over, like retries for failed cached tell
calls: the object may have revoked that capability, but may not mind
giving it to you again.

   Note further that although there are capabilities given to you for
every object in the room, this gives you no information other than that
an object is there; not even the name of the object or any description
information can be given to you if the object does not allow it (unless
the room has been coded to 'cheat' and store capabilities it is passed
and give them away freely).  This is how 'invisible' objects can be
implemented, although you can still inform the user that an 'invisible'
object seems to be in the room.

   Another example: you want to move to a roomed joined to this one by
an exit.

   * Call the listExits capability, use the capabilities provided to
     request name capabilities, check the names, figure out which exit
     you want.

   * Request the use capability on the exit.  If you don't get it,
     well, you can't go that way.

   * Call the use capability, pass it a capability on yourself allowing
     updating of your location information (i.e. the capablities on the
     current room).  Note that the updater in question should test
     whatever it gets passed, to make sure the capabilities it was
     given actually work!

   * The exit should already have an update capability on the room it's
     attached to, which it uses to remove you from the room's contents
     list, and add you to contents list on the other side.  It then
     calls your update capability with the information from the new
     room.  Any error causes everything to be changed back.

   * Revoke the update capability you passed the exit, stopping further
     updates.  In fact, the update capability shoud do this itself.


   There is one other, rather different, way to get new capabilities:
creating a new object returns a list of all available capabilites on
that object.


File: design.info,  Node: Capability Implementation,  Next: Wizardry,  Prev: Persistence,  Up: Security In Detail

Capability Implementation
=========================

Capabilities are normally going to be stored in records on various
attributes.  The format is going to be: capabilities( foo:<ozname>
bar:<ozname>), where foo and bar are methods on the object.  Theses
lists will be seperate from the attribute holding the reference to the
object wrapper procedure.  So, for example, the list of exits from the
current location would be retrieved as follows:

     {@location.wrapper @locationCapabilities.listExits listExits($)}

   Note that this means there are two attrs for every capability list.
When that request for listExits comes in, the object wrapper selects the
appropriate method from its dictionary which is keyed on the Oz names of
the methods, and calls that method.

   This way of doing things unfortunately breaks the abstraction of
treating the object wrapper as though it were just another object.  It
was possible to make it much cleaner, but it made saving objects a
gigantic pain and added a bunch of code.  There were other ways of
handling it without those drawbacks, but they all put a fair bit of
knowledge burden on the coder in terms of understanding how Oz
constructs records and such.

   If you really want to make a function that returns a function that
acts just like a normal object (which I don't particularily recommend,
by the way: it'll probably slow things down a bit), here's what one
would look like:

     proc {CapProcMaker ObjProc CapList ?CapProc}
         proc {CapProc Meth}
     	{ObjProc CapList.{Label Meth} Meth}
         end
     end

   Note that it is very important that you not try to save this
procedure on your object (i.e. do not add it to the exports variable of
the class), as this will cause the saving to fail.  This means that if
you are storing this procedure on an attr you need to check for its
existence (probably using IsDet or Value.type) pretty much every time
you use it, or make sure it gets recreated every time your object is
reloaded (i.e., create it in your `start' method).


File: design.info,  Node: Persistence,  Next: Capability Implementation,  Prev: Getting More Capabilities,  Up: Security In Detail

Persistence
===========

Persistence is something that is entirely normal in MUDs, so this whole
section may seem amazingly obvious to those of you used to MUD
programming.  However, it is very _abnormal_ in operating systems, but
see EROS (http://www.eros-os.org/).

   In an operating system, if you want to open a file, you go and get a
list of files, then ask for permission to open it.  This makes it easy
to deal with reboots: you just go look for the file again.

   Obviously, this can't work in a capability system: where do you get
the list of files from?  In the context of a MUD, there would need to be
some way to search through all the rooms to find the one you were in to
ask for capabilities on that room.  There is no such ability.  OK,
that's not quite true, the Storage object can, and does, have such an
ability, but _only_ for purposes of implementing persistence.

   So, the mud simply stores everything.  Every few minutes, each
object is written to disk, along with all the capabilities it has
acquired.  So there is no rebooting, really: after a crash or whatever,
the MOZ is brought back up as though nothing had changed.

   Actually, that may not be quite true: only the capabilities that are
saved as part of running `toRecord' on that class are stored, so stuff
that is only being stored in running code or cache attrs is not
preserved.

   Capabilities, because they are simply implemented as a record of Oz
names, are stored as per normal by the Storage object.  The object
wrapper handles are turned into Oz names on the way out and converted
back on the way in.

   For that to work, the newly loaded object that the capability is for
must remeber what the names were that it had associated with various
methods, especially since this is handled in the wrapper.  The way that
this is done is to simply have the information be stored as a dictionary
in the wrapper; the wrapper has code in it to intercept the `toRecord'
call and add the capability information, and also to intercept the
`fromRecord' call and extract it again.


File: design.info,  Node: Wizardry,  Prev: Capability Implementation,  Up: Security In Detail

Wizardry
========

It would be possible to have a capability based system with no user
having more power than any other user, in other words no Wizards, no
Gods, no root.  Of course, because of the nature of capabilities there's
nothing to stop a user from setting up their own little domain in which
they have ultimate power, but that's not the same.

   However, as a design decision I feel that that's a bad idea.
Capabilities, as previously stated, make it rather easy for users to
screw up if they try their hand at programming, or go into an area owned
by a malicious user and say 'yes' to a lot of request messages and end
up in a really bad way.  I would like there to be a way for them to get
un-screwed.

   Therefore, MOZ supports Wizardry by default.  Being a Wizard is very
simple: you have full capabilities on the Storage object, always has the
most up-to-date set of capabilities for every object in the MOZ.

   Note that as the wrapper code is just about the only ex-DB code, it
is impossible to circumvent the fact that the wrapper code will report
capability changes to the Storage object.

   Note that users can get around this by creating objects which they do
not report to the server.  This has the substantial disadvantage that
they will be lost upon server restart, as normal users are not given
capabilities to anything that would allow them to store the information.

   Also, the wrapper tells Storage to update this information on each
change.


File: design.info,  Node: Unsorted,  Prev: Security In Detail,  Up: Top

Unsorted
********

   * As a stylistic issue, all methods should use full record field
     names for their arguments.

   * I am currently of the belief that all special user capabilities
     should be stored on objects (i.e. keys and such), primarily
     because any other method is just too damned easy to spoof.  Here's
     some stuff about another way of doing it.

        * It is useful to have capablities on objects that are, more or
             less, automatically activated (i.e. a door that only you
          can walk     through).  MOZ calls such capabilities 'keys'.

        * Keys are stored on their own attribute on the user.

        * When a verb is call, a requestKey method is passed.  Actually
             passing a key requires asking the user first.

        * Keys are in a dictionary indexed by ozName; ideally there
          would be some way to verify the ozName of the calling object.

   * However, having special capabilites on objects (which are
     presumably carried) leads to some issues with things like a dragon
     who doesn't eat anyone wearing the Gauntlet Of Might, or whatever.
     Ways of handling this are below.  I have not picked yet, although
     I have a bit of a preference for a 'wear' verb.

        * Verb transparency to objects in inventory, which could cause
            problems if you pick up the wrong thing.  But this could be
             selectable, i.e. some objects are allowed to be
          verb-trasparent.      The easiest way would be a 'wear'
          command, such that objects that     are word are checked for
          verbs.

        * Extensible verb lists (i.e. an attr?) in which an object field
             is part of the verb definition.  This way the Gauntlet of
          Might     would add a verb to the *player* (with permission,
          of course) called     'challengedBy'. Calling challengedBy(
          arg1: <the dragon in question>     ) returns a value that
          causes the dragon to calm down.

   * This was in the class Parser section.  I was smoking crack.

          Note that the verb call can immediately thread off, and
          should almost always do so if any non-trivial computation is
          done, since output is handled by an Oz port.  This will be
          particularily important when in-game thread management is
          implemented; threading off will allow the player to kill
          threads if necessary, as commands can still get through.

     There is no way to get a list of threads in Oz, so what needs to
     be done at some point is to hack the parser object to thread off
     all verbs and save their thread ids on the player object, so that
     the player can kill them.

   * I have no idea where to put this.  Movement of an object is three
     seperate things, in terms of capabilities: changing of where the
     object's location attr points, and changing the contents list of
     the before *and* after objects.  Therefore, capabilities on three
     objects are involved.  This should be discussed, both as a
     capability example, and an implementation detail.  Maybe it's time
     for implementation notes?




Tag Table:
Node: Top356
Node: Requirements2817
Ref: R13122
Ref: R23180
Ref: R33242
Ref: R43292
Ref: R53332
Ref: R63423
Ref: R73551
Ref: R83603
Ref: R93644
Ref: R103667
Ref: R113692
Ref: R123785
Ref: R133808
Node: Security Overview3888
Node: One-Instance Classes9035
Node: Ex-DB Design10610
Node: The moz Program12694
Node: The new_moz Program13442
Node: The Parsing Module13838
Node: The EnhancedString Module14469
Node: The Active Object Wrapper14853
Node: The MozCompilation Module18231
Node: Object References19198
Node: Class Definitions20021
Node: General Class Issues21778
Ref: General Class Issues-Footnote-130036
Ref: General Class Issues-Footnote-230263
Node: The Class Hierarchy30515
Node: class MozBase32169
Node: class Storage32729
Node: class Server33521
Node: class Described34065
Node: class Located34368
Node: class Mobile34638
Node: class Location34874
Node: class Player35133
Node: class Wizard35484
Node: class Puppet35854
Node: class Container36150
Node: class Exit36391
Node: class Gate37675
Node: class Terminus38047
Node: class Connection38390
Node: class Parser38935
Node: class Control39810
Node: class ClassControl40633
Node: Storage Issues40997
Node: Loading And Unloading41463
Node: Associations43157
Node: MOZ Records46601
Node: object records47146
Ref: object records-Footnote-148247
Node: verbs records48303
Ref: verbs records-Footnote-149873
Node: string records50102
Node: Security In Detail50491
Node: Initial Capabilities51387
Node: Getting More Capabilities53402
Node: Capability Implementation56757
Node: Persistence58916
Node: Wizardry61113
Node: Unsorted62686

End Tag Table
