[MUD-Dev] Room-based vs. coordinate-based

clawrenc at cup.hp.com clawrenc at cup.hp.com
Wed Jun 11 15:26:44 CEST 1997


In <339C618C.167EB0E7 at iname.com>, on 06/09/97 
   at 05:16 PM, Shawn Halpenny <malachai at iname.com> said:

>clawrenc at cup.hp.com wrote:

>> In <3396ECE4.41C67EA6 at iname.com>, on 06/05/97
>>    at 07:38 PM, Shawn Halpenny <malachai at iname.com> said:

>> >clawrenc at cup.hp.com wrote:

>> The thing I really don't like about this /sort/ of solution is that if
>> BubbaTwit programmer comes along later and adds rooms to Castle Krak
>> he's fairly likely to not notice the special case magic handling and
>> to thus leave it out.  Of a sudden the sceptre only partially works.

>Yah.  I started thinking about this sort of thing after I'd posted.
>Originally, it was my intention to have all such programmed objects
>run by (probably) me before they'd be put in place; now, however, I
>want to take myself out of that picture and let the system handle it. 

You're going to have a checklist to run every piece of code past to
make sure nothing has been missed?  You're never going to skip or
skimp something on this list?  This list is going to always be updated
as the system changes?

>The solution above is not exactly conducive to that.

Quite.

>>   The sceptre then iterates across the container spoofing every room
>> to install a new magic handler.  The actual code for Castle Krak never
>> need be aware this has happened, or even could happen.

>So in this case these spoofs are room objects that are functionally
>identical to the old rooms, but with new magic-handling methods?  

Not quite.  The following is assembled from various earlier messges,
and so may be a little jerky:

A diagram of a spoof:

  Note: All references to "Object#" below are refering to the object
in
  the DB whose ObjectID is "Object#".

  ObjectA exists.
  ObjectB spoofs ObjectA.
    ObjectA is cloned (exact copy) to ObjectX.
    The contents the original ObjectA are replaced entire with the
      contents of the the spoof object.

Removal of a spoof does the same thing backwards:

  ObjectC is copied on top of ObjectB.
  ObjectC is deleted.

The power of a spoof comes from sonething called "a generic method". 
Very simply a generic method will match any and every incoming method
call which is ot more directly matched by another existant method on
the object.  Where the power comes in is that a spoof object is able
to use this to intercept certain method calls to an object, and to
allow others thru to the orignal object.  

Internally, the spoof may have a number of methods defined, and the
general method.  The result is that any other object sending a message
to what it thinks is the original ObjectA, instead is sending a
message to the spoof. The spoof can then intercept that message with
one of its own locally defined methods, or it can pass the message on
(possibly edited) to the original object via the general method.

In a way the spoof acts as an intelligent filter between the original
object and the rest of the world.  Considerable intelligence can be
built into a spoof.  The result is that the entire behaviour and
appearance of an object, even its API can be changed, all without
changing the source to the original object at all.

A spoof is just a normal MUD object.  The only specific difference
between a spoof and other objects is that a spoof is used to *replace*
a normal MUD object, relegating the original object to a backup copy. 
This leaves the rest of the system in ignorance -- it has no reason to
think that anything happened.  Thus message calls from other objects,
intended for the spoofed object, now arrive at the spoof, and the
spoof does with them whatever it wants (including passing the message
straight back to the hidden original object).

Diagrammed:

  ObjectA exists.
  ObjectA is spoofed.
    ObjectA is cloned to ObjectB.
    The contents of ObjectA are replaced with the spoof.
  ObjectX now calls ObjectA.get()
    Note that ObjectA is now the spoof.
    ObjectA does not have a method called "get()" defined.
    The general method on the spoof matches get(), and calls
      ObjectB.get()
      ObjectB is of course the original object, just with a
        different objectID now.
      ObjectB.get() is called and does whatever.

Or, to show the spoofing in action:

  ObjectA exists.
  ObjectA is spoofed.
    ObjectA is cloned to ObjectB.
    The contents of ObjectA are replaced with the spoof.
  ObjectX now calls ObjectA.get()
    Note that ObjectA is now the spoof.
    ObjectA __does__ have a method called "get()" defined.
    ObjectA.get() is called instead of any get() method on the
      original ObjectB.
      ObjectB is of course the original object, just with a
        different objectID now.
    ObjectA.get() does whatever.

Example:

  The DemonWroth watches all character objects (players) that have
ever been in the same room as the PrincessBride, until those objects
have been in the same room as the Great God GooGoo.

One solution is to have the DW spoof the containment methods on the PB
so that every time the PB enters a room a spoof is set on the room
(and removed from the room she left).  The spoof overlays the
containment methods on the room so that it in turn installs monitors
on any objects that enter the room, _and_ spoofs the object to overlay
_its_ containment methods to check for the presence of the GGGG when
ever it enters a room (and remove the monitor and the spoof if it
does).

Diagrammed:

  DemonWroth installs spoof on PrincessBride
    Spoof(PrincessBride) adds features to
PrincessBride.I_am_contained_by
      and PrincessBride.I_am_leaving_container.
      Spoof(PrincessBride).I_am_contained_by spoofs the room the
        PrincessBride is entering.
      Spoof(PrincessBride).I_am_leaving_container removes the same
spoof
        from the old location.
        Spoof(room) adds features to the room.contain_objects.
          Spoof(Room).contain_objects installs monitors on any objects
            which enter the room (call it "thing").
            Monitor(thing) reports back to the DemonWroth.
          Spoof(Room).contain_objects spoofs the object (thing) that
just
            entered the room, adding features to
thing.I_am_contained_by.
            Spoof(thing).I_am_contained_by checks every room the thing
              enters to see if the GGG is there, and if so removes
itself
              (the spoof), and the monitor that reports back to the
              DemonWroth

Starting to get the idea?

>And
>if so, does that imply that creation of magical effects is handled by
>the rooms themselves?  

Nope, the magical effects are created by whatever.  The spoofs just
intercept key methods to prevent magic in the first place. 

Actually, now that I've moved to a mana system, this gets even easier
to do than it was before:
  
  Sceptre enters the Elven Forest.
    Iterate thru all contents of the Castle Krak master object.
      Spoof all containers.  
        Spoof intercepts containment methods and auto-magically 
          hides (not destroys) all mana particles in room.
      Install watchers on all containers.
        Should a container leave the castle the above spoof and 
          the watcher is removed.
  Spoof the containment methods on the Sceptre.
    Spoof intercepts all I_AM_CONTAINED_BY methods and checks for 
      not being in the Elven Forest any more.  

  Sceptre leaves the Elven Forest.
    The Sceptre spoof acts like a watcher (could use watcher 
      instead), and notices that the Sceptre is no longer in 
      the EF.
    Iterate thru all contents of the Castle Krak master object.
    Remove all spoofs of containers.
    Mana is instantly available again.

Voila!  The sceptre enters the forest and magic fails.  The sceptre
leaves, and it works again.

>I'm beginning to think that I posted my
>procedure for the Scepter and Castle without enough forethought...

<innocent look>

>I make the magic-effect creator a method on a container (say, a room)
>and whenever I want to "spoof", I just override the method in a
>derived object (something I already do elsewhere, hence my realizing
>I'd not thought the post through enough).  Simple enough, since all
>the rooms are derived from a common object (which would have been
>that magic-effect creator if you went high enough up the inheritance
>tree) anyhow.  That should now account for stupid programmers and
>make things much more scalable.  And of course, if one does the
>inheritance and overriding properly, it's nicely applicable to all
>sorts of other situations.

Bingo.

>Right.  There are always two things to be done in this case:  kill
>existing effects and prevent creation of new effects.  Methods would
>also have to be overriden to take care of objects coming into the
>castle after the Sceptre has been brought into the forest (easy
>enough).

Ahh, part of intercepting the containmnet methods above is that any
new objects entering Castle Krak are tested to see if they are spoofed
already with the Sceptre Spoof.  If they are not, theyn they are
spoofed as well.

>If A wants to watch B, A sticks a reference to itself in a list
>inside B.  State changes in B will now send notification to A
>provided the change matches the parameters required by the watcher. 
>A can stop watching B whenever it chooses, but only the destruction
>of B can force A to stop watching B.

Ahh.  I don't have any sort of filtering or definition of watchers.  A
watcher just triggers whenever an object changes.  The result is a
message sent to the waiting object of the form, "I HAVE CHANGED".  I
then leave it up to the waiting object to figure out what changed, and
if they are interested in that change.  

This allows a watcher to trigger on a state change for a private data
member in an object.  Depending on the strictness of your views on
data encapsulation, this can be thought of as a Good Thing, or a Bad
Thing.  

--
J C Lawrence                           Internet: claw at null.net
(Contractor)                           Internet: coder at ibm.net
---------------(*)               Internet: clawrenc at cup.hp.com
...Honorary Member Clan McFUD -- Teamer's Avenging Monolith...




More information about the mud-dev-archive mailing list