1.0 Scope

1.1 This document tracks the core concepts and acts as an encyclopedia or dictionary.

1.2 Authors

1.2.1 Brian Jones (brianj@otterspace.com)

1.3 CVS Version: $Id: core_concepts.html,v 1.2 2004/06/24 21:40:05 brianj Exp $

2.0 Referenced Documents

2.1 Concept of Operations uses these terms.

2.2 Places Explained describes places in detail.

2.3 Events Explained describes the event model in detail.

2.4 Permissions Explained describes the permission model in detail.

2.5 Relations Explained describes the notion of using objects for relationships instead of collections on objects with back-links.

2.6 Time Explained describes the uses and notions of time in the NMC2 MU.

3.0 Concepts

Note: the section below are always alphabetical and not numbered. This avoids the renumbering problems as we grow the document. The entries must be unique, so the nomenclature will be the heading name itself.

Action

See also: command, event

When an event occurs, the system performs certain steps. These steps are collectively referred to as actions.

Whenever a programmer writes code that carries out steps (in the core or writing scripts inside the system in an extension language) they have implemented an action.

Character

See also: player

A character is any object in the system which has a point of view. In the NMC1 system, characters were both zombies and "player objects." We no longer use the term player to ever refer to an entity within the code of the game.

A character object exists in VR and is controlled by players, who are people logged into computers and issuing commands.

Characters may also be controlled by software, in which case they are often referred to as MOB - Mobile Objects. Thus, a character could be a monster under the control of a program instead of under the control of a live player.

Command

See also: action, event

When a player wants the system to do something, the player sends the system a command.

Commands were implemented in NMC1 as actions that invoked MUF or MPI code. They were also hard-coded into the NMC1 server in C++ as well.

Most of "MUCK Programming" is in fact creation or new commands to replace built-in commands or add new functionality.

In NMC2, a command is similar. It's what a player requests of the system. However, unlike NMC1, there are no hard-coded commands in our core server. All commands are dispatched through the core but never implemented there. Thus, the are no "master commands" in the server.

A shell is the tool that a user enters text into that typically generates the command to be dispatched. It's also possible for commands to come from other protocols than manual entry. This allows remote automation or special clients to send commands in ways that don't necessitate their being converted first into some shell-specific text representation.

Commands exist as a user-concept. Commands are a type of action that cause work to be done and may generate events.

From a developer perspective (core developer and in-game scripting developer) commands the user enter always cause at least the event that runs their code.

Core

The core is the part of the software that shouldn't need to be changed to add new features. It's the heart of the system responsible for the fundamental internal processing.

Declarative Programming

See also: imperative programming

There are a few major ways in which people control what a computer does. The most obvious of these ways is imperative programming. This means the user gives commands which the machine follows.

Another common way, best exemplified by SQL, is declarative programming.

In declarative programming the computer is given a goal-statement and the computer figures out how to achieve the desired result.

This means instead of giving the computer steps to follow, you give it a desired end result, and it chooses and carries out the steps itself. This isn't magic, or even close to magic. It simply means that the syntax of the language you request the end result in provides enough information for the job to be done.

As a simple example, consider the following (legal) SQL statement:

   select name,address,city,state,zipcode
   from customer as c inner join invoice as i
   where i.balance > 0 and (now-i.date)>30 

In the above example, is the system going to open customer table or invoice table first? What index files if any is it going to use? What are the names of the underlying files in the system? What is the sort ordering of each file?

The declarative SQL statement above doesn't indicate any of that. It just says "Give me the data to print labels for customers with invoices unpaid over 30 days ." And the machine will respond with just that data.

SQL can do this because the database management system (such as PostgreSQL, MySQL, Oracle, DB2, MS SQL Server, etc.) has a "query optimizer" which reads that statement and figures out what is needed to achieve it. Thus, the people who wrote the query optimizer wrote imperative code to enable us to write the declarative code.

A declarative model is powerful because it lets us state what we want instead of how to achieve it. It lets the decision of how to achieve the goal be deferred and possibly updated independently of the statements that describe the goal.

In NMC2, it would be nice to have declarative descriptions of places for example. An email  (RE: MUCK 101 for NMC2 from Brian Jones to the NMC mailing list on April 15,2004) was the basis for the following example of a declarative place:

<place root="mossflower_woods">
  <type>Region</type>
  <name>master_region</name>
  <vr-name>Mossflower Woods</vr-name>
  <place>
    <type>Room</type>
    <vr-name>A Clearing in the Woods</vr-name>
    <name>clearing_1</name>
  </place>
  <place>
    <type>Room</type>
    <vr-name>Mossflower Woods</vr-name>
    <name>woods_1</name>
  </place>
  <place>
    <type>Room</type>
    <vr-name>Mossflower Woods</vr-name>
    <name>woods_2</name>
  </place>
  <path>
    <type>bi-directional</type>
    <start>clearing_1</start>
    <end>woods_1</end>
    <forward>
      <vr-name>East</vr-name>
      <keystrokes>e</keystrokes>
    </forward>
    <backward>
      <vr-name>West</vr-name>
      <keystrokes>w</keystrokes>
    </backward>
  </path>
  <path>
    <type>bi-directional</type>
    <start>woods_1</start>
    <end>woods_2</end>
    <forward>
      <vr-name>North</vr-name>
      <keystrokes>n</keystrokes>
    </forward>
    <backward>
      <vr-name>South</vr-name>
      <keystrokes>s</keystrokes>
    </backward>
  </path>
</place>

In the above example, there's no hard-coding of any full path names. There's no rules on saying what order anything is done. There's no commands at all. There's just a description of what the area is like. There are no names for the exits. I've no idea if they are objects, properties on the rooms, or some as-yet-undefined mechanism.

I did give names to the rooms, such as clearing_1, woods_1 and woods_2. Those names are much shorter than the VR Names associated. They are longer than dbrefs would have been in NMC1, but not terribly so. To make sure the names had a context, I put in a "root" in the master place start-tag which indicated a directory name. This is similar to how we do code; we give a directory name, and everything "beneath" it is ours. What directory will the name "mossflower_woods" be in? Don't know...whatever directory this is processed from I presume.

Which also means if this was processed twice, it would overwrite the first with the second, allowing updates.

The names thus give us  a continuity of intent, they let us write a single place description that can be used anywhere, used multiple times, and allows the database to be updated if the script is changed and later re-imported.

This is declarative because it describes what we want as a result, but does not describe the steps or commands to achieve it.

Event

See also: action, command

Events occur; they can be caused by something external (such as a user command), by something internal (such as a timer expiring), by something changing in the DB (a character enters a new VR place), or programmatically, in which a developer chooses to trigger an event to queue up some behavior later.

In NMC1 the events were hard-coded and triggered hard-coded changes. For instance, entering a room while non-Dark always triggered arrive and depart events. These events in turn evaluated the code in "_arrive" and "_depart" on the room and object arriving/departing.

In NMC2, the events are more extensible. Events can be added or the cycle of events interfered with, depending on permissions.

There will be all the NMC1 event types supported in NMC2's default event model. But this model can be either extended or swapped out as desired. A site wishing no compatibility with NMC1 needn't have any of the NMC1 events.

Events should never need to be "worked around" by the administration or staff. They should have permissions needed to change the event model.

When an event occurs, it is said to have fired. All interested parties (called event listeners) are notified when an event fires. They then carry out some work, called an action. The action may in turn fire other events.

For a more in-depth document, read Events Explained.

Identity

Identity is the precise determination if two symbols refer to the same object.

In the real world, identity means the same thing! For instance, my identity is "Brian Jones". It's also "Otter" and it's also "Jones, Brian C.". They all refer to the same thing: me. In fact, pronouns are used to work with identity.

In the MU, identity requires that we be able to distinguish things even across time and space. As the MU is started and stopped, objects get flushed to and from disk. They aren't going to come back to memory in the same place, so we need a way to strongly refer to them with certainty.

In NMC1, this was done through the use of "database references" (called dbrefs). Dbrefs were exposed to the users and used continually by end users for even the most basic of tasks.

In NMC2 we need to use the notion of name-spaces and contexts.

In this way, we can map many names to the same object and be certain that comparisons compare the real object not the names. Further, this provides us the means to reference objects precisely regardless of the name mappings that exist.

In UNIX, this is achieved with the use of "i-node" values for all file and directory objects, and a hierarchical directory naming structure. The last name for a file removed  caused the release of the disk blocks for the file and allowed re-use of the i-node. While an end user can request to see the i-node (ls -i filename) the i-node was too vague to be useful for processing by the end user.

That same ability to have an internal unique ID value and allow it to be seen but not usefully processed might serve us well in NMC2.

Imperative Programming

See also: declarative programming

Imperative programming is specifying what steps in order the machine is to do.

For instance, to build a room in NMC1, the following imperative steps could be copied/pasted and tell the system exactly what to do in order:

@dig Mossflower Woods=$region=r1
@dig Mossflower Woods=$region=r2
@action [E]east;e=$r1=e1=$r2
@action [W]est;w=$r2=e2=$r1

Those are the precise commands to be run. The computer obeys, doesn't interpret. If the commands change, the above script will break.

Imperative programming requires the developer know the precise steps the machine is to follow to get something done. Declarative programming requires the programmer know how to precisely describe what the desired result is.

Message

See also: VR messages. response ,events

Messages are atomic packets of information delivered via the system.

The concept of messages is enormously general!

For instance, a player sends some message to the system which gets interpreted by the shell and causes a command to be launched. The command generates a series of outputs which are packaged as messages and returned to the player via the protocol.

In this sense, everything that flows through the system is probably done with the use of messages.

Receipt of a message is a type of event. So messages also trigger all the event processing machinery.

Commands may directly cause a series of messages. Those messages are said to be responses to the command. Indirect messages resulting from the command may or may not be classified as responses depending on the nature of how the command is written. Some commands will require accurate reporting of all responses, some don't need the overhead and won't deliver it. This is a choice of the author.

In NMC1 terms, from the time a command starts until the time it either finishes or goes into the background all resulting output is deemed a response. You can see the grouping through the use of OUTPUTPREFIX and OUTPUTSUFFIX commands in the NMC1 server.

Name

See also: namespace and VR name.

Names provide an external reference to something; in the case of NMC2, it provides a reference to an object. Every name maps to exactly zero or one object at any given time (it can map to an object that has been destroyed, so a request for the object would return an error). The name can be applied to a new object at any time; when this is done, it loses all knowledge of the prior object. Thus, the name can refer to any number of objects over time, but only one object at most at any given time.

We use names for objects in NMC2 so we can refer to an object responsible for some job. Over time, different objects may take on the responsibility (due to new versions of the software, or perhaps new ownership of an area or policy changes). Thus, by having the programs and scripts refer to an object by a name which can be re-bound to a new object the programs that depend on an object for doing a job will not break because the object that does the work is replaced with another.

This is similar to how DNS works. DNS gives an external name (such as nmc.limitless.org) to a machine. Over time, the machine may be upgraded, the IP address may be changed for various reasons, and the service may even move to a different operating system. But all the URLs and CVS configurations which hold "nmc.limitless.org" will survive un-broken because each time a connection to the machine is needed, the system requests the object (in this case, the IP address) each time.

This is also why it's not wise to store IP addresses in a client file to connect to servers (including an NMC MUCK). It's much wiser to always store the human-readable DNS name and let the system look it up instead.

Also, since NMC2 supports the idea of remote systems and access, providing a name that makes sense in a URL context is important. That way, people who establish links from other systems will be able store not some internal ID, but an external name that provides the most current version of whatever object they expect.

It's important that this name, which is purely for use in the creation and management of objects and content not be confused with what people type when accessing the objects inside a VR context.

For instance, a sword could be created. It's VR name would be "sword" but it's external reference name might be ~brianj/weapons/s1_sword_v1. Thus, a remote system could refer to the object as nameless.muck.limitless.org:2600/~brianj/weapons/s1_sword_v. In this way, links between systems can be established. If later, I decided to make a better sword, and use that instead, I could re-assign the name to my new sword (a different object) and the next time the remote site accessed the name, they'd get the new version of the object.

This replaces the hard-coding of names tied to internal array offsets (which is what the NMC 1.x dbref was). Instead of coding to dbrefs, code to names.

To reduce the burden of typing the really long paths in the code, names are stored in namespaces. When programming, one or more namespace objects (or "contexts") can be requested to different places in the name hierarchy. Then, all names become short. The same idea of a "current working directory" in a file-system so you don't have to type the entire long path from the root to your file every time.

Namespace

See also: name

Names are used to refer to things. A namespace is the context in which a name is unique.

For instance if I use the name Paris you don't know if I mean a city in Texas, France, or a girl named Paris. I'd have to give you the context of the name, or the namespace, for you to know.

In MU terms, this is especially difficult. For instance, anyone should be able to create a command for themselves in either a scripting language or in Java. They need to give some name for it to be accessed with. There is no requirement that they choose a name that is unique system-wide. How, then, would they share with me the command? I may have made one of my own.

The namespace exists to indicate which place to look in to find the name and thus what it refers to.

For instance, my command might be ~brianj/look, using the UNIX naming convention of tilde in front of user-name to indicate a directory. Or brianj@otterspace.com:/commands/look to use a more Internet style. Or even http://nameless.muck.limitless.org/nmc/~brianj/commands/look.command for a full blown URL.(NOTE: these are not real URLs that are linked to anything!).

Java mandates the use of packages to provide name-spaces. In java, the package-name "org.limitless.NMC" is the namespace that we can safely use to put all NMC stuff. The use of reverse-DNS is used as a standard to provide inter-organizational uniqueness. I control the domain "limitless.org" so I can safely use "org.limitless.*" in my Java applications for domain naming.

In the NMC1, names were done using "reg-names" which were text starting with a dollar-sign "$" and were defined in properties "_reg/name".

The problem was, the properties were searched for by checking the invoker first, then the room the invoker was in, and then the room that room was in, and so on. So, the name-space was tied to the nesting of places, not to a references point. We fixed this by adding the ability to put colon-separated names to look up where to look up the first name (is that as complex as it sounds). It was never heavily used outside of scripting.

The new scheme allows players to make a context on demand that gives them a "current directory" view. Then, they can use names with no hierarchy (no "slashes") to request what they want. The names will be found in the context requested.

NMC2 namespaces and conventions must be sensible to non-technical players and easily used.

Object

See also: name

Objects are the term for anything with identity.

We use objects to provide content. Anything which can be interacted with requires an object. The objects in the game can be further classified to how they are used.

In NMC1, objects were always of one of the following fixed categories:

  1. Player
  2. Thing
  3. Room
  4. Exit
  5. Program

In NMC2, Players are now known as Characters (to distinguish from the person at the keyboard) and any object can freely fulfill any of the roles above. Meaning it is now possible and expected to make a room that simultaneously has a point of view like a character.

This should allow the use of relations, objects, and properties to allow extensibility without limits.

Objects may have any number of names that refer to them, including none at all.

Permission

A permission is a way to grant someone (Player, Character, object, whatever) referred to as a subject the ability to carry out a task. It is also a way to prevent the subject from carrying out a task.

Thus, a permission specifies that someone is granted or rejected to do something particular to something.

See Permissions Explained for much more detail.

Place

Places are where VR takes place.

In NMC1, we had rooms. We required some areas be assembled of multiple rooms. Sometimes, we wanted to have a single room have multiple parts.

For instance, a tavern might want many booths. Each booth would hear what goes on in the tavern at large but not in any of the individual booths. People not in a booth but in the tavern would only hear mumblings and see movement in the booths. This would require complex use of +nearby and many rooms representing the same place.

In NMC2, places should be capable of being inside other places and having rules controlling event propagation, filtering and transformation.

For a detailed look at places, see the Places Explained document for a long explanation with two detailed examples worked through.

Places can often be mapped using state diagrams which are drawn with a circle for a place and lines connecting circles representing exits. It's legal to draw large circles around groups of circles and lines to show sub-places (or sub-states more formally).

Player

See also: character

A Player is a person in the real world that plays the game. Players type on keyboards and move mice. Players see text and graphics on screens.

Players have accounts which allow them to interact with the system. Players give the commands that cause characters to emit messages or change location in the VR space.

The terms player and user are synonymous in this system.

There may be objects in the system that track player data, such as email or connection information. These objects are not used in any VR context.

When a player wants to interact with other players in VR, they need to use a character object to do so. Thus, character objects exist in VR space and provide a point of view. Players can control character objects to participate in VR.

Property

See also: relation

Anything with identity can be further described by listing facts about it. These facts are stored as properties.

Another name for these are attributes.

Any data to be remembered must be stored in properties.

In NMC1, properties were stored directly using @set and read directly using examine. In fact, a huge number of command sin NMC1 were for property management. @desc set the "_/de" property, for instance, which was read by "look."

In NMC2 the idea of relationships between objects are likely to become objects in their own right, and then properties on the relation objects would hold the data. This is similar to the NMC1 idea of exit but more general because the relation can be between multiple objects with multiple properties.

Relation

A relation is an object describing how two or more other objects are related. Specifically, relations make nouns of what we often think of as verbs.

For instance, "Dude carries stone" (example from Jonathan Blow, Game Developer).

This relates Dude and stone. What kind of relation? One carries the other. So, we have a relation object that would hold who carries what.

Now, we don't know what types of relations clever future people might want. So we can conceptually look at this like this: (carries dude stone).

Now, when did the dude get the stone? You can't store that as a property on the dude, because it isn't just about the dude. You can't store it on the stone, because it isn't just about the stone. So where do you put it? On the relation object!

Relation objects thus have properties that describe the relation itself.

In the real world, you see this concept in play with things like licenses. A marriage license lists who marries whom and when, where, etc.

A much more detailed write-up is available in Relations Explained.

Response

See also: message

A response is a message that is directly caused by a command. It's a decision of the author of a command whether to cause responses or just plain messages without a triggering command attached.

Time

See also: VR Context

A much more detailed write-up is available in Time Explained.

There are a few uses of time in the game.

One use is real time, which includes the time zone and date. This is used for system logs and for coordination of events in the real world.

Another use is time from the perspective of the VR Context. In this use, an object in VR space called a Timekeeper holds whatever time and time policies that the owner of the VR Context dictates. Here, time is purely at the whim of the game world.

The last use of time is to speak of durations. A duration can be a single period, like "ten seconds from now" or can be recurring, such as "every 10 minutes." For durations, the system core functions are used to have the Time service generate events.

VR Context

See also: character and place

A VR Context is the part of the game that a character is used to experience.

When you talk about speaking, or looking around, or you see someone posing, you are seeing them in the VR Context.

In NMC1 and other MUs, the term "in character" typically refers to the VR Context.

Each VR Context in a server supports a consistent set of places and characters. No object can "enter" a VR Context unless it was either created within that context or has privileges to do so. This means that a player (the user, not a character!) can establish a private VR Context if they wish that will never have any characters or objects other than what they approve, with no possibility for "bleed" from another context.

VR Contexts can be nested if the outer grant permissions for nested contexts.

When people talk of "playing" in the MU, they are talking about playing inside a VR Context.

Note that NMC1 ONLY had VR contexts, and only a single VR Context. Even Nameless MUCK, which had the idea of "genres", didn't have isolation between them because there was no means to do so.

VR Messages

See also message, events

A VR Message is a kind of message that is specifically meant to carry information in the context of Characters vs. Players.

For instance, if a character says "Hello" that is something that should be interpreted within the VR context, so is a VR message.

VR messages are emitted through some mechanism.

Speech for instance is spoken and travels through the air to those nearby.

Telepathy might have unlimited range but only be received by those who are also telepaths.

The NMC1 had a few very basic means for VR messages:

  1. say
  2. pose
  3. spoof
  4. whisper

Some other MUs added mumble, or say in "private languages" and so on.

In general, anything that a Player should have the Character interpret is a VR message.

NMC1 made all messages just textual dumps. This made external automation brutally hard and uncertain.

In NMC2, VR messages need to be packaged better.

For instance, we could say that a message has a sender, a list of recipients, a location sent, a range, a mode of delivery, and finally the package of text itself. All the details OTHER than the text would make up the envelope of the message.

With this facility, it should be reasonable to allow characters to list what sorts of modes they support. Characters who are deaf then wouldn't receive messages that were auditory. Blind characters wouldn't get visual updates. Telepaths could freely talk "mind to mind" without being received by non-telepaths.

We don't need to decide in advance what modes there are or can ever be. A mode is really just an identifier that lets us specify whether a character receives the mode or not. Thus, there's an unlimited number of possible ways that characters could exchange messages in a VR context.

Some examples (not exhaustive or restrictive!):

  1. audible
  2. visual
  3. mental
  4. olfactory
  5. tactile
  6. chemical reception (pheromones?)

 

Some modes may further be restricted by permissions so that they can't be added without authorization. This could be a useful means to enforce policies and keep "private languages" private, for instance.

VR messages should also have an impact on the places the characters are, not just between characters. A message might be processed by a room to cause spawning of monsters when certain words are said. The room isn't an "intended recipient" of the message per-se, but the message is emitted in the range of it and it can process it.

This does mean that messages of types un-known to the author of some event-handling code won't trigger some events. This is a consequence of allowing continual extension: we're not mandating that extensions be approved or that everyone or anyone be notified.

On the other hand, well written code could process messages "in general" to some degree.

This also means that the mixing of message-types should be stopped. For instance, in NMC1 it was typical to use pose and spoof to mix visual and audible messages. An example:

  pose blinks and asks, "Um, is it morning yet?"

This really mixes two messages: visual blinking that would be seen and audible spoken words which ought to be heard.

This will cause audible to be sent via the visual channel. One way around this is to have the shell and pose programs in the NMC1 compatibility parse out the intermixed visual and audible parts by quoting or such. This could be problematic at best though since most people aren't perfect typists.

So, for the near-term, the fact that messages are going to be intermixed is probably a fact of life.

In the NMC2 shells and newer software, however, efforts should be made in the tools and GUI programs to make VR messages as accurate as possible.

VR Messages are implemented in the objects delivered via events.

VR Name

See also: name and namespace

A VR Name is what characters in a VR context use to refer to an object. The VR Name has no requirement for being unique or canonical.

In NMC1 for instance, this was legal (though annoying):

   @create sword
   drop sword
   @create sword
   drop sword

Now if someone did a 'look' they would see:

   Contents: sword and sword

Those "names" were VR Names. The real identifier in those cases was the "database reference" or dbref that was returned. Because they didn't happen to be unique in the same room, any attempt to "get sword" would give them one of them (at random). An attempt to get the second would give "You already have that!"

Thus, inside a VR namespace, the VR Names are only useful for showing in lists and such. They are not useful for identification beyond a limited room or inventory list. And even in the room and inventory list, they are not always useful. They should be rendered "unique enough" by a rendering routine as needed to enable players to easily interact with them. This should be done by the system at all times. The above example should show then as "Contents: sword (1) and sword (2)" where the numbers 1 and 2 where added by the room temporarily to ensure name uniqueness for ease of play.

The more general "names" are what are used by builders and content creators to refer unambiguously to objects anywhere in the MU, VR or not. Those names may also be fully exported to other remote systems. They don't get modified dynamically nor are they shown in VR mode to characters at play.

End of Document