Resets and repops

claw at null.net claw at null.net
Thu Mar 27 13:37:11 CET 1997


On 27/03/97 at 01:38 AM, Nathan Yospe <yospe at hawaii.edu> said: >On
Mon, 24 Mar 1997 claw at null.net wrote:
>:On 21/03/97 at 12:53 PM, Nathan Yospe <yospe at hawaii.edu> said: >On
>:Thu, 20 Mar 1997 claw at null.net wrote:

>*grin* Well, what we have here is a challenge. Lets see... I'm
>writing a scratch codebase. Aspect one covered. I'm a decent author.
>(Eventually, books by one Anthony Aspe are gonna start wandering into
>your part of the world. That's me.) I might or might not have the
>stamina to write an entire world. Probably not, but I can set the
>mood for the whole damn thing.

Before getting too cocky there, have a talk to some of the old Island
wizards.  They had to fight hard to maintain their quality level.

>:>:I suspect that the real problem is that I implicitly do not
>:>:support compound types in the internal language.  (Well, nothing
>:>:more complex than typeless lists/arrays).  If I supported complex
>:>:types which allowed full objects to be used as components, this
>:>:would be a LOT easier -- its just that doing that opens up a huge
>:>:nest of worms (incompleat objects, missing dependancies, etc).
>:
>:>Hmm. Obviously, we catalogue things differently.
>:
>:True, but I'm not sure why you comment that.  ??
>
>Because I didn't follow a word of your previous paragraph. Compound
>types? Complex types, I think, is something along the lines of my
>'parts' system. But what is a typeless list or array? Isn't that
>getting a little extreme? Then again, you did say that _any_ command
>could be applied to any object. The implications of that had never
>quite sunk in.

My internal language is typeless, but supports type representations
for a variable.  Thus a variable can be assigned a value of any type,
and may then be manipulated as if it were of any other type with
automatic inline type conversion.  I also support lists as one of the
base types, where a list merely consists of a list of other types
(some of which may also be lists).  List member addressing is done
array style.  A list is described as typeless because it in itself
really has no type -- only its non-list members have types (sorta). 
The items I don't support as base types are objects (I do support
ObjectIDs), and methods (ie method pointers).  I have come to suspect
that I should do both, or probably more likely, borrow another,
externally supported/written/etc language which does.

By compound types I mean types comprised of other types, ala C
structures.  Unfortunately above I mixed the terms "compound type" and
"complex type". I meant "compound type" for both.

When I wrote that any command could be appiled to any object, realise
that I am dealing with a message based system.  Method calls,
commands, all that rot -- they're all just messages, and anything is
capable of authoring any message it may wish.  However the receiving
object does not have to be so charitable.  It, and its component
methods can have their own security critria which determine what
messages thay are willing to receive, and how they wish to respond.  

A message calling a specific method on a target object will call that
method directly once it has passed the object-wide security criteria. 
If the method does not exist, the object returns an ERR__NOMETHOD
exception.  However, most objects also have a "general method" which
will match all incoming method calls, regardless,  The general method
can then do with the inbound message what it will: implementing its
own security criteria, forwarding the message to an internal method,
altering the content of the method and passing on to another object,
processing the message itself and returning a value, or returning an
exception.

As almost all objects have a general method any message will at least
be received by any object -- as long as it passes the object-wide
security criteria.

Whoops, just realised I didn't paste in an explantion of my lockless
system in the message I sent just a while ago.  I'm going to insert
the quote and my intended reponse here:

>:Because my memory image is so fluid (everything resides on disk) I
>:haven't looked much at using in-memory compression.  I do reference
>:count and fold strings tho, and the whole DB cache with the
>:requested, modified-but-not-committed, committed, etc states, along
>:with the interested party lists is pretty tight.

>Hmmm. An utterly different model here. I don't understand half of
>what you just said.

Ahh, its time for a refresher course in my lockless database model --
the old C&C (Compare&Commit) business:

-- All events execute in their own threads (we covered this before).

-- All IO from the event is buffered.


-- As an event executes it requests objects from the DB.

-- The DB provides local copies of the objects.  

-- If the event modifies one of the requested objects, a copy of the
object as supplied by the DB is made.  The changes made by the event
are made to this code.

-- When the event finishes execution the original copy of each touched
element is compared with the version of that object currently in the
DB.  

-- If they compare (ie identical), the the event commits, the modified
versions of the objects are committed to the DB atomically, and all
buffered IO is released.

-- If the original copies do not compare, the event will fail to
commit, the IO and all object copies objects are removed, and the
event is rescheduled for execution.

It actually gets a little messier that the above picture as the DB
actually only hands out references to objects in the DB cache.  It
then maintains an interested party list for each object, where the
interested parties are events that have requested that object.  This
then allows me to do some short circuiting:
 
-- Say EventA is executing and requests ObjectA.
-- The DB loads ObjectA and hands out a reference.
-- EventB is also executing, and requests Object B
-- The DB hands out a reference and adds EventB to the interested
party list for ObjectA (EventA is there already). -- EventB now
successfully C&C's.  
-- The DB now knows that EventA will be unable to C&C because one of
its dependancies has changed, so the DB messages EventA to tht effect.
-- EventA receives the message, reschedules itself and dies.

In truth it actually attempts to get a even little finer than the
above, with a goal of eventually having the compare portion of the C&C
only check the values of the members referenced/altered by the event. 
This would allow EventA and EventB above to both successfully C&C on
their first pass as long as they did not both reference or modify the
same members of ObjectA.  

NB "Folding" above essentially refers to refernce counting where a
single physical copy is used with multiple external
pointers/references to preserve memory and reduce copy expenses.

>I just posted something to r.g.m.diku about this in the loop driven
>vs event driven thread. I've got three layers of event queues:
>global, area, room, with internal threads in each queue. Remote
>reactions are going to be in the area or global queue, of course...
>but, getting deeper into the question... we're going to have to get
>really deep into the Impulse system here.

Mind reposting your article here?

>:I'll see if I can't remember the scenario that originally took me on
>:this route.  Do note that this is a fairly complex set that I used
>:as a proof-case for a whole chunk of ideas, with spoofing etc just
>:one of the results.
>:
>:
>:  The GreatGodGooGoo has a number of holy relics.
>:  Each relic has a non-magical base state, and a magical awakened 
>:state.

>Not sure what the application of the magical/non magical part is, but
>awakened would mean that a global condition would be logged.

Ahh, that's one thing I don't have:  A global namespace.  

While objects have unique ObjectID's, and any object (that exists) can
be referenced directly at any point via its object ID, which sort of
translates into a global namespace, I discourage that view strongly. 
As you say, I encourage localised reactionary and event based systems,
not global state retentive systems.

>:  If more than three of GGGG's relics are simultaneously awakened, 
>:  the GGGG does nasty things.

>Awakening a relic triggers a check/increment/create on a global
>condition object tracking the GGGG relics. A condition of 3 generates
>an Impulse to  GGGG at this point. This condition object is not used
>by the base classes, so affects nothing but GGGG.

The problem here is that this requires the component objects (the
relics in thsi case) to be programmed with the knowledge that the GGGG
or its global monitor object needs to be informed of their changes.  I
don't allow that.  

  "Any feature must be programmable on any object without source
access to any other objects."

As such, the GGGG must be able to be programmed without the code for
his relics (presuming they pre-exist) needing to be altered or touched
at all.  It is from this rule that spoofs and watchers originated. 
Most of your other solutiuons also fail on this rule,  (Sorry, thought
I'd encluded it in the quote)

>Those "localized" events were nothing of the sort. Each one did
>something out of the ordinary, and would register global states. Of
>course, this is all academic, as anything requiring global states in
>Singularity 2 (as opposed to Physmud++) is suspect for violations of
>the base laws, as is clearly the case with your example. But the code
>support is there. (So what are the global conditions there for?
>Symmetry. I have reasonable uses for local (room) and regional (area)
>conditions.... and since there is symmetry everywhere else, the
>global conditions got put in. Lucky for the ridiculous (by Sing2's
>laws) situation proposed.

Capiche.

I use a similar form of semi-globals (room, area, etc), via
containment.  All objects are in turn contained within anotehr object. 
This repeats until the root object which contains the entire game. 
This containment is not the old standard of stones in bags (well it is
logically), but is parrallel to that.

What this means is that specifics and effects, such as verbs and other
features can be implemented at any level of these nested containments
to have them them effect any contained item.

In this way the root object sorta represents a true global object, and
it could be abused to have everything under the sun defined in it for
global variables etc, but that's not what it is for.

Re: Bloodstone From Bartle's article

>:        Everything was interlinked.  If bricks were removed from a
>:wall, it might collapse, bringing the rest of the building down. 
>:Small-scale actions could have large-scale effects.  There are,
>:however, well known problems in the AI field of object
>:representation :concerning this kind of activity. Either the
>:programmer has to list explicitly all effects of players' actions
>:(which is difficult and tedious) or the game's interpreter can
>:figure it all out on-the-fly as it happens. This latter approach,
>:where there are a set of physical laws that are applied to
>:everything that has moved after a command has been executed, is
>:workable but vulnerable; there can be long delays as effects are
>:propagated throughout the universe being modelled, and some effects
>:may take considerable time to dampen down and disappear. Pulling a
>:petal off a flower may seem innocuous, but if it makes you weigh
>:just enough that the snow bridge upon which you're standing
>:collapses, and this in turn starts an avalanche, there can be
>:wide-scale devastation that is almost impossible to sort out.

>Not hard at all, actually. And taking up less CPU than the poll of a
>Diku through a handful of rooms. And _that_ is why I have a lot of
>sleeping threads. Because of those types of avalanche effects.

True.  At that time the concept of event driven systems that
intelligently propagate their internal events wasn't well developed.

>Though... well... there are more probably causes than a flower petal,
>which I would never allow to be coded (too much RAM for too little
>result) or some picked up object (remember, if you pick it up off of
>the bridge, nothing has changed)... jumping up and down might do it,
>though. The thing is, is we are not talking a 100% random system.

Stand on the bridge and pick an apple from an overhanging branch. 
Toss a snowball to the fellow on the bridge.  Bird shit from above.  

>:        Bloodstone was envisaged as a game of life, yet there lay
>:its central problem: it had no gameplay to speak of. It was a
>:simulation to incredible depth, but there wasn't really much that
>:players could do, it was too open-ended. Even given the extravagant
>:claims its publicists made, it probably could have been forgiven all
>:but that.

>This is more a failing of the mentality of mud design at the time. A
>simulation can add massively to gameplay exactly because of the
>avalanche effect described earlier. Bubba ticked you off, and you
>know Bubba is going to be crossing that bridge on his way home, so
>you start weakening its foundation, until it cannot support more than
>a coule hundred pounds. Then you hide a small cart full of nice
>knives just out of sight (almost) on Bubba's side of the bridge. Of
>course, the cart is cheap, but the knives are... actually tin, with
>rocks under the third layer. You get the idea.

Not quite.  While this does show the sort of advantage a simulation
can add to a game, it doesn't really counter argument of
open-ended-ness.  There are essentially two forms of games:  goal
oriented, and process oriented.  Goal oriented games are fairly
obvious: there is a goal one strives to achieve, often competitively
with others.  The goal may be advancement, levels, "winning", power,
money, or whatever.  Process oriented games are tougher, and may be
argued not to be games at all (Bartle's position).  Their fundament is
that actual process of playing the game is entertainment enough, and
that the player(s) are supposed to then use the process for amusing
means.  Bartle never states that there is a goal to Bloodstone.

>:>Ugh. No, I use a nervous system of sorts, with Impulses being
>:>passed along the limbs and into the body, to wherever the Character
>:>is stationed within the body. (In the head, for humans, etc..)
>:>Also, for example, shock can be passed as an Impulse, allowing a
>:>Character to be killed by pain, or some such. (but also creating a
>:>flinch reaction, etc, which is really nice.)

>:What causes the flinch to pull the hand off a hot plate as vs an
>:undirected body jerk reaction that leaves the hand there?

>The fact that the flinch is interpreted at every joint as a 'tighten'
>reaction, exactly like the human nervous system. The closer the
>joint, the stronger the response... and the hand pulls away.

That doesn't always work.  Examples: Raise your hand underneath a low
shelf while standing.  Have the shelf painfully hot.  Tightening the
joints will increase contact.

>:Oh dear!  You thought I was a mobile?  I shall have to kill you I'm
>:afraid.  Please stand still and don't struggle too much old chap. 
>:I'll try and make this painless.

>To which the clever TuringAI (which hides its own nature by
>challenging yours) replies, "Kill me?! That's it. You're really
>asking for it, punk." and pulls out a _very_ nasty looking self
>targetting deadman switched flamethrower. *grin* And that is a real
>TuringAI I designed. Haven't tested the sucker yet, mind you.

<kof>  I like it.

--
J C Lawrence                               Internet: claw at null.net
----------(*)                              Internet: coder at ibm.net
...Honourary Member of Clan McFud -- Teamer's Avenging Monolith...






More information about the mud-dev-archive mailing list